Transaction Processing

1 Introduction
2 Function Calls Reference
2.1 isLogOpen
2.2 isLogClose
2.3 isBegin
2.4 isCommit
2.5 isRollBack
2.6 isRecover
3 Data File Recovery
4 Transaction Processing Fundamentals
5 Overlapping Transactions

1 Introduction

We have attempted to provide a transparent implementation of the transaction processing routines provided by cisam™. The library should perform as specified in the cisam manuals, but also includes a few additional enhancements.

We are not certain that we have identified the log file locking offsets properly. There is a possibility that the library will not co-operate in concert with cisam, but we have not found any problems to date.

Transaction Processing is activated via ISLOGGING in isconfig.h

NOTE
The overlapping transactions option has been modified, issusplog and isresumlog are discontinued - see Overlapping Transactions for more details.
NOTE
Please ignore any references to multi-thread support in the following - we have currently abandoned the attempt to supply such support due to lack of interest. Please let us know if this is a problem to you, although please understand that this is not a trivial issue to resolve. It is difficult enough to keep reliable track of serial transactions, as it is..

2 Function Calls Reference

2.1 isLogOpen

  int isLogOpen( char * name )
  int islogopen( char * name )

Opens log file. Once the log file is opened all subsequent operations on all files will be logged until the log is closed or suspended. Each process is responsible for opening a log file. Usually all processes within an application will open the same log file. Access is governed by concurrency locks to prevent simultaneous writes, but this feature might not be compatible with cisam. Files opened/built with ISNOLOG in the mode will not be logged.

2.2 isLogClose

  int isLogClose( void );
  int islogclose( void );

Closes log file for the process. All subsequent operations will not be logged.

2.3 isBegin

  int isBegin( void );
  int isbegin( void );

Defines the beginning of a set of operations on all files opened with ISTRANS in the mode argument. This set of operations is known as a transaction.

All records updated within the transaction will remain locked to ensure no other process can affect the results. In multi-user situations it is important to keep the time spent within a transaction to a minimum to avoid impacting on other processes' access to the records involved.

All calls to isclose within the transaction will be deferred to avoid releasing the locks mentioned above. If the same file is reopened within the same transaction you will simply get the same file handle back.

All updates affect the data file immediately. If the process should terminate before completing the transaction, the changes will remain unless isrecover is used to rebuild the data from the last backup.

2.4 isCommit

  int isCommit( void )
  int iscommit( void )

Defines the successful completion of a transaction. All locked records will be released and all deferred closes honoured.

2.5 isRollBack

  int isRollBack( void )
  int isrollback( void )

Defines the unsuccessful completion of a transaction. All updated records will be restored to their original state, all record locks released and all deferred closes honoured.

2.6 isRecover

  int isRecover( void )
  int isrecover( void )

Called to rebuild a set of data files from an original condition by means of a common log file. islogopen() must be called first to open the log.

NOTE
isrecover is NOT threadsafe and should only be used under single threaded circumstances, or at very least only when there are no other threads working on isam files.

3 Data File Recovery

If, at the time a full data backup was made, the transaction log was purged, then, provided all updating processes call islogopen() before making changes, it is possible to rebuild the data files from the backup and the log file.

It is not necessary that files be opened with a mode of ISTRANS for changes to be logged. Once the log is open, all subsequent ISAM opens will automatically be logged, and only Files that are opened with a mode of ISNOLOG will not be logged.

To recover files it is necessary to compile a recovery utility that will call the following functions in order:

  islogopen( "logname" );
  isrecover();
  islogclose();

The recovery procedure will then be to restore the backup (make sure not to overwrite the log file) and run the recovery utility. The utility should check the return from isrecover() to ensure no errors occurred during recovery.

It is also possible to implement incremental backups by this method. The log file can be backed up and purged on a regular basis. To recover it will be necessary to restore the original backup, then restore and run the recovery utility on each log file in chronological order.

4 Transaction Processing Fundamentals

The theory behind transaction processing is that a collection of changes to a group of data files can be defined in such a way as to be able to undo these changes at any time during the operation.

The collection of changes is referred to as a transaction.

A sample program might best serve to illustrate. Proper error checking has been omitted to simplify:

/* post a sales invoice */

#include 

int invcFile;   /* source invoice record file */
int custFile;   /* customer master records */
int tranFile;   /* accounting transaction file */

main()
  {
  islogopen( "logfile" );

  invcFile = isopen( "invoice",     INOUT + ISTRANS );
  custFile = isopen( "customer",    INOUT + ISTRANS );
  tranFile = isopen( "transaction", INOUT + ISTRANS );

  isstart( invcFile, ..., ISFIRST );

  /* loop through invoices */
  while( isread( invcFile, invcrec, ISNEXT ) == SUCCESS )
    {
    isbegin();                  /* define transaction start */

    if(
      postCust() == SUCCESS     /* update customer master */
      &&
      postTran() == SUCCESS     /* create transaction record */
      &&
      delInvc() == SUCCESS      /* delete invoice record */
      )
      iscommit();               /* successful, commit changes */
    else
      isrollback();             /* failed, erase changes */
    }

  isclose( invcFile );
  isclose( custFile );
  isclose( tranFile );

  islogclose();

  exit( 0 );
  }

Note that the transaction processing logic will lock all records that are changed within the transaction for the duration of the transaction. In some instances it pays to keep the transaction cycle as short as possible to allow other processes access to these records.

Note also that those files whose changes are to be erased when isrollback is called must be opened with mode ISTRANS. changes will still be logged for those that are not, but the transaction processing logic ignores them and will not undo any changes.

5 Overlapping Transactions

As an extension to the cisam standard, and also as a means of allowing flexible use of transaction processing within multi- threaded applications, the library provides a mechanism for handling multiple concurrent (or overlapping) transactions.

Management centers around the use of a callback function provided by the application. In order to permit overlapping transactions you must first call isTxnInit( callback ), where callback is the name of a routine that will return a short integer value that the library will use to determine which operations belong to which transaction.

In a single threaded application the simplest method is to declare a variable that is visible to all routines that handle transactions and to the callback function itself.

For example, assuming a simple nested transaction operation:

    static short txnid;

    txnid = 1;
    isbegin();
    for( account = 0; account < 5; ++account )
      {
      /* update account master files */
      txnid = 2;
      isbegin();
      /* update account files */
      iscommit() or isrollback();
      txnid = 1;
      }
    iscommit() or isrollback();

In a multi-threaded application, assuming the intention is to allow atomic transactions within individual threads, you would have the callback routine return the thread id value.