gtpd1m28 | Database Reference |
Records that are used by TPFCS data stores are recouped as an extension of phase 1 of TPF recoup.
Because TPFCS has no knowledge of the contents of the data stored in a collection, this knowledge must be provided to TPFCS through another means so that collections that contain references to standard TPF files or to other collections can be recouped correctly. TPFCS can obtain information about the contents of the data by requiring the applications to describe the layout of data in a collection. Applications do this by identifying the displacements of any embedded 4- or 8-byte file addresses or PIDs.
During phase 1 of TPF recoup, TPFCS recoup will recoup its own internal collections. However, any collections created by user applications will not be recouped unless they are explicitly made known to TPFCS by establishing one or more recoup indexes. A recoup index describes the location of PIDs and 4- or 8-byte file addresses embedded in all collections associated with that recoup index. An anchor collection, usually the data store application dictionary (named DS_USER_DICT) of the data store, refers to user-created collections, which refer to other collections, and so on. Every user-created collection must be referred to by an anchor collection or it will not be recouped. A recoup index must be created and associated with the anchor collection and any other collections that contain embedded references.
Recoup indexes can be managed by an application or by using the ZBROW RECOUP command.
A separate index should be created for each of the different collection formats in your TPFCS database. A recoup index is unique to the data store. If necessary, a recoup index can be deleted.
After a recoup index is created, you must add one or more entries to it. (Previously added entries can be deleted from a recoup index if they are no longer needed.) Recoup index entries identify the location of file addresses or PIDs in the collection data. 4- or 8-byte file addresses embedded in TPFCS collections must be part of a traditionally chained TPF structure and must have a corresponding TPF recoup descriptor. File addresses of TPFDF records cannot be embedded in TPFCS collections.
There are two basic types of recoup indexes. The first type, known as an homogeneous index, is used when each of the elements in the collections associated with this index has the same format and can be recouped the same way. A homogeneous recoup index can be associated with any type of collection with the exception of BLOBs. The second type, known as a heterogeneous index, is used when the elements in the collections associated with this index cannot be recouped the same way because they have different formats. When adding entries to a heterogeneous index, you must specify which elements have embedded 4- or 8-byte file address or PID information (as well as the displacements in those elements where the file address or PID information is stored). The following restrictions exist:
Because BLOBs have a single element, special processing is required and the recoup index type indicator is ignored. Therefore, the recoup index associated with a BLOB is not considered to be either homogeneous or heterogeneous.
After the recoup index has been created, it can be associated with one or more collections if they have the same format for embedded 4- or 8-byte file addresses or PIDs. However, a single collection can only be associated with one recoup index at a time. You can also associate a recoup index with a collection when the collection is created by using an option list. You can also remove an association whenever you have determined that you no longer want TPFCS recoup to use a given recoup index to process the collection.
TPFCS will use the TPFCS recoup indexes to chain chase any embedded 4- or 8-byte file addresses or PIDs while processing a ZRECP RECALL command. You can also recoup individual collections by identifying a specific data store (DS). In test mode, use the ZRECP RECALL command with the SEL and DS parameters specified to recoup a specific collection. In production mode, use the ZRECP SELECT command with the PID parameter specified to recoup a specific collection when the collection has errors. To display the status of TPFCS recoup, use the ZRECP STATUS command. TPFCS recoup status messages are displayed approximately every minute, when recoup processing for a data store ends or when the ZRECP STATUS command is entered. See TPF Operations for more information about the ZRECP commands.
The following table lists the operations you can perform on a recoup index and identifies the API or parameter of the ZBROW RECOUP command you can use for each operation.
Table 17. Managing TPFCS Recoup Indexes
Operation | API | ZBROW RECOUP Command Parameter |
---|---|---|
Create a recoup index | TO2_createRecoupIndex | DEFINE |
Add an entry to a recoup index | TO2_addRecoupIndexEntry | ADD |
Associate a collection with a recoup index | TO2_associateRecoupIndexWithPID | LINK |
Display recoup indexes | None | DISPLAY |
Delete a recoup index to collection association | TO2_removeRecoupIndexFromPID | UNLINK |
Delete an entry from a recoup index | TO2_deleteRecoupIndexEntry | REMOVE |
Delete a recoup index | TO2_deleteRecoupIndex | DELETE |
See the TPF C/C++ Language Support User's Guide for more information about TPFCS APIs and TPF Operations for more information about the ZBROW RECOUP command.
If 4-byte file addresses are embedded in a collection, they must be stored as a 16-byte entry of type TO2_RECOUP_FA, which has the following format:
If 8-byte file addresses are embedded in a collection, they must be stored as a 16-byte entry of type TO2_RECOUP_XFA, which has the following format:
If PIDs are embedded within a collection, they must be stored in the following format:
The following examples are intended as suggested uses for TPFCS recoup applications.
The following example creates recoup indexes:
/*********************************************************************/ /* Sample application to create recoup indexes */ /*********************************************************************/ #include <tpfapi.h> /* Needed for TPF_regs structure */ #include <c$to2.h> /* Needed for TO2 API functions */ #include <stdio.h> #include <stdlib.h> #include <string.h> void main( void ) { TO2_ENV_PTR env_ptr = NULL; /* pointer to environment */ TO2_USER_TOKEN userToken = 0; /* user token */ char applid[] = "RECOUP_INDEX_CREATOR "; char dsname[] = "TESTX.DS"; TO2_PID dsDictPID; /* DS dictionary PID */ TO2_PID_PTR dsDictPtr = &dsDictPID; /* ptr to DS dict PID */ char IndexName[8]; /* Recoup index name */ TO2_RECOUP_TYPE rc_type; /* recoup index type */ TO2_RECOUP_CONTROL rc_ctrl; /* recoup index control */ TO2_RECOUP_ENTRY_TYPE rce_type; /* PID or FA indicator */ TO2_RECOUP_ENTRY_ACCESS rce_access; /* index or key indicator */ char rce_token[8]; /* recoup index entry token */ long rce_displ; /* displ. to embedded ref. */ long rce_valLen; /* length of collect. index */ long rce_value; /* collection index */ /*********************************************************************/ /* Create TO2_environment */ /*********************************************************************/ if (TO2_createEnv(&env_ptr,&userToken,applid,dsname) == TO2_ERROR) { printf("ERROR: createEnv failed ! \n"); exit(1); } /*********************************************************************/ /* Set up the recoup index for the application dictionary collection.*/ /* If this index already existed, delete it first and recreate it. */ /* Each entry in the dictionary collection will have a PID embedded */ /* at a displacement of 0, so the collection is homogeneous. */ /*********************************************************************/ if (TO2_getDSdictPID(dsDictPtr, env_ptr) == TO2_ERROR) { printf("ERROR: getDSdictPID failed\n"); TO2_deleteEnv(env_ptr); exit(1); } memcpy(IndexName, "APPLDICT", 8); TO2_deleteRecoupIndex(env_ptr, IndexName); rc_type = TO2_RECOUP_HOMOGENEOUS; rc_ctrl = TO2_RECOUP_CONTROL_NONE; if (TO2_createRecoupIndex(env_ptr, IndexName, rc_type, rc_ctrl, NULL, NULL, "Used with data store appl dictionary") == TO2_ERROR) { printf("ERROR: createRecoupIndex %s failed\n", IndexName); TO2_deleteEnv(env_ptr); exit(1); } memcpy(rce_token, "ENTRY001", 8); rce_type = TO2_RECOUP_ENTRY_PID; rce_displ = 0; rce_access = TO2_RECOUP_ACCESS_NOTUSED; if (TO2_addRecoupIndexEntry(env_ptr, IndexName, &rce_token, rce_type, &rce_displ, rce_access, NULL, NULL) == TO2_ERROR) { printf("ERROR: addRecoupIndexEntry for DS failed !\n"); } if (TO2_associateRecoupIndexWithPID(dsDictPtr, env_ptr, IndexName) == TO2_ERROR) { printf("ERROR: associateRecoupIndexWithPID for DS failed !\n"); } /*********************************************************************/ /* Create a recoup index for a heterogeneous collection. */ /* Every collection that is associated with this recoup index must */ /* have the following format: */ /* The second element has two embedded references; a file address */ /* at displacement 16, and a file address at displacement 40. */ /* The third element has an embedded file address at displacement */ /* 14. */ /* (Note: Minimal error checking is shown.) */ /*********************************************************************/ memcpy(IndexName,"HETERO01",8); rc_type = TO2_RECOUP_HETEROGENEOUS; rc_ctrl = TO2_RECOUP_CONTROL_NONE; if (TO2_createRecoupIndex(env_ptr, IndexName, rc_type, rc_ctrl, NULL, NULL, NULL) == TO2_ERROR) { if (TO2_getErrorCode(env_ptr) == TO2_ERROR_INDEX_EXISTS) printf("Index %8s already exists\n", IndexName); else { printf("ERROR: createRecoupIndex %s failed\n", IndexName); TO2_deleteEnv(env_ptr); exit(1); } } memcpy(rce_token, "ENTRY01A", 8); rce_type = TO2_RECOUP_ENTRY_FA; rce_displ = 16; rce_access = TO2_RECOUP_ACCESS_INDEX; rce_valLen = 4; rce_value = 2; TO2_addRecoupIndexEntry(env_ptr, IndexName, &rce_token, rce_type, &rce_displ, rce_access, &rce_valLen, &rce_value); memcpy(rce_token, "ENTRY01B", 8); rce_displ = 40; TO2_addRecoupIndexEntry(env_ptr, IndexName, &rce_token, rce_type, &rce_displ, rce_access, &rce_valLen, &rce_value); memcpy(rce_token, "ENTRY02A", 8); rce_displ = 14; rce_value = 3; TO2_addRecoupIndexEntry(env_ptr, IndexName, &rce_token, rce_type, &rce_displ, rce_access, &rce_valLen, &rce_value); /*********************************************************************/ /* Delete TO2_environment */ /*********************************************************************/ TO2_deleteEnv(env_ptr); exit(0); }
The following example associates recoup indexes with collections:
/*********************************************************************/ /* Sample application to associate recoup indexes with collections */ /*********************************************************************/ #include <tpfapi.h> /* Needed for TPF_regs structure */ #include <c$to2.h> /* Needed for TO2 API functions */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <tpfio.h> /* Needed for getfc() */ void main( void ) { TO2_ENV_PTR env_ptr = NULL; /* pointer to environment */ TO2_USER_TOKEN userToken = 0; /* user token */ char applid[] = "APPLICATION_1 "; char dsname[] = "TESTX.DS"; /* data store name */ char IndexName[8]; /* Recoup index name */ TO2_PID pid; /* area for array PID */ TO2_PID_PTR arpid_ptr=&pid; /* pointer to array PID */ char element[50]; /* array element */ long element_length; /* length of array element*/ TO2_RECOUP_FA fa_entry; /* fileAddr entry in elem */ char recid[2]; /* fileAddr record ID */ unsigned int file_addr; /* TPF record file address*/ struct stdhdr *file2rec_ptr; /* pointer to TPF record */ long size; /* size of PID */ TO2_OPTION_PTR optionListPtr = NULL; /* pointer to option list */ char colName[64]; /* collection name */ /*********************************************************************/ /* Create TO2_environment */ /*********************************************************************/ if (TO2_createEnv(&env_ptr,&userToken,applid,dsname) == TO2_ERROR) { printf("ERROR: createEnv failed ! \n"); exit(1); } /*********************************************************************/ /* Create an array that is associated with the heterogeneous recoup */ /* index created in the previous sample application. The array will */ /* be an anchor collection in the data store, so add it to the data */ /* store application dictionary. Also, assign a browse name to the */ /* array that is the same as the array's key in the application dict.*/ /*********************************************************************/ memcpy(IndexName,"HETERO01",8); element_length = sizeof(element); optionListPtr = TO2_createOptionList(env_ptr, TO2_OPTION_LIST_CREATE, TO2_CREATE_RECOUP, TO2_OPTION_LIST_END, IndexName); if (TO2_createArrayWithOptions(arpid_ptr, env_ptr, optionListPtr, &element_length) == TO2_ERROR) { printf("ERROR: createArray failed !\n"); } free(optionListPtr); memset(colName, 0x00, sizeof(colName)); memcpy(colName, "ARRAY1", 6); size = sizeof(TO2_PID); TO2_atDSdictNewKeyPut(env_ptr, colName, arpid_ptr, &size); TO2_defineBrowseNameForPID(arpid_ptr, env_ptr, colName); /*********************************************************************/ /* Add the 3rd element to the array. This element has a TPF file */ /* address embedded at a displacement of 14 bytes. The TPF file has */ /* a standard TPF header and will contain forward references. */ /*********************************************************************/ recid[0] = 0xAB; recid[1] = 0x12; file_addr = getfc(D2, GETFC_TYPE0, recid, GETFC_BLOCK|GETFC_FILL, GETFC_NOSERRC, 0x00); memset(&fa_entry, 0x00, sizeof(fa_entry)); fa_entry.flag = TO2_RECOUP_DSCR_YES; memcpy(&fa_entry.recID, recid, 2); memcpy(&fa_entry.fileAddr, &file_addr, 4); file2rec_ptr = ecbptr()->ce1cr2; memcpy(file2rec_ptr,&array_entry.recID,4); filec(D2); memset(&element, 0x00, sizeof(element)); memcpy(element,"DATA BEFORE FA",14); memcpy(&element[14], &fa_entry, sizeof(fa_entry)); memcpy(element,"DATA AFTER FA",13); TO2_add(arpid_ptr, env_ptr, element, &element_length); /*********************************************************************/ /* Delete TO2_environment */ /*********************************************************************/ TO2_deleteEnv(env_ptr); exit(0); }