LastInRange
Read the last data record in a range
Short Name
LSTRNG()
Type
ISAM function
Declaration
COUNT LastInRange(FILNO keyno, pVOID recptr) Description
In V12 the file number typedef was formally changed from COUNT, a two-byte value to FILNO, a four-byte value. Refer to this link for compatibility details. Four Byte File Numbering
Read the last data record in a range established by a call to AllocateRange(). If successful, the record becomes the current ISAM record for the associated data file. A successful LasttInRange() defines a current key value set, and subsequent calls to NextInRange() or PreviousInRange() will read the other records in the range.
If the data file has variable-length records, only the fixed-length portion of the record is actually read. You can use ReReadVRecord() to retrieve the whole record, including the variable-length portion. You can use LastInVRange() to read the whole variable-length record with one function call.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | CTDBRET_OK | Successful operation. |
| 101 | INOT_ERR |
Could not satisfy and ISAM search request for index isam_fil. This error frequently indicates "End of File" reached, or "Record not Found." The following items are the probable causes of the INOT_ERR (101).
|
See c-tree Error Codes for a complete listing of valid c-tree error values.
See also
AllocateRange(), EstimateRange(), FirstInRange(), FirstInVRange(), FreeRange(), LastInVRange(), NextInRange(), NextInVRange(), PreviousInRange(), PreviousInVRange()
LastInSet
Read the last data record in the set defined by a target.
Short Name
LSTSET()
Type
ISAM function
Declaration
COUNT LastInSet(FILNO keyno, pVOID target, pVOID recptr, COUNT siglen)Description
In V12 the file number typedef was formally changed from COUNT, a two-byte value to FILNO, a four-byte value. Refer to this link for compatibility details. Four Byte File Numbering
LastInSet() reads the last data record in the set of data records whose keys match the target key in the first siglen bytes. If successful, this record becomes the current ISAM record for the associated data file. A successful LastInSet() defines a current key value set, and subsequent calls to NextInSet() and PreviousInSet() will read the other records in the set (i.e., those records whose keys also match the last siglen bytes of target). If an error occurs or no key value matches the target, the current ISAM record is not updated, and no key value set is defined.
If the data file has variable-length records, only the fixed-length portion, defined by dreclen in the original call to CreateIFile(), is actually read into the buffer pointed to by recptr. If you wish to read the entire variable-length record into the same or a different buffer, issue a call to ReReadVRecord() after the call to LastInSet(). Note that ReReadVRecord() requires the size of the buffer area so that it can check if sufficient space is available.
The target buffer must be initialized to the full length of the key to avoid memory corruption when the target is transformed to match the key.
LastInSet() can be used to perform an equality search for duplicate keys. Set target to the key value of interest, and set siglen to the key length less the 4 bytes of the suffix.
Notice that you do not directly identify the data file number involved. The ISAM parameter file described in ISAM Functions (ISAM Database Technology, /doc/ctreeplus/30841.htm) of the c-tree Programmer’s Reference Guide contains the correspondence between the index file number and the associated data file.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful retrieval of current ISAM record. |
| 33 | DNUL_ERR | recptr is NULL. No data file read performed. |
| 42 | DLOK_ERR | Could not get lock on data record. No data file read performed. |
| 101 | INOT_ERR | No active entries. |
| 119 | SKTY_ERR | keyno must reference a non-numeric key type. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO keyfil;
TEXT target[24], recbuf[320];
printf("\nEnter set value:");
scanf("%23s", target);
LastInSet(keyfil, TransformKey(keyfil,target), recbuf,
strlen(target));
while (isam_err == NO_ERROR) {
process_data();
PreviousInSet(keyfil, recbuf);
}Limitations
No check is made to determine if recptr points to a region sufficiently large to accept a data record. If the area is too small, either code or data will be clobbered.
See also
NextInSet(), PreviousInSet(), FirstInSet(), PositionSet(), ChangeSet(), CreateIFile(),
ReReadVRecord(), TransformKey()
LastInVRange
Read the last data record in a range
Short Name
LSTVRNG()
Type
ISAM function
Declaration
COUNT LastInRange(FILNO keyno, pVOID recptr, pVRLEN plen) Description
In V12 the file number typedef was formally changed from COUNT, a two-byte value to FILNO, a four-byte value. Refer to this link for compatibility details. Four Byte File Numbering
Read the last data record in a range established by a call to AllocateRange(). If successful, the record becomes the current ISAM record for the associated data file. A successful LasttInVRange() defines a current key value set, and subsequent calls to NextInVRange() or PreviousInVRange() will read the other records in the range.
plen acts as both an input and output parameter:
- On input, plen contains the length of the output buffer.
- On output, the contents of plen is the actual data-record length. If the length of the output buffer is less than the actual record length, a partial read is performed. If an error occurs, plen is unspecified.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | CTDBRET_OK | Successful operation. |
| 101 | INOT_ERR |
Could not satisfy and ISAM search request for index isam_fil. This error frequently indicates "End of File" reached, or "Record not Found." The following items are the probable causes of the INOT_ERR (101).
|
See c-tree Error Codes for a complete listing of valid c-tree error values.
See also
AllocateRange(), EstimateRange(), FirstInRange(), FirstInVRange(), FreeRange(), LastInRange(), NextInRange(), NextInVRange(), PreviousInRange(), PreviousInVRange()
LastInVSet
Read the last variable-length data record in the set defined by target.
Short Name
LSTVSET()
Type
ISAM function
Declaration
COUNT LastInVSet(FILNO filno, pVOID target, pVOID recptr,
COUNT signlen, pVRLEN plen)Description
In V12 the file number typedef was formally changed from COUNT, a two-byte value to FILNO, a four-byte value. Refer to this link for compatibility details. Four Byte File Numbering
LastInVSet() is identical to it’s fixed-length counterpart, LastInSet(), except that it reads the last variable-length data record in the set defined by target and siglen. If successful, this record becomes the current ISAM record for the associated data file.
plen acts as both an input and output parameter:
- On input, plen contains the length of the output buffer.
- On output, the contents of plen is the actual data-record length. If the length of the output buffer is less than the actual record length, a partial read is performed. If an error occurs, plen is unspecified.
Read the function description for LastInSet() for additional important information.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful retrieval of current ISAM record. |
| 633 | NPLN_ERR | plen is NULL. |
| 634 | NLEN_ERR | plen is negative on input. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
See also
LastInSet(), NextInVSet(), PreviousInVSet(), TransformKey()
LastKey
Find the last entry in an index file.
Short Name
LSTKEY()
Type
Low-Level index file function
Declaration
LONG LastKey(FILNO keyno, pVOID idxval) Description
In V12 the file number typedef was formally changed from COUNT, a two-byte value to FILNO, a four-byte value. Refer to this link for compatibility details. Four Byte File Numbering
LastKey() searches index file keyno for the last entry in the index. If successful, it copies the last index entry into the space pointed to by idxval.
Return
LastKey() returns the data record position associated with the last entry in the index file. If the index is empty or an error is detected, LastKey() returns zero. If LastKey() returns zero, check uerr_cod to see if an error occurred: if uerr_cod is also zero, then the index is empty; otherwise, an error condition was detected. See c-tree Error Codes in the c-tree Programmer’s Reference Guide for a complete listing of valid c-tree error values.
Example
TEXT idxval[10];
FILNO keyno;
if (LastKey(keyno,idxval))
printf("\nLast index entry = %.10s", idxval);
else {
printf("\nEither index is empty or an error occurred.");
if (uerr_cod)
printf("\Error = %d",uerr_cod);
else
printf("\Index is empty.);
}Limitations
No check is made to determine if idxval points to a region sufficiently large to accept a key value from the index file. If the area is too small, either code or data will be clobbered. Use GetCtFileInfo() to determine the key length.
The key value returned by this function will be a properly formatted key value (i.e., HIGH_LOW order, forced to upper case, etc.). The main issue is if binary key values will be displayed on a LOW_HIGH machine, it will be necessary to reverse any numeric segments. Key Segment Modes (Key Segment Modes, /doc/ctreeplus/30863.htm) in the c-tree Programmer’s Reference Guide contains suggestions for manipulating the key value.
The recbyt parameter in this function is a 4-byte value capable of addressing at most 4 gigabytes. If your application supports HUGE files (greater than 4 gigabytes), you must use the ctSETHGH() and ctGETHGH() functions to set or get the high-order 4 bytes of the file offset. See also Record Offsets Under Huge File Support.
See also
GetCtFileInfo(), FirstKey(), NextKey()
LastRecord
Read the last data record.
Short Name
LSTREC()
Type
ISAM function
Declaration
COUNT LastRecord(FILNO filno, pVOID recptr)Description
In V12 the file number typedef was formally changed from COUNT, a two-byte value to FILNO, a four-byte value. Refer to this link for compatibility details. Four Byte File Numbering
LastRecord() retrieves the last data record found. If filno designates an index file, LastRecord() reads the last data record based on the key sequential order of entries in index file number filno. If filno designates a data file, LastRecord() reads the last active data record, in physical sequential order. If successful, the last record becomes the current ISAM record for the associated data file. If an error occurs or there are no entries, the current ISAM record is not updated.
If LastRecord() is called with an index number, the data file number involved is not directly described. The ISAM parameters described in ISAM Functions (ISAM Database Technology, /doc/ctreeplus/30841.htm) of the c-tree Programmer’s Reference Guide contain the correspondence between the index number and the associated data file.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful retrieval of current ISAM record. |
| 33 | DNUL_ERR | recptr is NULL. No data file read performed. |
| 42 | DLOK_ERR | Could not get lock on data record. No data file read performed. |
| 48 | FMOD_ERR | LastRecord() called with a data file number that is: a variable-length data file; a member of a superfile; has RESOURCES enabled. |
| 101 | INOT_ERR | No active entries. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO keyfil,datfil;
TEXT recbuf[320];
if (LastRecord(keyfil,recbuf))
printf("\nError %d retrieving last record.", isam_err);
else if (ReReadVRecord(datfil,recbuf,320))
printf("\nError %d retrieving variable portion.", isam_err);
else
printf("\nSuccessful LastRecord.");Limitations
No check is made to determine if recptr points to a region sufficiently large to accept a data record. If the area is too small, either code or data will be clobbered.
filno cannot be a data file number if any of the following are true:
- The data file is set up for variable-length records.
- The data file is a member of a Superfile.
- The data file has Resources enabled (the default state).
In any of the above cases, LastRecord() returns FMOD_ERR (48).
If filno is a key number whose associated data file has variable-length records, only the fixed-length portion, defined by dreclen in the original call to CreateIFile(), is actually read into the buffer pointed to by recptr. If you wish to read the entire variable-length record into the same or a different buffer, issue a call to ReReadVRecord() after the call to LastRecord(). Note that ReReadVRecord() requires the size of the buffer area so that it can check if sufficient space is available.
See also
NextRecord(), PreviousRecord(), FirstRecord(), CreateIFile(), ReReadVRecord()
LastVRecord
Read the last variable-length data record.
Short Name
LSTVREC()
Type
ISAM function
Declaration
COUNT LastVRecord(FILNO filno, pVOID recptr, pVRLEN plen)Description
In V12 the file number typedef was formally changed from COUNT, a two-byte value to FILNO, a four-byte value. Refer to this link for compatibility details. Four Byte File Numbering
LastVRecord() is identical to it’s fixed-length counterpart, LastRecord(), except that it reads the last variable-length data record in the data file. If successful, this record becomes the current ISAM record for the associated data file.
plen acts as both an input and output parameter:
- On input, plen contains the length of the output buffer.
- On output, the contents of plen is the actual data-record length. If the length of the output buffer is less than the actual record length, a partial read is performed. If an error occurs, plen is unspecified.
Read the function description for LastRecord() for additional important information.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful retrieval of current ISAM record. |
| 633 | NPLN_ERR | plen is NULL. |
| 634 | NLEN_ERR | plen is negative on input. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
See also
LastRecord(), NextVRecord(), PreviousVRecord(), TransformKey()
LoadFilter
Called when FairCom DB loads a filter callback DLL. This function initializes resources that are used by the filter callback DLL.
Declaration
NINT LoadFilter(pTEXT libname, ppVOID plibhandle);Where:
- libname is the filter callback DLL name that was passed to SetDataFilter().
- plibhandle is a pointer to an application-defined library handle.
Description
This function is defined in the ctuserx.c module used to build a filter callback function.
LoadFilter() can allocate memory for use by the filter callback function and can return its address in this parameter.
See also
ctfiltercbAddFilter(), EvaluateFilter(), ctfiltercbRemoveFilter(), UnloadFilter(), SetDataFilter()
LoadKey
Add key value to index file in presorted order.
Short Name
LOADKEY()
Type
Low-Level index file function
Declaration
COUNT LoadKey(FILNO keyno, pVOID target, LONG recbyt, COUNT typadd)Description
In V12 the file number typedef was formally changed from COUNT, a two-byte value to FILNO, a four-byte value. Refer to this link for compatibility details. Four Byte File Numbering
LoadKey() inserts the key value pointed to by target and the associated data record position recbyt into index file number keyno. Repeated calls to LoadKey() provide an exceptionally fast method to add key values which have already been sorted. The sorted keys must be added to an empty index or all of the sorted keys must be greater than the existing entries.
Calls to LoadKey() should not be intermixed for different indexes.
typadd signals the beginning, middle, and end of the calls to LoadKey() as shown below:
| typadd Value | Symbolic Constant | Sequence |
|---|---|---|
| 0 | FRSADD | The first call to LoadKey() for a given index must have typadd set to zero. |
| 1 | NXTADD | Subsequent calls to LoadKey() must have typadd set to one. |
| 2 | BLDADD | After all the key values have been added, one additional call is made to LoadKey() with typadd set to two. This last call causes LoadKey() to complete the b-tree structure for the index. target and recbyt should be NULL. |
LoadKey() is used by the RebuildIFile() to quickly build the indexes associated with a data file.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful key value insertion. |
| 48 | FMOD_ERR | LoadKey() called for a data file instead of index file. |
| 58 | KLOD_ERR | LoadKey() called for index without initial FRSADD() call, or an attempt to mix calls for different indexes. |
| 59 | KLOR_ERR | Key value is out of order and has not been added to index: target is less than previous entry or not greater than existing key values. Identical duplicate keys must be presented in record position order. It is permissible to continue calling LoadKey() after a KLOR_ERR. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
TEXT target[11];
LONG recbyt,trials;
FILNO name_key;
COUNT mode;
FILE *fp;
trials = 0L;
mode = FRSADD;
while (fscanf(fp,"%s %ld",target,&recbyt) == 2) {
if (LoadKey(name_key,target,recbyt,mode))
break;
if (trials++)
mode = NXTADD;
}
if (uerr_cod || LoadKey(name_key,NULL,0L,BLDADD))
printf("\nerror during LoadKey (%d) on trial #%ld", uerr_cod,trials);Limitations
LoadKey() does not pad key values. Therefore, if you pass a key value which is not completely specified to its full length, LoadKey() will effectively pad the value with whatever “garbage” follows the key value in memory.
Key values added to an index which supports duplicate keys (keydup = 1 in CreateIndexFile() or CreateIndexMember()) have their last 4 bytes overwritten by the associated data record position. In this way, identical key values become distinguishable.
The recbyt parameter in this function is a 4-byte value capable of addressing at most 4 gigabytes. If your application supports HUGE files (greater than 4 gigabytes), you must use the ctSETHGH() and ctGETHGH() functions to set or get the high-order 4 bytes of the file offset. See Record Offsets Under Huge File Support.
See also
AddKey(), CreateIndexFile(), CreateIndexMember(), ctSETHGH(), ctGETHGH()
LockCtData
Lock / unlock data records or tables.
Short Name
LOKREC()
Type
Low-Level data file function
Declaration
COUNT LockCtData(FILNO datno, COUNT lokmod, LONG recbyt)Description
LockCtData() provides Low-Level lock and unlock control over fixed- and variable-length data records. LockCtData() can also be used with ISAM files to relax the constraints of the “two-phase” protocol described in Multi-User Concepts of the c-tree Programmer’s Reference Guide. Because c-tree is based on write locks, a locked record can be read by other processes as long as they do not attempt their own write lock on the record.
lokmod specifies an action based on the following values:
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | ctFREE | An unlock operation. |
| 2 | ctENABLE | A write lock operation. Only one process may obtain a write lock on a record. |
| 3 | ctENABLE_BLK | As ctENABLE, but a process unable to get a lock sleeps until the lock is available instead of returning DLOK_ERR. However, if a dead lock is detected, DEAD_ERR is returned. |
| 4 | ctREADREC | A read lock operation. Read locks may be acquired by any number of users on the same data record at the same time. A read lock ensures that no other user can acquire a write lock on the record. |
| 11 | ctREADREC_BLK | Same as ctREADREC, but a process unable to get a read lock is “put to sleep” until the lock is available. |
| 18 | ctFREE_FILE | Frees all locks held on file datno. Set recbyt to 0L for this lokmod. See notes below. |
| 20 | ctFREE_ISAM | Frees all ISAM level locks on file datno. |
| 21 | ctCHKLOK | Checks the lock status of recbyt for datno. |
| 512 | ctLK_RECR | Enable recursive locking. |
| 22 | ctFREE_WRTLOKS | Unlock write locks for a user for a specified data file. |
| 23 | ctLOCK_FILE | Table lock request. See Table Lock Mode for LOCKREC. |
| 24 | ctUNLOCK_FILE | Table unlock request. See Table Lock Mode for LOCKREC. |
| 25 | ctFREE_REDLOKS | Unlock read locks for a user for a specified data file. |
| 26 | ctCHK_ANYLOK | Check if the table has any user lock . |
| 27 | ctCHKLOK_OTHER | Check for lock by other connection/datno |
| 28 | ctENABLE_BLKRQS | Make a non-blocking write lock request on the specified record. If acquired, the force blocking lock option is set on that lock (making other connections block when requesting the lock even if they are non-blocking lock requests). |
Note: Many systems do not support read locks. If read locks are not supported, c-tree returns no error condition (i.e., the read lock is not attempted, but no error is reported). The FairCom Server supports both read and write locks.
recbyt specifies the beginning byte offset for the record lock/unlock operation. c-tree automatically provides the data file record length for the number of bytes to be locked. In the case of a variable-length file, c-tree only applies the lock to the minimum, fixed-length portion of the record. In any event, c-tree always asks for at least a 1-byte lock.
Return
In single-user applications, LockCtData() always returns successfully. In other modes, check uerr_cod for the values in the following table.
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful lock/unlock operation. Check sysiocod. |
| 41 | UDLK_ERR | Could not unlock data record. Check sysiocod. |
| 42 | DLOK_ERR | Record is already locked. Check sysiocod. |
| 48 | FMOD_ERR | LockCtData() called for an index file. |
| 86 | DEAD_ERR | Waiting for a write lock would cause a dead lock. |
| 160 | ITIM_ERR | Multi-user interference: key value changed between index search and subsequent data record read. |
A LockCtData() call attempting to unlock a record that is part of transaction returns NO_ERROR (0), but sets sysiocod to UDLK-TRN (-3), indicating the lock will be held until the end of the transaction.
If LockCtData(datno,ctCHKLOK,recbyt) returns NO_ERROR then sysiocod holds the lock status. If sysiocod and uerr_cod are zero, then no lock is held by the calling user. If sysiocod is non-zero and uerr_cod is zero, interpret sysiocod as follows:
- The low-order byte contains the type of lock: ctENABLE (2) for a write lock, or ctREADREC (4) for a read lock.
- The high-order byte is composed of one or more of the following attributes bits (left shifted 8 bits):
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 1 | ctISAMLOCK | ISAM lock. |
| 4 | ctTRANLOCK | Lock obtained or touched in transaction. |
| 8 | ctTRANOUT | Lock obtained outside of transaction. |
The higher order byte may contain other attribute bits that may be found in ctport.h where ctISAMLOCK is defined.
For an example of ctCHKLOK, a call of the form LockCtData(datno, ctCHKLOK, recbyt) might return the following values:
| Value | Symbolic Constant | sysicod | Explanation |
|---|---|---|---|
| 0 | NO_ERROR | 0x0502 | ISAM write lock at recbyt obtained inside transaction. |
| 0 | NO_ERROR | 0x0000 | No lock held at recbyt. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
LONG pntr;
FILNO datno;
TEXT recbuf[147];
if ((pntr = NewData(datno)) == 0L ||
fill_buffer(recbuf) != NO_ERROR ||
WriteData(datno,pntr,recbuf) ||
LockCtData(datno,ctFREE,pntr))
printf("\nCould not write new record (%d)",uerr_cod);
/* NewData always acquires a lock on a new record */Limitations
The recbyt parameter in this function is a 4-byte value capable of addressing at most 4 gigabytes. If your application supports HUGE files (greater than 4 gigabytes), you must use the ctSETHGH() and ctGETHGH() functions to set or get the high-order 4 bytes of the file offset. See also Record Offsets Under Huge File Support.
Locks on a specified record offset
ctCHKLOK_OTHER can be used to check if a lock is held on the specified offset of a data file by either another connection or by the same connection but with a different file number. The definition of "different file number" depends on the MULTIOPN mode that is in effect on the data file whose file number is specified:
- If using MULTIOPN_NODIFUSR or MULTIOPN_DIFUSR, then a lock that was acquired on the record offset by the calling connection using a different file number (known as a co-file) is treated as though the lock was acquired by another connection.
- If using MULTIOPN_SAMUSR_1 or MULTIOPN_SAMUSR_M, then a co-file lock is treated as though the lock was acquired by the calling connection.
To use this feature, call LOKREC() with the mode ctCHKLOK_OTHER. As with the ctCHKLOK mode, LOKREC() returns NO_ERROR to indicate success, or a non-zero error code to indicate failure. On success, c-tree's connection-level state variable sysiocod is set to indicate whether or not another connection or co-file has acquired a lock on the specified offset:
- A sysiocod value of 0 indicates no lock is held by another connection or co-file.
- A sysiocod value of 2 indicates a write lock is held by another connection or co-file.
- A sysiocod value of 4 indicates a read lock is held by another connection or co-file.
Table Locking
V11 and later of FairCom DB support file-level locking on c-tree data files, which is known as a "table lock." An application can request a file lock to prevent other connections from reading from and/or writing to the file. Table Locks can be invoked using SQL or using the LockCtData() function. For information, see the sections titled Table Lock Support (Table Lock Support, Table Lock).
LOKREC() modes to unlock all records in all files of the specified type that are open by the caller
In V11, LOKREC() function's ctFREE_FILE mode now supports options to free ALL locks in ALL specified types of files that a caller has open. To use this feature, call LOKREC() with mode of ctFREE_FILE, recbyt of zero (it is ignored), and set datno to one, or a combination of the following values:
- ctFREEALL_NOTRAN - free all non-transaction file locks
- ctFREEALL_NOIICT - free all transaction-controlled file locks without IICT enabled
- ctFREEALL_IICT - free all transaction-controlled file locks with IICT enabled
- ctFREEALL_TRAN - free all transaction-controlled file locks
- ctFREEALL_ALL - free all file locks
Example
Free all locks in all non-transaction files and all transaction-controlled files that are not using IICT that the caller has open.
rc = LOKREC( ctFREEALL_NOTRAN | ctFREEALL_NOIICT,ctFREE_FILE, 0 );
See also
LockISAM(), NewData(), NewVData()
LockDump
Dump the FairCom Server internal lock table.
Short Name
ctLOKDMP()
Type
Low-Level function
Declaration
COUNT LockDump(COUNT refno, pTEXT dumpname, COUNT mode) Description
LockDump() creates a diagnostic dump of the FairCom Server internal lock table. refno indicates whether locks for a particular file or user are to be dumped or whether all locks are to be dumped. mode indicates whether the dump is organized by file or by user number. dumpname is the name of a text file to which the contents of the dump will be appended.
The possible legal combinations of the mode and refno parameters are as follows:
| refno | mode | Interpretation |
|---|---|---|
|
ctLOKDMPallfiles ctLOKDMPdatafiles ctLOKDMPindexfiles filno |
ctLOKDMPfile |
Dump all locks by file. Dump all locks on data files. Dump all locks on index files. Dump locks for file filno. |
|
ctLOKDMPallusers ctLOKDMPcaller userno |
ctLOKDMPuser |
Dump all locks by user. Dump locks for user calling LockDump(). Dump locks for user userno. |
In all but one case of the above combinations the caller of LockDump() does not have to have any files open, although it is no problem if the caller does have files open. In the case of ctLOKDMPfile/filno, the caller must have opened a file with file number filno. The userno referenced in the last combination is the thread ID assigned by the FairCom Server. This thread ID is listed when ctadmn is used to list users logged on to the FairCom Server. In addition to dumping the location of the lock and the type of lock, users waiting for a lock are also listed.
Lock Dump Contents
=================================================
All Files Lock Dump at Fri May 04 13:00:12 2007
----------------
----------------
SOMEFILE.FCS>>
0000-013c9a16x T221 write/1: W060 W254 W740 W763 W758
0000-002916abx T758 write/1: W774 W772 W771 W775 W773 W778 W779 W776 W071
cumulative lock attempts: 4002(616) blocked: 21(0) dead-lock: 0 denied: 0
Current file lock count: 0
----------------
cumulative I/O: read ops: 0 bytes: 0 write ops: 5 bytes: 16768
.
.
.
.
List of connected clients
-------------------------
User# 00002: (Node name not set)
User# 00012: (Node name not set)
=================================================Description
In the example above, there are two records with locks held in SOMEFILE.FCS. Each record is listed with it’s locked file offset value, the thread ID of the user holding the lock, the type of lock, and a listing of thread IDs waiting for the record lock to be released. The waiting thread IDs are further delineated with a prefix indicating the type of lock they are waiting to obtain, write (W) or read (R) locks.
Types of Locks
There are several types of record locks that can be reported. The most common of these are:
- read - A read lock requested and held by a user thread.
- write/1 - A write lock requested and held by a user thread.
- write/2 - An internal lock very briefly held by the FairCom Server for files under transaction control. You may occasionally observe these in a system with a high transaction volume, and these can be safely ignored.
- forcei cmtlok - A very briefly held commit read lock enforced by the FairCom Server. These will only occur when the COMMIT_READ_LOCK option is enabled in the server configuration file. These may be occasionally observed in systems with high transaction volumes.
File Lock Info
- cumulative lock attempts xxx (yyy) - Total number of file and (header) lock attempts. The header locks are internal FairCom Server locks required for critical updates to the file header.
- blocked - Total number of locks and (header locks) that were blocked while another lock was held. In a high volume system, some blocked lock attempts are expected.
- dead-lock - Total of dead-lock conditions reported for this file. These are generally not expected, and error DEAD_ERR (86) is returned to the application caller when this condition is detected. DEAD_ERR is returned when waiting for a write lock would cause a deadlock condition.
- denied - Total number of locks denied to a caller with error DLOK_ERR (42). A lock is denied if the record is already locked. Note that blocking locks cause the thread to sleep until the lock is available, avoiding the DLOK_ERR.
Cumulative I/O
- read ops - Total cumulative read operations for this file.
- bytes - Total cumulative bytes read for this file.
- write ops - Total cumulative write operations for this file.
- bytes - Total cumulative bytes written for this file.
List of Connected Clients
A list of all connected clients is appended to the end of the lock dump output. This assists the correlation of known user threads at the application level to threads with potential blocked locks.
- User# - The thread ID of the user as identified by the FairCom Server
- Node Name - The node name of the thread as assigned by the application.
Note: On Windows, the list of connected clients includes the IP address in addition to the user name and node name.
Return
The common error code returns are:
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful lock dump. |
| 12 | FNOP_ERR | Could not open the dumpname text file. |
| 22 | FNUM_ERR | mode is ctLOKDMPfile and refno (filno) is out of range. |
| 26 | FACS_ERR | mode is ctLOKDMPfile and refno (filno) does not reference an opened file for the caller. |
| 116 | IMOD_ERR | Bad mode or combination of mode and refno. |
| 454 | NSUP_ERR | The call is not made to a FairCom Server; or the caller is not part of the ADMIN group; or DIAGNOSTICS LOCK_DUMP is not in the configuration file. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
COUNT retval;
TEXT dumpname[20]="AllUserLocks.dmp"
retval = LockDump(ctLOKDMPallusers, dumpname, ctLOKDMPuser);
switch (retval) {
case NO_ERROR:
break;
case NUSUP_ERR:
terminate("LockDump not supported .");
default:
terminate("LockDump error.");
}Limitations
Note: Dumping large quantities of locks in a very active system could affect performance.
Because of potential performance impact, a FairCom Server will ONLY support the LockDump() call if either of the following conditions is met:
- The configuration file, ctsrvr.cfg, contains DIAGNOSTICS LOCK_DUMP.
- The user calling LockDump() belongs to the ADMIN user group.
Related Topics
- The command-line utility ctstat -filelocks and -userlocks modes provide an alternate way to retrieve lock table information. That utility provides a more granular method of inspecting locks. See File and User Lock Example in the FairCom DB Server Administrator's Guide.
- LockDump Output
LockISAM
Enable, free, or suspend data record locks.
Short Name
LKISAM()
Type
ISAM function
Declaration
COUNT LockISAM(COUNT lokmod) Description
LockISAM() manages the data record locks during multiple-user ISAM file handling. The LockISAM() options, defined in ctport.h, are:
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | ctFREE | Free all data record locks held by this program and cancel the ctENABLE mode. |
| 1 | ctRESET | Equivalent to first calling LockISAM() in the ctFREE mode followed by a call with the existing mode (or ctENABLE if the current mode was ctFREE). |
| 2 | ctENABLE | Once LockISAM() is called with lokmod set to ctENABLE, all subsequent data record reads attempt to get a write lock before proceeding. Write locks can be used to prevent more than one process from updating the record at the same time, since only one process may acquire a write lock on a record. Any number of processes may still read the record. |
| 3 | ctENABLE_BLK | Same as ctENABLE, but a process unable to get a write lock is “put to sleep” until the lock is available. |
| 4 | ctREADREC | Once LockISAM() is called with lokmod set to ctREADREC, all subsequent data record reads attempt to get a read lock before proceeding. Read locks can be used to prevent another process from acquiring a write lock on the record. Any number of processes may acquire read locks on the same record. Not supported by all platforms. See the note after this table. |
| 5 | ctSUSPEND | Temporarily suspend the attempt to get a lock on each ISAM record read. |
| 6 | ctRESTORE | Restore the ctENABLE mode after a previous call to suspend data record locks. |
| 7 | ctRESTRED | Restore the ctREADREC mode after a previous call to suspend data record locks. |
| 8 | ctRESTORE_BLK | Restore the ctENABLE_BLK mode after a previous call to suspend data record locks. |
| 11 | ctREADREC_BLK | Same as ctREADREC, but a process unable to get a read lock is “put to sleep” until the lock is available. |
| 14 | ctRESTRED_BLK | Restore the ctREADREC_BLK mode after a previous call to suspend data record locks. |
| 128 | ctGETLKISAM | Queries the current ISAM lock state. Returns the negative of the value of the current ISAM lock state. For example, if locks are enabled, -2 is returned. |
| 512 | ctLK_RECR | Enables recursive locking. |
To ensure multi-user systems make consistent updates, each program should ctENABLE data record locks prior to updating data, and hold these locks until the operations associated with those data records are completed. At that time, a call to LockISAM() with the ctFREE mode cancels all outstanding ISAM locks. Locks created by LockCtData() will NOT be released. ctRESET is used when traversing the data in key sequential order when, after each update, the previous locks should be released and new locks enabled for the next transaction.
ctREADREC signals that the record is under review by one or more readers, and that no update should be performed. If records are read without read, or write, locks, another process may update the record while it is under review. Usually, this is acceptable.
Note: Many systems do not support read locks. If read locks are not supported, c-tree returns a NO_ERROR condition (i.e., the read lock is not attempted, but no error is reported). The FairCom Server DOES support both read and write locks.
Five LockISAM() modes toggle locking, avoiding unnecessary data record locks in the middle of a transaction. These modes are ctSUSPEND, ctRESTORE, ctRESTORE_BLK, ctRESTRED, and ctRESTRED_BLK. Use the ctSUSPEND mode to scan one or more data records which will NOT be updated, or for which READ LOCKS ARE NOT REQUIRED, in the middle of a transaction which has already enabled data record locks. After scanning these records and before returning to your update activities, either:
- Call LockISAM() with the ctRESTORE mode to restore ctENABLE.
- Call LockISAM() with the ctRESTORE_BLK mode to restore ctENABLE_BLK.
- Call LockISAM() with the ctRESTRED mode to restore ctREADREC.
- Call LockISAM() with the ctRESTRED_BLK mode to restore ctREADREC_BLK.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful call to LockISAM(). |
| 112 | IPND_ERR | A call to ctENABLE locks found some pending record locks. This error check is made to ensure that program logic has not started a new transaction before clearing the locks associated with an old transaction. However, it will also cause an error if some locks are acquired and a redundant LockISAM() call in the ctENABLE mode is issued. |
| 113 | INOL_ERR | No more room left in the internal lock table maintained by LockISAM(). Insufficient system memory. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
In the example below, a program performing updates to customer invoices does updates involving price extension computations. To perform the computations, the program searches a separate ISAM file maintaining the prices. Since the program does not modify the price records, it calls LockISAM(ctSUSPEND) before searching the price records, and LockISAM(ctRESTORE) before continuing with the invoice updates.
Example
FILNO inv_idx, inv_fil, price_idx, price_fil;
TEXT target[9];
struct invd {
TEXT delflg;
TEXT invn[8];
TEXT dscrp[60];
TEXT part[12];
float quant;
float price;
float exten;
} cur_info;
struct {
TEXT pdlflg;
TEXT ppart[12];
float pprice;
} price_rec;
main() {
printf("\nEnter invoice number: ");
scanf("%8s",target);
if (LockISAM(ctENABLE) ||
FirstInSet(inv_idx, target, &cur_info,8)) {
printf("\n\nError starting SCAN with codes %d %d",
isam_err,isam_fil);
LockISAM(ctFREE);
return;
}
while (!isam_err) {
LockISAM(ctSUSPEND); /* turn off lock acquisition */
get_price_extension();
LockISAM(ctRESTORE); /* restore lock acquisition */
ReWriteRecord(inv_fil,&cur_info);
ResetRecord(inv_fil,SWTCURI);
/* reset current ISAM record */
LockISAM(ctRESET);
NextInSet(inv_idx,&cur_info);
}
LockISAM(ctFREE);
}
void get_price_extension()
{
if (GetRecord(price_idx,cur_info.part,&price_rec)) {
printf("\nCould not find part# %s.",cur_info.part);
return;
}
new_info.exten = (cur_info.price = price_rec.pprice) *
cur_info.quant;
}Limitations
The FairCom Server supports both read and write locks on records. When not using the Server for multi-user applications, read locks may show success even if read locks are not implemented.
When using Transaction functions, refer to “Data Integrity” in the c-tree Programmer’s Reference Guide for information on how transaction processing interacts with LockISAM().
See also
LockCtDat()
LockList
Retrieve a list of users that own, and are waiting for, a data record lock at a specified byte offset of a data file.
Declaration
NINT LockList(FILNO datno, ctRECPT recbyt, NINT NbrUsers, pLOCKID userlist, pLONG pNbrLockers, pLONG pNbrWaiters);Short Name
ctLOKLSTDescription
In V12 the file number typedef was formally changed from COUNT, a two-byte value to FILNO, a four-byte value. Refer to this link for compatibility details. Four Byte File Numbering
LockList() information is obtained with the following parameters
- datno is the file number of a data file opened by the calling program.
- recbyt is the byte offset of a data record. To set the high-order word of the record offset for huge files, call ctSETHGH() immediately before calling LockList().
- NbrUsers is the number of LOCKID structures in the array pointed to by userlist.
- userlist may be NULL, but then NbrUsers must be zero.
- pNbrLockers and pNbrWaiters cannot be NULL. In the event that NbrUsers is smaller than the sum of lockers and waiters, then the list returned in userlist is truncated after NbrUsers entries. LockList() returns NO_ERROR if successful.
LockList() returns the user identification information for lock owners and lock waiters in the userlist array. The lock owners are returned at the beginning of the array, and the lock waiters follow the lock owners in the array. The number of lock owners is returned in the 4-byte integer pointed to by pNbrLockers. For read locks there may be more than one lock owner. For write locks there can only be one lock owner unless strict serialization is in effect. The number of users waiting for the lock is returned in the 4-byte integer pointed to by pNbrWaiters. There are waiters for a lock only when a lock request includes the blocking attribute (e.g., ctENABLE_BLK).
Details
LOCKID is a structure defined in ctport.h that includes the internal thread ID, the login name and the node name:
typedef struct lockid {
LONG ThrdID; /* internal thread ID */
TEXT UserID[32]; /* logon ID [IDZ] */
TEXT NodeName[32]; /* optional network NodeName IDZ*/
} LOCKID, * pLOCKID;Because an ISAM operation that fails with a lock denied error DLOK_ERR (42) does not permit the denied locker to determine the record location of the denied lock, LockList() has been enhanced to accept a pseudo datno that indicates the request is for the last denied data record lock by the caller. Use ctLastDeniedLock, defined in ctport.h, for datno and the recbyt will be ignored. Instead, the last denied record lock, across all of the data files opened by the user, if any, will be examined for current lockers and waiters.
The last denied data record lock is not cleared upon the next successful data record lock. So calling LockList(ctLastDeniedLock ...) may be referencing a denied lock from the “distant” past. If the user closes the data file which contains the last denied lock, then the last denied lock will be cleared.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | No error occurred. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
The following is an example to list all lock owner and “waiters” for a given record offset.
Example
NINT ListLockUsers(NINT datno, ctRECPT recbyt)
{
NINT i;
LOCKID list[128];
LONG lockers, waiters;
NINT eRet;
ctSETHGH(0);
eRet = (NINT)LockList((FILNO)datno, recbyt, 128, &list, &lockers, &waiters);
if (eRet != NO_ERROR)
{
printf("LockList failed with error %d\n", eRet);
return -1;
}
/* list lock owners */
for (i = 0; i < (NINT)lockers; i++)
printf("Lock owner %s\n", list[i].UserID);
/* list lock waiters */
for (i = (NINT)lockers; i < (NINT)waiters; i++)
printf("Waiting for lock %s\n", list[i].UserID);
return (NINT)(lockers + waiters);
}See also
LockCtData(), LockDump(), LockISAM()