static struct tc_conn _tc_get_conn(mapcache_context *ctx, mapcache_tile* tile, int readonly) { struct tc_conn conn; /* create the object */ conn.bdb = tcbdbnew(); mapcache_cache_tc *cache = (mapcache_cache_tc*)tile->tileset->cache; /* open the database */ if(!readonly) { if(!tcbdbopen(conn.bdb, apr_pstrcat(ctx->pool, cache->basedir,"/tc.tcb",NULL), BDBOWRITER | BDBOCREAT)) { int ecode = tcbdbecode(conn.bdb); ctx->set_error(ctx,500, "tokyocabinet open error on %s: %s\n",apr_pstrcat(ctx->pool, cache->basedir,"/tc.tcf",NULL),tcbdberrmsg(ecode)); } conn.readonly = 0; } else { if(!tcbdbopen(conn.bdb, apr_pstrcat(ctx->pool, cache->basedir,"/tc.tcb",NULL), BDBOREADER)) { if(!tcbdbopen(conn.bdb, apr_pstrcat(ctx->pool, cache->basedir,"/tc.tcb",NULL), BDBOWRITER | BDBOCREAT)) { int ecode = tcbdbecode(conn.bdb); ctx->set_error(ctx,500, "tokyocabinet open error on %s: %s\n",apr_pstrcat(ctx->pool, cache->basedir,"/tc.tcf",NULL),tcbdberrmsg(ecode)); } conn.readonly = 0; } conn.readonly = 1; } return conn; }
/* perform optimize command */ static int procoptimize(const char *path, int lmemb, int nmemb, int bnum, int apow, int fpow, TCCMP cmp, int opts, int omode, bool df) { TCBDB *bdb = tcbdbnew(); if (!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd); if (cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb); if (!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb); if (!tcbdbopen(bdb, path, BDBOWRITER | omode)) { printerr(bdb); tcbdbdel(bdb); return 1; } bool err = false; if (df) { if (!tcbdbdefrag(bdb, INT64_MAX)) { printerr(bdb); err = true; } } else { if (!tcbdboptimize(bdb, lmemb, nmemb, bnum, apow, fpow, opts)) { printerr(bdb); err = true; } } if (!tcbdbclose(bdb)) { if (!err) printerr(bdb); err = true; } tcbdbdel(bdb); return err ? 1 : 0; }
dict_t open_dict(const char *fn, int oflags) { int omode = BDBOREADER; dict_t res; if (oflags & O_RDWR) { omode |= BDBOWRITER; } if (oflags & O_TRUNC) { omode |= BDBOTRUNC; } if (oflags & O_CREAT) { omode |= BDBOCREAT; } if (UNLIKELY((res = tcbdbnew()) == NULL)) { goto out; } else if (UNLIKELY(!tcbdbopen(res, fn, omode))) { goto free_out; } /* success, just return the handle we've got */ return res; free_out: tcbdbdel(res); out: return NULL; }
/* perform get command */ static int procget(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int omode, bool px, bool pz) { TCBDB *bdb = tcbdbnew(); if (!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd); if (cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb); if (!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb); if (!tcbdbopen(bdb, path, BDBOREADER | omode)) { printerr(bdb); tcbdbdel(bdb); return 1; } bool err = false; int vsiz; char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz); if (vbuf) { printdata(vbuf, vsiz, px); if (!pz) putchar('\n'); tcfree(vbuf); } else { printerr(bdb); err = true; } if (!tcbdbclose(bdb)) { if (!err) printerr(bdb); err = true; } tcbdbdel(bdb); return err ? 1 : 0; }
/* perform map command */ static int procmap(const char *name, const char *dest, const char *fmstr){ TCADB *adb = tcadbnew(); ADBSKEL skel; if(*name == '@'){ setskeltran(&skel); if(!tcadbsetskel(adb, &skel)){ printerr(adb); skel.del(skel.opq); tcadbdel(adb); return 1; } name++; } else if(*name == '%'){ if(!tcadbsetskelmulti(adb, 8)){ printerr(adb); tcadbdel(adb); return 1; } name++; } if(!tcadbopen(adb, name)){ printerr(adb); tcadbdel(adb); return 1; } bool err = false; TCBDB *bdb = tcbdbnew(); if(!tcbdbopen(bdb, dest, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){ printerr(adb); tcbdbdel(bdb); tcadbdel(adb); return 1; } if(fmstr){ TCLIST *keys = tcadbfwmkeys2(adb, fmstr, -1); if(!tcadbmapbdb(adb, keys, bdb, mapbdbproc, NULL, -1)){ printerr(adb); err = true; } tclistdel(keys); } else { if(!tcadbmapbdb(adb, NULL, bdb, mapbdbproc, NULL, -1)){ printerr(adb); err = true; } } if(!tcbdbclose(bdb)){ printerr(adb); err = true; } tcbdbdel(bdb); if(!tcadbclose(adb)){ printerr(adb); err = true; } tcadbdel(adb); return err ? 1 : 0; }
/* Open the database handle */ TCBDB * tc_bdb_create (const char *dbname, int module) { TCBDB *bdb; char *path = NULL; int ecode; uint32_t lcnum, ncnum, lmemb, nmemb, bnum, flags; path = tc_db_set_path (dbname, module); bdb = tcbdbnew (); lcnum = conf.cache_lcnum > 0 ? conf.cache_lcnum : TC_LCNUM; ncnum = conf.cache_ncnum > 0 ? conf.cache_ncnum : TC_NCNUM; /* set the caching parameters of a B+ tree database object */ if (!tcbdbsetcache (bdb, lcnum, ncnum)) { free (path); FATAL ("Unable to set TCB cache"); } /* set the size of the extra mapped memory */ if (conf.xmmap > 0 && !tcbdbsetxmsiz (bdb, conf.xmmap)) { free (path); FATAL ("Unable to set TCB xmmap."); } lmemb = conf.tune_lmemb > 0 ? conf.tune_lmemb : TC_LMEMB; nmemb = conf.tune_nmemb > 0 ? conf.tune_nmemb : TC_NMEMB; bnum = conf.tune_bnum > 0 ? conf.tune_bnum : TC_BNUM; /* compression */ flags = BDBTLARGE; if (conf.compression == TC_BZ2) { flags |= BDBTBZIP; } else if (conf.compression == TC_ZLIB) { flags |= BDBTDEFLATE; } /* set the tuning parameters */ tcbdbtune (bdb, lmemb, nmemb, bnum, 8, 10, flags); /* open flags */ flags = BDBOWRITER | BDBOCREAT; if (!conf.load_from_disk) flags |= BDBOTRUNC; /* attempt to open the database */ if (!tcbdbopen (bdb, path, flags)) { free (path); ecode = tcbdbecode (bdb); FATAL ("%s", tcbdberrmsg (ecode)); } free (path); return bdb; }
int main(int argc, char **argv){ if (argc != 3) { std::cerr << "Usage: " << argv[0] << " dbname record_num" << std::endl; exit(1); } double t1, t2; int rnum = atoi(argv[2]); int ecode; char *key, *value; t1 = gettimeofday_sec(); TCBDB *bdb = tcbdbnew(); tcbdbtune(bdb, 5, -1, -1, -1, -1, 0); tcbdbsetcache(bdb, 300, 100); if (!tcbdbopen(bdb, argv[1], BDBOWRITER | BDBOCREAT)) { ecode = tcbdbecode(bdb); fprintf(stderr, "open error: %s\n", tcbdberrmsg(ecode)); } for (int i = 0; i < rnum; ++i) { char key[9]; memset(key, 0, 9); sprintf(key,"%08d", i); char *val = new char[307201]; // 100K memset(val, 0, 307201); sprintf(val, "%0102400d", i); sprintf(val + 102400, "%0102400d", i); sprintf(val + 102400*2, "%0102400d", i); int size; void *data = tcbdbget(bdb, key, strlen(key), &size); if (data != NULL) { if (strcmp(val, (char *) data) != 0) { std::cout << "[error] value incorrect." << std::endl; } free(data); } else { std::cout << "[error] entry not found." << std::endl; } delete [] val; } if (!tcbdbclose(bdb)) { ecode = tcbdbecode(bdb); fprintf(stderr, "close error: %s\n", tcbdberrmsg(ecode)); } tcbdbdel(bdb); t2 = gettimeofday_sec(); std::cout << "get time: " << t2 - t1 << std::endl; return 0; }
/* Initialize database. Returns: pointer to database handle on success, NULL otherwise. */ void *db_open(void * dummy, bfpath *bfp, dbmode_t open_mode) { dbh_t *handle; bool res; int open_flags; TCBDB *dbp; UNUSED(dummy); if (open_mode & DS_WRITE) open_flags = BDBOWRITER; else open_flags = BDBOREADER; handle = dbh_init(bfp); if (handle == NULL) return NULL; dbp = handle->dbp = tcbdbnew(); res = tcbdbopen(dbp, handle->name, open_flags); if (!res && (open_mode & DS_WRITE)) { res = tcbdbopen(dbp, handle->name, open_flags | BDBOCREAT); handle->created |= res; } if (!res) goto open_err; if (DEBUG_DATABASE(1)) fprintf(dbgout, "(tc) tcbdbopen( %s, %d )\n", handle->name, open_mode); return handle; open_err: print_error(__FILE__, __LINE__, "(tc) tcbdbopen(%s, %d), err: %d, %s", handle->name, open_flags, tcbdbecode(dbp), tcbdberrmsg(tcbdbecode(dbp))); dbh_free(handle); return NULL; }
/* perform btwrite command */ int dobtwrite(char *name, int rnum, int rnd){ TCBDB *bdb; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("<Writing Test of B+ Tree>\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ bdb = tcbdbnew(); if(rnd){ tcbdbtune(bdb, 77, 256, -1, 0, 0, 0); tcbdbsetcache(bdb, rnum / 77, -1); } else { tcbdbtune(bdb, 101, 256, -1, 0, 0, 0); tcbdbsetcache(bdb, 256, 256); } tcbdbsetxmsiz(bdb, rnum * 32); if(!tcbdbopen(bdb, name, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){ fprintf(stderr, "tcbdbopen failed\n"); tcbdbdel(bdb); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", rnd ? myrand() % rnum + 1 : i); if(!tcbdbput(bdb, buf, len, buf, len)){ fprintf(stderr, "tcbdbput failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(!tcbdbclose(bdb)){ fprintf(stderr, "tcbdbclose failed\n"); tcbdbdel(bdb); return 1; } tcbdbdel(bdb); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; }
/* perform importtsv command */ static int procimporttsv(const char *path, const char *file, int omode, bool sc) { FILE *ifp = file ? fopen(file, "rb") : stdin; if (!ifp) { fprintf(stderr, "%s: could not open\n", file ? file : "(stdin)"); return 1; } TCBDB *bdb = tcbdbnew(); if (!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd); if (!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb); if (!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | omode)) { printerr(bdb); tcbdbdel(bdb); if (ifp != stdin) fclose(ifp); return 1; } bool err = false; char *line; int cnt = 0; while (!err && (line = mygetline(ifp)) != NULL) { char *pv = strchr(line, '\t'); if (!pv) { tcfree(line); continue; } *pv = '\0'; if (sc) tcstrutfnorm(line, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH); if (!tcbdbputdup2(bdb, line, pv + 1)) { printerr(bdb); err = true; } tcfree(line); if (cnt > 0 && cnt % 100 == 0) { putchar('.'); fflush(stdout); if (cnt % 5000 == 0) printf(" (%08d)\n", cnt); } cnt++; } printf(" (%08d)\n", cnt); if (!tcbdbclose(bdb)) { if (!err) printerr(bdb); err = true; } tcbdbdel(bdb); if (ifp != stdin) fclose(ifp); return err ? 1 : 0; }
/* open */ JNIEXPORT jboolean JNICALL Java_tokyocabinet_BDB_open (JNIEnv *env, jobject self, jstring path, jint omode){ if(!path){ throwillarg(env); return false; } TCBDB *bdb = (TCBDB *)(intptr_t)(*env)->GetLongField(env, self, bdb_fid_ptr); jboolean icp; const char *tpath = (*env)->GetStringUTFChars(env, path, &icp); if(!tpath){ throwoutmem(env); return false; } bool rv = tcbdbopen(bdb, tpath, omode); (*env)->ReleaseStringUTFChars(env, path, tpath); return rv; }
static int hcache_open_tc (struct header_cache* h, const char* path) { h->db = tcbdbnew(); if (!h->db) return -1; if (option(OPTHCACHECOMPRESS)) tcbdbtune(h->db, 0, 0, 0, -1, -1, BDBTDEFLATE); if (tcbdbopen(h->db, path, BDBOWRITER | BDBOCREAT)) return 0; else { dprint(2, (debugfile, "tcbdbopen %s failed: %s\n", path, errno)); tcbdbdel(h->db); return -1; } }
/* * Opens the backend database. * * ARGUMENTS: * backend Pointer to pointer to backend structure. Upon * successful return, "*backend" will be set. The client * should call "beClose(*backend)" when the backend is no * longer needed. * path Pathname of the database file. Shall not be NULL. * forWriting Open the database for writing? 0 <=> no * RETURNS: * 0 Success. "*backend" is set. * RDB_SYSERR System error. See "errno". * RDB_DBERR Backend database error. */ RdbStatus beOpen( Backend** const backend, const char* const path, int forWriting) { RdbStatus status; Backend* back = (Backend*)malloc(sizeof(Backend)); if (back == NULL) { status = RDB_SYSERR; } else { TCBDB* bdb = tcbdbnew(); assert(path != NULL); assert(backend != NULL); if (bdb == NULL) { status = RDB_SYSERR; } else { if (!tcbdbopen(bdb, path, forWriting ? BDBOWRITER | BDBOCREAT : BDBOREADER)) { status = RDB_DBERR; } else { back->bdb = bdb; *backend = back; status = 0; } if (status) tcbdbdel(bdb); } /* "bdb" allocated */ if (status) free(back); } /* "back" allocated */ return status; }
/* Open a word database object. `wdb' specifies the word 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 tcwdbopenimpl(TCWDB *wdb, const char *path, int omode){ assert(wdb && path); int bomode = BDBOREADER; if(omode & WDBOWRITER){ bomode = BDBOWRITER; if(omode & WDBOCREAT) bomode |= BDBOCREAT; if(omode & WDBOTRUNC) bomode |= BDBOTRUNC; int64_t bnum = (wdb->etnum / WDBLMEMB) * 2 + 1; int bopts = 0; if(wdb->opts & WDBTLARGE) bopts |= BDBTLARGE; if(wdb->opts & WDBTDEFLATE) bopts |= BDBTDEFLATE; if(wdb->opts & WDBTBZIP) bopts |= BDBTBZIP; if(wdb->opts & WDBTTCBS) bopts |= BDBTTCBS; if(!tcbdbtune(wdb->idx, WDBLMEMB, WDBNMEMB, bnum, WDBAPOW, WDBFPOW, bopts)) return false; if(!tcbdbsetlsmax(wdb->idx, WDBLSMAX)) return false; } if(wdb->lcnum > 0){ if(!tcbdbsetcache(wdb->idx, wdb->lcnum, wdb->lcnum / 4 + 1)) return false; } else { if(!tcbdbsetcache(wdb->idx, (omode & WDBOWRITER) ? WDBLCNUMW : WDBLCNUMR, WDBNCNUM)) return false; } if(omode & WDBONOLCK) bomode |= BDBONOLCK; if(omode & WDBOLCKNB) bomode |= BDBOLCKNB; if(!tcbdbopen(wdb->idx, path, bomode)) return false; if((omode & WDBOWRITER) && tcbdbrnum(wdb->idx) < 1){ memcpy(tcbdbopaque(wdb->idx), WDBMAGICDATA, strlen(WDBMAGICDATA)); } else if(!(omode & WDBONOLCK) && memcmp(tcbdbopaque(wdb->idx), WDBMAGICDATA, strlen(WDBMAGICDATA))){ tcbdbclose(wdb->idx); tcbdbsetecode(wdb->idx, TCEMETA, __FILE__, __LINE__, __func__); return 0; } if(omode & WDBOWRITER){ wdb->cc = tcmapnew2(WDBCCBNUM); wdb->dtokens = tcmapnew2(WDBDTKNBNUM); wdb->dids = tcidsetnew(WDBDIDSBNUM); } wdb->open = true; return true; }
/* perform out command */ static int procout(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int omode) { TCBDB *bdb = tcbdbnew(); if (!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd); if (cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb); if (!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb); if (!tcbdbopen(bdb, path, BDBOWRITER | omode)) { printerr(bdb); tcbdbdel(bdb); return 1; } bool err = false; if (!tcbdbout(bdb, kbuf, ksiz)) { printerr(bdb); err = true; } if (!tcbdbclose(bdb)) { if (!err) printerr(bdb); err = true; } tcbdbdel(bdb); return err ? 1 : 0; }
/* perform create command */ static int proccreate(const char *path, int lmemb, int nmemb, int bnum, int apow, int fpow, TCCMP cmp, int opts) { TCBDB *bdb = tcbdbnew(); if (!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd); if (cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb); if (!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb); if (!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)) { printerr(bdb); tcbdbdel(bdb); return 1; } if (!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC)) { printerr(bdb); tcbdbdel(bdb); return 1; } bool err = false; if (!tcbdbclose(bdb)) { printerr(bdb); err = true; } tcbdbdel(bdb); return err ? 1 : 0; }
/* perform put command */ static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz, TCCMP cmp, int omode, int dmode) { TCBDB *bdb = tcbdbnew(); if (!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd); if (cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb); if (!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb); if (!tcbdbopen(bdb, path, BDBOWRITER | omode)) { printerr(bdb); tcbdbdel(bdb); return 1; } bool err = false; int inum; double dnum; switch (dmode) { case -1: if (!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz)) { printerr(bdb); err = true; } break; case 1: if (!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)) { printerr(bdb); err = true; } break; case 2: if (!tcbdbputdup(bdb, kbuf, ksiz, vbuf, vsiz)) { printerr(bdb); err = true; } break; case 3: if (!tcbdbputdupback(bdb, kbuf, ksiz, vbuf, vsiz)) { printerr(bdb); err = true; } break; case 10: inum = tcbdbaddint(bdb, kbuf, ksiz, tcatoi(vbuf)); if (inum == INT_MIN) { printerr(bdb); err = true; } else { printf("%d\n", inum); } break; case 11: dnum = tcbdbadddouble(bdb, kbuf, ksiz, tcatof(vbuf)); if (isnan(dnum)) { printerr(bdb); err = true; } else { printf("%.6f\n", dnum); } break; default: if (!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)) { printerr(bdb); err = true; } break; } if (!tcbdbclose(bdb)) { if (!err) printerr(bdb); err = true; } tcbdbdel(bdb); return err ? 1 : 0; }
int main(int argc, char *argv[], char *envp[]) { int c; char *synchttp_settings_listen = "0.0.0.0"; int synchttp_settings_port = 2688; char *synchttp_settings_datapath = NULL; bool synchttp_settings_daemon = false; int synchttp_settings_timeout = 60; /* 单位:秒 */ synchttp_settings_syncinterval = 5; /* 单位:秒 */ int synchttp_settings_cachenonleaf = 1024; /* 缓存非叶子节点数。单位:条 */ int synchttp_settings_cacheleaf = 2048; /* 缓存叶子节点数。叶子节点缓存数为非叶子节点数的两倍。单位:条 */ int synchttp_settings_mappedmemory = 104857600; /* 单位:字节 */ synchttp_settings_pidfile = "/tmp/synchttp.pid"; synchttp_settings_auth = NULL; /* 验证密码 */ /* 启动选项 */ while ((c = getopt(argc, argv, "l:p:x:t:s:c:m:i:a:w:dh")) != -1) { switch (c) { case 'l': synchttp_settings_listen = strdup(optarg); break; case 'p': synchttp_settings_port = atoi(optarg); break; case 'x': synchttp_settings_datapath = strdup(optarg); /* synchttp数据库文件存放路径 */ if (access(synchttp_settings_datapath, W_OK) != 0) { /* 如果目录不可写 */ if (access(synchttp_settings_datapath, R_OK) == 0) { /* 如果目录可读 */ chmod(synchttp_settings_datapath, S_IWOTH); /* 设置其他用户具可写入权限 */ } else { /* 如果不存在该目录,则创建 */ create_multilayer_dir(synchttp_settings_datapath); } if (access(synchttp_settings_datapath, W_OK) != 0) { /* 如果目录不可写 */ fprintf(stderr, "synchttp database directory not writable\n"); } } break; case 't': synchttp_settings_timeout = atoi(optarg); break; case 's': synchttp_settings_syncinterval = atoi(optarg); break; case 'c': synchttp_settings_cachenonleaf = atoi(optarg); synchttp_settings_cacheleaf = synchttp_settings_cachenonleaf * 2; break; case 'm': synchttp_settings_mappedmemory = atoi(optarg) * 1024 * 1024; /* 单位:M */ break; case 'i': synchttp_settings_pidfile = strdup(optarg); break; case 'a': synchttp_settings_auth = strdup(optarg); break; case 'd': synchttp_settings_daemon = true; break; case 'h': default: show_help(); return 1; } } /* 判断是否加了必填参数 -x */ if (synchttp_settings_datapath == NULL) { show_help(); fprintf(stderr, "Attention: Please use the indispensable argument: -x <path>\n\n"); exit(1); } /*curl初始化全局信息*/ if ((curl_global_init(CURL_GLOBAL_ALL)) != CURLE_OK) { fprintf(stderr, "Curl global init fail.\n"); exit(1); } /* 数据表路径 */ int synchttp_settings_dataname_len = 1024; char *synchttp_settings_dataname = (char *) tccalloc(1, synchttp_settings_dataname_len); sprintf(synchttp_settings_dataname, "%s/synchttp.db", synchttp_settings_datapath); /* 打开数据表 */ synchttp_db_tcbdb = tcbdbnew(); tcbdbsetmutex(synchttp_db_tcbdb); /* 开启线程互斥锁 */ tcbdbtune(synchttp_db_tcbdb, 1024, 2048, 50000000, 8, 10, BDBTLARGE); tcbdbsetcache(synchttp_db_tcbdb, synchttp_settings_cacheleaf, synchttp_settings_cachenonleaf); tcbdbsetxmsiz(synchttp_db_tcbdb, synchttp_settings_mappedmemory); /* 内存缓存大小 */ /* 判断表是否能打开 */ if (!tcbdbopen(synchttp_db_tcbdb, synchttp_settings_dataname, BDBOWRITER | BDBOCREAT)) { fprintf(stderr, "Attention: Unable to open the database.\n\n"); exit(1); } /* 释放变量所占内存 */ free(synchttp_settings_dataname); /* 如果加了-d参数,以守护进程运行 */ if (synchttp_settings_daemon == true) { pid_t pid; /* Fork off the parent process */ pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } /* If we got a good PID, then we can exit the parent process. */ if (pid > 0) { exit(EXIT_SUCCESS); } } /* 将进程号写入PID文件 */ FILE *fp_pidfile; fp_pidfile = fopen(synchttp_settings_pidfile, "w"); fprintf(fp_pidfile, "%d\n", getpid()); fclose(fp_pidfile); /* 派生synchttp子进程(工作进程) */ pid_t synchttp_worker_pid_wait; pid_t synchttp_worker_pid = fork(); /* 如果派生进程失败,则退出程序 */ if (synchttp_worker_pid < 0) { fprintf(stderr, "Error: %s:%d\n", __FILE__, __LINE__); exit(EXIT_FAILURE); } /* synchttp父进程内容 */ if (synchttp_worker_pid > 0) { /* 处理父进程接收到的kill信号 */ /* 忽略Broken Pipe信号 */ signal(SIGPIPE, SIG_IGN); /* 处理kill信号 */ signal(SIGINT, kill_signal_master); signal(SIGKILL, kill_signal_master); signal(SIGQUIT, kill_signal_master); signal(SIGTERM, kill_signal_master); signal(SIGHUP, kill_signal_master); /* 处理段错误信号 */ signal(SIGSEGV, kill_signal_master); /* 如果子进程终止,则重新派生新的子进程 */ while (1) { synchttp_worker_pid_wait = wait(NULL); if (synchttp_worker_pid_wait < 0) { continue; } usleep(100000); synchttp_worker_pid = fork(); if (synchttp_worker_pid == 0) { break; } } } /*****************************************子进程处理************************************/ /* 忽略Broken Pipe信号 */ signal(SIGPIPE, SIG_IGN); /* 处理kill信号 */ signal(SIGINT, kill_signal_worker); signal(SIGKILL, kill_signal_worker); signal(SIGQUIT, kill_signal_worker); signal(SIGTERM, kill_signal_worker); signal(SIGHUP, kill_signal_worker); /* 处理段错误信号 */ signal(SIGSEGV, kill_signal_worker); /*创建消息队列监听进程*/ pthread_t synchttp_dispatch_tid; pthread_create(&synchttp_dispatch_tid, NULL, (void *) synchttp_dispatch, NULL); /* 创建定时同步线程,定时将内存中的内容写入磁盘 */ pthread_t synchttp_worker_tid; pthread_create(&synchttp_worker_tid, NULL, (void *) synchttp_worker, NULL); /* 外部请求处理部分 */ struct evhttp *synchttpd; event_init(); synchttpd = evhttp_start(synchttp_settings_listen, synchttp_settings_port); if (synchttpd == NULL) { fprintf(stderr, "Error: Unable to listen on %s:%d\n\n", synchttp_settings_listen, synchttp_settings_port); kill(0, SIGTERM); exit(1); } evhttp_set_timeout(synchttpd, synchttp_settings_timeout); evhttp_set_gencb(synchttpd, synchttp_handler, NULL); event_dispatch(); evhttp_free(synchttpd); }
int main(int argc, char* argv[]) { // Parse the command line. if (argc != 3) usage(argv[0]); std::string outputFile = argv[2]; // Open the input file. std::cout << "Processing: " << argv[1] << std::endl; std::ifstream file(argv[1], std::ios_base::in | std::ios_base::binary); if (! file) { std::cerr << "ERROR: Could not open input file: " << argv[1] << std::endl; std::exit(1); } ::boost::iostreams::filtering_istream in; if (file.peek() == 0x1f) in.push(::boost::iostreams::gzip_decompressor()); in.push(file); // Initialise the database. #ifdef QDBM_AS_TOKYOCABINET VILLA* db; if (! (db = vlopen(outputFile.c_str(), VL_OWRITER | VL_OCREAT | VL_OTRUNC | VL_OZCOMP, VL_CMPLEX))) { std::cerr << "ERROR: Could not open QDBM database: " << outputFile << std::endl; std::exit(1); } #else TCBDB* db = tcbdbnew(); if (! tcbdbopen(db, outputFile.c_str(), BDBOWRITER | BDBOCREAT | BDBOTRUNC)) { std::cerr << "ERROR: Could not open Tokyo Cabinet database: " << outputFile << std::endl; std::exit(1); } #endif // Fill the database with the user-supplied key-value pairs. std::string sig, name; const char* pos; unsigned long tot = 0; while (true) { in >> sig; if (in.eof()) break; std::getline(in, name); if (in.eof()) { std::cerr << "ERROR: Signature " << sig << " is missing a corresponding name.\n\n"; DB_CLOSE(db); usage(argv[0]); } // Skip initial whitespace in the manifold name (which will // always be present, since the previous in >> sig // does not eat the separating whitespace). pos = name.c_str(); while (*pos && std::isspace(*pos)) ++pos; if (! *pos) { std::cerr << "ERROR: Signature " << sig << " has an empty name.\n\n"; DB_CLOSE(db); usage(argv[0]); } #ifdef QDBM_AS_TOKYOCABINET if (! vlput(db, sig.c_str(), sig.length(), pos, -1 /* strlen */, VL_DDUP)) { #else if (! tcbdbputdup2(db, sig.c_str(), pos)) { #endif std::cerr << "ERROR: Could not store the record for " << sig << " in the database." << std::endl; DB_CLOSE(db); std::exit(1); } ++tot; } // Close and tidy up. #ifdef QDBM_AS_TOKYOCABINET if (! vloptimize(db)) { std::cerr << "ERROR: Could not optimise QDBM database: " << outputFile << std::endl; DB_CLOSE(db); std::exit(1); } if (! vlclose(db)) { std::cerr << "ERROR: Could not close QDBM database: " << outputFile << std::endl; std::exit(1); } #else // The following call to tcbdboptimise() does not change any options // other than the bitwise compression option given in the final argument. if (! tcbdboptimize(db, 0, 0, 0, -1, -1, BDBTBZIP)) { std::cerr << "ERROR: Could not optimise Tokyo Cabinet database: " << outputFile << std::endl; std::cerr << "Tokyo cabinet error: " << tcerrmsg(tcbdbecode(db)) << std::endl; DB_CLOSE(db); std::exit(1); } if (! tcbdbclose(db)) { std::cerr << "ERROR: Could not close Tokyo Cabinet database: " << outputFile << std::endl; tcbdbdel(db); std::exit(1); } tcbdbdel(db); #endif std::cout << "Success: " << tot << " records." << std::endl; return 0; }
int main(int argc, char **argv){ if (argc != 3) { std::cerr << "Usage: " << argv[0] << " file dbname" << std::endl; exit(1); } double t1, t2; FILE *fp = fopen(argv[1], "r"); if (fp == NULL) { std::cerr << "failed to open " << argv[1] << std::endl; exit(1); } int ecode; char *key, *value; t1 = gettimeofday_sec(); TCBDB *bdb = tcbdbnew(); tcbdbtune(bdb, 5, -1, -1, -1, -1, 0); tcbdbsetcache(bdb, 300, 100); if (!tcbdbopen(bdb, argv[2], BDBOWRITER | BDBOCREAT)) { ecode = tcbdbecode(bdb); fprintf(stderr, "open error: %s\n", tcbdberrmsg(ecode)); } char buf[256]; while (fgets(buf, 256, fp)) { char *key = strchr(buf, ' '); if (key == NULL) { continue; } *key++ = '\0'; char *valp = strchr(key, ' '); if (valp == NULL) { continue; } *valp++ = '\0'; char *val = new char[102401]; // 100K sprintf(val, "%0102400d", atoi(valp)); int size; void *data = tcbdbget(bdb, key, strlen(key), &size); if (data != NULL) { if (strcmp(val, (char *) data) != 0) { std::cout << "[error] value incorrect." << std::endl; } free(data); } else { std::cout << "[error] entry not found." << std::endl; } delete [] val; } if (!tcbdbclose(bdb)) { ecode = tcbdbecode(bdb); fprintf(stderr, "close error: %s\n", tcbdberrmsg(ecode)); } tcbdbdel(bdb); t2 = gettimeofday_sec(); std::cout << "get time: " << t2 - t1 << std::endl; fclose(fp); return 0; }
static int control(ErlDrvData handle, unsigned int command, char* buf, int count, char** res, int res_size) { tcbdb_drv_t *driver = (tcbdb_drv_t*)handle; TCBDB *bdb = driver->bdb; int index = 1, tp, sz, version; char key[MAX_KEY_SIZE], value[MAX_VALUE_SIZE]; long key_size, value_size; long long long_tmp; bool rs; const char *value_tmp = NULL; ei_x_buff x; ei_x_new_with_version(&x); if (bdb == NULL && command != OPEN) return ei_error(&x, "database_not_opened", res, res_size); ei_decode_version(buf, &index, &version); switch (command) { case OPEN: // open(Filepath::string()) if (bdb == NULL) { ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_STRING_EXT) return ei_error(&x, "invalid_argument", res, res_size); TCBDB *bdb = tcbdbnew(); tcbdbsetmutex(bdb); tcbdbsetcache(bdb, 104800, 51200); tcbdbsetxmsiz(bdb, 1048576); tcbdbtune(bdb, 0, 0, 0, 7, -1, BDBTLARGE); char *file = driver_alloc(sz + 1); ei_decode_string(buf, &index, file); rs = tcbdbopen(bdb, file, BDBOWRITER | BDBOCREAT); driver_free(file); if (!rs) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); driver->bdb = bdb; ei_x_encode_atom(&x, "ok"); } else return ei_error(&x, "database already opened", res, res_size); break; case CLOSE: tcbdbclose(bdb); tcbdbdel(bdb); driver->bdb = NULL; ei_x_encode_atom(&x, "ok"); break; case PUT: case PUTDUP: case PUTCAT: case PUTKEEP: // put({Key::binary(), Value::binary()}) ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_SMALL_TUPLE_EXT || sz != 2) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_tuple_header(buf, &index, &sz); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT) return ei_error(&x, "invalid_argument", res, res_size); if (sz <= MAX_VALUE_SIZE) { ei_decode_binary(buf, &index, &value[0], &value_size); switch (command) { case PUT: rs = tcbdbput(bdb, &key[0], key_size, &value[0], value_size); break; case PUTDUP: rs = tcbdbputdup(bdb, &key[0], key_size, &value[0], value_size); break; case PUTCAT: rs = tcbdbputcat(bdb, &key[0], key_size, &value[0], value_size); break; default: rs = tcbdbputkeep(bdb, &key[0], key_size, &value[0], value_size); } } else { void *p = driver_alloc(sz); if (p) { ei_decode_binary(buf, &index, p, &value_size); switch (command) { case PUT: rs = tcbdbput(bdb, &key[0], key_size, p, value_size); break; case PUTDUP: rs = tcbdbputdup(bdb, &key[0], key_size, p, value_size); break; case PUTCAT: rs = tcbdbputcat(bdb, &key[0], key_size, p, value_size); break; default: rs = tcbdbputkeep(bdb, &key[0], key_size, p, value_size); } driver_free(p); } else return ei_error(&x, "too long value", res, res_size); }; if (!rs) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); ei_x_encode_atom(&x, "ok"); break; case GET: // get(Key::binary()) -> {ok, Value} | {error, not_found} ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); value_tmp = tcbdbget3(bdb, &key[0], key_size, &sz); ei_x_encode_tuple_header(&x, 2); if (value_tmp != NULL) { ei_x_encode_atom(&x, "ok"); ei_x_encode_binary(&x, value_tmp, sz); } else { ei_x_encode_atom(&x, "error"); ei_x_encode_atom(&x, "not_found"); } break; case GETDUP: // get(Key::binary()) -> {ok, Values} ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); TCLIST *vals = tcbdbget4(bdb, key, key_size); if (vals) { ei_x_encode_tuple_header(&x, 2); ei_x_encode_atom(&x, "ok"); int j; for (j=0; j<tclistnum(vals); j++) { value_tmp = tclistval(vals, j, &sz); ei_x_encode_list_header(&x, 1); ei_x_encode_binary(&x, value_tmp, sz); } tclistdel(vals); ei_x_encode_empty_list(&x); } else { ei_x_encode_tuple_header(&x, 2); ei_x_encode_atom(&x, "ok"); ei_x_encode_empty_list(&x); } break; case REMOVE: // remove(Keys::list()) // remove(Key::binary()) // remove({Key::binary(), Value::binary()}) ei_get_type(buf, &index, &tp, &sz); if (tp == ERL_LIST_EXT) { int count, j; ei_decode_list_header(buf, &index, &count); for (j=0; j<count; j++) { ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); if (!tcbdbout3(bdb, &key[0], key_size)) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); } ei_x_encode_atom(&x, "ok"); } else if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) { ei_decode_binary(buf, &index, &key[0], &key_size); tcbdbout3(bdb, &key[0], key_size); ei_x_encode_atom(&x, "ok"); } else if (tp == ERL_SMALL_TUPLE_EXT && sz == 2) { ei_decode_tuple_header(buf, &index, &sz); // get key ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &key[0], &key_size); // get value ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_VALUE_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &value[0], &value_size); // remove by key&value BDBCUR *cur = tcbdbcurnew(bdb); if (!tcbdbcurjump(cur, &key[0], key_size)) return ei_error(&x, "record_not_found", res, res_size); bool removed = false, not_found = false; while (!removed && !not_found) { int cur_key_size, cur_val_size; const void *curkey = tcbdbcurkey3(cur, &cur_key_size); if (cur_key_size == key_size && memcmp(curkey, key, key_size) == 0) { const void *curval = tcbdbcurval3(cur, &cur_val_size); if (cur_val_size == value_size && memcmp(curval, value, value_size) == 0) { tcbdbcurout(cur); removed = true; } else if (!tcbdbcurnext(cur)) not_found = true; } else not_found = true; } if (not_found) ei_x_encode_atom(&x, "not_found"); else ei_x_encode_atom(&x, "ok"); } else return ei_error(&x, "invalid_argument", res, res_size); break; case RANGE: /* * range({Prefix::binary(), limit:integer()}) * range({StartKey::binary(), BeginInclusion::boolean(), EndKey::binary(), EndInclusion::binary(), limit:integer()}) */ ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_SMALL_TUPLE_EXT || sz < 2) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_tuple_header(buf, &index, &sz); ei_get_type(buf, &index, &tp, &sz); if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) { char keys[MAX_KEY_SIZE], keyf[MAX_KEY_SIZE]; long keys_size, keyf_size; int keys_inc, keyf_inc; long max = -1; TCLIST *range; ei_decode_binary(buf, &index, &keys[0], &keys_size); ei_get_type(buf, &index, &tp, &sz); if (tp == ERL_ATOM_EXT) { // range ei_decode_boolean(buf, &index, &keys_inc); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_BINARY_EXT || sz > MAX_KEY_SIZE) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_binary(buf, &index, &keyf[0], &keyf_size); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_ATOM_EXT) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_boolean(buf, &index, &keyf_inc); ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_INTEGER_EXT) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_long(buf, &index, &max); range = tcbdbrange(bdb, &keys[0], keys_size, keys_inc == 1, &keyf[0], keyf_size, keyf_inc == 1, max); } else if (tp == ERL_INTEGER_EXT) { // prefix ei_get_type(buf, &index, &tp, &sz); if (tp != ERL_INTEGER_EXT) return ei_error(&x, "invalid_argument", res, res_size); ei_decode_long(buf, &index, &max); range = tcbdbfwmkeys(bdb, &keys[0], keys_size, max); } else return ei_error(&x, "invalid_argument", res, res_size); const char *key; int key_size, value_size; int idx, cnt = 0, rcount = tclistnum(range); ei_x_encode_tuple_header(&x, 2); ei_x_encode_atom(&x, "ok"); BDBCUR *cur = tcbdbcurnew(bdb); for (idx=0; idx<rcount; idx++) { key = tclistval(range, idx, &key_size); TCLIST *vals = tcbdbget4(bdb, key, key_size); if (vals) { int j; for (j=0; j<tclistnum(vals); j++) { ei_x_encode_list_header(&x, 1); value_tmp = tclistval(vals, j, &value_size); ei_x_encode_binary(&x, value_tmp, value_size); if (max >= 0 && ++cnt >= max) break; } tclistdel(vals); } idx++; } tcbdbcurdel(cur); tclistdel(range); ei_x_encode_empty_list(&x); } else return ei_error(&x, "invalid_argument", res, res_size); break; case SYNC: // sync() if (!tcbdbsync(bdb)) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); ei_x_encode_atom(&x, "ok"); break; case INFO: // info() ei_x_encode_tuple_header(&x, 3); ei_x_encode_atom(&x, "ok"); long_tmp = tcbdbrnum(bdb); ei_x_encode_longlong(&x, long_tmp); long_tmp = tcbdbfsiz(bdb); ei_x_encode_longlong(&x, long_tmp); break; case ITERATE: // Read(none) -> {ok, Key} | {error, not_found} // Read(Key::binary()) -> {ok, Key} | {error, not_found} ei_get_type(buf, &index, &tp, &sz); BDBCUR *cur = tcbdbcurnew(bdb); if (tp == ERL_BINARY_EXT && sz <= MAX_KEY_SIZE) { ei_decode_binary(buf, &index, &key[0], &key_size); rs = tcbdbcurjump(cur, &key[0], key_size) && tcbdbcurnext(cur); } else rs = tcbdbcurfirst(cur); if (rs) { int key_size; const char *key = tcbdbcurkey3(cur, &key_size); ei_x_encode_tuple_header(&x, 2); ei_x_encode_atom(&x, "ok"); ei_x_encode_binary(&x, key, key_size); tcbdbcurdel(cur); } else { tcbdbcurdel(cur); return ei_error(&x, "not_found", res, res_size); } break; case VANISH: // vanish() -> ok if (!tcbdbvanish(bdb)) return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); ei_x_encode_atom(&x, "ok"); break; case BACKUP: // backup(path::string()) -> ok | {error, Reason} ei_get_type(buf, &index, &tp, &sz); if (tp == ERL_STRING_EXT) { char *file = driver_alloc(sz + 1); ei_decode_string(buf, &index, file); if (tcbdbcopy(driver->bdb, file)) ei_x_encode_atom(&x, "ok"); else return ei_error(&x, tcbdberrmsg(tcbdbecode(bdb)), res, res_size); } else return ei_error(&x, "invalid_argument", res, res_size); break; default: return ei_error(&x, "invalid_command", res, res_size); } if (res_size < x.index) (*res) = (char *)driver_alloc(x.index); int n = x.index; memcpy(*res, x.buff, x.index); ei_x_free(&x); return n; };
/* perform list command */ static int proclist(const char *path, TCCMP cmp, int omode, int max, bool pv, bool px, bool bk, const char *jstr, const char *bstr, const char *estr, const char *fmstr) { TCBDB *bdb = tcbdbnew(); if (!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd); if (cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb); if (!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb); if (!tcbdbopen(bdb, path, BDBOREADER | omode)) { printerr(bdb); tcbdbdel(bdb); return 1; } bool err = false; if (bstr || fmstr) { TCLIST *keys = fmstr ? tcbdbfwmkeys2(bdb, fmstr, max) : tcbdbrange(bdb, bstr, strlen(bstr), true, estr, strlen(estr), true, max); int cnt = 0; for (int i = 0; i < tclistnum(keys); i++) { int ksiz; const char *kbuf = tclistval(keys, i, &ksiz); if (pv) { TCLIST *vals = tcbdbget4(bdb, kbuf, ksiz); if (vals) { for (int j = 0; j < tclistnum(vals); j++) { int vsiz; const char *vbuf = tclistval(vals, j, &vsiz); printdata(kbuf, ksiz, px); putchar('\t'); printdata(vbuf, vsiz, px); putchar('\n'); if (max >= 0 && ++cnt >= max) break; } tclistdel(vals); } } else { int num = tcbdbvnum(bdb, kbuf, ksiz); for (int j = 0; j < num; j++) { printdata(kbuf, ksiz, px); putchar('\n'); if (max >= 0 && ++cnt >= max) break; } } if (max >= 0 && cnt >= max) break; } tclistdel(keys); } else { BDBCUR *cur = tcbdbcurnew(bdb); if (bk) { if (jstr) { if (!tcbdbcurjumpback(cur, jstr, strlen(jstr)) && tcbdbecode(bdb) != TCENOREC) { printerr(bdb); err = true; } } else { if (!tcbdbcurlast(cur) && tcbdbecode(bdb) != TCENOREC) { printerr(bdb); err = true; } } } else { if (jstr) { if (!tcbdbcurjump(cur, jstr, strlen(jstr)) && tcbdbecode(bdb) != TCENOREC) { printerr(bdb); err = true; } } else { if (!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC) { printerr(bdb); err = true; } } } TCXSTR *key = tcxstrnew(); TCXSTR *val = tcxstrnew(); int cnt = 0; while (tcbdbcurrec(cur, key, val)) { printdata(tcxstrptr(key), tcxstrsize(key), px); if (pv) { putchar('\t'); printdata(tcxstrptr(val), tcxstrsize(val), px); } putchar('\n'); if (bk) { if (!tcbdbcurprev(cur) && tcbdbecode(bdb) != TCENOREC) { printerr(bdb); err = true; } } else { if (!tcbdbcurnext(cur) && tcbdbecode(bdb) != TCENOREC) { printerr(bdb); err = true; } } if (max >= 0 && ++cnt >= max) break; } tcxstrdel(val); tcxstrdel(key); tcbdbcurdel(cur); } if (!tcbdbclose(bdb)) { if (!err) printerr(bdb); err = true; } tcbdbdel(bdb); return err ? 1 : 0; }
/* perform inform command */ static int procinform(const char *path, int omode) { TCBDB *bdb = tcbdbnew(); if (!INVALIDHANDLE(g_dbgfd)) tcbdbsetdbgfd(bdb, g_dbgfd); tcbdbsetcmpfunc(bdb, mycmpfunc, NULL); tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL); if (!tcbdbopen(bdb, path, BDBOREADER | omode)) { printerr(bdb); tcbdbdel(bdb); return 1; } bool err = false; const char *npath = tcbdbpath(bdb); if (!npath) npath = "(unknown)"; printf("path: %s\n", npath); printf("database type: btree\n"); uint8_t flags = tcbdbflags(bdb); printf("additional flags:"); if (flags & BDBFOPEN) printf(" open"); if (flags & BDBFFATAL) printf(" fatal"); printf("\n"); TCCMP cmp = tcbdbcmpfunc(bdb); printf("comparison function: "); if (cmp == tccmplexical) { printf("lexical"); } else if (cmp == tccmpdecimal) { printf("decimal"); } else if (cmp == tccmpint32) { printf("int32"); } else if (cmp == tccmpint64) { printf("int64"); } else { printf("custom"); } printf("\n"); printf("max leaf member: %d\n", tcbdblmemb(bdb)); printf("max node member: %d\n", tcbdbnmemb(bdb)); printf("leaf number: %" PRIuMAX "\n", (uint64_t) tcbdblnum(bdb)); printf("node number: %" PRIuMAX "\n", (uint64_t) tcbdbnnum(bdb)); printf("bucket number: %" PRIuMAX "\n", (uint64_t) tcbdbbnum(bdb)); #ifndef NDEBUG if (bdb->hdb->cnt_writerec >= 0) printf("used bucket number: %" PRIdMAX "\n", (int64_t) tcbdbbnumused(bdb)); #endif printf("alignment: %u\n", tcbdbalign(bdb)); printf("free block pool: %u\n", tcbdbfbpmax(bdb)); printf("inode number: %" PRIdMAX "\n", (int64_t) tcbdbinode(bdb)); char date[48]; tcdatestrwww(tcbdbmtime(bdb), INT_MAX, date); printf("modified time: %s\n", date); uint8_t opts = tcbdbopts(bdb); printf("options:"); if (opts & BDBTLARGE) printf(" large"); if (opts & BDBTDEFLATE) printf(" deflate"); if (opts & BDBTBZIP) printf(" bzip"); if (opts & BDBTTCBS) printf(" tcbs"); if (opts & BDBTEXCODEC) printf(" excodec"); printf("\n"); printf("record number: %" PRIuMAX "\n", (uint64_t) tcbdbrnum(bdb)); printf("file size: %" PRIuMAX "\n", (uint64_t) tcbdbfsiz(bdb)); if (!tcbdbclose(bdb)) { if (!err) printerr(bdb); err = true; } tcbdbdel(bdb); return err ? 1 : 0; }