ICOBOL INDEXED API LIBRARY 5.5x Dec-2024 NOTE: ICAPI is 64-bit only - it is not released as a 32-bit .dll or .so. A. Introduction The ICOBOL Indexed API Library, called icapi, allows users to write programs in other computer languages, usually C or C++, to access ICOBOL indexed files (not sequential or relative, just indexed) through the ICOBOL interface. This interface allows the user programs to co-operate and share these files with ICOBOL processes. All the necessary calls to create, lock, open, read, rewrite, and write to the indexed files supported by ICOBOL are provided. To execute programs built using the Indexed API Library, an ICOBOL ICAPI license must be available from the license manager (ICPERMIT). The ICPERMIT_MACHINE environment variable can be used to direct licensing. The include file 'status.h' contains macro definitions for extracting the values of the various fields comprising a status code. The return type of all of the Indexed API routines is now simply status_t. Older versions of the Indexed API Library used the special type ic_api_status_t, which was defined the same as status_t. Both types are defined in this header file so that previous users of the library are not required to modify their sources. This file also defines the exit codes which are be returned by the 'ic_init_sys' function. The Indexed API file open functions 'ic_open_indexed' and 'ic_open_void_indexed' support all of the enhanced features of ICISAM version 7 and 8 indexed file support. **NOTE** that ICISAM version 5 and 6 files are no longer supported. The file specification structure includes an identifier entry which will be used to detect future upward compatible revisions of the specification structure. Under all Linux platforms, the library is packaged as a shared object, icapi64.so.xxx, xxx is the version number of the release. The icapi64.so.xxx shared object does have a dependency on the icsys64.so.xxx shared object (same version). When using shared objects you must ensure the objects can be found at runtime. The installso.sh script of the ICOBOL release can be used to install the icapi and icsys shared objects. Under Windows, the user library is packaged as a .dll (icapi64.dll) that provides a standard cdecl interface. When linking, the corresponding icapi64.lib import library should be used. The .dll must be placed in the PATH used by your application. *** NOTE *** In addition, the PATH must include the location of the *** icsys64.dll AND the icsys64.dll must have the same revision as *** the icapi64.dll that your application is using. When using the Indexed API Library, files can be opened via ICNETD by using an icnetd-type name as "@\\machine\dir\file". Where machine has an ICNETD running. B. General Comments The icapi files are located in two places in the install. The .dll (Windows) or .so (Linux) are located in the root folder of the install. The remaining files are located in the icapi folder under the examples folder. (1) All interfaces and type definitions used by the user library are contained in three header files: status.h - error handling macros and error definitions system.h - system runtime declarations indexed.h - indexed i/o declarations and definitions (2) All the ICOBOL User Library calls return a value of type status_t, indicating whether the call succeeded or failed. The return code will be moved into the Exception Status, and is defined as such: A zero return value means no error, A positive return value means an error occurred, and A negative return value means the operation was ok, but a status code is being returned to provide additional information. (3) To initialize the User Library the following calls must be made. These are: ic_init_sys (followed by) ic_init_indexed These "ic_init_" calls must be made before any of the indexed calls are attempted. These calls connect the process with the shared area set up by ICEXEC. Upon termination, corresponding calls must be made in the exact reverse order. These are: ic_term_indexed (followed by) ic_term_sys You should never terminate without making the appropriate "ic_term_" call for each of the "init_" calls that previously succeeded; otherwise, structures in memory could become corrupt, requiring that you shutdown and restart ICEXEC. (4) All the indexed calls correspond to their COBOL counterparts with the exception of ic_open_void_indexed and ic_update_indexed. The ic_open_void_indexed call allows the user program to open an indexed file that already exists without the user needing to know anything about the file other than its name. All the file's vital information is returned in the ic_indexed_file_spec_t structure. The ic_update_indexed call forces the file to be flushed to the operating system and the reliability bits cleared if the file had been modified. (5) Miscellaneous limits and options that the user program needs for the indexed files are defined in indexed.h that should be included in all sources that use the User Library. (6) The specification structure for an indexed file, ic_indexed_file_spec_t, is defined in indexed.h. It describes the file's vital information. The typedef, ic_indexed_key_spec_t, is a substructure that defines each key. The ic_indexed_file_spec_t must be provided to an ic_open_indexed to provide the specifications for the file. If the file already exists the specifications must match, with the exception of type and version fields which may be set to default (i.e., 0). If the ic_open_void_indexed call is used, none of the ic_indexed_file_spec_t structure is used but it is set to the file's vital information on the specified file. (7) Each call checks that the given parameters are valid for that particular call, if not, an error is returned. (8) The limit for the number of indexed files and the size of the buffers being used is determined by the current configuration used by ICEXEC. If ICEXEC is not running then 64 Indexed files and 256KB of buffers are used. C. Interface C.1. User Initialization ic_init_sys(proc_name) returns an int exit_code ic_term_sys() Where proc_name (char *) Specifies a character string specifying the name of the program that will be registered. The ic_init_sys call initializes the necessary information between the user program and the ICOBOL Indexed Library routines. Under UNIX and Windows, this includes setting up the necessary information in the ICEXEC shared area. The ic_term_sys call must be called before terminating the program if a successful ic_init_sys had been executed. C.2. Indexed Initialization ic_init_indexed() ic_term_indexed() The ic_init_indexed call must be called before any other indexed calls can be made. The ic_term_indexed call must be called before terminating the program if a successful ic_init_indexed had been executed. It insures that all indexed files are closed and flushed. It should be called before ic_term_sys. C.3. Opening and Closing Files ic_close_indexed(handle) ic_open_indexed(filename_ptr, open_options, indexed_spec_ptr, handle_ptr) ic_open_void_indexed(filename_ptr, open_options, indexed_spec_ptr, handle_ptr) Where filename_ptr (char *) Specifies a pointer to a character string holding the name of the indexed file to open. The extensions `.xd' and `.nx' will be appended to this name when opening files. handle_ptr (ic_indexed_handle_t *) Specifies a pointer to a location where the file handle to be used on subsequent calls to refer to this open file for a successful open is stuffed. indexed_spec_ptr (ic_indexed_file_spec_t *) Specifies a pointer to a packet of information describing an indexed file. For ic_open_indexed this packet is passed in and if the file exists it must exactly match. For ic_open_void_indexed, upon a successful open, this packet is returned filled in with information from the specified indexed file that must already exist. open_options (short unsigned int) Specifies the type of open to perform using some combination of the IC_OPEN_.._INDEXED options. (IC_OPEN_INPUT_INDEXED, IC_OPEN_OUTPUT_INDEXED, IC_OPEN_CREATE_INDEXED, IC_OPEN_RECREATE_INDEXED, or IC_OPEN_EXCLUSIVE_INDEXED.) One of the open calls must be made for each file you wish to access in the program. An ic_close_indexed call must be called to close any indexed file that had been successfully opened with an open call. C.4. Reading ic_read_key_indexed(handle, key_number, key_ptr, key_length, record_ptr, record_length_ptr, read_options) ic_read_next_indexed(handle, record_ptr, record_length_ptr, read_options) ic_read_next_keyto_indexed(handle, record_ptr, record_length_ptr, read_options, keyto_ptr, keyto_length_ptr) ic_read_prev_indexed(handle, record_ptr, record_length_ptr, read_options) ic_read_prev_keyto_indexed(handle, record_ptr, record_length_ptr, read_options, keyto_ptr, keyto_length_ptr) Where handle (ic_indexed_handle_t) Specifies the file handle for the file that had previously been opened with an open call. keyto_length_ptr (short unsigned int *) Specifies a pointer to the size of the buffer pointed to by keyto_ptr. Its returned value is the actual number of bytes transferred to the buffer. keyto_ptr (char *) Specifies a pointer to a buffer to which the selected key value for the record is transferred. key_len (short unsigned int) Specifies the number of bytes from key_ptr to use in the lookup. key_number (short unsigned int) Specifies the number (0 for primary, 1 for first alternate, etc.) of the particular key to be looked up. key_ptr (char *) Specifies a pointer to the key string to be looked up for this particular key. read_options (short unsigned int) Specifies how the read should deal with record locking. Valid options are IC_NULL_OPTION_INDEXED or any or all of the IC_LOCK_ options except IC_LOCK_IGNORE_INDEXED cannot be set with either IC_LOCK_SET_INDEXED or IC_LOCK_CLEAR_INDEXED. Having both IC_LOCK_SET_INDEXED and IC_LOCK_CLEAR_INDEXED set allows for a program to read records locking one at a time while clearing the last lock before setting the next lock. record_length_ptr (short unsigned int *) Specifies a pointer to the size of the buffer pointed to by record_ptr. Its return value is the actual number of bytes transferred to the buffer. record_ptr (char *) Specifies a pointer to a buffer to which the record is to be placed. The "ic_read_" calls provide the mechanism to read records from files opened for input. The "ic_read_next_" calls will read the next sequential record in the file, the "ic_read_prev_" calls will read the previous record in the file as set by a previous read, start, or open. The ic_read_key_indexed call will allow the user to position to a particular record and read it. The "_keyto_" versions of these calls return the key value for the record that was read. C.5. Writing and Rewriting ic_rewrite_indexed(handle, record_ptr, record_length, rewrite_options) ic_write_indexed(handle, record_ptr, record_length, write_options) Where handle (ic_indexed_handle_t) Specifies the file handle for the file that had previously been opened with an open call. record_ptr (char *) Specifies a pointer to a buffer from which the record is to be written. record_length (short unsigned int) Specifies the number of bytes to be written. write_options (short unsigned int) Specifies how the write should deal with the record. Valid options are IC_UPDATE_FILE_INDEXED or IC_NULL_OPTION_INDEXED. rewrite_options (short unsigned int) Specifies how the rewrite should deal with the record. Valid options are IC_UPDATE_FILE_INDEXED or IC_NULL_OPTION_INDEXED. C.6. Miscellaneous Calls ic_delete_key_indexed(handle, key_ptr, key_length) ic_start_indexed(handle, start_options, key_number, key_ptr, key_length) ic_unlock_indexed(handle) ic_update_indexed(handle) ic_get_records_indexed(handle, record_cnt_ptr) ic_get_delrecords_indexed(handle, record_cnt_ptr) Where handle (ic_indexed_handle_t) Specifies the file handle for the file that had previously been opened with an open call. key_number (short unsigned int) Specifies the number of the particular key to be looked up. Valid numbers are 0 for the primary key, 1 for the first alternate, 2 for the second alternate, etc. This number cannot reference a key that does not exist. key_ptr (char *) Specifies a pointer to the key string to be looked up for this particular key. key_len (short unsigned int) Specifies the number of bytes from key_ptr to use in the lookup. It cannot be larger than the size of the key. start_options (short unsigned int) Specifies the kind of lookup to perform. Valid options are any one of the IC_START_options. (IC_START_EQL_INDEXED, IC_START_GEQ_INDEXED, IC_START_GTR_INDEXED, IC_START_LEQ_INDEXED, IC_START_LSS_INDEXED, IC_START_BEG_INDEXED, IC_START_END_INDEXED). record_cnt_ptr (long unsigned int *) Specifies a pointer to a long unsigned integer into which the number or records (ic_get_records_indexed) or the number of deleted/purged records (ic_get_delrecords_indexed) for the indicated file is returned. ICISAM rev 5 files will always return a 0 for the deleted count and currently network files (those open via ICNETD) will return 2**32 for the deleted count. The ic_delete_key_indexed call always works on the primary key. The ic_start_indexed positions to a particular position in the file based on the particular key value (key_ptr) looked up on a particular key (key_number) using a particular lookup (start_options). The length of the key_value may be smaller than the specified actual key size. The ic_unlock_indexed call clears all locks that have been placed on this file by this program on this handle. The ic_update_indexed call forces all modified data to the disk and clears the reliability bits. This can also be done as an option on the write and rewrite calls. D. Building an executable Your application source code must #include the 3 header files: status_t.h, system.h and indexed.h (see indxsamp.c as an example) in order to make the api calls. They are found in the icapi directory under the exmaples directory. The headers may be copied to your sources directory or you must modify your compile command to add the icapi directory to the list of directories to search for #include files. Under Linux, the command to link your application must include the appropriate icapi shared object in its list of objects to link -- icapi64.so.xxx for 64-bit builds. The execution environment must include both the icapi shared object and the corresponding ICOBOL system shared object, icsys64.so.xxx. (xxx=revision) If a newer version of ICOBOL is installed, the application should be re-linked to reference the updated version. Under Windows, the command to link your application must include the appropriate icapi library header in its list of libraries to link -- icapi64.lib for 64-bit builds. The execution environment must include both the icapi dynamic link library (.dll) and the corresponding ICOBOL system dynamic link library, icsys64.dll. Although the revision number is not part of the name in Windows, the revision number is embedded in the .dll and the two versions must match. If a newer version of ICOBOL is installed, the application does not typically have to be relinked, you can simply deploy the new icapi and icsys dlls. E. Sample program (INDXSAMP.C) The included file, indxsamp.c, is a simple program that provides a few examples on how to connect, use, and disconnect from the ICOBOL User Library. F. Miscellaneous Under Linux, user written non-COBOL programs should be careful in how they open and use files (especially ICISAM files) that are in use by COBOL programs especially in posting Linux locks on the files. ICOBOL uses Linux locks to thread its way through files and any arbitrary use of these Linux locks could cause ICOBOL processes to hang. End of readapi