static TCLIST* hash2tclist(lua_State *L, int index){ int len = 0; lua_pushnil(L); while(lua_next(L, index) != 0){ len++; lua_pop(L, 1); } TCLIST *list = tclistnew2(len); lua_pushnil(L); while(lua_next(L, index) != 0){ const char *key, *value; size_t ksize, vsize; if(lua_type(L, -2)==LUA_TNUMBER){ lua_pushvalue(L, -2); key = lua_tolstring(L, -1, &ksize); lua_pop(L, 1); } else { key = lua_tolstring(L, -2, &ksize); } tclistpush(list, key, ksize); if(lua_type(L, -1)==LUA_TNUMBER){ lua_pushvalue(L, -1); value = lua_tolstring(L, -1, &vsize); lua_pop(L, 1); } else { value = lua_tolstring(L, -1, &vsize); } tclistpush(list, value, vsize); lua_pop(L, 1); } return list; }
extern TCLIST *varytolist(VALUE vary){ VALUE vval; TCLIST *list; int i, num; num = RARRAY_LEN(vary); list = tclistnew2(num); for(i = 0; i < num; i++){ vval = rb_ary_entry(vary, i); vval = StringValueEx(vval); tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval)); } return list; }
static TCLIST* array2tclist(lua_State *L, int index){ int len = lua_objlen(L, index); TCLIST *list = tclistnew2(len); int i; for(i=1; i<=len; i++){ lua_rawgeti(L, index, i); size_t vsiz; const char *vbuf = lua_tolstring(L, -1, &vsiz); if(vbuf) tclistpush(list, vbuf, vsiz); lua_pop(L, 1); } return list; }
TCLIST *explode(const char *delimiter , char *str) { TCLIST *data = NULL; char *tmp = NULL; char *next = NULL; data = tclistnew2(30); next = strtok_r(str, delimiter, &tmp); while (next != NULL) { tclistpush2(data, next); next = strtok_r(NULL, delimiter, &tmp); } return data; }
static int _sandbox_listen(const char *type, NOTIFY_HANDLER handler, void *listener, TCMAP *map) { TCLIST **p, *list; int sp; if (!type || !handler) return -1; p = (TCLIST **)tcmapget(map, type, strlen(type), &sp); if (p) { list = *p; //free(p); } else { list = tclistnew2(8); tcmapput(map, type, strlen(type), &list, sizeof(list)); } tclistpush(list, &handler, sizeof(handler)); //DEBUG_PRINT("sandbox_listen(): type=%s, handler=%X, s=%d\n", type, (unsigned int)handler, sizeof(handler)); return 0; }
extern TCLIST *vhashtolist(VALUE vhash){ /* Seems like something like this might work just as well vary = rb_hash_to_a(vhash); vary = rb_ary_flatten(vary); args = varytolist(vary); */ VALUE vkeys, vkey, vval; TCLIST *list; int i, num; vkeys = rb_funcall(vhash, rb_intern("keys"), 0); num = RARRAY_LEN(vkeys); list = tclistnew2(num); for(i = 0; i < num; i++){ vkey = rb_ary_entry(vkeys, i); vval = rb_hash_aref(vhash, vkey); vkey = StringValueEx(vkey); vval = StringValueEx(vval); tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey)); tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval)); } return list; }
/* * Class: org_ejdb_driver_EJDBQuery * Method: execute * Signature: (Lorg/ejdb/bson/BSONObject;[Lorg/ejdb/bson/BSONObject;Lorg/ejdb/bson/BSONObject;ILjava/io/OutputStream;)Lorg/ejdb/driver/EJDBQuery$QResult; */ JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBQuery_execute (JNIEnv *env, jobject obj, jobject qobj, jobjectArray qorarrobj, jobject hobj, jint flags, jobject logstream) { jclass jQResultClazz = (*env)->FindClass(env, "org/ejdb/driver/EJDBQuery$QResult"); jmethodID initQResultMethodID = (*env)->GetMethodID(env, jQResultClazz, "<init>", "(IJ)V"); TCXSTR *log = NULL; bson *qbson = NULL; bson *qorbsons = NULL; bson *qhbson = NULL; EJQ *q = NULL; jobject qresult = NULL; EJDB* db = get_ejdb_from_object(env, obj); if (!ejdbisopen(db)) { set_error(env, 0, "EJDB not opened"); goto finish; } qbson = encode_bson(env, qobj, NULL); if (!qbson) { // TODO: ? goto finish; } jsize qorz = NULL != qorarrobj ? (*env)->GetArrayLength(env, qorarrobj) : 0; if (qorz > 0) { qorbsons = (bson*)malloc(qorz * sizeof(bson)); if (!qorbsons) { set_error(env, 0, "Not enought memory"); goto finish; } for (jsize i = 0; i < qorz; ++i) { jobject qorobj = (*env)->GetObjectArrayElement(env, qorarrobj, i); encode_bson(env, qorobj, &qorbsons[i]); } } if (NULL != hobj){ qhbson = encode_bson(env, hobj, NULL); } q = ejdbcreatequery(db, qbson, qorz > 0 ? qorbsons : NULL, qorz, qhbson); if (!q) { set_ejdb_error(env, db); goto finish; } jstring colname = get_coll_name(env, obj); const char *cname = (*env)->GetStringUTFChars(env, colname, NULL); EJCOLL *coll = ejdbgetcoll(db, cname); if (!coll) { bson_iterator it; //If we are in $upsert mode a new collection will be created if (bson_find(&it, qbson, "$upsert") == BSON_OBJECT) { coll = ejdbcreatecoll(db, cname, NULL); (*env)->ReleaseStringUTFChars(env, colname, cname); if (!coll) { set_ejdb_error(env, db); goto finish; } } } else { (*env)->ReleaseStringUTFChars(env, colname, cname); } uint32_t count = 0; TCLIST *qres = NULL; if (!coll) { //No collection -> no results qres = (flags & JBQRYCOUNT) ? NULL : tclistnew2(1); //empty results } else { if (NULL != logstream) { log = tcxstrnew(); } qres = ejdbqryexecute(coll, q, &count, flags, log); if (ejdbecode(db) != TCESUCCESS) { set_ejdb_error(env, db); goto finish; } } qresult = (*env)->NewObject(env, jQResultClazz, initQResultMethodID, (jint)count, (jlong)qres); finish: // clear if (log) { jclass logstreamClazz = (*env)->GetObjectClass(env, logstream); jmethodID writeMethodID = (*env)->GetMethodID(env, logstreamClazz, "write", "([B)V"); jmethodID flushMethodID = (*env)->GetMethodID(env, logstreamClazz, "flush", "()V"); jsize logLength = TCXSTRSIZE(log); jbyteArray jlogdata = (*env)->NewByteArray(env, logLength); (*env)->SetByteArrayRegion(env, jlogdata, 0, logLength, (jbyte*)TCXSTRPTR(log)); (*env)->CallVoidMethod(env, logstream, writeMethodID, jlogdata); (*env)->DeleteLocalRef(env, jlogdata); (*env)->CallVoidMethod(env, logstream, flushMethodID); tcxstrdel(log); } if (qbson) { bson_del(qbson); } if (qorbsons) { for (int i = 0; i < qorz; ++i) { bson_destroy(&qorbsons[i]); } free(qorbsons); } if (qhbson) { bson_del(qhbson); } if (q) { ejdbquerydel(q); } return qresult; };
/* 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; }
list(int num) : list_(tclistnew2(num)) {}