Transaction processing in a distributed data processing system5438509Abstract A system for processing transactions and a methodology for the design of such a system for enhanced transaction processing across different computing platforms. Transaction orders and transaction data are transferred and stored within the system in a standard, hardware independent format. Data generated as part of a transaction is stored in a circular queue; orders are stored so that they can be accessed by their order number or other key attribute. Nonvolatile memory is used extensively to increase system reliability and data integrity by reducing the chances of data loss due to a system shutdown. Data is stored to nonvolatile memory before pointers to the data are modified to eliminate problems due to pointers pointing to nonexistent data. Claims What is claimed is: Description BACKGROUND OF THE INVENTION
______________________________________
struct ddam.sub.-- head {
USHORT rbn;
USHORT rrn;
USHORT secsz;
USHORT hdsz;
USHORT blksz;
USHORT blkn;
USHORT full;
USHORT sysid;
UCHAR create[7];
UCHAR opn[512];
};
______________________________________
"hd->rbn" is used to hold the last relative block number read from the file. This value in the header record is initialized to binary ones at file allocation, indicating a "null file". "hd->rrn" is used to hold the last relative record number read from the file. This value in the header record is initialized to binary ones at file allocation, indicating a "null file". "hd->secsz" is used to hold the disk sector size for a specified file. "hd->hdsz" is used to hold the header record size in bytes. "hd->blksz" is used to hold the data block size in bytes. "hd->blkn" is used to hold the total number of data blocks in a specified file. This value is used to assist in determining a wrap condition where the file must be pointed back to the first data block. "hd->full" is used as a flag to indicate that the file is full and data writing is not permitted. This flag can be set to the "full" indication during a write to the file and set to a "not full" indication after records have been retrieved from the file. "hd->sysid" is used to optionally hold an application identification. "hd->create" is used to hold the file creation date. This date is applied to the header record when the file is allocated and formatted. "hd->opn" is the start of the remaining open space in the header record. It is defined in the structure as 512 bytes but this value will be dynamic based upon the specified header size. It is of interest only to read the first 512 bytes of the header into memory and assures the application of at least 512 bytes for the header record. The "ddam.sub.-- calc" structure is used to hold calculated values during positioning, reading and write processing of the file. This structure can also optionally hold the last relative block and record numbers received from another application. The "ddam.sub.-- calc" structure is referenced by prefixing "calc->" to a specific structure variable name (e.g. calc->first).
______________________________________
struct ddam.sub.-- calc {
USHORT rbn;-
USHORT rrn;
USHORT first;
USHORT last;
UCHAR cycle;
USHORT from.sub.-- rbn;
USHORT from.sub.-- rrn;
};
______________________________________
"calc->rbn" is used to hold the calculated relative block number of the file. The calculated relative block number addresses the data block that will be written to disk when the next record is added to the file. This is the dynamic logical beginning of the file. This value is established during application initialization when the file is positioned and updated as required during a write to the file. "calc->rrn" is used to hold the calculated relative record number within the relative data block described above. The calculated relative record number addresses the next position in the data block that will be used when the next record is added to the file. "calc->first" is used to hold the first relative block number of the file. Relative block and record numbering start at zero. "calc->last" is used to hold the relative block number of the last block read during file positioning. This value is used to assist in the determination of the dynamic logical beginning of the file. calc->cycle" is used to hold the current cycle byte comparison value. This value is used to assist in the determination of the dynamic beginning of the file. "calc->from rbn" is used to hold the relative block number contained in a record received from another application. This value is used to keep two Direct Data Access Method files in lock step with each other. "calc->from.sub.-- rrn" is used to hold the relative record number contained in a record received from another application. This value is also used to keep two Direct Data Access Method files in lock step with each other. The "ddam.sub.-- blk" data structure is used to hold memory address pointers to the file header buffer and the data block memory buffer reserved for writing. These pointers are used during positioning and write processing of the file. The "ddam.sub.-- blk" structure is referenced by prefixing "db->" to a specific structure variable name (e.g. db->fsl).
______________________________________
struct ddam.sub.-- blk {
USHORT *hd;
UCHAR *cb;
UCHAR *fsl;
UCHAR *fso;
};
______________________________________
"db->hd" is a memory address pointer to the file header memory buffer. This address is established at file access initialization. "db->cb" is a memory address pointer to the cycle byte position of the file data block memory buffer reserved for writing. This address is established at file access initialization. db->fsl" is a memory address pointer to the free space length value of the file data block memory buffer reserved for writing. This address is established at file access initialization. "db->fso" is a memory address pointer to the free space offset value of the file data block memory buffer reserved for writing. This address is established at file access initialization. The "ddam.sub.-- blkg" data structure is used to hold memory address pointers to the file header and the data block memory buffer reserved for reading. These pointers are used during read processing of the file. The "ddam.sub.-- blkg" structure is referenced by prefixing "dbg->" to a specific structure variable name (e.g. dbg->cb).
______________________________________
struct ddam.sub.-- blkg {
USHORT *hd;
UCHAR *cb;
UCHAR *fsl;
UCHAR *fso;
};
______________________________________
"dbg->hd" is a memory address pointer to the file header memory buffer. This address is established the file access initialization. "dbg->cb" is a memory address pointer to the cycle byte position of the file data block memory buffer reserved for reading . This address is established at file access initialization. "dbg->fsl" is a memory address pointer to the free space length value of the file data block memory buffer reserved for reading. This address is established at file access initialization. dbg->fso" is a memory address pointer to the free space offset value of the file data block memory buffer reserved for reading. This address is established at file access initialization. The "ddam.sub.-- get" structure is used to hold values required during read processing. The "ddam.sub.-- get" structure is referenced by prefixing "getx->" to a specific structure variable name (e.g. getx->flag).
______________________________________
struct ddam.sub.-- get {
USHORT rbn;
USHORT rrn;
USHORT flag;
USHORT w.sub.-- flag;
USHORT lnth;
UCHAR *addr;
};
______________________________________
"getx->rbn" is used to hold the relative block number for the next read. This value is established and updated during read processing. "getx->rrn" is used to hold the relative record number for the next read. This value is established and updated during read processing. "getx->flag" is used to indicate the status of read processing. This value is defined as zero at initialization, updated to "IDAM.sub.-- GET.sub.-- STARTED" on the first call to the get routine and updated to "IDAM.sub.-- GET.sub.-- COMPLETE" when the get processing is complete. "getx->w.sub.-- flag is used by the write and read processing routines only if a write occurs to a data block that is currently being read. "getx->lnth" is used to store the length of the data record during read processing. "getx->addr" is an address pointer to the data record in the block and is updated during read processing. At file allocation all cycle bytes are initialized to binary zeros and the header record fields for the relative block and record numbers are initialized to binary ones. This indicates a "null file" with no data records. A Direct Data Access file is considered "null" until two conditions are met. The first, records must be written to the file and the second, records must have been retrieved from the file. The file remains "null" when only records have been written. At file initialization the logical and physical beginning and end of the file are the same. The logical beginning and end change as records are written and retrieved from the file. The cycle byte is used to assist in calculating the next relative block number that may be used for the next write to the file. It is one of the values that determine the dynamic logical beginning and end of the file. It is inverted when the first write to the data block occurs. The relative position of a data block in the file where the cycle byte changes is of interest. The value of binary zeros or binary ones is significant only to detect the change. At application program initialization the first 512 bytes of the file header record are read into a temporary buffer and the file specification information is accessed to dynamically allocate system memory for the file processing. Specifically, the initialization for file processing is as follows. The file is opened and the actual size of the header record is determined from the first 512 bytes of the header record. Memory is then dynamically allocated and the address is stored in the address pointer to the file header record in memory. The total header record is read into that memory. The size of a data block is determined from the header record, memory dynamically allocated for both the read and write data block storage. The addresses of those memory locations are stored in the appropriate structures described above. The "C" functions, "ddam.sub.-- inth", "ddam.sub.-- intp" and "ddam.sub.-- intg" perform the file access initialization and the "C" function "ddam.sub.-- finish" releases the allocated memory at the end of the application. The file is then positioned to determine the next available relative block and record for write processing. The "C" function "ddam.sub.-- pos" is used to position the file and is illustrated in FIGS. 9a and 9b. The flow is described as follows. At 220 "hd->rbn" is checked to determine if the file is "null". A "null file" indicates first, that no records have been read from the file and second that records may not have been written to the file. If at 220 the file is determined to be "null" at 222 the first data block is read into memory and at 224 the cycle byte is examined to determine if it is binary zeros. If at 224 the cycle byte is binary zeros, at 226 the routine "fix.sub.-- p" is called to set the calculated relative block and record numbers ("fix.sub.-- p" is described later). This condition indicates both that no records have been written and no records retrieved. Otherwise at 228 the routine has determined that there are no records in the block and points the file to the first data block. In either case, the routine then returns control to the calling routine. If the file is determined at 220 not to be "null", (records have been written and retrieved indicated by "hd->rbn" not being all binary ones) at 230 the file is pointed to the relative block number contained in "hd->rbn". This value is stored in the header record and is the pointer to the last data block that was read or retrieved from the file. This is the relative block of the logical beginning of the file. At 232 the data block is read into memory and the cycle byte value saved. At 234 the next sequential data block is read into memory. If at 236 this data block read detects the end of the physical file, at 238 the file is pointed to the first data block and at 240 the first data block is read into memory. If at 236 the end of the physical file is not detected, the routine at 242 determines if any data records have been written beyond the logical beginning of the file. This is done by looking for a transition in the value of the cycle byte from one block to the next block. This is accomplished by checking the cycle byte to determine if it is the inversion of the cycle byte saved on the first data block read. If at 242 the cycle byte is not different from the cycle byte saved on the first data block read, the routine moves to 234. The routine continues to move through the data blocks until it detects the transition. When at 242 the transition is detected, the file is now pointing one block beyond the last block that had data written to it. A call to the routine "fix.sub.-- p" is executed. The routine "fix.sub.-- p" is illustrated in FIG. 9b. At 250 the routine "fix.sub.-- p" points the file back to the last relative data block read or "calc->last". At 252 the data block is read into memory and scanned to determine "calc->rrn". This is the next relative record number to be used for that block. Its location is in the free space of the block. "calc->rbn" is then set to "calc->last". The file is now considered "positioned", such that the next relative block and record numbers (for a write) are known to the method. Direct Data Access Method file reading is illustrated in FIGS. 7a and 7b and described as follows. The purpose of the file read is to retrieve any data records that may have been written to the file. The intended use of this method is temporary storage of data. Storage such that a specific data record be secured to disk and need only be read if the memory image was not processed or transferred to another system. (reference back to the lock step description) The "C" function call "ddam.sub.-- getr" provides the read logic for this method and is referenced at the label "GETR" on FIG. 7a. At 100 the routine checks an internal flag to determine if the call is the first call to the routine. If so, at 102 the relative record number for the next read is set to minus one and at 104 "hd->rbn" is examined to determine if the file is initially considered "null". If this is true, at 106 "getx->rbn" is set to "calc->first", at 108 the file is pointed to "calc->first" and at 110 the first data block is read into memory. At 112, the cycle byte is examined for binary zeros. If the cycle byte is binary zeros, the file is considered "null" and no data records exist. At 114 the status variable "util.sub.-- drc" is set indicating that the read is complete and the routine returns from the call. If the cycle byte is not binary zeros, the file is still considered "null" but it does contain some records that have not been retrieved. A check is made at 116 to see if the variables "getx->rrn" and "hd->rrn" are equal. If so the routine moves to 140 in FIG. 7b to read the record. If the variables are not equal, at 118 "getx->rrn" is incremented, the free space offset variable is updated and the routine moves back to 116. If, at 104, the file is determined not "null", at 120 "getx->rbn" is set to "hd->rbn". This is the relative block number of the last data block read from the file. At 122 the file is then pointed to "hd->rbn" and at 124 the data block is read into memory. The routine then moves to 116 as described above. If, at 100, this is not the first call to the routine, at 130, the file is pointed to "getx->rbn". This is required in the event that the file was repositioned during a write to the file. At 132 a check is made to determine if a write has occurred to the current block that records are being retrieved from. If not the routine moves to 140 in FIG. 7b. If so, the routine at 134 reads the block from the file, providing the latest data record information, before moving to 140. The primary function of the logic started at 140 in FIG. 7b is to make the next record available to the application. This "availability" is an address pointer to the record in the data block memory buffer and the length of the record. It is then the responsibility of the application program to process that record as required. At 140 the routine checks if the read and write file pointers are equal. If the file pointers are equal, the last data record has been retrieved from the file. At 142 "getx->rrn" is decremented by one and at 144 the "util.sub.-- drc" status variable is set to a complete status. The routine then returns from the call. If at 140 the file pointers are not equal, there may be more records to retrieve from the file. At 146 "getx->rrn" is incremented by one in expectation of another record. At 148, the read and write file pointers are again checked for inequality and if found equal, the last data record has been retrieved from the file and the routine moves to 142, 144 and returns. If at 148 the file pointers are not equal, a check is made at 150 to determine if the record pointer is in the free space of the data block. If the record pointer is in the free space, at 158 "getx->rbn" is incremented by one and at 160 a check is made for the end of the physical file. If the end of the physical file has been reached, at 162 the file is pointed to "calc->first", at 164 the first data block is read into memory and at 166 "getx->rbn" is set to "calc->first". If at 160 the end of the physical file has not been reached, at 168 the file is pointed to "getx->rbn" and at 170 the data block is read into memory. In either case, at 172 the file pointers are again checked for inequality. If the file pointers are equal the routine proceeds to 142, 144 and returns. Otherwise the routine moves to 152. If at 150 the record pointer is not in the free space portion of the record, the routine moves to 152. At 152, "getx-addr" is set to the data block memory buffer address of the record and at 154 "getx->lnth" is set to the length of the record. At 156 the read is flagged as started and the function returns from the call. This routine returns when each record is read and when the routine detects completion of the read or that the last record has been retrieved. Direct Data Access Method file writing is illustrated in FIG. 8 and described as follows. The label "PUT" is the entry point for the write function and the "C" function call "ddam.sub.-- put" is used. At 180 the first check determines if the file is in a full state. This is accomplished by checking "hd->full", which is stored in the file header. If the file is full, at 182 the status variable "util.sub.-- drc" is set to the file full condition and the function returns from the call. If at 180 the file is determined not to be full, at 184 the length of the data passed in the requesting write is compared with the free space in the current data block. If the length of the data is less than or equal to the amount of free space remaining, the routine moves to 194. If the length of the data is greater than the amount of free space remaining in the block, at 186 "calc->rbn" is incremented and "calc->rrn" is set to zero. This indicates a new or subsequent data block is needed and that the first relative record number will be zero. A check is made at 188 to determine if this relative block is equal to the logical end of the file. The logical end of file is the relative block number stored in "hd->rbn", the last relative data block that was read from the file. If the logical end of file has been reached, the file has wrapped around to the location of the next record to be read and therefore there is no room to write the record to the file. At 190 the status variable is set to a file full condition, the header record updated and the function returns from the call. If at 188 the logical end of file was not reached, at 191 the free space offset and free space length values are reset in the data block memory buffer and the routine moves to 192. At 192 a check is made to see if the current record contains a relative block or record number. If not the routine moves to 194. If the current record does contain a relative block or record number, this number is in error. Relative block or record numbers are inserted into a record by the application code. They are used to keep applications running on different platforms in lock step. The application attaches the number, its field length and its attribute code to the record string. The number used is read from "calc->rbn" or "calc->rrn," the block and record of the next record write. This works fine as long as there is enough free space in the current block for the record to be written. However, the length of the record is not checked against the free space remaining until the record is written. This means that if enough free space does not exist, relative block and record numbers within the record must be modified to reflect the new block and record location. This is done at 193. The routine then moves to 194. At 194 the data record is moved to the free space in the data block memory buffer. At 196, the free space offset is incremented by the length of the data record and the free space length is decremented by the length of the data record. This is in expectation of the next write to the file. A check is made at 198 to determine if the end of the physical file has been reached. This can occur as "calc->rbn" is incremented. If the physical end of the file has not been reached, the routine moves to 206. If the physical end of the file has been reached, at 200 the file is pointed to the first data block. A check is made at 202 to determine if this is the logical end of file. If not, the routine moves to 206. If it is the logical end of file, at 204 the status variable is set to the file full condition and the function returns from the call. At 206 the routine points the file to the current data block contained in "calc->rbn". This is required due to the fact that reading and writing can be interleaved to the same file. At 208 the data block is then written to disk. At 210 the relative record number "calc->rrn" is incremented and the function returns from the call. The record manipulation primitives and direct data access primitives are all that are required to build self-contained data collection systems. A system built on these primitives is capable of storing data to nonvolatile memory as it is acquired and retrieving and examining that data at a later date. The use of nonvolatile memory provides high data integrity in the handling of data. Addition of the proper communication primitives allows transfer of captured data to other processor platforms. These primitives could be used in systems outside of transaction processing. In the field of manufacturing, the relative block number and the relative record number could be used to track the discrete events of a robotic manipulation in order to recover from unforeseen events such as power failures. A much more complex processing system can be constructed when the record manipulation and direct data access primitives are combined with an index data access primitive. The Index Data Access (IDA) Method is a simplified method for organized storage and retrieval of data records via an index of keys. Each key in the index is a meaningful value associated with a data record. The key is usually also contained in the data record. All keys are fixed to a specified length and all data blocks are fixed to a specified length on a per file basis. For each data block one key entry exists in the index. The relative position of a key in the index determines the relative position of the data record on disk. The IDA primitives are designed such that a copy of the complete index is stored in memory. This reduces program complexity and the search time needed to scan the index. This also limits the index size to a portion of system memory. However, the intended use of the method is for smaller distributed systems and as memory becomes less costly the limitation becomes less significant. Overall processing time is reduced to a minimum for the fundamental functions of an index access method. The index is updated on disk only after it is changed in memory. Only the disk sector containing the portion changed is written back to disk. If an index entry spans a sector, both sectors are written to disk. This assists in reducing disk processing time. Disk processing time is reduced on a "record delete" function by flagging the control byte of the key in the index, and again only writing that portion of the index back to disk. The "record add" function requires writing both the index portion and the data record to disk. The "record update" function requires reading the data record into memory, changing it, and writing the data record back to disk. The "record replace" function requires only writing the data record to disk. Reading the record is of no interest on a "replace" function. The IDA method reduces the possibility of file corruption during abnormal program termination. During a "record add" function a data block is written to disk before the updated index portion. During a "record delete" function only the control byte of the index key entry is changed (not the actual key). Then only that portion of the index is written to disk. With appropriate structure addressing more than one index access file can be utilized in an application. A file is allocated and formatted for use as an Index Data Access Method file. The specifications for allocation are as follows: Disk sector size: This is generally the smallest subdivision of a disk file that the operating system will read or write. The file allocation size is based on multiples of the sector size. Number of data blocks or records: This is the perceived total number of application records that the file will hold. Application record and data block record are considered to be the same. Size of the data block: This is the size of the record data block in bytes, required by the application. The size of each data block will be rounded up to multiples of the sector size. All data blocks are allocated to the same size for a specified file. Length of the key field in bytes: Each record on the file is located by a unique key. This key is an application specific data item that is meaningful in relation to the record. From the above specifications the size of the file is determined. The block size is rounded up to a multiple of the given sector size. The total block size is the individual block size times the number of records. The index is structured such that a one byte control field is prefixed to each key field. Also, one additional key field is allocated to indicate the end of the index. This end of index marker is a key field and control byte set to binary ones. The size of the index is the key size plus the control byte, times the number of records plus one (for the end of index) and rounded up to a multiple of the given sector size. In addition to the index and data blocks a header record is required for each file. This header record is allocated as the size of one sector. The total byte size of the file is a summation of the above. When the file is created the index is formatted with all key fields initialized to binary zeros, and key field control bytes initialized to an "open" status. Also, all data blocks are initialized to binary zeros. A given file can be represented by the diagram shown in FIG. 5. The file header record contains the file specification information and is formatted as follows: Two byte unsigned integer for the header record size in bytes; Two byte unsigned integer for the sector size in bytes; Two byte unsigned integer for the index size in bytes; Two byte unsigned integer for the key size in bytes; (key size plus one) Two byte unsigned integer for the data block size in bytes; Two byte unsigned integer for the number of data blocks; Two byte unsigned integer for the file full flag; Two byte unsigned integer for the optional application identification; Seven byte field for the file creation date stored as unsigned hexadecimal values (YYYYMMDDHHMMSS); Open space for the remainder of the header record. In the preferred embodiment, a utility program is provided for the allocation and formatting of an Index Access Method file. A data structure of file information is partially created at application initialization. This structure is also referenced and updated during processing and contains the following: Address pointer to the file header record in memory; Address pointer to the specific record; Address pointer to the data block memory buffer; Address pointer to the specific index disk sector; Address pointer to the data block cycle byte; Address pointer to a search key field; Address pointer to the free space length value of a data block; Address pointer to the free space offset value of a data block; Address pointer to the index memory buffer; Address pointer to the key of interest in the index memory buffer; Address pointer to end of index marker; Two byte unsigned integer for the length of the record; Two byte unsigned integer for the relative data record number; Two byte unsigned integer for the count of open index entries; Two byte unsigned integer for the relative record in a data block; At application program initialization the first 512 bytes of the file header record are read into a temporary buffer and the file specification information is accessed to dynamically allocate system memory for the file processing. The initialization for file processing is explained next. At initialization the file is opened and the first 512 bytes of the header record are read into a temporary buffer. The actual size of the header record is determined, memory dynamically allocated and the address is stored in the address pointer to the file header record in memory. The total header record is read into that memory. The size of the index is determined from the header record, memory is dynamically allocated and the address is stored in the address pointer to the index memory buffer. The size of a data block is determined from the header record, memory is dynamically allocated and the address is stored in the address pointer to the data block memory buffer. The index is then read into the appropriate memory buffer. All index access is from this memory buffer for performance. Once the index is read into memory, the data memory block buffer is cleared to binary zeros. The address pointer to the end of index marker is established, and the pointer to the key of interest in the index memory buffer is set to the address of the first key in the index memory buffer. In the preferred embodiment, a "C" function call (idam.sub.-- int) is provided for this initialization and a "C" function call (idam.sub.-- finish) is provided to de-allocate system memory at application termination. The fundamental data processing functions of the Index Data Access Method provide addition or replacement of data records, deletion of data records and reading of data records. To add or replace a data record implies writing the data record to disk. This also further implies that on an add condition the index be updated on disk. The add condition, by design, will write the data record to disk first, then update the index on disk. A replace condition does not require the index to be updated. This approach provides a minimal amount of data loss and disk file corruption in the event of a hardware or software failure during an update to the file. To delete using the IDA method the control byte for the key of interest is charged to an "open" status. The index is then updated on disk. The data record is of no interest. The specific function calls provided with the Index Data Access Method are next described. To add a record to the file the application program has to determine if an open index entry exists. This is accomplished with the "C" function call "idam.sub.-- find.sub.-- open". This call starts at the beginning of the index in memory and scans to the end of index marker. During the scan the relative data record number is updated and the pointer to the key of interest is updated. Each index entry control byte is examined for an "open" status and the first occurrence of an "open index entry causes the function to return to the application. If no "open" index entries were found the status variable (util.sub.-- irc) is set to IDAM.sub.-- NO.sub.-- OP. If an "open" index entry was found the status variable is set to IDAM.sub.-- OK. It is the responsibility of the application program to check this value on completion of the call. At the completion of the call, the pointer to the key of interest is available to the application program. It is the responsibility of the application program to build the key and to build the application data in the data record buffer. The pointer to the key of interest points to the control byte. It is the responsibility of the application program to set this byte to the appropriate value. In this example the value is IDAM.sub.-- INUSE. The application program may then use the "C" function "idam.sub.-- build.sub.-- key". This function will move the application key data to the index entry. The length of the move is derived from the key size in the file header record. The next call to be issued is "idam.sub.-- write.sub.-- data". This call will write the data record buffer to the file at the relative data record number. The relative data record number was established during the "idam.sub.-- find.sub.-- open" call. The index will optionally be written after the data record. This index write function is specified as one of the parameters to the call. In the preferred embodiment this option is used to force the write of the index on each "add" data write. This will assist in maintaining file integrity. To replace an existing data record on the file the application program has to first determine if the record key exists. This is accomplished with the "C" function call "idam.sub.-- find.sub.-- equal". This function expects the search key field to contain the key value to search for. It is the responsibility of the application program to build the search key and set the search key pointer in the structure of file information. This function call starts at the beginning of the index in memory and scans to the end of index marker. During the scan the relative data record number is updated and the pointer to the key of interest is updated. Each index entry is compared to the search key and the first occurrence of an "equal" condition causes the function to return to the application. If no "equal" condition occurs the status variable (util.sub.-- irc) is set to IDAM.sub.-- NO.sub.-- EQ. If an "equal" index entry was found the status variable is set to IDAM.sub.-- OK. It is the responsibility of the application program to check this value on completion of the call. The next call to be issued is "idam.sub.-- write.sub.-- data". This call will write the data record buffer to the file at the relative data record number. The relative data record number was established during the previous call. The index does not have to be written and the function call should be made without the write index option. To delete an existing data record the application must determine if the record key exists. The "idam.sub.-- find.sub.-- equal" is used again. If an "equal" condition is determined, it is the responsibility of the application program to update the control byte of the key to "IDAM.sub.-- OPEN". The "IDAM.sub.-- OPEN" status in a control byte signifies that this index entry may be used again. The application program must then write the index to the disk. This is accomplished with the "C" function call "idam.sub.-- write.sub.-- index". This call will determine the specific sector that the updated key is in. The file is then positioned to this location and the specific sector of the index is written. It is the responsibility of the application program to examine the "util.sub.-- irc" status variable on completion of the call. To read an existing data record the application must determine if the record key exists. The "idam.sub.-- find.sub.-- equal" is used again. If an "equal" condition is determined, the application program must use the "C" function call "idam.sub.-- read.sub.-- data". This function call will read the appropriate data record into the data block memory buffer. The application program may then access the data via the pointer to the data block memory buffer. Other ancillary functions for the index data access method are described. A count of all "open" index entries can be determined by using the "C" function call "idam.sub.-- count.sub.-- open". The index can be cleared or each entry control byte set to "IDAM.sub.-- 0PEN" by using the "C" function call "idam.sub.-- clear". This call will write the index to disk for each entry. Each "in use" or active key can be returned to an application program by using the "C" function call "idam.sub.-- get.sub.-- keys". This call is intended to be used iteratively as it will return each time an "in use" key is detected. Each "open" key can be returned to an application program by using the "C" function call "idam.sub.-- get.sub.-- key.sub.-- op". This call is intended to be used iteratively as it will return each time an "open" key is detected. By design the Index Data Access method does not destroy any key field data or data block data during delete or clear functions. Only the index entry control byte is changed and the index written back to disk. This will provide a measure of recovery in the event that an application program deletes or clears index entries inadvertently. The "C" function call "idam.sub.-- get.sub.-- key.sub.-- op" could be used and an application program could examine the key, the data record, or change the index entry control byte. The Index Data Access Method can store a block of data in essentially the same format as the Direct Data Access Method. This provides a mechanism to store variable length records in an Index Data Access Method data block and access the data block with a key. In order to perform this function, IDA primitives are provided. In the preferred embodiment at the protocol level the primitives are provided as source code in "C" and parts of the utility level are supplied in assembly language. The source code is then compiled in a library and linked with the application code. Format and initialization functions are required. If the data block is considered "new" or "unknown", it must be formatted. Initialization is required before the first write access to a data block. Initialization establishes the location for writing the next record. To format a "new" or "unknown" data block the "C" function call "idam.sub.-- fmtn" is used. The data block is cleared to binary zeros. A cycle byte, free space length and offset values are established in the data block memory buffer. The cycle byte is present only to maintain format compatibility with the Direct Data Access Method. The free space length is the remaining number of bytes in the data block available for record storage. The free space offset is the starting location in the data block of the free space. The above values are stored in the structure of file information and in the data block memory buffer. The values occupy the first four bytes of the data block in this implementation. To initialize the environment before the first "write" access the "C" function "idam.sub.-- intb" is used. This function call will establish the free space length and offset values in the structure of file information from the data block memory buffer. The data block in memory could be a "newly" created data block or a data block that has been read from disk. To add a record to a data block the "C" function "idam.sub.-- addt" is used. This function call will move a record to the data block provided there is enough free space in the data block. The data block will then be optionally written to disk. It is the responsibility of the application program to examine the "util.sub.-- irc" status variable on completion of the call. To retrieve a record from a data block the "C" function "idam.sub.-- gets" is used. This function searches the data block for a specific record and sets a status variable accordingly. The address pointer to the specific record and the record length are also updated. It is the responsibility of the application program to examine the "util.sub.-- irc" status variable on completion of the call. The methodology of the present invention can be used to connect processing platforms from hand held calculators to mainframes and has applications ranging from transaction processing to manufacturing. Although the present invention has been described with reference to the preferred embodiments, those skilled in the art will recognize that changes may be made in form and detail without departing from the spirit and scope of the invention.
|
Same subclass Same class Consider this |
||||||||||
