You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2011/08/23 22:35:48 UTC

svn commit: r1160884 - in /subversion/branches/fs-py/subversion: libsvn_fs_py/fs_fs.c libsvn_fs_py/py_util.c libsvn_fs_py/py_util.h python/svn/__init__.py python/svn/fs/__init__.py

Author: hwright
Date: Tue Aug 23 20:35:48 2011
New Revision: 1160884

URL: http://svn.apache.org/viewvc?rev=1160884&view=rev
Log:
On the fs-py branch:
A couple of steps toward getting pack implemented in Python.  Right now, all
this does is call the Python method which grabs a lock and checks for
cancellation.  The bulk of this commit is dedicated to locking and improved
error handling.

* subversion/python/svn/__init__.py
  (SubversionException._new_from_err_list): New.

* subversion/python/svn/fs/__init__.py
  (FS.__init__): Get a lock object.
  (FS.pack): Grab the lock, and notify and check for cancellation.

* subversion/libsvn_fs_py/fs_fs.c
  (svn_fs_py__pack): Wrap the cancellation and notify functions, and call the
    Python pack method.
 
* subversion/libsvn_fs_py/py_util.c
  (raise_and_clear_err): New.
  (svn_fs_py__wrap_pack_notify_func, cancel_func_wrapper,
   svn_fs_py__wrap_cancel_func): New.

* subversion/libsvn_fs_py/py_util.h
  (svn_fs_py__wrap_pack_notify_func, svn_fs_py__wrap_cancel_func): New.

Modified:
    subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c
    subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c
    subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h
    subversion/branches/fs-py/subversion/python/svn/__init__.py
    subversion/branches/fs-py/subversion/python/svn/fs/__init__.py

Modified: subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c?rev=1160884&r1=1160883&r2=1160884&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_fs_py/fs_fs.c Tue Aug 23 20:35:48 2011
@@ -7327,12 +7327,23 @@ svn_fs_py__pack(svn_fs_t *fs,
                 void *cancel_baton,
                 apr_pool_t *pool)
 {
+  fs_fs_data_t *ffd = fs->fsap_data;
   struct pack_baton pb = { 0 };
+  PyObject *p_cancel_func;
+  PyObject *p_notify_func;
+
   pb.fs = fs;
   pb.notify_func = notify_func;
   pb.notify_baton = notify_baton;
   pb.cancel_func = cancel_func;
   pb.cancel_baton = cancel_baton;
+
+  p_notify_func = svn_fs_py__wrap_pack_notify_func(notify_func, notify_baton);
+  p_cancel_func = svn_fs_py__wrap_cancel_func(cancel_func, cancel_baton);
+
+  SVN_ERR(svn_fs_py__call_method(NULL, ffd->p_fs, "pack", "(NN)",
+                                 p_notify_func, p_cancel_func));
+
   return svn_fs_py__with_write_lock(fs, pack_body, &pb, pool);
 }
 

Modified: subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c?rev=1160884&r1=1160883&r2=1160884&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.c Tue Aug 23 20:35:48 2011
@@ -209,6 +209,123 @@ load_error:
   }
 }
 
+static void
+raise_and_clear_err(svn_error_t *error_chain)
+{
+  PyObject *args_list = NULL;
+  PyObject *args = NULL;
+  PyObject *apr_err_ob = NULL;
+  PyObject *message_ob = NULL;
+  PyObject *file_ob = NULL;
+  PyObject *line_ob = NULL;
+  PyObject *svn_module = NULL;
+  PyObject *exc_class = NULL;
+  PyObject *exc_ob = NULL;
+  svn_error_t *err;
+
+  if (error_chain == NULL)
+    return;
+
+  args_list = PyList_New(0);
+  if (PyErr_Occurred())
+    goto finished;
+
+  for (err = error_chain; err; err = err->child)
+    {
+      int i;
+
+      args = PyTuple_New(4);
+      if (PyErr_Occurred())
+        goto finished;
+
+      /* Convert the fields of the svn_error_t to Python objects. */
+      apr_err_ob = PyInt_FromLong(err->apr_err);
+      if (PyErr_Occurred())
+        goto finished;
+
+      if (err->message)
+        {
+          message_ob = PyString_FromString(err->message);
+          if (PyErr_Occurred())
+            goto finished;
+        }
+      else
+        {
+          Py_INCREF(Py_None);
+          message_ob = Py_None;
+        }
+
+      if (err->file)
+        {
+          file_ob = PyString_FromString(err->file);
+          if (PyErr_Occurred())
+            goto finished;
+        }
+      else
+        {
+          Py_INCREF(Py_None);
+          file_ob = Py_None;
+        }
+
+      line_ob = PyInt_FromLong(err->line);
+      if (PyErr_Occurred())
+        goto finished;
+
+      /* Store the objects in the tuple. */
+      i = 0;
+#define append(item)                                            \
+      if (PyTuple_SetItem(args, i++, item) == 0)                \
+        /* tuple stole our reference, so don't DECREF */        \
+        item = NULL;                                            \
+      else                                                      \
+        goto finished;
+      append(apr_err_ob);
+      append(message_ob);
+      append(file_ob);
+      append(line_ob);
+#undef append
+
+      /* Append the tuple to the args list. */
+      PyList_Append(args_list, args);
+      if (PyErr_Occurred())
+        goto finished;
+
+      /* The list takes its own reference, so release ours. */
+      Py_DECREF(args);
+    }
+  args = NULL;
+  svn_error_clear(error_chain);
+
+  /* Create the exception object chain. */
+  svn_module = PyImport_ImportModule((char *)"svn");
+  if (PyErr_Occurred())
+    goto finished;
+
+  exc_class = PyObject_GetAttrString(svn_module, (char *)"SubversionException");
+  if (PyErr_Occurred())
+    goto finished;
+
+  exc_ob = PyObject_CallMethod(exc_class, (char *)"_new_from_err_list",
+                               (char *)"(O)", args_list);
+  if (PyErr_Occurred())
+    goto finished;
+
+  /* Raise the exception. */
+  PyErr_SetObject(exc_class, exc_ob);
+
+ finished:
+  /* Release any references. */
+  Py_XDECREF(args_list);
+  Py_XDECREF(args);
+  Py_XDECREF(apr_err_ob);
+  Py_XDECREF(message_ob);
+  Py_XDECREF(file_ob);
+  Py_XDECREF(line_ob);
+  Py_XDECREF(svn_module);
+  Py_XDECREF(exc_class);
+  Py_XDECREF(exc_ob);
+}
+
 svn_error_t *
 svn_fs_py__init_python(apr_pool_t *pool)
 {
@@ -502,3 +619,73 @@ svn_fs_py__load_module(fs_fs_data_t *ffd
 {
   return svn_error_trace(load_module(&ffd->p_module, FS_MODULE_NAME));
 }
+
+PyObject *
+svn_fs_py__wrap_pack_notify_func(svn_fs_pack_notify_t notify_func,
+                                 void *notify_baton)
+{
+  if (!notify_func)
+    Py_RETURN_NONE;
+
+  Py_RETURN_NONE;
+}
+
+static PyObject *
+cancel_func_wrapper(PyObject *p_tuple, PyObject *args)
+{
+  PyObject *c_func;
+  PyObject *baton;
+  void *cancel_baton;
+  svn_cancel_func_t cancel_func;
+  svn_error_t *err;
+
+  c_func = PySequence_GetItem(p_tuple, 0);
+  cancel_func = PyCObject_AsVoidPtr(c_func);
+  Py_DECREF(c_func);
+
+  baton = PySequence_GetItem(p_tuple, 1);
+  if (baton == Py_None)
+    cancel_baton = NULL;
+  else
+    cancel_baton = PyCObject_AsVoidPtr(baton);
+  Py_DECREF(baton);
+
+  err = cancel_func(cancel_baton);
+  if (err)
+    raise_and_clear_err(err);
+
+  Py_RETURN_NONE;
+}
+
+PyObject *
+svn_fs_py__wrap_cancel_func(svn_cancel_func_t cancel_func,
+                            void *cancel_baton)
+{
+  static PyMethodDef method_def = { "cancel", cancel_func_wrapper,
+                                    METH_NOARGS, NULL };
+  PyObject *func;
+  PyObject *c_func;
+  PyObject *baton;
+  PyObject *p_tuple;
+
+  if (!cancel_func)
+    Py_RETURN_NONE;
+
+  c_func = PyCObject_FromVoidPtr(cancel_func, NULL);
+
+  if (cancel_baton)
+    {
+      baton = PyCObject_FromVoidPtr(cancel_baton, NULL);
+    }
+  else
+    {
+      baton = Py_None;
+      Py_INCREF(baton);
+    }
+
+  p_tuple = Py_BuildValue("(NN)", c_func, baton);
+  func = PyCFunction_New(&method_def, p_tuple);
+  Py_DECREF(p_tuple);
+
+  return func;
+}

Modified: subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h?rev=1160884&r1=1160883&r2=1160884&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h (original)
+++ subversion/branches/fs-py/subversion/libsvn_fs_py/py_util.h Tue Aug 23 20:35:48 2011
@@ -67,3 +67,11 @@ svn_error_t *
 svn_fs_py__get_int_attr(int *result,
                         PyObject *p_obj,
                         const char *name);
+
+PyObject *
+svn_fs_py__wrap_pack_notify_func(svn_fs_pack_notify_t notify_func,
+                                 void *notify_baton);
+
+PyObject *
+svn_fs_py__wrap_cancel_func(svn_cancel_func_t cancel_func,
+                            void *cancel_baton);

Modified: subversion/branches/fs-py/subversion/python/svn/__init__.py
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/python/svn/__init__.py?rev=1160884&r1=1160883&r2=1160884&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/python/svn/__init__.py (original)
+++ subversion/branches/fs-py/subversion/python/svn/__init__.py Tue Aug 23 20:35:48 2011
@@ -27,6 +27,16 @@ class SubversionException(Exception):
     def __str__(self):
         return self.message
 
+    @classmethod
+    def _new_from_err_list(cls, errors):
+        '''This is provided for any C callers to manually construct an
+        exception.'''
+        child = None
+        errors.reverse()
+        for (apr_err, message, file, line) in errors:
+            child = cls(apr_err, message)
+        return child
+
 
 def is_valid_revnum(rev):
     return rev >= 0

Modified: subversion/branches/fs-py/subversion/python/svn/fs/__init__.py
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/python/svn/fs/__init__.py?rev=1160884&r1=1160883&r2=1160884&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/python/svn/fs/__init__.py (original)
+++ subversion/branches/fs-py/subversion/python/svn/fs/__init__.py Tue Aug 23 20:35:48 2011
@@ -25,6 +25,7 @@ import svn
 import svn.hash
 import svn.prop
 import svn._cache
+import svn._lock
 import svn.err
 
 # Some constants
@@ -439,6 +440,18 @@ class FS(object):
         else:
             self._open_fs()
 
+        self._write_lock = svn._lock.Lock(self.__path_lock)
+
+
+    def pack(self, notify=None, cancel=None):
+        'Pack the filesystem, calling NOTIFY and CANCEL as appropriate.'
+
+        with self._write_lock:
+            if notify:
+                notify()
+            if cancel:
+                cancel()
+
 
 
 # A few helper functions for C callers