home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / proglc / index.lzh / INDEX.DOC < prev    next >
Text File  |  1988-02-02  |  27KB  |  670 lines

  1.  
  2.  
  3.  
  4. INDEX.DOC                   Version 1.03                  February 2, 1988
  5.                                                                    Page 1
  6.  
  7. This documentation and the software it describes are Copyright 1987, 1988 by 
  8. Jim Mischel.  You are free to use this software providing that the following 
  9. conditions are met:
  10.  
  11.      1)  Any distributed versions contain the my copyright notice and are 
  12.          accompanied by documentation and source code.  The package doesn't do 
  13.          anybody any good if they don't know how to use it.
  14.      2)  You notify me before using it in any commercial application.  I won't 
  15.          ask for any money, I'd just like to know about it.  Also, if you 
  16.          notify me I may be able to get you a current version and/or notify 
  17.          you of any bug fixes.
  18.  
  19. This package was developed using Turbo C version 1.0.  It should port to other 
  20. compilers and operating systems with very little modification.
  21.  
  22. Questions, comments, problems should be addressed via EMAIL to Jim Mischel, 
  23. CIS id number 73717,1355.  I'd be more than happy to reply to inquiries.
  24.  
  25.  
  26. INDEX.DOC                   Version 1.03                  February 2, 1988
  27.                                                                    Page 2
  28. DESCRIPTION
  29.  
  30. INDEX is a collection of routines designed to provide single-key indexed file 
  31. access to C programs.  They are modeled after the ISAM features supplied in 
  32. standard COBOL implementations, with some additions.  Keys can be of any type, 
  33. including float, double, and user-defined key types.
  34.  
  35. This version of the package uses a threaded binary tree to maintain the index.  
  36. This may change in future versions.  I chose the threaded tree because it is 
  37. relatively simple to implement, uses little memory, and is acceptable for 
  38. small and medium-sized data sets.  It is not the fastest method available, and 
  39. I make no claims as to the speed of record access, though it should be 
  40. acceptable.  Currently, no balancing is performed when adding or deleting 
  41. records from the file.  In many cases, this can result in a severely un-
  42. balanced tree and horribly slow access times.  There is, however, a rebuild 
  43. function that will remove deleted records and balance the index tree.
  44.  
  45. Following are descriptions of the user-accessable routines.  These are the 
  46. only routines that should be called by applications programs.  Calling other 
  47. routines in the package will produce unpredictable results and could very 
  48. possibly destroy the database.
  49.  
  50. The examples provided build on previous examples.  For example, the example 
  51. used with iclose() uses data types defined in the example provided with 
  52. iopen().
  53.  
  54.  
  55. INDEX.DOC                   Version 1.03                  February 2, 1988
  56.                                                                    Page 3
  57. IOPEN - open a file for indexed I/O
  58.  
  59. void *iopen(char *fname, unsigned recsiz, unsigned offset,
  60.             char dupflag, int (*cmp_rtn)());
  61.  
  62. iopen opens an indexed file for reading/writing.  If the file to be opened 
  63. does not exist, iopen attempts to create it.  Upon successful completion, 
  64. iopen will return a pointer to an index control record.  This pointer should 
  65. not be modified by the application program, nor should the fields in the index 
  66. control record be changed by the application.  The data in the record is used 
  67. by the index routines and is at best marginally useful to the application.  
  68. Modifying either the returned pointer or the data pointed to will produce 
  69. unpredictable results and could very likely make the database unuseable.  If 
  70. iopen can not open the file, NULL is returned and the global variable ierrno 
  71. is set to identify the cause of the error. 
  72.  
  73. Arguments passed to iopen()
  74.  
  75. fname          A string containing the name of the file to be opened.  This 
  76.                name should be without an extension.  iopen will append the 
  77.                extension '.DAT' for the data file and the extension '.INX' for 
  78.                the index file.
  79.  
  80. recsiz         Size of the data record in characters.
  81.  
  82. offset         The offset (in characters) from the beginning of the record to 
  83.                the first byte of the key.
  84.  
  85. dupflag        Controls whether duplicate keys are allowed.  If dupflag is 0, 
  86.                duplicate keys are not allowed, and an attempt to add a 
  87.                duplicate key will return an error (see error codes below).  If 
  88.                dupflag is 1, duplicate keys will be allowed.
  89.  
  90. cmp_rtn        Is a pointer to a user-defined key comparison routine.
  91.                The index routines use this routine for key comparisons
  92.                The declaration of the routine must be:
  93.  
  94.                int routine_name(void *arg1, void *arg2);
  95.  
  96.                This routine accepts pointers to the operands and returns
  97.                   -1 if arg1 < arg2
  98.                    0 if arg1 == arg2
  99.                    1 if arg1 > arg2
  100.  
  101.  
  102.  
  103. INDEX.DOC                   Version 1.03                  February 2, 1988
  104.                                                                    Page 4
  105. IOPEN - open a file for indexed I/O
  106. Example:
  107.  
  108. #include <stdio.h>
  109. #include "index.h"
  110.  
  111. int cmpr_rtn(void *arg1, void *arg2);   /* for string comparisons */
  112.  
  113. main (int argc, char *argv[]) {
  114.  
  115.     struct {
  116.       char first_name[25],
  117.            last_name[25];
  118.     } name_rec;
  119.  
  120.     char *name_file;         /* pointer to control record */
  121.     unsigned offset;
  122.  
  123.     offset = &name_rec.last_name - &name_rec;    /* compute key offset */
  124.     if ((name_file = iopen(argv[1],sizeof(name_rec),offset,1,cmpr_rtn) ==
  125.         NULL) {
  126.         printf("Error opening file %s\n",argv[1]);
  127.         printf("Error code is %X\n",ierrno);
  128.         return;
  129.     }
  130.   ...
  131.   ...
  132.   ...
  133.  
  134. int cmpr_rtn(void *arg1, void *arg2)
  135. {
  136.     int r;
  137.  
  138.     return(((r = strcmp((char *)arg1, (char *)arg2)) == 0) ? 0 :
  139.            (r > 0) ? 1 : -1);
  140. }
  141.  
  142.  
  143. INDEX.DOC                   Version 1.03                  February 2, 1988
  144.                                                                    Page 5
  145. ICLOSE - close files and free memory
  146.  
  147. void iclose(void *db_control);
  148.  
  149. iclose closes the index and data files assigned to the index control record, 
  150. and frees the memory used.  iclose does not return status.
  151.  
  152. IMPORTANT NOTE:
  153. All files opened with iopen that have had records added or deleted MUST be 
  154. closed with iclose.  Failure to do so may result in losing data or destroying 
  155. the integrity of the index file.
  156.  
  157. Arguments passed to iclose()
  158.  
  159. db_control     The pointer returned when the file was opened by iopen.
  160.  
  161.  
  162. Example: (building on the one above)
  163.  
  164.   iclose(name_file);
  165.  
  166.  
  167. INDEX.DOC                   Version 1.03                  February 2, 1988
  168.                                                                    Page 6
  169. IREAD - read a record from the file
  170.  
  171. int iread(void *db_control, void *destin);
  172.  
  173. iread reads a record and places it in memory at destin.  iread assumes there 
  174. is sufficient space at destin to hold the entire data record.  Place the key 
  175. value to be searched for at the key position in the record at destin and call 
  176. iread.  iread returns 0 if the record was found, I_NOREC if not, and error 
  177. status if there was an I/O error.  On error conditions, the data at destin is 
  178. not changed.  Using iread does not change the pointer used by the sequential 
  179. read functions iread_next and iread_prev.
  180.  
  181. Arguments passed to iread()
  182.  
  183. db_control     The pointer returned when the file was opened by iopen.
  184.  
  185. destin         A pointer to the structure that will receive the data record.
  186.  
  187. Example:
  188.  
  189.   name_rec.last_name = "Mischel";
  190.   if (iread(name_file,&name_rec)) {
  191.     printf("\007Record key %s not found in file %s\n",
  192.             name_rec.last_name,argv[1]);
  193.     printf("Error code is %X\n",ierrno);
  194.   }
  195.   else
  196.     printf("Record found\n");
  197.  
  198.  
  199. INDEX.DOC                   Version 1.03                  February 2, 1988
  200.                                                                    Page 7
  201. ISTART - position file for sequential access
  202.  
  203. int istart(void *db_control, char cond, void *source);
  204.  
  205. istart positions the file pointer for sequential file access.  This function 
  206. must be called before attempting to sequentially access the file through 
  207. iread_next or iread_prev.  Place the key value to be searched for at the key 
  208. position in source and call istart.  No data is transferred by this function.
  209. istart will return 0 if the file pointer was positioned successfully, EOF if 
  210. no record meeting key and cond could be found, and one of the standard error 
  211. codes on error.
  212.  
  213. Arguments passed to istart()
  214.  
  215. db_control     The pointer returned when the file was opened by iopen.
  216.  
  217. cond           One of the conditions defined in INDEX.H:
  218.  
  219.                START_FILE     Start at beginning of file, source is ignored
  220.                LT             Start at the key less than the key in source
  221.                LE             Start at key less then or equal to key in 
  222.                               source.  If a record exists with key, it will 
  223.                               start there.
  224.                EQ             Start at key equal to the key in source.
  225.                GE             Start at key greater than or equal to key in 
  226.                               source.  If a record exists with key, it will 
  227.                               start there.
  228.                GT             Start at key greater than key in source.
  229.                END_FILE       Start at end of file.  This is useful for 
  230.                               reading the entire file backwards.
  231.  
  232. Example:
  233.  
  234. /*
  235.  * to position the file at the first record with a key greater than or equal
  236.  * to Sm.
  237.  */
  238.   name_rec.last_name = "Sm";
  239.   if (istart(db_control,GE,&name_rec)) {
  240.     printf("Couldn't position file\n");
  241.     printf("Error code is %X\n",ierrno);
  242.   }
  243.   else {
  244.   /*
  245.    * read the file sequentially forward or backward.  See examples for
  246.    * iread_next and iread_prev.
  247.    */
  248.   }
  249.  
  250.  
  251. INDEX.DOC                   Version 1.03                  February 2, 1988
  252.                                                                    Page 8
  253. IREAD_NEXT - Sequentially read the next record
  254.  
  255. int iread_next(void *db_control, void *destin);
  256.  
  257. Read the next record in sequence into destin.  iread_next assumes there is 
  258. room in destin for the entire record.  Returns 0 if successful, EOF at end of 
  259. file, standard error code on error.  On error conditions, the data at destin 
  260. is not changed.
  261.  
  262. Arguments passed to iread_next()
  263.  
  264. db_control     The pointer returned when the file was opened by iopen.
  265.  
  266. destin         A pointer to the structure to receive the data record.
  267.  
  268. Example:
  269.  
  270.   /*
  271.    * read the file sequentially forward (assuming it was started as above)
  272.    */
  273.     while (!iread_next(db_control,&name_rec))
  274.       printf("%s %s\n",name_rec.first_name,name_rec.last_name);
  275.  
  276.  
  277. INDEX.DOC                   Version 1.03                  February 2, 1988
  278.                                                                    Page 9
  279. IREAD_PREV - sequentially read the previous record
  280.  
  281. int iread_prev(void *db_control, void *destin);
  282.  
  283. read the previous record in sequence into destin.  Assumes there is room in 
  284. destin for the entire record.  Returns 0 if successful, EOF at top of file, 
  285. standard error code on error.  On error conditions, the data at destin is not 
  286. changed.
  287.  
  288. Arguments passed to iread_prev()
  289.  
  290. db_control     The pointer returned when the file was opened by iopen.
  291.  
  292. destin         A pointer to the structure to receive the data record.
  293.  
  294. Example:
  295.  
  296.   /*
  297.    * read the file sequentially backward (assuming it was started as above)
  298.    */
  299.     while (!iread_prev(db_control,&name_rec))
  300.       printf("%s %s\n",name_rec.first_name,name_rec.last_name);
  301.  
  302.  
  303. INDEX.DOC                   Version 1.03                  February 2, 1988
  304.                                                                    Page 10
  305. IWRITE - add a new record
  306.  
  307. int iwrite(void *db_control, void *source);
  308.  
  309. Write the record from source to the data file.  Data records are always added 
  310. to the end of the file.  Returns 0 if successful, I_INVKEY if duplicates are 
  311. not permitted and an attempt was made to add a duplicate record, standard 
  312. error code otherwise.
  313.  
  314. Arguments passed to iwrite()
  315.  
  316. db_control     The pointer returned when the file was opened by iopen.
  317.  
  318. source         A pointer to the structure to be written.
  319.  
  320. Example:
  321.  
  322.   name_rec.first_name = "Jim";
  323.   name_rec.last_name = "Mischel";
  324.   switch (iwrite(db_control,&name_rec)) {
  325.     case 0        :
  326.       printf("Record written\n");
  327.       break;
  328.     case I_INVKEY :
  329.       printf("Duplicate key %s\n",name_rec.last_name);
  330.       break;
  331.     default       :
  332.       printf("Write error.  Error code is %X\n",ierrno);
  333.   }
  334.  
  335.  
  336. INDEX.DOC                   Version 1.03                  February 2, 1988
  337.                                                                    Page 11
  338. IREWRITE - update an existing record
  339.  
  340. int irewrite(void *db_control, void *source);
  341.  
  342. Update the current record in the file.  The record must have been read using 
  343. one of the read routines, or written using iwrite, and must still be in the 
  344. buffer.  It is not possible to change the key using irewrite.  Use idelete to 
  345. remove the record and iwrite to add the record after the key has been changed.
  346. Returns 0 on success, I_INVKEY if attempt to rewrite a record that isn't in 
  347. the buffer, standard error code otherwise.
  348.  
  349. Arguments passed to irewrite()
  350.  
  351. db_control     The pointer returned when the file was opened by iopen.
  352.  
  353. source         A pointer to the structure to be written.
  354.  
  355. Example:
  356.  
  357.   /* first we have to read the record */
  358.   name_rec.last_name = "Smith";
  359.   if (iread(name_file,&name_rec)) {
  360.     printf("\007Record key %s not found in file %s\n",
  361.             name_rec.last_name,argv[1]);
  362.     printf("Error code is %X\n",ierrno);
  363.   }
  364.   else {
  365.     name_rec.first_name = "John";
  366.     switch (irewrite(db_control,&name_rec)) {
  367.       case 0 :
  368.         printf("Success\n");
  369.         break;
  370.       case I_INVKEY :
  371.         printf("Invalid rewrite attempted\n");
  372.         break;
  373.       default :
  374.         printf("Rewrite error.  Error code is %X\n",ierrno);
  375.     }
  376.  
  377.  
  378. INDEX.DOC                   Version 1.03                  February 2, 1988
  379.                                                                    Page 12
  380. IDELETE - delete a record
  381.  
  382. int idelete(void *d, void *source);
  383.  
  384. Delete the record currently in the buffer.  Record must have been read using 
  385. one of the read routines, or written using iwrite, and still be in the buffer.  
  386. Returns 0 on success, I_INVKEY if attempt to delete a record that isn't in the 
  387. buffer, standard error code otherwise.
  388.  
  389. When a record is deleted, it is not removed from the data file and its index 
  390. pointer is not removed from the index file.  What happens is that the index 
  391. record is flagged as deleted and the read routines treat the record as if it 
  392. didn't exist.  This has at least two major side affects:
  393.  
  394.   1)  If the data file is scanned by a program that doesn't use the index 
  395.       routines, deleted records will be picked up along with current records.
  396.   2)  In a file that has a large turnover rate, there will be a considerable 
  397.       amount of wasted space taken up by the deleted records.
  398.  
  399. Beginning with Version 1.03 (02/02/88), the function irebuild() will remove 
  400. deleted records from a data file and balance the index tree for optimum 
  401. performance.  This takes care of the wasted space in the data file.
  402.  
  403. The first problem can be solved by using the irebuild() function before 
  404. scanning the data file, or you can add a deleted record flag to the data 
  405. record.  Your program will have to manipulate this flag, setting it before the 
  406. record is deleted.
  407.  
  408. Arguments passed to idelete()
  409.  
  410. db_control     The pointer returned when the file was opened by iopen.
  411.  
  412. source         A pointer to the structure containing the key name to be 
  413.                deleted.
  414.  
  415.  
  416. INDEX.DOC                   Version 1.03                  February 2, 1988
  417.                                                                    Page 13
  418. IDELETE - delete a record
  419.  
  420. Example:
  421.  
  422.   /* first read the record */
  423.   name_rec.last_name = "Smith";
  424.   if (iread(name_file,&name_rec)) {
  425.     printf("\007Record key %s not found in file %s\n",
  426.             name_rec.last_name,argv[1]);
  427.     printf("Error code is %X\n",ierrno);
  428.   }
  429.   else {
  430.     switch (idelete(db_control,&name_rec)) {
  431.       case 0 :
  432.         printf("Record deleted\n");
  433.         break;
  434.       case I_INVKEY :
  435.         printf("Invalid delete attempted\n");
  436.         break;
  437.       default :
  438.         printf("Delete error.  Error code is %X\n",ierrno);
  439.     }
  440.  
  441.  
  442. INDEX.DOC                   Version 1.03                  February 2, 1988
  443.                                                                    Page 14
  444. IREBUILD - rebuild data and index files
  445.  
  446. int irebuild(char *old_fname, unsigned recsiz, unsigned offset,
  447.              char dupflag, int (*cmp_rtn)(), char *new_fname);
  448.  
  449. Copy the file old_fname to the file new_fname, removing deleted records and 
  450. balancing the index tree.  old_fname must be the name of an existing index 
  451. file (without the extension).  new_fname must be the name of the new file 
  452. (without extension), and it must not exist.  If a file with new_fname already 
  453. exists, the function returns with an error.
  454.  
  455. The routine returns 0 if the rebuild is successful.  A non-zero return 
  456. signifies error.  If the routine exits with an error, it does not clean up its 
  457. workspace.  It may leave files open and temporary memory buffers allocated.  
  458. If the routine exits with an error, it is a good idea to abort the calling 
  459. program.
  460.  
  461. irebuild() uses a temporary file called !REBLD!.$$$ to hold the data records 
  462. while it is balancing the index tree.  If the function exits with an error, 
  463. this file will remain.  If you break out of the program (using Control-C) 
  464. while the file is being re-built, the original file (old_fname) will not be 
  465. harmed.  However, the new file (new_fname) will most likely not contain valid 
  466. data.
  467.  
  468. Arguments passed to irebuild()
  469.  
  470. old_fname      A string containing the name of the file to be rebuilt.  This 
  471.                name must be without an extension.  irebuild will append the 
  472.                extension '.DAT' for the data file and the extension '.INX' for 
  473.                the index file.
  474.  
  475. recsiz         Size of the data record in characters.
  476.  
  477. offset         The offset (in characters) from the beginning of the record to 
  478.                the first byte of the key.
  479.  
  480. dupflag        Controls whether duplicate keys are allowed.  If dupflag is 0, 
  481.                duplicate keys are not allowed, and an attempt to add a 
  482.                duplicate key will return an error (see error codes below).  If 
  483.                dupflag is 1, duplicate keys will be allowed.
  484.  
  485. cmp_rtn        Is a pointer to a user-defined key comparison routine.
  486.                The index routines use this routine for key comparisons
  487.                The declaration of the routine must be:
  488.  
  489.                int routine_name(void *arg1, void *arg2);
  490.  
  491.                This routine accepts pointers to the operands and returns
  492.                   -1 if arg1 < arg2
  493.                    0 if arg1 == arg2
  494.                    1 if arg1 > arg2
  495.  
  496.  
  497.  
  498. INDEX.DOC                   Version 1.03                  February 2, 1988
  499.                                                                    Page 15
  500. IREBUILD - rebuild data and index files
  501. new_fname      A string containing the name of the file to be created.  This 
  502.                file will contain the packed data and balanced index files.  
  503.                This name must be without an extension.  irebuild will append 
  504.                the extension '.DAT' for the data file and the extension '.INX' 
  505.                for the index file.
  506.  
  507. Example:
  508.  
  509. #include <stdio.h>
  510. #include "index.h"
  511.  
  512. int cmpr_rtn(void *arg1, void *arg2);   /* for string comparisons */
  513.  
  514. main (int argc, char *argv[]) {
  515.  
  516.     struct {
  517.         char first_name[25],
  518.         last_name[25];
  519.     } name_rec;
  520.  
  521.     char *name_file;         /* pointer to control record */
  522.     unsigned offset;
  523.  
  524.     offset = &name_rec.last_name - &name_rec;    /* compute key offset */
  525.     if (irebuild(argv[1],sizeof(name_rec),offset,1,cmpr_rtn,argv[2])) {
  526.         printf("Error rebuilding file %s\n",argv[1]);
  527.         printf("Error code is %X\n",ierrno);
  528.     }
  529.     return;
  530. } /* main */
  531.  
  532. int cmpr_rtn(void *arg1, void *arg2)
  533. {
  534.     int r;
  535.  
  536.     return(((r = strcmp((char *)arg1, (char *)arg2)) == 0) ? 0 :
  537.            (r > 0) ? 1 : -1);
  538. }
  539.  
  540.  
  541. INDEX.DOC                   Version 1.03                  February 2, 1988
  542.                                                                    Page 16
  543. ERROR CODES
  544.  
  545. The global variable ierrno will contain the results of the last I/O operation.  
  546. Possible values are:
  547.  
  548. Code      Value  Description
  549. ----      -----  -----------
  550. I_NODAT   0x10 - couldn't open data file (iopen)
  551. I_DATRD   0x11 - I/O error attempting to read data file (any)
  552. I_DATWT   0x12 - I/O error attempting to write to data file (any)
  553. I_NOINX   0x20 - couldn't open index file (iopen)
  554. I_INXRD   0x21 - I/O error attempting to read index file (any)
  555. I_INXWT   0x22 - I/O error attempting to write to index file (any)
  556. I_INVKEY  0x80 - Attempt to add duplicate key when duplicates not permitted 
  557.                  (iwrite)
  558.                  Attempt to rewrite deleted record, or record not in buffer
  559.                  (irewrite)
  560.                  Attempt to delete deleted record, or record not in buffer
  561.                  (idelete)
  562. I_NOMEM   0x81 - out of memory (iopen)
  563. I_NOREC   0x82 - record not found (iread)
  564. I_NOCMP   0x83 - no comparison routine (iopen)
  565.  
  566.  
  567. INDEX.DOC                   Version 1.03                  February 2, 1988
  568.                                                                    Page 17
  569. NOTES
  570.  
  571. I have included a two sample programs that illustrate the use of several of 
  572. the routines in this package.  The first program, ADR.C, is a simple 
  573. address/phone book that is marginally useful as a real application, but does 
  574. show how to use the routines.  The second program, IBLD.C, illustrates the use 
  575. of the irebuild() function.
  576.  
  577. MAKE FILE
  578. I have included a make file that can be used to re-compile the package.  This 
  579. file includes commands to rebuild the library (INDEX.LIB), using either the 
  580. QLIB program available on BPROGB DL 4, or Microsoft's LIB.  The supplied 
  581. library was build with MS LIB and is compatible with TLINK and MS LINK.  
  582. Remember, if you use QLIB, the resulting library will not be compatible with 
  583. Microsoft LINK.
  584.  
  585. KNOWN BUGS
  586.  
  587. The current version (1.03) fixes all reported bugs.  If you run accross any, 
  588. please drop me a note.
  589.  
  590. REVISION HISTORY
  591.  
  592. This package started as a "I wonder how that's done" type of project.  The 
  593. original program used a primitive hashing algorithm to store and retrieve the 
  594. keys.  The program (written in Pascal) did work, but was a terrible kludge and 
  595. I threw it away.  The current version was written for two reasons:  1)  I 
  596. wanted to learn C, and 2)  I needed something like this for a project I was 
  597. planning.
  598.  
  599. Version 1.00  August 13, 1987
  600. Original release version.
  601.  
  602. Version 1.01  August 21, 1987
  603.      1) Fixed bugs in iwrite() and irewrite() that prevented the data buffer 
  604.         from being updated when the record was written.  This bug caused 
  605.         irewrite() and idelete() to erroneously return I_INVKEY.
  606.      2) Updated documentation.  Added examples and cleaned things up quite a 
  607.         bit.
  608.      3) Split the package into multiple source files and added a make file 
  609.         that creates a Turbo C compatible library.
  610.      4) Add calls to fflush() in the write routines.  This slows things down a 
  611.         bit (a lot?), but does help keep data file integrity.
  612.  
  613. Version 1.02  November 4, 1987
  614.      1) Removed the 'keytyp' parameter from the iopen() call.  Also removed 
  615.         default key comparison routines.  All key comparison routines are now 
  616.         user-defined.  Added new error code, I_NOCMP, returned by iopen() when 
  617.         the 'cmp_rtn' parameter is NULL.
  618.  
  619.  
  620. INDEX.DOC                   Version 1.03                  February 2, 1988
  621.                                                                    Page 18
  622. NOTES
  623. Version 1.03  February 2, 1988
  624.      1) There are some possible conflicts when using sequential and random I/O 
  625.         at the same time.  These can only occur when adding or deleting 
  626.         records while sequentially scanning the file.  In general, the only 
  627.         problems involve deleting a record that is to be the next one read, or 
  628.         adding a record between the current and next records.  In the delete 
  629.         case, the deleted record will still be read, and in the add case, the 
  630.         new record will not be read.  These problems have been fixed in the 
  631.         current release.
  632.      2) There were some serious problems with the idelete() function when 
  633.         deleting the root node, which caused backward pointers to get munged.  
  634.         This problem has been fixed in the current release.
  635.      3) Add irebuild() function.  This function removes deleted records from 
  636.         the data file and balances the index tree.  Use it often.
  637.      4) Include IBLD.C program to illustrate use of irebuild() function.
  638.      5) Modify make file (INDEX.MAK) to allow for use of either QLIB or 
  639.         Microsoft's LIB.
  640.  
  641.  
  642. INDEX.DOC                   Version 1.03                  February 2, 1988
  643.                                                                    Page 19
  644. NOTES
  645.  
  646. Files that make up the index package
  647.  
  648. ADR.C     - demonstration program for index package
  649. ADR.MAK   - make file for ADR
  650. ARCIT.BAT - batch file to build the archive
  651. IBLD.C    - demonstration program for irebuild() function
  652. IBLD.MAK  - make file for IBLD
  653. IDELETE.C - delete record routine
  654. INAMES    - name file for QLIB program
  655. INXRTNS.C - support functions for index package
  656. INDEX.DOC - index package documentation, rough but useable
  657. INDEX.H   - header file included by application programs
  658. INDEX.LIB - index routines library (useable only by TLINK, not by MS LINK)
  659. INDEX.MAK - make file for index routines
  660. INXDEFS.H - header file for index routines
  661. IOPEN.C   - open and close functions
  662. IREADN.C  - readnext function
  663. IREADP.C  - readprevious function
  664. IREADR.C  - read random function
  665. IREWRITE.C- rewrite (update) record function
  666. IREBUILD.C- rebuild file (remove deleted records and balance tree)       
  667. ISTART.C  - start function
  668. IWRITE.C  - write record function
  669. READ.ME   - Latest revision notes
  670.