API base reference

1 Primary Details
2 Return Values and Result Indicators
3 Machine Independent Data
4 ISAM indexes
5 Open Modes
6 Search Modes
7 Lock Modes

The library provides two separate interface methods.

The base API uses allocated file descriptors (similar to the system fopen/fwrite calls) to manage isam files, and it will be this interface that is described here.

The wrap (CISAM™ standard) interface is covered here.

1 Primary Details

All modules which make core API calls should include isbase.h

In all of the following, isfd will be used to refer to an open isam file descriptor, as returned by isOpen or isBuild, and declared as:

  struct IsamFile *isfd;          /* the formal way */
  IsFile *isfd;                   /* typedef shortcut */

2 Return Values and Result Indicators

With the exception of isBuild, isOpen and a few others, the base will return a boolean ISTRUE or ISFALSE. ISTRUE and ISFALSE are defined in the isbase.h header as 1 and 0 respectively.

When ISFALSE is returned you will find the system or isam error code in isfd->iserrno, where isfd is an open file descriptor. ISAM error codes start at 500 (refer to ISERRBASE in [DISAM_INSTALL] if you need to change this) and are listed under error codes below. System error codes have their usual values for the target system.

If iserrno is less than 500 (ie a system error) isErrio( isfd ) (or isfd->iserrio) will provide a little more detail as to where and why, as shown under [Error Codes] below.

Please note the original value for ISERRBASE, while compatible with CISAM, is no longer high enough to encompass all the normal system errors, however if you are willing to deal with the confusion which may result, there should be no other harm in re-setting ISERRBASE to the original value of 100.

In situations where no file descriptor is available, such as when isBuild or isOpen fail, or after isClose, isErase or isRename, the call will return the error code in the global errno variable.

3 Machine Independent Data

The library includes the following series of calls to provide a means of generating data that will be portable to different machines, across the endian divide.

Use of these is only required if you need such portability, since the library will accept native formats without complaint.

 int ldInt( char *pad );
 int stInt( int value, char *pad );
 long ldLong( char *pad );
 int stLong( long value, char *pad );
 int stChar( char *pad, char *str, int len );
 int ldChar( char *pad, int len, char *str );
 double ldFloat( char *pad );
 int stFloat( double value, char *pad );
 double ldDbl( char *pad );
 int stDbl( double value, char *pad );
 int stFltNull( double value, char *pad, short *null );
 double ldFltNull( char *pad, short *null );
 int stDblNull( double value, char *pad, short *null );
 double ldDblNull( char *pad, short *null );

In all of the above, st identifies calls that will place a value in the specified location, which can then be retrieved by the matching ld call.

The Null suffix calls will load the variable passed (by address) in the last parameter with a boolean ISTRUE if the associated value is zero, or ISFALSE if not.

All pads referred to should be the size of the associated data type, with the exception of ldInt and stInt, which refer to a two byte integer, regardless of the native word size, and ldLong and stLong, which refer to four bytes.

These (cisam derived) function names are based on old world (16 bit native word size) realities, where int was 2 bytes (short) and long meant 4.

The Float and Double calls do not perform any actual data conversion, and are provided as a means of avoiding data alignment problems only.

The Int and Long calls will perform byte order reversal (sometimes referred to as swabbing) on platforms where the least significant byte is found at the beginning of the field.

ldInt and stInt operate on short (2 byte) integers, although the value and return are passed as int, which ought to be big enough in all models, including 16 bit.

Since the 64 bit model suddenly makes long twice as big as will fit, ldLong and stLong now operate on int32_t as defined in stdint.h. See Standard (C99) Integers for more.

4 ISAM indexes

ISAM indexes are defined/described by means of the keydesc structure.

The following is an example of the basic procedure, and describes an index that allows duplicates, has full compression, and consists of two fields - a machine independent integer taken from the first two bytes of the record, and a character string from the seventh through sixteenth bytes.

 struct keydesc key;

 key.k_flags = ISDUPS+ISCOMPRESS;        /* see index flags */
 key.k_nparts = 2;                       /* number of fields involved */
 key.k_part[0].kp_start = 0;             /* offset in data record */
 key.k_part[0].kp_leng = INTSIZE;        /* length */
 key.k_part[0].kp_type = INTTYPE;        /* type */
 key.k_part[1].kp_start = 7;             /* offset in data record */
 key.k_part[1].kp_leng = 10 * CHARSIZE;  /* length */
 key.k_part[1].kp_type = CHARTYPE;       /* type */

This structure is then passed to isBuild, isAddIndex, isStart, etc.

Index flag values - these apply to the index as a whole
  ISNODUPS     no duplicates permitted
  ISDUPS       duplicates permitted
  DCOMPRESS    compress duplicates
  LCOMPRESS    leading compression
  TCOMPRESS    trailing space compression
  COMPRESS     full compression
  TNULL        compress on zero instead of space in TCOMPRESS
Individual index component/part/field types
  CHARTYPE     array of bytes/characters
  INTTYPE      two byte (short) integer
  LONGTYPE     four byte (long) integer
  DOUBLETYPE   ieee double floating point
  FLOATTYPE    ieee single floating point
  MINTTYPE     machine (native) short
  MLONGTYPE    machine (native) long
  STRINGTYPE   null terminated string
  ISDESC       add to any above for descending order

It is generally advisable to provide some callable means of loading your key descriptions into a keydesc structure, or to provide some other means of easy access, since they will be needed for selecting indexes via isStart.

You will also need to exercise caution when using CHARTYPE fields as the library does not recognise null terminated strings. For example, if you're referring to a 10 byte wide character field, and it contains a seven byte string, a null terminator and 2 garbage bytes following the null, the library will build a key 10 bytes in length that includes the null and trailing garbage. This key might prove difficult to locate later.

The officially approved solution is to use the included stchar() and ldchar() calls, which will pad the string passed with spaces on store and replace the null terminator on load.

Note also that cisam standard trailing compression works on strings of trailing spaces, so the common practice of terminating strings with a zero (and optionally padding the remainder of the field with zeros) will result in inefficient operation when trailing compression is expected.

STRINGTYPE has been added, to extend the standard, and this causes terminated strings to be correctly indexed without extra padding.

TNULL has also been added, to trigger trailing compression on zero values, rather than spaces.

5 Open Modes

There are two different groups of open modes used by the isOpen and isBuild calls. The first group describes the operations which the current process will be allowed to perform, while the latter controls what forms of external access will be permitted.

Locking Method (mandatory)

  ISMANULOCK  record locks placed manually
  ISAUTOLOCK  record locks placed automatically on read
  ISEXCLLOCK  exclusive access to index and data
  ISRDONLY    read only - no locking

I/O Modes

  ISINPUT     open file for reading only (default)
  ISOUTPUT    open file for writing only
  ISINOUT     open file for both reading and writing

Variable Length - see Variable Length Records.

  ISVARLEN    variable length records - see varlen.ref
  ISVARCMP    RLE compressed varlen data
  ISNOCARE    open either fixed or variable length

Transaction Processing - see Transaction Processing.

  ISTRANS     transaction processing
  ISNOLOG     disable logging

Other Options

  ISMASKED    index masking option - see Index Masking
  ISSYNCWR    all writes flushed to disk before return

Please note that ISSYNCWR is only active for systems that permit O_SYNC in the file open call. This precludes most DOS flavoured systems.

6 Search Modes

all isRead operations act on the currently selected index.

  ISFIRST  select the first record in the index
  ISLAST   select the last record in the index
 
  ISEQUAL  search for and return the first exact match, or error
  ISGTEQ   search for first exact match, or next greater
  ISGREAT  search for the next greatest key in the index
 
  ISNEXT   skip to the next key in the index
  ISPREV   skip to the previous key in the index
 
  ISCURR   reread the current location.

ISNEXT and ISPREV behave differently when used in isRead immediately after in isStart call in that they will return the current rather than the next/previous record.

This is a feature, not a bug. The intention is to allow isStart to function as an initialisation call preceding a read next/previous loop, as in the following:

  isStart( isfd, &secondary_index, 0, NULL, ISFIRST );
    while( isRead( isfd, data_pointer, ISNEXT ) )
      display_data( data_pointer );

The above will read the contents of isfd from the top in secondary_index order.

7 Lock Modes

These are added to the search mode in isRead to lock or wait for the release of the selected record.

  ISLOCK   lock the selected record against external update
  ISWAIT   wait until the selected record has been released
  ISLCKW   wait for and unlock the selected record

ISLOCK will return an ELOCKED error if the selected record has been locked, but will still return the selected record image. this allows the process to read an externally locked record, but warns that updates will not be permitted.

ISWAIT and ISLCKW do no deadlock processing, and will wait forever, so applications should be coded appropriately.

The isLock, isUnLock, isRelease, isRelRec and isRelCurr group of functions provide further control over record locking, and you can also use ISEXCLLOCK to lock other processes out of a file completely.