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

📄 tcfdb.c

📁 高性能嵌入式数据库在高并发的环境下使用最好是64位系统比较好
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Get the inode number of the database file of a fixed-length database object. */uint64_t tcfdbinode(TCFDB *fdb){  assert(fdb);  if(fdb->fd < 0){    tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return fdb->inode;}/* Get the modification time of the database file of a fixed-length database object. */time_t tcfdbmtime(TCFDB *fdb){  assert(fdb);  if(fdb->fd < 0){    tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return fdb->mtime;}/* Get the connection mode of a fixed-length database object. */int tcfdbomode(TCFDB *fdb){  assert(fdb);  if(fdb->fd < 0){    tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return fdb->omode;}/* Get the database type of a fixed-length database object. */uint8_t tcfdbtype(TCFDB *fdb){  assert(fdb);  if(fdb->fd < 0){    tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return fdb->type;}/* Get the additional flags of a fixed-length database object. */uint8_t tcfdbflags(TCFDB *fdb){  assert(fdb);  if(fdb->fd < 0){    tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);    return 0;  }  return fdb->flags;}/* Get the pointer to the opaque field of a fixed-length database object. */char *tcfdbopaque(TCFDB *fdb){  assert(fdb);  if(fdb->fd < 0){    tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__);    return NULL;  }  return fdb->map + FDBOPAQUEOFF;}/* Generate the ID number from arbitrary binary data.   `kbuf' specifies the pointer to the region of the key.   `ksiz' specifies the size of the region of the key.   The return value is the ID number. */int64_t tcfdbkeytoid(const char *kbuf, int ksiz){  assert(kbuf && ksiz >= 0);  if(ksiz == 3 && !memcmp(kbuf, "min", 3)){    return FDBIDMIN;  } else if(ksiz == 4 && !memcmp(kbuf, "prev", 4)){    return FDBIDPREV;  } else if(ksiz == 3 && !memcmp(kbuf, "max", 3)){    return FDBIDMAX;  } else if(ksiz == 4 && !memcmp(kbuf, "next", 4)){    return FDBIDNEXT;  }  int64_t id = 0;  const char *end = kbuf + ksiz;  while(kbuf < end){    int c = *(unsigned char *)(kbuf++);    if(c >= '0' && c <= '9') id = id * 10 + c - '0';  }  return id;}/************************************************************************************************* * private features *************************************************************************************************//* Serialize meta data into a buffer.   `fdb' specifies the fixed-length database object.   `hbuf' specifies the buffer. */static void tcdumpmeta(TCFDB *fdb, char *hbuf){  memset(hbuf, 0, FDBHEADSIZ);  sprintf(hbuf, "%s\n%s:%d\n", FDBMAGICDATA, _TC_FORMATVER, _TC_LIBVER);  memcpy(hbuf + FDBTYPEOFF, &(fdb->type), sizeof(fdb->type));  memcpy(hbuf + FDBFLAGSOFF, &(fdb->flags), sizeof(fdb->flags));  uint64_t llnum;  llnum = fdb->rnum;  llnum = TCHTOILL(llnum);  memcpy(hbuf + FDBRNUMOFF, &llnum, sizeof(llnum));  llnum = fdb->fsiz;  llnum = TCHTOILL(llnum);  memcpy(hbuf + FDBFSIZOFF, &llnum, sizeof(llnum));  llnum = fdb->width;  llnum = TCHTOILL(llnum);  memcpy(hbuf + FDBWIDTHOFF, &llnum, sizeof(llnum));  llnum = fdb->limsiz;  llnum = TCHTOILL(llnum);  memcpy(hbuf + FDBLIMSIZOFF, &llnum, sizeof(llnum));  llnum = fdb->min;  llnum = TCHTOILL(llnum);  memcpy(hbuf + FDBMINOFF, &llnum, sizeof(llnum));  llnum = fdb->max;  llnum = TCHTOILL(llnum);  memcpy(hbuf + FDBMAXOFF, &llnum, sizeof(llnum));}/* Deserialize meta data from a buffer.   `fdb' specifies the fixed-length database object.   `hbuf' specifies the buffer. */static void tcloadmeta(TCFDB *fdb, const char *hbuf){  memcpy(&(fdb->type), hbuf + FDBTYPEOFF, sizeof(fdb->type));  memcpy(&(fdb->flags), hbuf + FDBFLAGSOFF, sizeof(fdb->flags));  uint64_t llnum;  memcpy(&llnum, hbuf + FDBRNUMOFF, sizeof(llnum));  fdb->rnum = TCITOHLL(llnum);  memcpy(&llnum, hbuf + FDBFSIZOFF, sizeof(llnum));  fdb->fsiz = TCITOHLL(llnum);  memcpy(&llnum, hbuf + FDBWIDTHOFF, sizeof(llnum));  fdb->width = TCITOHLL(llnum);  memcpy(&llnum, hbuf + FDBLIMSIZOFF, sizeof(llnum));  fdb->limsiz = TCITOHLL(llnum);  memcpy(&llnum, hbuf + FDBMINOFF, sizeof(llnum));  fdb->min = TCITOHLL(llnum);  memcpy(&llnum, hbuf + FDBMAXOFF, sizeof(llnum));  fdb->max = TCITOHLL(llnum);}/* Clear all members.   `fdb' specifies the fixed-length database object. */static void tcfdbclear(TCFDB *fdb){  assert(fdb);  fdb->mmtx = NULL;  fdb->amtx = NULL;  fdb->rmtxs = NULL;  fdb->eckey = NULL;  fdb->type = TCDBTFIXED;  fdb->flags = 0;  fdb->width = FDBDEFWIDTH;  fdb->limsiz = FDBDEFLIMSIZ;  fdb->wsiz = 0;  fdb->rsiz = 0;  fdb->limid = 0;  fdb->path = NULL;  fdb->fd = -1;  fdb->omode = 0;  fdb->rnum = 0;  fdb->fsiz = 0;  fdb->min = 0;  fdb->max = 0;  fdb->iter = 0;  fdb->map = NULL;  fdb->array = NULL;  fdb->ecode = TCESUCCESS;  fdb->fatal = false;  fdb->inode = 0;  fdb->mtime = 0;  fdb->dbgfd = -1;  fdb->cnt_writerec = -1;  fdb->cnt_readrec = -1;  fdb->cnt_truncfile = -1;  TCDODEBUG(fdb->cnt_writerec = 0);  TCDODEBUG(fdb->cnt_readrec = 0);  TCDODEBUG(fdb->cnt_truncfile = 0);}/* Set the open flag.   `fdb' specifies the fixed-length database object.   `flag' specifies the flag value.   `sign' specifies the sign. */static void tcfdbsetflag(TCFDB *fdb, int flag, bool sign){  assert(fdb);  char *fp = (char *)fdb->map + FDBFLAGSOFF;  if(sign){    *fp |= (uint8_t)flag;  } else {    *fp &= ~(uint8_t)flag;  }  fdb->flags = *fp;}/* Lock a method of the fixed-length database object.   `fdb' specifies the fixed-length database object.   `wr' specifies whether the lock is writer or not.   If successful, the return value is true, else, it is false. */static bool tcfdblockmethod(TCFDB *fdb, bool wr){  assert(fdb);  if(wr ? pthread_rwlock_wrlock(fdb->mmtx) != 0 : pthread_rwlock_rdlock(fdb->mmtx) != 0){    tcfdbsetecode(fdb, TCETHREAD, __FILE__, __LINE__, __func__);    return false;  }  TCTESTYIELD();  return true;}/* Unlock a method of the fixed-length database object.   `fdb' specifies the fixed-length database object.   If successful, the return value is true, else, it is false. */static bool tcfdbunlockmethod(TCFDB *fdb){  assert(fdb);  if(pthread_rwlock_unlock(fdb->mmtx) != 0){    tcfdbsetecode(fdb, TCETHREAD, __FILE__, __LINE__, __func__);    return false;  }  TCTESTYIELD();  return true;}/* Lock the attributes of the fixed-length database object.   `fdb' specifies the fixed-length database object.   If successful, the return value is true, else, it is false. */static bool tcfdblockattr(TCFDB *fdb){  assert(fdb);  if(pthread_mutex_lock(fdb->amtx) != 0){    tcfdbsetecode(fdb, TCETHREAD, __FILE__, __LINE__, __func__);    return false;  }  TCTESTYIELD();  return true;}/* Unlock the attributes of the fixed-length database object.   `fdb' specifies the fixed-length database object.   If successful, the return value is true, else, it is false. */static bool tcfdbunlockattr(TCFDB *fdb){  assert(fdb);  if(pthread_mutex_unlock(fdb->amtx) != 0){    tcfdbsetecode(fdb, TCETHREAD, __FILE__, __LINE__, __func__);    return false;  }  TCTESTYIELD();  return true;}/* Lock a record of the fixed-length database object.   `fdb' specifies the fixed-length database object.   `wr' specifies whether the lock is writer or not.   If successful, the return value is true, else, it is false. */static bool tcfdblockrecord(TCFDB *fdb, bool wr, uint64_t id){  assert(fdb && id > 0);  if(wr ? pthread_rwlock_wrlock((pthread_rwlock_t *)fdb->rmtxs + id % FDBRMTXNUM) != 0 :     pthread_rwlock_rdlock((pthread_rwlock_t *)fdb->rmtxs + id % FDBRMTXNUM) != 0){    tcfdbsetecode(fdb, TCETHREAD, __FILE__, __LINE__, __func__);    return false;  }  TCTESTYIELD();  return true;}/* Unlock a record of the fixed-length database object.   `fdb' specifies the fixed-length database object.   If successful, the return value is true, else, it is false. */static bool tcfdbunlockrecord(TCFDB *fdb, uint64_t id){  assert(fdb);  if(pthread_rwlock_unlock((pthread_rwlock_t *)fdb->rmtxs + id % FDBRMTXNUM) != 0){    tcfdbsetecode(fdb, TCETHREAD, __FILE__, __LINE__, __func__);    return false;  }  TCTESTYIELD();  return true;}/* Lock all records of the hash database object.   `fdb' specifies the hash database object.   `wr' specifies whether the lock is writer or not.   If successful, the return value is true, else, it is false. */static bool tcfdblockallrecords(TCFDB *fdb, bool wr){  assert(fdb);  for(int i = 0; i < FDBRMTXNUM; i++){    if(wr ? pthread_rwlock_wrlock((pthread_rwlock_t *)fdb->rmtxs + i) != 0 :       pthread_rwlock_rdlock((pthread_rwlock_t *)fdb->rmtxs + i) != 0){      while(--i >= 0){        pthread_rwlock_unlock((pthread_rwlock_t *)fdb->rmtxs + i);      }      tcfdbsetecode(fdb, TCETHREAD, __FILE__, __LINE__, __func__);      return false;    }  }  TCTESTYIELD();  return true;}/* Unlock all records of the hash database object.   `fdb' specifies the hash database object.   If successful, the return value is true, else, it is false. */static bool tcfdbunlockallrecords(TCFDB *fdb){  assert(fdb);  bool err = false;  for(int i = FDBRMTXNUM - 1; i >= 0; i--){    if(pthread_rwlock_unlock((pthread_rwlock_t *)fdb->rmtxs + i)) err = true;  }  TCTESTYIELD();  if(err){    tcfdbsetecode(fdb, TCETHREAD, __FILE__, __LINE__, __func__);    return false;  }  return true;}/* Open a database file and connect a fixed-length database object.   `fdb' specifies the fixed-length database object.   `path' specifies the path of the database file.   `omode' specifies the connection mode.   If successful, the return value is true, else, it is false. */static bool tcfdbopenimpl(TCFDB *fdb, const char *path, int omode){  assert(fdb && path);  int mode = O_RDONLY;  if(omode & FDBOWRITER){    mode = O_RDWR;    if(omode & FDBOCREAT) mode |= O_CREAT;  }  int fd = open(path, mode, FDBFILEMODE);  if(fd < 0){    int ecode = TCEOPEN;    switch(errno){    case EACCES: ecode = TCENOPERM; break;    case ENOENT: ecode = TCENOFILE; break;    }    tcfdbsetecode(fdb, ecode, __FILE__, __LINE__, __func__);    return false;  }  if(!(omode & FDBONOLCK)){    if(!tclock(fd, omode & FDBOWRITER, omode & FDBOLCKNB)){      tcfdbsetecode(fdb, TCELOCK, __FILE__, __LINE__, __func__);      close(fd);      return false;    }  }  if((omode & FDBOWRITER) && (omode & FDBOTRUNC)){    if(ftruncate(fd, 0) == -1){      tcfdbsetecode(fdb, TCETRUNC, __FILE__, __LINE__, __func__);      close(fd);      return false;    }  }  struct stat sbuf;  if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){    tcfdbsetecode(fdb, TCESTAT, __FILE__, __LINE__, __func__);    close(fd);    return false;  }  char hbuf[FDBHEADSIZ];  if((omode & FDBOWRITER) && sbuf.st_size < 1){    fdb->flags = 0;    fdb->rnum = 0;    fdb->fsiz = FDBHEADSIZ;    fdb->min = 0;    fdb->max = 0;    tcdumpmeta(fdb, hbuf);    if(!tcwrite(fd, hbuf, FDBHEADSIZ)){      tcfdbsetecode(fdb, TCEWRITE, __FILE__, __LINE__, __func__);      close(fd);      return false;    }    sbuf.st_size = fdb->fsiz;  }  if(lseek(fd, 0, SEEK_SET) == -1){    tcfdbsetecode(fdb, TCESEEK, __FILE__, __LINE__, __func__);    close(fd);    return false;  }  if(!tcread(fd, hbuf, FDBHEADSIZ)){    tcfdbsetecode(fdb, TCEREAD, __FILE__, __LINE__, __func__);    close(fd);    return false;  }  int type = fdb->type;  tcloadmeta(fdb, hbuf);  if(!(omode & FDBONOLCK)){    if(memcmp(hbuf, FDBMAGICDATA, strlen(FDBMAGICDATA)) || fdb->type != type ||       fdb->width < 1 || sbuf.st_size < fdb->fsiz || fdb->limsiz < FDBHEADSIZ ||       fdb->fsiz > fdb->limsiz){      tcfdbsetecode(fdb, TCEMETA, __FILE__, __LINE__, __func__);      close(fd);      return false;    }    if(sbuf.st_size > fdb->fsiz) fdb->fsiz = sbuf.st_size;  }  void *map = mmap(0, fdb->limsiz, PROT_READ | ((omode & FDBOWRITER) ? PROT_WRITE : 0),                   MAP_SHARED, fd, 0);  if(map == MAP_FAILED){    tcfdbsetecode(fdb, TCEMMAP, __FILE__, __LINE__, __func__);    close(fd);    return false;  }  if(fdb->width <= UINT8_MAX){    fdb->wsiz = sizeof(uint8_t);  } else if(fdb->width <= UINT16_MAX){    fdb->wsiz = sizeof(uint16_t);  } else {    fdb->wsiz = sizeof(uint32_t);  }  fdb->rsiz = fdb->width + fdb->wsiz;  fdb->limid = (fdb->limsiz - FDBHEADSIZ) / fdb->rsiz;  fdb->path = tcstrdup(path);  fdb->fd = fd;  fdb->omode = omode;  fdb->iter = 0;  fdb->map = map;  fdb->array = (unsigned char *)map + FDBHEADSIZ;  fdb->ecode = TCESUCCESS;  fdb->fatal = false;  fdb->inode = (uint64_t)sbuf.st_ino;  fdb->mtime = sbuf.st_mtime;  if(fdb->omode & FDBOWRITER) tcfdbsetflag(fdb, FDBFOPEN, true);  return true;}/* Close 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 tcfdbcloseimpl(TCFDB *fdb){  assert(fdb);  bool err = false;  if(fdb->omode & FDBOWRITER) tcfdbsetflag(fdb, FDBFOPEN, false);  TCFREE(fdb->path);  if((fdb->omode & FDBOWRITER) && !tcfdbmemsync(fdb, false)) err = true;  if(munmap(fdb->map, fdb->limsiz) == -1){    tcfdbsetecode(fdb, TCEMMAP, __FILE__, __LINE__, __func__);    err = true;  }  if(close(fdb->fd) == -1){    tcfdbsetecode(fdb, TCECLOSE, __FILE__, __LINE__, __func__);    err = true;  }  fdb->path = NULL;  fdb->fd = -1;  return !err;}/* Get the previous record of a record.   `fdb' specifies the fixed-length database object.   `id' specifies the ID number.   The return value is the ID number of the previous record or 0 if no record corresponds. */static int64_t tcfdbprevid(TCFDB *fdb, int64_t id){  assert(fdb && id >= 0);  id--;  while(id >= fdb->min){    TCDODEBUG(fdb->cnt_readrec++);    unsigned char *rec = fdb->array + (id - 1) * (fdb->rsiz);    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) return id;    id--;  }  return 0;}/* Get the next record of a record.   `fdb' specifies the fixed-length database object.   `id' specifies the ID number.   The return value is the ID number of the next record or 0 if no record corresponds. */static int64_t tcfdbnextid(TCFDB *fdb, int64_t id){  assert(fdb && id >= 0);  id++;  while(id <= fdb->max){    TCDODEBUG(fdb->cnt_readrec++);    unsigned char *rec = fdb->array + (id - 1) * (fdb->rsiz);    unsigned char *rp = rec;    uint32_t osiz;    uint16_t snum;

⌨️ 快捷键说明

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