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

📄 tcbdb.c

📁 Tokyo Cabinet的Tokyo Cabinet 是一个DBM的实现。这里的数据库由一系列key-value对的记录构成。key和value都可以是任意长度的字节序列,既可以是二进制也可以是字符
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Synchronize updating contents on memory of a B+ tree database object. */bool tcbdbmemsync(TCBDB *bdb, bool phys){  assert(bdb);  if(!bdb->open || !bdb->wmode){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return false;  }  bool err = false;  bool clk = BDBLOCKCACHE(bdb);  const char *vbuf;  int vsiz;  TCMAP *leafc = bdb->leafc;  tcmapiterinit(leafc);  while((vbuf = tcmapiternext(leafc, &vsiz)) != NULL){    int rsiz;    BDBLEAF *leaf = (BDBLEAF *)tcmapiterval(vbuf, &rsiz);    if(leaf->dirty && !tcbdbleafsave(bdb, leaf)) err = true;  }  TCMAP *nodec = bdb->nodec;  tcmapiterinit(nodec);  while((vbuf = tcmapiternext(nodec, &vsiz)) != NULL){    int rsiz;    BDBNODE *node = (BDBNODE *)tcmapiterval(vbuf, &rsiz);    if(node->dirty && !tcbdbnodesave(bdb, node)) err = true;  }  if(clk) BDBUNLOCKCACHE(bdb);  tcbdbdumpmeta(bdb);  if(!tchdbmemsync(bdb->hdb, phys)) err = true;  return !err;}/* Clear the cache of a B+ tree database object. */bool tcbdbcacheclear(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return false;  }  bool err = false;  if(TCMAPRNUM(bdb->leafc) > 0){    bool clk = BDBLOCKCACHE(bdb);    TCMAP *leafc = bdb->leafc;    tcmapiterinit(leafc);    int rsiz;    const void *buf;    while((buf = tcmapiternext(leafc, &rsiz)) != NULL){      if(!tcbdbleafcacheout(bdb, (BDBLEAF *)tcmapiterval(buf, &rsiz))) err = true;    }    if(clk) BDBUNLOCKCACHE(bdb);  }  if(TCMAPRNUM(bdb->nodec) > 0){    bool clk = BDBLOCKCACHE(bdb);    TCMAP *nodec = bdb->nodec;    tcmapiterinit(nodec);    int rsiz;    const void *buf;    while((buf = tcmapiternext(nodec, &rsiz)) != NULL){      if(!tcbdbnodecacheout(bdb, (BDBNODE *)tcmapiterval(buf, &rsiz))) err = true;    }    if(clk) BDBUNLOCKCACHE(bdb);  }  return !err;}/* Get the comparison function of a B+ tree database object. */TCCMP tcbdbcmpfunc(TCBDB *bdb){  assert(bdb);  return bdb->cmp;}/* Get the opaque object for the comparison function of a B+ tree database object. */void *tcbdbcmpop(TCBDB *bdb){  assert(bdb);  return bdb->cmpop;}/* Get the maximum number of cached leaf nodes of a B+ tree database object. */uint32_t tcbdblmemb(TCBDB *bdb){  assert(bdb);  return bdb->lmemb;}/* Get the maximum number of cached non-leaf nodes of a B+ tree database object. */uint32_t tcbdbnmemb(TCBDB *bdb){  assert(bdb);  return bdb->nmemb;}/* Get the number of the leaf nodes of B+ tree database object. */uint64_t tcbdblnum(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return bdb->lnum;}/* Get the number of the non-leaf nodes of B+ tree database object. */uint64_t tcbdbnnum(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return bdb->nnum;}/* Get the number of elements of the bucket array of a B+ tree database object. */uint64_t tcbdbbnum(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return tchdbbnum(bdb->hdb);}/* Get the record alignment of a B+ tree database object. */uint32_t tcbdbalign(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return tchdbalign(bdb->hdb);}/* Get the maximum number of the free block pool of a B+ tree database object. */uint32_t tcbdbfbpmax(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return tchdbfbpmax(bdb->hdb);}/* Get the inode number of the database file of a B+ tree database object. */uint64_t tcbdbinode(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return tchdbinode(bdb->hdb);}/* Get the modification time of the database file of a B+ tree database object. */time_t tcbdbmtime(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return tchdbmtime(bdb->hdb);}/* Get the additional flags of a B+ tree database object. */uint8_t tcbdbflags(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return tchdbflags(bdb->hdb);}/* Get the options of a B+ tree database object. */uint8_t tcbdbopts(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return bdb->opts;}/* Get the pointer to the opaque field of a B+ tree database object. */char *tcbdbopaque(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return NULL;  }  return bdb->opaque + BDBOPAQUESIZ;}/* Get the number of used elements of the bucket array of a B+ tree database object. */uint64_t tcbdbbnumused(TCBDB *bdb){  assert(bdb);  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return tchdbbnumused(bdb->hdb);}/* Set the maximum size of each leaf node. */bool tcbdbsetlsmax(TCBDB *bdb, uint32_t lsmax){  assert(bdb);  if(bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return false;  }  bdb->lsmax = (lsmax > 0) ? tclmax(lsmax, BDBMINLSMAX) : BDBDEFLSMAX;  return true;}/* Set the capacity number of records. */bool tcbdbsetcapnum(TCBDB *bdb, uint64_t capnum){  assert(bdb);  if(bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    return false;  }  bdb->capnum = capnum;  return true;}/* Set the custom codec functions of a B+ tree database object. */bool tcbdbsetcodecfunc(TCBDB *bdb, TCCODEC enc, void *encop, TCCODEC dec, void *decop){  assert(bdb && enc && dec);  if(!BDBLOCKMETHOD(bdb, true)) return false;  if(bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    BDBUNLOCKMETHOD(bdb);    return false;  }  bool rv = tchdbsetcodecfunc(bdb->hdb, enc, encop, dec, decop);  BDBUNLOCKMETHOD(bdb);  return rv;}/* Store a new record into a B+ tree database object with backward duplication. */bool tcbdbputdupback(TCBDB *bdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){  assert(bdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);  if(!BDBLOCKMETHOD(bdb, true)) return false;  if(!bdb->open || !bdb->wmode){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    BDBUNLOCKMETHOD(bdb);    return false;  }  bool rv = tcbdbputimpl(bdb, kbuf, ksiz, vbuf, vsiz, BDBPDDUPB);  BDBUNLOCKMETHOD(bdb);  return rv;}/* Store a record into a B+ tree database object with a duplication handler. */bool tcbdbputproc(TCBDB *bdb, const void *kbuf, int ksiz, const char *vbuf, int vsiz,                  TCPDPROC proc, void *op){  assert(bdb && kbuf && ksiz >= 0 && proc);  if(!BDBLOCKMETHOD(bdb, true)) return false;  if(!bdb->open || !bdb->wmode){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    BDBUNLOCKMETHOD(bdb);    return false;  }  BDBPDPROCOP procop;  procop.proc = proc;  procop.op = op;  BDBPDPROCOP *procptr = &procop;  char stack[TCNUMBUFSIZ*2];  char *rbuf;  if(ksiz <= sizeof(stack) - sizeof(procptr)){    rbuf = stack;  } else {    TCMALLOC(rbuf, ksiz + sizeof(procptr));  }  char *wp = rbuf;  memcpy(wp, &procptr, sizeof(procptr));  wp += sizeof(procptr);  memcpy(wp, kbuf, ksiz);  kbuf = rbuf + sizeof(procptr);  bool rv = tcbdbputimpl(bdb, kbuf, ksiz, vbuf, vsiz, BDBPDPROC);  if(rbuf != stack) TCFREE(rbuf);  BDBUNLOCKMETHOD(bdb);  return rv;}/* Store a new string record into a B+ tree database object with backward duplication. */bool tcbdbputdupback2(TCBDB *bdb, const char *kstr, const char *vstr){  assert(bdb && kstr && vstr);  return tcbdbputdupback(bdb, kstr, strlen(kstr), vstr, strlen(vstr));}/* Move a cursor object to the rear of records corresponding a key. */bool tcbdbcurjumpback(BDBCUR *cur, const void *kbuf, int ksiz){  assert(cur && kbuf && ksiz >= 0);  TCBDB *bdb = cur->bdb;  if(!BDBLOCKMETHOD(bdb, false)) return false;  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    BDBUNLOCKMETHOD(bdb);    return false;  }  bool rv = tcbdbcurjumpimpl(cur, kbuf, ksiz, false);  BDBUNLOCKMETHOD(bdb);  return rv;}/* Move a cursor object to the rear of records corresponding a key string. */bool tcbdbcurjumpback2(BDBCUR *cur, const char *kstr){  assert(cur && kstr);  return tcbdbcurjumpback(cur, kstr, strlen(kstr));}/* Process each record atomically of a B+ tree database object. */bool tcbdbforeach(TCBDB *bdb, TCITER iter, void *op){  assert(bdb && iter);  if(!BDBLOCKMETHOD(bdb, true)) return false;  if(!bdb->open){    tcbdbsetecode(bdb, TCEINVALID, __FILE__, __LINE__, __func__);    BDBUNLOCKMETHOD(bdb);    return false;  }  BDBTHREADYIELD(bdb);  bool rv = tcbdbforeachimpl(bdb, iter, op);  BDBUNLOCKMETHOD(bdb);  return rv;}/************************************************************************************************* * private features *************************************************************************************************//* Clear all members.   `bdb' specifies the B+ tree database object. */static void tcbdbclear(TCBDB *bdb){  assert(bdb);  bdb->mmtx = NULL;  bdb->cmtx = NULL;  bdb->hdb = NULL;  bdb->opaque = NULL;  bdb->open = false;  bdb->wmode = false;  bdb->lmemb = BDBDEFLMEMB;  bdb->nmemb = BDBDEFNMEMB;  bdb->opts = 0;  bdb->root = 0;  bdb->first = 0;  bdb->last = 0;  bdb->lnum = 0;  bdb->nnum = 0;  bdb->rnum = 0;  bdb->leafc = NULL;  bdb->nodec = NULL;  bdb->cmp = NULL;  bdb->cmpop = NULL;  bdb->lcnum = BDBDEFLCNUM;  bdb->ncnum = BDBDEFNCNUM;  bdb->lsmax = BDBDEFLSMAX;  bdb->lschk = 0;  bdb->capnum = 0;  bdb->hist = NULL;  bdb->hnum = 0;  bdb->hleaf = 0;  bdb->lleaf = 0;  bdb->tran = false;  bdb->rbopaque = NULL;  bdb->clock = 0;  bdb->cnt_saveleaf = -1;  bdb->cnt_loadleaf = -1;  bdb->cnt_killleaf = -1;  bdb->cnt_adjleafc = -1;  bdb->cnt_savenode = -1;  bdb->cnt_loadnode = -1;  bdb->cnt_adjnodec = -1;  TCDODEBUG(bdb->cnt_saveleaf = 0);  TCDODEBUG(bdb->cnt_loadleaf = 0);  TCDODEBUG(bdb->cnt_killleaf = 0);  TCDODEBUG(bdb->cnt_adjleafc = 0);  TCDODEBUG(bdb->cnt_savenode = 0);  TCDODEBUG(bdb->cnt_loadnode = 0);  TCDODEBUG(bdb->cnt_adjnodec = 0);}/* Serialize meta data into the opaque field.   `bdb' specifies the B+ tree database object. */static void tcbdbdumpmeta(TCBDB *bdb){  assert(bdb);  memset(bdb->opaque, 0, 64);  char *wp = bdb->opaque;  if(bdb->cmp == tccmplexical){    *(uint8_t *)(wp++) = 0x0;  } else if(bdb->cmp == tccmpdecimal){    *(uint8_t *)(wp++) = 0x1;  } else if(bdb->cmp == tccmpint32){    *(uint8_t *)(wp++) = 0x2;  } else if(bdb->cmp == tccmpint64){    *(uint8_t *)(wp++) = 0x3;  } else {    *(uint8_t *)(wp++) = 0xff;  }  wp += 7;  uint32_t lnum;  lnum = bdb->lmemb;  lnum = TCHTOIL(lnum);  memcpy(wp, &lnum, sizeof(lnum));  wp += sizeof(lnum);  lnum = bdb->nmemb;  lnum = TCHTOIL(lnum);  memcpy(wp, &lnum, sizeof(lnum));  wp += sizeof(lnum);  uint64_t llnum;  llnum = bdb->root;  llnum = TCHTOILL(llnum);  memcpy(wp, &llnum, sizeof(llnum));  wp += sizeof(llnum);

⌨️ 快捷键说明

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