DISAM Reference Files

    Reference files and History of DISAM.
  • upgrading from old disam
    upgrading from old disam
    the process of upgrading from older versions of disam should be as
    simple as relinking with the new library, but there are a few things
    that are different, and may need addressing.
    the header file
    the standard header file as distributed is named iswrap.h to avoid
    confusion with older versions and to differentiate from the alternate
    interface header, which is called isbase.h
    the simplest procedure is to replace the contents of your original
    disam.h with a copy of iswrap.h
    alternatively you might wish to create a new copy of disam.h which
    does nothing more than include either iswrap.h or a renamed copy of
    your old disam (or cisam) header file. this would permit you to
    easily switch back and forth until you are comfortable with the new
    the trouble with isfdmap
    the old disam library used an array of pointers, called isfdmap, to
    manage it's table of open files. the new library uses an internally
    manipulated dynamic array that is not quite as easy to get to, and
    the associated file descriptor structure has changed significantly.
    analogs for the more common values are now available via the
    common dictionary access routines described in wrap.ref
    please let support know if anything important has been left out.
    virtual file open handling (ISVIRTUAL define in old isport.h)
    older versions of disam included a compile time option for
    virtual file handling support. this was activated by means
    of the ISVIRTUAL define in isport.h
    it was designed to allow the library to bypass the system
    file handle limit by swapping out (closing) inactive system
    handles to make room for new opens.
    because it is not possible to retain locks on closed system
    handles, this feature introduced a bug that created problems
    with index access concurrency, sometimes resulting in index
    at time of writing there appears to be no practical solution
    to this problem, and virtual file handling support has been
    discontinued in the current release.
    the current library provides an alternative solution (although
    not as extensive) via duplicate open handling. this feature,
    active by default, allows the library to multiplex the system
    handles used to access multiple opens on the same isam file.
    in other words - you can open the same isam file as often as
    you wish without the need for additional system handles.
    while this does not cover instances where the application
    needs to access large numbers of different isam files, it
    should be of value under the circumstances denoted.
    no specific configuration is needed to access this feature,
    as it is an integral part of standard operation.
    isindex( int isfd, int idx, int locate );
    the idx argument has been changed. under old disam, a value of zero
    was used to select the primary index, and a value equal to the max
    number of active indexes was used to select natural order.
    the new library uses a value of zero to denote natural order, and
    the active index count starts at one.
    if you prefer the original functionality, please refer to the pre-
    processor directive within the islocate code in stdread.c
    ispop( int isfd, int idx, long rec );
    the idx argument has been changed. under old disam, a value of zero
    was used to select the primary index, and a value equal to the max
    number of active indexes was used to select natural order.
    the new library uses a value of zero to denote natural order, and
    the active index count starts at one.
    if you prefer the original functionality, please refer to the pre-
    processor directive within the ispop code in stdread.c
    if you change ispop functionality you should make the same change
    in ispush.
    ispush( int isfd, int *idx, long *rec );
    since the new library no longer supports the isfdmap array, this call
    has been added to load the current index and record numbers for later
    use by ispop.
    isclone( int isfd, char *name );
    you can no longer specify the mode of the new file, nor list the
    indexes to be copied. if this is a problem to you please let the
    support department know - the option was dropped because it was felt
    that it had limited use and the associated varargs processing caused
    an amount of difficulty in porting.
    the current version copies all indexes by default, and the open mode
    of the returned handle will be the same as for the original file.
    iscopy( int isfd, char *name );
    iscopy no longer requires that you pass a buffer to assist in the
    copying process, and the extraneous flags argument has been dropped
    because it was never used.
    isgetmode( int isfd, int *mode );
    this routine loads the open mode value into the mode pointer passed
    ISAUTOLOCK behaviour
    Disam by default release automatic record locks only on a subsequent
    read. For older D-ISAM v3.x behaviour set isconfig.h D3XAUTOLOCK 
    to 1 to enable automatic release on read, update or delete
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • upgrading from cisam
    upgrading from cisam 
    the process of upgrading from cisam should be as simple as relinking
    with the new library, but there are a few things that you should know
    the header file
    isam.h is cisam's standard header file, ours is called iswrap.h
    there are three basic alternatives:
    1. modify your application code to include iswrap.h
    2. replace the contents of isam.h with a copy of iswrap.h
    3. create a new copy of isam.h which does nothing more than include
    either iswrap.h or a renamed copy of isam.h. this would permit
    you to easily switch back and forth until you are comfortable with
    the new library.
    what happens when you change the current key on rewrites
    the best way to explain this is by example. assume you have a file
    containing the following records: AAA, BBB, CCC, EEE, and that the
    current index is based on these values.
    under cisam, if AAA was the current record and you were to change
    it's contents to DDD and rewrite, an isread or isstart with a mode
    of ISNEXT would set the current to EEE.
    this can be somewhat problematic if you are doing a read next loop
    through your file, so we have arbitrarily adjusted this behaviour
    to ensure that the next record found will follow the current as set
    BEFORE the rewrite.
    this means that, given the above example, BBB would become current
    on an isread or isstart with a mode of ISNEXT.
    the same (in reverse) is true when reading backwards through the
    file with a mode if ISPREV.
    we currently consider this behaviour to be an enhancement over the
    cisam standard, but would be happy to provide true cisam operation
    if anyone should ask for it. please contact the support department
    if this is important to you.
    cisam autolock / nowait 
    for cisam compatible nowait on open and automatic record locks set
    C7NOWAIT to 1 in isconfig.h
    cisam version 5.0 through 7.1 locking concurrency
    for cisam version 5.0 through 7.1 locking concurrency when running
    against cisam executables set C7LOCKING to 1 in isconfig.h.
    keep in mind that exectuables compiled with C7LOCKING set to 1
    will no longer run concurrent with executables compiled for standard
    disam locking.
    cisam version 7.2x locking concurrency
    same as above, except C7LOCKING should be set to 2
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • base library reference
    base library reference --------------------------------------------------------------------- the library provides two separate interface methods. the base code uses allocated file descriptors ( similar to fopen/fwrite etc ) to manage isam files, and it will be this interface that is described here. the differences between the base and the wrapper interfaces is covered in wrap.ref --------------------------------------------------------------------- primary details --------------------------------------------------------------------- all modules which make base library 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 */ --------------------------------------------------------------------- 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 100 (refer to ISERRBASE in install.ref 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 100 (ie a system error) isfd->iserrio will provide a little more detail as to where and why, as listed under errio codes below. 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. --------------------------------------------------------------------- IsFile *isBuild( char *name, int dlen, int mlen, IsKdsc *key, int mode ); --------------------------------------------------------------------- name: [path]name of file to be created dlen: length of data record in bytes mlen: if ISVARLEN then max record length else ignored key: primary index description, see isam indexes mode: see open modes return: allocated file descriptor or NULL note: if successful, isBuild will return an isam file descriptor open in the specified mode and ready for use. a NULL pointer is returned on failure and the error code will be found in the global errno variable. refer to varlen.ref for more details regarding ISVARLEN --------------------------------------------------------------------- IsFile *isOpen( char *name, int mode ); --------------------------------------------------------------------- name: [path]name of an existing isam file mode: see open modes return: allocated file descriptor or NULL note: the file name must be specified without the .dat or .idx extension, and must be less than 251 bytes in length. the current index will be set to the primary. a NULL pointer is returned on failure and the error code will be found in the global errno variable. --------------------------------------------------------------------- int isCleanUp( void ) --------------------------------------------------------------------- note: this routine will close all currently open isam files and release all allocated global memory. only available if the base library was compiled with the ISADMIN feature activated. --------------------------------------------------------------------- IsFile *isLockCheck( IsFile *isfd, int mode ); --------------------------------------------------------------------- isfd: isam file descriptor flag: 0: off 1:on note: a flag value of 1 will cause the library to fail on update or delete if the record in question has not been successfully locked prior to the operation. the iserrno value returned in this instance is ENOCURR. --------------------------------------------------------------------- IsFile *isSetMode( IsFile *isfd, int mode ); --------------------------------------------------------------------- isfd: isam file descriptor mode: either ISMANULOCK or ISAUTOLOCK note: this routine can be used to switch the designated file between manual and automatic locking modes. when switching from automatic to manual, the current record, if locked, will be released. future plans include the ability to switch to/from exclusive lock as well, but at present an attempt to do so will result in an EBADARG error. --------------------------------------------------------------------- IsFile *isClose( IsFile *isfd ); --------------------------------------------------------------------- isfd: isam file descriptor note: isClose drops all locks and releases all allocated memory. isClose will return FALSE on failure and the error code will be found in the global errno variable. --------------------------------------------------------------------- int isAddIndex( IsFile *isfd, IsKdsc *key ); --------------------------------------------------------------------- isfd: isam file descriptor key: description of secondary index to add, see isam indexes note: when adding an index to a populated file, isAddIndex will load the new index with keys for all the existing data records. in the case of larger files this could take a while.. isAddIndex will attempt to place an exclusive lock on the isam file for the duration of the update (assuming you have not done so already) and will fail if any other process already has the file open. --------------------------------------------------------------------- int isDelIndex( IsFile *isfd, IsKdsc *key ); --------------------------------------------------------------------- isfd: isam file descriptor key: description of secondary index to delete, see isam indexes note: when deleting an index from a populated file, isDelIndex will purge the accumulated keys. in the case of larger files this could take a while, but will be significantly faster than the isAddIndex call. isDelIndex will attempt to place an exclusive lock on the isam file for the duration of the update (assuming you have not done so already) and will fail if any other process already has the file open. --------------------------------------------------------------------- IsFile *isCluster( IsFile *isfd, IsKdsc *key ); --------------------------------------------------------------------- isfd: isam file descriptor key: description of index to cluster on note: the file must be open in exclusive mode this routine makes use of a temporary file, created in the same directory as the original. all active data records will be transferred to the temp file in the index order specified, and all indexes will be packed as efficiently as possible. if successful, isCluster will return a new file descriptor, opened in the same format as the original, which will be abandoned. a NULL pointer will be returned on error, and the original descriptor and file will be left intact. be warned that this call may take some time to run if the file in question is large. --------------------------------------------------------------------- int isErase( char *name ); --------------------------------------------------------------------- name: [path]name of an existing isam file to be physically removed. note: isErase will not remove files that are currently in use by other processes. the error code will be found in errno on failure. --------------------------------------------------------------------- int isRename( char *old, char *new ); --------------------------------------------------------------------- old: original [path]name of an existing isam file new: new [path]name of isam file note: isRename will not rename files that are currently in use by other processes. isRename can be used to move an isam file from one directory to another, but not to a different drive or device. the error code will be found in errno on failure. --------------------------------------------------------------------- int isStart( IsFile *isfd, IsKdsc *kdsc, int len, char *data, int mode ); --------------------------------------------------------------------- isfd: isam file descriptor kdsc: description of index to be selected or NULL to retain the current index len: partial length of key, or 0 for full data: data record pointer if needed for search mode, or NULL mode: see search modes note: this routine has multiple purposes. if kdsc is passed then the index described will become current. if length is non zero then isStart will set a partial key length for the selected index, and will only consider the first len bytes of the key during subsequent searches. this will remain in effect until the next isStart call. the selected location in the index will be flagged as a start point, which means that the next call to isRead, if made with a search mode of ISNEXT or ISPREV, will return the current record, rather than the actual next or previous. this is often useful for initialising next or previous read loops. after a successful isStart call, isfd->isrecnum will be set to the current record number. --------------------------------------------------------------------- int isRead( IsFile *isfd, char *data, int mode ); --------------------------------------------------------------------- isfd: isam file descriptor data: pointer to data buffer to be loaded mode: search mode plus optional lock mode note: if successful isfd->isrecnum will be set to the current record number. when isRead is called with ISLOCK, and the record requested is currently locked by another process, isRead will return ISFALSE with an iserrno value of ELOCKED but will still have read the requested record into the data buffer. --------------------------------------------------------------------- int isIndex( IsFile *isfd, int index ); --------------------------------------------------------------------- isfd: isam file descriptor index: index number to select note: isIndex is used to select indexes by number. if index is zero then natural order will be selected, otherwise indexes are numbered starting at one for the primary index. isIndex retains a current record pointer for each index. after selection the current pointer will be at the record selected when the index was last used. --------------------------------------------------------------------- int isGoto( IsFile *isfd, long recnum ); --------------------------------------------------------------------- isfd: isam file descriptor recnum: an existing active record number note: this call will locate the specified record in the current index, making it the current index location. if successful, the specified record image will be found in isam->data. --------------------------------------------------------------------- int isData( IsFile *isfd, char *data, long recnum ); --------------------------------------------------------------------- isfd: isam file descriptor data: pointer to data buffer to be loaded recnum: an existing active record number note: isData performs a direct read on the data file, and does not disturb the current index pointer, and does not check for record locks. it will return ENOREC if the record requested does not exist or has been deleted. isData is provided primarily as a means of accessing data records in as an efficient a manner as possible. --------------------------------------------------------------------- int isWrite( IsFile *isfd, char *data ); --------------------------------------------------------------------- isfd: isam file descriptor data: pointer to data record to be written note: if successful this call will add the data record to the data file and create an appropriate key in all indexes. --------------------------------------------------------------------- int isWrLock( IsFile *isfd, char *data ); --------------------------------------------------------------------- note: as for isWrite, but the resultant data record will be locked on successful return. --------------------------------------------------------------------- int isWrCurr( IsFile *isfd, char *data ); --------------------------------------------------------------------- note: as for isWrite, but the current pointer in the current index will be set to the record just written. --------------------------------------------------------------------- int isDelete( IsFile *isfd, char *data ); --------------------------------------------------------------------- isfd: isam file descriptor data: data record to be deleted note: the record image passed is expected to contain enough data to cover the fields required by the primary index. if the primary index allows duplicates this call will fail, since isDelete has no means of determining exactly which record you are referring to. the original data image can be found in isfd->data on return. --------------------------------------------------------------------- int isDelCurr( IsFile *isfd ); --------------------------------------------------------------------- isfd: isam file descriptor note: this call will delete the currently selected record. the original data image can be found in isfd->data on return. --------------------------------------------------------------------- int isDelRec( IsFile *isfd, long recnum ); --------------------------------------------------------------------- isfd: isam file descriptor recnum: record number to be deleted note: the original data image can be found in isfd->data on return. --------------------------------------------------------------------- int isRewrite( IsFile *isfd, char *data ); --------------------------------------------------------------------- isfd: isam file descriptor data: data image to be updated note: the record to be updated is determined by the contents of the primary index fields as found in the data image passed. if the primary index allows duplicates this call will fail. the original data image can be found in isfd->data on return. --------------------------------------------------------------------- int isRewCurr( IsFile *isfd, char *data ); --------------------------------------------------------------------- isfd: isam file descriptor data: data record to be updated - the contents of the current record in the data file will be replaced with the image passed. note: the original data image can be found in isfd->data on return --------------------------------------------------------------------- int isRewRec( IsFile *isfd, long recnum, char *data ); --------------------------------------------------------------------- isfd: isam file descriptor recnum: record number to be replaced data: data image with which recnum is to be replaced. note: the original data image can be found in isfd->data on return --------------------------------------------------------------------- int isRewNxt( IsFile *isfd, char *data ); --------------------------------------------------------------------- isfd: isam file descriptor data: data record to be updated - the contents of the current record in the data file will be replaced with the image passed. note: isRewNxt first sets the current pointer to the next record in the current index before updating the original current record. it is useful in situations where the update would place the new record between the original current and next keys in the index. on successful return the application can then read current to obtain the record that was next in the sequence before the update was performed. an error code of EENDFILE on an unsuccessful return indicates that the update was successful and isRewNxt has reached the end of the file. any other error code indicates a failure in the update operation. the original data image can be found in isfd->data on return --------------------------------------------------------------------- int isLock( IsFile *isfd ); --------------------------------------------------------------------- isfd: isam file descriptor note: this call will lock all records in the file against update by any process other than the current, or return ELOCKED if this is not possible. --------------------------------------------------------------------- int isUnLock( IsFile *isfd ); --------------------------------------------------------------------- isfd: isam file descriptor note: reverses the action of isLock --------------------------------------------------------------------- int isRelease( IsFile *isfd ); --------------------------------------------------------------------- isfd: isam file descriptor note: this call will release any records that have been manually or automatically locked by the current process. --------------------------------------------------------------------- int isRelRec( IsFile *isfd, long recnum ); --------------------------------------------------------------------- isfd: isam file descriptor recnum: record number to be unlocked --------------------------------------------------------------------- int isRelCurr( IsFile *isfd ); --------------------------------------------------------------------- isfd: isam file descriptor note: unlock the currently selected record --------------------------------------------------------------------- int isSetUnique( IsFile *isfd, long value ); --------------------------------------------------------------------- isfd: isam file descriptor value: new unique value starting point note: this will set the value returned by the next call to isUniqueID. --------------------------------------------------------------------- int isUniqueId( IsFile *isfd, long *value ); --------------------------------------------------------------------- isfd: isam file descriptor value: pointer to variable to receive value note: the value returned is guaranteed unique for the current file. --------------------------------------------------------------------- int isIndexInfo( IsFile *isfd, IsKdsc *kdsc, int idx ); --------------------------------------------------------------------- isfd: isam file descriptor kdsc: pointer to dictinfo or key description structure idx: zero for dictinfo, otherwise index number note: this call serves two somewhat different purposes. if idx is zero, then it's actually expecting you to pass a pointer to a dictinfo structure, which will then be loaded with information about the current file. refer to isIsamInfo below for a somewhat cleaner method. if idx is non zero then isIndexInfo will return the specified key description, where a value of 1 represents the primary, followed by each successive index in the file. --------------------------------------------------------------------- int isIsamInfo( IsFile *isfd, struct dictinfo *dict ); --------------------------------------------------------------------- isfd: isam file descriptor dict: pointer to dictinfo structure note: this call will return information about the specified file in the structure passed. the values available are: short di_nkeys; /* number of indexes */ short di_recsize; /* data record length */ short di_idxsize; /* index record block size */ long di_nrecords; /* current record count */ --------------------------------------------------------------------- int isCheckData( IsFile *isfd ); --------------------------------------------------------------------- isfd: isam file descriptor note: this routine checks the data file and data file free list for errors, and will return a value with the following bits set in accordance with it's findings: IC_DATREAD 0 /* data file read error */ IC_BADDATA 1 /* data record corrupt */ IC_DATFREE 2 /* data free list is corrupt */ if the return value is zero then no errors were detected. --------------------------------------------------------------------- int isCheckIndex( IsFile *isfd, int idx ); --------------------------------------------------------------------- isfd: isam file descriptor int: key id number, where 1 represents the primary note: this routine checks the specified index for errors, and will return a value with the following bits set in accordance with it's findings: IC_IDXREAD 3 /* index file read error */ IC_ORDER 4 /* key out of order */ IC_COUNT 5 /* index count mismatch */ IC_BADMAGIC 6 /* bad index node magic number */ if the return value is zero then no errors were detected. --------------------------------------------------------------------- int isCheckVarlen( IsFile *isam, struct isVarStat *stats ); --------------------------------------------------------------------- isfd: isam file descriptor stats: variable length statistics structure, defined in ischeck.h, or NULL to ignore same. note: this routine checks the variable length storage system for errors, and will return a value with the following bits set in accordance with it's findings: IC_VLMISFILE 12 /* node misfiled in hash table */ IC_VLHASHLINK 13 /* mangled link in hash list */ IC_VLMISSING 14 /* nodes missing or unaccounted */ IC_VLBADDATA 15 /* data length mismatch */ it will also optionally load the following fields in stats: hashcount; /* number of nodes held in hashtable */ hashspace; /* total bytes free space in same */ fullcount; /* number of nodes not in hashtable */ fullspace; /* total (unusable) space in same */ filecount; /* total number of storage nodes in use */ filespace; /* total free space for the file */ --------------------------------------------------------------------- machine independent data --------------------------------------------------------------------- the library includes the following series of calls to provide a means of generating data that will be transportable to different machines. use of these is only required if you require 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/stInt, which refer to a two byte integer, regardless of the native word size. note that the float and double calls do not perform any actual data conversion, and are provided as a means of avoiding data alignment problems. 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. note also that ldint and stint operate on short (2 byte) integers, although the value and return are passed in the natural word size. --------------------------------------------------------------------- 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, or isStart. 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 nulls in TCOMPRESS individual index component/part/field types CHARTYPE 0 array of bytes/characters INTTYPE 1 two byte (short) integer LONGTYPE 2 four byte (long) integer DOUBLETYPE 3 ieee double floating point FLOATTYPE 4 ieee single floating point MINTTYPE 5 machine (native) short MLONGTYPE 6 machine (native) long ISDESC 0x80 add to individual parts 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. in other words, 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 trailing compression operates on strings of trailing spaces, so the fairly common practice of padding the remainder of the field with nulls could result in inefficient operation where trailing compression is expected. --------------------------------------------------------------------- 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. you must chose one from each list. ISINPUT open file for reading only ISOUTPUT open file for writing only ISINOUT open file for both reading and writing ISSYNCWR all writes flushed to disk before return ISMANULOCK record locks placed manually ISAUTOLOCK record locks placed automatically on read ISEXCLLOCK exclusive access to index and data ISRDONLY read only - no locking ISVARLEN variable length records - see varlen.ref ISVARCMP RLE compressed varlen data ISNOCARE open either fixed or variable length ISMASKED index masking option - see mask.ref ISTRANS transaction processing - see trans.ref ISNOLOG disable logging - see trans.ref NOTE: ISSYNCWR is only active for systems that permit O_SYNC in the file open call. this precludes most DOS flavoured systems. --------------------------------------------------------------------- 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. note 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. --------------------------------------------------------------------- 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. --------------------------------------------------------------------- error codes --------------------------------------------------------------------- in addition to the standard operating system error codes, the library will return the following values in isfd->iserrno where appropriate. EDUPL 100 illegal duplicate ENOTOPEN 101 file not open EBADARG 102 illegal argument EBADKEY 103 illegal key description EBADFILE 105 isam file is corrupt ENOTEXCL 106 can't get exclusive access ELOCKED 107 record is locked EKEXISTS 108 index already defined EENDFILE 110 start or end file reached ENOREC 111 record not found ENOCURR 112 no current record EFLOCKED 113 file is locked EFNAME 114 file name is too long EBADMEM 116 can't allocate memory ENOPRIM 127 no primary key when the library returns a system error code it will also load isfd->iserrio with the sum of the following two groups of values: IO_IDX 0x01 index file IO_DAT 0x02 data file IO_OPEN 0x10 while opening IO_CREA 0x20 while creating IO_SEEK 0x30 while seeking IO_READ 0x40 while reading IO_WRIT 0x50 while writing IO_LOCK 0x60 while locking --------------------------------------------------------------------- Worldwide Copyright (c) Byte Designs Ltd (2009-2014) ---------------------------------------------------------------------
  • answers to frequently asked questions
    answers to frequently asked questions
    Q: i'm sure i have compiled the library properly, and i am sure i
    have the right linker commands, but i keep getting unresolved
    references to base library (isUppperCase) functions..
    A: if you're linking wrapper (islowercase) calls then it is possible
    your linker resolves references canonically - in a single pass
    through the listed libraries. linker objects should be listed
    in order of precedence - object module(s), wrapper lib, base lib.
    Q: everything appears to compile normally, but i sometimes get
    "FATAL iscomp.c(55)" when trying to read or update my files
    A: your compiler is probably defaulting char types to unsigned -
    you will need to set your compiler to produce signed char types
    by default, and rebuild the library.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • suggestions, pitfalls and defenses
    suggestions, pitfalls and defenses
    long duplicate chains
    if you are using keys that will result in a large number of duplicate
    records, you should be warned that deletes and rewrites within these
    can become painfully slow. this is due to the fact that, when you
    request an update or delete, the library is forced to start at the
    beginning of the chain and read sequentially through each looking
    for the record number you are referring to.
    the isam standard does not currently appear to offer a solution to
    this problem, but if anyone has any suggestions you can be sure we'll
    be interested.
    if this is a concern, specifically during long update runs that will
    be doing a large amount of duplicate key changes, you might wish to
    consider deleting the offending indexes before you start, and adding
    them again after the run is complete. this is potentially dangerous,
    of course, but the advantages will be significantly faster processing
    times and better balanced trees on completion.
    long duplicate chains are not a problem when writing or reading, since
    writes get tacked onto the end of the chain, and reads are sequential
    by definition.
    duplicate open files
    isam allows you to open the same file many times within a given
    process. cisam and older disam also allowed some rather dangerous
    operations on these files. for instance:
    fd = build file
    erase file
    write records to fd
    close file
    none of the above will return any errors, but you won't be able
    to open the file again because it has been erased from the file
    system - everything written has been discarded.
    the ISDUPLOCKS option in isconfig.h, when set to a value of one,
    will prevent the library from erasing or renaming files which are
    already open in the current process.
    when ISDUPLOCKS is zero this will not be enforced, and it is up to
    the application to apply the appropriate degree of caution.
    due to fixed index file format specifications, a single char is used
    to store the number of leading compressed bytes and another to store
    the number of trailing compressed bytes. this forces a limitation
    of 255 bytes ( max unsigned char ) for compressed key size,
    regardless of ISMAXKEY setting to ensure full compression of all
    trailing spaces or nulls for TCOMPRESS, and all leading duplicate
    characters for LCOMPRESS.
    allows compressed key sizes larger than 255 bytes, but will only
    permit partial compression on leading and trailing characters.
    a maximum of 255 leading duplicate characters, and 255 trailing 
    spaces or nulls will be compressed.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • audit trail mechanism
    audit trail mechanism
    ISAUDIT settings in isconfig.h
    0 - no audit functionality
    1 - audit writes, updates and deletes
    2 - audit writes only
    3 - audit deletes only
    4 - audit updates only
    5 - audit writes and deletes
    6 - audit writes and updates
    7 - audit deletes and updates
    int isAudit( IsFile *isfd, char *pad, int mode );
    isfd isam file descriptor
    pad pointer to pad, usage dependent on mode
    mode operation mode, see below
    note mode is one of the following:
    AUDSTART start recording
    AUDSTOP stop recording
    AUDSETNAME name and path of audit file
    AUDGETNAME return current name and path
    AUDINFO recording status
    start and stop do not refer to pad, setname and getname will
    store and retrieve (respectively) a null terminated string
    from or to pad. audinfo will set the first byte of pad to
    a value of zero (stopped) or one (active).
    there are a couple of obvious caveats:
    do not start recording until you have set a file name.
    be careful not to use the same audit file for more than
    one file.
    the filename cannot be longer than 64 characters.
    isAudit generally returns an EBADARG error if you do some-
    thing wrong.
    audit trail support is activated by setting ISAUDIT to a value of 1
    in isconfig.h before compiling the library.
    notes and caveats
    the audit trail is essentially a more streamlined alternative to the
    full featured transaction processing option. only updates to the file
    are tracked, and the processing overhead is less. while there is no
    harm in having both options active in your library at the same time,
    it would be somewhat redundant to have both in use on the same file.
    two things to be aware of:
    the audit trail impacts the overall efficiency of the library - if
    you do not plan to use it, you would probably be best advised to leave
    it inactive.
    once a file has been designated as having an audit trail, and even if
    the trail is currently in the inactive state (AUDSTOP'ed), updates to
    the file will be slower because the design (not our fault, talk to the
    cisam people) requires that the status be checked each time the file
    is updated by another process. this is only the case when the file is
    open by multiple processes.
    this information presented mostly for reference - the actual impact
    is reportedly quite minimal under all platforms tested.
    the format of the audit trail consists of a header record followed by
    a data image, repeated sequentially. in the case of variable length
    files, an additional 2 bytes are included to give the record length.
    all values are stored in machine independent (ldint/ldlong) format.
    struct audhead /* audit record header format */
    char au_type[2]; /* record type (aa/dd/rr/ww) */
    char au_time[4]; /* date and time */
    char au_procid[2]; /* process id */
    char au_userid[2]; /* user id */
    char au_recnum[4]; /* record number */
    char au_reclen[2]; /* record length if variable */
    #define AUDHEADSIZE 14 /* audit header length */
    #define VAUDHEADSIZE 16 /* if variable length */
    type codes are translated as follows:
    aa - record added to file
    dd - record deleted from file
    rr - record image before rewriting
    ww - record image after rewriting
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • large files - 64bit implementation
    large files - 64bit implementation
    as of version 6.12 we have attempted to implement 64bit support for
    large files. todate most unix platforms as well as NT are supported. 
    as more systems develop 64bit capability we will add the same support for
    disam. we have attempted to make switching to 64bit support as
    simple as setting a compile time flag..ISHUGE found in isconfig.h. you
    may need to redefine the ISHUGE related settings for OFFT and UOFFT,
    depending on how your OS handles large file support and lseek offsets.
    second level support can be found in isbase.h where platform specific
    functions such as lseek64 are defined. 
    please let us know if you require 64bit functionality for your platform,
    or if you successfully manage to get 64bit working on any platform not
    currently setup.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • custom key types
    custom key types
    the following steps are required to add your own custom keys:
    set ISCUSTOM to 1 in isconfig.h
    set ISCUSTKEYS to 1 in base/iscustom.h, and add defines for the key
    type(s) and size(s) you require.
    add a case for each key type to the switch statement in isCustCmp()
    in base/iscustom.c. each case should set retc to a negative value
    if key one is less than key two, positive if greater, and zero if
    remove the sample key types unless you need them.
    include iscustom in your makefile.
    NOTE: be careful, if/when applying updates, that you do not overwrite
    any changes you have made to the base files.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • design concepts
    design concepts
    in order to facilitate thread safe programming, the core library has
    been developed to use isam file descriptor structures, rather than
    the standard integral handle concept. the external function calls
    are named after the original function names, but use capital letters
    to keep them separate, as in isOpen rather than isopen. the status
    and information globals, such is iserrno and iserrio, have been
    eliminated, and each file descriptor now carries it's own copy. 
    the standard (lower case) calls are provided as an optional wrapper
    layer which maintains a dictionary of descriptors to allow mapping
    via the standard integer file handles. it also defines and passes
    the standard global variables.
    all public library function names start with 'is' and use capital
    letters to distinguish keywords.
    all structure definitions and typedefs start with a capital letter,
    and use the same capitalisation rules to distinguish keywords.
    the posix standard system calls are wrapped in functions prefixed
    by is and an underscore.
    local support routines in each module are named in lowercase.
    macro definitions are all capitals.
    virtually all entry and internal functions return TRUE on success
    and FALSE on failure. TRUE is defined as 1, FALSE is 0.
    the tree node buffering system operates by handing node images which
    are no longer part of the current path to a storage mechanism. each
    index carries it's own path list and storage array.
    a single linked list holds the current path and facilitates traversal
    without having to move data around. the node description structures,
    which contain current status information and a copy of the node disk
    image, are are passed to and from the path list and the buffer array
    as pointers.
    the buffer cache is currently optimised on a last in first out basis.
    it might be worthwhile to consider optimising this further by giving
    a degree of precedence to nodes from lower levels in the tree, on the
    assumption that these will take more hits.
    buffers are flagged invalid whenever the index file header transaction
    count has been changed by another process, and will be refreshed as
    at some point in the future, at the cost of cisam concurrency, it may
    be worthwhile to consider designing a more detailed currency control
    which would maintain separate transaction counts for each index, and
    perhaps additional counts for the index and data free lists, variable
    length storage space, and so on.
    the same buffering system provides a failsafe error recovery method
    in which updated node images are flagged invalid on error, which then
    results in a forced refresh before the image can be used again. this
    method allows for optimistic updates, eliminating the need to check
    first before embarking on potentially illegal updates. see error
    handling below for more details.
    uncompressed (flat) versus compressed indexes
    for the dual purpose of keeping the code cleaner and to improve
    performance, the index handling routines are split into separate
    functions where the associated handling is markedly different.
    flat indexes, in general, can be operated on mathematically, lend
    themselves to shell searches, and permit the current key value to
    be a simple pointer into the node image.
    compressed indexes require that each node be searched in a linear
    fashion, building the key image in an allocated buffer en route,
    and generally require a fair amount more processing to operate.
    the index handing and manipulation modules - isnode, isgrow and
    isprune - all adhere to this standard. the decision as to which
    handling method to apply is made at the top level, eliminating the
    need for myriad if-then-else tests during processing.
    error handling
    the new library deals with errors via setjmp/longjmp. each external
    entry point is responsible for initialising a jump buffer and mode
    flag in the file descriptor. when an error is detected the thread
    is passed to an error handling routine which sets the error codes
    and drops the index locks before returning control the entry call.
    the error handling routine is also responsible for clearing the
    update buffers when triggered in write mode.
    the nature of setjmp/longjmp means that it appears to the calling
    function as if the ISFAIL call, made initially to initialise the
    jump buffer, had returned TRUE.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • disam client/server reference
    disam client/server reference
    to access isam filesets on remote machines set ISCLIENT in isconfig.h to 1
    prior to compiling the Disam library. link your application code on the
    client to the Disam library as well as to the platforms socket library/
    libraries (SCO-libsocket.a, SUN-libsocket.a and libnsl.a, NT-wsock32.lib).
    before executing the application you must start the server program,
    risamsrv on your server machine. this program may be run in foreground or 
    back ground mode. risamsrv - listens for requests from the client and 
    excutes the isam calls passed from the client program on the isam files
    on the server machine.
    ** important: the risamsrv executable expects ISMAXPARTS in isconfig.h
    to be set to the default setting of 20. If you've compiled your client
    Disam library with a setting other than 20..please contact Byte Designs
    so we may customize risamsrv to suit your client library configuration.
    there are two ways to let disam know where the remote files exist:
    i) specify the ip of the remote machine as well as the full path
    of the filename when opening the isam fileset.
    e.g. strcpy( filename, "//" );
    fd = isopen( filename, ISINOUT + ISMANULOCK );
    ii) set the environment variable on the client machine to the ip address
    of the server machine where the isam files reside:
    Disam determines if a fileset is local or remote by checking for the prefix
    of "//" on unix or "\" on dos, win, nt in the filename. if mutiple slashes
    prefix a filename without an ip address..Disam expects RISAMHOST to be set.
    if no multiple slashes prefix a filename/path Disam defaults to local path/
    as well as the standard group of isam calls, Disam also support remote
    system calls such as open/sopen, read, write, lseek etc..these are called
    be prefixing the call with r for example rread()/rwrite().
    Disam client/server code defaults the remote port number to 5002. If this
    port number is already in use you may bypass the default by setting the 
    environment variable RISAMPORT to the port number you wish to use.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • dcheck
    dcheck - isam file integrity check/repair utility
    usage - dcheck [-hifbB] [...]
    options - h - display isam header information only
    i - just check indexes, ignore data file
    f - fix corrupt indexes
    b - rebuild all indexes
    B - rebuild specific index
    the option string, preceded by a dash, can be placed anywhere on the
    command line. all options must be specified in one string, and all
    options apply to all files specified.
    the -B option is a little different. it can be specified multiple
    times, and each occurance must be followed by an index number. a
    value of 1 denotes the primary index, 2 the next, etc. you cannot
    specify -B on multiple files.
    dcheck is not interactive, and will ask no questions, so it can be
    safely used in batch and script files without operator intervention.
    dcheck has been designed to run co-operatively ( unless -f or -b
    specified ) on files in active use, but note that other processes
    will be blocked for the duration of some of the check cycles.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2013)
  • dpack
    dpack - isam file pack/rebuild utility
    usage - dpack [...]
    dpack takes a list of one or more isam files and will rebuild each
    in turn. it works by building a temporary copy of the original file
    and copying all active data records to it, then deleting the original
    and renaming the working copy.
    the temporary file is created in the same directory as the original
    and is named dpnnnnn, where nnnnn is the current process id.
    you must ensure that you have write permission on the data directory
    and that there is enough room for dpack to build the working copy.
    dpack will fail if it cannot obtain an exclusive lock on the file.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • dreport (new)
    dreport - create .xml, .csv or .txt output from isam data
    usage - dreport 
    dreport takes an .xml format input file that provides the report details,
    see export/samples directory for sample input files, and produces output based
    on the input file specifications. dreport allows for isam file cross reference,
    and filtering of data.
    sample tests provided in the export directory.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • dschema (new)
    dschema - utility to load, store or dump schema file to/from isam file
    usage - dschema [-dDSr] 
    where d - dump schema layout from isamfile to stdout
    D - dump schema layout to path
    S - store schemafile to isamfile
    r - remove schema layout from isamfile
    dschema can be used to store a schema layout for an isam file to the isam file
    where it can be used to report on data from the isamfile via dreport or simply
    as a reference to the layout of the isamfile.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • dsplit
    dpack - isam file split utility
    usage - dsplit [...]
    dpack takes an isam file and will split the original file into two
    smaller isamfiles, each with the same name as the original for the
    prefix but with a 1 and 2 appended to the original name.
    it works by building two temporary copies of the original file
    and copying half the active data records into filename1 and the
    second half into filename2. dsplit can be compiled to delete the 
    original fileset by adding a #define REMOVE to the code before compiling.
    the temporary files are created in the same directory as the original.
    you must ensure that you have write permission on the data directory
    and that there is enough room for dpack to build the working copies.
    dpack will fail if it cannot obtain an exclusive lock on the file.
    Worldwide Copyright (c) Byte Designs Ltd (2009)
  • dvlrebld (new)
    dvlrebld - variable length isam file conversion utility
    specifically for converting variable length isam files from
    old disam/c-isam standard to new disam v7.0 format - expects
    ISOLDVARLEN to be set to 0 in isconfig.h prior to compiling library
    and this utility.
    usage - dvlrebld 
    dvlrebld converts old disam/c-isam format variable length files to the new
    variable length format now used by disam. this new format overcomes the old
    record number limit of 16777216L previously imposed on varinfo and continuation
    node pointers when being stored in 3 character bytes.
    the temporary file is created in the same directory as the original
    and is named dpnnnnn, where nnnnn is the current process id.
    you must ensure that you have write permission on the data directory
    and that there is enough room for dvlrebld to build the working copy.
    dvlrebld will fail if it cannot obtain an exclusive lock on the file.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • dstats
    dstats - report library statistics - expiration date, compilation date
    and client limit
    usage - dstats
    dlist makes use of the isLibInfo() or islibinfo() functions to load
    and report some library statistics. dstats is only useful if it is
    recompiled and relinked when ever the library is recompiled, to ensure
    that the statistics reported are current.
    Worldwide Copyright (c) Byte Designs Ltd (2009)
  • expiration date
    expiration date
    a simple mechanism for setting an automatic
    expiration date in the library is provided by means of a define.
  • isconfig.h ISEXTENDED configuration setting
    isconfig.h ISEXTENDED configuration setting
    defining ISEXTENDED to 1 will ensure the global ispid will
    hold the id of the process blocking the lock attempt by the calling
    process - ISLOCKING 2 only.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • isread filtering
    isread filtering
    this feature is currently only available in the wrapper - please let
    the support department know if this is a problem to you.
    the isfilter() call provides a means of externally controlling which
    records are accessible via isread(). originally developed inhouse as
    a means of avoiding the work involved in updating inflexible older
    application code, it allows the programmer to register a routine that
    will be called, on a per file basis, to check if each record located
    by isread() is valid.
    isfilter( int isfd, int ( *filter )() );
    isfd isam file handle
    filter application defined filter routine
    note once a filter routine has been registered, it will be called
    automatically each time isread() locates a record().
    pass a NULL pointer for filter to deactivate.
    the application filter routine should be declared as:
    int myfilter( int isfd, char *data, int mode );
    isfd the associated isam file handle
    data data record pointer as passed to isread()
    mode the mode parameter passed to isread()
    if the filter routine returns a value of one, then isread() will
    return the record found.
    if the filter routine sets iserrno and returns a value of zero,
    then isread() will return the specified error to the application.
    if iserrno is not set, and the read mode is one of those listed
    below, isread() will attempt to read the next record as shown
    and, if successful, will call the filter routine again.
    ISFIRST read next
    ISLAST read previous
    ISNEXT read next
    ISPREV read previous
    ISGREAT read greater
    ISGTEQ read greater 
    isread() will return ENOREC if the original mode was either ISCURR
    or ISEQUAL.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • user info
    user info
    two functions
    int isUserInfo( struct IsamFile *isam, int mode, char *pad );
    int isuserinfo( int isfd, int mode, char *pad );
    where pad is a character array of size USERINFOSIZE.
    USERINFOSIZE is fixed at ten bytes and should not be changed.
    allow the application to store a fixed length ten byte info pad
    in the index header of any isam file.
    mode has two possible values
    ISINPUT load pad from index header
    ISOUTPUT write pad to index header
    these ten bytes are freely available to any application system
    that requires the ability to store additional information about
    a given isam file.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • installation
    the library is split into two sections - the base and the wrapper -
    as explained in source.ref. the base source is found in the base
    subdirectory, and the wrapper source in wrap. all public header
    files are in the head directory.
    if you plan to use only the base library then you can ignore both
    the wrap directory and head/iswrap.h
    if you are planning to use only the wrapped (cisam standard) calls
    then you should probably compile everything into one library and
    ignore head/isbase.h
    if you intend to use both flavours, then it might be an idea to
    build two separate libraries, but this is optional.
    note that if you plan to use the wrapper calls, or the transaction
    processing module, the base library MUST be compiled with ISADMIN
    before starting you will need to edit isconfig.h and adjust it as
    appropriate - refer to configuration below for details.
    NOTE: some compilers produce unsigned char types as the default.
    this must be changed - at least when compiling the base and
    wrapper modules - all char types must default to signed.
    this inconvenience will be corrected in future releases.
    your compiler may generate a number of warnings to the effect that
    certain lines of code have no effect, or that arguments are not used
    in some functions. this is an expected situation and is due to the
    fact that turning some options off will result in functions being
    nulled by means of empty ifdef declarations in some cases, or replaced
    by empty stubs in others.
    the source for the dcheck utility is located in the util directory
    and should be linked with the base library to produce an executable.
    documentation for same will be found in dcheck.ref. the same is
    true for the dpack and dlist utilities.
    the test directory contains a collection of benchmark utilities,
    documented in test.ref
    you will find a generic makefile in the make directory. to use the
    makefile, copy the contents of head, wrap and base into one directory,
    edit isconfig.h as explained below, edit the makefile and follow the
    the makefile should be compatible with most standard unix platforms,
    and should also be compatible with a fair number of the more standard
    dos, windows and os2 compilers, as well as the gnu make command.
    #define ISADMIN 1 /* global file administration */
    with this option active, the library will maintain an internal table
    of active isam file descriptors, reuse system file handles when more
    than one instance of the same isam file is opened, and include the
    isCleanUp call amongst the library entry points. admin is mandatory
    when the standard wrapper library or transaction processing are used,
    and definitely advisable if you plan to open more than one instance
    of the same file at any given time.
    #define ISAUDIT 1 /* 0:off 1:active */
    a value of one includes support for cisam standard audit trail
    logging, see audit.ref for details.
    #define ISLOGGING 1 /* 0:none 1:standard */
    a value of one includes support for cisam standard transaction
    logging and processing, together with a number of enhancements.
    see trans.ref for more details. NOTE - to use this option you
    must activate the ISADMIN feature. NOTE also that transaction
    processing is currently not supported under threads - this will
    be resolved in the near future.
    #define ISVARIABLE 0 /* 0:none 1:std 2:pack */
    a value of one includes support for variable length records in the
    standard cisam compatible configuration. a value of two provides
    a better hash table algorithm and finer granularity with regard to
    the use and reuse of slots in the variable length data storage nodes.
    both one and two include support for data compression. see varlen.ref
    for more details.
    #define ISOLDVARLEN 0 /* 0: new v7.0 format */
    /* 1: old disam/c-isam format */
    there was a limitation in the old disam/disam96/c-isam variable length
    in that the maximum record number that could be stored in the 3 char bytes
    allocated for storing varinfo and continuation node record numbers was 
    16777216L. this limit has been removed but requires that old files 
    are converted, see dvlrebld.ref via the dvlrebld utility prior to use.
    #define ISLOCKING 2 /* 0:none 1:old 2:new 3:lck */
    a value of zero will disable locking entirely, resulting in a single
    user version of the library. locking one enables the original cisam
    (prior to version 4) locking algorithm. locking two is the current
    (standard) method used by cisam versions 4 and greater, may also be
    faster on some platforms. locking three is compatible with the dos
    'third file' locking method, and is provided to allow 'lowest common
    denominator' NFS concurrency with dos based applications. locking
    one and three rely on the lockf() system call, and two requires fcntl().
    #define ISDUPLOCKS 1 /* honour locks in dup opens */
    cisam allows the same file to be opened more than once in EXCLLOCK
    mode within the same process. it also permits the same record to
    be locked more than one under different filehandles within the same
    process, not to mention that it is also legal to erase a file that
    is already open in the current process, after which point any data
    written to the file will evaporate. set this to zero for cisam
    compatible operation, but please be careful..
    #define ISDECLARE 1 /* include prototypes */
    if non zero then full ansi standard function prototyping is enabled.
    #define ISDATAVOID 0 /* void data pointers */
    cisam insists that all record pointers passed must be char type.
    if ISDATAVOID is set to one, they will be declared as type void
    which, under some compilers, will allow you to pass anything with-
    out warnings. this feature is compiler dependent.
    #define ISCUSTOM 0 /* custom key types */
    this option allows the addition of custom key types - refer to
    custkeys.ref for more details.
    #define ISBERKELY 0	 /* 0:memcpy() 1:bcopy() */
    a value of one uses the berkely memory handling functions bcopy()
    and bcmp() and covers for the absence of memset() internally. a
    value of zero uses the default memcpy(), memcmp() and memset()
    #define ISLONGID 0 /* allows for long pids */
    a value of 1 will override the C-ISAM / X/OPEN spec that forces
    short integer values to be stored in the transaction processing logfile
    and audit trail file for pids and uids. WARNING: do not set to 1 
    if you are expecting C-ISAM/X/OPEN concurrency or file compatibility
    or if the process ids returned from the systems getpid() function are
    short values.
    #define ISIDXBLK 1024 /* default index block size */
    the default index block size to be used when creating isam files.
    512 and 1024 are the usual standards. 512 is compatible with older
    versions of cisam, while 1024 seems to be most common value, and
    is compatible with current cisam files. 1024 will be enforced when
    building variable length files, but you can still use other values
    for your regular data.
    #define ISDUPLEN 4 /* default duplicate width */
    the width of the field used to store the duplicate sequence numbers
    in the index. a value of 4 will permit approximately 2000 million
    identical keys in any given index, while 2 imposes a limit of just
    over 32500. 4 is more expensive in terms of disk space, so you may
    wish to consider using 2 if this is important and you not intend to
    go over the limit. bear in mind that the limit applies to the max
    count of an individual identical key, not to the total number of
    duplicates in the index. 4 is compatible with current cisam, 2
    with older versions.
    #define ISMAXIDX 10 /* indexes per file */
    #define ISMAXPARTS 10 /* parts per key */
    #define ISMAXKEY 128 /* bytes per key */
    these should be fairly obvious, and refer to the number of indexes
    per file, the number of parts per index, and the total allowable byte
    count per index key. the value of ISMAXPARTS is also available via
    the standard NPARTS define.
    #define ISMAXBUF 20 /* buffers per index */
    this is actually a slight misnomer in that the root node is always
    buffered, so the resultant number of memory allocations will actually
    be one more than the number you specify here. one important caveat
    applies - you must specify a value that is at least twice the expected
    depth of the largest expected index tree. **Note: should you encounter
    an ISFATAL error: fatal isam error iscomp.c(68) the value of ISMAXBUF
    should be increased and the entire library recompiled before attempting
    to continue. 
    #define ISERRBASE 100 /* start error codes at */
    the library generated iserrno values usually start at 100. on
    some systems this conflicts with system generated errno values.
    you can use this define to change the start point.
    #define ISTHREADED 0	 /* threadsafe handling */
    please refer the thread.ref for details if you plan to use this.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • key compression
    key compression
    due to fixed index file format specifications, a single char is used
    to store the number of leading compressed bytes and another to store
    the number of trailing compressed bytes. this forces a limitation
    of 255 bytes ( max unsigned char ) for compressed key size,
    regardless of ISMAXKEY setting to ensure full compression of all
    trailing spaces or nulls for TCOMPRESS, and all leading duplicate
    characters for LCOMPRESS.
    allows compressed key sizes larger than 255 bytes, but will only
    permit partial compression on leading and trailing characters.
    a maximum of 255 leading duplicate characters, and 255 trailing 
    spaces or nulls will be compressed.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • transparent file links
    transparent file links
    when building, opening, renaming or erasing isam files, the library
    will first check for the existence of a .lnk file in the specified
    path. this is a text file that is expected to contain the physical
    path for the associated isam file in the first line. the remainder
    of the file contents is ignored.
    for instance, if you create a file called sample.lnk in directory
    testdata with "mydata/temp" in the first line, then attempt to open
    "testdata/sample", the library will bypass any existing sample file
    in testdata and open mydata/temp instead.
    linking is not recursive - the only place the library will look for
    a link is on the original path passed to the associated isam call.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • index masking
    index masking
    index masking is a mechanism through which the application can control
    which indexes a given record will be stored in. usage is relatively
    simple, and best explained by example.
    masked files are created by adding ISMASKED to the mode when calling
    isBuild or isbuild, and are opened in the same way.
    the library will return an EBADARG error if a masked file is opened
    without ISMASKED in the mode or ISMASKED is added to the open mode
    on an unmasked file.
    given a file with three indexes, where a value of 1 represents the
    primary, 2 the middle index, and 3 the last, the following call will
    add a record to the primary index only:
    issetmask( isfd, ISMASK(2) + ISMASK(3) );
    iswrite( isfd, record_data );
    to rewrite a record such that it will be masked in the primary:
    issetmask( isfd, ISMASK(1) );
    isrewrite( isfd, record_data );
    where isrewrite could also be isrewcurr or isrewrec.
    the mask value for the current record can be obtained via a call to
    isgetmask( isfd );
    record masks must be set explicitly - if reading through a file with
    the intention of adjusting mask values you must call issetmask for
    each record you wish to change.
    files built with masking active will allow multiple copies of
    identical indexes to be added to the file. this is to allow the
    developer to store different record subsets in separate indexes,
    but it is important to note that only the *last* of these indexes
    can be accessed via isstart - isindex should be used instead.
    BASE: if using the base ( file descriptor ) calls you should enquire
    and set the mask values directly, rather than using isgetmask
    and issetmask. for example:
    if( isam->mask & ISMASK(1) ) /* current record masked in primary */
    isam->mask = ISMASK(2) + ISMASK(3); /* mask 2nd and 3rd indexes */
    NOTES: masking is a custom extension - files built with ISMASKED are
    not cisam compatible.
    you should not remove indexes from a masked file once it has
    been populated.
    as of version 6.1, the flag in the index header that denotes
    masked files has been changed - you will need to run fixflags
    (in the util directory) to patch older files.
    see nullkeys.ref for an alternate method of filtering indexes.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • isam file mirroring reference
    isam file mirroring reference
    isam file mirroring works by setting an environment variable BDMIRROR to
    the full path of location of the mirror fileset.
    BDMIRROR will mirror to remote destinations if ISCLIENT is set to 1 in
    isconfig.h prior to compiling the Disam library. If the mirror files
    are on a remote machine the path of BDMIRROR must be prefixed with the
    ip of the remote machine such as:
    BDMIRROR = // for unix platforms
    BDMIRROR = \\\\\\isamfilepath for DOS,Win or NT platforms
    The mirror fileset must exist in the BDMIRROR location for mirroring to work.
    All disam calls will be duplicated to the locale fileset as well as the mirrored
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • null key masking
    null key masking
    it is possible to flag indexes such that null keys (those whose value
    equates to null) will not be added to the index, and the associated
    records will not be accessible via that index,
    the default value used to determine if a given key is null is zero,
    but this can be modified by adding the value (left shifted by eight)
    to the key type field.
    the following code constructs a null key index in which a character
    field containing all spaces will be considered null:
    key->k_flags = ISDUPS + NULLKEY;
    key->k_nparts = 1;
    key->k_part[0].kp_type = CHARTYPE + ( 32 << 8 );
    key->k_part[0].kp_start = 10; 
    key->k_part[0].kp_leng = 10;
    null key indexes are not cisam compatible.
    see mask.ref for an alternate method of filtering indexes.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • pure indexes
    pure indexes
    pure index files provide a method of managing key information without
    the overheads required for full data handling. they offer advantages
    in speed and storage requirements, but are necessarily limited in
    other ways.
    both isBuild and isbuild will create pure index files when passed a
    value of zero for the record length. the result is a single .idx
    system file - no .dat is created.
    pure index files consist of the primary index only - you may not add
    secondary indexes.
    only the fields pointed to by the key description will be stored and
    available for retrieval.
    the current value of isrecnum will be stored on writes and updates
    and will be returned on read. since the global isrecnum normally 
    contains the data record number, in the case of pure index files where
    there are no data records, the following pure idx iswrite will inherit
    whatever the current isrecnum value is. to allow for the user application 
    setting isrecnum, or to allow the current value to be herited set ISPURE
    in isconfig.h to 0, this is the current default setting.
    if the preference is for disam to assign an incremented isrecnum value
    prior to iswrite set ISPURE to 1 in isconfig.h
    record locking is not possible, and pure indexes may not be opened in
    autolock mode.
    you cannot delete or rewrite by record number.
    pure indexes cannot be rebuilt or repaired if damaged, so should not
    be used for critical data.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • auto file corruption repair
    auto file corruption repair
    index and data file corruptions can occurr if a running process is
    aborted mid-stream or if a system failure occurs.
    often running dcheck -b or dpack after such a failure can be time
    consuming if the effected files are large, not to mention dcheck or dpack
    must be run manually for each isam file, first to determine the file 
    status and then to repair any corruptions.
    by setting ISREPAIR to 1 in isconfig.h prior to compiling the library,
    Disam will maintain data record images of records being updated,
    for the duration of the update. if the update concludes successfully
    the image is removed from the file system, however if a system failure
    occurs the data image remains on the file system and Disam uses these
    images to check and repair the effected index/data records.
    this removes the need to rebuild the entire isam file manually, which
    can be time consuming.
    to enable the auto repair facility:
    set ISREPAIR to 1 in isconfig.h prior to compiling the Disam
    set the repair file path in isport.h - see #define reppath
    this tells Disam where to store the data record image files
    these files are named as: .rep and are of the format
    short int - isam filename/path length
    short int - data image length
    long int - data record number
    char string - isam filename/path
    char string - isam data record image
    after a system failure all corrupted isam files will be automatically
    repaired simply by ensuring a call to isStartup() - base, or isstartup()
    - wrap, is included in the application's main startup program prior
    to opening any isam files. since only one call to isStartUp()/isstartup()
    is enforced, and since absolutely no isam files should be opened or already
    open at the time isStartUp()/isstartup() is called the application should
    ensure that only one application routine performs the startup/repair.
    the following restrictions apply:
    i) at no time should isstartup() be called if other processes
    are accessing or have open any isam files
    ii) only one process should call istartup() immediately after
    the system has recovered
    iii) at no time should the .rep files be manually removed, unless
    dcheck -b or dpack is used in place of calling isstartup()
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • DISAMv7.0 schema manipulation routines
    DISAMv7.0 schema manipulation routines
    int isStSchema( IsFile *isam, char *loadfile )
    store schema definitions from loadfile to the isam file
    isam	isam file descriptor
    loadfile file containing a schema layout or a file containing a list
    of schema layout filenames
    if there are multiple record definitions such as is the case with C
    union usage in record definitions, loadfile can be a file with the
    names of the different schema layout files
    if loadfile is a schema layout DISAM/DB expects the word 'structure'
    to precede the actual layout, for example:
    field1 type	format	length
    int isLdSchema( IsFile *isam, char *path )
    load schema definitions stored in the isam file to flat files in
    isam	isam file descriptor
    path	path to place schema layout definitions stored in isam file
    int isDpSchema( IsFile *isam )
    dump any schema layouts stored in isam file to stdout
    isam	isam file descriptor
    int isRmSchema( IsFile *isam )
    remove any schema layouts stored in isam file
    isam	isam file descriptor
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • status variables
    status variables
    cisam implements a bank of four char fields named isstat1 through
    isstat4, primarily for use by isam based COBOL programs.
    they are declared and initialised in the wrapper library, but the
    code makes no attempt to set or modify the values.
    Worldwide Copyright (c) Byte Designs Ltd (2009)
  • bench test source
    bench test source
    the test directory contains four stand-alone executables which you
    may find useful for reliability or performance testing, or as a
    sample of the standard wrapper interface usage.
    all three depend on bench.h and bench.c in the same directory.
    auto.c essentially a loose collection of calls that will build,
    add and delete indexes, write, read and delete pseudo
    random data records, and check the results. useful for
    testing the integrity of your compiled library. the
    standard auto run is 500 records, but this can be
    changed by specifying a different count on the command
    lock.c test record locking - will build and populate a sample
    data file (if not found in current directory) and then
    loop through the data, locking a sequential subset of
    the records.
    mult.c cyclic add/update/delete test intended for checking the
    index locking and multi-user features.
    user.c an undocumented and simplistic command line interactive 
    test engine used to verify specific operations. it is a
    long way from complete yet, but might prove useful if
    you are able to figure it out. the support department
    may ask you to run it as a means of checking that your
    compiled library is operating correctly.
    user now includes the ability to make system calls (sys)
    and can run simple scripts (run).
    auto and mult will use varlen data if -v is passed on the command
    line, and will add compression to same if -vc is used.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • transaction processing
    transaction processing
    we have attempted to provide a transparent implementation of the
    transaction processing routines provided by cisam. the library
    should perform as specified in the cisam manuals, but includes
    a few additional enhancements.
    we are not certain that we have identified the log file locking offsets
    properly. there is a possibility that the library will not co-operate
    in concert with cisam, but we have not found any problems to date.
    transaction processing is activated via ISLOGGING in isconfig.h
    the overlapping transactions option has been modified, and issusplog
    and isresumlog have been discontinued - see overlapping transactions
    for more details.
    NOTE: please ignore references to multi-thread support in the
    following - we are currently working on a revision, but
    this is not yet available. please let support know if
    this is a problem to you, and we will add you to the list
    of people to notify when it is ready.
    function calls reference
    int islogopen( char *name )
    opens log file. once the log file is opened all subsequent operations
    on all files will be logged until the log is closed or suspended. each
    process is responsible for opening a log file. usually all processes
    within an application will open the same log file. access is governed
    by concurrency locks to prevent simultaneous writes, but this feature
    might not be compatible with cisam. files opened/built with ISNOLOG
    in the mode will not be logged.
    int islogclose( void )
    closes log file for the process. all subsequent operations will not
    be logged.
    int isbegin( void )
    defines the beginning of a set of operations on all files opened with
    ISTRANS in the mode argument. this set of operations is known as a
    all records updated within the transaction will remain locked to ensure
    no other process can affect the results. in multi-user situations it
    is important to keep the time spent within a transaction to a minimum
    to avoid impacting on other processes' access to the records involved.
    all calls to isclose within the transaction will be deferred to avoid
    releasing the locks mentioned above. if the same file is reopened
    within the same transaction you will simply get the same file handle
    all updates affect the data file immediately. if the process should
    terminate before completing the transaction, the changes will remain
    unless isrecover is used to rebuild the data from the last backup.
    int iscommit( void )
    defines the successful completion of a transaction. all locked
    records will be released and all deferred closes honoured.
    int isrollback( void )
    defines the unsuccessful completion of a transaction. all updated
    records will be restored to their original state, all record locks
    released and all deferred closes honoured.
    int isrecover( void )
    used to rebuild a set of data files from an original condition by
    means of a common log file. islogopen() must be called first to
    open the log.
    usage reference
    data file recovery
    if, at the time a full data backup was made, the transaction log
    was purged, then, provided all updating processes call islogopen()
    before making changes, it is possible to rebuild the data files
    from the backup and the log file.
    it is not necessary that files be opened with a mode of ISTRANS
    for changes to be logged. files that are opened with a mode of
    ISNOLOG will not be logged and will not be recoverable.
    to do so it is necessary to compile a recovery utility that will
    call the following functions in order:
    islogopen( );
    the recovery procedure will then be to restore the backup ( make
    sure not to overwrite the log file ) and run the recovery utility.
    the utility should check the return from isrecover() to ensure no
    errors occurred during recovery.
    it is also possible to implement incremental backups by this
    method. the log file can be backed up and purged on a regular
    basis. to recover it will be necessary to restore the original
    backup, then restore and run the recovery utility on each log
    file in chronological order.
    transaction processing fundamentals
    the theory behind transaction processing is that a collection of
    changes to a group of data files can be defined in such a way as
    to be able to undo these changes at any time during the operation.
    the collection of changes is referred to as a transaction.
    a sample program might best serve to illustrate. proper error
    checking has been omitted to simplify:
    /* post a sales invoice */
    int invcFile; /* source invoice record file */
    int custFile; /* customer master records */
    int tranFile; /* accounting transaction file */
    islogopen( "logfile" );
    invcFile = isopen( "invoice", INOUT + ISTRANS );
    custFile = isopen( "customer", INOUT + ISTRANS );
    tranFile = isopen( "transaction", INOUT + ISTRANS );
    isstart( invcFile, ..., ISFIRST );
    /* loop through invoices */
    while( isread( invcFile, invcrec, ISNEXT ) == SUCCESS )
    isbegin(); /* define transaction start */
    postCust() == SUCCESS /* update customer master */
    postTran() == SUCCESS /* create transaction record */
    delInvc() == SUCCESS /* delete invoice record */
    iscommit(); /* successful, commit changes */
    isrollback(); /* failed, erase changes */
    isclose( invcFile );
    isclose( custFile );
    isclose( tranFile );
    exit( 0 );
    note that the transaction processing logic will lock all records
    that are changed within the transaction for the duration of the
    transaction. in some instances it pays to keep the transaction
    cycle as short as possible to allow other processes access to
    these records.
    note also that those files whose changes are to be erased when
    isrollback is called must be opened with mode ISTRANS. changes
    will still be logged for those that are not, but the transaction
    processing logic ignores them and will not undo any changes.
    overlapping transactions
    as an extension to the cisam standard, and also as a means of
    allowing flexible use of transaction processing within multi-
    threaded applications, the library provides a mechanism for
    handling multiple concurrent (or overlapping) transactions.
    management centers around the use of a callback function provided
    by the application. in order to permit overlapping transactions
    you must first call isTxnInit( callback ), where callback is the
    name of a routine that will return a short integer value that the
    library will use to determine which operations belong to which
    in a single threaded application the simplest method is to declare
    a variable that is visible to all routines that handle transactions
    and to the callback function itself.
    for example, assuming a simple nested transaction operation:
    static short txnid;
    txnid = 1;
    for( account = 0; account < 5; ++account )
    /* update account master files */
    txnid = 2;
    /* update account files */
    iscommit() or isrollback();
    txnid = 1;
    iscommit() or isrollback();
    in a multi-threaded application, assuming the intention is to
    allow atomic transactions within individual threads, you would
    have the callback routine return the thread id value.
    NOTE: isrecover is NOT threadsafe and should only be used under
    single threaded circumstances, or at very least only when
    there are no other threads working on isam files.
    NOTE: when implementing transaction processing in a client/server
    environment the logfile MUST be opened as:
    isLogOpen/islogopen( "//ip/path/logname" );
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • variable length records
    variable length records
    refer to install.ref for activation and configuration details.
    the following is a list of the functional and programmatic differences
    between fixed length and variable length isam file handling.
    isreclen is a global integer used to pass variable length info around
    in much the same way as isrecnum.
    the parts of any key added must reside within the fixed length part
    of the record.
    you can add ISVARLEN to the mode argument to create a varlen file.
    if so then the record length argument must define the maximum possible
    length of the records. you must also set isreclen to the size of the
    fixed length header portion of the record. key fields can only reside
    in the fixed length portion. you can also use ISVARCMP in place of
    ISVARLEN to specify that RLE compression be applied to the data.
    isvbuild should be used in place of isbuild if you are creating
    variable length files in a multithreaded environment - refer to
    thread.ref for details.
    if file is variable, the msb of di_nkeys will be set to indicate same.
    di_recsize contains the maximum record size, the fixed length size is
    returned in isreclen.
    if the file is variable length you must use ISVARLEN in the mode, or
    else isopen will return an EBADARG error. the converse is also true -
    if the file is not variable length, then specifying ISVARLEN will
    return the same error. if successful then isreclen will be set to the
    maximum record length of the opened file.
    to get around the inconvenience of the above, you can use ISNOCARE
    in the open mode, in which case the file will be opened regardless
    of whether it is variable or fixed length. you can then check the
    open mode value to determine which kind of file was opened. this
    is found in isam->openmode if you are using the base library calls,
    or loaded by means of isgetmode( int isfd, int *mode ) if using
    the wrapper library.
    isreclen will be set to the actual size of the record just read.
    set isreclen to actual size of record before calling.
    the library provides optional RLE compression on the variable length
    portion of the data record. this is specified when creating the file
    by using a mode flag of ISVARCMP in place of ISVARLEN. note that
    ISVARCMP and ISVARLEN are NOT additive - you must use one or the
    other, not both.
    once a compressed varlen file has been created, you can use either
    ISVARLEN or ISVARCMP when opening the file - either will work, and
    the file will be opened in the appropriate mode.
    note that RLE encoding is only valuable if your data has a fair
    distribution of repeated zero (0), decimal zero (48), or space (32)
    compression is transparent to the application - records are written
    and read as before.
    compression is not cisam compatible.
    the check utility will analyse and test the variable length storage
    nodes and report statistics.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)
  • wrapper reference
    wrapper reference
    the standard interface is provided in the form of a wrapper, and is
    intended to allow plug and play compatibility with existing cisam
    (or equivalent) application code. only the differences between the
    base and wrapper interfaces are explained below - you should refer
    to the base library reference for the remaining details.
    the integer handle wrapper
    this interface is provided for those who prefer or require a cisam
    compatible API. this interface will link transparently with existing
    cisam or cisam compatible application source, and should require no
    changes to your code, other than to switch to the iswrap.h header.
    all modules that use the integer wrapper should include iswrap.h
    all function names are identical except that they use exclusively
    lower case letters.
    all parameters are identical except that an integer file handle is
    used in place of the IsamFile structure pointer, and except for the
    isbuild() call, which has the standard cisam arguments, whereas the
    base version includes an extra argument for variable length support.
    all functions return 0 on success, or -1 on error, with the exception
    of isbuild and isopen, which return an integer file handle or -1 on
    SUCCESS and ERROR are defined in the header and can be used to test
    the returns from these calls.
    isrecnum, isreclen, iserrno and iserrio are global variables declared
    in the wrapper, defined as externals in iswrap.h and are maintained
    in the same way as defined for the equivalent isfd values in the base,
    and by the usual cisam standard.
    since the base library maintains an individual set of these variables
    on a per file basis, we have also provided a collection of four calls
    that will return a pointer to the associated variable:
    long *is_recnum( int isfd );
    int *is_reclen( int isfd );
    int *is_errno( int isfd );
    int *is_errio( int isfd );
    these can be used to enquire or set values for individual files, and
    are not overwritten on each isam call made.
    common dictionary access
    char *isdi_name( int isfd ); file name as used in isopen/isbuild
    int isdi_datlen( int isfd ); fixed record length
    int isdi_curidx( int isfd ); current index number (zero based)
    int isdi_idxfd( int isfd ); index file system handle
    int isdi_datfd( int isfd ); data file system handle
    struct keydesc *isdi_kdsc( int isfd ); current key description
    isdi_name return a pointer to the file name string, or NULL if
    the isfd value is invalid. the remainder return an integer value
    or -1 on failure.
    Worldwide Copyright (c) Byte Designs Ltd (2009-2014)