📄 tcfdb.c
字号:
} else if(id == FDBIDMAX){ id = fdb->max; } if(id < 1 || id > fdb->limid){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return false; } if(!FDBLOCKRECORD(fdb, false, id)){ FDBUNLOCKMETHOD(fdb); return false; } int vsiz; const void *vbuf = tcfdbgetimpl(fdb, id, &vsiz); if(!vbuf) vsiz = -1; FDBUNLOCKRECORD(fdb, id); FDBUNLOCKMETHOD(fdb); return vsiz;}/* Get the size of the value with a decimal key in a fixed-length database object. */int tcfdbvsiz2(TCFDB *fdb, const void *kbuf, int ksiz){ assert(fdb && kbuf && ksiz >= 0); return tcfdbvsiz(fdb, tcfdbkeytoid(kbuf, ksiz));}/* Get the size of the string value with a decimal key in a fixed-length database object. */int tcfdbvsiz3(TCFDB *fdb, const char *kstr){ assert(fdb && kstr); return tcfdbvsiz(fdb, tcfdbkeytoid(kstr, strlen(kstr)));}/* Initialize the iterator of a fixed-length database object. */bool tcfdbiterinit(TCFDB *fdb){ assert(fdb); if(!FDBLOCKMETHOD(fdb, true)) return false; if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return false; } bool rv = tcfdbiterinitimpl(fdb); FDBUNLOCKMETHOD(fdb); return rv;}/* Get the next ID number of the iterator of a fixed-length database object. */uint64_t tcfdbiternext(TCFDB *fdb){ assert(fdb); if(!FDBLOCKMETHOD(fdb, true)) return false; if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return false; } uint64_t rv = tcfdbiternextimpl(fdb); FDBUNLOCKMETHOD(fdb); return rv;}/* Get the next decimay key of the iterator of a fixed-length database object. */void *tcfdbiternext2(TCFDB *fdb, int *sp){ assert(fdb && sp); uint64_t id = tcfdbiternextimpl(fdb); if(id < 1) return NULL; char kbuf[TCNUMBUFSIZ]; int ksiz = sprintf(kbuf, "%llu", (unsigned long long)id); *sp = ksiz; return tcmemdup(kbuf, ksiz);}/* Get the next decimay key string of the iterator of a fixed-length database object. */char *tcfdbiternext3(TCFDB *fdb){ assert(fdb); int ksiz; return tcfdbiternext2(fdb, &ksiz);}/* Get range matching decimal keys in a fixed-length database object. */uint64_t *tcfdbrange(TCFDB *fdb, int64_t lower, int64_t upper, int max, int *np){ assert(fdb && np); if(!FDBLOCKMETHOD(fdb, true)) return false; if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); *np = 0; return tcmalloc(1); } if(lower == FDBIDMIN) lower = fdb->min; if(upper == FDBIDMAX) upper = fdb->max; if(lower < 1 || lower > fdb->limid || upper < 1 || upper > fdb->limid){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); *np = 0; return tcmalloc(1); } uint64_t *rv = tcfdbrangeimpl(fdb, lower, upper, max, np); FDBUNLOCKMETHOD(fdb); return rv;}/* Get range matching decimal keys in a fixed-length database object. */TCLIST *tcfdbrange2(TCFDB *fdb, const void *lbuf, int lsiz, const void *ubuf, int usiz, int max){ assert(fdb && lbuf && lsiz >= 0 && ubuf && usiz >= 0); int num; uint64_t *ids = tcfdbrange(fdb, tcfdbkeytoid(lbuf, lsiz), tcfdbkeytoid(ubuf, usiz), max, &num); TCLIST *keys = tclistnew2(num); for(int i = 0; i < num; i++){ char kbuf[TCNUMBUFSIZ]; int ksiz = sprintf(kbuf, "%llu", (unsigned long long)ids[i]); TCLISTPUSH(keys, kbuf, ksiz); } TCFREE(ids); return keys;}/* Get range matching decimal keys with strings in a fixed-length database object. */TCLIST *tcfdbrange3(TCFDB *fdb, const char *lstr, const char *ustr, int max){ assert(fdb && lstr && ustr); return tcfdbrange2(fdb, lstr, strlen(lstr), ustr, strlen(ustr), max);}/* Get keys with an interval notation in a fixed-length database object. */TCLIST *tcfdbrange4(TCFDB *fdb, const void *ibuf, int isiz, int max){ assert(fdb && ibuf && isiz >= 0); char *expr; TCMEMDUP(expr, ibuf, isiz); char *pv = expr; while(*pv > '\0' && *pv <= ' '){ pv++; } bool linc = false; if(*pv == '['){ linc = true; } else if(*pv != '('){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); TCFREE(expr); return tclistnew(); } pv++; char *sep = strchr(pv, ','); if(!sep){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); TCFREE(expr); return tclistnew(); } *sep = '\0'; tcstrtrim(pv); int64_t lower = tcfdbkeytoid(pv, strlen(pv)); pv = sep + 1; bool uinc = false; if((sep = strchr(pv, ']')) != NULL){ uinc = true; *sep = '\0'; } else if((sep = strchr(pv, ')')) != NULL){ *sep = '\0'; } else { tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); TCFREE(expr); return tclistnew(); } tcstrtrim(pv); int64_t upper = tcfdbkeytoid(pv, strlen(pv)); if(lower == FDBIDMIN){ lower = fdb->min; } else if(lower == FDBIDPREV){ lower = fdb->min - 1; } else if(lower == FDBIDMAX){ lower = fdb->max; } else if(lower == FDBIDNEXT){ lower = fdb->max + 1; } if(!linc) lower++; if(upper == FDBIDMIN){ upper = fdb->min; } else if(upper == FDBIDPREV){ upper = fdb->min - 1; } else if(upper == FDBIDMAX){ upper = fdb->max; } else if(upper == FDBIDNEXT){ upper = fdb->max + 1; } if(!uinc) upper--; TCFREE(expr); int num; uint64_t *ids = tcfdbrange(fdb, lower, upper, max, &num); TCLIST *keys = tclistnew2(num); for(int i = 0; i < num; i++){ char kbuf[TCNUMBUFSIZ]; int ksiz = sprintf(kbuf, "%llu", (unsigned long long)ids[i]); TCLISTPUSH(keys, kbuf, ksiz); } TCFREE(ids); return keys;}/* Get keys with an interval notation string in a fixed-length database object. */TCLIST *tcfdbrange5(TCFDB *fdb, const void *istr, int max){ assert(fdb && istr); return tcfdbrange4(fdb, istr, strlen(istr), max);}/* Add an integer to a record in a fixed-length database object. */int tcfdbaddint(TCFDB *fdb, int64_t id, int num){ assert(fdb); if(!FDBLOCKMETHOD(fdb, id < 1)) return INT_MIN; if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return INT_MIN; } if(id == FDBIDMIN){ id = fdb->min; } else if(id == FDBIDPREV){ id = fdb->min - 1; } else if(id == FDBIDMAX){ id = fdb->max; } else if(id == FDBIDNEXT){ id = fdb->max + 1; } if(id < 1 || id > fdb->limid){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return INT_MIN; } if(!FDBLOCKRECORD(fdb, true, id)){ FDBUNLOCKMETHOD(fdb); return INT_MIN; } bool rv = tcfdbputimpl(fdb, id, (char *)&num, sizeof(num), FDBPDADDINT); FDBUNLOCKRECORD(fdb, id); FDBUNLOCKMETHOD(fdb); return rv ? num : INT_MIN;}/* Add a real number to a record in a fixed-length database object. */double tcfdbadddouble(TCFDB *fdb, int64_t id, double num){ assert(fdb); if(!FDBLOCKMETHOD(fdb, id < 1)) return nan(""); if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return nan(""); } if(id == FDBIDMIN){ id = fdb->min; } else if(id == FDBIDPREV){ id = fdb->min - 1; } else if(id == FDBIDMAX){ id = fdb->max; } else if(id == FDBIDNEXT){ id = fdb->max + 1; } if(id < 1 || id > fdb->limid){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return nan(""); } if(!FDBLOCKRECORD(fdb, true, id)){ FDBUNLOCKMETHOD(fdb); return nan(""); } bool rv = tcfdbputimpl(fdb, id, (char *)&num, sizeof(num), FDBPDADDDBL); FDBUNLOCKRECORD(fdb, id); FDBUNLOCKMETHOD(fdb); return rv ? num : nan("");}/* Synchronize updated contents of a fixed-length database object with the file and the device. */bool tcfdbsync(TCFDB *fdb){ assert(fdb); if(!FDBLOCKMETHOD(fdb, true)) return false; if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return false; } bool rv = tcfdbmemsync(fdb, true); FDBUNLOCKMETHOD(fdb); return rv;}/* Optimize the file of a fixed-length database object. */bool tcfdboptimize(TCFDB *fdb, int32_t width, int64_t limsiz){ assert(fdb); if(!FDBLOCKMETHOD(fdb, true)) return false; if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return false; } bool rv = tcfdboptimizeimpl(fdb, width, limsiz); FDBUNLOCKMETHOD(fdb); return rv;}/* Remove all records of a fixed-length database object. */bool tcfdbvanish(TCFDB *fdb){ assert(fdb); if(!FDBLOCKMETHOD(fdb, true)) return false; if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return false; } bool rv = tcfdbvanishimpl(fdb); FDBUNLOCKMETHOD(fdb); return rv;}/* Copy the database file of a fixed-length database object. */bool tcfdbcopy(TCFDB *fdb, const char *path){ assert(fdb && path); if(!FDBLOCKMETHOD(fdb, false)) return false; if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return false; } if(!FDBLOCKALLRECORDS(fdb, false)){ FDBUNLOCKMETHOD(fdb); return false; } bool rv = tcfdbcopyimpl(fdb, path); FDBUNLOCKALLRECORDS(fdb); FDBUNLOCKMETHOD(fdb); return rv;}/* Get the file path of a fixed-length database object. */const char *tcfdbpath(TCFDB *fdb){ assert(fdb); if(!FDBLOCKMETHOD(fdb, false)) return NULL; if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return NULL; } const char *rv = fdb->path; FDBUNLOCKMETHOD(fdb); return rv;}/* Get the number of records of a fixed-length database object. */uint64_t tcfdbrnum(TCFDB *fdb){ assert(fdb); if(!FDBLOCKMETHOD(fdb, false)) return 0; if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return 0; } uint64_t rv = fdb->rnum; FDBUNLOCKMETHOD(fdb); return rv;}/* Get the size of the database file of a fixed-length database object. */uint64_t tcfdbfsiz(TCFDB *fdb){ assert(fdb); if(!FDBLOCKMETHOD(fdb, false)) return 0; if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); FDBUNLOCKMETHOD(fdb); return 0; } uint64_t rv = fdb->fsiz; FDBUNLOCKMETHOD(fdb); return rv;}/************************************************************************************************* * features for experts *************************************************************************************************//* Set the error code of a fixed-length database object. */void tcfdbsetecode(TCFDB *fdb, int ecode, const char *filename, int line, const char *func){ assert(fdb && filename && line >= 1 && func); if(!fdb->fatal){ fdb->ecode = ecode; if(fdb->mmtx) pthread_setspecific(*(pthread_key_t *)fdb->eckey, (void *)(intptr_t)ecode); } if(ecode != TCEINVALID && ecode != TCEKEEP && ecode != TCENOREC){ fdb->fatal = true; if(fdb->fd >= 0 && (fdb->omode & FDBOWRITER)) tcfdbsetflag(fdb, FDBFFATAL, true); } if(fdb->dbgfd >= 0){ char obuf[FDBIOBUFSIZ]; int osiz = sprintf(obuf, "ERROR:%s:%d:%s:%s:%d:%s\n", filename, line, func, fdb->path ? fdb->path : "-", ecode, tcfdberrmsg(ecode)); tcwrite(fdb->dbgfd, obuf, osiz); }}/* Set the file descriptor for debugging output. */void tcfdbsetdbgfd(TCFDB *fdb, int fd){ assert(fdb && fd >= 0); fdb->dbgfd = fd;}/* Get the file descriptor for debugging output. */int tcfdbdbgfd(TCFDB *fdb){ assert(fdb); return fdb->dbgfd;}/* Synchronize updating contents on memory of a fixed-length database object. */bool tcfdbmemsync(TCFDB *fdb, bool phys){ assert(fdb); if(fdb->fd < 0 || !(fdb->omode & FDBOWRITER)){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); return false; } bool err = false; char hbuf[FDBHEADSIZ]; tcdumpmeta(fdb, hbuf); memcpy(fdb->map, hbuf, FDBOPAQUEOFF); if(phys){ if(msync(fdb->map, fdb->limsiz, MS_SYNC) == -1){ tcfdbsetecode(fdb, TCEMMAP, __FILE__, __LINE__, __func__); err = true; } if(fsync(fdb->fd) == -1){ tcfdbsetecode(fdb, TCESYNC, __FILE__, __LINE__, __func__); err = true; } } return !err;}/* Get the minimum ID number of records of a fixed-length database object. */uint64_t tcfdbmin(TCFDB *fdb){ assert(fdb); if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return fdb->min;}/* Get the maximum ID number of records of a fixed-length database object. */uint64_t tcfdbmax(TCFDB *fdb){ assert(fdb); if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return fdb->max;}/* Get the width of the value of each record of a fixed-length database object. */uint64_t tcfdbwidth(TCFDB *fdb){ assert(fdb); if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return fdb->width;}/* Get the limit file size of a fixed-length database object. */uint64_t tcfdblimsiz(TCFDB *fdb){ assert(fdb); if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return fdb->limsiz;}/* Get the limit ID number of a fixed-length database object. */uint64_t tcfdblimid(TCFDB *fdb){ assert(fdb); if(fdb->fd < 0){ tcfdbsetecode(fdb, TCEINVALID, __FILE__, __LINE__, __func__); return 0; } return fdb->limid;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -