[PATCH 10/14] pytdb: Add support for tdb_check()
Kirill Smelkov
kirr at landau.phys.spbu.ru
Sat Oct 2 07:43:49 MDT 2010
From: Kirill Smelkov <kirr at mns.spb.ru>
tdb_check() is needed when one wants to verify integrity of db, and
since tdb_check() is used in tdbtorture, let's add support for it.
NOTE: I've tried to reduce code duplication between __obj_traverse and
obj_check, but given these two functions sizes, deduplication only makes
things less readable and worse...
Signed-off-by: Kirill Smelkov <kirr at mns.spb.ru>
---
lib/tdb/pytdb.c | 62 ++++++++++++++++++++++++++++++++++++++++
lib/tdb/python/tests/simple.py | 15 +++++++++
2 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/lib/tdb/pytdb.c b/lib/tdb/pytdb.c
index 6d74b39..f119f5e 100644
--- a/lib/tdb/pytdb.c
+++ b/lib/tdb/pytdb.c
@@ -478,6 +478,7 @@ static int pytraverse_helper(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void
if (!pydata)
goto out;
+ /* fn(db, key, data) */
pyret = PyObject_CallFunctionObjArgs(pystate->pyfn, pystate->self, pykey, pydata, NULL);
if (!pyret)
goto out;
@@ -530,6 +531,64 @@ static PyObject *obj_traverse_read(PyTdbObject *self, PyObject *args)
return __obj_traverse(self, args, tdb_traverse_read);
}
+/* check is like traverse, but differs in signature, sigh... */
+static int pycheck_helper(TDB_DATA key, TDB_DATA dbuf, void *state)
+{
+ struct pytraverse_state *pystate = state;
+
+ PyObject *pykey=NULL, *pydata=NULL;
+ PyObject *pyret=NULL;
+ int ret=-1;
+
+ pykey = __PyString_FromTDB_DATA(key, /*release=*/false);
+ if (!pykey)
+ goto out;
+
+ pydata = __PyString_FromTDB_DATA(dbuf, /*release=*/false);
+ if (!pydata)
+ goto out;
+
+ /* check(key, data) */
+ pyret = PyObject_CallFunctionObjArgs(pystate->pyfn, pykey, pydata, NULL);
+ if (!pyret)
+ goto out;
+
+ if (PyObject_IsTrue(pyret))
+ ret = 0; /* tell tdb to continue traversal */
+
+out:
+ Py_XDECREF(pykey);
+ Py_XDECREF(pydata);
+ Py_XDECREF(pyret);
+
+ return ret;
+}
+
+static PyObject *obj_check(PyTdbObject *self, PyObject *args)
+{
+ struct pytraverse_state st;
+ int ret;
+
+ st.self = self;
+ if (!PyArg_ParseTuple(args, "O", &st.pyfn))
+ return NULL;
+
+ ret = tdb_check(self->ctx,
+ (st.pyfn != Py_None ? pycheck_helper : NULL),
+ &st);
+
+ /* check for py exceptions raised from-inside pycheck_helper, and
+ * re-raise it if needed */
+ if (PyErr_Occurred())
+ return NULL;
+
+ if (ret == -1) {
+ PyErr_SetTDBError(self->ctx);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
static PyMethodDef tdb_object_methods[] = {
{ "transaction_cancel", (PyCFunction)obj_transaction_cancel, METH_NOARGS,
@@ -590,6 +649,9 @@ static PyMethodDef tdb_object_methods[] = {
"Wipe the entire database." },
{ "repack", (PyCFunction)obj_repack, METH_NOARGS, "S.repack() -> None\n"
"Repack the entire database." },
+ { "check", (PyCFunction)obj_check, METH_VARARGS,
+ "S.check(check|None) -> None\n"
+ "check(key, data) -> ok?" },
{ "enable_seqnum", (PyCFunction)obj_enable_seqnum, METH_NOARGS,
"S.enable_seqnum() -> None" },
{ "increment_seqnum_nonblock", (PyCFunction)obj_increment_seqnum_nonblock, METH_NOARGS,
diff --git a/lib/tdb/python/tests/simple.py b/lib/tdb/python/tests/simple.py
index cd65b22..d0abaad 100644
--- a/lib/tdb/python/tests/simple.py
+++ b/lib/tdb/python/tests/simple.py
@@ -207,6 +207,21 @@ class SimpleTdbTests(TestCase):
# the rest is the same as in .traverse
+ def test_check(self):
+ self.tdb["foo"] = "1"
+ self.tdb["zzzz"]= "123"
+ self.tdb.check(None)
+
+ def check(key, data):
+ return True # checked ok
+ self.tdb.check(check)
+
+ def check(key, data):
+ if key=="zzzz" and data != "1234":
+ 1/0
+ return True
+ self.assertRaises(ZeroDivisionError, self.tdb.check, check)
+
def test_iterkeys(self):
self.tdb["bloe"] = "2"
--
1.7.3.1.50.g1e633
More information about the samba-technical
mailing list