⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tchdb.c

📁 Tokyo Cabinet的Tokyo Cabinet 是一个DBM的实现。这里的数据库由一系列key-value对的记录构成。key和value都可以是任意长度的字节序列,既可以是二进制也可以是字符
💻 C
📖 第 1 页 / 共 5 页
字号:
    1399, 1531, 1663, 1789, 1913, 2039, 2297, 2557, 2803, 3067, 3323, 3583, 3833,    4093, 4603, 5119, 5623, 6143, 6653, 7159, 7673, 8191, 9209, 10223, 11261,    12281, 13309, 14327, 15359, 16381, 18427, 20479, 22511, 24571, 26597, 28669,    30713, 32749, 36857, 40949, 45053, 49139, 53239, 57331, 61417, 65521, 73727,    81919, 90107, 98299, 106487, 114679, 122869, 131071, 147451, 163819, 180221,    196597, 212987, 229373, 245759, 262139, 294911, 327673, 360439, 393209, 425977,    458747, 491503, 524287, 589811, 655357, 720887, 786431, 851957, 917503, 982981,    1048573, 1179641, 1310719, 1441771, 1572853, 1703903, 1835003, 1966079,    2097143, 2359267, 2621431, 2883577, 3145721, 3407857, 3670013, 3932153,    4194301, 4718579, 5242877, 5767129, 6291449, 6815741, 7340009, 7864301,    8388593, 9437179, 10485751, 11534329, 12582893, 13631477, 14680063, 15728611,    16777213, 18874367, 20971507, 23068667, 25165813, 27262931, 29360087, 31457269,    33554393, 37748717, 41943023, 46137319, 50331599, 54525917, 58720253, 62914549,    67108859, 75497467, 83886053, 92274671, 100663291, 109051903, 117440509,    125829103, 134217689, 150994939, 167772107, 184549373, 201326557, 218103799,    234881011, 251658227, 268435399, 301989881, 335544301, 369098707, 402653171,    436207613, 469762043, 503316469, 536870909, 603979769, 671088637, 738197503,    805306357, 872415211, 939524087, 1006632947, 1073741789, 1207959503,    1342177237, 1476394991, 1610612711, 1744830457, 1879048183, 2013265907,    2576980349, 3092376431, 3710851741, 4718021527, 6133428047, 7973456459,    10365493393, 13475141413, 17517683831, 22772988923, 29604885677, 38486351381,    50032256819, 65041933867, 84554514043, 109920868241, 153889215497, 0  };  int i;  for(i = 0; primes[i] > 0; i++){    if(num <= primes[i]) return primes[i];  }  return primes[i-1];}/* Seek and read data from a file.   `hdb' specifies the hash database object.   `off' specifies the offset of the region to seek.   `buf' specifies the buffer to store into.   `size' specifies the size of the buffer.   The return value is true if successful, else, it is false. */static bool tchdbseekwrite(TCHDB *hdb, off_t off, const void *buf, size_t size){  assert(hdb && off >= 0 && buf && size >= 0);  if(hdb->tran && !tchdbwalwrite(hdb, off, size)) return false;  off_t end = off + size;  if(end <= hdb->xmsiz){    if(end >= hdb->fsiz && end >= hdb->xfsiz){      uint64_t xfsiz = end + HDBXFSIZINC;      if(ftruncate(hdb->fd, xfsiz) == -1){        tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);        return false;      }      hdb->xfsiz = xfsiz;    }    memcpy(hdb->map + off, buf, size);    return true;  }  if(!TCUBCACHE && off < hdb->xmsiz){    int head = hdb->xmsiz - off;    memcpy(hdb->map + off, buf, head);    off += head;    buf = (char *)buf + head;    size -= head;  }  while(true){    int wb = pwrite(hdb->fd, buf, size, off);    if(wb >= size){      return true;    } else if(wb > 0){      buf = (char *)buf + wb;      size -= wb;      off += wb;    } else if(wb == -1){      if(errno != EINTR){        tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);        return false;      }    } else {      if(size > 0){        tchdbsetecode(hdb, TCEWRITE, __FILE__, __LINE__, __func__);        return false;      }    }  }  return true;}/* Seek and read data from a file.   `hdb' specifies the hash database object.   `off' specifies the offset of the region to seek.   `buf' specifies the buffer to store into.   `size' specifies the size of the buffer.   The return value is true if successful, else, it is false. */static bool tchdbseekread(TCHDB *hdb, off_t off, void *buf, size_t size){  assert(hdb && off >= 0 && buf && size >= 0);  if(off + size <= hdb->xmsiz){    memcpy(buf, hdb->map + off, size);    return true;  }  if(!TCUBCACHE && off < hdb->xmsiz){    int head = hdb->xmsiz - off;    memcpy(buf, hdb->map + off, head);    off += head;    buf = (char *)buf + head;    size -= head;  }  while(true){    int rb = pread(hdb->fd, buf, size, off);    if(rb >= size){      break;    } else if(rb > 0){      buf = (char *)buf + rb;      size -= rb;      off += rb;    } else if(rb == -1){      if(errno != EINTR){        tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);        return false;      }    } else {      if(size > 0){        tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);        return false;      }    }  }  return true;}/* Try to seek and read data from a file.   `hdb' specifies the hash database object.   `off' specifies the offset of the region to seek.   `buf' specifies the buffer to store into.   `size' specifies the size of the buffer.   The return value is true if successful, else, it is false. */static bool tchdbseekreadtry(TCHDB *hdb, off_t off, void *buf, size_t size){  assert(hdb && off >= 0 && buf && size >= 0);  off_t end = off + size;  if(end > hdb->fsiz) return false;  if(end <= hdb->xmsiz){    memcpy(buf, hdb->map + off, size);    return true;  }  if(!TCUBCACHE && off < hdb->xmsiz){    int head = hdb->xmsiz - off;    memcpy(buf, hdb->map + off, head);    off += head;    buf = (char *)buf + head;    size -= head;  }  int rb = pread(hdb->fd, buf, size, off);  if(rb == size) return true;  if(rb == -1) tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);  return false;}/* Serialize meta data into a buffer.   `hdb' specifies the hash database object.   `hbuf' specifies the buffer. */static void tchdbdumpmeta(TCHDB *hdb, char *hbuf){  memset(hbuf, 0, HDBHEADSIZ);  sprintf(hbuf, "%s\n%s:%d\n", HDBMAGICDATA, _TC_FORMATVER, _TC_LIBVER);  memcpy(hbuf + HDBTYPEOFF, &(hdb->type), sizeof(hdb->type));  memcpy(hbuf + HDBFLAGSOFF, &(hdb->flags), sizeof(hdb->flags));  memcpy(hbuf + HDBAPOWOFF, &(hdb->apow), sizeof(hdb->apow));  memcpy(hbuf + HDBFPOWOFF, &(hdb->fpow), sizeof(hdb->fpow));  memcpy(hbuf + HDBOPTSOFF, &(hdb->opts), sizeof(hdb->opts));  uint64_t llnum;  llnum = hdb->bnum;  llnum = TCHTOILL(llnum);  memcpy(hbuf + HDBBNUMOFF, &llnum, sizeof(llnum));  llnum = hdb->rnum;  llnum = TCHTOILL(llnum);  memcpy(hbuf + HDBRNUMOFF, &llnum, sizeof(llnum));  llnum = hdb->fsiz;  llnum = TCHTOILL(llnum);  memcpy(hbuf + HDBFSIZOFF, &llnum, sizeof(llnum));  llnum = hdb->frec;  llnum = TCHTOILL(llnum);  memcpy(hbuf + HDBFRECOFF, &llnum, sizeof(llnum));}/* Deserialize meta data from a buffer.   `hdb' specifies the hash database object.   `hbuf' specifies the buffer. */static void tchdbloadmeta(TCHDB *hdb, const char *hbuf){  memcpy(&(hdb->type), hbuf + HDBTYPEOFF, sizeof(hdb->type));  memcpy(&(hdb->flags), hbuf + HDBFLAGSOFF, sizeof(hdb->flags));  memcpy(&(hdb->apow), hbuf + HDBAPOWOFF, sizeof(hdb->apow));  memcpy(&(hdb->fpow), hbuf + HDBFPOWOFF, sizeof(hdb->fpow));  memcpy(&(hdb->opts), hbuf + HDBOPTSOFF, sizeof(hdb->opts));  uint64_t llnum;  memcpy(&llnum, hbuf + HDBBNUMOFF, sizeof(llnum));  hdb->bnum = TCITOHLL(llnum);  memcpy(&llnum, hbuf + HDBRNUMOFF, sizeof(llnum));  hdb->rnum = TCITOHLL(llnum);  memcpy(&llnum, hbuf + HDBFSIZOFF, sizeof(llnum));  hdb->fsiz = TCITOHLL(llnum);  memcpy(&llnum, hbuf + HDBFRECOFF, sizeof(llnum));  hdb->frec = TCITOHLL(llnum);}/* Clear all members.   `hdb' specifies the hash database object. */static void tchdbclear(TCHDB *hdb){  assert(hdb);  hdb->mmtx = NULL;  hdb->rmtxs = NULL;  hdb->dmtx = NULL;  hdb->tmtx = NULL;  hdb->wmtx = NULL;  hdb->eckey = NULL;  hdb->type = TCDBTHASH;  hdb->flags = 0;  hdb->bnum = HDBDEFBNUM;  hdb->apow = HDBDEFAPOW;  hdb->fpow = HDBDEFFPOW;  hdb->opts = 0;  hdb->path = NULL;  hdb->fd = -1;  hdb->omode = 0;  hdb->rnum = 0;  hdb->fsiz = 0;  hdb->frec = 0;  hdb->iter = 0;  hdb->map = NULL;  hdb->msiz = 0;  hdb->xmsiz = HDBDEFXMSIZ;  hdb->xfsiz = 0;  hdb->ba32 = NULL;  hdb->ba64 = NULL;  hdb->align = 0;  hdb->runit = 0;  hdb->zmode = false;  hdb->fbpmax = 0;  hdb->fbpool = NULL;  hdb->fbpnum = 0;  hdb->fbpmis = 0;  hdb->async = false;  hdb->drpool = NULL;  hdb->drpdef = NULL;  hdb->drpoff = 0;  hdb->recc = NULL;  hdb->rcnum = 0;  hdb->enc = NULL;  hdb->encop = NULL;  hdb->dec = NULL;  hdb->decop = NULL;  hdb->ecode = TCESUCCESS;  hdb->fatal = false;  hdb->inode = 0;  hdb->mtime = 0;  hdb->tran = false;  hdb->walfd = -1;  hdb->walend = 0;  hdb->dbgfd = -1;  hdb->cnt_writerec = -1;  hdb->cnt_reuserec = -1;  hdb->cnt_moverec = -1;  hdb->cnt_readrec = -1;  hdb->cnt_searchfbp = -1;  hdb->cnt_insertfbp = -1;  hdb->cnt_splicefbp = -1;  hdb->cnt_dividefbp = -1;  hdb->cnt_mergefbp = -1;  hdb->cnt_reducefbp = -1;  hdb->cnt_appenddrp = -1;  hdb->cnt_deferdrp = -1;  hdb->cnt_flushdrp = -1;  hdb->cnt_adjrecc = -1;  TCDODEBUG(hdb->cnt_writerec = 0);  TCDODEBUG(hdb->cnt_reuserec = 0);  TCDODEBUG(hdb->cnt_moverec = 0);  TCDODEBUG(hdb->cnt_readrec = 0);  TCDODEBUG(hdb->cnt_searchfbp = 0);  TCDODEBUG(hdb->cnt_insertfbp = 0);  TCDODEBUG(hdb->cnt_splicefbp = 0);  TCDODEBUG(hdb->cnt_dividefbp = 0);  TCDODEBUG(hdb->cnt_mergefbp = 0);  TCDODEBUG(hdb->cnt_reducefbp = 0);  TCDODEBUG(hdb->cnt_appenddrp = 0);  TCDODEBUG(hdb->cnt_deferdrp = 0);  TCDODEBUG(hdb->cnt_flushdrp = 0);  TCDODEBUG(hdb->cnt_adjrecc = 0);}/* Get the padding size to record alignment.   `hdb' specifies the hash database object.   `off' specifies the current offset.   The return value is the padding size. */static int32_t tchdbpadsize(TCHDB *hdb, uint64_t off){  assert(hdb);  int32_t diff = off & (hdb->align - 1);  return (diff > 0) ? hdb->align - diff : 0;}/* Set the open flag.   `hdb' specifies the hash database object.   `flag' specifies the flag value.   `sign' specifies the sign. */static void tchdbsetflag(TCHDB *hdb, int flag, bool sign){  assert(hdb);  char *fp = (char *)hdb->map + HDBFLAGSOFF;  if(sign){    *fp |= (uint8_t)flag;  } else {    *fp &= ~(uint8_t)flag;  }  hdb->flags = *fp;}/* Get the bucket index of a record.   `hdb' specifies the hash database object.   `kbuf' specifies the pointer to the region of the key.   `ksiz' specifies the size of the region of the key.   `hp' specifies the pointer to the variable into which the second hash value is assigned.   The return value is the bucket index. */static uint64_t tchdbbidx(TCHDB *hdb, const char *kbuf, int ksiz, uint8_t *hp){  assert(hdb && kbuf && ksiz >= 0 && hp);  uint64_t idx = 19780211;  uint32_t hash = 751;  const char *rp = kbuf + ksiz;  while(ksiz--){    idx = idx * 37 + *(uint8_t *)kbuf++;    hash = (hash * 31) ^ *(uint8_t *)--rp;  }  *hp = hash;  return idx % hdb->bnum;}/* Get the offset of the record of a bucket element.   `hdb' specifies the hash database object.   `bidx' specifies the index of the bucket.   The return value is the offset of the record. */static off_t tchdbgetbucket(TCHDB *hdb, uint64_t bidx){  assert(hdb && bidx >= 0);  if(hdb->ba64){    uint64_t llnum = hdb->ba64[bidx];    return TCITOHLL(llnum) << hdb->apow;  }  uint32_t lnum = hdb->ba32[bidx];  return (off_t)TCITOHL(lnum) << hdb->apow;}/* Get the offset of the record of a bucket element.   `hdb' specifies the hash database object.   `bidx' specifies the index of the record.   `off' specifies the offset of the record. */static void tchdbsetbucket(TCHDB *hdb, uint64_t bidx, uint64_t off){  assert(hdb && bidx >= 0);  if(hdb->ba64){    uint64_t llnum = off >> hdb->apow;    if(hdb->tran) tchdbwalwrite(hdb, HDBHEADSIZ + bidx * sizeof(llnum), sizeof(llnum));    hdb->ba64[bidx] = TCHTOILL(llnum);  } else {    uint32_t lnum = off >> hdb->apow;    if(hdb->tran) tchdbwalwrite(hdb, HDBHEADSIZ + bidx * sizeof(lnum), sizeof(lnum));    hdb->ba32[bidx] = TCHTOIL(lnum);  }}/* Load the free block pool from the file.   The return value is true if successful, else, it is false. */static bool tchdbsavefbp(TCHDB *hdb){  assert(hdb);  if(hdb->fbpnum > hdb->fbpmax){    tchdbfbpmerge(hdb);  } else if(hdb->fbpnum > 1){    tcfbpsortbyoff(hdb->fbpool, hdb->fbpnum);  }  int bsiz = hdb->frec - hdb->msiz;  char *buf;  TCMALLOC(buf, bsiz);  char *wp = buf;  HDBFB *cur = hdb->fbpool;  HDBFB *end = cur + hdb->fbpnum;  uint64_t base = 0;  bsiz -= sizeof(HDBFB) + sizeof(uint8_t) + sizeof(uint8_t);  while(cur < end && bsiz > 0){    uint64_t noff = cur->off >> hdb->apow;    int step;    uint64_t llnum = noff - base;    TCSETVNUMBUF64(step, wp, llnum);    wp += step;    bsiz -= step;    uint32_t lnum = cur->rsiz >> hdb->apow;    TCSETVNUMBUF(step, wp, lnum);    wp += step;    bsiz -= step;    base = noff;    cur++;  }  *(wp++) = '\0';  *(wp++) = '\0';  if(!tchdbseekwrite(hdb, hdb->msiz, buf, wp - buf)){    TCFREE(buf);    return false;  }  TCFREE(buf);  return true;}/* Save the free block pool into the file.   The ret

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -