Пример #1
0
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;
}
Пример #2
0
/* 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;
}
Пример #3
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;
}
Пример #4
0
/* 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;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
0
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;
}
Пример #8
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;
}
Пример #9
0
/* 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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
0
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;
  }
}
Пример #13
0
/*
 * 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;
}
Пример #14
0
/* 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;
}
Пример #15
0
/* 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;
}
Пример #16
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;
}
Пример #17
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;
}
Пример #18
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);
}
Пример #19
0
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;
}
Пример #20
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;
}
Пример #21
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;
};
Пример #22
0
/* 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;
}
Пример #23
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;
}