isam.c performs the identical function that lowlevel.c does, and creates a data file and index that matches those created by lowlevel.c. In fact, the data and index files created by one program can be accessed by the other. The primary difference is that isam.c uses the ISAM functions and an ISAM parameter file (which is now considered legacy) instead of low-level functions.
In lowlevel.c we established the FairCom DB buffer parameters with a call to InitCTree(), and set up the attributes of the two data files and one index by successive calls to CreateDataFile() and CreateIndexFile(), or to OpenCtFile(). With three files to create/open, we needed four function calls.
CreateISAM and OpenISAM
With the ISAM functions, we only need one call: CreateISAM() to create the files, or OpenISAM() to open existing files. The only parameter passed to either function is the name of the ISAM parameter file. The parameter file contains all of the information to initialize FairCom DB and to create/open the data files. In our example the ISAM parameter file is isam.p, as follows:
10 1 4 1
0 invent.dat 128 4096 1 1 Delflag Buffer
1 invent.idx 25 0 0 0 4096 1 0 32 1 Itemidx
2 25 2
The first record in the ISAM parameter file is the Initialization record. This contains the same information as is used in the InitCTree() call, organized in a slightly different manner. The first value is the number of index file buffers, as before. The third value is the number of node sectors. The difference is that in InitCTree() we had one figure for the number of data files and indexes that will be opened (2 in this example), while in the ISAM parameter file we must specify the number of indexes (1) as the second parameter, and the number of data files (1) as the fourth parameter.
Data Description Record
Each data file must have a data description record, the line following the Initialization record in the ISAM parameter file. The first parameter is a file number we assign to each file, followed by the file name, the record length, the extension size, the numeric representation of the file mode, and the number of associated index files. You should be able to match the values in isam.p with the values in the CreateDataFile() calls in lowlevel.c, with the exception of the last one.
In our example we have prepared the data description record for use with the r-tree Report Generator by assigning symbolic names for the first and last fields in the data record. If you set up your FairCom DB system for use with r-tree, you need two names here, even if you are not going to use r-tree for the time being. The symbolic names allow us to use this same sample program in the r-tree Reference Guide.
Index Description Record
If there is one or more indexes associated with a file there must be an index description record for each. The first parameter is the file number we assign to the index, followed by the index file name, key length, key type, duplicate file value, number of additional index members, file extension size, and the numeric representation of the file mode. You should be able to match these with the parameters used in CreateIndexFile in lowlevel.c. In addition, we have parameters for the null key flag and empty character (leave these as 0 and 32 respectively until you understand them fully), and the number of key segments. Itemidx is a symbolic name for r-tree, as discussed above.
Key Segment Description Record
Each key for an ISAM index must be composed of elements drawn from the data record. You cannot have an arbitrary value from an outside source as a part of the key. Even if this wasn’t a requirement of the FairCom DB product it would make good sense, because you cannot easily rebuild a corrupted index if the key contains information that doesn’t exist in the data record. In addition, keys can be created from multiple portions of the data record, and a number of translations can be performed. This is specified in the Key Segment Description record.
In our example, the key is a simple one of one segment. The first value is the offset of the segment in the data record. Starting at zero, the item field starts at byte 2 of the record (bytes 0 and 1 being the delete flag). The second value is the length of the segment, 25 in this case. The third value is the segment mode, which describes how the segment is to be translated. ISAM Functions describes the various segment modes. A value of 0 means no transformation, a value of 2 (as in our example) means that the lower case letters will be translated to upper case.
Error handling is essentially the same as before with the low-level sample, except that we look at isam_err instead of uerr_cod, and the variable isam_fil tells in which file the error occurred. This last is important, as ISAM functions may manage multiple files within a single call, and we need to know which file created the problem.
Adding the data to the application data files is very simple with the ISAM functions. After we have called the getfld() function to capture the data, we simply call AddRecord(). This takes care of all of the functions performed by transkey(), AddKey(), NewData(), WriteData() in the low-level function example.
Record locking is more automatic, as well. Before the call to AddRecord() we enable automatic record locking with the LockISAM(ctENABLE) call, and later we release the lock with the LockISAM(ctFREE) call.
GetRecord and DeleteRecord
Deleting a record and index entry is almost as simple. We use GetRecord() to determine if the key exists. This also reads the record so we have something to display. We then call DeleteRecord() to delete the key and record. Even if we had multiple indexes for this file we would do just those two calls, since DeleteRecord() deletes all keys associated with that record.
The key passed to GetRecord() must be a properly formatted key, just as in lowlevel.c. We use TransformKey() instead of our own function. TransformKey() takes the information found in the key buffer and reformats it according to the values found in the ISAM parameter file.
Closing the data and index files is very simple. A single call to CloseISAM() closes all files referenced in the ISAM parameter file. It also calls StopUser() automatically.