/* This program demonstrates the calls necessary for recovery unit journaling. It is meant as an example of use in C, it does not implement complete error checking. */ #include rms #include stsdef #include ssdef #include stdio #include descrip /* This macro is used to check the status of System Services. If there is an error the appropriate error message is printed, the recovery unit is aborted (if we are in one), signal on the particular status */ #define check(expression,mycode) { int sys_status; \ sys_status=(expression); \ if ((sys_status & 1) == 0) { \ fprintf( stderr, \ "RUF example error -%s\n",\ mycode );\ sys$abort_ru (&recovery_unit_handle);\ lib$signal(sys_status); }} /* 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 FAB savings_fab; /* File Access Block for the savings file */ struct RAB savings_rab; /* Record Access Block for the savings file */ struct XABKEY checking_key; /* XABKEY for checking account */ struct XABKEY savings_key; /* XABKEY for savings account */ /* Describe the record structure of the checking and savings account file */ struct { char account_number [9]; /* account number (primary key) */ int account_balance; /* balance of the account */ char filler [5]; /* filler for compatibility for other examples*/ } checking,savings; char *checking_file_name = "ruf$checking.dat"; char *savings_file_name = "ruf$savings.dat"; int recovery_unit_handle; /* Used by RUF system services */ int status; /* Check completion status of RMS operations */ int delay; /* Delay time after updating checking account file */ main () { int status; /* Status returned by RMS and other System Services */ /* Initial RMS user structures with default values */ checking_key = cc$rms_xabkey; savings_key = cc$rms_xabkey; checking_fab = cc$rms_fab; checking_rab = cc$rms_rab; savings_fab = cc$rms_fab; savings_rab = cc$rms_rab; /* Initialize additional FAB/RAB characteristics for the checking account. */ checking_fab.fab$l_fna = checking_file_name; checking_fab.fab$b_fns = strlen (checking_file_name); checking_rab.rab$l_fab = &checking_fab; checking_fab.fab$b_fac = FAB$M_UPD | FAB$M_PUT | FAB$M_GET; checking_rab.rab$w_rsz = 18; checking_rab.rab$w_usz = 18; checking_rab.rab$l_ubf = &checking; checking_rab.rab$l_rbf = &checking; checking_fab.fab$l_xab = &checking_key; /* Initial additional FAB/RAB characteristics for the savings account. */ savings_fab.fab$l_fna = savings_file_name; savings_fab.fab$b_fns = strlen (savings_file_name); savings_rab.rab$l_fab = &savings_fab; savings_fab.fab$b_fac = FAB$M_UPD | FAB$M_PUT | FAB$M_GET; savings_rab.rab$w_usz = 18; savings_rab.rab$w_rsz = 18; savings_rab.rab$l_ubf = &savings; savings_rab.rab$l_rbf = &savings; savings_fab.fab$l_xab = &savings_key; /* * Open the Savings and Checking account files */ check ( sys$open (&checking_fab), "Checking account OPEN failed" ); check (sys$open (&savings_fab), " Savings account OPEN failed "); /* * Connect the Savings and Checking account files */ check ( sys$connect (&checking_rab)," connecting checking rab "); check ( sys$connect (&savings_rab)," connecting savings rab "); /* Recovery unit to initialize savings and checking account files. Note that any I/O errors in this recovery unit will be ignored. The checking and savings account will be initialized to $100 for account "000001234". */ check (sys$start_ru (&recovery_unit_handle), " couldn't start initialization transaction"); /* Put $100 dollars in the checking account of "000001234" */ 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" */ 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 recovery unit to initialize the checking and savings account */ check (sys$end_ru (&recovery_unit_handle), " couldn't end initialization transaction \n"); /* 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. */ check( sys$start_ru (&recovery_unit_handle), "Could not start transfer transaction\n"); /* Read the checking account record for "000001234". Abort recovery unit if the operation is not successful. */ check (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. */ check (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 recovery unit if the operation is not successful. */ check (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. */ check ( sys$update (&savings_rab), "Cannot update savings account.\n"); /* End the recovery unit. */ check (sys$end_ru (&recovery_unit_handle), "Could not end transfer transaction\n"); /* 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); }