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

📄 tchdb.c

📁 Tokyo Cabinet的Tokyo Cabinet 是一个DBM的实现。这里的数据库由一系列key-value对的记录构成。key和value都可以是任意长度的字节序列,既可以是二进制也可以是字符
💻 C
📖 第 1 页 / 共 5 页
字号:
  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return INT_MIN;  }  if(hdb->async && !tchdbflushdrp(hdb)){    HDBUNLOCKMETHOD(hdb);    return INT_MIN;  }  if(!HDBLOCKRECORD(hdb, bidx, true)){    HDBUNLOCKMETHOD(hdb);    return INT_MIN;  }  if(hdb->zmode){    char *zbuf;    int osiz;    char *obuf = tchdbgetimpl(hdb, kbuf, ksiz, bidx, hash, &osiz);    if(obuf){      if(osiz != sizeof(num)){        tchdbsetecode(hdb, TCEKEEP, __FILE__, __LINE__, __func__);        TCFREE(obuf);        HDBUNLOCKRECORD(hdb, bidx);        HDBUNLOCKMETHOD(hdb);        return INT_MIN;      }      num += *(int *)obuf;      TCFREE(obuf);    }    int zsiz;    if(hdb->opts & HDBTDEFLATE){      zbuf = _tc_deflate((char *)&num, sizeof(num), &zsiz, _TCZMRAW);    } else if(hdb->opts & HDBTBZIP){      zbuf = _tc_bzcompress((char *)&num, sizeof(num), &zsiz);    } else if(hdb->opts & HDBTTCBS){      zbuf = tcbsencode((char *)&num, sizeof(num), &zsiz);    } else {      zbuf = hdb->enc((char *)&num, sizeof(num), &zsiz, hdb->encop);    }    if(!zbuf){      tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);      HDBUNLOCKRECORD(hdb, bidx);      HDBUNLOCKMETHOD(hdb);      return INT_MIN;    }    bool rv = tchdbputimpl(hdb, kbuf, ksiz, bidx, hash, zbuf, zsiz, HDBPDOVER);    TCFREE(zbuf);    HDBUNLOCKRECORD(hdb, bidx);    HDBUNLOCKMETHOD(hdb);    return rv ? num : INT_MIN;  }  bool rv = tchdbputimpl(hdb, kbuf, ksiz, bidx, hash, (char *)&num, sizeof(num), HDBPDADDINT);  HDBUNLOCKRECORD(hdb, bidx);  HDBUNLOCKMETHOD(hdb);  return rv ? num : INT_MIN;}/* Add a real number to a record in a hash database object. */double tchdbadddouble(TCHDB *hdb, const void *kbuf, int ksiz, double num){  assert(hdb && kbuf && ksiz >= 0);  if(!HDBLOCKMETHOD(hdb, false)) return nan("");  uint8_t hash;  uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash);  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return nan("");  }  if(hdb->async && !tchdbflushdrp(hdb)){    HDBUNLOCKMETHOD(hdb);    return nan("");  }  if(!HDBLOCKRECORD(hdb, bidx, true)){    HDBUNLOCKMETHOD(hdb);    return nan("");  }  if(hdb->zmode){    char *zbuf;    int osiz;    char *obuf = tchdbgetimpl(hdb, kbuf, ksiz, bidx, hash, &osiz);    if(obuf){      if(osiz != sizeof(num)){        tchdbsetecode(hdb, TCEKEEP, __FILE__, __LINE__, __func__);        TCFREE(obuf);        HDBUNLOCKRECORD(hdb, bidx);        HDBUNLOCKMETHOD(hdb);        return nan("");      }      num += *(double *)obuf;      TCFREE(obuf);    }    int zsiz;    if(hdb->opts & HDBTDEFLATE){      zbuf = _tc_deflate((char *)&num, sizeof(num), &zsiz, _TCZMRAW);    } else if(hdb->opts & HDBTBZIP){      zbuf = _tc_bzcompress((char *)&num, sizeof(num), &zsiz);    } else if(hdb->opts & HDBTTCBS){      zbuf = tcbsencode((char *)&num, sizeof(num), &zsiz);    } else {      zbuf = hdb->enc((char *)&num, sizeof(num), &zsiz, hdb->encop);    }    if(!zbuf){      tchdbsetecode(hdb, TCEMISC, __FILE__, __LINE__, __func__);      HDBUNLOCKRECORD(hdb, bidx);      HDBUNLOCKMETHOD(hdb);      return nan("");    }    bool rv = tchdbputimpl(hdb, kbuf, ksiz, bidx, hash, zbuf, zsiz, HDBPDOVER);    TCFREE(zbuf);    HDBUNLOCKRECORD(hdb, bidx);    HDBUNLOCKMETHOD(hdb);    return rv ? num : nan("");  }  bool rv = tchdbputimpl(hdb, kbuf, ksiz, bidx, hash, (char *)&num, sizeof(num), HDBPDADDDBL);  HDBUNLOCKRECORD(hdb, bidx);  HDBUNLOCKMETHOD(hdb);  return rv ? num : nan("");}/* Synchronize updated contents of a hash database object with the file and the device. */bool tchdbsync(TCHDB *hdb){  assert(hdb);  if(!HDBLOCKMETHOD(hdb, true)) return false;  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->tran){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return false;  }  if(hdb->async && !tchdbflushdrp(hdb)){    HDBUNLOCKMETHOD(hdb);    return false;  }  bool rv = tchdbmemsync(hdb, true);  HDBUNLOCKMETHOD(hdb);  return rv;}/* Optimize the file of a hash database object. */bool tchdboptimize(TCHDB *hdb, int64_t bnum, int8_t apow, int8_t fpow, uint8_t opts){  assert(hdb);  if(!HDBLOCKMETHOD(hdb, true)) return false;  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->tran){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return false;  }  if(hdb->async && !tchdbflushdrp(hdb)){    HDBUNLOCKMETHOD(hdb);    return false;  }  HDBTHREADYIELD(hdb);  bool rv = tchdboptimizeimpl(hdb, bnum, apow, fpow, opts);  HDBUNLOCKMETHOD(hdb);  return rv;}/* Remove all records of a hash database object. */bool tchdbvanish(TCHDB *hdb){  assert(hdb);  if(!HDBLOCKMETHOD(hdb, true)) return false;  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->tran){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return false;  }  if(hdb->async && !tchdbflushdrp(hdb)){    HDBUNLOCKMETHOD(hdb);    return false;  }  HDBTHREADYIELD(hdb);  bool rv = tchdbvanishimpl(hdb);  HDBUNLOCKMETHOD(hdb);  return rv;}/* Copy the database file of a hash database object. */bool tchdbcopy(TCHDB *hdb, const char *path){  assert(hdb && path);  if(!HDBLOCKMETHOD(hdb, false)) return false;  if(hdb->fd < 0){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return false;  }  if(hdb->async && !tchdbflushdrp(hdb)){    HDBUNLOCKMETHOD(hdb);    return false;  }  if(!HDBLOCKALLRECORDS(hdb, false)){    HDBUNLOCKMETHOD(hdb);    return false;  }  HDBTHREADYIELD(hdb);  bool rv = tchdbcopyimpl(hdb, path);  HDBUNLOCKALLRECORDS(hdb);  HDBUNLOCKMETHOD(hdb);  return rv;}/* Begin the transaction of a hash database object. */bool tchdbtranbegin(TCHDB *hdb){  assert(hdb);  for(double wsec = 1.0 / sysconf(_SC_CLK_TCK); true; wsec *= 2){    if(!HDBLOCKMETHOD(hdb, true)) return false;    if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->fatal){      tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);      HDBUNLOCKMETHOD(hdb);      return false;    }    if(!hdb->tran) break;    HDBUNLOCKMETHOD(hdb);    if(wsec > 1.0) wsec = 1.0;    tcsleep(wsec);  }  if(hdb->async && !tchdbflushdrp(hdb)){    HDBUNLOCKMETHOD(hdb);    return false;  }  hdb->flags &= ~HDBFOPEN;  if(!tchdbmemsync(hdb, false)){    hdb->flags |= HDBFOPEN;    HDBUNLOCKMETHOD(hdb);    return false;  }  hdb->flags |= HDBFOPEN;  if((hdb->omode & HDBOTSYNC) && fsync(hdb->fd) == -1){    tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__);    return false;  }  if(hdb->walfd < 0){    char *tpath = tcsprintf("%s%c%s", hdb->path, MYEXTCHR, HDBWALSUFFIX);    int walfd = open(tpath, O_RDWR | O_CREAT | O_TRUNC, HDBFILEMODE);    TCFREE(tpath);    if(walfd < 0){      int ecode = TCEOPEN;      switch(errno){      case EACCES: ecode = TCENOPERM; break;      case ENOENT: ecode = TCENOFILE; break;      }      tchdbsetecode(hdb, ecode, __FILE__, __LINE__, __func__);      HDBUNLOCKMETHOD(hdb);      return false;    }    hdb->walfd = walfd;  }  if(!tchdbwalinit(hdb)){    HDBUNLOCKMETHOD(hdb);    return false;  }  hdb->tran = true;  HDBUNLOCKMETHOD(hdb);  return true;}/* Commit the transaction of a hash database object. */bool tchdbtrancommit(TCHDB *hdb){  assert(hdb);  if(!HDBLOCKMETHOD(hdb, true)) return false;  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->fatal || !hdb->tran){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return false;  }  bool err = false;  if(hdb->async && !tchdbflushdrp(hdb)) err = true;  if(!tchdbmemsync(hdb, hdb->omode & HDBOTSYNC)) err = true;  if(!err && ftruncate(hdb->walfd, 0) == -1){    tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__);    err = true;  }  hdb->tran = false;  HDBUNLOCKMETHOD(hdb);  return !err;}/* Abort the transaction of a hash database object. */bool tchdbtranabort(TCHDB *hdb){  assert(hdb);  if(!HDBLOCKMETHOD(hdb, true)) return false;  if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || !hdb->tran){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return false;  }  bool err = false;  if(hdb->async && !tchdbflushdrp(hdb)) err = true;  if(!tchdbmemsync(hdb, false)) err = true;  if(!tchdbwalrestore(hdb, hdb->path)) err = true;  char hbuf[HDBHEADSIZ];  if(lseek(hdb->fd, 0, SEEK_SET) == -1){    tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__);    err = false;  } else if(!tcread(hdb->fd, hbuf, HDBHEADSIZ)){    tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__);    err = false;  } else {    tchdbloadmeta(hdb, hbuf);  }  hdb->iter = 0;  hdb->xfsiz = 0;  hdb->fbpnum = 0;  if(hdb->recc) tcmdbvanish(hdb->recc);  hdb->tran = false;  HDBUNLOCKMETHOD(hdb);  return !err;}/* Get the file path of a hash database object. */const char *tchdbpath(TCHDB *hdb){  assert(hdb);  if(!HDBLOCKMETHOD(hdb, false)) return NULL;  if(hdb->fd < 0){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return NULL;  }  const char *rv = hdb->path;  HDBUNLOCKMETHOD(hdb);  return rv;}/* Get the number of records of a hash database object. */uint64_t tchdbrnum(TCHDB *hdb){  assert(hdb);  if(!HDBLOCKMETHOD(hdb, false)) return 0;  if(hdb->fd < 0){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return 0;  }  uint64_t rv = hdb->rnum;  HDBUNLOCKMETHOD(hdb);  return rv;}/* Get the size of the database file of a hash database object. */uint64_t tchdbfsiz(TCHDB *hdb){  assert(hdb);  if(!HDBLOCKMETHOD(hdb, false)) return 0;  if(hdb->fd < 0){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return 0;  }  uint64_t rv = hdb->fsiz;  HDBUNLOCKMETHOD(hdb);  return rv;}/************************************************************************************************* * features for experts *************************************************************************************************//* Set the error code of a hash database object. */void tchdbsetecode(TCHDB *hdb, int ecode, const char *filename, int line, const char *func){  assert(hdb && filename && line >= 1 && func);  if(!hdb->fatal){    if(hdb->mmtx){      pthread_setspecific(*(pthread_key_t *)hdb->eckey, (void *)(intptr_t)ecode);    } else {      hdb->ecode = ecode;    }  }  if(ecode != TCEINVALID && ecode != TCEKEEP && ecode != TCENOREC){    hdb->fatal = true;    if(hdb->fd >= 0 && (hdb->omode & HDBOWRITER)) tchdbsetflag(hdb, HDBFFATAL, true);  }  if(hdb->dbgfd >= 0 && (hdb->dbgfd != UINT16_MAX || hdb->fatal)){    int dbgfd = (hdb->dbgfd == UINT16_MAX) ? 1 : hdb->dbgfd;    char obuf[HDBIOBUFSIZ];    int osiz = sprintf(obuf, "ERROR:%s:%d:%s:%s:%d:%s\n", filename, line, func,                       hdb->path ? hdb->path : "-", ecode, tchdberrmsg(ecode));    tcwrite(dbgfd, obuf, osiz);  }}/* Set the type of a hash database object. */void tchdbsettype(TCHDB *hdb, uint8_t type){  assert(hdb);  if(hdb->fd >= 0){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    return;  }  hdb->type = type;}/* Set the file descriptor for debugging output. */void tchdbsetdbgfd(TCHDB *hdb, int fd){  assert(hdb && fd >= 0);  hdb->dbgfd = fd;}/* Get the file descriptor for debugging output. */int tchdbdbgfd(TCHDB *hdb){  assert(hdb);  return hdb->dbgfd;}/* Check whether mutual exclusion control is set to a hash database object. */

⌨️ 快捷键说明

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