From bcc2606f37088b9f5c8c377edff1dc1923ea2683 Mon Sep 17 00:00:00 2001 From: Flinn Date: Wed, 3 Mar 2010 00:30:13 -0500 Subject: [PATCH] add putlist and getlist support for B+ tree --- ext/tokyo_tyrant.c | 27 ++++++++++++++++ ext/tokyo_tyrant.h | 2 +- ext/tokyo_tyrant_db.c | 67 +++++++++++++++++++++++++++++++++++++++ ext/tokyo_tyrant_module.c | 11 +++++-- 4 files changed, 103 insertions(+), 4 deletions(-) diff --git a/ext/tokyo_tyrant.c b/ext/tokyo_tyrant.c index 101c6b1..1410eeb 100644 --- a/ext/tokyo_tyrant.c +++ b/ext/tokyo_tyrant.c @@ -123,6 +123,33 @@ extern TCLIST *vhashtolist(VALUE vhash){ return list; } +extern TCLIST *vhashtoputlist(VALUE vhash){ + VALUE vkey, vval, vkeys, vvals; + TCLIST *list; + int i, j; + vkeys = rb_funcall(vhash, rb_intern("keys"), 0); + list = tclistnew(); + for(i = 0; i < RARRAY_LEN(vkeys); i++){ + vkey = rb_ary_entry(vkeys, i); + vkey = StringValueEx(vkey); + + vvals = rb_hash_aref(vhash, vkey); + if (TYPE(vvals) == T_ARRAY){ + for(j = 0; j < RARRAY_LEN(vvals); j++){ + vval = rb_ary_entry(vvals, j); + vval = StringValueEx(vval); + tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey)); + tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval)); + } + } else { + vval = StringValueEx(vvals); + tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey)); + tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval)); + } + } + return list; +} + VALUE mTokyoTyrant; VALUE eTokyoTyrantError; VALUE cDB; diff --git a/ext/tokyo_tyrant.h b/ext/tokyo_tyrant.h index 47349c5..b456c3e 100644 --- a/ext/tokyo_tyrant.h +++ b/ext/tokyo_tyrant.h @@ -46,5 +46,5 @@ extern TCMAP *vhashtomap(VALUE vhash); extern VALUE maptovhash(TCMAP *map); extern TCMAP *varytomap(VALUE vhash); extern TCLIST *vhashtolist(VALUE vhash); - +extern TCLIST *vhashtoputlist(VALUE vhash); #endif diff --git a/ext/tokyo_tyrant_db.c b/ext/tokyo_tyrant_db.c index 9dda29c..5d70239 100644 --- a/ext/tokyo_tyrant_db.c +++ b/ext/tokyo_tyrant_db.c @@ -47,6 +47,25 @@ static VALUE cDB_mput(VALUE vself, VALUE vhash){ return vary; } +static VALUE cDB_putlist(VALUE vself, VALUE vhash){ + VALUE vary; + TCLIST *list, *result; + TCRDB *db = mTokyoTyrant_getdb(vself); + Check_Type(vhash, T_HASH); + + // need a different vhash to putlist 'k v k v' instead of 'k v v v' + list = vhashtoputlist(vhash); + if ((result = tcrdbmisc(db, "putlist", 0, list)) != NULL){ + vary = listtovary(result); + tclistdel(result); + } else { + vary = rb_ary_new(); + } + tclistdel(list); + + return vary; +} + static VALUE cDB_putkeep(VALUE vself, VALUE vkey, VALUE vstr){ return cDB_put_method(vself, vkey, vstr, TTPUTKEEP); } @@ -126,6 +145,52 @@ static VALUE cDB_mget(int argc, VALUE *argv, VALUE vself){ return vhash; } +static VALUE cDB_getlist(int argc, VALUE *argv, VALUE vself){ + VALUE vkeys, vvalue, vary, vhash, vkey, vval, vvals; + TCLIST *list, *result; + int i; + TCRDB *db = mTokyoTyrant_getdb(vself); + rb_scan_args(argc, argv, "*", &vkeys); + + // I really hope there is a better way to do this + if (RARRAY_LEN(vkeys) == 1) { + vvalue = rb_ary_entry(vkeys, 0); + switch (TYPE(vvalue)){ + case T_STRING: + case T_FIXNUM: + break; + case T_ARRAY: + vkeys = vvalue; + break; + case T_OBJECT: + vkeys = rb_convert_type(vvalue, T_ARRAY, "Array", "to_a"); + break; + } + } + Check_Type(vkeys, T_ARRAY); + + list = varytolist(vkeys); + result = tcrdbmisc(db, "getlist", RDBMONOULOG, list); + tclistdel(list); + vary = listtovary(result); + tclistdel(result); + + vhash = rb_hash_new(); + for(i = 0; i < RARRAY_LEN(vary); i += 2){ + vkey = rb_ary_entry(vary, i); + vval = rb_ary_entry(vary, i + 1); + vvals = rb_hash_aref(vhash, vkey); + if (TYPE(vvals) == T_ARRAY){ + vvals = rb_ary_push(vvals, vval); + } else { + vvals = rb_ary_new(); + vvals = rb_ary_push(vvals, vval); + } + rb_hash_aset(vhash, vkey, vvals); + } + return vhash; +} + static VALUE cDB_vsiz(VALUE vself, VALUE vkey){ TCRDB *db = mTokyoTyrant_getdb(vself); @@ -202,6 +267,7 @@ static VALUE cDB_values(VALUE vself){ void init_db(){ rb_define_method(cDB, "mput", cDB_mput, 1); rb_define_alias(cDB, "lput", "mput"); // Rufus Compat + rb_define_method(cDB, "putlist", cDB_putlist, 1); rb_define_method(cDB, "put", cDB_put, 2); rb_define_alias(cDB, "[]=", "put"); rb_define_method(cDB, "putkeep", cDB_putkeep, 2); @@ -212,6 +278,7 @@ void init_db(){ rb_define_alias(cDB, "[]", "get"); rb_define_method(cDB, "mget", cDB_mget, -1); rb_define_alias(cDB, "lget", "mget"); // Rufus Compat + rb_define_method(cDB, "getlist", cDB_getlist, -1); rb_define_method(cDB, "vsiz", cDB_vsiz, 1); /* rb_define_method(cDB, "check_value", cDB_check_value, 1); diff --git a/ext/tokyo_tyrant_module.c b/ext/tokyo_tyrant_module.c index 9cdcabc..c8aca4b 100644 --- a/ext/tokyo_tyrant_module.c +++ b/ext/tokyo_tyrant_module.c @@ -359,9 +359,14 @@ static VALUE mTokyoTyrant_misc(int argc, VALUE *argv, VALUE vself){ args = varytolist(vargs); vname = StringValueEx(vname); - list = tcrdbmisc(db, RSTRING_PTR(vname), NUM2INT(vopts), args); - vary = listtovary(list); - tclistdel(list); + if ((list = tcrdbmisc(db, RSTRING_PTR(vname), NUM2INT(vopts), args)) != NULL){ + vary = listtovary(list); + tclistdel(list); + } else { + vary = rb_ary_new(); + } + tclistdel(args); + return vary; }