[PATCH 02/14] pytdb: Add support for tdb_lockall_nonblock() & tdb_lockall_read_nonblock()

Kirill Smelkov kirr at landau.phys.spbu.ru
Sat Oct 2 07:43:41 MDT 2010


From: Kirill Smelkov <kirr at mns.spb.ru>

The API is a bit different from tdb_lockall() & friends -- we return
True or False depending on whether lock was taken (and raise on errors).

It's better to put boilerplate code which implements return/raise logic
into macro, becase it is needed twise here, and also we'll need it soon
for tdb_chainlock_nonblock() soon.

NOTE

Py_RETURN_TRUE / Py_RETURN_FALSE were introduced in Python 2.4, so
if we need to support older Pythons, we can always hand-write it as we
did with Py_RETURN_NONE.

Or if we support only Python >= 2.4, we should kill our own #define for
Py_RETURN_NONE.

Cc: 597386 at bugs.debian.org
Signed-off-by: Kirill Smelkov <kirr at mns.spb.ru>
---
 lib/tdb/pytdb.c                |   27 +++++++++++++++++++++++++++
 lib/tdb/python/tests/simple.py |   12 ++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/lib/tdb/pytdb.c b/lib/tdb/pytdb.c
index c2ba661..f5cb307 100644
--- a/lib/tdb/pytdb.c
+++ b/lib/tdb/pytdb.c
@@ -75,6 +75,17 @@ static PyObject *PyString_FromTDB_DATA(TDB_DATA data)
 		return NULL; \
 	}
 
+/* after lock_*_nonblock(), return True|False or raise */
+#define	PyTdb_LOCK_NONBLOCK_RET_OR_RAISE(ret, tdb) do { \
+	if (ret != 0) { \
+		if (tdb_error(self->ctx) == TDB_ERR_LOCK && errno == EAGAIN) \
+			Py_RETURN_FALSE; \
+		PyErr_SetTDBError(self->ctx); \
+		return NULL; \
+	} \
+	Py_RETURN_TRUE; \
+} while (0)
+
 static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
 	char *name = NULL;
@@ -165,6 +176,18 @@ static PyObject *obj_unlockall_read(PyTdbObject *self)
 	Py_RETURN_NONE;
 }
 
+static PyObject *obj_lockall_nonblock(PyTdbObject *self)
+{
+	int ret = tdb_lockall_nonblock(self->ctx);
+	PyTdb_LOCK_NONBLOCK_RET_OR_RAISE(ret, self->ctx);
+}
+
+static PyObject *obj_lockall_read_nonblock(PyTdbObject *self)
+{
+	int ret = tdb_lockall_read_nonblock(self->ctx);
+	PyTdb_LOCK_NONBLOCK_RET_OR_RAISE(ret, self->ctx);
+}
+
 static PyObject *obj_close(PyTdbObject *self)
 {
 	int ret;
@@ -373,6 +396,10 @@ static PyMethodDef tdb_object_methods[] = {
 	{ "unlock_all", (PyCFunction)obj_unlockall, METH_NOARGS, NULL },
 	{ "read_lock_all", (PyCFunction)obj_lockall_read, METH_NOARGS, NULL },
 	{ "read_unlock_all", (PyCFunction)obj_unlockall_read, METH_NOARGS, NULL },
+	{ "lock_all_nonblock", (PyCFunction)obj_lockall_nonblock, METH_NOARGS,
+		"S.lock_all_nonblock() -> True|False" },
+	{ "read_lock_all_nonblock", (PyCFunction)obj_lockall_read_nonblock, METH_NOARGS,
+		"S.read_lock_all_nonblock() -> True|False" },
 	{ "close", (PyCFunction)obj_close, METH_NOARGS, NULL },
 	{ "get", (PyCFunction)obj_get, METH_VARARGS, "S.get(key) -> value\n"
 		"Fetch a value." },
diff --git a/lib/tdb/python/tests/simple.py b/lib/tdb/python/tests/simple.py
index 18180e1..eb7fd17 100644
--- a/lib/tdb/python/tests/simple.py
+++ b/lib/tdb/python/tests/simple.py
@@ -66,6 +66,18 @@ class SimpleTdbTests(TestCase):
         self.tdb.read_lock_all()
         self.tdb.read_unlock_all()
 
+    def test_lockall_nonblock(self):
+        locked = False
+        while not locked:
+            locked = self.tdb.lock_all_nonblock()
+        self.tdb.unlock_all()
+
+    def test_lockall_read_nonblock(self):
+        locked = False
+        while not locked:
+            locked = self.tdb.read_lock_all_nonblock()
+        self.tdb.read_unlock_all()
+
     def test_reopen(self):
         self.tdb.reopen()
 
-- 
1.7.3.1.50.g1e633


More information about the samba-technical mailing list