with RECOVERY_UNIT_SERVICES; use RECOVERY_UNIT_SERVICES; with CONDITION_HANDLING; use CONDITION_HANDLING; with TEXT_IO; use TEXT_IO; with INTEGER_TEXT_IO; use INTEGER_TEXT_IO; with INDEXED_IO; procedure RUFEXAMPLE is -- -- This program demonstrates the calls necessary for recovery unit journaling. -- It is meant as an example of use in Ada, it does not implement complete -- error checking. -- -- -- Structure used for the checking and savings account files. -- subtype ACCOUNT_NUMBER is STRING (1..9); subtype ACCOUNT_BALANCE is INTEGER range INTEGER'FIRST..INTEGER'LAST; type ACCOUNT_RECORD is record NUMBER: ACCOUNT_NUMBER; -- Primary key BALANCE: ACCOUNT_BALANCE; FILLER: STRING (1..9-ACCOUNT_BALANCE'SIZE/8); end record; package ACCOUNT_IO is new INDEXED_IO (ELEMENT_TYPE => ACCOUNT_RECORD); use ACCOUNT_IO; procedure READ is new READ_BY_KEY (KEY_TYPE => ACCOUNT_NUMBER); RECOVERY_UNIT_HANDLE: RU_HANDLE_TYPE; CHECKING_ACCOUNT_FILE: ACCOUNT_IO.FILE_TYPE; SAVINGS_ACCOUNT_FILE: ACCOUNT_IO.FILE_TYPE; CHECKING_ACCOUNT: ACCOUNT_RECORD; SAVINGS_ACCOUNT: ACCOUNT_RECORD; STATUS: COND_VALUE_TYPE; begin -- -- Open the checking and savings account files. -- OPEN ( FILE => CHECKING_ACCOUNT_FILE, MODE => INOUT_FILE, NAME => "RUF$CHECKING.DAT"); OPEN ( FILE => SAVINGS_ACCOUNT_FILE, MODE => INOUT_FILE, NAME => "RUF$SAVINGS.DAT"); -- -- 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". -- START_RU (STATUS, RECOVERY_UNIT_HANDLE); if not SUCCESS (STATUS) then PUT_LINE ("Cannot start recovery unit"); SIGNAL (STATUS); end if; -- -- Put $100 dollars in the checking account of "000001234" -- CHECKING_ACCOUNT.NUMBER := "000001234"; CHECKING_ACCOUNT.BALANCE:= 100; begin WRITE (FILE => CHECKING_ACCOUNT_FILE, ITEM => CHECKING_ACCOUNT); exception when KEY_ERROR => PUT_LINE ("Checking account already exists"); end; -- -- Put $100 dollars in the savings account of "000001234" -- SAVINGS_ACCOUNT.NUMBER := "000001234"; SAVINGS_ACCOUNT.BALANCE:= 100; begin WRITE (FILE => SAVINGS_ACCOUNT_FILE, ITEM => SAVINGS_ACCOUNT); exception when KEY_ERROR => PUT_LINE ("Savings account already exists"); end; -- -- End the recovery unit to initialize the checking and savings account -- END_RU (STATUS, RECOVERY_UNIT_HANDLE); if not SUCCESS (STATUS) then PUT_LINE (" Cannot end recovery unit to initialize accounts"); SIGNAL (STATUS); end if; -- -- 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. -- START_RU (STATUS, RECOVERY_UNIT_HANDLE); if not SUCCESS (STATUS) then PUT_LINE (" Cannot start recovery unit to transfer funds"); SIGNAL (STATUS); end if; -- -- Read the checking account record for "000001234". Abort recovery unit -- if the operation is not successful. -- CHECKING_ACCOUNT.NUMBER := "000001234"; begin READ (FILE => CHECKING_ACCOUNT_FILE, ITEM => CHECKING_ACCOUNT, KEY => CHECKING_ACCOUNT.NUMBER); exception when KEY_ERROR => PUT_LINE ("Cannot read checking account balance"); ABORT_RU (STATUS, RECOVERY_UNIT_HANDLE); end; -- -- 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. -- begin UPDATE (FILE => CHECKING_ACCOUNT_FILE, ITEM => CHECKING_ACCOUNT); exception when KEY_ERROR => PUT_LINE ("Cannot update checking account balance"); ABORT_RU (STATUS, RECOVERY_UNIT_HANDLE); end; PUT_LINE ("Pausing for 5 seconds..."); delay (5.0); -- -- Read the savings account record for "000001234". Abort recovery unit -- if the operation is not successful. -- SAVINGS_ACCOUNT.NUMBER := "000001234"; begin READ (FILE => SAVINGS_ACCOUNT_FILE, ITEM => SAVINGS_ACCOUNT, KEY => SAVINGS_ACCOUNT.NUMBER); exception when KEY_ERROR => PUT_LINE ("Cannot read savings account balance"); ABORT_RU (STATUS, RECOVERY_UNIT_HANDLE); end; -- -- 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. -- begin UPDATE (FILE => SAVINGS_ACCOUNT_FILE, ITEM => SAVINGS_ACCOUNT); exception when KEY_ERROR => PUT_LINE ("Cannot update savings account balance"); ABORT_RU (STATUS, RECOVERY_UNIT_HANDLE); end; -- -- End the recovery unit. -- END_RU (STATUS, RECOVERY_UNIT_HANDLE); if not SUCCESS (STATUS) then PUT_LINE (" Cannot end recovery unit to transfer funds"); SIGNAL (STATUS); end if; -- -- Display the new balances. -- PUT ("The new checking account balance is $"); PUT (CHECKING_ACCOUNT.BALANCE, WIDTH => 0); NEW_LINE; PUT ("The new savings account balance is $"); PUT (SAVINGS_ACCOUNT.BALANCE, WIDTH => 0); NEW_LINE; -- -- Close the checking and savings account files. -- CLOSE (CHECKING_ACCOUNT_FILE); CLOSE (SAVINGS_ACCOUNT_FILE); end RUFEXAMPLE;