author | Alberto Bertogli
<albertito@gmail.com> 2008-06-23 00:09:40 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2008-06-23 00:15:17 UTC |
parent | e97b3e9ab8aca33f481f1fea2479fa6a328eb4f7 |
bindings/bigloo/nmdb.scm | +6 | -3 |
bindings/d/nmdb.d | +11 | -9 |
bindings/d/nmdb_ll.d | +2 | -2 |
bindings/d/testt.d | +6 | -2 |
bindings/haskell/Nmdb.hs | +13 | -4 |
bindings/newlisp/nmdb.lsp | +5 | -2 |
bindings/python/nmdb.py | +2 | -2 |
bindings/python/nmdb_ll.c | +6 | -4 |
bindings/ruby/nmdb.rb | +2 | -2 |
bindings/ruby/nmdb_ll.c | +6 | -5 |
doc/network.rst | +3 | -1 |
libnmdb/libnmdb.3 | +6 | -3 |
libnmdb/libnmdb.c | +14 | -8 |
libnmdb/nmdb.skel.h | +2 | -2 |
nmdb/cache.c | +9 | -5 |
nmdb/cache.h | +1 | -1 |
nmdb/dbloop.c | +4 | -1 |
nmdb/parse.c | +9 | -5 |
tests/c/incr.c | +5 | -3 |
diff --git a/bindings/bigloo/nmdb.scm b/bindings/bigloo/nmdb.scm index 014dbdb..3b086bb 100644 --- a/bindings/bigloo/nmdb.scm +++ b/bindings/bigloo/nmdb.scm @@ -6,6 +6,7 @@ ;; C functions (extern (type _nmdb_t (pointer void) "void *") + (type long* (pointer long) "int64_t *") (macro _nmdb_init::_nmdb_t () "nmdb_init") (macro _nmdb_free::int (::_nmdb_t) "nmdb_free") @@ -54,10 +55,10 @@ "nmdb_cache_cas") (macro _nmdb_incr::int - (::_nmdb_t ::string ::uint ::long) + (::_nmdb_t ::string ::uint ::long ::long*) "nmdb_incr") (macro _nmdb_cache_incr::int - (::_nmdb_t ::string ::uint ::long) + (::_nmdb_t ::string ::uint ::long ::long*) "nmdb_cache_incr") ) @@ -147,7 +148,9 @@ ;; incr functions (define (nmdb-generic-incr func db key increment) - (func db key (string-length key) increment ) ) + (define newval (make-long* 1)) + (define res (func db key (string-length key) increment newval) ) + (list res (long*-ref newval 0) ) ) (define (nmdb-incr db key increment) (nmdb-generic-incr _nmdb_incr db key increment)) (define (nmdb-cache-incr db key increment) diff --git a/bindings/d/nmdb.d b/bindings/d/nmdb.d index 9c96062..e668bf9 100644 --- a/bindings/d/nmdb.d +++ b/bindings/d/nmdb.d @@ -165,15 +165,17 @@ class DB return res; } - private int do_incr(char[] key, long increment, int mode) + private int do_incr(char[] key, long increment, long *newval, + int mode) { ubyte* k = cast(ubyte *) key.ptr; int res = 0; if (mode == MODE_NORMAL || mode == MODE_SYNC) { - res = nmdb_incr(db, k, key.length, increment); + res = nmdb_incr(db, k, key.length, increment, newval); } else if (mode == MODE_CACHE) { - res = nmdb_cache_incr(db, k, key.length, increment); + res = nmdb_cache_incr(db, k, key.length, increment, + newval); } else { throw new Exception("Invalid mode"); } @@ -255,19 +257,19 @@ class DB } - int incr(char[] key, long increment) + int incr(char[] key, long increment, long *newval) { - return do_incr(key, increment, mode); + return do_incr(key, increment, newval, mode); } - int incr_normal(char[] key, long increment) + int incr_normal(char[] key, long increment, long *newval) { - return do_incr(key, increment, MODE_NORMAL); + return do_incr(key, increment, newval, MODE_NORMAL); } - int cache_incr(char[] key, long increment) + int cache_incr(char[] key, long increment, long *newval) { - return do_incr(key, increment, MODE_CACHE); + return do_incr(key, increment, newval, MODE_CACHE); } diff --git a/bindings/d/nmdb_ll.d b/bindings/d/nmdb_ll.d index beb28d3..03c2426 100644 --- a/bindings/d/nmdb_ll.d +++ b/bindings/d/nmdb_ll.d @@ -65,7 +65,7 @@ extern (C) int nmdb_cache_cas(nmdb_t *db, ubyte *key, size_t ksize, ubyte *oldval, size_t ovsize, ubyte *newval, size_t nvsize); extern (C) int nmdb_incr(nmdb_t *db, ubyte *key, size_t ksize, - long increment); + long increment, long *newval); extern (C) int nmdb_cache_incr(nmdb_t *db, ubyte *key, size_t ksize, - long increment); + long increment, long *newval); diff --git a/bindings/d/testt.d b/bindings/d/testt.d index e2b820c..a70441d 100644 --- a/bindings/d/testt.d +++ b/bindings/d/testt.d @@ -7,16 +7,20 @@ import std.stream; int main() { char[] val1; + long newval, ret; nmdb.DB db = new nmdb.DB(); db.add_tipc_server(); db.mode = MODE_CACHE; - db["1"] = "D"; - val1 = db["1"]; + db["D"] = "1\0"; + val1 = db["D"]; writefln(val1); + ret = db.incr("D", 4, &newval); + writefln(newval, " ", db["D"]); + return 0; } diff --git a/bindings/haskell/Nmdb.hs b/bindings/haskell/Nmdb.hs index 735385a..fe621d0 100644 --- a/bindings/haskell/Nmdb.hs +++ b/bindings/haskell/Nmdb.hs @@ -14,7 +14,9 @@ module Nmdb ( nmdbIncr, nmdbCacheIncr, ) where +import Foreign import Foreign.Ptr +import Foreign.Storable import Foreign.C.Types import Foreign.C.String import Foreign.Marshal.Alloc @@ -158,15 +160,22 @@ nmdbCacheCAS = nmdbGenericCAS llNmdbCacheCAS -- Incr functions foreign import ccall "nmdb.h nmdb_incr" llNmdbIncr :: - NmdbPtr -> CString -> Int -> Int -> IO Int + NmdbPtr -> CString -> Int -> Int64 -> Ptr Int64 -> IO Int foreign import ccall "nmdb.h nmdb_cache_incr" llNmdbCacheIncr :: - NmdbPtr -> CString -> Int -> Int -> IO Int + NmdbPtr -> CString -> Int -> Int64 -> Ptr Int64 -> IO Int nmdbGenericIncr llfunc db key increment = do kl <- newCStringLen key - r <- llfunc db (fst kl) (snd kl) increment + newval <- malloc + r <- llfunc db (fst kl) (snd kl) increment newval + v <- (peek newval) free (fst kl) - return r + free newval + if r == 2 + then do + return $ Just v + else + return Nothing nmdbIncr = nmdbGenericIncr llNmdbIncr nmdbCacheIncr = nmdbGenericIncr llNmdbCacheIncr diff --git a/bindings/newlisp/nmdb.lsp b/bindings/newlisp/nmdb.lsp index 640bfe7..713d300 100644 --- a/bindings/newlisp/nmdb.lsp +++ b/bindings/newlisp/nmdb.lsp @@ -142,8 +142,11 @@ ; *-incr functions (define (priv-incr func key increment) - (letn ( (keylen (length key)) ) - (func NMDB key keylen increment) ) ) + (letn ( (keylen (length key)) + (newval 0) + ) + (set 'ret (func NMDB key keylen increment (address newval)) ) + (list ret newval) ) ) (define (db-incr key increment) (priv-incr nmdb_incr key increment)) (define (cache-incr key increment) (priv-incr nmdb_cache_incr key increment)) diff --git a/bindings/python/nmdb.py b/bindings/python/nmdb.py index 38f7366..406c653 100644 --- a/bindings/python/nmdb.py +++ b/bindings/python/nmdb.py @@ -172,10 +172,10 @@ class GenericDB (object): key by the given increment.""" if self.autopickle: key = str(hash(key)) - r = incrf(key, increment) + r, v = incrf(key, increment) if r == 2: # success - return 2 + return v elif r == 1: # no match, because the value didn't have the right # format diff --git a/bindings/python/nmdb_ll.c b/bindings/python/nmdb_ll.c index 2374118..e2ef5ca 100644 --- a/bindings/python/nmdb_ll.c +++ b/bindings/python/nmdb_ll.c @@ -189,6 +189,7 @@ static PyObject *db_cache_incr(nmdbobject *db, PyObject *args) int ksize; int rv; long long int increment; + int64_t newval; if (!PyArg_ParseTuple(args, "s#L:cache_incr", &key, &ksize, &increment)) { @@ -196,10 +197,10 @@ static PyObject *db_cache_incr(nmdbobject *db, PyObject *args) } Py_BEGIN_ALLOW_THREADS - rv = nmdb_cache_incr(db->db, key, ksize, increment); + rv = nmdb_cache_incr(db->db, key, ksize, increment, &newval); Py_END_ALLOW_THREADS - return PyLong_FromLong(rv); + return Py_BuildValue("LL", rv, newval); } @@ -303,16 +304,17 @@ static PyObject *db_incr(nmdbobject *db, PyObject *args) int ksize; int rv; long long int increment; + int64_t newval; if (!PyArg_ParseTuple(args, "s#L:incr", &key, &ksize, &increment)) { return NULL; } Py_BEGIN_ALLOW_THREADS - rv = nmdb_incr(db->db, key, ksize, increment); + rv = nmdb_incr(db->db, key, ksize, increment, &newval); Py_END_ALLOW_THREADS - return PyLong_FromLong(rv); + return Py_BuildValue("LL", rv, newval); } diff --git a/bindings/ruby/nmdb.rb b/bindings/ruby/nmdb.rb index 09672af..4d38d82 100644 --- a/bindings/ruby/nmdb.rb +++ b/bindings/ruby/nmdb.rb @@ -142,14 +142,14 @@ class GenericDB if @automarshal then key = Marshal.dump(key) end - r = gfunc.call(key, increment) + r, v = gfunc.call(key, increment) if r == 0 then # key not in the database return nil elsif r == 1 or r < 0 then raise NetworkException else - return r + return v end end diff --git a/bindings/ruby/nmdb_ll.c b/bindings/ruby/nmdb_ll.c index 1ef13cc..a07e274 100644 --- a/bindings/ruby/nmdb_ll.c +++ b/bindings/ruby/nmdb_ll.c @@ -202,23 +202,24 @@ static VALUE m_cache_cas(VALUE self, VALUE key, VALUE oldval, VALUE newval) { } -/* Del functions */ +/* Increment functions */ typedef int (*incrf_t) (nmdb_t *db, const unsigned char *k, size_t ks, - int64_t increment); + int64_t increment, int64_t *newval); VALUE generic_incr(VALUE self, VALUE key, VALUE increment, incrf_t incr_func) { ssize_t rv; unsigned char *k; size_t ksize; - int64_t cincr; + int64_t cincr, newval; nmdb_t *db; Data_Get_Struct(self, nmdb_t, db); k = rb_str2cstr(key, &ksize); cincr = rb_num2ll(increment); - rv = incr_func(db, k, ksize, cincr); - return INT2NUM(rv); + rv = incr_func(db, k, ksize, cincr, &newval); + + return rb_ary_new3(2, INT2NUM(rv), rb_ll2inum(newval)); } VALUE m_incr(VALUE self, VALUE key, VALUE increment) { diff --git a/doc/network.rst b/doc/network.rst index 0c5030e..f9f4313 100644 --- a/doc/network.rst +++ b/doc/network.rst @@ -157,7 +157,9 @@ REP_CACHE_HIT REP_OK Depending on the request, this reply does or doesn't have an associated value. For *REQ_SET**, *REQ_DEL** and *REQ_CAS** there is no payload. But - for *REQ_GET* the first 32 bits are the value size, and then the value. + for *REQ_GET* the first 32 bits are the value size, and then the value; and + for *REQ_INCR* the first 32 bits are the payload size, and then the + post-increment value as a signed 64-bit integer in network byte order. Reply error codes diff --git a/libnmdb/libnmdb.3 b/libnmdb/libnmdb.3 index 5b3c1e4..a7a1058 100644 --- a/libnmdb/libnmdb.3 +++ b/libnmdb/libnmdb.3 @@ -47,10 +47,10 @@ libnmdb - Library for interacting with a nmdb server .sp .BI "int nmdb_incr(nmdb_t *" db "," .BI " const unsigned char *" key " , size_t " ksize "," -.BI " int64_t " increment ");" +.BI " int64_t " increment ", int64_t *" newval ");" .BI "int nmdb_cache_incr(nmdb_t *" db "," .BI " const unsigned char *" key " , size_t " ksize "," -.BI " int64_t " increment ");" +.BI " int64_t " increment ", int64_t *" newval ");" .fi .SH DESCRIPTION @@ -157,7 +157,10 @@ bit number to add to the value (it can be negative), and returns 2 if the increment was performed, 1 if the value was not in the appropriate format, 0 if the key was not in the database/cache, or < 0 on failure. The value MUST be a NULL-terminated string with only a number in base 10 in it -(i.e. it must be parseable by strtoll(3)). +(i.e. it must be parseable by strtoll(3)). If the number was incremented +correctly and the +.I newval +parameter is not NULL, it will be set to the resulted value. .SH SEE ALSO diff --git a/libnmdb/libnmdb.c b/libnmdb/libnmdb.c index fd52306..800d43b 100644 --- a/libnmdb/libnmdb.c +++ b/libnmdb/libnmdb.c @@ -573,11 +573,11 @@ int nmdb_cache_cas(nmdb_t *db, const unsigned char *key, size_t ksize, static int do_incr(nmdb_t *db, const unsigned char *key, size_t ksize, - int64_t increment, unsigned short flags) + int64_t increment, int64_t *newval, unsigned short flags) { ssize_t rv, t; - unsigned char *buf; - size_t bufsize, payload_offset, reqsize; + unsigned char *buf, *payload; + size_t bufsize, payload_offset, reqsize, psize; uint32_t reply; struct nmdb_srv *srv; @@ -602,11 +602,17 @@ static int do_incr(nmdb_t *db, const unsigned char *key, size_t ksize, goto exit; } - reply = get_rep(srv, buf, bufsize, NULL, NULL); + psize = sizeof(int64_t); + reply = get_rep(srv, buf, bufsize, &payload, &psize); switch (reply) { case REP_OK: rv = 2; + if (newval != NULL && psize == sizeof(int64_t) + 4) { + /* skip the 4 bytes of length */ + *newval = *((int64_t *) (payload + 4)); + *newval = ntohll(*newval); + } break; case REP_NOMATCH: rv = 1; @@ -626,15 +632,15 @@ exit: } int nmdb_incr(nmdb_t *db, const unsigned char *key, size_t ksize, - int64_t increment) + int64_t increment, int64_t *newval) { - return do_incr(db, key, ksize, increment, 0); + return do_incr(db, key, ksize, increment, newval, 0); } int nmdb_cache_incr(nmdb_t *db, const unsigned char *key, size_t ksize, - int64_t increment) + int64_t increment, int64_t *newval) { - return do_incr(db, key, ksize, increment, NMDB_CACHE_ONLY); + return do_incr(db, key, ksize, increment, newval, NMDB_CACHE_ONLY); } diff --git a/libnmdb/nmdb.skel.h b/libnmdb/nmdb.skel.h index 1c21a14..448fb15 100644 --- a/libnmdb/nmdb.skel.h +++ b/libnmdb/nmdb.skel.h @@ -90,9 +90,9 @@ int nmdb_cache_cas(nmdb_t *db, const unsigned char *key, size_t ksize, const unsigned char *newval, size_t nvsize); int nmdb_incr(nmdb_t *db, const unsigned char *key, size_t ksize, - int64_t increment); + int64_t increment, int64_t *newval); int nmdb_cache_incr(nmdb_t *db, const unsigned char *key, size_t ksize, - int64_t increment); + int64_t increment, int64_t *newval); int nmdb_stats(nmdb_t *db, unsigned char *buf, size_t bsize, unsigned int *nservers, unsigned int *nstats); diff --git a/nmdb/cache.c b/nmdb/cache.c index 5f8ae14..522ac4d 100644 --- a/nmdb/cache.c +++ b/nmdb/cache.c @@ -363,12 +363,15 @@ exit: * -1 if the value was not in the cache. * -2 if the value was not null terminated. * -3 if there was a memory error. + * + * The new value will be set in the newval parameter if the increment was + * successful. */ int cache_incr(struct cache *cd, const unsigned char *key, size_t ksize, - int64_t increment) + int64_t increment, int64_t *newval) { uint32_t h = 0; - unsigned char *val, *newval; + unsigned char *val; int64_t intval; size_t vsize; struct cache_chain *c; @@ -397,15 +400,16 @@ int cache_incr(struct cache *cd, const unsigned char *key, size_t ksize, * and strlen('18446744073709551615') = 20, so if the value is smaller * than 24 (just in case) we create a new buffer. */ if (vsize < 24) { - newval = malloc(24); - if (newval == NULL) + unsigned char *nv = malloc(24); + if (nv == NULL) return -3; free(val); - e->val = val = newval; + e->val = val = nv; e->vsize = vsize = 24; } snprintf((char *) val, vsize, "%23lld", (long long int) intval); + *newval = intval; return 1; } diff --git a/nmdb/cache.h b/nmdb/cache.h index c4d3d7f..039dd91 100644 --- a/nmdb/cache.h +++ b/nmdb/cache.h @@ -49,7 +49,7 @@ int cache_cas(struct cache *cd, const unsigned char *key, size_t ksize, const unsigned char *oldval, size_t ovsize, const unsigned char *newval, size_t nvsize); int cache_incr(struct cache *cd, const unsigned char *key, size_t ksize, - int64_t increment); + int64_t increment, int64_t *newval); #endif diff --git a/nmdb/dbloop.c b/nmdb/dbloop.c index e50901d..0a7e4a7 100644 --- a/nmdb/dbloop.c +++ b/nmdb/dbloop.c @@ -13,6 +13,7 @@ #include "net-const.h" #include "req.h" #include "log.h" +#include "netutils.h" static void *db_loop(void *arg); @@ -216,7 +217,9 @@ static void process_op(db_t *db, struct queue_entry *e) return; } - e->req->reply_mini(e->req, REP_OK); + intval = htonll(intval); + e->req->reply_long(e->req, REP_OK, + (unsigned char *) &intval, sizeof(intval)); free(dbval); diff --git a/nmdb/parse.c b/nmdb/parse.c index 57a2ba8..90d6670 100644 --- a/nmdb/parse.c +++ b/nmdb/parse.c @@ -455,7 +455,7 @@ static void parse_incr(struct req_info *req) int cres, cache_only; const unsigned char *key; uint32_t ksize; - int64_t increment; + int64_t increment, newval; const int max = 65536; /* Request format: @@ -481,7 +481,7 @@ static void parse_incr(struct req_info *req) key = req->payload + sizeof(uint32_t); increment = ntohll( * (int64_t *) (key + ksize) ); - cres = cache_incr(cache_table, key, ksize, increment); + cres = cache_incr(cache_table, key, ksize, increment, &newval); if (cres == -3) { req->reply_err(req, ERR_MEM); return; @@ -510,10 +510,14 @@ static void parse_incr(struct req_info *req) queue_signal(op_queue); } else { - if (cres == -1) + if (cres == -1) { req->reply_mini(req, REP_NOTIN); - else - req->reply_mini(req, REP_OK); + } else { + newval = htonll(newval); + req->reply_long(req, REP_OK, + (unsigned char *) &newval, + sizeof(newval)); + } } return; diff --git a/tests/c/incr.c b/tests/c/incr.c index a0604d1..f0036a3 100644 --- a/tests/c/incr.c +++ b/tests/c/incr.c @@ -18,6 +18,7 @@ int main(int argc, char **argv) char *initval = "0"; size_t ksize; long long int increment; + int64_t newval; nmdb_t *db; if (argc != 3) { @@ -49,16 +50,17 @@ int main(int argc, char **argv) timer_start(); for (i = 0; i < times; i++) { - r = NINCR(db, (unsigned char *) key, ksize, increment); + r = NINCR(db, (unsigned char *) key, ksize, increment, + &newval); if (r != 2) { - printf("result: %d\n", r); + printf("result: %d %lld\n", r, (long long) newval); perror("Incr"); return 1; } } s_elapsed = timer_stop(); - printf("%lu\n", s_elapsed); + printf("%lu %lld\n", s_elapsed, (long long) newval); nmdb_free(db);