📄 tchdb.c
字号:
bool tchdbhasmutex(TCHDB *hdb){ assert(hdb); return hdb->mmtx != NULL;}/* Synchronize updating contents on memory of a hash database object. */bool tchdbmemsync(TCHDB *hdb, bool phys){ assert(hdb); if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return false; } bool err = false; char hbuf[HDBHEADSIZ]; tchdbdumpmeta(hdb, hbuf); memcpy(hdb->map, hbuf, HDBOPAQUEOFF); if(phys){ size_t xmsiz = (hdb->xmsiz > hdb->msiz) ? hdb->xmsiz : hdb->msiz; if(msync(hdb->map, xmsiz, MS_SYNC) == -1){ tchdbsetecode(hdb, TCEMMAP, __FILE__, __LINE__, __func__); err = true; } if(fsync(hdb->fd) == -1){ tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__); err = true; } } return !err;}/* Clear the cache of a hash tree database object. */bool tchdbcacheclear(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return false; } if(hdb->recc) tcmdbvanish(hdb->recc); return true;}/* Get the number of elements of the bucket array of a hash database object. */uint64_t tchdbbnum(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->bnum;}/* Get the record alignment a hash database object. */uint32_t tchdbalign(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->align;}/* Get the maximum number of the free block pool of a a hash database object. */uint32_t tchdbfbpmax(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->fbpmax;}/* Get the size of the extra mapped memory of a hash database object. */uint64_t tchdbxmsiz(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->xmsiz;}/* Get the inode number of the database file of a hash database object. */uint64_t tchdbinode(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->inode;}/* Get the modification time of the database file of a hash database object. */time_t tchdbmtime(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->mtime;}/* Get the connection mode of a hash database object. */int tchdbomode(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->omode;}/* Get the database type of a hash database object. */uint8_t tchdbtype(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->type;}/* Get the additional flags of a hash database object. */uint8_t tchdbflags(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->flags;}/* Get the options of a hash database object. */uint8_t tchdbopts(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return hdb->opts;}/* Get the pointer to the opaque field of a hash database object. */char *tchdbopaque(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return NULL; } return hdb->map + HDBOPAQUEOFF;}/* Get the number of used elements of the bucket array of a hash database object. */uint64_t tchdbbnumused(TCHDB *hdb){ assert(hdb); if(hdb->fd < 0){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } uint64_t unum = 0; if(hdb->ba64){ uint64_t *buckets = hdb->ba64; for(int i = 0; i < hdb->bnum; i++){ if(buckets[i]) unum++; } } else { uint32_t *buckets = hdb->ba32; for(int i = 0; i < hdb->bnum; i++){ if(buckets[i]) unum++; } } return unum;}/* Set the custom codec functions of a hash database object. */bool tchdbsetcodecfunc(TCHDB *hdb, TCCODEC enc, void *encop, TCCODEC 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;}/* Store a record into a hash database object with a duplication handler. */bool tchdbputproc(TCHDB *hdb, const void *kbuf, int ksiz, const char *vbuf, int vsiz, TCPDPROC proc, void *op){ assert(hdb && kbuf && ksiz >= 0 && proc); if(!HDBLOCKMETHOD(hdb, false)) return false; 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 false; } if(hdb->async && !tchdbflushdrp(hdb)){ HDBUNLOCKMETHOD(hdb); return false; } if(!HDBLOCKRECORD(hdb, bidx, true)){ HDBUNLOCKMETHOD(hdb); return false; } if(hdb->zmode){ char *zbuf; int osiz; char *obuf = tchdbgetimpl(hdb, kbuf, ksiz, bidx, hash, &osiz); if(obuf){ int nsiz; char *nbuf = proc(obuf, osiz, &nsiz, op); if(nbuf == (void *)-1){ bool rv = tchdboutimpl(hdb, kbuf, ksiz, bidx, hash); TCFREE(obuf); HDBUNLOCKRECORD(hdb, bidx); HDBUNLOCKMETHOD(hdb); return rv; } else if(nbuf){ if(hdb->opts & HDBTDEFLATE){ zbuf = _tc_deflate(nbuf, nsiz, &vsiz, _TCZMRAW); } else if(hdb->opts & HDBTBZIP){ zbuf = _tc_bzcompress(nbuf, nsiz, &vsiz); } else if(hdb->opts & HDBTTCBS){ zbuf = tcbsencode(nbuf, nsiz, &vsiz); } else { zbuf = hdb->enc(nbuf, nsiz, &vsiz, hdb->encop); } TCFREE(nbuf); } else { zbuf = NULL; } TCFREE(obuf); } else if(vbuf){ if(hdb->opts & HDBTDEFLATE){ zbuf = _tc_deflate(vbuf, vsiz, &vsiz, _TCZMRAW); } else if(hdb->opts & HDBTBZIP){ zbuf = _tc_bzcompress(vbuf, vsiz, &vsiz); } else if(hdb->opts & HDBTTCBS){ zbuf = tcbsencode(vbuf, vsiz, &vsiz); } else { zbuf = hdb->enc(vbuf, vsiz, &vsiz, hdb->encop); } } else { tchdbsetecode(hdb, TCENOREC, __FILE__, __LINE__, __func__); HDBUNLOCKRECORD(hdb, bidx); HDBUNLOCKMETHOD(hdb); return false; } if(!zbuf){ tchdbsetecode(hdb, TCEKEEP, __FILE__, __LINE__, __func__); HDBUNLOCKRECORD(hdb, bidx); HDBUNLOCKMETHOD(hdb); return false; } bool rv = tchdbputimpl(hdb, kbuf, ksiz, bidx, hash, zbuf, vsiz, HDBPDOVER); TCFREE(zbuf); HDBUNLOCKRECORD(hdb, bidx); HDBUNLOCKMETHOD(hdb); return rv; } HDBPDPROCOP procop; procop.proc = proc; procop.op = op; HDBPDPROCOP *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 = tchdbputimpl(hdb, kbuf, ksiz, bidx, hash, vbuf, vsiz, HDBPDPROC); if(rbuf != stack) TCFREE(rbuf); HDBUNLOCKRECORD(hdb, bidx); HDBUNLOCKMETHOD(hdb); return rv;}/* Get the custom codec functions of a hash database object. */void tchdbcodecfunc(TCHDB *hdb, TCCODEC *ep, void **eop, TCCODEC *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, NULL, NULL); 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);}/* Retrieve the key and the value of the next record of a record in a hash database object. */char *tchdbgetnext3(TCHDB *hdb, const char *kbuf, int ksiz, int *sp, const char **vbp, int *vsp){ assert(hdb && sp && vbp && vsp); 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, vbp, vsp); HDBUNLOCKMETHOD(hdb); return rv;}/* Process each record atomically of a hash database object. */bool tchdbforeach(TCHDB *hdb, TCITER iter, void *op){ assert(hdb && iter); 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 = tchdbforeachimpl(hdb, iter, op); HDBUNLOCKALLRECORDS(hdb); HDBUNLOCKMETHOD(hdb); return rv;}/* Void the transaction of a hash database object. */bool tchdbtranvoid(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; } hdb->tran = false; HDBUNLOCKMETHOD(hdb); return true;}/************************************************************************************************* * private features *************************************************************************************************//* 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -