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

📄 tcfdb.c

📁 高性能嵌入式数据库在高并发的环境下使用最好是64位系统比较好
💻 C
📖 第 1 页 / 共 4 页
字号:
    uint32_t lnum;    switch(fdb->wsiz){    case 1:      osiz = *(rp++);      break;    case 2:      memcpy(&snum, rp, sizeof(snum));      osiz = TCITOHS(snum);      rp += sizeof(snum);      break;    default:      memcpy(&lnum, rp, sizeof(lnum));      osiz = TCITOHL(lnum);      rp += sizeof(lnum);      break;    }    if(osiz > 0 || *rp != 0) return id;    id++;  }  return 0;}/* Store a record.   `fdb' specifies the fixed-length database object.   `id' specifies the ID number.   `vbuf' specifies the pointer to the region of the value.   `vsiz' specifies the size of the region of the value.   `dmode' specifies behavior when the key overlaps.   If successful, the return value is true, else, it is false. */static bool tcfdbputimpl(TCFDB *fdb, int64_t id, const void *vbuf, int vsiz, int dmode){  assert(fdb && id > 0 && vbuf && vsiz >= 0);  if(vsiz > fdb->width) vsiz = fdb->width;  TCDODEBUG(fdb->cnt_readrec++);  unsigned char *rec = fdb->array + (id - 1) * (fdb->rsiz);  uint64_t nsiz = FDBHEADSIZ + id * fdb->rsiz;  if(nsiz > fdb->fsiz){    if(nsiz > fdb->limsiz){      tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);      return false;    }    if(!FDBLOCKATTR(fdb)) return false;    if(nsiz > fdb->fsiz){      if(nsiz + fdb->rsiz * FDBTRUNCALW < fdb->limsiz) nsiz += fdb->rsiz * FDBTRUNCALW;      if(ftruncate(fdb->fd, nsiz) == -1){        tcfdbsetecode(fdb, TCETRUNC, __FILE__, __LINE__, __func__);        FDBUNLOCKATTR(fdb);        return false;      }      TCDODEBUG(fdb->cnt_truncfile++);      fdb->fsiz = nsiz;      unsigned char *wp = rec;      uint16_t snum;      uint32_t lnum;      switch(fdb->wsiz){      case 1:        *(wp++) = vsiz;        break;      case 2:        snum = TCHTOIS(vsiz);        memcpy(wp, &snum, sizeof(snum));        wp += sizeof(snum);        break;      default:        lnum = TCHTOIL(vsiz);        memcpy(wp, &lnum, sizeof(lnum));        wp += sizeof(lnum);        break;      }      if(vsiz > 0){        memcpy(wp, vbuf, vsiz);      } else {        *wp = 1;      }      TCDODEBUG(fdb->cnt_writerec++);      fdb->rnum++;      if(fdb->min < 1 || id < fdb->min) fdb->min = id;      if(fdb->max < 1 || id > fdb->max) fdb->max = id;      FDBUNLOCKATTR(fdb);      return true;    }    FDBUNLOCKATTR(fdb);  }  unsigned char *rp = rec;  uint32_t osiz;  uint16_t snum;  uint32_t lnum;  switch(fdb->wsiz){  case 1:    osiz = *(rp++);    break;  case 2:    memcpy(&snum, rp, sizeof(snum));    osiz = TCITOHS(snum);    rp += sizeof(snum);    break;  default:    memcpy(&lnum, rp, sizeof(lnum));    osiz = TCITOHL(lnum);    rp += sizeof(lnum);    break;  }  bool miss = osiz == 0 && *rp == 0;  if(dmode != FDBPDOVER && !miss){    if(dmode == FDBPDKEEP){      tcfdbsetecode(fdb, TCEKEEP, __FILE__, __LINE__, __func__);      return false;    }    if(dmode == FDBPDCAT){      vsiz = tclmin(vsiz, fdb->width - osiz);      unsigned char *wp = rec;      int usiz = osiz + vsiz;      switch(fdb->wsiz){      case 1:        *(wp++) = usiz;        break;      case 2:        snum = TCHTOIS(usiz);        memcpy(wp, &snum, sizeof(snum));        wp += sizeof(snum);        break;      default:        lnum = TCHTOIL(usiz);        memcpy(wp, &lnum, sizeof(lnum));        wp += sizeof(lnum);        break;      }      if(usiz > 0){        memcpy(wp + osiz, vbuf, vsiz);      } else {        *wp = 1;      }      TCDODEBUG(fdb->cnt_writerec++);      return true;    }    if(dmode == FDBPDADDINT){      if(osiz != sizeof(int)){        tcfdbsetecode(fdb, TCEKEEP, __FILE__, __LINE__, __func__);        return false;      }      int lnum;      memcpy(&lnum, rp, sizeof(lnum));      if(*(int *)vbuf == 0){        *(int *)vbuf = lnum;        return true;      }      lnum += *(int *)vbuf;      *(int *)vbuf = lnum;      memcpy(rp, &lnum, sizeof(lnum));      return true;    }    if(dmode == FDBPDADDDBL){      if(osiz != sizeof(double)){        tcfdbsetecode(fdb, TCEKEEP, __FILE__, __LINE__, __func__);        return false;      }      double dnum;      memcpy(&dnum, rp, sizeof(dnum));      if(*(double *)vbuf == 0.0){        *(double *)vbuf = dnum;        return true;      }      dnum += *(double *)vbuf;      *(double *)vbuf = dnum;      memcpy(rp, &dnum, sizeof(dnum));      return true;    }  }  unsigned char *wp = rec;  switch(fdb->wsiz){  case 1:    *(wp++) = vsiz;    break;  case 2:    snum = TCHTOIS(vsiz);    memcpy(wp, &snum, sizeof(snum));    wp += sizeof(snum);    break;  default:    lnum = TCHTOIL(vsiz);    memcpy(wp, &lnum, sizeof(lnum));    wp += sizeof(lnum);    break;  }  if(vsiz > 0){    memcpy(wp, vbuf, vsiz);  } else {    *wp = 1;  }  TCDODEBUG(fdb->cnt_writerec++);  if(miss){    if(!FDBLOCKATTR(fdb)) return false;    fdb->rnum++;    if(fdb->min < 1 || id < fdb->min) fdb->min = id;    if(fdb->max < 1 || id > fdb->max) fdb->max = id;    FDBUNLOCKATTR(fdb);  }  return true;}/* Remove a record of a fixed-length database object.   `fdb' specifies the fixed-length database object.   `id' specifies the ID number.   If successful, the return value is true, else, it is false. */static bool tcfdboutimpl(TCFDB *fdb, int64_t id){  assert(fdb && id >= 0);  TCDODEBUG(fdb->cnt_readrec++);  unsigned char *rec = fdb->array + (id - 1) * (fdb->rsiz);  uint64_t nsiz = FDBHEADSIZ + id * fdb->rsiz;  if(nsiz > fdb->fsiz){    tcfdbsetecode(fdb, TCENOREC, __FILE__, __LINE__, __func__);    return false;  }  unsigned char *rp = rec;  uint32_t osiz;  uint16_t snum;  uint32_t lnum;  switch(fdb->wsiz){  case 1:    osiz = *(rp++);    break;  case 2:    memcpy(&snum, rp, sizeof(snum));    osiz = TCITOHS(snum);    rp += sizeof(snum);    break;  default:    memcpy(&lnum, rp, sizeof(lnum));    osiz = TCITOHL(lnum);    rp += sizeof(lnum);    break;  }  if(osiz == 0 && *rp == 0){    tcfdbsetecode(fdb, TCENOREC, __FILE__, __LINE__, __func__);    return false;  }  memset(rec, 0, fdb->wsiz + 1);  TCDODEBUG(fdb->cnt_writerec++);  if(!FDBLOCKATTR(fdb)) return false;  fdb->rnum--;  if(fdb->rnum < 1){    fdb->min = 0;    fdb->max = 0;  } else if(fdb->rnum < 2){    if(fdb->min == id){      fdb->min = fdb->max;    } else if(fdb->max == id){      fdb->max = fdb->min;    }  } else {    if(id == fdb->min) fdb->min = tcfdbnextid(fdb, id);    if(id == fdb->max) fdb->max = tcfdbprevid(fdb, id);  }  FDBUNLOCKATTR(fdb);  return true;}/* Retrieve a record.   `fdb' specifies the fixed-length database object.   `id' specifies the ID number.   `sp' specifies the pointer to the variable into which the size of the region of the return   value is assigned.   If successful, the return value is the pointer to the region of the value of the corresponding   record. */static const void *tcfdbgetimpl(TCFDB *fdb, int64_t id, int *sp){  assert(fdb && id >= 0 && sp);  TCDODEBUG(fdb->cnt_readrec++);  unsigned char *rec = fdb->array + (id - 1) * (fdb->rsiz);  uint64_t nsiz = FDBHEADSIZ + id * fdb->rsiz;  if(nsiz > fdb->fsiz){    tcfdbsetecode(fdb, TCENOREC, __FILE__, __LINE__, __func__);    return false;  }  unsigned char *rp = rec;  uint32_t osiz;  uint16_t snum;  uint32_t lnum;  switch(fdb->wsiz){  case 1:    osiz = *(rp++);    break;  case 2:    memcpy(&snum, rp, sizeof(snum));    osiz = TCITOHS(snum);    rp += sizeof(snum);    break;  default:    memcpy(&lnum, rp, sizeof(lnum));    osiz = TCITOHL(lnum);    rp += sizeof(lnum);    break;  }  if(osiz == 0 && *rp == 0){    tcfdbsetecode(fdb, TCENOREC, __FILE__, __LINE__, __func__);    return false;  }  *sp = osiz;  return rp;}/* Initialize the iterator of a fixed-length database object.   `fdb' specifies the fixed-length database object.   If successful, the return value is true, else, it is false. */static bool tcfdbiterinitimpl(TCFDB *fdb){  assert(fdb);  fdb->iter = fdb->min;  return true;}/* Get the next key of the iterator of a fixed-length database object.   `fdb' specifies the fixed-length database object.   If successful, the return value is the next ID number of the iterator, else, it is 0. */static uint64_t tcfdbiternextimpl(TCFDB *fdb){  assert(fdb);  if(fdb->iter < 1){    tcfdbsetecode(fdb, TCENOREC, __FILE__, __LINE__, __func__);    return 0;  }  uint64_t cur = fdb->iter;  fdb->iter = tcfdbnextid(fdb, fdb->iter);  return cur;}/* Get range matching ID numbers in a fixed-length database object.   `fdb' specifies the fixed-length database object.   `lower' specifies the lower limit of the range.   `upper' specifies the upper limit of the range.   `max' specifies the maximum number of keys to be fetched.   `np' specifies the pointer to the variable into which the number of elements of the return   value is assigned.   If successful, the return value is the pointer to an array of ID numbers of the corresponding   records. */static uint64_t *tcfdbrangeimpl(TCFDB *fdb, int64_t lower, int64_t upper, int max, int *np){  assert(fdb && lower > 0 && upper > 0 && np);  if(lower < fdb->min) lower = fdb->min;  if(upper > fdb->max) upper = fdb->max;  if(max < 0) max = INT_MAX;  int anum = FDBIDARYUNIT;  uint64_t *ids;  TCMALLOC(ids, anum * sizeof(*ids));  int num = 0;  for(int64_t i = lower; i <= upper && num < max; i++){    int vsiz;    const void *vbuf = tcfdbgetimpl(fdb, i, &vsiz);    if(vbuf){      if(num >= anum){        anum *= 2;        TCREALLOC(ids, ids, anum * sizeof(*ids));      }      ids[num++] = i;    }  }  *np = num;  return ids;}/* Optimize the file of a fixed-length database object.   `fdb' specifies the fixed-length database object.   `width' specifies the width of the value of each record.   `limsiz' specifies the limit size of the database file.   If successful, the return value is true, else, it is false. */static bool tcfdboptimizeimpl(TCFDB *fdb, int32_t width, int64_t limsiz){  assert(fdb);  if(width < 1) width = fdb->width;  if(limsiz < 1) limsiz = fdb->limsiz;  char *tpath = tcsprintf("%s%ctmp%c%llu", fdb->path, MYEXTCHR, MYEXTCHR, fdb->inode);  TCFDB *tfdb = tcfdbnew();  tcfdbtune(tfdb, width, limsiz);  if(!tcfdbopen(tfdb, tpath, FDBOWRITER | FDBOCREAT | FDBOTRUNC)){    tcfdbsetecode(fdb, tfdb->ecode, __FILE__, __LINE__, __func__);    tcfdbdel(tfdb);    TCFREE(tpath);    return false;  }  bool err = false;  int64_t max = fdb->max;  for(int i = fdb->min; !err && i <= max; i++){    int vsiz;    const void *vbuf = tcfdbgetimpl(fdb, i, &vsiz);    if(vbuf && !tcfdbput(tfdb, i, vbuf, vsiz)){      tcfdbsetecode(fdb, tfdb->ecode, __FILE__, __LINE__, __func__);      err = true;    }  }  if(!tcfdbclose(tfdb)){    tcfdbsetecode(fdb, tfdb->ecode, __FILE__, __LINE__, __func__);    err = true;  }  tcfdbdel(tfdb);  if(unlink(fdb->path) == -1){    tcfdbsetecode(fdb, TCEUNLINK, __FILE__, __LINE__, __func__);    err = true;  }  if(rename(tpath, fdb->path) == -1){    tcfdbsetecode(fdb, TCERENAME, __FILE__, __LINE__, __func__);    err = true;  }  TCFREE(tpath);  if(err) return false;  tpath = tcstrdup(fdb->path);  int omode = (fdb->omode & ~FDBOCREAT) & ~FDBOTRUNC;  if(!tcfdbcloseimpl(fdb)){    TCFREE(tpath);    return false;  }  bool rv = tcfdbopenimpl(fdb, tpath, omode);  TCFREE(tpath);  return rv;}/* Remove all records of a fixed-length database object.   `fdb' specifies the fixed-length database object.   If successful, the return value is true, else, it is false. */static bool tcfdbvanishimpl(TCFDB *fdb){  assert(fdb);  char *path = tcstrdup(fdb->path);  int omode = fdb->omode;  bool err = false;  if(!tcfdbcloseimpl(fdb)) err = true;  if(!tcfdbopenimpl(fdb, path, FDBOTRUNC | omode)) err = true;  TCFREE(path);  return !err;}/* Copy the database file of a hash database object.   `fdb' specifies the hash database object.   `path' specifies the path of the destination file.   If successful, the return value is true, else, it is false. */static bool tcfdbcopyimpl(TCFDB *fdb, const char *path){  assert(fdb && path);  bool err = false;  fdb->flags &= ~FDBFOPEN;  if((fdb->omode & FDBOWRITER) && !tcfdbmemsync(fdb, false)) err = true;  if(*path == '@'){    char tsbuf[TCNUMBUFSIZ];    sprintf(tsbuf, "%llu", (unsigned long long)(tctime() * 1000000));    const char *args[3];    args[0] = path + 1;    args[1] = fdb->path;    args[2] = tsbuf;    if(tcsystem(args, sizeof(args) / sizeof(*args)) != 0) err = true;  } else {    if(!tccopyfile(fdb->path, path)){      tcfdbsetecode(fdb, TCEMISC, __FILE__, __LINE__, __func__);      err = true;    }  }  fdb->flags |= FDBFOPEN;  return !err;}/************************************************************************************************* * debugging functions *************************************************************************************************//* Print meta data of the header into the debugging output.   `fdb' specifies the fixed-length database object. */void tcfdbprintmeta(TCFDB *fdb){  assert(fdb);  if(fdb->dbgfd < 0) return;  char buf[FDBIOBUFSIZ];  char *wp = buf;  wp += sprintf(wp, "META:");  wp += sprintf(wp, " mmtx=%p", (void *)fdb->mmtx);  wp += sprintf(wp, " amtx=%p", (void *)fdb->amtx);  wp += sprintf(wp, " rmtxs=%p", (void *)fdb->rmtxs);  wp += sprintf(wp, " eckey=%p", (void *)fdb->eckey);  wp += sprintf(wp, " type=%02X", fdb->type);  wp += sprintf(wp, " flags=%02X", fdb->flags);  wp += sprintf(wp, " width=%u", fdb->width);  wp += sprintf(wp, " limsiz=%llu", (unsigned long long)fdb->limsiz);  wp += sprintf(wp, " wsiz=%u", fdb->wsiz);  wp += sprintf(wp, " rsiz=%u", fdb->rsiz);  wp += sprintf(wp, " limid=%llu", (unsigned long long)fdb->limid);  wp += sprintf(wp, " path=%s", fdb->path ? fdb->path : "-");  wp += sprintf(wp, " fd=%d", fdb->fd);  wp += sprintf(wp, " omode=%u", fdb->omode);  wp += sprintf(wp, " rnum=%llu", (unsigned long long)fdb->rnum);  wp += sprintf(wp, " fsiz=%llu", (unsigned long long)fdb->fsiz);  wp += sprintf(wp, " min=%llu", (unsigned long long)fdb->min);  wp += sprintf(wp, " max=%llu", (unsigned long long)fdb->max);  wp += sprintf(wp, " iter=%llu", (unsigned long long)fdb->iter);  wp += sprintf(wp, " map=%p", (void *)fdb->map);  wp += sprintf(wp, " array=%p", (void *)fdb->array);  wp += sprintf(wp, " ecode=%d", fdb->ecode);  wp += sprintf(wp, " fatal=%u", fdb->fatal);  wp += sprintf(wp, " inode=%llu", (unsigned long long)fdb->inode);  wp += sprintf(wp, " mtime=%llu", (unsigned long long)fdb->mtime);  wp += sprintf(wp, " dbgfd=%d", fdb->dbgfd);  wp += sprintf(wp, " cnt_writerec=%lld", (long long)fdb->cnt_writerec);  wp += sprintf(wp, " cnt_readrec=%lld", (long long)fdb->cnt_readrec);  wp += sprintf(wp, " cnt_truncfile=%lld", (long long)fdb->cnt_truncfile);  *(wp++) = '\n';  tcwrite(fdb->dbgfd, buf, wp - buf);}// END OF FILE

⌨️ 快捷键说明

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