/************************************************************************ * Transaction example demonstrates the calls necessary to implement a * * transaction for recovery unit journaling. * ************************************************************************/ /* * Include Files */ #include rms #include stsdef #include ssdef #include stdio #include descrip #include #include #include #define event_flag 0 /* * This macro is used to check the status of System Services. * If an error occurs the message is printed and the transaction * is aborted (if we are in one), The status is then signaled. */ #define exit_on_error(expression,mycode) { \ int \ sys_status; \ sys_status=(expression); \ if ((sys_status & 1) == 0) { \ fprintf( stderr, "Transaction example error - %s\n", mycode );\ sys$abort_transw (event_flag,0,&transaction_iosb,0,0,&transaction_tid);\ lib$signal(sys_status); }} /* * Create the IOSB data type. */ typedef struct { short int status; unsigned char filler [6]; } IOSB; /* * Describe the record structure of the checking and savings account file. */ typedef struct { char account_number [9]; /* account number (primary key) */ int account_balance; /* balance of the account */ char filler [5]; /* filler for compatibility with other examples*/ } RECORD; /* * Create the TID data type. */ typedef struct { char filler [16]; /* TID is an opaque structure 16 bytes long */ } TID; /* * Allocate the RMS user structures */ struct FAB checking_fab; /* File Access Block for the checking file */ struct RAB checking_rab; /* Record Access Block for the checking file */ struct XABKEY checking_key; /* XABKEY for checking account */ struct FAB savings_fab; /* File Access Block for the savings file */ struct RAB savings_rab; /* Record Access Block for the savings file */ struct XABKEY savings_key; /* XABKEY for savings account */ char *checking_file_name = "rmsjnl$checking.idx", *savings_file_name = "rmsjnl$savings.idx"; float delay; /* time delay after updating checking account */ int status; /* Check completion status of RMS operations */ IOSB transaction_iosb; RECORD checking,savings; TID transaction_tid; main () { /* Initialize RMS user structures for the checking file. */ checking_fab = cc$rms_fab; checking_fab.fab$l_fna = checking_file_name; checking_fab.fab$b_fns = strlen (checking_file_name); checking_fab.fab$b_fac = FAB$M_UPD | FAB$M_PUT | FAB$M_GET; checking_fab.fab$l_xab = &checking_key; checking_rab = cc$rms_rab; checking_rab.rab$l_fab = &checking_fab; checking_rab.rab$w_rsz = 18; checking_rab.rab$w_usz = 18; checking_rab.rab$l_ubf = (char *) &checking; checking_rab.rab$l_rbf = (char *) &checking; checking_key = cc$rms_xabkey; /* * Initialize RMS user structures for the savings file. */ savings_fab = cc$rms_fab; savings_fab.fab$l_fna = savings_file_name; savings_fab.fab$b_fns = strlen (savings_file_name); savings_fab.fab$b_fac = FAB$M_UPD | FAB$M_PUT | FAB$M_GET; savings_fab.fab$l_xab = &savings_key; savings_rab = cc$rms_rab; savings_rab.rab$l_fab = &savings_fab; savings_rab.rab$w_usz = 18; savings_rab.rab$w_rsz = 18; savings_rab.rab$l_ubf = (char *) &savings; savings_rab.rab$l_rbf = (char *) &savings; savings_key = cc$rms_xabkey; /* * Open the Savings and Checking account files */ exit_on_error(sys$open (&checking_fab), "Checking account OPEN failed"); exit_on_error(sys$open (&savings_fab), "Savings account OPEN failed "); /* * Connect the Savings and Checking account files */ exit_on_error( sys$connect (&checking_rab),"connecting checking rab "); exit_on_error( sys$connect (&savings_rab), "connecting savings rab "); /* * Start a transaction on both the checking and savings accounts. * The checking and savings account will be initialized to $100 * for account "000001234". Note that any I/O errors in this * recovery unit will be ignored. */ exit_on_error( sys$start_transw (event_flag,0, &transaction_iosb,0,0, &transaction_tid), "couldn't start the initialization transaction."); exit_on_error( transaction_iosb.status, "could not start the initialization transaction."); /* * Put $100 dollars in the checking account of "000001234" * The put will cause this stream to become part of the transaction. */ strcpy (checking.account_number, "000001234"); checking.account_balance= 100; status = sys$put (&checking_rab); if ((status & 1) == 0) { fprintf (stderr, "Checking account already exists.\n");} /* * Put $100 dollars in the savings account of "000001234" * The put will cause this stream to become part of the transaction. */ strcpy (savings.account_number, "000001234"); savings.account_balance = 100; status = sys$put (&savings_rab); if ((status & 1) == 0) { fprintf (stderr, "Savings account already exists\n");} /* * End the transaction to initialize the checking and savings account. */ exit_on_error( sys$end_transw (event_flag,0, &transaction_iosb,0,0, &transaction_tid), "couldn't end the initialization transaction."); exit_on_error( transaction_iosb.status, "could not end the initialization transaction."); /* * Transfer $10.00 from checking to savings using a recovery unit. * Note that the recovery unit is aborted if any I/O errors are * encountered. */ exit_on_error( sys$start_transw (event_flag,0, &transaction_iosb,0,0, &transaction_tid), "couldn't start the transfer transaction."); exit_on_error( transaction_iosb.status, "could not start the transfer transaction."); /* * Read the checking account record for "000001234". Abort recovery * unit if the operation is not successful. This get will cause this * stream to become part of the transaction. */ exit_on_error(sys$get (&checking_rab),"Checking account not found.\n"); /* * Subtract $10 from the checking account balance. */ checking.account_balance = checking.account_balance - 10; /* * Update the checking account file reflecting the new balance. Abort * the recovery unit if the update is not successful. */ exit_on_error(sys$update (&checking_rab), "Cannot update checking account.\n"); printf ("Pausing for 5 seconds.\n"); delay = 5; lib$wait (&delay); /* * Read the savings account record for "000001234". Abort the recovery * unit if the get is not successfull. The put will cause this stream * to become part of the transaction. */ exit_on_error(sys$get (&savings_rab), "savings account not found.\n"); /* * Add $10 to the savings account. */ savings.account_balance = savings.account_balance + 10; /* * Update the savings account file reflecting the new balance. Abort * the recovery unit if the update is not successful. */ exit_on_error( sys$update (&savings_rab), "Cannot update savings account.\n"); /* * End the recovery unit. */ exit_on_error( sys$end_transw (event_flag,0, &transaction_iosb,0,0, &transaction_tid), "couldn't end the transfer transaction."); exit_on_error( transaction_iosb.status, "could not end the transfer transaction."); /* * Display the new balances. */ printf("The new checking account balance is %d\n", checking.account_balance); printf("The new savings account balance is %d\n", savings.account_balance); }