/* perform setindex command */ static int procsetindex(const char *path, const char *name, int omode, int type){ TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb); int64_t msiz = 0; TCMAP *info = tcsysinfo(); if(info){ msiz = tcatoi(tcmapget4(info, "total", "0")); tcmapdel(info); } if(!tctdbsetinvcache(tdb, msiz >= (1 << 30) ? msiz / 4 : 0, 1.0)) printerr(tdb); if(!tctdbopen(tdb, path, TDBOWRITER | omode)){ printerr(tdb); tctdbdel(tdb); return 1; } bool err = false; if(!tctdbsetindex(tdb, name, type)){ printerr(tdb); err = true; } if(!tctdbclose(tdb)){ if(!err) printerr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform put command */ static int procput(const char *path, const char *pkbuf, int pksiz, TCMAP *cols, int omode, int dmode){ TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb); if(!tctdbopen(tdb, path, TDBOWRITER | omode)){ printerr(tdb); tctdbdel(tdb); return 1; } bool err = false; char pknumbuf[TCNUMBUFSIZ]; if(pksiz < 1){ pksiz = sprintf(pknumbuf, "%lld", (long long)tctdbgenuid(tdb)); pkbuf = pknumbuf; } const char *vbuf; switch(dmode){ case -1: if(!tctdbputkeep(tdb, pkbuf, pksiz, cols)){ printerr(tdb); err = true; } break; case 1: if(!tctdbputcat(tdb, pkbuf, pksiz, cols)){ printerr(tdb); err = true; } break; case 10: vbuf = tcmapget2(cols, "_num"); if(!vbuf) vbuf = "1"; if(tctdbaddint(tdb, pkbuf, pksiz, tcatoi(vbuf)) == INT_MIN){ printerr(tdb); err = true; } break; case 11: vbuf = tcmapget2(cols, "_num"); if(!vbuf) vbuf = "1.0"; if(isnan(tctdbadddouble(tdb, pkbuf, pksiz, tcatof(vbuf)))){ printerr(tdb); err = true; } break; default: if(!tctdbput(tdb, pkbuf, pksiz, cols)){ printerr(tdb); err = true; } break; } if(!tctdbclose(tdb)){ if(!err) printerr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform get command */ static int procget(const char *path, const char *pkbuf, int pksiz, int omode, bool px, bool pz){ TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb); if(!tctdbopen(tdb, path, TDBOREADER | omode)){ printerr(tdb); tctdbdel(tdb); return 1; } bool err = false; TCMAP *cols = tctdbget(tdb, pkbuf, pksiz); if(cols){ tcmapiterinit(cols); const char *kbuf; int ksiz; while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){ int vsiz; const char *vbuf = tcmapiterval(kbuf, &vsiz); printdata(kbuf, ksiz, px); putchar('\t'); printdata(vbuf, vsiz, px); putchar(pz ? '\t' : '\n'); } tcmapdel(cols); } else { printerr(tdb); err = true; } if(!tctdbclose(tdb)){ if(!err) printerr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* * /logout/ * * HTML is in templates/logout.tmpl * * Clean up a users session. Remove their entry from the sessions db and * set the session_id browser cookie to expired. */ static void logout(void) { TCTDB *tdb; TDBQRY *qry; TCLIST *res; int rsize; const char *rbuf; tdb = tctdbnew(); tctdbopen(tdb, SESSION_DB, TDBOWRITER); qry = tctdbqrynew(tdb); tctdbqryaddcond(qry, "session_id", TDBQCSTREQ, user_session.session_id); res = tctdbqrysearch(qry); rbuf = tclistval(res, 0, &rsize); tctdbout(tdb, rbuf, strlen(rbuf)); tclistdel(res); tctdbqrydel(qry); tctdbclose(tdb); tctdbdel(tdb); /* Immediately expire the session cookies */ printf("Set-Cookie: session_id=deleted; " "expires=Thu, 01 Jan 1970 00:00:01 GMT; " "path=/; httponly\r\n"); send_template("templates/logout.tmpl", NULL, NULL); }
/* * Create a new user session. This is done upon each successful login. */ void create_session(unsigned long long sid) { char session_id[SID_LEN + 1]; char restrict_ip[2] = "0\0"; char pkbuf[256]; char timestamp[21]; char ssid[21]; char tenant[TENANT_MAX + 1]; char *username; int primary_key_size; MYSQL_RES *res; TCTDB *tdb; TCMAP *cols; GHashTable *db_row = NULL; username = make_mysql_safe_string(get_var(qvars, "username")); res = sql_query("SELECT uid, name, capabilities FROM passwd WHERE " "username = '******'", username); db_row = get_dbrow(res); get_tenant(env_vars.host, tenant); generate_hash(session_id, SHA256); if (strcmp(get_var(qvars, "restrict_ip"), "true") == 0) { d_fprintf(debug_log, "Restricting session to origin ip " "address\n"); restrict_ip[0] = '1'; } tdb = tctdbnew(); tctdbopen(tdb, SESSION_DB, TDBOWRITER | TDBOCREAT); primary_key_size = sprintf(pkbuf, "%ld", (long)tctdbgenuid(tdb)); snprintf(timestamp, sizeof(timestamp), "%ld", (long)time(NULL)); snprintf(ssid, sizeof(ssid), "%llu", sid); cols = tcmapnew3("tenant", tenant, "sid", ssid, "uid", get_var(db_row, "uid"), "username", get_var(qvars, "username"), "name", get_var(db_row, "name"), "login_at", timestamp, "last_seen", timestamp, "origin_ip", env_vars.remote_addr, "client_id", env_vars.http_user_agent, "session_id", session_id, "csrf_token", "\0", "restrict_ip", restrict_ip, "capabilities", get_var(db_row, "capabilities"), NULL); tctdbput(tdb, pkbuf, primary_key_size, cols); tcmapdel(cols); tctdbclose(tdb); tctdbdel(tdb); fcgx_p("Set-Cookie: session_id=%s; path=/; httponly\r\n", session_id); mysql_free_result(res); free_vars(db_row); free(username); }
/* perform tblread command */ int dotblread(char *name, int rnum){ TCTDB *tdb; int i, j, err, pksiz, rsiz; char pkbuf[RECBUFSIZ]; const char *rbuf; TCMAP *cols; TDBQRY *qry; TCLIST *res; if(showprgr) printf("<Reading Test of Table>\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ tdb = tctdbnew(); tctdbsetxmsiz(tdb, rnum * 80); tctdbsetcache(tdb, -1, rnum / 100, -1); if(!tctdbopen(tdb, name, TDBOREADER)){ fprintf(stderr, "tctdbopen failed\n"); tctdbdel(tdb); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* search for a record */ pksiz = sprintf(pkbuf, "%08d", i); qry = tctdbqrynew(tdb); tctdbqryaddcond(qry, "s", TDBQCSTREQ, pkbuf); res = tctdbqrysearch(qry); for(j = 0; j < tclistnum(res); j++){ rbuf = tclistval(res, j, &rsiz); cols = tctdbget(tdb, rbuf, rsiz); if(cols){ tcmapdel(cols); } else { fprintf(stderr, "tctdbget failed\n"); err = TRUE; break; } } tclistdel(res); tctdbqrydel(qry); /* 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(!tctdbclose(tdb)){ fprintf(stderr, "tctdbclose failed\n"); tctdbdel(tdb); return 1; } tctdbdel(tdb); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; }
static PyObject * search(PyObject *self, PyObject *args){ TCTDB *tdb; int ecode, i, rsiz; const char *rbuf, *name; TCMAP *cols; TDBQRY *qry; TCLIST *res; const char *dbname; const char *sfield; const char *stext; const int *max; PyObject* pDict = PyDict_New(); PyObject* pList = PyList_New(0); if (!PyArg_ParseTuple(args, "sssi", &dbname, &sfield, &stext,&max)) return NULL; tdb = tctdbnew(); if(!tctdbopen(tdb, dbname, TDBONOLCK | TDBOREADER)){ ecode = tctdbecode(tdb); fprintf(stderr, "open error: %s\n", tctdberrmsg(ecode)); } qry = tctdbqrynew(tdb); tctdbqryaddcond(qry, sfield, TDBQCSTREQ, stext); tctdbqrysetorder(qry, "savedate", TDBQOSTRDESC); tctdbqrysetlimit(qry, max, 0); res = tctdbqrysearch(qry); for(i = 0; i < tclistnum(res); i++){ rbuf = tclistval(res, i, &rsiz); cols = tctdbget(tdb, rbuf, rsiz); if(cols){ tcmapiterinit(cols); PyDict_SetItemString(pDict, "kid", Py_BuildValue("s",rbuf)); while((name = tcmapiternext2(cols)) != NULL){ PyDict_SetItemString(pDict, name, Py_BuildValue("s", tcmapget2(cols, name))); } PyList_Append(pList,pDict); pDict = PyDict_New(); tcmapdel(cols); } } tclistdel(res); tctdbqrydel(qry); if(!tctdbclose(tdb)){ ecode = tctdbecode(tdb); fprintf(stderr, "close error: %s\n", tctdberrmsg(ecode)); } tctdbdel(tdb); return Py_BuildValue("O",pList); }
/* * This checks if a user is currently logged in. It is called at the start * of each request. * * There are upto three checks performed: * * 1) The session_id cookie from the browser is checked with the stored * session_id generated at login. * 2) The client_id from the browser (currently the user agent string) is * checked against the stored client_id. * * 4) Optionally (enabled by default on the login screen) a check is made * on the requesting ip address against the stored origin_ip that was * used at login. * * If any of these checks fail, the request is denied and the user is * punted to the login screen. */ bool is_logged_in(void) { char session_id[SID_LEN + 1]; TCTDB *tdb; TDBQRY *qry; TCLIST *res; TCMAP *cols; int rsize; const char *rbuf; bool login_ok = false; if (!env_vars.http_cookie) goto out3; snprintf(session_id, sizeof(session_id), "%s", env_vars.http_cookie + 11); tdb = tctdbnew(); tctdbopen(tdb, SESSION_DB, TDBOREADER); qry = tctdbqrynew(tdb); tctdbqryaddcond(qry, "session_id", TDBQCSTREQ, session_id); res = tctdbqrysearch(qry); if (tclistnum(res) == 0) goto out2; rbuf = tclistval(res, 0, &rsize); cols = tctdbget(tdb, rbuf, rsize); tcmapiterinit(cols); /* restrict_ip */ if (atoi(tcmapget2(cols, "restrict_ip")) == 1) { /* origin_ip */ if (strcmp(tcmapget2(cols, "origin_ip"), env_vars.remote_addr) != 0) goto out; } /* client_id */ if (strcmp(tcmapget2(cols, "client_id"), env_vars.http_user_agent) != 0) goto out; /* We got here, all checks are OK */ login_ok = true; out: tcmapdel(cols); out2: tctdbqrydel(qry); tclistdel(res); tctdbclose(tdb); tctdbdel(tdb); out3: return login_ok; }
/* perform remove command */ static int procremove(const char *dbpath, int64_t id){ TCTDB *tdb = tctdbnew(); if(!tctdbopen(tdb, dbpath, TDBOWRITER)){ printdberr(tdb); tctdbdel(tdb); return 1; } bool err = false; if(!dboutart(tdb, id)){ printdberr(tdb); err = true; } if(!tctdbclose(tdb)){ printdberr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform create command */ static int proccreate(const char *dbpath, int scale, bool fts){ TCTDB *tdb = tctdbnew(); int bnum = (scale > 0) ? scale * 2 : TUNEBNUM; if(!tctdbtune(tdb, bnum, TUNEAPOW, TUNEFPOW, 0)){ printdberr(tdb); tctdbdel(tdb); return 1; } if(!tctdbopen(tdb, dbpath, TDBOWRITER | TDBOCREAT)){ printdberr(tdb); tctdbdel(tdb); return 1; } bool err = false; if(!tctdbsetindex(tdb, "name", TDBITLEXICAL | TDBITKEEP) && tctdbecode(tdb) != TCEKEEP){ printdberr(tdb); err = true; } if(!tctdbsetindex(tdb, "cdate", TDBITDECIMAL | TDBITKEEP) && tctdbecode(tdb) != TCEKEEP){ printdberr(tdb); err = true; } if(!tctdbsetindex(tdb, "mdate", TDBITDECIMAL | TDBITKEEP) && tctdbecode(tdb) != TCEKEEP){ printdberr(tdb); err = true; } if(!tctdbsetindex(tdb, "xdate", TDBITDECIMAL | TDBITKEEP) && tctdbecode(tdb) != TCEKEEP){ printdberr(tdb); err = true; } if(fts && !tctdbsetindex(tdb, "text", TDBITQGRAM | TDBITKEEP) && tctdbecode(tdb) != TCEKEEP){ printdberr(tdb); err = true; } if(!tctdbclose(tdb)){ printdberr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform out command */ static int procout(const char *path, const char *pkbuf, int pksiz, int omode){ TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb); if(!tctdbopen(tdb, path, TDBOWRITER | omode)){ printerr(tdb); tctdbdel(tdb); return 1; } bool err = false; if(!tctdbout(tdb, pkbuf, pksiz)){ printerr(tdb); err = true; } if(!tctdbclose(tdb)){ if(!err) printerr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform create command */ static int proccreate(const char *path, int bnum, int apow, int fpow, int opts){ TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb); if(!tctdbtune(tdb, bnum, apow, fpow, opts)){ printerr(tdb); tctdbdel(tdb); return 1; } if(!tctdbopen(tdb, path, TDBOWRITER | TDBOCREAT | TDBOTRUNC)){ printerr(tdb); tctdbdel(tdb); return 1; } bool err = false; if(!tctdbclose(tdb)){ printerr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform update command */ static int procupdate(const char *dbpath, int64_t id, const char *wiki){ TCTDB *tdb = tctdbnew(); if(!tctdbopen(tdb, dbpath, TDBOWRITER)){ printdberr(tdb); tctdbdel(tdb); return 1; } bool err = false; TCMAP *cols = tcmapnew2(TINYBNUM); wikiload(cols, wiki); if(!dbputart(tdb, id, cols)){ printdberr(tdb); err = true; } tcmapdel(cols); if(!tctdbclose(tdb)){ printdberr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform optimize command */ static int procoptimize(const char *path, int bnum, int apow, int fpow, int opts, int omode, bool df){ TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb); int64_t msiz = 0; TCMAP *info = tcsysinfo(); if(info){ msiz = tcatoi(tcmapget4(info, "total", "0")); tcmapdel(info); } if(!tctdbsetinvcache(tdb, msiz >= (1 << 30) ? msiz / 4 : 0, 1.0)) printerr(tdb); if(!tctdbopen(tdb, path, TDBOWRITER | omode)){ printerr(tdb); tctdbdel(tdb); return 1; } bool err = false; if(df){ if(!tctdbdefrag(tdb, INT64_MAX)){ printerr(tdb); err = true; } } else { if(!tctdboptimize(tdb, bnum, apow, fpow, opts)){ printerr(tdb); err = true; } } if(!tctdbclose(tdb)){ if(!err) printerr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform search command */ static int procsearch(const char *path, TCLIST *conds, const char *oname, const char *otype, int omode, int max, int skip, bool pv, bool px, bool kw, bool ph, int bt, bool rm, const char *mtype){ TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb); if(!tctdbopen(tdb, path, (rm ? TDBOWRITER : TDBOREADER) | omode)){ printerr(tdb); tctdbdel(tdb); return 1; } bool err = false; TDBQRY *qry = tctdbqrynew(tdb); int cnum = tclistnum(conds); for(int i = 0; i < cnum - 2; i += 3){ const char *name = tclistval2(conds, i); const char *opstr = tclistval2(conds, i + 1); const char *expr = tclistval2(conds, i + 2); int op = tctdbqrystrtocondop(opstr); if(op >= 0) tctdbqryaddcond(qry, name, op, expr); } if(oname){ int type = tctdbqrystrtoordertype(otype); if(type >= 0) tctdbqrysetorder(qry, oname, type); } tctdbqrysetlimit(qry, max, skip); if(rm){ double stime = tctime(); if(!tctdbqrysearchout(qry)){ printerr(tdb); err = true; } double etime = tctime(); if(ph){ TCLIST *hints = tcstrsplit(tctdbqryhint(qry), "\n"); int hnum = tclistnum(hints); for(int i = 0; i < hnum; i++){ const char *hint = tclistval2(hints, i); if(*hint == '\0') continue; printf("\t:::: %s\n", hint); } tclistdel(hints); printf("\t:::: number of records: %d\n", tctdbqrycount(qry)); printf("\t:::: elapsed time: %.5f\n", etime - stime); } } else if(bt > 0){ double sum = 0; for(int i = 1; i <= bt; i++){ double stime = tctime(); TCLIST *res = tctdbqrysearch(qry); double etime = tctime(); tclistdel(res); printf("%d: %.5f sec.\n", i, etime - stime); sum += etime - stime; } printf("----\n"); printf("total: %.5f sec. (%.5f s/q = %.5f q/s)\n", sum, sum / bt, bt / sum); } else { double stime = tctime(); TCLIST *res; TCLIST *hints; int count; int mtnum = mtype ? tctdbmetastrtosettype(mtype) : -1; if(mtnum >= 0){ TDBQRY *qrys[cnum/3+1]; int qnum = 0; for(int i = 0; i < cnum - 2; i += 3){ const char *name = tclistval2(conds, i); const char *opstr = tclistval2(conds, i + 1); const char *expr = tclistval2(conds, i + 2); int op = tctdbqrystrtocondop(opstr); if(op >= 0){ qrys[qnum] = tctdbqrynew(tdb); tctdbqryaddcond(qrys[qnum], name, op, expr); if(oname){ int type = tctdbqrystrtoordertype(otype); if(type >= 0) tctdbqrysetorder(qrys[qnum], oname, type); } tctdbqrysetlimit(qrys[qnum], max, skip); qnum++; } } res = tctdbmetasearch(qrys, qnum, mtnum); hints = qnum > 0 ? tcstrsplit(tctdbqryhint(qrys[0]), "\n") : tclistnew2(1); count = qnum > 0 ? tctdbqrycount(qrys[0]) : 0; for(int i = 0; i < qnum; i++){ tctdbqrydel(qrys[i]); } } else { res = tctdbqrysearch(qry); hints = tcstrsplit(tctdbqryhint(qry), "\n"); count = tctdbqrycount(qry); } double etime = tctime(); if(max < 0) max = INT_MAX; int rnum = tclistnum(res); for(int i = 0; i < rnum && max > 0; i++){ int pksiz; const char *pkbuf = tclistval(res, i, &pksiz); if(kw){ TCMAP *cols = tctdbget(tdb, pkbuf, pksiz); if(cols){ TCLIST *texts = tctdbqrykwic(qry, cols, NULL, 16, TCKWMUTAB); int tnum = tclistnum(texts); for(int j = 0; j < tnum && max > 0; j++){ int tsiz; const char *text = tclistval(texts, j, &tsiz); printdata(pkbuf, pksiz, px); putchar('\t'); printdata(text, tsiz, px); putchar('\n'); max--; } tclistdel(texts); tcmapdel(cols); } } else { printdata(pkbuf, pksiz, px); if(pv){ TCMAP *cols = tctdbget(tdb, pkbuf, pksiz); if(cols){ tcmapiterinit(cols); const char *kbuf; int ksiz; while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){ int vsiz; const char *vbuf = tcmapiterval(kbuf, &vsiz); putchar('\t'); printdata(kbuf, ksiz, px); putchar('\t'); printdata(vbuf, vsiz, px); } tcmapdel(cols); } } putchar('\n'); max--; } } if(ph){ int hnum = tclistnum(hints); for(int i = 0; i < hnum; i++){ const char *hint = tclistval2(hints, i); if(*hint == '\0') continue; printf("\t:::: %s\n", hint); } printf("\t:::: number of records: %d\n", count); printf("\t:::: elapsed time: %.5f\n", etime - stime); } tclistdel(hints); tclistdel(res); } tctdbqrydel(qry); if(!tctdbclose(tdb)){ if(!err) printerr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform list command */ static int proclist(const char *path, int omode, int max, bool pv, bool px, const char *fmstr){ TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb); if(!tctdbopen(tdb, path, TDBOREADER | omode)){ printerr(tdb); tctdbdel(tdb); return 1; } bool err = false; if(fmstr){ TCLIST *pkeys = tctdbfwmkeys2(tdb, fmstr, max); for(int i = 0; i < tclistnum(pkeys); i++){ int pksiz; const char *pkbuf = tclistval(pkeys, i, &pksiz); printdata(pkbuf, pksiz, px); if(pv){ TCMAP *cols = tctdbget(tdb, pkbuf, pksiz); if(cols){ tcmapiterinit(cols); const char *kbuf; int ksiz; while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){ int vsiz; const char *vbuf = tcmapiterval(kbuf, &vsiz); putchar('\t'); printdata(kbuf, ksiz, px); putchar('\t'); printdata(vbuf, vsiz, px); } tcmapdel(cols); } } putchar('\n'); } tclistdel(pkeys); } else { if(!tctdbiterinit(tdb)){ printerr(tdb); err = true; } int cnt = 0; TCMAP *cols; while((cols = tctdbiternext3(tdb)) != NULL){ int pksiz; const char *pkbuf = tcmapget(cols, "", 0, &pksiz); if(pkbuf){ printdata(pkbuf, pksiz, px); if(pv){ tcmapiterinit(cols); const char *kbuf; int ksiz; while((kbuf = tcmapiternext(cols, &ksiz)) != NULL){ if(*kbuf == '\0') continue; int vsiz; const char *vbuf = tcmapiterval(kbuf, &vsiz); putchar('\t'); printdata(kbuf, ksiz, px); putchar('\t'); printdata(vbuf, vsiz, px); } } } tcmapdel(cols); putchar('\n'); if(max >= 0 && ++cnt >= max) break; } } if(!tctdbclose(tdb)){ if(!err) printerr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform import command */ static int procimport(const char *dbpath, TCLIST *files, TCLIST *sufs){ TCTDB *tdb = tctdbnew(); if(!tctdbtune(tdb, TUNEBNUM, TUNEAPOW, TUNEFPOW, 0)){ printdberr(tdb); tctdbdel(tdb); return 1; } if(!tctdbopen(tdb, dbpath, TDBOWRITER | TDBOCREAT)){ printdberr(tdb); tctdbdel(tdb); return 1; } bool err = false; if(!tctdbsetindex(tdb, "name", TDBITLEXICAL | TDBITKEEP) && tctdbecode(tdb) != TCEKEEP){ printdberr(tdb); err = true; } if(!tctdbsetindex(tdb, "cdate", TDBITDECIMAL | TDBITKEEP) && tctdbecode(tdb) != TCEKEEP){ printdberr(tdb); err = true; } if(!tctdbsetindex(tdb, "mdate", TDBITDECIMAL | TDBITKEEP) && tctdbecode(tdb) != TCEKEEP){ printdberr(tdb); err = true; } if(!tctdbsetindex(tdb, "xdate", TDBITDECIMAL | TDBITKEEP) && tctdbecode(tdb) != TCEKEEP){ printdberr(tdb); err = true; } tclistinvert(files); char *fpath; while((fpath = tclistpop2(files)) != NULL){ TCLIST *cfiles = tcreaddir(fpath); if(cfiles){ tclistsort(cfiles); for(int i = tclistnum(cfiles) - 1; i >= 0; i--){ const char *cfile = tclistval2(cfiles, i); bool hit = false; for(int j = 0; j < tclistnum(sufs); j++){ if(tcstribwm(cfile, tclistval2(sufs, j))){ hit = true; break; } } if(!hit) continue; char *lpath = tcsprintf("%s/%s", fpath, cfile); tclistpush2(files, lpath); tcfree(lpath); } tclistdel(cfiles); } else { int isiz; char *ibuf = tcreadfile(fpath, IOMAXSIZ, &isiz); if(ibuf){ TCMAP *cols = tcmapnew2(TINYBNUM); wikiload(cols, ibuf); const char *name = tcmapget2(cols, "name"); if(name && *name != '\0'){ int64_t id = tcatoi(tcmapget4(cols, "id", "")); if(dbputart(tdb, id, cols)){ id = tcatoi(tcmapget4(cols, "id", "")); printf("%s: imported: id=%lld name=%s\n", fpath, (long long)id, name); } else { printdberr(tdb); err = true; } } else { printf("%s: ignored because there is no name\n", fpath); } tcmapdel(cols); tcfree(ibuf); } } tcfree(fpath); } if(!tctdbclose(tdb)){ printdberr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform export command */ static int procexport(const char *dbpath, int64_t id, const char *dirpath){ TCTDB *tdb = tctdbnew(); if(!tctdbopen(tdb, dbpath, TDBOREADER)){ printdberr(tdb); tctdbdel(tdb); return 1; } bool err = false; if(id > 0){ char pkbuf[NUMBUFSIZ]; int pksiz = sprintf(pkbuf, "%lld", (long long)id); TCMAP *cols = tctdbget(tdb, pkbuf, pksiz); if(cols){ TCXSTR *rbuf = tcxstrnew3(IOBUFSIZ); wikidump(rbuf, cols); fwrite(tcxstrptr(rbuf), 1, tcxstrsize(rbuf), stdout); tcxstrdel(rbuf); tcmapdel(cols); } else { printdberr(tdb); err = true; } } else { if(!dirpath) dirpath = "."; if(!tctdbiterinit(tdb)){ printdberr(tdb); err = true; } char *pkbuf; int pksiz; while((pkbuf = tctdbiternext(tdb, &pksiz)) != NULL){ TCMAP *cols = tctdbget(tdb, pkbuf, pksiz); if(cols){ char *name = tcstrdup(tcmapget4(cols, "name", "")); tcstrcututf(name, 32); char *enc = pathencode(name); char *path = tcsprintf("%s/%s-%s.tpw", dirpath, pkbuf, enc); TCXSTR *rbuf = tcxstrnew3(IOBUFSIZ); wikidump(rbuf, cols); if(tcwritefile(path, tcxstrptr(rbuf), tcxstrsize(rbuf))){ printf("%s: exported: id=%s name=%s\n", path, pkbuf, name); } else { printf("%s: writing failed\n", path); err = true; } tcxstrdel(rbuf); tcfree(path); tcfree(enc); tcfree(name); tcmapdel(cols); } else { printdberr(tdb); err = true; } tcfree(pkbuf); } } if(!tctdbclose(tdb)){ printdberr(tdb); err = true; } tctdbdel(tdb); return err ? 1 : 0; }
/* perform inform command */ static int procinform(const char *path, int omode){ TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL); if(!tctdbopen(tdb, path, TDBOREADER | omode)){ printerr(tdb); tctdbdel(tdb); return 1; } bool err = false; const char *npath = tctdbpath(tdb); if(!npath) npath = "(unknown)"; printf("path: %s\n", npath); printf("database type: table\n"); uint8_t flags = tctdbflags(tdb); printf("additional flags:"); if(flags & TDBFOPEN) printf(" open"); if(flags & TDBFFATAL) printf(" fatal"); printf("\n"); printf("bucket number: %llu\n", (unsigned long long)tctdbbnum(tdb)); if(tdb->hdb->cnt_writerec >= 0) printf("used bucket number: %lld\n", (long long)tctdbbnumused(tdb)); printf("alignment: %u\n", tctdbalign(tdb)); printf("free block pool: %u\n", tctdbfbpmax(tdb)); printf("index number: %d\n", tctdbinum(tdb)); TDBIDX *idxs = tdb->idxs; int inum = tdb->inum; for(int i = 0; i < inum; i++){ TDBIDX *idxp = idxs + i; switch(idxp->type){ case TDBITLEXICAL: printf(" name=%s, type=lexical, rnum=%lld, fsiz=%lld\n", idxp->name, (long long)tcbdbrnum(idxp->db), (long long)tcbdbfsiz(idxp->db)); break; case TDBITDECIMAL: printf(" name=%s, type=decimal, rnum=%lld, fsiz=%lld\n", idxp->name, (long long)tcbdbrnum(idxp->db), (long long)tcbdbfsiz(idxp->db)); break; case TDBITTOKEN: printf(" name=%s, type=token, rnum=%lld, fsiz=%lld\n", idxp->name, (long long)tcbdbrnum(idxp->db), (long long)tcbdbfsiz(idxp->db)); break; case TDBITQGRAM: printf(" name=%s, type=qgram, rnum=%lld, fsiz=%lld\n", idxp->name, (long long)tcbdbrnum(idxp->db), (long long)tcbdbfsiz(idxp->db)); break; } } printf("unique ID seed: %lld\n", (long long)tctdbuidseed(tdb)); printf("inode number: %lld\n", (long long)tctdbinode(tdb)); char date[48]; tcdatestrwww(tctdbmtime(tdb), INT_MAX, date); printf("modified time: %s\n", date); uint8_t opts = tctdbopts(tdb); printf("options:"); if(opts & TDBTLARGE) printf(" large"); if(opts & TDBTDEFLATE) printf(" deflate"); if(opts & TDBTBZIP) printf(" bzip"); if(opts & TDBTTCBS) printf(" tcbs"); if(opts & TDBTEXCODEC) printf(" excodec"); printf("\n"); printf("record number: %llu\n", (unsigned long long)tctdbrnum(tdb)); printf("file size: %llu\n", (unsigned long long)tctdbfsiz(tdb)); if(!tctdbclose(tdb)){ if(!err) printerr(tdb); err = true; } tctdbdel(tdb); 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; } TCTDB *tdb = tctdbnew(); if(g_dbgfd != INVALID_HANDLE_VALUE) tctdbsetdbgfd(tdb, g_dbgfd); if(!tctdbsetcodecfunc(tdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(tdb); int64_t msiz = 0; TCMAP *info = tcsysinfo(); if(info){ msiz = tcatoi(tcmapget4(info, "total", "0")); tcmapdel(info); } if(!tctdbsetinvcache(tdb, msiz >= (1 << 30) ? msiz / 4 : 0, 1.0)) printerr(tdb); if(!tctdbopen(tdb, path, TDBOWRITER | TDBOCREAT | omode)){ printerr(tdb); tctdbdel(tdb); if(ifp != stdin) fclose(ifp); return 1; } bool err = false; char *line, numbuf[TCNUMBUFSIZ]; 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); const char *pkey; if(*line == '\0'){ sprintf(numbuf, "%lld", (long long)tctdbgenuid(tdb)); pkey = numbuf; } else { pkey = line; } if(!tctdbput3(tdb, pkey, pv + 1)){ printerr(tdb); 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(!tctdbclose(tdb)){ if(!err) printerr(tdb); err = true; } tctdbdel(tdb); if(ifp != stdin) fclose(ifp); return err ? 1 : 0; }
/* * Sets up the user_session structure. This contains various bits of * information pertaining to the users session. */ void set_user_session(void) { TCTDB *tdb; TDBQRY *qry; TCLIST *res; TCMAP *cols; int rsize; int primary_key_size; char pkbuf[256]; char session_id[SID_LEN + 1]; char login_at[21]; char last_seen[21]; char uid[11]; char sid[21]; char restrict_ip[2]; char capabilities[4]; char user_hdr[1025]; char *xss_string; const char *rbuf; /* * Don't assume the order we get the cookies back is the * same order as we sent them. */ if (strncmp(env_vars.http_cookie, "session_id", 10) == 0) snprintf(session_id, sizeof(session_id), "%s", env_vars.http_cookie + 11); else snprintf(session_id, sizeof(session_id), "%s", env_vars.http_cookie + 88); tdb = tctdbnew(); tctdbopen(tdb, SESSION_DB, TDBOREADER | TDBOWRITER); /* Get the users stored session */ qry = tctdbqrynew(tdb); tctdbqryaddcond(qry, "session_id", TDBQCSTREQ, session_id); res = tctdbqrysearch(qry); rbuf = tclistval(res, 0, &rsize); cols = tctdbget(tdb, rbuf, rsize); tcmapiterinit(cols); memset(&user_session, 0, sizeof(user_session)); snprintf(user_session.tenant, sizeof(user_session.tenant), "%s", tcmapget2(cols, "tenant")); user_session.sid = strtoull(tcmapget2(cols, "sid"), NULL, 10); user_session.uid = atoi(tcmapget2(cols, "uid")); user_session.username = strdup(tcmapget2(cols, "username")); user_session.name = strdup(tcmapget2(cols, "name")); user_session.login_at = atol(tcmapget2(cols, "login_at")); user_session.last_seen = time(NULL); snprintf(user_session.origin_ip, sizeof(user_session.origin_ip), "%s", tcmapget2(cols, "origin_ip")); user_session.client_id = strdup(tcmapget2(cols, "client_id")); snprintf(user_session.session_id, sizeof(user_session.session_id), "%s", tcmapget2(cols, "session_id")); snprintf(user_session.csrf_token, sizeof(user_session.csrf_token), "%s", tcmapget2(cols, "csrf_token")); user_session.restrict_ip = atoi(tcmapget2(cols, "restrict_ip")); user_session.capabilities = atoi(tcmapget2(cols, "capabilities")); tcmapdel(cols); tclistdel(res); tctdbqrydel(qry); /* * Set the user header banner, which displays the users name, uid and * whether they are an Approver and or Admin. */ xss_string = xss_safe_string(user_session.name); snprintf(user_hdr, sizeof(user_hdr), "<big><big> %s</big></big><small>" "<span class = \"lighter\"> (%d) </span>" "</small>", xss_string, user_session.uid); free(xss_string); if (IS_APPROVER() && IS_ADMIN()) strncat(user_hdr, "<span class = \"t_red\">(Approver / Admin)" "</span>", 1024 - strlen(user_hdr)); else if (IS_APPROVER()) strncat(user_hdr, "<span class = \"t_red\">(Approver)" "</span>", 1024 - strlen(user_hdr)); else if (IS_ADMIN()) strncat(user_hdr, "<span class = \"t_red\">(Admin)" "</span>", 1024 - strlen(user_hdr)); strncat(user_hdr, " ", 1024 - strlen(user_hdr)); user_session.user_hdr = strdup(user_hdr); /* * We want to update the last_seen timestamp in the users session. * This entails removing the old session first then storing the new * updated session. */ qry = tctdbqrynew(tdb); tctdbqryaddcond(qry, "session_id", TDBQCSTREQ, session_id); res = tctdbqrysearch(qry); rbuf = tclistval(res, 0, &rsize); tctdbout(tdb, rbuf, strlen(rbuf)); tclistdel(res); tctdbqrydel(qry); primary_key_size = sprintf(pkbuf, "%ld", (long)tctdbgenuid(tdb)); snprintf(login_at, sizeof(login_at), "%ld", user_session.login_at); snprintf(last_seen, sizeof(last_seen), "%ld", user_session.last_seen); snprintf(uid, sizeof(uid), "%u", user_session.uid); snprintf(sid, sizeof(sid), "%llu", user_session.sid); snprintf(restrict_ip, sizeof(restrict_ip), "%d", user_session.restrict_ip); snprintf(capabilities, sizeof(capabilities), "%d", user_session.capabilities); cols = tcmapnew3("tenant", user_session.tenant, "sid", sid, "uid", uid, "username", user_session.username, "name", user_session.name, "login_at", login_at, "last_seen", last_seen, "origin_ip", user_session.origin_ip, "client_id", user_session.client_id, "session_id", user_session.session_id, "csrf_token", user_session.csrf_token, "restrict_ip", restrict_ip, "capabilities", capabilities, NULL); tctdbput(tdb, pkbuf, primary_key_size, cols); tcmapdel(cols); tctdbclose(tdb); tctdbdel(tdb); }
/* perform tblwrite command */ int dotblwrite(char *name, int rnum){ TCTDB *tdb; int i, err, pksiz, vsiz; char pkbuf[RECBUFSIZ], vbuf[RECBUFSIZ]; TCMAP *cols; if(showprgr) printf("<Writing Test of Table>\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ tdb = tctdbnew(); tctdbtune(tdb, rnum * 3, 0, 0, 0); tctdbsetxmsiz(tdb, rnum * 80); tctdbsetcache(tdb, -1, rnum / 100, -1); if(!tctdbopen(tdb, name, TDBOWRITER | TDBOCREAT | TDBOTRUNC)){ fprintf(stderr, "tctdbopen failed\n"); tctdbdel(tdb); return 1; } if(!tctdbsetindex(tdb, "s", TDBITLEXICAL)){ fprintf(stderr, "tctdbsetindex failed\n"); tctdbdel(tdb); return 1; } if(!tctdbsetindex(tdb, "n", TDBITDECIMAL)){ fprintf(stderr, "tctdbsetindex failed\n"); tctdbdel(tdb); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ pksiz = sprintf(pkbuf, "%d", i); cols = tcmapnew2(7); vsiz = sprintf(vbuf, "%08d", i); tcmapput(cols, "s", 1, vbuf, vsiz); vsiz = sprintf(vbuf, "%08d", myrand() % i); tcmapput(cols, "n", 1, vbuf, vsiz); vsiz = sprintf(vbuf, "%08d", i); tcmapput(cols, "t", 1, vbuf, vsiz); vsiz = sprintf(vbuf, "%08d", myrand() % rnum); tcmapput(cols, "f", 1, vbuf, vsiz); if(!tctdbput(tdb, pkbuf, pksiz, cols)){ fprintf(stderr, "tctdbput failed\n"); err = TRUE; break; } tcmapdel(cols); /* 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(!tctdbclose(tdb)){ fprintf(stderr, "tctdbclose failed\n"); tctdbdel(tdb); return 1; } tctdbdel(tdb); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; }