The best way to learn how to use FairCom DB is to examine programs that use it. We have created two series of sample applications to help you understand how to apply what we have shown you in this guide so far.
We start with a series of very simple applications that begins with a basic file maintenance program, and then builds until we have a more sophisticated program. We have tried to keep the non FairCom DB material to a minimum. We have briefly introduced these sample programs in the beginning of “Using Low-Level Functions” and “ISAM Functions (ISAM Database Technology, /doc/ctreeplus/30841.htm)”.
The programs in the second series are more complex, and illustrate many advanced features. Some of the non FairCom DB material is a bit more sophisticated as well. They will take more study on your part, but the understanding that you gain is well worth the effort. These programs are used in various places throughout this guide.
See the Sample Programs in the ISAM section of this documentation for ISAM versions of these programs.
Simple Applications
The sample applications are very simple ones to avoid obscuring the FairCom DB functions. They maintain a simple inventory file, with just one key field. We start with just the basics necessary to start and create a file and index, and gradually add on a variety of functions. This approach lets you study each of the concepts introduced without clutter from non-FairCom DB code, and without the confusion of advanced FairCom DB concepts.
These programs compile in single user, standard multi-user, or client/server mode, without any change to the code. If a function does not apply to a particular mode, such as Commit(), it is ignored. However, more sophisticated transaction functions available with the FairCom Server are not used. The programs that we provide are:
- lowlevel.c - Creates a data file and index, adds and deletes records using the low-level functions of FairCom DB.
- isam.c - Identical to lowlevel.c using ISAM functions instead of low-level functions. Shows how the ISAM functions simplify programs. Requires isam.p as a parameter file.
- isam1.c - Identical to isam.c except that it uses Incremental ISAM structures.
- isam2.c - Builds upon isam1.c. Lists the file to the screen. Introduces “sets”.
- isam3.c - Scans the file to find a record. Allows update or delete of the record.
All of these examples are built upon the same program structure, and use the same data, index, and (where appropriate) parameter files. FairCom recommends using ISAM level functionality over low-level. The low-level example is provided primarily to show the advantages inherent in the ISAM level. Unless you have a specific need to use low-level functionality, (i.e., to manipulate data and index entries independently), consider skipping the low-level example.
Simple File Maintenance
lowlevel.c, the first sample program, introduces FairCom DB low-level functions.
Throughout this series of sample programs, we use the following data record structure for our data file:
struct INVENTORY { /* data record format */
COUNT delete_flag; /* delete flag byte */
TEXT item[26]; /* Item ID - the key value */
TEXT descrip[51]; /* Item Description */
TEXT location[10]; /* Item Location */
double quantity; /* Quantity on hand */
double cost; /* Unit Cost */
TEXT padding[23]; /* unused padding */
} invent;
We will build just one index, using the item field.
We have allocated one field at the beginning of the record structure for the delete flag. It is best to set aside space for this in your structure. If you decide that you want to use a status value for each record, you could use this same variable for the status. Just remember to not use the value of 0xff as a status value, as that represents a deleted record to FairCom DB.
The program mainline is the same in all of the examples of this series:
main (argc,argv)
int argc;
pTEXT argv[];
{
void create(),initial(),database(),closeit();
if (argc == 1)
create(); /* create the database files */
else
initial(); /* initialize the system */
database(); /* perform database routines */
closeit(); /* close the files, and any other ending stuff*/
}
If there is any value passed on the command line, we will assume that you want to create the database. Otherwise, we assume that the database has already been created. You could have a more sophisticated startup than this, where you try to open the files first, and if that fails then trying to create them.
After the file system has been set up, we call database() to perform the operations, and when done we call closeit() to finish up.
|
In This Section |
Initialize the system
InitCTree
Before we can do any FairCom DB actions we must initialize the FairCom DB buffers with the InitCTree() function call. This allocates the memory for index buffers, (10 in our example), data and index file structures, (2 in our example), and establish the number of sectors available in each FairCom DB node, (4 in our example).
In single user systems, improve performance by increasing the number of index buffers, the first InitCTree() parameter. We typically suggest a maximum of 6 buffers per active index. The only reason that you might want to use a smaller number is if you cannot afford to allocate the space. In Standalone Multi-user systems the number of buffers should be set to 6 no matter how many indexes you are using, as local buffering will not be used.
For most situations, you should leave the number of sectors per node at 4, which allocates 512 bytes per node. It is important to be consistent with this parameter, as an index created with one value cannot be used if you use a smaller value in a subsequent call to InitCTree().
For additional information on index buffer and sector settings see “Performance Optimization”.
Create and Open Files
Once we have initialized FairCom DB, we can go on to either create or open the data files and indexes. When using low-level functions you must explicitly create/open each file separately. The create functions are almost identical to the open functions, except that the create functions have additional parameters that are stored in the header record of the data file or index. This is information such as the record or key length, whether the data file is to have fixed- or variable-length records, and so forth.
Two files are created in our example. The first file is the data file, with a fixed record length of 128 bytes. The xtdsiz parameter is set to 4096, which means that every time the file is extended in size it will be extended by 4096 bytes. This improves the efficiency of the system. Note that we have included a file mode of ctSHARED, to allow multiple users access to the data file. The second file is the index, with a key length of 25. We are not allowing duplicate keys.
Error Handling
If an error occurs in one of the FairCom DB functions, we call one of two error handling functions. terminate() is called if the error occurs at a time where we don’t want to continue until the error is corrected. func_error() is called when the situation is not bad enough for the program to be terminated.
uerr_cod
isam.c has a very basic error handler in func_error(). Based on the global error variable uerr_cod, we print a number of different error messages. If the error is not one that we have a specific message for, we just print the error number. You certainly can create a more sophisticated error handling.
terminate() prints an error message that we pass to it, and calls func_error(). The next function invoked is StopUser(). In single user and Standalone Multi-user situations, this function is ignored. When using the FairCom Server the application must call this function before exiting the program for any reason. It tells the FairCom Server that this application is finished with FairCom DB services, freeing server resources to be used by other applications.
Adding Data
Now that the files are open, we can add records. The function datadd() is used.
The first step is to initialize the data record buffer. The only thing required for FairCom DB is setting the delete flag to a value other than 0xff. It is risky to not initialize this variable with some safe value.
The function getfld() captures data from the screen. As supplied, there is no form of error checking. We leave this part of the program up to you.
translate key
After we have the data that we want to enter, we call transkey() to format the key the way we want it. This is a function created for this sample program. In this case, we are doing two things. First, we translate all of the alpha characters to upper case. For the purpose of our example, we have decided that we don’t want to distinguish between upper case and lower case characters in our keys. This keeps the collating sequence for the keys in a usable form. The second step of the key translation is most important. We pad the key to its full length with null characters.
Padding the key is an extremely important step. FairCom DB keys are NOT treated as standard null-terminated C strings. The full length of the key, as specified when the index was created, is important even if the actual value used is shorter. If you are using string values as keys you must pad them to their full length, or you may not be able to retrieve them later.
For example, let’s look at a situation where we have a key length of 10, and we add two key values. The first key value is
“ABCDEFGHIJ”, which is 10 characters long. After adding this key to the index we add another, “XYZ”, which is only 3 characters long. While adding the keys we use the same buffer variable to store the values. If we look at what is stored in the variable when “XYZ” is there, we see that the contents of the variable are “XYZýEFGHIJ”, where ý represents the null character that terminates the string. All 10 characters are added to the index as the key! Later, when we retrieve this record, we have a hard time finding an exact match to the key when we enter the value “XYZ”. FairCom DB looks for the rest of the information. By padding the values to their full length with some consistent character, such as a null or space, we will find that our programs work as expected.
GetKey
Now that we have a key to work with, we want to see if the key already exists in the index. We use GetKey() to look for an exact match. If the function returns a value, we have found a match, and we don’t want to try to add the key again. A zero means no match was found, and we check uerr_cod to see if there was an error or not.
NewData
The process of adding the key to the index and writing the record to the data file takes several steps. First, call NewData() to obtain a data record position to write the record. FairCom DB keeps a list of deleted records and reuses those records when you call NewData(). If there are no deleted records, NewData() automatically extends the file to gain a new record position.
WriteData
Once we have a record position, we write the data record to the file with WriteData(). If an error occurs, we return the data record position to the file with ReleaseData().
AddKey
With the record is in the data file, we add the key to the index with AddKey(). We do this after writing the data record for two reasons. First, AddKey() requires the data record position to store with the key value. Second, since most access to the file will be through the index, we want to be sure that the record exists before the key is written. In a multi-user environment we don’t want the key written and accessed by another user before the data record is written.
LockCtData
Any time after the call to NewData() that we leave this function, due to a failure of a function or the successful completion of the process, we call LockCtData(). When NewData() acquires a data record, it puts a lock on the record that must be released before other users can access it. On a single user system, LockCtData() is ignored.
Delete a key
The datdel() function deletes a key from the index and deletes the record from the data file. Once again we use the transkey() function to translate our input key to the format that we want to use. GetKey() is used to locate the key in the index.
ReadData
If the key is found, we use ReadData() to read the record so that we can display it. You might decide that you want to ask the user if this is the correct record to display.
DeleteKey and ReleaseData
DeleteKey() deletes the key from the index. ReleaseData() returns the data record to the list of deleted records.
Close the system
When the application finishes, it must shut down the FairCom DB system and close files properly. Each open data file and index must be closed with CloseCtFile(). If a file has been created and/or modified during this run of the application, and it is NOT closed properly, the file will be considered damaged. Information stored in the header record about the status of the file is not always written to disk until the file is closed. If the file is not closed, and the information in the header is incorrect, the next time the file is opened you will receive an error indicating the file has been corrupted. Either throw the file away or rebuild it. See ctixmg.c for an example of how to use the incremental ISAM function RebuildIFile() to rebuild a file.
As noted in the discussion of terminate(), the application must call StopUser() before exiting. This tells the FairCom Server the application is finished, releasing resources for other users. When not using the FairCom Server, StopUser() is ignored.
Same Application with ISAM Functions
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 This Section |
ISAM Parameter File
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
Initialization Record
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
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 Data
AddRecord
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.
LockISAM
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.
Delete Record
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.
TransformKey
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.
Close the System
CloseISAM
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.
Using Incremental ISAM Structures
Incremental ISAM structures allow you to create, open, close, and rebuild individual ISAM files independent of an ISAM parameter file. The incremental ISAM structures contain the same information as the parameter file, but permit the information to be stored in your application instead of an external file, and permit direct control of the opening and closing of individual files instead of complete sets of files.
isam1.c is an example of how to use incremental ISAM structures. Other than its use of incremental ISAM structures, it is identical to isam.c.
|
In This Section |
Incremental ISAM structure
The incremental ISAM structure typedefs are used to create a series of related structures to describe a data file, its associated index files, and the key segments from the data file used to build each index. Details on these structures are in “ISAM Functions”. We briefly discuss them here in relation to isam1.c.
IFIL Structure
Each data file will have one IFIL structure. Here we show the structure for the inventory data file. The values shown match those found in the data description record in the ISAM parameter file isam.p. When using incremental ISAM structures the file extention .dat is added to the data file name automatically. Note that one of the values is a pointer to the IIDX structure containing information about the indexes.
IFIL inv_dat = {
"invent", /* data file name
(".dat" extension is default) */
0, /* data file number */
128, /* data record length */
4096, /* data extension size */
1, /* data file mode */
1, /* number of indexes */
4096, /* index extension size */
1, /* index file mode */
&inv_idx, /* pointer to index array */
"", /* r-tree info (not used here) */
"" /* r-tree info (not used here) */
};
IIDX Structure
The IIDX structure describes the indexes for the data file. As before, you should be able to relate the values here with the values of the index description record. The file extent .idx is added to the index file name by default when the non-extended create functions are used (i.e., CreateIndexFile() and CreateIFile()). Note the pointer to the ISEG structure, which contains information about the structure of the keys.
IIDX inv_idx = {
25, /* key length */
0, /* key type */
0, /* dup off */
0, /* null off */
32, /* empty char */
1, /* number of key segments */
&inv_seg, /* pointer to segment array */
"Itemidx", /* pointer to symbolic index name (r-tree) */
"invent" /* optional index name (if this field is *
* omitted, the default index name will be *
* used. The default is the name supplied *
* in the IFIL pfilnam with an extension *
* of ".idx".) */
};
ISEG Structure
Each key segment is described by an ISEG structure. If there are multiple segments then the ISEG structure must be an array. There must be an ISEG array element for each key segment as specified in the IIDX structure. It is easy to relate the key segment description record of isam.p to the following ISEG structure:
ISEG inv_seg = {
2,25,2
};
Initialize the system
InitISAM
When using incremental ISAM structures initializing the system is similar to the low-level functions. InitISAM() performs the same function as InitCTree() or the initialization record of the ISAM parameter file.
CreateIFile and OpenIFile
Each data file is created or initialized by CreateIFile() or OpenIFile(). The address of the IFIL structure for that data file is passed to the function. This call also opens all associated index files.
All other operations in isam1.c are identical to the ISAM parameter file example isam.c. The only differences are in the way you initialize the system and create/open the files. There are two other incremental ISAM functions, which we don’t use in these examples. CloseIFile() closes individual data files and their associated indexes, and RebuildIFile() rebuilds a corrupted data file and its indexes.
The regular CloseISAM() function closes all open ISAM files, whether they were opened with an ISAM parameter file or as an incremental structure.
File Searches and Sets
isam2.c takes the sample that we started with in isam1.c and adds functionality. The two features added are the ability to list the contents of a file, and Sets.
|
In This Section |
Listing a file
We have added the function datalist() to sequentially list the records in key order. The first step is to ask if the user wants to enter a string to define a Set. This is discussed in the next section of this chapter. For now let us assume that the user just presses the Enter/Return key, which makes the program call the doall() function.
FirstRecord
The process that we want to perform is to find the first key in the index, display the record that it represents, and find each successive key in turn. To start the process we use FirstRecord(). It finds the first key in the index specified. If passed the data file number as the parameter, it finds the record that is physically the first in the file. FirstRecord() reads the record associated with the key into the buffer specified.
NextRecord
After we display the record, we are ready to locate the next record in key sequence. We use NextRecord() for this, again passing the number of the index file. NextRecord() finds the next record in key order, in relation to the last record found. We continue in a loop until NextRecord() returns an error value of INOT_ERR (101), which signifies that we have reached the end of the file.
Sets
A Set is a group of records that have keys matching a certain target. For example, an index contains the following keys:
CASE DISKCASE DISKDRIVE DISKETTE KEY KEYBOARD KEYCAP
We could define a Set by the target DISK. This set would contain the values:
DISKCASE DISKDRIVE DISKETTE
In the function datalist() we ask the user for a string to define a Set. If the user enters nothing we list the entire file, as described above. If a string is entered we use this to define a Set and call the function doset(). This function is nearly identical to doall(). It finds the first key in the index, displays the record, then goes through the index sequentially. The difference is it starts with the first key beginning with the Set string and ends with the last key starting with the Set string.
FirstInSet
Instead of starting with FirstRecord(), we use FirstInSet(). It performs the same function, but FirstInSet() asks for a target key, and the number of characters to match. In our example, the input value is passed through TransformKey() to make it a perfectly formed key. The length parameter is the length of the input target key. For example, if we had the keys that we show above, we could enter the target key DISK, with a length of 4. FirstInSet() finds DISKCASE as the first key of the set.
NextInSet
To go on to the next key we use NextInSet() instead of NextRecord(). It performs the same function, but stops when the last key that matches the Set is found. For example, it tells us we reached the end of the file (INOT_ERR) after DISKETTE.
Do not pass the Set target to NextInSet(). This information is stored by FairCom DB. It also means that you can only process one Set at a time. Get around this by switching from one set to another with ChangeSet().
Scanning, Updating, Deleting
Continuing to build upon our sample program, we take isam2.c and add the ability to scan the index looking for a particular file, and to either update or delete it. The new program is isam3.c. We replace the datadel() function with update().
|
In This Section |
Start the scan
In the previous examples, if we wanted to delete a record we had to enter an exact match of the key. Sometimes it is desirable to just enter a target and search up or down from that point. In addition, you may not know exactly what keys are in the index, so you can enter something that is close and scan forward or backward until you find the one you want.
GetGTERecord
If we use GetRecord() as we did before, we can only find a key that exists in the index, as GetRecord() finds only exact matches. Instead, use GetGTERecord(). This finds a key that is equal to the target, but if there is no exact match, it finds the next key after the target. Use TransformKey() to format the key properly. A return of INOT_ERR (160) means the user entered a target that is past all of the keys in the index.
Once we find a starting point we display the data values GetGTERecord() read into the buffer. The user is given the option of updating, deleting, or scanning up or down through the index.
Scanning the file
NextRecord and PreviousRecord
As we saw when listing the file sequentially, NextRecord() can find the next record after the one previously found. We can continue to scan forward through the file with NextRecord(), or we can scan backwards through the file with PreviousRecord(). This function works identically to NextRecord() except that it goes the opposite direction through the index.
Update the record
Once we find the record to update, we can easily change the values and write the record back to the file. We changed the getfld() function so it displays the existing value before asking you for the new value. If you press the Enter/Return key, you get the same value as before.
ReWriteRecord
ReWriteRecord() rewrites the current ISAM record back to the disk. Pass it the number of the data file and a pointer to the buffer where the updated record exists.
In our example, it is possible to change the value of the “item” field, which is our key field. ReWriteRecord() notices the new record has a different value for that key field than the original record. It deletes the old key from the index and adds the new key automatically. This may not be the best practice in a real application, but it serves to illustrate how ReWriteRecord() works. If we have multiple indices based on different fields ReWriteRecord() makes the same change for all key values.
Delete a record
Once we find the record to delete by scanning to it we can easily delete it by using DeleteRecord() as before. Keep in mind that this deletes the Current ISAM Record.
Windows-Specific Samples
wtixmg - A Windows version of the ctixmg sample
Like ctixmg, wtixmg supports single-user transaction processing, multi-user locking, and uses the same file. In addition, wtixmg uses multiple instance support discussed in “Multiple Instance Support”. This program provides a good working example of the multi-instance functions, RegisterCtree(), SwitchCtree(), etc., to maintain multiple FairCom DB instances.
wtlxmg - A Windows version of the ctlxmg sample
wtlxmg allows the user to create multiple local and/or FairCom Server instances (if linked with the LOCLIB feature) of the application. To switch between the instances:
- Select the Exit button to exit the current instance.
- In the FairCom DB Instances window, select the SWITCH button to perform the actually change of instances.
In both wtixmg and wtlxmg , the inactive buttons indicate the particular feature is not presently active. For example, the Abort and SavePt buttons will not be active when linked with a Standalone Multi-user library.
wtmtap - Windows Multi-threaded Sample Application
wtmtap [a <action>] [g <aborts>] [m <transaction mode>]
[n <iterations>] [r <seed>] [s <server name>]
[t <threads>] [x <ctmaxparm>]
See the ctmtap utility description for details of the parameters given above. If no parameters are given, wtmtap will prompt for the necessary information.
Sample Programs
Before running the sample programs, be sure that the parameter files supplied with c‑tree (ctexam.p, ctvxam.p, isam.p) are in the same directory as the executable sample programs. Otherwise, the samples requiring a parameter file report error INOD_ERR (102, could not open parameter file).
If you disable r-tree support, by changing #define RTREE to #define NO_RTREE in ctoptn.h, remove the symbolic names at the end of each data and index line in the parameter files.
On systems that enforce double word alignment for long integers, such as Unix 386, add 2 to each of the key segment offsets in the ctexam.p parameter file.
The sample programs use the same command line format as described in “FairCom DB Utility Programs”.
ctcnfg - System Configuration Example
This sample demonstrates the SystemConfiguration() function. Upon running the utility, you will see the main menu with the following choices:
SYSCFG: SystemConfiguration example
1. Dynamic system resources
2. Static system resources
3. FairCom Server only resources
4. Client and Server side resources
5. Pre-initialization resources
Enter the number of your choice to see a display of the current configuration. For example, if you type the number 2 and then press the Enter key, you will see a display similar to the following:
Static system resources
-----------------------
Maximum c-tree Plus FCBs system wide : 14
Maximum indexes per data file : 32
Maximum key segments per index : 12
Press the Enter key to return to the main menu.
To exit from the utility, type q at the main menu and then press the Enter key.
ctcompare - Database Comparison Tool
The Database Comparison utility, ctcompare is available in V11 and later. It allows you to compare two files (or two versions of the same file) or two tables. Options are provided that allow you to merge the differences into one of the files without affecting the other.
Usage:
ctcompare -s source -t target -n source name
[-u source uid][-U target uid]
[-p source pwd][-P target pwd][-N target name][-I name][-d]
[-b source dir][-B target dir]
Where:
- -bB - base directory for session dictionary (only used with -d)
- -d - interpret name as a database name (default is table name)
- -s - source server name
- -t - target server name
- -u - source user name (default: admin)
- -U - target user name (default: admin)
- -p - source password
- -P - target password
- -n - source file name
- -N - target file name (default is the source name)
- -x - printf hex offsets
- -I - Use r-tree symbolic index 'name' as record identifier
The following parameters are used to apply differences from the source to the target. The source will remain unchanged. When determining the differences between the two files, records are identified based on their unique keys.
- -A1 - Apply all differences (deletes extra records from target)
- -A2 - Apply only missing records
- -A3 - Apply missing records and updates
Example 1
Compare two files named custmast.dat on different servers, log differences:
ctcompare -s FAIRCOMS@localhost -t FAIRCOMS@otherhost -n custmast.dat -u admin -p ADMIN
Example 2
Compare two versions of the same file, and merge all differences to custmast2:
ctcompare -s FAIRCOMS -t FAIRCOMS -n .\dir1\custmast.dat -N .\dir2\custmast2.dat -A1
Example 3
Compare all tables in two SQL/CTDB databases:
ctcompare -s FAIRCOMS -t FAIRCOMS@otherhost -n db1 -N db2 -d -u admin -p ADMIN
ctixmg - Incremental ISAM / Resource sample
Operational Model:
- Client
Usage
ctixmg [<UserID> <UserPassWord> <ServerName>]
Description
ctixmg supports variable-length data records using Incremental ISAM structures to specify the file parameters for creation and optionally supports resources. If RESOURCES are defined in ctoptn.h prior to opening the files the proper resource open, OpenFileWithResource(), and close, CloseRFile(), functions are used. If RESOURCES are not defined, then OpenIFileXtd() and CloseIFile() are used to open and close the files. The optional UserId, UserPassWord and ServerName parameters only apply to FairCom Server based systems.
ctixmg automatically creates the files it needs if they do not exist. It rebuilds the files if they appear corrupt. In transaction processing environments, automatic recovery replaces the need for rebuilding the files.
ctixmg runs in all FairCom DB console-based models. ctixmg permits transaction processing control including Begin(), and Commit(). In a non-transaction processing system, Begin() and Commit() are replaced by LockISAM() to control ISAM level locking.
ctlxmg - LOCLIB sample program
Usage
ctlxmg <UserId> <UserPassword> [<ServerName>]
Arguments
- UserId - If connecting to a Server, provide a valid User ID, or leave blank to use the default User ID of “guest”. To connect to a local library, leave blank.
- UserPassword - If UserID has been specified, provide the proper password or leave blank.
- ServerName (Optional) - Specify the Server name. Be sure to include the Server’s host machine name. For example, to connect to the c-tree HP9000 Server with a host file entry of “HP”, use the following name: “FAIRCOMS@HP”. This name assumes the SERVER_NAME keyword has not been specified in the ctsrvr.cfg file, and that the FairCom Server is using the default name. When connecting to a local library, provide a unique arbitrary name for this local library instance.
Description
ctlxmg, based on ctixmg, uses the FairCom DB instance functions to maintain multiple FairCom DB instances. ctlxmg provides a good example of the ‘multiple Server per client support’ and the ‘local library support’. If no parameters are given, ctlxmg prompts the user for the following information:
Important Points
- The use of FairCom DB instance functions: RegisterCtree(), SwitchCtree(), NextCtree(), UnRegisterCtree(), and WhichCtree().
- The userprf argument to the FairCom DB function InitISAMXtd() must include the USERPRF_LOCLIB option for a local connection.
ctmtap - Multi-threaded API sample and performance tester
Usage
ctmtap [a <action>] [g <aborts>] [m <transaction mode>]
[n <iterations>] [r <seed>] [s <server name>]
[t <threads>] [x <ctmaxparm>]
Arguments
The additional parameters below are supported by ctmtap:
- g <aborts>
Approximate quantity of transactions to be aborted; for example, a value of 2 implies that about 20% of the transactions will be aborted; defaults to 1, 10% aborted transactions.
- s <server name>
Specifies the name of FairCom Server and defaults to “FAIRCOMS”.
- t <#>
Number of threads; defaults to 1
- x <ctmaxparm>
Specifies the maximum number of open files and defaults to value of MAXFIL.
Description
This sample program demonstrates FairCom’s Multi-thread API. The main routine runs a trial of database operations; however, this application spawns one or more threads, each of which runs a trial. ctmtap divides the screen into columns, with the output from each thread placed in its own column. If you specify more than 8 threads, only the output from the first eight threads will be shown. This limit is for on-screen clarity and can be changed by editing the #define for MAX_COLS in ctmtap.c. Regardless of the value of MAX_COLS, all threads will be running, but output will be shown for only MAX_COLS threads.
ctmtap is designed for the FairCom Server and FairCom’s multi-threaded stand-alone model. Upon execution, this program will prompt you for the desired operation.
See also
ctmtex - Multi-threaded Incremental ISAM / Resource sample
Multi-threaded sample program based on ctixmg.c.
ctstap - Single-Threaded Version of Multi-Threaded Test
In V11 and later, a new test program has been added: ctstap, which is a single-threaded version of ctmtap. This test program is useful for checking that concurrent add, delete, and update operations on a file by multiple FPUTFGET processes work properly.
Description
ctstap is FairCom's Singlethreaded API sample program. This sample program is an IFIL version of ctmark. As in ctmark, the main routine runs a trial of database operations.
Supported options:
- a<action>, where <action> is one of the following values:
- A - add data
- D - delete data retrieved in random order
- G - retrieve data in random order (this is the default action)
- S - call STPUSR() and terminate immediately
- T - run cttestfunc() routine
- U - update data retrieved in random order
- e<cipher> - Encrypt the files using the specified cipher, where <cipher> is the numeric value of one of the cipher types listed in ctport.h. For example, for AES32 encryption specify e62. Use with the fc option.
- fc - Create the data and index files. If not specified, open existing files.
- g<transaction aborts> - Approximate number of transactions to be aborted. For example, a value of 2 implies that about 20% of the transactions will be aborted. Defaults to 1 (10% aborted transactions).
- h<filename> - Use the specified file name (without extension).
- ic - Create files that use record compression. Use with the fc option.
- ih - Create files that use 8-byte offsets. Use with the fc option.
- in - Create files without extended header. Use with the fc option.
- is - Create segmented files. Use with the fc option.
- iv - Create variable-length record files. Use with the fc option.
- L - Use a local connection, otherwise use a client connection. This option is supported only in the LOCLIB model.
- mc - Create files with offset compression in index nodes. Use with the fc option.
- md<data cache_size in MB> - Set the data cache size in megabytes.
- mi<index cache size in MB> - Set the index cache size in megabytes.
- mm - Create files with optimized transaction marks. Use with the fc option.
- mN - Create files with no transaction processing. Use with the fc option.
- mt - Create files with transaction processing without logging. Use with the fc option.
- mT - Create files with transaction processing with logging. Use with the fc option.
- mta - Create files with auto switch to ctPREIMG mode. Use with the fc option.
- mTa - Create files with auto switch to ctTRNLOG mode. Use with the fc option.
- mxa - Create files with variable length index node format. Use with the fc option.
- n<number of iterations> - Number of iterations of the specified action per trial. Defaults to 100 if not specified.
- od<data cache size in bytes> - Set the data cache size in bytes.
- oi<index cache size in bytes> - Set the index cache size in bytes.
- op<page size in bytes> - Set the page size in bytes.
- ox - Open the files in exclusive mode.
- p<password> - Use the specified user password.
- q - Quiet mode - don't print progress messages.
- r<seed> - Random number seed (0-65535); defaults to 1
- s<server name> - Name of FairComDB Server. Defaults to FAIRCOMS.
- u<user name> - Use the specified user name.
ctstress - Perform Record Operations on Files
This sample program performs various database operations for use as a test program. The source is in the ..\sdk\Xtras\ctree.samples\special\utils folder.
ctsxmg - Incremental ISAM / Record Schema example
Usage
ctsxmg [<UserID> <UserPassWord> <ServerName>]
Description
ctsxmg is based directly on ctixmg except that a record definition is stored in the data file via PUTDODA(). The key segments use segment modes based on Record Schema field numbers, which reference field definitions, instead of absolute byte offsets or relative field numbers. See “Key Segment Modes (Key Segment Modes, /doc/ctreeplus/30863.htm)” for more information. The optional UserId, UserPassWord and ServerName parameters only apply to FairCom Server type systems.
cttpca - TPC A Test
Operational Model:
- Client
This is a C code sample program implementing the TPC (Transaction Processing Council) A test using the FairCom DB ISAM, FairCom DB API (CTDB), and ODBC APIs. You can execute the same test set using any combination of these APIs.
When included with FairCom ISAM, this utility supports the FairCom DB BTRV interface as a fourth API.
This utility is perfect for benchmarking across computer systems, or for comparing the performance of these FairCom DB APIs. For full usage information, simply execute the utility without any parameters.
See ct_tpc for a C++ code version.
Note: This program is considered legacy, in favor of the more advanced ct_tpc version.
ct_tpc - TPC A Test
Operational Model:
- Client
This is a C++ code sample program implementing the TPC (Transaction Processing Council) A test using the FairCom DB ISAM, FairCom DB API (CTDB), and ODBC APIs. You can execute the same test set using any combination of these three APIs. For full usage information, simply execute the utility without any parameters.
When included with FairCom ISAM, this utility supports the FairCom DB BTRV interface as a fourth API.
This utility is perfect for benchmarking across computer systems, or for comparing the performance of these FairCom DB APIs.
See cttpca for a C code version.
lowlevel, isam, isam1, isam2, isam3
This chapter covers the introductory sample programs lowlevel, isam, isam1, isam2 AND isam3. These programs use the existence of a command line argument, which may be anything, to indicate that the associated files need to be created.
ioperf
This sample demonstrates the IOPERFORMANCEX() function.
selomt
This sample demonstrates a simple use for conditional index support, also referred to as select/omit.
trnhis
This sample demonstrates the transaction history function as an online utility. The user enters a key target and data records matching this target are returned.
CGI
This directory contains a sample program and documentation for demonstrating the use of FairCom DB with the Common Gateway Interface (CGI). The CGI standard provides a mechanism for interfacing to external executables residing on remote HTTP server machines. Data can be passed both directions through system environment variables or standard in (stdin) and standard out (stdout). The FairCom DB CGI sample makes it easy to see how FairCom DB and/or the FairCom Server can be utilized within WWW application development by showing a simple customer name and address database.
Java
This directory contains UNSUPPORTED sample code and documentation for demonstrating the use of FairCom DB with the Java. Please proceed to the SAMPLES/JAVA/JNI or SAMPLES/JAVA/RMI directory and see the readme.txt in that directory. FairCom provides this code for example purposes only.