📄 tchdb.c
字号:
}/* 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); uint8_t hash; uint64_t bidx = tchdbbidx(hdb, kbuf, ksiz, &hash); if(!HDBLOCKMETHOD(hdb, false)) return nan(""); 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; } 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)){ 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)){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); HDBUNLOCKMETHOD(hdb); return false; } if(hdb->async && !tchdbflushdrp(hdb)){ HDBUNLOCKMETHOD(hdb); return false; } 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)){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); HDBUNLOCKMETHOD(hdb); return false; } if(hdb->async && !tchdbflushdrp(hdb)){ HDBUNLOCKMETHOD(hdb); return false; } 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 || !(hdb->omode & HDBOWRITER)){ 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; } bool rv = tchdbcopyimpl(hdb, path); HDBUNLOCKALLRECORDS(hdb); HDBUNLOCKMETHOD(hdb); return rv;}/* 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){ 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(hdb->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;}/* 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]; tcdumpmeta(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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -