home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / database / db12 / db_ran.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-11-15  |  18.4 KB  |  633 lines

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