Index Transaction Code (TB#6) (Functions/Subroutines/Programs)
Created at 12 AUG 1996 03:13PM
Index Transaction Code
Advanced Revelation 1.1 provides a unique and powerful hook into index processing. A developer can modify or replace the routines that process transactions created during modifications to an indexed file.
Index Transactions
In Advanced Revelation 1.1, most index updating activity is handled by the processing of transaction information. When a record is modified or added, information regarding changes to indexed fileds in that record is written to the !INDEXING file. These transactions are later moved into the index files (the !data files), which are created during the index creation process.
The process of moving the transactions into the !INDEXING file is now handled by a specialized routine generated during the index creation process. Since a custom transaction program is created for each indexed file, the index transactions are handled more efficiently than by the general processing routines used in version 1.0.
The transaction routine is a symbolic field, generated when the index is created. The dictionary record for this symbolic is stored in the "!" record of the index file of the data file. For example, the index transaction routine that updates the indexes for the CUSTOMER file is stored in the '!' record of the !CUSTOMER file.
Capturing Index Transaction Code
When the system generates the transaction routine, it will look for a "!!" record in the index file. If this record is present, it will store the R/BASIC source code used by the symbolic field into this record. The source code can then be edited and used to modify the index transaction process.
To capture the source code, simply create an empty "!!" record in the index file. The next time an index for this file is created, the system will store the source code in the "!!" record.
Modifications
Since the "!" record is called as a symbolic field, implementing a modified transaction program requires a few more steps than simply compiling the modified source code and copying the object code to the '!' record. The '!' record format must be that of a symbolic dictionary item. There are a couple of methods for implementing changes to the transaction process.
The first method involves an R/BASIC program that converts the source code in the '!!' record into a symbolic dictionary format, and moveds it into the "!" record. See figure 1.
Another method is to create an entry in the VOC file for the compiled source. For example, if the "!!" record of the !DATA.FILE was compiled, simply use the editor to create a new record in the VOC. The VOC record key can be any permissible key. The record layout should be:
field 1: RBASIC
field 2:
field 3: !DATA.FILE
field 4: !!
Next, create a symbolic field in the dictionary of the data file. The formula of this symbolic simply calls the VOC item created above. For example, if the VOC item key is INDEX.TRANSACTION.CODE, the formula would be:
CALL INDEX.TRANSACTION.CODE
The last step is to RECORDCOPY this dictionary item from the DICT.DATA.FILE into the '!' record of the !DATA.FILE. Use the (O) option to overwrite the existing '!' record.
Since each indexed file has its own transaction routine, it is possible to tailor the index transactions for specific files. Note: Use the unmodified transaction code to gain a full understanding of how index transactions are handled before making any modifications! Examining unmodified code will aid in understanding the following example.
Example
Figure 2 demonstrates how index transaction can be modified "on-the-fly" based on external criteria. This listing outlines changes made to the generated index transaction code for a sample file.
In this example, a labeled common variable is used as a flag to determine whether or not this index should be updated immediately after posting the transaction. The flag variable is set by an external routine.
The labeled common variable UPDATE.INDEX.NOW determines the update process. If it is true, then a local subroutine invokes a call to the system subroutine INDEX.FLUSH. The flag is tested only when a transaction has been written to the !INDEXING file to avoid unnecessary updates to the index.
Figure 1
* create new ! record in !file
FILE = CALL MSG("Which File?","R",FILE,
)
OPEN "!":FILE TO INDEX.FILE.VAR ELSE
CALL MSG('!':FILE:"can't be opened!",,
,)
STOP
END
READ SOURCE FROM INDEX.FILE.VAR, '!!' THEN
NEW.UPDATE.PGM = 'S'
CONVERT @FM TO @VM IN SOURCE
NEW.UPDATE.PGM<8> = SOURCE
WRITE NEW.UPDATE.PGM ON INDEX.FILE.VAR, '$!!'
PERFORM 'DICTCOMPILE !':FILE:' $!!'
READ OBJECT FROM INDEX.FILE.VAR, '$!!' THEN
WRITE OBJECT ON INDEX.FILE.VAR,'!'
END
END ELSE
CALL MSG('No !! source code available',
,,
)
END
Figure 2
* program INDEX.TEST secondary index transaction builder
*——————-
* invoked like a dictionary CALCULATE
* input: @MV = 0 for WRITE, 1 for DELETE, 2 for CLEARFILE
* @ID = record key for WRITE and DELETE
* @RECORD = record for WRITE
* @ANS = datafile file variable
* returns: nothing
*——————–
* this routine forces a flush of the index transaction for the
* FIELDNAME field of the INDEX.TEST file if the flag UPDATE.INDEX.NOW
* has been set by an external routine.
*
* the first parameter required by INDEX.FLUSH is:
*
* FILENAME*ACCOUNT.NAME*MEDIA.NAME
*
* this string is hardcoded to speed processing. The second parameter
* is the indexed file name.
* (for additional information on using the system subroutine
* INDEX.FLUSH, refer to the "Appendix to Using Advanced Revelation")
*——————–
* common block used by indexing system (NOTE: this should be ONE line)
COMMON /SI/MAX.UPDATE.SIZE,INDEXES,INDEXES.FILEVAR,NO.PROTECT,OLD.REC OLD.FLAG,OLD.FV,OLD.ID,DICT.FVS%,BATCH.MODE%,UPDATE.ITEM%
* labeled common area to use as flag value for forced index flush
COMMON /%BANG.BANG.FLAGS%/ UPDATE.INDEX.NOW
*———————
* (body of index transaction code generated by system goes here
*———————
IF WRITE.UPDATES THEN
WRITE UPDATE.ITEM% ON INDEXES.FILEVAR,'0'
IF @STATION NE THEN
UNLOCK INDEXES.FILEVAR,'0'
END
* (customization here)
* test if index flush should be forced after the write.
* this test is only made after a write to !INDEXING
IF UPDATE.INDEX.NOW THEN
* the parameters should match the appropriate media name
* and fieldname for the application
PARM1 = "INDEX.TEST*SYSPROG*AREV.06:52:53 21 JUN 1988 (S)"
PARM2 = 'FIELDNAME"
CALL INDEX.FLUSH(PARM1,PARM2)
UPDATE.ITEM% =
END ;* if update.index.now
* (end of customization)
END ;* if write.updates
* skip final processing if CLEARFILE
IF @MV EQ 2 ELSE
* unlock all indexes that were logically locked before getting
* the old values
IF @STATION NE '' THEN
IF ITEM.LOCKED THEN
UNLOCKED LOCK.FILEVAR,@ID
END
END ; * if @station
END ; * if @mv