home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / c / cuj9301.zip / 1101083A < prev    next >
Text File  |  1992-11-10  |  12KB  |  487 lines

  1. //////////////
  2. // Isam.cpp //
  3. //////////////
  4.  
  5. #include "isam.h"
  6. #include <fstream.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <stdarg.h>
  11. #include <ctype.h>
  12.  
  13. static struct BTParms {
  14.     char         name[9], filename[9];
  15.     int        keylen, dreclen, maxrecs, indxfd, datafd,
  16.                 kstart, count;
  17.     t_func    keygen;
  18. } btparms[40];
  19.  
  20. static int items = 0;
  21.  
  22. extern "C" {
  23.     int (*Write)(int,const void *,unsigned) = write;
  24.     int (*Read )(int,void *,unsigned) = read;
  25. }
  26. static void isam_init(void);
  27.  
  28. static void isam_init(void)
  29. {
  30.     ifstream btr("btparms.btr");
  31.     char nwln, item[81], buf[20], fname[13], fcname[9];
  32.     int i;
  33.  
  34.     if (!btr)
  35.         eprintf("\n\nUnable to open btparms.btr.\n");
  36.  
  37.     for (i = 0; i < 40; i++) {
  38.         btr.get (item, 80);
  39.         if (!strlen(item))
  40.             break;
  41.         btr.get(nwln);
  42.         strcpy(btparms[i].name, strtok(item, "^"));
  43.         strtok(NULL, "^");
  44.         strcpy(buf, strtok(NULL, "^"));
  45.         btparms[i].keylen  = atoi(buf);
  46.         strtok(NULL, "^");
  47.         strcpy(buf, strtok(NULL, "^"));
  48.         btparms[i].dreclen = atoi(buf);
  49.         strtok(NULL, "^");
  50.         strcpy(fname, strtok(NULL, "^"));
  51.         strtok(NULL, "^");
  52.         strcpy(buf, strtok(NULL, "^"));
  53.         btparms[i].kstart = atoi(buf);
  54.         strcpy(fcname, nospace(strtok(NULL, "^")));
  55.         strcpy(btparms[i].filename, strtok(fname,"."));
  56.         btparms[i].count = 0;
  57.         btparms[i].indxfd = btparms[i].datafd = -1;
  58.         if (strlen(fcname))
  59.             btparms[i].keygen = cataloged_func (
  60.                 catalog_number(fcname));
  61.         else
  62.             btparms[i].keygen = (t_func) NULL;
  63.     }
  64.  
  65.     items = i;
  66.     btr.close();
  67.  
  68.     if (!items)
  69.         eprintf("\n\nUnable to initialize isam system.\n");
  70.  
  71.     for (i = items; i < 40; i++) {
  72.         strcpy(btparms[i].name,"");
  73.         strcpy(btparms[i].filename,"");
  74.         btparms[i].keygen = NULL;
  75.         btparms[i].keylen = btparms[i].dreclen =
  76.             btparms[i].count = btparms[i].kstart = 0;
  77.         btparms[i].indxfd = btparms[i].datafd = -1;
  78.     }
  79. }
  80.  
  81. Isam::Isam(const char *datafilename, int e)
  82. {
  83.     int i, j;
  84.     char buf[20];
  85.  
  86.     backingout = 0;
  87.     elements = e;
  88.     if (!items)                        // this is the first Isam
  89.         isam_init();                // initialize btparms
  90.  
  91.     strcpy(buf, nospace(datafilename));
  92.     indices = 0;
  93.                                         // find btree params
  94.     for (i = 0; i < items; i++)
  95.         if (!stricmp(buf, btparms[i].filename))
  96.             btr[indices++] = i;
  97.     if (!indices)                    // couldn't find any, fatal
  98.         eprintf("\n\nCan't find parameters for %s!\n",
  99.             datafilename);
  100.                                         // set up btree interfaces
  101.     if(    !(btc = new BTC [indices])                      ||
  102.             !(inames = new char* [indices])                 ||
  103.             !(loc = new long [elements])                    ||
  104.             !(oldrec = new char* [elements])                ||
  105.             !(rec = new char* [elements])                   ||
  106.             !(okey = new char [btparms[*btr].dreclen])||
  107.             !(nkey = new char [btparms[*btr].dreclen])     )
  108.         eprintf("\n\nOut of memory.\n");
  109.     for (i = 0; i < indices; i++) {
  110.         inames[i] = btparms[btr[i]].name;
  111.         btc[i].btvcount    = 1;
  112.         if (btrinit(inames[i], btc+i) == ERR)
  113.             eprintf("\n\nCouldn't initialize %s.\n",
  114.                 inames[i]);
  115.         btc[i].btmulti     = 0;    // record locking off
  116.     }
  117.     for (i = 0; i < elements; i++) {
  118.         loc[i] = 0L;
  119.         if (!(oldrec[i] = new char
  120.             [btparms[*btr].dreclen + 1]) ||
  121.             !(rec[i] = new char
  122.             [btparms[*btr].dreclen + 1]) )
  123.                 eprintf("\n\nOut of memory.\n");
  124.     }
  125.     if (btparms[*btr].count) {    // open files if neccesary
  126.         fd[0] = btparms[*btr].datafd;
  127.         fd[1] = btparms[*btr].indxfd;
  128.     }
  129.     else {                            // yup, it's neccesary
  130.         strcpy(buf, btparms[*btr].filename);
  131.         strcat(buf, ".dat");
  132.         if ((fd[0]=bt_open(buf, O_RDWR,S_IRDWR)) == ERR)
  133.             eprintf("\n\nCan't open %s.\n", buf);
  134.         strcpy(buf, btparms[*btr].filename);
  135.         strcat(buf, ".idx");
  136.         if ((fd[1]=bt_open(buf, O_RDWR,S_IRDWR)) == ERR)
  137.             eprintf("\n\nCan't open %s.\n", buf);
  138.         btparms[*btr].datafd = fd[0];
  139.         btparms[*btr].indxfd = fd[1];
  140.     }
  141.  
  142.     (btparms[*btr].count)++;    // record that we are here
  143.     clear();
  144. }
  145.  
  146. Isam::~Isam()
  147. {
  148.     int i, j;
  149.                                         // clean up out mess
  150.     for (i = 0; i < indices; i++)
  151.         btrterm(btc+i);
  152.     for (i = 0; i < elements; i++) {
  153.         delete [] oldrec[i];
  154.         delete [] rec[i];
  155.     }
  156.     delete [] btc;
  157.     delete [] inames;
  158.     delete [] loc;
  159.     delete [] oldrec;
  160.     delete [] rec;
  161.     delete [] nkey;
  162.     delete [] okey;
  163.             // if we're last ones out, turn off the lights
  164.     if (!(--(btparms[*btr].count))) {
  165.         close (fd[0]);
  166.         close (fd[1]);
  167.         btparms[*btr].indxfd = -1;
  168.         btparms[*btr].datafd = -1;
  169.     }
  170. }
  171.  
  172. int Isam::write ()
  173. {
  174.     int deltakey, old1, new1, ele, index, result, len,
  175.          start, notfirst;
  176.     t_func fcn;
  177.     if (*loc < 0)    // programmer hasn't followed rules
  178.         eprintf ("No writes after gets!");
  179.     for (ele = 0; ele < elements; ele++) {
  180.         old1 = strlen(oldrec[ele]);
  181.         new1 = strlen(   rec[ele]);
  182.         if (!(old1 || new1) ||
  183.                 !strcmp(oldrec[ele], rec[ele]))
  184.             continue;
  185.         for (index = 0; index < indices; index++) {
  186.                         // generate the old and/or new key
  187.             len   = btparms[btr[index]].keylen;
  188.             start = btparms[btr[index]].kstart;
  189.             if ((fcn = btparms[btr[index]].keygen) !=
  190.                     (t_func) NULL) {
  191.                 if (old1)
  192.                     strcpy(okey, fcn(oldrec[ele]));
  193.                 if (new1)
  194.                     strcpy(nkey, fcn(   rec[ele]));
  195.             }
  196.             else {
  197.                 if (old1)
  198.                     strnncpy(okey, oldrec[ele] + start, len);
  199.                 if (new1)
  200.                     strnncpy(nkey,    rec[ele] + start, len);
  201.             }
  202.             deltakey = (!old1||!new1||stricmp(okey,nkey));
  203.  
  204.             if (old1 && deltakey) {
  205.                 notfirst = 0;
  206.                 while (strlen(okey) >= len) {
  207.                     strnncpy(btc[index].btkey, ToUpper(okey),
  208.                         len);
  209.                     btc[index].btoptype = (new1 || index ||
  210.                         notfirst++ || backingout) ? DELTKY
  211.                         : DELETE;
  212.                     btc[index].btloc = loc[ele];
  213.                     result=cbtree(fd[0], fd[1], btc+index);
  214.                     if (result != BTCALLOK)
  215.                         backout (ele, 'D', index, result);
  216.                     strcpy(okey, okey + len);
  217.                 }
  218.             }
  219.             if (new1 && deltakey) {
  220.                 notfirst = 0;
  221.                 while (strlen(nkey) >= len) {
  222.                     strnncpy(btc[index].btkey, ToUpper(nkey),
  223.                         len);
  224.                     btc[index].btoptype =  (loc[ele] == 0L) ?
  225.                         INSERT : ISRTKY;
  226.                     btc[index].btloc = loc[ele];
  227.                     result = cbtree(fd[0], fd[1], btc+index);
  228.                     if (result == BTCALLOK)
  229.                         loc[ele] = btc[index].btloc;
  230.                     else
  231.                         backout(ele, 'I', index, result);
  232.                     strcpy(nkey, nkey + len);
  233.                 }
  234.             }
  235.         }
  236.         if (!new1)
  237.             continue;
  238.         if (btseek (fd[0], loc[ele], btc->btdtalen)
  239.                 == -1L)
  240.             backout(ele, 'S');
  241.         if (Write(fd[0],rec[ele],(unsigned)btc->btdtalen)
  242.                 != btc->btdtalen)
  243.             backout(ele, 'W');
  244.     }
  245.     clear ();
  246.     return 0;
  247. }
  248.  
  249. void Isam::backout(int ele,char op,int index,int result)
  250. {    // backs out record add/change/delete on error
  251.     char *trec;
  252.     if (!(trec = new char [btparms[*btr].dreclen]) ||
  253.             backingout) // I quit!  Error in error backout!
  254.         eprintf("\n\nBackout error, error type was %c\n",
  255.             backingout);
  256.     if (index >= 0)
  257.         indices = index + 1; // those beyond index are ok
  258.     backingout = op;
  259.     elements = 1;
  260.     strcpy(trec,rec[ele]);
  261.     strcpy(rec[0],oldrec[ele]);
  262.     strcpy(oldrec[0],trec);
  263.     loc[0] = loc[ele];
  264.     write();
  265.     switch (backingout) {
  266.     case 'I':
  267.         eprintf(
  268. "\n\nINSERT error, element %d, index %s, result %d\n",
  269.             ele, inames[index], result);
  270.     case 'D':
  271.         eprintf(
  272. "\n\nDELETE error, element %d, index %s, result %d\n",
  273.             ele, inames[index], result);
  274.     case 'S':
  275.         eprintf ("\n\nSeek error, element %d\n", ele);
  276.     case 'W':
  277.         eprintf ("\n\nWrite error, element %d\n", ele);
  278.     }
  279. }
  280.  
  281. int Isam::read(const char *key, int ele_limit, int idx,
  282.     int ele)
  283. {
  284.     int i = 0, j = 0;
  285.  
  286.     if ((ele_limit + ele) > elements)
  287.         eprintf("\n\nNot enough elements!\n");
  288.     free_svkey(btc+idx);
  289.     btc[idx].btoptype = GETALL;
  290.     strcpy(btc[idx].btkey, ToUpper(key));
  291.     btc[idx].btloc = 0L;
  292.     while (cbtree(fd[0], fd[1], btc + idx) == BTCALLOK) {
  293.         while (btc[idx].btrecnum[i-j] != 0L) {
  294.             if (i < ele_limit) {
  295.                 loc[i+ele] = btc[idx].btrecnum[i-j];
  296.                 btseek(fd[0], loc[i+ele], btc[idx].btdtalen);
  297.                 Read  (fd[0], rec[i+ele], btc[idx].btdtalen);
  298.             }
  299.             i++;
  300.             if (!((i-j) < btc[idx].btmax))
  301.                 break;
  302.         }
  303.         if ((i-j) < btc[idx].btmax)
  304.             break;
  305.         j += btc[idx].btmax;
  306.     }
  307.     for (j = 0; j < ele_limit; j++)
  308.         strcpy(oldrec[j], rec[j]);
  309.     return i;
  310. }
  311.  
  312. int Isam::getfirst(int index)
  313. {
  314.     return getxxx (index, GETFRST);
  315. }
  316.  
  317. int Isam::getnext(int index)
  318. {
  319.     return getxxx (index, GETNXT);
  320. }
  321.  
  322. int Isam::getge (char *key, int index)
  323. {
  324.     *loc = -1;
  325.     btc[index].btoptype = GETGE;
  326.     strcpy(btc[index].btkey, ToUpper(key));
  327.     if (!(cbtree(fd[0], fd[1], btc + index) == BTCALLOK))
  328.         return 0;
  329.     btseek(fd[0], btc[index].btloc, btc[index].btdtalen);
  330.     Read  (fd[0], rec[0], btc[index].btdtalen);
  331.     return 1;
  332. }
  333.  
  334. int Isam::getxxx(int index, int opt)
  335. {
  336.     *loc = -1;
  337.     btc[index].btoptype = opt;
  338.     if (!(cbtree(fd[0], fd[1], btc + index) == BTCALLOK))
  339.         return 0;
  340.     btseek(fd[0], btc[index].btloc, btc[index].btdtalen);
  341.     Read  (fd[0], rec[0], btc[index].btdtalen);
  342.     return 1;
  343. }
  344.  
  345. void Isam::clear()
  346. {
  347.     int i;
  348.     for (i = 0; i < elements; i++) {
  349.         loc[i] = 0L;
  350.         memset (oldrec[i],'\0', btparms[*btr].dreclen + 1);
  351.         memset (   rec[i],'\0', btparms[*btr].dreclen + 1);
  352.     }
  353. }
  354.  
  355. int Isam::keynum (const char *btname)
  356. {
  357.     int i;
  358.  
  359.     if (!items)
  360.         eprintf("\n\nBtparms not initialized!\n");
  361.     if (indices < 1)
  362.         eprintf("\n\nNo indices.\n");
  363.     for (i = 0; i < indices; i++)
  364.         if (!stricmp(inames[i], nospace(btname)))
  365.             return i;
  366.     eprintf ("\n\nIndex %s not found.\n", btname);
  367.     return -1;
  368. }
  369.  
  370. char* nospace(const char *arg)
  371. {
  372.     static char rtn[80];
  373.     int i, j = 0, k = strlen(arg);
  374.     for (i = 0; i < k; i++)
  375.         if (arg[i] != ' ')
  376.             rtn[j++] = arg[i];
  377.     rtn[j] = '\0';
  378.     return rtn;
  379. }
  380.  
  381. int eprintf(const char *format, ... )
  382. {
  383.     int rtn;
  384.     va_list argptr;
  385.     va_start(argptr, format);
  386.     rtn = vprintf(format, argptr);
  387.     va_end (argptr);
  388.     exit (1);
  389.     return rtn;
  390. }
  391.  
  392. char *ToUpper(const char *c)
  393. {
  394.     static char d[257];
  395.     int i;
  396.  
  397.     for (i = 0; i < 256, c[i] != '\0'; i++)
  398.         d[i] = toupper(c[i]);
  399.     d[i] = '\0';
  400.     return d;
  401. }
  402.  
  403. void Isam::reindex(rel_func func)
  404. {
  405.     char buf[20], cmd[80];
  406.     int tad, i, rlen = btparms[*btr].dreclen, x, y;
  407.     long l;
  408.  
  409.     clear();
  410.     strcpy(buf, btparms[*btr].filename);
  411.     strcat(buf, ".tad");
  412.     if (bt_open(buf, O_RDWR,S_IRDWR) != ERR)
  413.                             // I can't cook in a dirty kitchen!
  414.                             // Besides that, the last re-index
  415.                             // must have failed and I don't know
  416.                             // where the real data is, now.
  417.         eprintf("\n\n%s still exists!\n", buf);
  418.     sprintf(cmd, "ren %s.dat %s.tad",
  419.         btparms[*btr].filename, btparms[*btr].filename);
  420.     close (fd[0]);
  421.     system (cmd);                                // ren .dat to .tad
  422.     if ((tad = bt_open(buf, O_RDWR,S_IRDWR)) == ERR)
  423.         eprintf("\n\nCan't open %s\n", buf);// ren didn't go
  424.     strcpy(buf, btparms[*btr].filename);    // recreate .dat
  425.     strcat(buf, ".dat");
  426.     if((fd[0]=bt_open(buf, O_NEW|O_RDWR, S_IRDWR) ) == ERR)
  427.         eprintf ("\n\nCouldn't recreate %s.dat\n",
  428.             btparms[*btr].filename);
  429.     initdat(fd[0], btc);                    // create file header
  430.     btparms[*btr].datafd = fd[0];
  431.     strcpy(buf, btparms[*btr].filename);    // unlink .idx
  432.     strcat(buf, ".idx");
  433.     close (fd[1]);
  434.     unlink (buf);
  435.     for (i = 0; i < indices; i++) {
  436.         btrterm(btc + i);        // to btrinit() with no .idx
  437.         if (btrinit(inames[i], btc+i) == ERR)
  438.             eprintf("\n\nCouldn't re-initialize %s.\n",
  439.                 inames[i]);
  440.         creatbtr(btc + i);
  441.     }
  442.     for (i = 0; i < indices; i++) {            // re-initialize
  443.         btrterm(btc + i);
  444.         if (btrinit(inames[i], btc+i) == ERR)
  445.             eprintf("\n\nCouldn't re-initialize %s.\n",
  446.                 inames[i]);
  447.     }                // We now have empty datafile and indexfile
  448.     strcpy(buf, btparms[*btr].filename);    // re-open .idx
  449.     strcat(buf, ".idx");
  450.     if((fd[1]=bt_open(buf, O_RDWR, S_IRDWR) ) == ERR)
  451.         eprintf ("\n\nCouldn't recreate %s.idx\n",
  452.             btparms[*btr].filename);
  453.     btparms[*btr].indxfd = fd[1];
  454.     clrscr();                                        // we're ready
  455.     l = 2L; i = 0;
  456.     while (1) {
  457.         if (!(l%10)) {
  458.             if (l < 11L) {
  459.                 gotoxy(10,10);
  460.                 cprintf("Processing %s location ",
  461.                     btparms[*btr].filename);
  462.                 x = wherex(); y = wherey();
  463.             }
  464.             gotoxy(x, y);
  465.             cprintf("%ld", l);
  466.         }
  467.         btseek(tad, l++, rlen);
  468.         if (Read (tad, *rec, rlen) == rlen) {
  469.             if (**rec != '~') {
  470.                 if (func)
  471.                     if (func(*rec))
  472.                         continue;
  473.                 write();
  474.                 i++;
  475.             }
  476.         }
  477.         else
  478.             break;
  479.     }
  480.     printf ("\n\n%d records added.\n", i);
  481.     close (tad);
  482.     strcpy(buf, btparms[*btr].filename);
  483.     strcat(buf, ".tad");
  484.     unlink (buf);                // clean kitchen for next time
  485. }
  486.  
  487.