cdb_make.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:4k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* basic cdb creation routines
  2.  *
  3.  * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
  4.  * Public domain.
  5.  */
  6. #include "common/setup_before.h"
  7. #include <stdio.h>
  8. #ifdef STDC_HEADERS
  9. # include <stdlib.h>
  10. #else
  11. # ifdef HAVE_MALLOC_H
  12. #  include <malloc.h>
  13. # endif
  14. #endif
  15. #ifdef HAVE_STRING_H
  16. # include <string.h>
  17. #else
  18. # ifdef HAVE_STRINGS_H
  19. #  include <strings.h>
  20. # endif
  21. # ifdef HAVE_MEMORY_H
  22. #  include <memory.h>
  23. # endif
  24. #endif
  25. #include "cdb_int.h"
  26. #include "common/setup_after.h"
  27. void
  28. cdb_pack(unsigned num, unsigned char buf[4])
  29. {
  30.   buf[0] = num & 255; num >>= 8;
  31.   buf[1] = num & 255; num >>= 8;
  32.   buf[2] = num & 255;
  33.   buf[3] = num >> 8;
  34. }
  35. int
  36. cdb_make_start(struct cdb_make *cdbmp, FILE *fd)
  37. {
  38.   memset(cdbmp, 0, sizeof(*cdbmp));
  39.   cdbmp->cdb_fd = fd;
  40.   cdbmp->cdb_dpos = 2048;
  41.   cdbmp->cdb_bpos = cdbmp->cdb_buf + 2048;
  42.   return 0;
  43. }
  44. static int
  45. ewrite(FILE *fd, const char *buf, int len)
  46. {
  47.   while(len) {
  48.     int l = fwrite(buf, 1, len, fd);
  49.     if (l < 0 && errno != EINTR)
  50.       return -1;
  51.     len -= l;
  52.     buf += l;
  53.   }
  54.   return 0;
  55. }
  56. int
  57. _cdb_make_write(struct cdb_make *cdbmp, const char *ptr, unsigned len)
  58. {
  59.   unsigned l = sizeof(cdbmp->cdb_buf) - (cdbmp->cdb_bpos - cdbmp->cdb_buf);
  60.   cdbmp->cdb_dpos += len;
  61.   if (len > l) {
  62.     memcpy(cdbmp->cdb_bpos, ptr, l);
  63.     if (ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf, sizeof(cdbmp->cdb_buf)) < 0)
  64.       return -1;
  65.     ptr += l; len -= l;
  66.     l = len / sizeof(cdbmp->cdb_buf);
  67.     if (l) {
  68.       l *= sizeof(cdbmp->cdb_buf);
  69.       if (ewrite(cdbmp->cdb_fd, ptr, l) < 0)
  70. return -1;
  71.       ptr += l; len -= l;
  72.     }
  73.     cdbmp->cdb_bpos = cdbmp->cdb_buf;
  74.   }
  75.   if (len) {
  76.     memcpy(cdbmp->cdb_bpos, ptr, len);
  77.     cdbmp->cdb_bpos += len;
  78.   }
  79.   return 0;
  80. }
  81. static int
  82. cdb_make_finish_internal(struct cdb_make *cdbmp)
  83. {
  84.   unsigned hcnt[256]; /* hash table counts */
  85.   unsigned hpos[256]; /* hash table positions */
  86.   struct cdb_rec *htab;
  87.   unsigned char *p;
  88.   struct cdb_rl *rl;
  89.   unsigned hsize;
  90.   unsigned t, i;
  91.   if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt)
  92.     return errno = ENOMEM, -1;
  93.   /* count htab sizes and reorder reclists */
  94.   hsize = 0;
  95.   for (t = 0; t < 256; ++t) {
  96.     struct cdb_rl *rlt = NULL;
  97.     i = 0;
  98.     rl = cdbmp->cdb_rec[t];
  99.     while(rl) {
  100.       struct cdb_rl *rln = rl->next;
  101.       rl->next = rlt;
  102.       rlt = rl;
  103.       i += rl->cnt;
  104.       rl = rln;
  105.     }
  106.     cdbmp->cdb_rec[t] = rlt;
  107.     if (hsize < (hcnt[t] = i << 1))
  108.       hsize = hcnt[t];
  109.   }
  110.   /* allocate memory to hold max htable */
  111.   htab = (struct cdb_rec*)malloc((hsize + 2) * sizeof(struct cdb_rec));
  112.   if (!htab)
  113.     return errno = ENOENT, -1;
  114.   p = (unsigned char *)htab;
  115.   htab += 2;
  116.   /* build hash tables */
  117.   for (t = 0; t < 256; ++t) {
  118.     unsigned len, hi;
  119.     hpos[t] = cdbmp->cdb_dpos;
  120.     if ((len = hcnt[t]) == 0)
  121.       continue;
  122.     for (i = 0; i < len; ++i)
  123.       htab[i].hval = htab[i].rpos = 0;
  124.     for (rl = cdbmp->cdb_rec[t]; rl; rl = rl->next)
  125.       for (i = 0; i < rl->cnt; ++i) {
  126. hi = (rl->rec[i].hval >> 8) % len;
  127. while(htab[hi].rpos)
  128.   if (++hi == len)
  129.     hi = 0;
  130. htab[hi] = rl->rec[i];
  131.       }
  132.     for (i = 0; i < len; ++i) {
  133.       cdb_pack(htab[i].hval, p + (i << 3));
  134.       cdb_pack(htab[i].rpos, p + (i << 3) + 4);
  135.     }
  136.     if (_cdb_make_write(cdbmp, p, len << 3) < 0) {
  137.       free(p);
  138.       return -1;
  139.     }
  140.   }
  141.   free(p);
  142.   if (cdbmp->cdb_bpos != cdbmp->cdb_buf &&
  143.       ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf,
  144.      cdbmp->cdb_bpos - cdbmp->cdb_buf) != 0)
  145.       return -1;
  146.   p = cdbmp->cdb_buf;
  147.   for (t = 0; t < 256; ++t) {
  148.     cdb_pack(hpos[t], p + (t << 3));
  149.     cdb_pack(hcnt[t], p + (t << 3) + 4);
  150.   }
  151.   rewind(cdbmp->cdb_fd);
  152.   if (ewrite(cdbmp->cdb_fd, p, 2048) != 0)
  153.     return -1;
  154.   return 0;
  155. }
  156. static void
  157. cdb_make_free(struct cdb_make *cdbmp)
  158. {
  159.   unsigned t;
  160.   for(t = 0; t < 256; ++t) {
  161.     struct cdb_rl *rl = cdbmp->cdb_rec[t];
  162.     while(rl) {
  163.       struct cdb_rl *tm = rl;
  164.       rl = rl->next;
  165.       free(tm);
  166.     }
  167.   }
  168. }
  169. int
  170. cdb_make_finish(struct cdb_make *cdbmp)
  171. {
  172.   int r = cdb_make_finish_internal(cdbmp);
  173.   cdb_make_free(cdbmp);
  174.   return r;
  175. }