[Libguestfs] [nbdkit PATCH v2 2/5] python: Expose can_zero callback

Eric Blake
2018-04-11T05:03:39Z

Fairly straightforward, as the code in plugins.c already takes
care of necessary .pwrite fallbacks.

Simplify similar can_FOO callbacks that were copy-and-pasted while
implementing py_can_zero.

Signed-off-by: Eric Blake <eblake@redhat.com>
---
 plugins/python/nbdkit-python-plugin.pod |  7 +++++
 plugins/python/python.c                 | 51 +++++++++++++++++++--------------
 tests/test.py                           |  4 +++
 3 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/plugins/python/nbdkit-python-plugin.pod
b/plugins/python/nbdkit-python-plugin.pod
index 19f9eff..29250ce 100644
--- a/plugins/python/nbdkit-python-plugin.pod
+++ b/plugins/python/nbdkit-python-plugin.pod
@@ -183,6 +183,13 @@ contents will be garbage collected.
  def can_trim(h):
    # return a boolean

+=item C<can_zero>
+
+(Optional)
+
+ def can_zero(h):
+   # return a boolean
+
 =item C<pread>

 (Required)
diff --git a/plugins/python/python.c b/plugins/python/python.c
index 07559a5..d75b36a 100644
--- a/plugins/python/python.c
+++ b/plugins/python/python.c
@@ -629,13 +629,8 @@ py_can_write (void *handle)
     Py_DECREF (r);
     return ret;
   }
-  /* No Python can_write callback, but there's a Python pwrite callback
-   * defined, so return 1.  (In C modules, nbdkit would do this).
-   */
-  else if (callback_defined ("pwrite", NULL))
-    return 1;
-  else
-    return 0;
+  /* No Python can_write callback, so check for Python pwrite callback. */
+  return callback_defined ("pwrite", NULL);
 }

 static int
@@ -657,13 +652,8 @@ py_can_flush (void *handle)
     Py_DECREF (r);
     return ret;
   }
-  /* No Python can_flush callback, but there's a Python flush callback
-   * defined, so return 1.  (In C modules, nbdkit would do this).
-   */
-  else if (callback_defined ("flush", NULL))
-    return 1;
-  else
-    return 0;
+  /* No Python can_flush callback, so check for Python flush callback. */
+  return callback_defined ("flush", NULL);
 }

 static int
@@ -708,13 +698,31 @@ py_can_trim (void *handle)
     Py_DECREF (r);
     return ret;
   }
-  /* No Python can_trim callback, but there's a Python trim callback
-   * defined, so return 1.  (In C modules, nbdkit would do this).
-   */
-  else if (callback_defined ("trim", NULL))
-    return 1;
-  else
-    return 0;
+  /* No Python can_trim callback, so check for Python trim callback. */
+  return callback_defined ("trim", NULL);
+}
+
+static int
+py_can_zero (void *handle)
+{
+  PyObject *obj = handle;
+  PyObject *fn;
+  PyObject *r;
+  int ret;
+
+  if (callback_defined ("can_zero", &fn)) {
+    PyErr_Clear ();
+
+    r = PyObject_CallFunctionObjArgs (fn, obj, NULL);
+    Py_DECREF (fn);
+    if (check_python_failure ("can_zero") == -1)
+      return -1;
+    ret = r == Py_True;
+    Py_DECREF (r);
+    return ret;
+  }
+  /* No Python can_zero callback, so check for Python zero callback. */
+  return callback_defined ("zero", NULL);
 }

 #define py_config_help \
@@ -743,6 +751,7 @@ static struct nbdkit_plugin plugin = {
   .can_flush         = py_can_flush,
   .is_rotational     = py_is_rotational,
   .can_trim          = py_can_trim,
+  .can_zero          = py_can_zero,

   .pread             = py_pread,
   .pwrite            = py_pwrite,
diff --git a/tests/test.py b/tests/test.py
index 518cdd4..852af55 100644
--- a/tests/test.py
+++ b/tests/test.py
@@ -30,6 +30,10 @@ def can_trim(h):
     return True


+def can_zero(h):
+    return True
+
+
 def pread(h, count, offset):
     global disk
     return disk[offset:offset+count]
--
2.14.3