git » nmdb » commit 317141d

Implement CAS in Python bindings.

author Alberto Bertogli
2007-04-29 06:45:38 UTC
committer Alberto Bertogli
2007-04-29 06:45:38 UTC
parent d33c7a6be68271cf0300573a8c79b4800072f404

Implement CAS in Python bindings.

bindings/python/nmdb.py +24 -4
bindings/python/nmdb_ll.c +44 -0

diff --git a/bindings/python/nmdb.py b/bindings/python/nmdb.py
index caa5663..d0d2eba 100644
--- a/bindings/python/nmdb.py
+++ b/bindings/python/nmdb.py
@@ -50,11 +50,12 @@ class NetworkError (Exception):
 
 
 class _nmdbDict (object):
-	def __init__(self, db, op_get, op_set, op_delete):
+	def __init__(self, db, op_get, op_set, op_delete, op_cas):
 		self.db = db
 		self.get = op_get
 		self.set = op_set
 		self.delete = op_delete
+		self._cas = op_cas
 		self.autopickle = True
 
 	def add_server(self, port):
@@ -115,22 +116,41 @@ class _nmdbDict (object):
 		"Returns True if the key is in the database, False otherwise."
 		return self.__contains__(key)
 
+	def cas(self, key, oldval, newval):
+		"Perform a compare-and-swap."
+		if self.autopickle:
+			key = str(hash(key))
+			oldval = cPickle.dumps(oldval, protocol = -1)
+			newval = cPickle.dumps(newval, protocol = -1)
+		r = self._cas(key, oldval, newval)
+		if r == 2:
+			# success
+			return 1
+		elif r == 1:
+			# no match
+			return 0
+		elif r == 0:
+			# not in
+			raise KeyError
+		else:
+			raise NetworkError
+
 
 class Cache (_nmdbDict):
 	def __init__(self, port = -1):
 		db = nmdb_ll.connect(port)
 		_nmdbDict.__init__(self, db, db.cache_get, db.cache_set,
-					db.cache_delete)
+					db.cache_delete, db.cache_cas)
 
 class DB (_nmdbDict):
 	def __init__(self, port = -1):
 		db = nmdb_ll.connect(port)
-		_nmdbDict.__init__(self, db, db.get, db.set, db.delete)
+		_nmdbDict.__init__(self, db, db.get, db.set, db.delete, db.cas)
 
 class SyncDB (_nmdbDict):
 	def __init__(self, port = -1):
 		db = nmdb_ll.connect(port)
 		_nmdbDict.__init__(self, db, db.get, db.set_sync,
-					db.delete_sync)
+					db.delete_sync, db.cas)
 
 
diff --git a/bindings/python/nmdb_ll.c b/bindings/python/nmdb_ll.c
index 47f5b2c..387ea87 100644
--- a/bindings/python/nmdb_ll.c
+++ b/bindings/python/nmdb_ll.c
@@ -124,6 +124,28 @@ static PyObject *db_cache_delete(nmdbobject *db, PyObject *args)
 	return PyLong_FromLong(rv);
 }
 
+/* cache cas */
+static PyObject *db_cache_cas(nmdbobject *db, PyObject *args)
+{
+	unsigned char *key, *oldval, *newval;
+	int ksize, ovsize, nvsize;
+	int rv;
+
+	if (!PyArg_ParseTuple(args, "s#s#s#:cache_cas", &key, &ksize,
+				&oldval, &ovsize,
+				&newval, &nvsize)) {
+		return NULL;
+	}
+
+	Py_BEGIN_ALLOW_THREADS
+	rv = nmdb_cache_cas(db->db, key, ksize, oldval, ovsize,
+			newval, nvsize);
+	Py_END_ALLOW_THREADS
+
+	return PyLong_FromLong(rv);
+}
+
+
 /* db set */
 static PyObject *db_set(nmdbobject *db, PyObject *args)
 {
@@ -196,6 +218,26 @@ static PyObject *db_delete(nmdbobject *db, PyObject *args)
 	return PyLong_FromLong(rv);
 }
 
+/* db cas */
+static PyObject *db_cas(nmdbobject *db, PyObject *args)
+{
+	unsigned char *key, *oldval, *newval;
+	int ksize, ovsize, nvsize;
+	int rv;
+
+	if (!PyArg_ParseTuple(args, "s#s#s#:cas", &key, &ksize,
+				&oldval, &ovsize,
+				&newval, &nvsize)) {
+		return NULL;
+	}
+
+	Py_BEGIN_ALLOW_THREADS
+	rv = nmdb_cas(db->db, key, ksize, oldval, ovsize, newval, nvsize);
+	Py_END_ALLOW_THREADS
+
+	return PyLong_FromLong(rv);
+}
+
 
 /* db set sync */
 static PyObject *db_set_sync(nmdbobject *db, PyObject *args)
@@ -243,9 +285,11 @@ static PyMethodDef nmdb_methods[] = {
 	{ "cache_set", (PyCFunction) db_cache_set, METH_VARARGS, NULL },
 	{ "cache_get", (PyCFunction) db_cache_get, METH_VARARGS, NULL },
 	{ "cache_delete", (PyCFunction) db_cache_delete, METH_VARARGS, NULL },
+	{ "cache_cas", (PyCFunction) db_cache_cas, METH_VARARGS, NULL },
 	{ "set", (PyCFunction) db_set, METH_VARARGS, NULL },
 	{ "get", (PyCFunction) db_get, METH_VARARGS, NULL },
 	{ "delete", (PyCFunction) db_delete, METH_VARARGS, NULL },
+	{ "cas", (PyCFunction) db_cas, METH_VARARGS, NULL },
 	{ "set_sync", (PyCFunction) db_set_sync, METH_VARARGS, NULL },
 	{ "delete_sync", (PyCFunction) db_delete_sync, METH_VARARGS, NULL },