home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 311_01 / db_ran.c < prev    next >
C/C++ Source or Header  |  1990-04-22  |  19KB  |  628 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      db_ran.c  v1.3  (c) 1987-1990  Ken Harris                           */
  5. /*                                                                          */
  6. /*                                                                          */
  7. /****************************************************************************/
  8. /*                                                                          */
  9. /*      This software is made available on an AS-IS basis. Unrestricted     */
  10. /*      use is granted provided that the copyright notice remains intact.   */
  11. /*      The author makes no warranties expressed or implied.                */
  12. /*                                                                          */
  13. /****************************************************************************/
  14.  
  15. #include "dblib.h"
  16.  
  17. /*
  18.  *      db_add_ran  -  Add a record to a random file
  19.  */                                                 
  20.  
  21. void db_add_ran(df, user_data)
  22.  DATA_FILE df;
  23.  char    *user_data;
  24. {
  25.         FILE_HDR   fh;
  26.         RANDOM_HDR rhdr, thdr;
  27.         RANDOM_REC rrec;
  28.         BUFFER     buf, tmp;    
  29.         short      hval;
  30.         char      *rbuf;
  31.  
  32.         db_error = 0;
  33.  
  34.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  35.         buf  = df->df_buf;
  36.         tmp  = df->df_tmp;
  37.         rhdr = (RANDOM_HDR) buf->buf_data;
  38.         thdr = (RANDOM_HDR) tmp->buf_data;
  39.  
  40.         hval = db_hash_ran(df, user_data);
  41.  
  42.         db_get_blk(df, (long) hval, buf);
  43.         if (db_error) return;
  44.  
  45.         if (rhdr->ran_stat != DB_INUSE)
  46.         {       db_error = DB_INVALID_RANDOM;
  47.                 return;
  48.         }
  49.  
  50.         if (db_search_blk_ran(df, user_data, buf))
  51.         {       db_error = DB_DUP_NOT_ALLOWED;
  52.                 return;
  53.         }
  54.  
  55.         while (rhdr->ran_next)
  56.         {       db_get_blk(df, (long) rhdr->ran_next, buf);
  57.                 if (db_error) return;
  58.  
  59.                 if (db_search_blk_ran(df, user_data, buf))
  60.                 {       db_error = DB_DUP_NOT_ALLOWED;
  61.                         return;
  62.                 }
  63.         }
  64.  
  65.         tmp->buf_cur_blk = 0;
  66.         if (rhdr->ran_rec_cnt >= fh->fh_recs_per_blk)
  67.         {       buf        = df->df_tmp;
  68.                 tmp        = df->df_buf;
  69.                 df->df_buf = buf;
  70.                 df->df_tmp = tmp;
  71.                 rhdr       = (RANDOM_HDR) buf->buf_data;
  72.                 thdr       = (RANDOM_HDR) tmp->buf_data;
  73.  
  74.                 db_get_next_avail(df, buf);
  75.                 if (db_error) return;
  76.  
  77.                 rhdr->ran_next = 0;
  78.                 thdr->ran_next = buf->buf_cur_blk;
  79.  
  80.         }
  81.  
  82.         rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  83.              + rhdr->ran_rec_cnt * fh->fh_rec_size;
  84.         rrec = (RANDOM_REC) rbuf;
  85.  
  86.         if (rrec->ran_stat != DB_FREE)
  87.         {       db_error = DB_INVALID_FREE;
  88.         printf("ran - free stat = %d\n", rrec->ran_stat);
  89.                 return;
  90.         }
  91.         memcpy(rbuf+fh->fh_ctl_size, user_data, fh->fh_data_size);
  92.         rrec->ran_stat = DB_INUSE;
  93.  
  94.         rhdr->ran_rec_cnt += 1;
  95.         db_add_blk = buf->buf_cur_blk;
  96.         db_add_rec = rhdr->ran_rec_cnt;
  97.  
  98.         fh->fh_rec_cnt += 1;
  99.  
  100.         db_put_blk(df, buf);
  101.         if (db_error) return;
  102.  
  103.         if (tmp->buf_cur_blk) 
  104.         {       db_put_blk(df, tmp);
  105.                 if (db_error) return;
  106.         }
  107.  
  108.         db_put_blk(df, df->df_fhdr);
  109. }
  110.  
  111. /*
  112.  *      db_find_ran  -  Find a Random record
  113.  */
  114.  
  115. void db_find_ran(df, user_data, key)
  116.  DATA_FILE  df;
  117.  char     *user_data, *key;
  118. {
  119.         RANDOM_HDR rhdr;
  120.         RANDOM_REC rrec;
  121.         FILE_HDR   fh;
  122.         BUFFER     buf;
  123.         short      hval, rec;
  124.         char      *rbuf;
  125.  
  126.         db_error = 0;
  127.  
  128.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  129.         buf  = df->df_buf;
  130.         rhdr = (RANDOM_HDR) buf->buf_data;
  131.  
  132.         hval = db_hash_ran(df, key);
  133.  
  134.         while (hval)
  135.         {       db_get_blk(df, (long)hval, buf);
  136.                 if (db_error) return;
  137.  
  138.                 if (rec = db_search_blk_ran(df, key, buf))
  139.                 {       buf->buf_rec_inx = rec;
  140.                         rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  141.                              + (rec - 1) * fh->fh_rec_size;
  142.  
  143.                         rrec = (RANDOM_REC) rbuf;
  144.                         if (rrec->ran_stat != DB_INUSE)
  145.                         {       db_error = DB_INVALID_RANDOM;
  146.                                 return;
  147.                         }
  148.                         memcpy(user_data, rbuf+fh->fh_ctl_size, fh->fh_data_size);
  149.                         return;
  150.                 }
  151.                 hval = rhdr->ran_next;
  152.         }
  153.         db_error = DB_REC_NOT_FOUND;
  154.         return;
  155. }
  156.  
  157. /*
  158.  *      db_read_first_ran - Read first record from a random file
  159.  */
  160.  
  161. void db_read_first_ran(df, user_data)
  162.  DATA_FILE  df;
  163.  char     *user_data;
  164. {
  165.         RANDOM_HDR  rhdr;
  166.         RANDOM_REC  rrec;
  167.         FILE_HDR    fh;
  168.         BUFFER      buf;
  169.         ulong       blk;
  170.         char       *rbuf;
  171.  
  172.         db_error = 0;
  173.  
  174.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  175.         buf  = df->df_buf;
  176.         rhdr = (RANDOM_HDR) buf->buf_data;
  177.  
  178.         for (blk=1; blk <= fh->fh_last_block; blk++)
  179.         {       db_get_blk(df, blk, buf);
  180.                 if (db_error) return;
  181.  
  182.                 if (rhdr->ran_stat == DB_INUSE && rhdr->ran_rec_cnt > 0)
  183.                 {       buf->buf_rec_inx = 1;
  184.                         rbuf = buf->buf_data + sizeof(struct db_random_uhdr);
  185.  
  186.                         rrec = (RANDOM_REC) rbuf;
  187.                         if (rrec->ran_stat != DB_INUSE)
  188.                         {       db_error = DB_INVALID_RANDOM;
  189.                                 return;
  190.                         }
  191.                         memcpy(user_data, rbuf+fh->fh_ctl_size, fh->fh_data_size);
  192.                         return;
  193.                 }
  194.         }
  195.         db_error = DB_END_OF_FILE;
  196.         return;
  197. }
  198.  
  199. /*
  200.  *      db_read_next_ran - Read next record from a random file
  201.  */
  202.  
  203. void db_read_next_ran(df, user_data)
  204.  DATA_FILE  df;
  205.  char     *user_data;
  206. {
  207.         RANDOM_HDR  rhdr;
  208.         RANDOM_REC  rrec;
  209.         FILE_HDR    fh;
  210.         BUFFER      buf;
  211.         ulong       blk;
  212.         ushort      rec;
  213.         char       *rbuf;
  214.  
  215.         db_error = 0;
  216.  
  217.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  218.         buf  = df->df_buf;
  219.         rhdr = (RANDOM_HDR) buf->buf_data;
  220.  
  221.         if (df->df_prev_rec < fh->fh_recs_per_blk)
  222.         {       blk = df->df_prev_blk;
  223.                 rec = df->df_prev_rec;
  224.         }
  225.         else
  226.         {       blk = df->df_prev_blk + 1;
  227.                 rec = 0;
  228.         }
  229.  
  230.         for (; blk <= fh->fh_last_block; blk++, rec=0)
  231.         {       db_get_blk(df, blk, buf);
  232.                 if (db_error) return;
  233.                                                    
  234.                 if (rhdr->ran_stat != DB_INUSE) continue;
  235.                 if (rhdr->ran_rec_cnt <= rec) continue;
  236.  
  237.  
  238.                 buf->buf_rec_inx = rec + 1;
  239.                 rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  240.                      + (buf->buf_rec_inx - 1) * fh->fh_rec_size;
  241.  
  242.                 rrec = (RANDOM_REC) rbuf;
  243.                 if (rrec->ran_stat != DB_INUSE)
  244.                 {       db_error = DB_INVALID_RANDOM;
  245.                         return;
  246.                 }
  247.                 memcpy(user_data, rbuf+fh->fh_ctl_size, fh->fh_data_size);
  248.                 return;
  249.         }
  250.         db_error = DB_END_OF_FILE;
  251.         return;
  252. }
  253.  
  254. /*
  255.  *    db_read_last_ran - Read last record from a random file
  256.  */
  257.  
  258. void db_read_last_ran(df, user_data)
  259.  DATA_FILE  df;
  260.  char     *user_data;
  261. {
  262.         RANDOM_HDR  rhdr;
  263.         RANDOM_REC  rrec;
  264.         FILE_HDR    fh;
  265.         BUFFER      buf;
  266.         ulong       blk;
  267.         char       *rbuf;
  268.  
  269.         db_error = 0;
  270.  
  271.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  272.         buf  = df->df_buf;
  273.         rhdr = (RANDOM_HDR) buf->buf_data;
  274.  
  275.     for (blk=fh->fh_last_block; blk >= 1; blk--)
  276.         {       db_get_blk(df, blk, buf);
  277.                 if (db_error) return;
  278.  
  279.                 if (rhdr->ran_stat == DB_INUSE && rhdr->ran_rec_cnt > 0)
  280.         {    buf->buf_rec_inx = rhdr->ran_rec_cnt;
  281.             rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  282.                  + (rhdr->ran_rec_cnt - 1) * fh->fh_rec_size;
  283.  
  284.                         rrec = (RANDOM_REC) rbuf;
  285.                         if (rrec->ran_stat != DB_INUSE)
  286.                         {       db_error = DB_INVALID_RANDOM;
  287.                                 return;
  288.                         }
  289.                         memcpy(user_data, rbuf+fh->fh_ctl_size, fh->fh_data_size);
  290.                         return;
  291.                 }
  292.         }
  293.         db_error = DB_END_OF_FILE;
  294.         return;
  295. }
  296.  
  297. /*
  298.  *    db_read_prev_ran - Read next record from a random file
  299.  */
  300.  
  301. void db_read_prev_ran(df, user_data)
  302.  DATA_FILE  df;
  303.  char     *user_data;
  304. {
  305.         RANDOM_HDR  rhdr;
  306.         RANDOM_REC  rrec;
  307.         FILE_HDR    fh;
  308.         BUFFER      buf;
  309.         ulong       blk;
  310.         ushort      rec;
  311.         char       *rbuf;
  312.  
  313.         db_error = 0;
  314.  
  315.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  316.         buf  = df->df_buf;
  317.         rhdr = (RANDOM_HDR) buf->buf_data;
  318.  
  319.     if (df->df_prev_rec > 1)
  320.         {       blk = df->df_prev_blk;
  321.         rec = df->df_prev_rec - 1;
  322.         }
  323.         else
  324.     {    blk = df->df_prev_blk - 1;
  325.                 rec = 0;
  326.         }
  327.  
  328.     for (; blk >= 1; blk--, rec=0)
  329.         {       db_get_blk(df, blk, buf);
  330.                 if (db_error) return;
  331.                                                    
  332.                 if (rhdr->ran_stat != DB_INUSE) continue;
  333.         if (!rhdr->ran_rec_cnt) continue;
  334.  
  335.         if (rec)
  336.             buf->buf_rec_inx = rec;
  337.         else
  338.             buf->buf_rec_inx = rhdr->ran_rec_cnt;
  339.  
  340.                 rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  341.                      + (buf->buf_rec_inx - 1) * fh->fh_rec_size;
  342.  
  343.                 rrec = (RANDOM_REC) rbuf;
  344.                 if (rrec->ran_stat != DB_INUSE)
  345.                 {       db_error = DB_INVALID_RANDOM;
  346.                         return;
  347.                 }
  348.                 memcpy(user_data, rbuf+fh->fh_ctl_size, fh->fh_data_size);
  349.                 return;
  350.         }
  351.         db_error = DB_END_OF_FILE;
  352.         return;
  353. }
  354.  
  355.  
  356. /*
  357.  *      db_update_ran - Update a random record
  358.  */
  359.  
  360. void db_update_ran(df, user_data)
  361.  DATA_FILE  df;
  362.  char     *user_data;
  363. {
  364.         RANDOM_HDR  rhdr;
  365.         RANDOM_REC  rrec;
  366.         FILE_HDR    fh;
  367.         BUFFER      buf;
  368.         char       *rbuf;
  369.  
  370.         db_error = 0;
  371.  
  372.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  373.         buf  = df->df_buf;
  374.         rhdr = (RANDOM_HDR) buf->buf_data;
  375.  
  376.         if (rhdr->ran_rec_cnt < buf->buf_rec_inx)
  377.         {       db_error = DB_DELETED_REC;
  378.                 return;
  379.         }
  380.  
  381.         rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  382.              + (buf->buf_rec_inx - 1) * fh->fh_rec_size;
  383.  
  384.         rrec = (RANDOM_REC) rbuf;
  385.         if (rrec->ran_stat != DB_INUSE)
  386.         {       db_error = DB_INVALID_RANDOM;
  387.                 return;
  388.         }
  389.         memcpy(rbuf+fh->fh_ctl_size, user_data, fh->fh_data_size);
  390.         db_put_blk(df, buf);
  391.         return;
  392. }
  393.  
  394. /*
  395.  *      db_delete_ran - Delete a random record
  396.  */
  397.  
  398. void db_delete_ran(df)
  399.  DATA_FILE df;
  400. {
  401.         FILE_HDR    fh;
  402.         RANDOM_HDR  rhdr,  thdr;
  403.         RANDOM_REC  rrec,  trec;
  404.         BUFFER      buf,   tmp;
  405.         char       *rbuf, *tbuf;
  406.         ulong       hval,  next;
  407.  
  408.         db_error = 0;
  409.  
  410.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  411.         buf  = df->df_buf;
  412.         tmp  = df->df_tmp;
  413.         rhdr = (RANDOM_HDR) buf->buf_data;
  414.         thdr = (RANDOM_HDR) tmp->buf_data;
  415.  
  416.         if (buf->buf_rec_inx > rhdr->ran_rec_cnt)
  417.         {       db_error = DB_DELETED_REC;
  418.                 return;
  419.         }
  420.  
  421.         rbuf = buf->buf_data + sizeof(struct db_random_uhdr) + fh->fh_ctl_size;
  422.         hval = db_hash_ran(df, rbuf);
  423.  
  424.         df->df_prev_blk = buf->buf_cur_blk;
  425.         df->df_prev_rec = buf->buf_rec_inx - 1;
  426.  
  427.         if (!rhdr->ran_next)
  428.         {       if (buf->buf_rec_inx < rhdr->ran_rec_cnt)
  429.                 {       rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  430.                              + (buf->buf_rec_inx - 1) * fh->fh_rec_size;
  431.  
  432.                         tbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  433.                              + (rhdr->ran_rec_cnt - 1) * fh->fh_rec_size;
  434.  
  435.                         rrec = (RANDOM_REC) rbuf;
  436.                         if (rrec->ran_stat != DB_INUSE)
  437.                         {       db_error = DB_INVALID_RANDOM;
  438.                                 return;
  439.                         }
  440.                         memcpy(rbuf, tbuf, fh->fh_rec_size);
  441.                         memset(tbuf, 0, fh->fh_rec_size);
  442.  
  443.                         trec = (RANDOM_REC) tbuf;
  444.                         trec->ran_stat = DB_FREE;
  445.                 }
  446.                 else
  447.                 if (buf->buf_rec_inx == rhdr->ran_rec_cnt)
  448.                 {       rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  449.                              + (buf->buf_rec_inx - 1) * fh->fh_rec_size;
  450.  
  451.                         rrec = (RANDOM_REC) rbuf;
  452.                         if (rrec->ran_stat != DB_INUSE)
  453.                         {       db_error = DB_INVALID_RANDOM;
  454.                                 return;
  455.                         }
  456.  
  457.                         memset(rbuf, 0, fh->fh_rec_size);
  458.  
  459.                         rrec = (RANDOM_REC) rbuf;
  460.                         rrec->ran_stat = DB_FREE;
  461.                 }
  462.  
  463.                 rhdr->ran_rec_cnt--;
  464.                 db_put_blk(df, buf);
  465.                 if (db_error) return;
  466.  
  467.                 if (!rhdr->ran_rec_cnt)
  468.                 {       db_delete_blk_ran(df, hval);
  469.                         return;
  470.                 }
  471.                 return;
  472.         }
  473.  
  474.         if (rhdr->ran_next)
  475.         {       next = rhdr->ran_next;
  476.                 while (next)
  477.                 {       db_get_blk(df, next, tmp);
  478.                         if (db_error) return;
  479.  
  480.                         next = thdr->ran_next;
  481.                 }
  482.                                       
  483.                 if (!thdr->ran_rec_cnt)
  484.                 {       db_error = DB_INVALID_RANDOM;
  485.                         return;
  486.                 }
  487.  
  488.                 rbuf = buf->buf_data + sizeof(struct db_random_uhdr)
  489.                      + (buf->buf_rec_inx - 1) * fh->fh_rec_size;
  490.  
  491.                 tbuf = tmp->buf_data + sizeof(struct db_random_uhdr)
  492.                      + (thdr->ran_rec_cnt - 1) * fh->fh_rec_size;
  493.  
  494.                 rrec = (RANDOM_REC) rbuf;
  495.                 if (rrec->ran_stat != DB_INUSE)
  496.                 {       db_error = DB_INVALID_RANDOM;
  497.                         return;
  498.                 }
  499.                 memcpy(rbuf, tbuf, fh->fh_rec_size);
  500.                 memset(tbuf, 0, fh->fh_rec_size);
  501.  
  502.                 trec = (RANDOM_REC) tbuf;
  503.                 trec->ran_stat = DB_FREE;
  504.  
  505.                 thdr->ran_rec_cnt--;
  506.                 db_put_blk(df, buf);
  507.                 if (db_error) return;
  508.  
  509.                 db_put_blk(df, tmp);
  510.                 if (db_error) return;
  511.  
  512.                 if (!thdr->ran_rec_cnt)
  513.                 {       db_delete_blk_ran(df, hval);
  514.                         return;
  515.                 }
  516.                 return;
  517.         }
  518. }
  519.  
  520. /*
  521.  *      db_delete_blk_ran - Delete empty overflow buckets
  522.  *                          There should be at most one at the end of the chain.
  523.  */
  524.  
  525. void db_delete_blk_ran(df, base_blk)
  526.  DATA_FILE  df;
  527.  ulong     base_blk;
  528. {
  529.         FILE_HDR    fh;
  530.         RANDOM_HDR  rhdr, thdr;
  531.         BUFFER      buf,  tmp;
  532.         ulong       next;
  533.  
  534.         db_error = 0;
  535.  
  536.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  537.         buf  = df->df_buf;
  538.         tmp  = df->df_tmp;
  539.         rhdr = (RANDOM_HDR) buf->buf_data;
  540.         thdr = (RANDOM_HDR) tmp->buf_data;
  541.  
  542.         buf->buf_cur_blk = 0;
  543.         tmp->buf_cur_blk = 0;
  544.  
  545.         next = base_blk;
  546.         while (next)
  547.         {       db_get_blk(df, next, tmp);
  548.                 if (db_error) return;
  549.  
  550.                 next = thdr->ran_next;
  551.  
  552.                 if (!thdr->ran_rec_cnt)
  553.                 {       if (buf->buf_cur_blk)
  554.                         {       rhdr->ran_next = next;
  555.                                 db_put_blk(df, buf);
  556.                                 if (db_error) return;
  557.                         }
  558.                         if (tmp->buf_cur_blk > fh->fh_base_size)
  559.                         {       db_free_rec(df, tmp);
  560.                                 continue;
  561.                         }
  562.                 }
  563.  
  564.                 buf        = df->df_tmp;
  565.                 tmp        = df->df_buf;
  566.                 df->df_buf = buf;
  567.                 df->df_tmp = tmp;
  568.                 rhdr = (RANDOM_HDR) buf->buf_data;
  569.                 thdr = (RANDOM_HDR) tmp->buf_data;
  570.         }
  571.  }
  572.  
  573. /*
  574.  *      db_hash_ran  -  Hash a random key
  575.  */
  576.  
  577. short db_hash_ran(df, key)
  578.  DATA_FILE  df;
  579.  char     *key;
  580. {
  581.         FILE_HDR  fh;
  582.         ulong     hval = 0l;                               
  583.         short     i;
  584.  
  585.         fh = (FILE_HDR) df->df_fhdr->buf_data;
  586.  
  587.         for (i=0; i < fh->fh_key_size; i++) hval += key[i];
  588.  
  589.         hval = (hval % fh->fh_base_size) + 1;
  590.  
  591.         return((short) hval);
  592. }
  593.  
  594. /*
  595.  *      db_search_blk_ran  - Search a random block for matching record
  596.  */
  597.  
  598. short db_search_blk_ran(df, key, buf)
  599.  DATA_FILE  df;
  600.  char     *key;
  601.  BUFFER    buf;
  602. {                            
  603.         RANDOM_HDR rhdr;
  604.         RANDOM_REC rrec;
  605.         FILE_HDR   fh;
  606.         char      *rec;
  607.         short      r_cnt;
  608.  
  609.         fh   = (FILE_HDR) df->df_fhdr->buf_data;
  610.         rhdr = (RANDOM_HDR) buf->buf_data;
  611.         rec  = buf->buf_data + sizeof(struct db_random_uhdr);
  612.  
  613.         for (r_cnt = 1; r_cnt <= rhdr->ran_rec_cnt; r_cnt++)
  614.         {       rrec = (RANDOM_REC) rec;
  615.                 if (rrec->ran_stat != DB_INUSE)
  616.                 {       db_error = DB_INVALID_RANDOM;
  617.                         return(0);
  618.                 }
  619.  
  620.                 if (memcmp(key, rec+fh->fh_ctl_size, fh->fh_key_size)==0) 
  621.                         return(r_cnt);
  622.  
  623.                 rec += fh->fh_rec_size;
  624.         }
  625.  
  626.         return(0);
  627. }
  628.