📄 tchdb.c
字号:
if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER)){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); HDBUNLOCKMETHOD(hdb); return INT_MIN; } if(hdb->async && !tchdbflushdrp(hdb)){ HDBUNLOCKMETHOD(hdb); return INT_MIN; } if(!HDBLOCKRECORD(hdb, bidx, true)){ HDBUNLOCKMETHOD(hdb); return INT_MIN; } 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 INT_MIN; } num += *(int *)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 INT_MIN; } bool rv = tchdbputimpl(hdb, kbuf, ksiz, bidx, hash, zbuf, zsiz, HDBPDOVER); TCFREE(zbuf); HDBUNLOCKRECORD(hdb, bidx); HDBUNLOCKMETHOD(hdb); return rv ? num : INT_MIN; } bool rv = tchdbputimpl(hdb, kbuf, ksiz, bidx, hash, (char *)&num, sizeof(num), HDBPDADDINT); HDBUNLOCKRECORD(hdb, bidx); HDBUNLOCKMETHOD(hdb); return rv ? num : INT_MIN;}/* 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); if(!HDBLOCKMETHOD(hdb, false)) return nan(""); 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 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 ? num : nan(""); } 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) || hdb->tran){ 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) || hdb->tran){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); HDBUNLOCKMETHOD(hdb); return false; } if(hdb->async && !tchdbflushdrp(hdb)){ HDBUNLOCKMETHOD(hdb); return false; } HDBTHREADYIELD(hdb); 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) || hdb->tran){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); HDBUNLOCKMETHOD(hdb); return false; } if(hdb->async && !tchdbflushdrp(hdb)){ HDBUNLOCKMETHOD(hdb); return false; } HDBTHREADYIELD(hdb); 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){ 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 = tchdbcopyimpl(hdb, path); HDBUNLOCKALLRECORDS(hdb); HDBUNLOCKMETHOD(hdb); return rv;}/* Begin the transaction of a hash database object. */bool tchdbtranbegin(TCHDB *hdb){ assert(hdb); for(double wsec = 1.0 / sysconf(_SC_CLK_TCK); true; wsec *= 2){ if(!HDBLOCKMETHOD(hdb, true)) return false; if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || hdb->fatal){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); HDBUNLOCKMETHOD(hdb); return false; } if(!hdb->tran) break; HDBUNLOCKMETHOD(hdb); if(wsec > 1.0) wsec = 1.0; tcsleep(wsec); } if(hdb->async && !tchdbflushdrp(hdb)){ HDBUNLOCKMETHOD(hdb); return false; } hdb->flags &= ~HDBFOPEN; if(!tchdbmemsync(hdb, false)){ hdb->flags |= HDBFOPEN; HDBUNLOCKMETHOD(hdb); return false; } hdb->flags |= HDBFOPEN; if((hdb->omode & HDBOTSYNC) && fsync(hdb->fd) == -1){ tchdbsetecode(hdb, TCESYNC, __FILE__, __LINE__, __func__); return false; } if(hdb->walfd < 0){ char *tpath = tcsprintf("%s%c%s", hdb->path, MYEXTCHR, HDBWALSUFFIX); int walfd = open(tpath, O_RDWR | O_CREAT | O_TRUNC, HDBFILEMODE); TCFREE(tpath); if(walfd < 0){ int ecode = TCEOPEN; switch(errno){ case EACCES: ecode = TCENOPERM; break; case ENOENT: ecode = TCENOFILE; break; } tchdbsetecode(hdb, ecode, __FILE__, __LINE__, __func__); HDBUNLOCKMETHOD(hdb); return false; } hdb->walfd = walfd; } if(!tchdbwalinit(hdb)){ HDBUNLOCKMETHOD(hdb); return false; } hdb->tran = true; HDBUNLOCKMETHOD(hdb); return true;}/* Commit the transaction of a hash database object. */bool tchdbtrancommit(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; } bool err = false; if(hdb->async && !tchdbflushdrp(hdb)) err = true; if(!tchdbmemsync(hdb, hdb->omode & HDBOTSYNC)) err = true; if(!err && ftruncate(hdb->walfd, 0) == -1){ tchdbsetecode(hdb, TCETRUNC, __FILE__, __LINE__, __func__); err = true; } hdb->tran = false; HDBUNLOCKMETHOD(hdb); return !err;}/* Abort the transaction of a hash database object. */bool tchdbtranabort(TCHDB *hdb){ assert(hdb); if(!HDBLOCKMETHOD(hdb, true)) return false; if(hdb->fd < 0 || !(hdb->omode & HDBOWRITER) || !hdb->tran){ tchdbsetecode(hdb, TCEINVALID, __FILE__, __LINE__, __func__); HDBUNLOCKMETHOD(hdb); return false; } bool err = false; if(hdb->async && !tchdbflushdrp(hdb)) err = true; if(!tchdbmemsync(hdb, false)) err = true; if(!tchdbwalrestore(hdb, hdb->path)) err = true; char hbuf[HDBHEADSIZ]; if(lseek(hdb->fd, 0, SEEK_SET) == -1){ tchdbsetecode(hdb, TCESEEK, __FILE__, __LINE__, __func__); err = false; } else if(!tcread(hdb->fd, hbuf, HDBHEADSIZ)){ tchdbsetecode(hdb, TCEREAD, __FILE__, __LINE__, __func__); err = false; } else { tchdbloadmeta(hdb, hbuf); } hdb->iter = 0; hdb->xfsiz = 0; hdb->fbpnum = 0; if(hdb->recc) tcmdbvanish(hdb->recc); hdb->tran = false; HDBUNLOCKMETHOD(hdb); return !err;}/* 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 && (hdb->dbgfd != UINT16_MAX || hdb->fatal)){ int dbgfd = (hdb->dbgfd == UINT16_MAX) ? 1 : hdb->dbgfd; 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(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;}/* Check whether mutual exclusion control is set to a hash database object. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -