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

📄 tchdb.c

📁 高性能嵌入式数据库在高并发的环境下使用最好是64位系统比较好
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* Set the custom codec functions of a hash database object. */bool tchdbsetcodecfunc(TCHDB *hdb, HDBCODEC enc, void *encop, HDBCODEC dec, void *decop){  assert(hdb && enc && dec);  if(!HDBLOCKMETHOD(hdb, true)) return false;  if(hdb->fd >= 0){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return false;  }  hdb->enc = enc;  hdb->encop = encop;  hdb->dec = dec;  hdb->decop = decop;  HDBUNLOCKMETHOD(hdb);  return true;}/* Get the custom codec functions of a hash database object. */void tchdbcodecfunc(TCHDB *hdb, HDBCODEC *ep, void **eop, HDBCODEC *dp, void **dop){  assert(hdb && ep && eop && dp && dop);  *ep = hdb->enc;  *eop = hdb->encop;  *dp = hdb->dec;  *dop = hdb->decop;}/* Retrieve the next record of a record in a hash database object. */void *tchdbgetnext(TCHDB *hdb, const void *kbuf, int ksiz, int *sp){  assert(hdb && sp);  if(!HDBLOCKMETHOD(hdb, true)) return NULL;  if(hdb->fd < 0){    tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__);    HDBUNLOCKMETHOD(hdb);    return NULL;  }  if(hdb->async && !tchdbflushdrp(hdb)){    HDBUNLOCKMETHOD(hdb);    return NULL;  }  char *rv = tchdbgetnextimpl(hdb, kbuf, ksiz, sp);  HDBUNLOCKMETHOD(hdb);  return rv;}/* Retrieve the next record of a string record in a hash database object. */char *tchdbgetnext2(TCHDB *hdb, const char *kstr){  assert(hdb);  int vsiz;  return tchdbgetnext(hdb, kstr, strlen(kstr), &vsiz);}/************************************************************************************************* * private features *************************************************************************************************//* 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 tcseekwrite(TCHDB *hdb, off_t off, const void *buf, size_t size){  assert(hdb && off >= 0 && buf && size >= 0);  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 tcseekread(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 tcseekreadtry(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 tcdumpmeta(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 tcloadmeta(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);}/* Get a natural prime number not less than a floor number.   `num' specified the floor number.   The return value is a prime number not less than the floor number. */static uint64_t tcgetprime(uint64_t num){  uint64_t primes[] = {    1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 43, 47, 53, 59, 61, 71, 79, 83,    89, 103, 109, 113, 127, 139, 157, 173, 191, 199, 223, 239, 251, 283, 317, 349,    383, 409, 443, 479, 509, 571, 631, 701, 761, 829, 887, 953, 1021, 1151, 1279,    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, 0  };  int i;  for(i = 0; primes[i] > 0; i++){    if(num <= primes[i]) return primes[i];  }  return primes[i-1];}/* 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->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->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;

⌨️ 快捷键说明

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