ReadData
Read fixed-length data record.
Short Name
REDREC()
Type
Low-Level data file function
Declaration
COUNT ReadData(FILNO datno, LONG recbyt, 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
ReadData() reads the data record at byte position recbyt for data file datno into the buffer area pointed to by recptr. If datno refers to a variable-length file, ReadData() reads only the fixed-length portion into the buffer. Use ReReadVRecord() to read an entire variable-length record.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful read. |
| 29 | ZREC_ERR | Attempt to read at byte offset zero. |
| 30 | LEOF_ERR | recbyt exceeds the logical end of file maintained in the data file header. |
| 33 | DNUL_ERR | recptr is NULL. |
| 35 | SEEK_ERR | lseek() failed while preparing for read. |
| 36 | READ_ERR | Operating system could not execute read. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO datno,keyno;
TEXT recptr[1024];
LONG part_number;
scanf("%ld",&part_number);
if (ReadData(datno, GetKey(keyno, &part_number), recptr))
printf("\nCould not retrieve record for part #%ld", part_number);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.
See also
ctSETHGH(), ctGETHGH(), ReReadVRecord(), ReadIsamData(), WriteData()
ReadIsamData
ISAM read data at record position.
Short Name
REDIREC()
Type
ISAM function
Declaration
COUNT ReadIsamData(FILNO datno, LONG recbyt, 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
ReadIsamData() is the ISAM equivalent to the Low-Level function ReadData(). ReadIsamData() reads the data at record position recbyt for data file datno into the buffer pointed to by recptr. The significance of this function is that it decreases network traffic by eliminating the need to call ReadData() and SetRecord() to update the ISAM record buffers.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful read. |
| 33 | DNUL_ERR | recptr is NULL. No data file read performed. |
| 36 | READ_ERR | Operating system could not execute read. |
| 42 | DLOK_ERR | Could not get lock on data record. No data file read performed. |
| 160 | ITIM_ERR | Record deleted by another user. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO datno;
LONG recbyt[16];
TEXT recptr[1024];
/* fill in an array of record positions */
FillRecordByteArray(recbyt);
/* read the 10th record in the array */
if (ReadIsamData(datno,recbyt[9],recptr))
printf("\nCould not read 10th record, error = %d",
isam_err);
else
printf("\nSuccessful record read at offset %ld",recbyt[9]);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.
See also
ctSETHGH(), ctGETHGH(), ReadData(), SetRecord()
ReadIsamVData
ISAM read variable-length data at record position.
Short Name
REDIVREC()
Type
ISAM function
Declaration
COUNT ReadIsamVData(FILNO datno, LONG recbyt, 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
ReadIsamVData() reads a variable-length ISAM record and is the variable-length analog to ReadIsamData(). ReadIsamVData() reads the data at record position recbyt for data file datno into the buffer pointed to by recptr for plen bytes.
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.
ReadIsamVData() decreases network traffic by eliminating the need to make two separate function calls as follows:
- Retrieve the fixed-length portion of the record with an ISAM search routine, such as FirstRecord(),
- Call ReReadVRecord() to retrieve the variable-length component.
As with the other variable-length ISAM functions, ReadIsamVData() can read all or a portion of the variable-length record, potentially further reducing network traffic.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful ISAM read operation. |
| 33 | DNUL_ERR | recptr is NULL. No data file read performed. |
| 36 | READ_ERR | Read error occurred. Bad record byte value. |
| 42 | DLOK_ERR | Could not get lock on data record. No data file read performed. |
| 160 | ITIM_ERR | Record deleted by another user. |
| 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.
Example
FILNO datno;
LONG recbyt[16];
TEXT recptr[1024];
VRLEN varlen;
/* fill in an array of record positions */
FillRecordByteArray(recbyt);
varlen = 64; /* set plen to 64 bytes */
/* read *plen bytes of the 10th record in the array */
if (ReadIsamVData(datno,recbyt[9],recptr,&varlen))
printf("\nCould not read 10th record, error = %d", isam_err);
else
printf("\nSuccessful record read at offset %ld", recbyt[10]);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.
See also
ctSETHGH(), ctGETHGH(), FirstRecord(), ReReadVRecord(), ReadData(), ReadIsamData().
ReadVData
Read variable-length data record.
Short Name
RDVREC()
Type
Low-Level variable-length record function
Declaration
COUNT ReadVData(FILNO datno, LONG recbyt, pVOID recptr, VRLEN varlen)Description
ReadVData() reads the variable-length data record at byte position recbyt for data file datno into the buffer area pointed to by recptr. If varlen, the size of the buffer pointed to by recptr, is not large enough for the variable-length record, ReadVData() returns an error.
To ensure varlen is large enough, call VDataLength() before calling ReadVData(). VDataLength() returns the actual length of the record. If the existing buffer is not large enough, a new, larger buffer must be allocated before calling ReadVData().
Note: No check is actually made to be sure that the region pointed to by recptr is in fact as large as varlen indicates. It is up to the application to ensure that varlen accurately specifies the size of the area pointed to by recptr.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful read. |
| 29 | ZREC_ERR | Attempt to read at byte offset zero. |
| 33 | DNUL_ERR | recptr is NULL. |
| 35 | SEEK_ERR | lseek() failed while preparing for read. |
| 36 | READ_ERR | Operating system could not execute read. |
| 48 | FMOD_ERR | datno is not assigned to a variable-length data file. |
| 123 | RVHD_ERR | Record is not preceded by a valid record mark. |
| 153 | VBSZ_ERR | varlen < actual record length. |
| 154 | VRCL_ERR | Variable-length record is zero bytes long. |
| 158 | VFLG_ERR | Variable-length record is not marked as active. |
| 160 | ITIM_ERR | Multi-user interference: key value changed between index search and subsequent data record read. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO datno, keyno;
VRLEN cur_bufsiz, varlen;
pTEXT recptr, calloc();
LONG part_number, pntr;
scanf("%ld",&part_number);
if ((pntr = GetKey(keyno,&part_number)) != DRNZERO) {
varlen = VDataLength(datno,pntr);
if (varlen > cur_bufsiz) {
free(recptr);
recptr = calloc(1,varlen));
cur_bufsiz = varlen;
}
if (ReadVData(datno,pntr,recptr,varlen))
printf>("\nError #%d reading at %ld", uerr_cod, pntr);
}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.
See also
ctSETHGH(), ctGETHGH(), ReReadVRecord(), VDataLength(), WriteVData()
RebuildIFile
Incremental ISAM rebuild.
Short Name
RBLIFIL()
Type
ISAM function
Declaration
COUNT RebuildIFile(pIFIL ifilptr) Description
RebuildIFile() rebuilds the data file and index files referenced by the IFIL structure pointed to by ifilptr. The file(s) to be rebuilt MUST be closed. RebuildIFile() opens the file(s), performs the rebuild, and closes the files upon completion.
RebuildIFile() does the following:
- Resets the update corrupt flag updflg in the header of the data file.
- Rebuilds the internal delete stack chain in fixed-length files and rebuilds the internal delete management index in variable-length files.
- Removes the existing index file and builds an index, optimized for both size and speed, over the existing data file.
- If a SRLSEG exists, RebuildIFile() finds the highest serial number in use and updates the file header with that value.
The user data is not affected in any way.
If you desire the files to be rebuilt in directories that are not specified until run-time, then ifilptr->pfilnam should not be finalized until run-time.
If RESOURCES are defined, and if ifilptr->tfilno is set to updateIFIL, RebuildIFile() automatically places the current IFIL array into a resource record in the data file - even if the data file was created without resources. After writing the IFIL structure, RebuildIFile() checks to see if the IIDX or ISEG arrays have changed. If changes are detected, the new structures replace any existing structures in the data file or will be added if no structures were previously present.
Note: Do not use RebuildIFile() to add indexes to an existing index, since the member headers are all at the front of the physical file with the key values afterward, and there is no slack space to add new member headers without recreating the physical index file. Therefore, first delete the physical index file and then do the rebuild if additional index members are added. You may also use PermIIndex() or TempIIndexXtd().
Rebuild times can be optimized by increasing the number of temporary sort files used. Increase the #define MAX_HANDLES found in ctsort.h from its default of 50 to a larger number up to the maximum of 255. The value to use is a function of the size of the index to be rebuilt and the number of available file handles and is best determined by performing timing tests on the target system. The temporary files created during rebuild are c-tree files. After changing ctsort.h, recompile the entire c-tree library, including removing the object files and library, and the rebuild application.
The path and/or drive of the temporary sort files can be modified in non-server mode with minor changes to ctsort.h and ctsort.c as follows:
Change approximately line 32 of ctsort.h from:
#define WORK_DRIVE_OR_PATH ""to:
pTEXT WORK_DRIVE_OR_PATH;Now declare WORK_DRIVE_OR_PATH as an ‘extern’ in the rebuild application and assign the desired path. See also the GetCtTempFileName() function description.
A second method for decreasing rebuild times is to link the rebuild application with a single-user c-tree library so that index caching will be used. To increase the size of the index cache, increase the number of index buffers (i.e., bufs parameter to InitISAM() or the first number of the parameter file initialization record). The index cache uses a hashing algorithm, therefore the larger the index cache the faster the rebuild will be. The size of the index cache can be calculated as follows:
memory(in bytes) = bufs *(sect * 128 + MAXLEN + 128)MAXLEN, the maximum key length defined in ctopt2.h, defaults to 1024 bytes.
Option to skip initial data file scan
Normally, the rebuild function starts by scanning the data file, checking for valid record marks if it is a variable-length data file, and checking that the logical and physical end of file values are correct. If the data file is known to be in a good state, it can be beneficial to skip this scan. OR the skipdatascanIFILoption bit into the tfilno field of the IFIL structure that you pass to the rebuild function. When using this and other options, remember to negate the tfilno value after you OR in the options. For example:
myifil.tfilno = -(redosrlIFILoption | skipdatascanIFILoption);
RBLIFIL(&myifil);Automatic Duplicate Purge Logic
Prior to c-tree V6.7, rebuilding a file with duplicate key values on an index for which duplicates were not allowed terminated the rebuild completely or left the indexes in an inconsistent state. The index not supporting duplicates would not have an entry for the record while the other indexes would have an entry for the record. For consistency, this is still the default behavior, but details concerning the duplicate keys are sent to a temporary text file instead of the console. The name of the temporary file is sent to the console and to CTSTATUS.FCS. This information is not subject to the RB_OUTPUT define. It happens automatically and may not be disabled.
Records containing the unwanted duplicates are marked deleted, and none of the indexes will have an entry for this record. A copy of each deleted duplicate record is stored in a temporary file, which notes the position, length, and content of the record. CTSTATUS.FCS contains entries indicating how many duplicate keys were rejected, the name of the data file, the name of the temporary file, and a message indicating successful completion of the duplicate purge.
To implement the automatic duplicate purge behavior, where records with duplicate keys are purged from the data file and copied into a temporary file, one of the following two approaches is used:
- Incremental ISAM Structure Support (IFIL): Rebuilding files defined by an Incremental ISAM Structure is typically accomplished with RebuildIFile(). Setting ifilptr->tfilno to purgeIFIL, which is defined in ctport.h, instigates the new auto-purge logic. It is permissible to set ifilptr->tfilno to purgeIFIL + updateIFIL so both behaviors can be achieved.
- Parameter Files: For parameter files rebuilt with ctrbld.c, add #define ctRBLD_AUTO_PURGE when compiling ctrbld.c. This causes the parameter file rebuild to attempt automatic record purge if duplicate keys are rejected.
Note: If the record is longer than the operating system maximum unsigned integer (MUI), only MUI bytes are stored in the temporary file for this record. Typically, this will only be an issue with 16-bit systems where MUI will be 64K bytes.
To re-instate a deleted record, open the temporary file using c-tree open calls, retrieve the desired record, and insert it back into the data file.
If purgeIFIL is used and a binary stream file can be opened, duplicate keys and bad serial numbers are automatically purged from the indexes and the data records are deleted from the file. RebuildIFile() returns DUPJ_ERR (650) and the temporary stream file contains the deleted data records. This is an informational, not fatal, error.
If purgeIFIL is NOT used and an ASCII stream file can be opened, the duplicate keys and bad serial numbers are not added to the indexes, but the data records remain in the file. RebuildIFile() returns DUPL_ERR (652), and lists the offending keys and data records in the stream file. Before V6.7, RebuildIFile() returned NO_ERROR (0) under this condition. DUPL_ERR is an informational, not fatal, error.
Option Values
Prior to FairCom DB V9.5, several option values were defined such as updateIFIL, purgeIFIL, and badpartIFIL, that can be specified. These values are specified by adding them together. For example: myifil.tfilno = updateIFIL + purgeIFIL. A new approach simplifies checking of these options. The following option values are now specified in ctport.h:
#define updateIFILoption 0x0002
#define purgeIFILoption 0x0004
#define badpartIFILoption 0x0008
#define redosrlIFILoption 0x0010These values can now be OR-ed together and, using the setIFILoptions() macro, assigned to the tfilno field of the IFIL structure passed to the compact or rebuild function. For example, to indicate that you want to assign new serial numbers, do the following:
myifil.tfilno = setIFILoptions(redosrlIFILoption);
RBLIFIL(&myifil);If you want to also use more than one option when compacting or rebuilding a file, OR them in to the value. For example:
/* assign new serial numbers and update IFIL resource. */
myifil.tfilno = setIFILoptions(redosrlIFILoption | updateIFILoption);
RBLIFIL(&myifil);If a stream file cannot be opened, RebuildIFile() returns either KDUP_ERR (2) or KSRL_ERR (605) when duplicate keys and/or bad serial numbers are encountered. Further, no more indexes are processed. That is, the rebuild does not run to completion as it does in the above two cases.
To rebuild a mirrored file, ensure the mirror is specified in ifilptr. RebuildIFile() copies the primary file to the mirrored name on successful completion.
badpartIFILoption (badpartIFIL)
The rebuild should reference the partition host. If the partition host can be opened, we attempt to open each member and rebuild only the members that get an error on open. If the partition host itself fails to open, we rebuild the host and all members.
Online Rebuild - new for V13
An online index rebuild has been implemented. It requires the target file to have the ctTRNLOG file mode (full transaction control).
To invoke an online rebuild, use onlineIFILoption:
myifil.tfilno = setIFILoptions(onlineIFILoption);
RBLIFIL(&myifil);The file must be closed by the calling user, as for a normal rebuild, but may be open by OTHER users for update. The IFIL resource embedded in the file is used, not the IFIL definition provided by the caller. Behavior is undefined if the IFIL resource embedded in the file doesn't match the definition used to create the indexes.
Note: Online rebuild uses the dynamic dump and immediate restore, so it requires the ctrdmp binary exists in the server working directory. Only one dynamic dump may occur at a time, so the online rebuild will wait to begin if backups or other online rebuilds are in process. When the new index is ready, access to the file will be suspended while the index is replaced. Any active transactions that have updated this file will be aborted at this point. If an error occurs after this point, the index will need to be rebuilt in exclusive mode. The online rebuild is not supported for memory files, partition files, segmented files, or superfiles. Files with deferred indexes are not currently supported.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful rebuild of ISAM files. |
| 12 | FNOP_ERR | Could not open file(s). Check isam_fil for the specific file number. |
| 20 | KMIN_ERR | Key length too large for node size. |
| 22 | FNUM_ERR | File number is out of range. |
| 45 | KLEN_ERR | Key length exceeds MAXLEN parameter in ctoptn.h. |
| 46 | FUSE_ERR | If ifilptr->dfilno >= 0, file number (range) already in use. If ifilptr->dfilno < 0, no block of numbers available. |
| 107 | IDRK_ERR | Too many index files for one data file. Increase MAX_DAT_KEY parameter in ctoptn.h. |
| 109 | IKRS_ERR | Too many key segments. Increase MAX_KEY_SEG parameter in ctoptn.h. |
| 115 | ISLN_ERR | Key segments do not equal key length. |
| 120 | RRLN_ERR | Not enough dynamic memory for record buffer. |
| 122 | RMOD_ERR | Attempt to change between fixed and variable-length records. |
| 123 | RVHD_ERR | A variable-length record is not preceded by a valid record mark. |
| 454 | NSUP_ERR | Mirrored file rebuilds are not supported. Rebuild the primary if necessary and then copy to the mirrored file name. |
|
484 485 |
Error opening sortwork file. Increase the number of file handles requested at c-tree initialization time (InitISAM(), InitISAMXtd() or second value in parameter file Initialization Record). | |
| 605 | KSRL_ERR | Bad serial number. |
| 650 | DUPJ_ERR | Informational: Duplicate records successfully purged. |
| 652 | DUPL_ERR | Duplicates found and listed in stream file. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
extern IFIL customer;
COUNT retval;
main() {
if (retval = InitISAM(10,10,16))
printf("\nInitISAM error = %d",retval);
if (!(RebuildIFile(&customer)))
printf("\nSuccessful rebuild");
else
printf("\nRebuildIFile isam_err = %d",isam_err);
CloseISAM();
}Limitations
RebuildIFile() can be called from applications linked with the Standalone Multi-user (FPUTFGET) mode. RebuildIFile() opens the files in ctEXCLUSIVE mode, so no processes may access the file during rebuild. For performance reasons, single-user rebuilds are recommended.
To rebuild superfiles, call SuperfilePrepassXtd() prior to RebuildIFile().
See also
- Preventing Possible Data Loss with Compact & Rebuild Operations
- PermIIndex()
- TempIIndexXtd()
- GetCtTempFileName()
- RebuildIFileXtd()
- InitISAM()
- CompactIFile()
- SuperfilePrepassXtd()
- ISAM Functions (ISAM Database Technology, /doc/ctreeplus/30841.htm) in the c-tree Programmer’s Reference Guide (describes the ISAM parameters)
RebuildIFileXtd
Extended Incremental ISAM rebuild.
Short Name
RBLIFILX()
Type
Extended ISAM function
Declaration
COUNT RebuildIFileXtd(pIFIL ifilptr, cpTEXT dataextn, cpTEXT indxextn,
LONG permmask, cpTEXT groupid, cpTEXT fileword)Description
RebuildIFileXtd() is a variation of RebuildIFile() that permits the use of the FairCom Server’s security system. This section expands on the description of RebuildIFile().
- dataextn and indxextn point to buffers specifying optional data and index file name extensions, respectively. The extensions are 8-byte ASCIIZ strings. If the pointers are NULL, the default extension are used: .dat for data files and .idx for index files. To use no extensions, pass a pointer to a buffer containing only blanks terminated by NULL. Do not set both extensions to blanks. The data and index files must be distinct.
- permmask is the permission mask assigned to this data file. It is formed by OR-ing the appropriate permission constants.
- groupid is a pointer to a buffer that contains the group id that this file is to be assigned to. The group id must be valid for the user that is creating the file. If groupid is null, the file will be assigned to the default group for the user.
- fileword is an optional file password. If fileword is null then there will be no password for this file. If a password is established, every user will need to use the password to be able to open the file.
For more information on permission masks, group id’s, and file passwords, review Security and Encryption (File Security and Encryption, /doc/ctreeplus/FileSecurityandEncryption.htm) in the c-tree Programmer’s Reference Guide.
Return
The following error code may be seen in addition to those for RebuildIFile():
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 455 | SGRP_ERR | This user does not belong to the group groupid. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
See also
- Preventing Possible Data Loss with Compact & Rebuild Operations
- InitISAM()
- RebuildIFile()
- CloseISAM()
RebuildIFileXtd8
Extended 8-byte Incremental ISAM rebuild.
Short Name
RBLIFILX8()
Type
Extended 8-byte ISAM function
Declaration
COUNT RebuildIFileXtd8(pIFIL ifilptr, cpTEXT dataextn,
cpTEXT indxextn, LONG permmask, cpTEXT groupid,
cpTEXT fileword, pXCREblk pxcreblk)Description
RebuildIFileXtd8() is a variation of RebuildIFile() that permits the use of huge file support. This section expands on the description of RebuildIFile() and RebuildIFileXtd().
pxcreblk points to an array of XCREblk structures, the extended creation block, one for each physical file in ifilptr. For more information, review Huge File Support in the c-tree Programmer’s Reference Guide.
Return
RebuildIFileXtd8() returns error codes similar to those for RebuildIFile() and RebuildIFileXtd().
See c-tree Error Codes in the c-tree Programmer’s Reference Guide for a complete listing of valid c-tree error values.
See also
- Preventing Possible Data Loss with Compact & Rebuild Operations
- InitISAM()
- RebuildIFile()
- CloseISAM()
- RebuildIFileXtd()
RebuildIIndex
Rebuilds a single index.
Short Name
RBLIIDX()
Type
ISAM function
Declaration
COUNT RebuildIIndex(pIFIL ifilptr) Description
RebuildIIndex() rebuilds the indexes specified by ifilptr, starting with the file number specified in ifilptr->tfilno, producing new optimized indexes.
InitISAM() or InitISAMXtd() must be called prior to calling RebuildIIndex() and the file pointed to by ifilptr->tfilno must be open at the time of the call to RebuildIIndex().
RebuildIIndex() was created for use with PermIIndex() and TempIIndexXtd(). By default, both functions create and fill index files in one action. The ability to separate the index creation from the index build permits UpdateConditionalIndex() to set conditional expressions for the new indexes. If PermIIndex() is involved, the data file has its conditional index resource updated. If TempIIndexXtd() is involved, no permanent storage of the conditional index expression is made. The proper steps are:
- PermIIndex() or TempIIndexXtd() with ifilptr->dxtdsiz == ctNO_IDX_BUILD.
- UpdateConditionalIndex() for each new index with a conditional expression.
- RebuildIIndex() for each new index.
Note: Between a call to PermIIndex() or TempIIndexXtd() and a call to RebuildIIndex(), the newly created indexes have remained opened, and have not been closed or closed and re-opened.
The setting for SORT_MEMORY <n> in ctsrvr.cfg should be increased when rebuilding large indexes for performance. The closer SORT_MEMORY is set to the size of the index, the faster the sort phase of the rebuild will be, regardless of the index size. (There is no additional benefit in setting SORT_MEMORY larger than the size of the index.)
Return
A zero (0) return indicates successful operation. A non-zero return indicates an error, check isam_err. The error returns are similar OpenCtFile() and RebuildIFile(). See c-tree Error Codes in the c-tree Programmer’s Reference Guide for a complete listing of valid c-tree error values.
Example
extern IFIL customer;
COUNT retval;
FILNO filno;
COUNT conditional;
main() {
if (retval = InitISAM(10,10,16))
printf("\nInitISAM error = %d",retval);
filno = OpenFileWithResource(-1,"test", (ctEXCLUSIVE | ctPERMANENT));
if (filno < 0) {
printf("\nOpen failed");
exit(1);
}
customer->dfilno = filno
customer->tfilno = -1
if (conditional)
customer->dxtdsiz = ctNO_IDX_BUILD;
if (permIIndex(&customer))
printf("\nAdding Index failed (%d %d)", isam_err, isam_fil);
if (conditional && !(RebuildIIndex(&customer)))
printf("\nSuccessful compact");
else
printf("\nRebuildIIndex isam_err = %d",isam_err);
CloseISAM();
}Limitations
RebuildIIndex() does not support superfiles, see Superfiles in the c-tree Programmer’s Reference Guide.
RebuildIIndex() is not recommended for existing indexes. If one index becomes corrupt, FairCom recommend rebuilding all indexes associated with the data file.
See also
InitISAM(), InitISAMXtd(), UpdateConditionalIndex(), OpenCtFile(), PermIIndex(), RebuildIFile(), TempIIndexXtd()
RegisterCtree
Register (establish) a c-tree instance.
Short Name
REGCTREE()
Type
Low-Level function
Declaration
COUNT RegisterCtree(pTEXT regid) Description
RegisterCtree() accepts a unique registration reference name, pointed to by regid, and establishes a unique c-tree instance. Each call allocates a new control block for the c-tree global variables. The registration reference name can be up to 31 bytes and a NULL terminator in length.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Instance successfully registered. |
| 82 | UALC_ERR | User allocation error (usually out of memory). |
| 518 | GEXS_ERR | regid is already registered. |
| 536 | AREG_ERR | Only automatic RegisterCtree() is allowed. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
TEXT inpbuf[32]; /* input buffer */
ctrt_printf("\nEnter Instance Name\n");
gets(inpbuf);
if (RegisterCtree(inpbuf))
{
ctrt_printf("\nCould not register {%s} data base",inpbuf);
ctlxmg_exit(2);
}Limitations
File handles are not shared between instances. Virtual logic cannot close files in other instances.
See also
NextCtree(), SwitchCtree(), WhichCtree(), GetCtreePointer(), UnRegisterCtree()
ReleaseData
Release fixed-length data record for reuse.
Short Name
RETREC()
Type
Low-Level data file function
Declaration
COUNT ReleaseData(FILNO datno, LONG recbyt)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
ReleaseData() adds record position recbyt to the chain of deleted records for fixed-length file datno. ReleaseData() should be called when a data record is no longer needed so that the space can be reused. Records returned by ReleaseData() are reused by NewData() before the data file is extended. ReleaseData() is automatically called by DeleteRecord().
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful return operation. |
| 29 | ZREC_ERR | recbyt is zero. |
| 30 | LEOF_ERR | recbyt exceeds the logical end-of-file maintained in the data file header. |
| 32 | DDRN_ERR | Attempt to return recbyt twice in a row. |
| 48 | FMOD_ERR | datno is not assigned to a fixed-length data file. |
| 57 | DADV_ERR | Proper lock not found by the FairCom Server. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO keyno,datno;
LONG recbyt;
pTEXT target;
if (recbyt = GetKey(keyno,target))
if (DeleteKey(keyno,target,recbyt) == NO_ERROR)
if (ReleaseData(datno,recbyt) == NO_ERROR)
printf("\nSUCCESS.");Limitations
ReleaseData() writes an 0xff byte and a 4-byte data record position starting at the first byte of the returned data record. Therefore, even if you only write ASCII information into the data records, ReleaseData() will place binary information into the beginning of deleted records.
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
ctSETHGH(), ctGETHGH(), DeleteRecord(), LockCtData(), NewData()
ReleaseVData
Release variable-length data record for reuse.
Short Name
RETVREC()
Type
Low-Level data file function
Declaration
COUNT ReleaseVData(FILNO datno, LONG recbyt)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
ReleaseVData() adds record position recbyt to the pool of deleted records for variable-length file datno. ReleaseVData() should be called when a data record is no longer needed so that the space can be reused. Records returned by ReleaseVData() are reused by NewVData() before the data file is extended. ReleaseVData() is automatically called by DeleteVRecord().
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful return operation. |
| 2 | KDUP_ERR | Attempt to delete a record already in reuse list. |
| 48 | FMOD_ERR | datno is not assigned to a variable-length data file. |
| 57 | DADV_ERR | Proper lock not found by the FairCom Server. |
| 159 | VPNT_ERR | recbyt is zero. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO keyno,datno;
LONG recbyt;
pTEXT target;
if (recbyt = GetKey(keyno,target))
if (DeleteKey(keyno,target,recbyt) == NO_ERROR)
if (ReleaseVData(datno,recbyt) == NO_ERROR)
printf("\nSUCCESS.");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.
See also
ctSETHGH(), ctGETHGH(), DeleteVRecord(), LockCtData(), NewVData()
RemoveAutoSysTimeFields
Removes the automatic system time definition from datno.
Type
ISAM Function
Declaration
NINT RemoveAutoSysTimeFields(FILNO datno);Description
- datno - the data file number. 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
Return
NO_ERROR on success
RenameFile
Rename a file.
Short Name
ctRENFIL()
Type
Low-Level function
Declaration
COUNT RenameFile(FILNO filno, cpTEXT newname) 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
RenameFile() renames a file that has been opened exclusively, meaning no other processes have the file open. RenameFile() is particularly useful for allowing a client application to rename a file controlled by a FairCom Server.
A superfile host cannot have any members open when it is renamed. A superfile member must have a correct matching host name in the newname string. For example, if the file being renamed is myhost!oldname, the newname string must be of the form “myhost!newname”. A file opened as part of a mirrored pair cannot be renamed.
Note: filno corresponds to the file to rename, and which must have been open exclusively. When renaming transaction logged files, it would be wise to include SKIP_MISSING_FILES YES in the FairCom Server configuration file since the log may contain references to the old file, which will not appear present during recovery.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful file rename. |
| 22 | FNUM_ERR | Bad filno. |
| 62 | LERR_ERR | File must be opened exclusively. |
| 67 | RENF_ERR | Could not rename file, usually because newname already exists or newname implies an unsupported move of the file to a different directory. |
| 70 | TEXS_ERR | Cannot rename a transaction logged file in the middle of a transaction in which it is updated. |
| 418 | SNAM_ERR | Bad superfile member name. Old name and new name must have matching hosts. |
| 446 | BMOD_ERR | Attempt to rename a superfile host directory. |
| 454 | NSUP_ERR | Cannot rename a file opened as part of a mirrored pair. Open the file with ctMIRROR_SKP. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
RenameIFile
Atomically rename some or all of the files associated with the IFIL structure.
Short Name
RENIFIL()
Type
ISAM function
Declaration
COUNT RenameIFile(pIFIL ifilptr)Description
RenameIFile() atomically renames some or all of the files associated with the IFIL structure ifilptr, and updates the internal IFIL resource. ifilptr must point to a complete IFIL structure corresponding to an exclusively opened IFIL, with the names replaced by the new names. If the “new” name is the same as the original name, no renaming takes place for that file. The tfilno member of ifilptr must contain the file number of the data file associated with the IFIL. The dataextn and indxextn parameters can be used to modify the file name suffixes of the data and/or index files.
The data file’s IFIL resource will be updated under the following conditions:
- Resources have been enabled.
- The ctDISABLERES bit of the dfilmod member of ifilptr is not on.
When the IFIL resource is updated, then the following protocol is used:
- If an existing IFIL resource is found, then only the name fields are updated to reflect the renaming operations.
- If no existing IFIL resource is found, then the IFIL information passed into RenameIFile() is used in its entirety.
The IFIL structure passed into RenameIFile() must agree with both the physical files and the existing IFIL resource (if any) on the following points:
- The number of indexes.
- The key length and duplicate key status of each index.
- The specification of which indexes serve as a host index, keeping in mind that the aidxnam member of IIDX can create host indexes in addition to the “base” index.
If any of these characteristics do not match, RenameIFile() returns IAIX_ERR (608).
The first index in the IFIL may derive its name either from the data file name, or through a non-NULL aidxnam parameter. The new IFIL may change whether or not the aidxnam parameter is used for the first index. It cannot change whether aidxnam is used for any of the other indexes.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful rename of file. |
| 14 | FCRP_ERR | File updated since ctEXCLUSIVE open. |
| 70 | TEXS_ERR | Transaction in progress. |
| 608 | IAIX_ERR | IFIL resources too different. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
ISEG inv_seg = {
2,25,2
};
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.idx" / 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".)*/
};
IFIL inv_dat = {
"invent", /* data file name ("dat" is always assumed)/
INVENTDAT, / data file number /
sizeof(invent), / data record length /
4096, / data extension size /
1, / data file mode /
1, / number of indices /
4096, / index extension size /
1, / index file mode /
&inv_idx, / pointer to index array*/
"Delflag", /* pointer to first field name (r-tree)/
"Buffer" / pointer to last field name (r-tree)*/
};
#ifdef PROTOTYPE
VOID RenameTable(void)
#else
VOID RenameIFile1()
#endif
{
if (CloseIFile(&inv_dat)) /* Close file - file must be opened in exclusive mode */
printf("\nCloseIFile error %d",isam_err);
inv_dat.dfilmod = 0; /* set data file mode to exclusive for RenameIFile /
inv_dat.ifilmod = 0; / set index file mode to exclusive for RenameIFile */
if (OpenIFile(&inv_dat)) /* Open file now that the data file AND the index are set to exclusive */
printf("\nOpenIFile error %d",isam_err);
cpybuf(inv_dat.pfilnam,"invent2",sizeof("invent2")); /* copy in the new file name for the data file /
cpybuf(inv_idx.aidxnam,"invent2",sizeof("invent2")); / copy in the new file name for the index file */
if (RenameIFile(&inv_dat))
printf("\nRenameIFile error %d",isam_err);
}
Limitations
Transaction Logging
If the data file supports transaction logging and it does NOT have the ctTRANDEP or ctRSTRDEL extended file attributes, two criteria must be satisfied:
- No transaction can be active when RenameIFile() is called.
- The files cannot be updated between the exclusive open and the renaming call.
If either of the criteria is violated, RenameIFile() returns TEXS_ERR (70) or FCRP_ERR (14), respectively.
The renaming and optional updating of the IFIL resource are performed atomically under the control of a transaction automatically managed by c-tree.
Note: Transaction dependent files that have the ctTRANDEP or ctRSTRDEL extended file attributes MUST be within an active transaction to be renamed (the exact opposite of those that do not have these attributes).
Other Limitations
The IFIL structure passed into RenameIFile() must agree with both the physical files and the existing IFIL resource (if any) on the following points:
- The number of indexes.
- The key length and duplicate key status of each index.
- The specification of which indexes serve as a host index, keeping in mind that the aidxnam member of IIDX can create host indexes in addition to the “base” index.
See also
RenameIFileXtd(), RenameFile()
RenameIFileXtd
Rename ISAM files, extended version.
Short Name
RENIFILX()
Type
Extended ISAM function
Declaration
COUNT RenameIFileXtd(pIFIL ifilptr, cpTEXT dataextn, cpTEXT indxextn)Description
RenameIFileXtd() is a variation of RenameIFile() permitting the file extensions to be changed. This section expands on the description of RenameIFile().
dataextn and indxextn point to buffers specifying the data and index file name extensions, respectively. The extensions are 8-byte ASCIIZ (NULL terminated ASCII) strings. If the pointers are NULL, the default extension will be used: .dat for data files and .idx for index files. For files with no extension, pass a pointer to a buffer that contains only blanks terminated by a NULL character.
Return
As with RenameIFile(). See c-tree Error Codes in the c-tree Programmer’s Reference Guide for a complete listing of valid c-tree error values.
ReplaceSavePoint
Maintain a moving savepoint within a transaction.
Short Name
SPCLSAV()
Type
Low-Level data file function.
Declaration
LONG SPCLSAV(VOID)
LONG ReplaceSavePoint(VOID)Description
Call ReplaceSavePoint() to establish a savepoint while at the same time clearing the previous savepoint. ReplaceSavePoint() can be used to maintain a single “moving” savepoint within a transaction, which is useful for applications that may need to undo the work since the last savepoint but that never need to restore back to a point prior to the most recent savepoint. ReplaceSavePoint() provides this ability in the form of a single savepoint rather than multiple savepoints. Because ReplaceSavePoint() clears the previous savepoint, only the most recently established savepoint can be restored to. To restore to this savepoint, call TRANRST(-1).
Return
ReplaceSavePoint() returns a non-zero value to indicate success and a value of zero to indicate failure. If the return value is zero, uerr_cod contains the c-tree error code. If a client supports ReplaceSavePoint() but the server does not, the message:
Bad raw function #. fn: 231will be placed in CTSTATUS.FCS and the c-tree error SFUN_ERR (170) will be returned. A RestoreSavePoint() cannot go back beyond a special save point set with SPCLSAV(). Further, ClearSavePoint() cannot clear a special save point. Either of these situations returns a SPCL_ERR (753).
Example
An example of the use of SPCLSAV() is within the c-treeSQL Server engine that must be able to undo the last update, and may involve a very large number of updates within a single transaction.
See also
SetSavePoint(), RestoreSavePoint()
ReReadRecord
Reread current ISAM record.
Short Name
RRDREC()
Type
ISAM function
Declaration
COUNT ReReadRecord(FILNO datno, 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
ReReadRecord() provides a simple way to reread the current ISAM record for fixed-length data records belonging to data file number datno. The record is read into the record buffer pointed to by recptr. Use ReReadVRecord() to reread the current ISAM record for a variable-length data file, unless only the fixed-length portion of the variable-length record is needed.
As of c-tree V8.14, c-tree sets the current ISAM position after a record is added such that the next or previous record can be read without having to re-read the record just added. Prior to V8.14, the current ISAM position was not set to a newly-added record and an INOT_ERR (101) error would result if you tried to read either the next or previous record.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful read 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. |
| 100 | ICUR_ERR | No current ISAM record. |
| 160 | ITIM_ERR | Record deleted by another user. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO datno;
TEXT buffer[256];
if (LockISAM(ctENABLE) || ReReadRecord(datno,buffer)) {
printf("\nCould not reread record (%d)",isam_err);
LockISAM(ctFREE);
return(-1);
}See also
ReReadVRecord(), the LOCK discussion of multi-user updates in Multi-User Concepts of the c-tree Programmer’s Reference Guide and the source code of CTIXMG.C.
ReReadVRecord
Reread variable-length ISAM data record.
Short Name
REDVREC()
Type
ISAM variable-length record function
Declaration
COUNT ReReadVRecord(FILNO datno,pVOID recptr, VRLEN varlen)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
ReReadVRecord() reads the current variable-length ISAM record for data file datno into the buffer area pointed to by recptr. If varlen, the size of the buffer pointed to by recptr, is not large enough for the variable-length record, ReReadVRecord() returns an error. ReReadVRecord() is used to read the entire variable-length record after the fixed-length portion is read via one of the fixed-length ISAM search routines (e.g., FirstInSet() instead of FirstInVSet()).
To ensure varlen is large enough, call VRecordLength() before calling ReReadVRecord(). VRecordLength() returns the actual length of the record. If the existing buffer is not large enough, allocate a new, larger buffer before calling ReReadVRecord().
Note: No check is actually made to be sure that the region pointed to by recptr is in fact as large as varlen indicates. It is up to the application to ensure that varlen accurately specifies the size of the area pointed to by recptr.
As of c-tree V8.14, c-tree sets the current ISAM position after a record is added such that the next or previous record can be read without having to re-read the record just added. Prior to V8.14, the current ISAM position was not set to a newly-added record and an INOT_ERR (101) error would result if you tried to read either the next or previous record.
See also Record Offsets Under Huge File Support.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful read. |
| 33 | DNUL_ERR | recptr is NULL. |
| 35 | SEEK_ERR | lseek() failed while preparing for read. |
| 36 | READ_ERR | Operating system could not execute read. |
| 48 | FMOD_ERR | datno is not assigned to a variable-length data file. |
| 100 | ICUR_ERR | No current ISAM record for file datno. |
| 153 | VBSZ_ERR | varlen < actual record length. |
| 154 | VRCL_ERR | Variable-length record is zero bytes long. |
| 158 | VFLG_ERR | Variable-length record is not marked as active. |
| 159 | VPNT_ERR | recbyt is zero. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO datno, keyno;
VRLEN cur_bufsiz = 128, varlen;
pTEXT recptr;
LONG part_number;
recptr = calloc(1, cur_bufsiz));
if (FirstRecord(keyno, recptr)) == NO_ERROR) {
if ((varlen = VRecordLength(datno)) > cur_bufsiz) {
free(recptr);
recptr = calloc(1,varlen));
cur_bufsiz = varlen;
}
if (ReReadVRecord(datno,recptr,varlen))
printf>("\nCould not reread record (%d).", isam_err);
}See also
ReadVData(), ReReadRecord(), VRecordLength(), WriteVData()
resetIDfield
Resets the IDENTITY value assigned to a DODA field.
Declaration
NINT resetIDfield(FILNO datno, LONG8 nxtval)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
resetIDfield() resets an IDfield (IDENTITY) auto-numbering value for a numeric field in a record to a new specified value.
Where:
- datno is the data file number
- nxtval is the next value to be assigned on record addition
IDfield requires a DAR resource (Direct Access Resource) embedded in the file. The DAR is a specialized high-speed resource.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Success |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
retval = resetIDfield(fileno, 1000);
if (retval) {
printf("\tERROR: Failed to reset ID field with error %d\n", retval);
}Override IDENTITY Values
PUTHDR() using the ctIDfieldOverRide mode can turn on and off the ability to override the automatic IDfield values. The override is on a per user, per file basis. A nonzero hdrval turns on the override, and a zero hdrval restores the standard operation. When the override is on for a data file that supports an IDfield, then an add record operation does not fill-in the IDfield value. Whatever is passed in the record buffer is used for the IDfield. And a rewrite permits the IDfield value to change instead of generating the IDFL_CHG error. When the override is enabled, add record operations do not consume IDfield values.
See also
addIDfield(), delIDfield(), getIDfield(), wchIDfield(), IDfields - Extended support
ResetRecord
Updates the current ISAM record image buffers.
Short Name
UPDCURI()
Type
ISAM function
Declaration
COUNT ResetRecord(FILNO datno, COUNT mode); 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
ResetRecord() manipulates the internal image of the current ISAM record kept by c-tree. An image is kept of the current ISAM record’s key structure and the current ISAM record’s file address. Whenever an ISAM function changes the current ISAM record, such as an AddRecord() or ReWriteRecord(), the original current ISAM record information is copied over to a secondary buffer before the primary buffer is changed. ResetRecord() can be used to manage these two buffers.
- datno specifies the ISAM file that is to be affected.
- mode can be one of several values;
| mode | Description |
| SWTCURI | Switches the ISAM buffers. Use SWTCURI after a rewrite to move the old buffer back to the original. This allows you to keep your position in the file as it was before the rewrite. |
| SAVCURI | Copies the current ISAM record information to the secondary buffer. |
| RSTCURI | Restores the primary ISAM record information from the secondary area. |
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 22 | FNUM_ERR | File number is out of range. |
| 26 | FACS_ERR | File number is not assigned to a file in use. |
| 47 | FINT_ERR | c-tree has not been initialized. |
| 48 | FMOD_ERR | datno is not assigned to a data file. |
| 116 | IMOD_ERR | Invalid value in mode. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO invfil;
struct invd {
TEXT delflg[4];
LONG part_no;
LONG on_hand;
TEXT part_name[60];
} recbuf;
scanf("%ld %59s %ld",&recbuf.part_no,recbuf.part_name, &recbuf.on_hand);
recbuf.delflg = '\0'; /* clear delete flag */
if (AddRecord(invfil,&recbuf) )
printf("\nAddRecord error %d in file %d", isam_err, isam_fil);
/* after adding record, restore current ISAM to previous point */
if (ResetRecord(invfil,SWTCURI) )
printf("\nCannot reset, error %d",isam_err);See also
AddRecord(), ReWriteRecord(), SetRecord().
RestoreSavePoint
Undo transaction operations back to a savepoint.
Short Name
TRANRST()
Type
Low-Level data file function
Declaration
COUNT RestoreSavePoint(COUNT savpnt)Description
RestoreSavePoint() rolls the current transaction back to a previously defined savepoint created with a call to SetSavePoint(). savpnt is the savepoint to roll back to, and is the value returned by the call to SetSavePoint(). This allows you to back up in a transaction to a particular point, without having to Abort() or Commit() the entire transaction. For a complete discussion of this process please see Data Integrity in the c-tree Programmer’s Reference Guide.
savpnt can also be specified as a small negative number. -1 means go back to the most current savepoint. -2 means go back one more, etc.
RestoreSavePoint() also clears errors that have occurred since the savepoint.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | No error occurred. |
| 71 | TNON_ERR | There is no active transaction pending. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
COUNT savepoint;
void domaster() {
Begin( ctENABLE | ctTRNLOG ); /* start transaction with locks */
while( another() ); { /* get next record to add */
savepoint = SetSavePoint();
/* get save point at beginning of each master record */
if ( add_master() < 0 )
Abort(); /* RestoreSavePoint if can't add master rec */
dodetail(); /* process detail records */
}
if ( Commit(ctFREE) )
printf("\nError %d in transaction",uerr_cod);
return;
}
void dodetail() {
while( moredetail() ); { /*get next detail record to add */
if ( add_detail()<0 ) { /* add details, if possible */
RestoreSavePoint( savepoint ) /* with error, return to savept */
return;
}
}
}See also
Abort(), AbortXtd(), Begin(), ClearSavePoint(), Commit(), SetSavePoint(), TRANRDY()
ReWritePartialRecord
Rewrites a partial fixed or variable-length record.
Declaration
COUNT ReWritePartialRecord (FILNO datno, pVOID recptr, VRLEN varlen);Short Name
RWTPREC()
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
ReWritePartialRecord() permits a fixed or variable-length record to be updated (i.e., rewritten) without passing back an entire record image. It is only necessary to pass enough bytes to hold the fields that have been modified. As a matter of good practice, varlen should end on a field boundary. This routine is especially effective for files whose records start with status fields and end with potentially large variable-length fields. For example, for a record containing ID fields and status fields followed by a very large binary field, say a graphic image, and one desired to only change a status or ID field, it is not necessary to pass the entire record to ReWritePartialRecord() rather, only the first few bytes at the beginning of the record. This significantly reduces network traffic and improves performance.
There is a subtle difference between ReWriteVRecord() and ReWritePartialRecord() called with a varlen equal to the original record length: ReWritePartialRecord() assumes a well formed record and will permit a variable-length field to be truncated by the end of the record. ReWriteVRecord() assumes it must avoid field truncation, and would return error SDAT_ERR (445) under the same circumstance. Practically, ReWritePartialRecord() should not be used to perform a full rewrite and good practices would not permit a truncated record image for ReWriteVRecord().
ReWritePartialRecord() can only be used to rewrite with a partial record image that is less than or equal to the full record image length. An attempt to grow the existing record results in error VMAX_ERR (140). When updating records with ReWritePartialRecord() the partial record image must contain enough data to enable c-tree to construct all key segments for all indexes of the data file. ReWriteVRecord() should be used instead of ReWritePartialRecord() if any variable-length field of the record was resized, even if the resulting record length remains unchanged.
Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | No error occurred. |
| 2 | KDUP_ERR | Duplicate key value detected in index file number isam_fil. Record update not performed. |
| 22 | FNUM_ERR | File number is out of range. |
| 26 | FACS_ERR | File number is not assigned to a file in use. |
| 57 | DADV_ERR | Proper lock not found by FairCom Server. |
| 100 | ICUR_ERR | No current ISAM record. |
| 105 | IUND_ERR | Could not undo a rejected ISAM update. |
| 140 | VMAX_ERR | Variable record length too long. |
| 199 | NSCH_ERR | Key segment refers to schema, but schema not defined. |
| 433 | SSCH_ERR | Segment definition inconsistent with schema. |
| 445 | SDAT_ERR | Not enough data to assemble key. |
| 446 | BMOD_ERR | Bad key segment mode. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
If a data file has a record structure that contains three fields: id (CT_INT4), status (CT_INT4) and description (CT_STRING), and the id field is never updated, but the status or the description field may be updated, the ReWritePartialRecord() or ReWriteVRecord() may be used, depending on which field was updated.
Example
typedef struct
{
LONG id;
LONG status;
TEXT description[MAX_DESCRIPTION];
} MYRECORD;
NINT UpdateMyRecord(FILNO datno, LONG id, LONG status, pTEXT description)
{
NINT eRet;
NINT partial = YES;
VRLENvarlen = sizeof(LONG)*2;
MYRECORD recbuf;
/* set the fixed portion of the record */
recbuf.id = id;
recbuf.status = status;
/* check if we need to set the description field */
if (description)
{
strcpy(recbuf.description, description);
partial = NO;
varlen += strlen(description) + 1;
}
/* update/rewrite the record */
if (partial)
eRet = ReWritePartialRecord(datno, &recbuf, varlen);
else
eRet = ReWriteVRecord(datno, &recbuf, varlen);
return eRet;
}
Limitations
An issue remains for how to perform the rewrite, partial or full, if the prior read of the record was itself partial (only the fixed portion of a variable-length record was read) and did not permit all of the internal key buffers to be updated. This issue remains in a pending state and you are advised to not attempt this sequence of operations. In addition, support for row level call callbacks has not been enabled for partitioned files during full or partial rewrites.
See also
ReWriteRecord(), ReWriteVRecord()
ReWriteRecord
Rewrite current fixed-length ISAM record.
Short Name
RWTREC()
Type
ISAM function
Declaration
COUNT ReWriteRecord(FILNO datno, 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
ReWriteRecord() allows changes to be made in the current ISAM record for fixed-length data records belonging to data file number datno. recptr should point to the updated version of the current ISAM record. ReWriteRecord() assumes that the current ISAM record is the original version. After successful completion of ReWriteRecord(), the updated version is now stored in the data file and all necessary changes to the key values associated with the updates are automatically made.
The typical ReWriteRecord() usage is:
- First, an ISAM retrieval function, (e.g., ReadISAMData(), GetRecord(), or NextRecord()), reads the desired record, making it the current ISAM record.
- Updates are made to the record buffer.
- ReWriteRecord() rewrites the updated record, making the updated record the current ISAM record. If any of the key fields have been changed, the old key is removed from the appropriate indexes, and the new one is added.
Unlike c-tree version 4.3 and older, you do not have to be careful about making changes to the current record in your buffer. c-tree maintains its own copy of the current ISAM record key information and position.
Multi-user updates are more complex because of the possibility of either locking out the record for prolonged periods, or because of two users trying to update the same record at the same time. See Multi-User Concepts in the c-tree Programmer’s Reference Guide for a detailed discussion of multi-user updates.
ReWriteRecord() does not change the automatic serial number key segments, if any. If you want the serial number updated, delete the old record and add the updated record.
To make the old record the current ISAM record, so that NextRecord() will be performed relative to the position before the update, make the following call after successfully completing the record rewrite:
ResetRecord(datno,SWTCURI);Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful record update. New record becomes the current ISAM record. |
| 2 | KDUP_ERR | Duplicate key value detected in index file number isam_fil. Record update not performed. |
| 22 | FNUM_ERR | File number is out of range. |
| 26 | FACS_ERR | File number is not assigned to a file in use. |
| 48 | FMOD_ERR | datno is not assigned to a fixed length data file. |
| 57 | DADV_ERR | Proper lock not found by the c-tree. |
| 100 | ICUR_ERR | No current ISAM record. |
| 105 | IUND_ERR | Could not undo a rejected ISAM update. Unless the files support transaction processing, this is a serious error indicating the data file must be rebuilt. |
| 199 | NSCH_ERR | Key segment refers to schema, but schema not defined. |
| 433 | SSCH_ERR | Segment definition inconsistent with schema. |
| 445 | SDAT_ERR | Not enough data to assembly key. |
| 446 | BMOD_ERR | Invalid key mode. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO datno,keyno;
LONG cust_no;
TEXT buffer[128];
printf("\nEnter customer number: ");
scanf("%ld",&cust_no);
if (GetRecord(keyno,cust_no,buffer)) /* read current record */
printf("\nCould not read customer record.");
else {
update(buffer); /* make your changes to buffer */
if (ReWriteRecord(datno,buffer))
printf("\nCould not rewrite customer record.");
else
printf("\nSuccessful update of customer record.");
}
Limitations
After a call to ReWriteRecord(), the current ISAM record is set to the new record. This may create a situation that you don’t expect when ReWriteRecord() is used inside a loop that steps over the data in key sequential order. If the key value is changed during the update, the current ISAM record position will skip to the new position, which may be before or after the original position. To avoid this situation, reset the current ISAM record after ReWriteRecord() using ResetRecord().
See also
ReadISAMData(), GetRecord(), NextRecord(), ResetRecord()
ReWriteVRecord
Rewrite current variable-length ISAM record.
Short Name
RWTVREC()
Type
ISAM function
Declaration
COUNT ReWriteVRecord(FILNO datno, pVOID recptr, VRLEN varlen)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
ReWriteVRecord() allows changes to be made in the current variable-length ISAM record for data file number datno. recptr should point to the updated version of the current ISAM record, and varlen specifies the length of the updated version. ReWriteVRecord() assumes that the current ISAM record is the original version. After successful completion of ReWriteVRecord(), the updated version is now stored in the data file and all necessary changes to the key values associated with the updates are automatically made. If the updated version does not fit into the space available for the current record, it is moved to another location in the data file. All associated indexes are updated appropriately.
The typical ReWriteVRecord() usage is:
- First, an ISAM retrieval function, (e.g., GetRecord() or NextRecord()), reads the fixed portion of desired record, making it the current ISAM record.
- ReReadVRecord() reads the entire record into the buffer. This buffer now contains the entire current ISAM record.
Note: Variable-length retrieval functions, such as ReadISAMVData(), GetVRecord(), and NextVRecord(), accomplish these two steps in one function call.
- Updates are made to the record buffer.
- ReWriteVRecord() rewrites the updated record, making the updated record the current ISAM record. If any of the key fields have been changed, the old key is removed from the appropriate indexes, and the new one is added.
Multi-user updates are more complex because of the possibility of either locking out the record for prolonged periods, or because of two users trying to update the same record at the same time. See Multi-User Concepts in the c-tree Programmer’s Reference Guide for a detailed discussion of multi-user updates.
ReWriteVRecord() does not change the automatic serial number key segments, if any. To update the serial number, delete the old record and add the updated record.
To make the old record the current ISAM record, so that NextRecord() will be performed relative to the position before the update, make the following call after successfully completing the record rewrite:
ResetRecord(datno,SWTCURI);Return
| Value | Symbolic Constant | Explanation |
|---|---|---|
| 0 | NO_ERROR | Successful record update. New record becomes the current ISAM record. |
| 2 | KDUP_ERR | Duplicate key value detected in index file number isam_fil. Record update not performed. |
| 22 | FNUM_ERR | File number is out of range. |
| 26 | FACS_ERR | File number is not assigned to a file in use. |
| 48 | FMOD_ERR | datno is not assigned to a variable-length data file. |
| 57 | DADV_ERR | Proper lock not found by the FairCom Server. |
| 100 | ICUR_ERR | No current ISAM record. |
| 105 | IUND_ERR | Could not undo a rejected ISAM update. Unless the files support transaction processing, this is a serious error indicating the data file must be rebuilt. |
| 199 | NSCH_ERR | Key segment refers to schema, but schema not defined. |
| 433 | SSCH_ERR | Segment definition inconsistent with schema. |
| 445 | SDAT_ERR | Not enough data to assembly key. |
| 446 | BMOD_ERR | Invalid key mode. |
See c-tree Error Codes for a complete listing of valid c-tree error values.
Example
FILNO datno, keyno;
VRLEN newlen, varlen;
LONG cust_no;
TEXT buffer[512];
printf("\nEnter customer number: ");
scanf("%ld",&cust_no);
if (GetRecord(keyno,cust_no,buffer) /* read current record */
|| ReReadVRecord(datno,buffer,512))
printf("\nCould not read customer record.");
else {
newlen = update(buffer); /* make your changes to buffer */
if (ReWriteVRecord(datno,buffer,newlen))
printf("\nCould not rewrite customer record.");
else
printf("\nSuccessful update of customer record.");
}Limitations
After a call to ReWriteVRecord(), the current ISAM record is set to the new record. This may create a situation that you don’t expect when ReWriteVRecord() is used inside a loop that steps over the data in key sequential order. If the key value is changed during the update, the current ISAM record position will skip to the new position, which may be before or after the original position. To avoid this situation, reset the current ISAM record after ReWriteVRecord() using ResetRecord().
See also
GetRecord(), NextRecord(), ReReadVRecord(), ReadISAMVData(), GetVRecord(),
NextVRecord(), ResetRecord()