subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hwri...@apache.org
Subject svn commit: r1156226 - in /subversion/branches/fs-py/subversion: libsvn_fs_py/fs.c libsvn_fs_py/fs.h libsvn_fs_py/fs_fs.c libsvn_fs_py/py_util.c libsvn_fs_py/py_util.h python/svn/fs.py
Date Wed, 10 Aug 2011 15:22:53 GMT
Author: hwright
Date: Wed Aug 10 15:22:52 2011
New Revision: 1156226

URL: http://svn.apache.org/viewvc?rev=1156226&view=rev
Log:
On the fs-py branch:
Add a filesystem class, and have it track the uuid, rather than storing the
fs uuid in the C library.  This commit also includes various cleanups to the
error handling and helper functions.

There remains one test failure in svnlook tests 12.  From the failure log, it
looks like we're somehow loading the wrong module somewhere, but I can't seem
to figure out where.

* subversion/python/svn/fs.py
  (PATH_UUID, PATH_CURRENT): New.
  (FS): New.
  (_create_fs): Implement.
  (_open_fs, _set_uuid): New.

* subversion/libsvn_fs_py/fs.c
  (fs_serialized_init): Fetch the uuid from the python object.

* subversion/libsvn_fs_py/fs.h
  (fs_fs_data_t): Remove the uuid member.
 
* subversion/libsvn_fs_py/fs_fs.c
  (svn_fs_py__open): Don't read the UUID from the file, it will be loaded upon
    creating the python object.
  (svn_fs_py__get_uuid): Implement as a simple attribute fetch.
  (svn_fs_py__set_uuid): Call into the python object ot set the uuid.

* subversion/libsvn_fs_py/py_util.c
  (create_py_stack): Simplify, and allow better error generation even if not
    given a stack trace.
  (catch_py_exception): Call create_py_stack() even if not given a stack trace.
  (get_string_attr_baton, get_string_attr, svn_fs_py__get_string_attr): New.
  (call_method): Cleanup a stray object.
  (svn_fs_py__call_method): Cleanup baton assignment.

* subversion/libsvn_fs_py/py_util.h
  (svn_fs_py__get_string_attr): New.

Modified:
    subversion/branches/fs-py/subversion/libsvn_fs_py/fs.c
    subversion/branches/fs-py/subversion/libsvn_fs_py/fs.h
    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/fs.py

Modified: subversion/branches/fs-py/subversion/libsvn_fs_py/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_fs_py/fs.c?rev=1156226&r1=1156225&r2=1156226&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_fs_py/fs.c (original)
+++ subversion/branches/fs-py/subversion/libsvn_fs_py/fs.c Wed Aug 10 15:22:52 2011
@@ -55,6 +55,7 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   const char *key;
+  const char *uuid;
   void *val;
   fs_fs_shared_data_t *ffsd;
   apr_status_t status;
@@ -73,8 +74,9 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
      "svnadmin load", so this is a low-priority problem, and we don't
      know of a better way of associating such data with the
      repository. */
+  SVN_ERR(svn_fs_py__get_string_attr(&uuid, ffd->p_fs, "uuid", pool));
 
-  key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX, ffd->uuid,
+  key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX, uuid,
                     (char *) NULL);
   status = apr_pool_userdata_get(&val, key, common_pool);
   if (status)

Modified: subversion/branches/fs-py/subversion/libsvn_fs_py/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/libsvn_fs_py/fs.h?rev=1156226&r1=1156225&r2=1156226&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/libsvn_fs_py/fs.h (original)
+++ subversion/branches/fs-py/subversion/libsvn_fs_py/fs.h Wed Aug 10 15:22:52 2011
@@ -212,9 +212,6 @@ typedef struct fs_fs_data_t
      layouts) or zero (for linear layouts). */
   int max_files_per_dir;
 
-  /* The uuid of this FS. */
-  const char *uuid;
-
   /* The revision that was youngest, last time we checked. */
   svn_revnum_t youngest_rev_cache;
 

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=1156226&r1=1156225&r2=1156226&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 Wed Aug 10 15:22:52 2011
@@ -1204,13 +1204,15 @@ svn_error_t *
 svn_fs_py__open(svn_fs_t *fs, const char *path, apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-  apr_file_t *uuid_file;
   int format, max_files_per_dir;
-  char buf[APR_UUID_FORMATTED_LENGTH + 2];
-  apr_size_t limit;
 
   fs->path = apr_pstrdup(fs->pool, path);
 
+  SVN_ERR(svn_fs_py__call_method(&ffd->p_fs, ffd->p_module, "_open_fs",
+                                 "(s)", path));
+  apr_pool_cleanup_register(fs->pool, ffd->p_fs, svn_fs_py__destroy_py_object,
+                            apr_pool_cleanup_null);
+
   /* Read the FS format number. */
   SVN_ERR(read_format(&format, &max_files_per_dir,
                       path_format(fs, pool), pool));
@@ -1220,16 +1222,6 @@ svn_fs_py__open(svn_fs_t *fs, const char
   ffd->format = format;
   ffd->max_files_per_dir = max_files_per_dir;
 
-  /* Read in and cache the repository uuid. */
-  SVN_ERR(svn_io_file_open(&uuid_file, path_uuid(fs, pool),
-                           APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
-
-  limit = sizeof(buf);
-  SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit, pool));
-  ffd->uuid = apr_pstrdup(fs->pool, buf);
-
-  SVN_ERR(svn_io_file_close(uuid_file, pool));
-
   /* Read the min unpacked revision. */
   if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
     SVN_ERR(update_min_unpacked_rev(fs, pool));
@@ -6755,8 +6747,8 @@ svn_fs_py__get_uuid(svn_fs_t *fs,
 {
   fs_fs_data_t *ffd = fs->fsap_data;
 
-  *uuid_p = apr_pstrdup(pool, ffd->uuid);
-  return SVN_NO_ERROR;
+  return svn_error_trace(svn_fs_py__get_string_attr(uuid_p, ffd->p_fs,
+                                                    "uuid", pool));
 }
 
 svn_error_t *
@@ -6764,34 +6756,11 @@ svn_fs_py__set_uuid(svn_fs_t *fs,
                     const char *uuid,
                     apr_pool_t *pool)
 {
-  char *my_uuid;
-  apr_size_t my_uuid_len;
-  const char *tmp_path;
-  const char *uuid_path = path_uuid(fs, pool);
   fs_fs_data_t *ffd = fs->fsap_data;
 
-  if (! uuid)
-    uuid = svn_uuid_generate(pool);
-
-  /* Make sure we have a copy in FS->POOL, and append a newline. */
-  my_uuid = apr_pstrcat(fs->pool, uuid, "\n", (char *)NULL);
-  my_uuid_len = strlen(my_uuid);
-
-  SVN_ERR(svn_io_write_unique(&tmp_path,
-                              svn_dirent_dirname(uuid_path, pool),
-                              my_uuid, my_uuid_len,
-                              svn_io_file_del_none, pool));
-
-  /* We use the permissions of the 'current' file, because the 'uuid'
-     file does not exist during repository creation. */
-  SVN_ERR(move_into_place(tmp_path, uuid_path,
-                          svn_fs_py__path_current(fs, pool), pool));
-
-  /* Remove the newline we added, and stash the UUID. */
-  my_uuid[my_uuid_len - 1] = '\0';
-  ffd->uuid = my_uuid;
-
-  return SVN_NO_ERROR;
+  return svn_error_trace(svn_fs_py__call_method(NULL, ffd->p_module,
+                                                "_set_uuid",
+                                                "(Os)", ffd->p_fs, uuid));
 }
 
 /** Node origin lazy cache. */

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=1156226&r1=1156225&r2=1156226&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 Wed Aug 10 15:22:52 2011
@@ -23,6 +23,7 @@
 #include <apr_pools.h>
 
 #include "svn_error.h"
+#include "svn_pools.h"
 
 #include "py_util.h"
 
@@ -44,65 +45,62 @@ create_py_stack(PyObject *p_exception,
   p_reason = PyObject_Str(p_exception);
   reason = PyString_AsString(p_reason);
 
-#ifdef SVN_ERR__TRACING
-  {
-    PyObject *p_module_name;
-    PyObject *p_traceback_mod;
-    PyObject *p_stack;
-    PyObject *p_frame;
-    PyObject *p_filename;
-    PyObject *p_lineno;
-    Py_ssize_t i;
-
-    /* We don't use load_module() here to avoid an infinite recursion. */
-    /* ### This could use more python error checking. */
-    p_module_name = PyString_FromString("traceback");
-    p_traceback_mod = PyImport_Import(p_module_name);
-    Py_DECREF(p_module_name);
-
-    p_stack = PyObject_CallMethod(p_traceback_mod, "extract_tb",
-                                  "(O)", p_traceback);
-    Py_DECREF(p_traceback_mod);
-
-    i = PySequence_Length(p_stack);
-
-    /* Build the "root error" for the chain. */
-    p_frame = PySequence_GetItem(p_stack, i-1);
-    p_filename = PySequence_GetItem(p_frame, 0);
-    p_lineno = PySequence_GetItem(p_frame, 1);
-    Py_DECREF(p_frame);
-
-    err = svn_error_createf(SVN_ERR_BAD_PYTHON, NULL,
-                          _("Exception while executing Python; cause: '%s'"),
+  err = svn_error_createf(SVN_ERR_BAD_PYTHON, NULL,
+                          _("Exception while executing Python; cause: \"%s\""),
                           reason);
 
-    err->file = apr_pstrdup(err->pool, PyString_AsString(p_filename));
-    err->line = PyInt_AsLong(p_lineno);
+#ifdef SVN_ERR__TRACING
+  if (p_traceback)
+    {
+      PyObject *p_module_name;
+      PyObject *p_traceback_mod;
+      PyObject *p_stack;
+      PyObject *p_frame;
+      PyObject *p_filename;
+      PyObject *p_lineno;
+      Py_ssize_t i;
+
+      /* We don't use load_module() here to avoid an infinite recursion. */
+      /* ### This could use more python error checking. */
+      p_module_name = PyString_FromString("traceback");
+      p_traceback_mod = PyImport_Import(p_module_name);
+      Py_DECREF(p_module_name);
+
+      p_stack = PyObject_CallMethod(p_traceback_mod, "extract_tb",
+                                    "(O)", p_traceback);
+      Py_DECREF(p_traceback_mod);
+
+      i = PySequence_Length(p_stack);
+
+      /* Build the "root error" for the chain. */
+      p_frame = PySequence_GetItem(p_stack, i-1);
+      p_filename = PySequence_GetItem(p_frame, 0);
+      p_lineno = PySequence_GetItem(p_frame, 1);
+      Py_DECREF(p_frame);
 
-    Py_DECREF(p_filename);
-    Py_DECREF(p_lineno);
+      err->file = apr_pstrdup(err->pool, PyString_AsString(p_filename));
+      err->line = PyInt_AsLong(p_lineno);
 
-    for (i = i-2; i >=0; i--)
-      {
-        p_frame = PySequence_GetItem(p_stack, i);
-        p_filename = PySequence_GetItem(p_frame, 0);
-        p_lineno = PySequence_GetItem(p_frame, 1);
-        Py_DECREF(p_frame);
-
-        err = svn_error_quick_wrap(err, SVN_ERR__TRACED);
-        err->file = apr_pstrdup(err->pool, PyString_AsString(p_filename));
-        err->line = PyInt_AsLong(p_lineno);
+      Py_DECREF(p_filename);
+      Py_DECREF(p_lineno);
+
+      for (i = i-2; i >=0; i--)
+        {
+          p_frame = PySequence_GetItem(p_stack, i);
+          p_filename = PySequence_GetItem(p_frame, 0);
+          p_lineno = PySequence_GetItem(p_frame, 1);
+          Py_DECREF(p_frame);
+
+          err = svn_error_quick_wrap(err, SVN_ERR__TRACED);
+          err->file = apr_pstrdup(err->pool, PyString_AsString(p_filename));
+          err->line = PyInt_AsLong(p_lineno);
         
-        Py_DECREF(p_filename);
-        Py_DECREF(p_lineno);
-      }
+          Py_DECREF(p_filename);
+          Py_DECREF(p_lineno);
+        }
 
-    Py_DECREF(p_stack);
-  }
-#else
-  err = svn_error_createf(SVN_ERR_BAD_PYTHON, NULL,
-                          _("Exception while executing Python; cause: '%s'"),
-                          reason);
+      Py_DECREF(p_stack);
+    }
 #endif
 
   /* If the exception object has a 'code' attribute, and it's an integer,
@@ -119,7 +117,7 @@ create_py_stack(PyObject *p_exception,
 
   Py_DECREF(p_reason);
 
-  return err;
+  return svn_error_trace(err);
 }
 
 typedef void (*py_exc_func_t)(void *baton, va_list argp);
@@ -150,7 +148,7 @@ catch_py_exception(py_exc_func_t func,
 
   PyErr_Fetch(&p_type, &p_exception, &p_traceback);
 
-  if (p_exception && p_traceback)
+  if (p_exception)
     err = create_py_stack(p_exception, p_traceback);
   else
     err = svn_error_create(SVN_ERR_BAD_PYTHON, NULL,
@@ -162,7 +160,7 @@ catch_py_exception(py_exc_func_t func,
   Py_XDECREF(p_exception);
   Py_XDECREF(p_traceback);
 
-  return err;
+  return svn_error_trace(err);
 }
 
 static svn_error_t *
@@ -258,6 +256,58 @@ svn_fs_py__destroy_py_object(void *data)
 }
 
 
+struct get_string_attr_baton
+{
+  const char **result;
+  PyObject *p_obj;
+  const char *name;
+  apr_pool_t *result_pool;
+};
+
+
+static void
+get_string_attr(void *baton,
+                va_list argp)
+{
+  struct get_string_attr_baton *gsab = baton;
+  PyObject *p_attr;
+  PyObject *p_str;
+
+  /* ### This needs some exception handling */
+  
+  p_attr = PyObject_GetAttrString(gsab->p_obj, gsab->name);
+  if (PyErr_Occurred())
+    return;
+
+  p_str = PyObject_Str(p_attr);
+  Py_DECREF(p_attr);
+  if (PyErr_Occurred())
+    return;
+
+  *gsab->result = PyString_AsString(p_str);
+
+  if (gsab->result)
+    *gsab->result = apr_pstrdup(gsab->result_pool, *gsab->result);
+
+  Py_DECREF(p_str);
+
+  return;
+}
+
+
+svn_error_t *
+svn_fs_py__get_string_attr(const char **result,
+                           PyObject *p_obj,
+                           const char *name,
+                           apr_pool_t *result_pool)
+{
+  struct get_string_attr_baton gsab = {
+      result, p_obj, name, result_pool
+    };
+  return svn_error_trace(catch_py_exception(get_string_attr, &gsab, NULL));
+}
+
+
 struct call_method_baton
 {
   PyObject **p_result;
@@ -302,6 +352,7 @@ cm_free_objs:
   /* Error handler, decrefs all python objects we may have. */
   Py_XDECREF(p_args);
   Py_XDECREF(p_func);
+  Py_XDECREF(p_value);
 }
 
 
@@ -314,21 +365,17 @@ svn_fs_py__call_method(PyObject **p_resu
 {
   svn_error_t *err;
   va_list argp;
-  struct call_method_baton cmb;
+  struct call_method_baton cmb = {
+      p_result, p_obj, name, format
+    };
 
   SVN_ERR_ASSERT(p_obj != NULL);
 
   va_start(argp, format);
-
-  cmb.p_result = p_result;
-  cmb.p_obj = p_obj;
-  cmb.name = name;
-  cmb.format = format;
-
   err = catch_py_exception(call_method, &cmb, argp);
-
   va_end(argp);
-  return err;
+
+  return svn_error_trace(err);
 }
 
 PyObject *

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=1156226&r1=1156225&r2=1156226&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 Wed Aug 10 15:22:52 2011
@@ -46,3 +46,11 @@ svn_fs_py__convert_hash(void *object);
 /* Load a reference to the FS Python module into the shared data. */
 svn_error_t *
 svn_fs_py__load_module(fs_fs_data_t *ffd);
+
+/* Get an attribute value from a Python object, and return it in *RESULT,
+   allocated in RESULT_POOL. */
+svn_error_t *
+svn_fs_py__get_string_attr(const char **result,
+                           PyObject *p_obj,
+                           const char *name,
+                           apr_pool_t *result_pool);

Modified: subversion/branches/fs-py/subversion/python/svn/fs.py
URL: http://svn.apache.org/viewvc/subversion/branches/fs-py/subversion/python/svn/fs.py?rev=1156226&r1=1156225&r2=1156226&view=diff
==============================================================================
--- subversion/branches/fs-py/subversion/python/svn/fs.py (original)
+++ subversion/branches/fs-py/subversion/python/svn/fs.py Wed Aug 10 15:22:52 2011
@@ -18,8 +18,66 @@
 # specific language governing permissions and limitations
 # under the License.
 
+import os, uuid, shutil
+
+
+# Some constants
+PATH_UUID                   = "uuid"            # Contains UUID
+PATH_CURRENT                = "current"         # Youngest revision
+
+
+class FS(object):
+    def set_uuid(self, uuid_in = None):
+        '''Set the UUID for the filesystem.  If UUID_IN is not given, generate
+           a new one a la RFC 4122.'''
+
+        if not uuid_in:
+            uuid_in = uuid.uuid1()
+        self.uuid = uuid_in
+
+        open(self.__path_uuid, 'wb').write(str(self.uuid) + '\n')
+        # We use the permissions of the 'current' file, because the 'uuid'
+        # file does not exist during repository creation.
+        shutil.copymode(self.__path_current, self.__path_uuid)
+
+
+    def _create_fs(self):
+        'Create a new Subversion filesystem'
+
+
+    def _open_fs(self):
+        'Open an existing Subvesion filesystem'
+        self.uuid = uuid.UUID(open(
+                                self.__path_uuid, 'rb').readline().rstrip())
+
+
+    def __setup_paths(self):
+        self.__path_uuid = os.path.join(self.path, PATH_UUID)
+        self.__path_current = os.path.join(self.path, PATH_CURRENT)
+
+
+    def __init__(self, path, create=False, config=None):
+        self.path = path
+        self.__setup_paths()
+
+        if config:
+            self._config = config
+        else:
+            self._config = {}
+
+        if create:
+            self._create_fs()
+        else:
+            self._open_fs()
+
 
 
 # A few helper functions for C callers
 def _create_fs(path, config=None):
-    return "this is a filesystem object"
+    return FS(path, create=True, config=config)
+
+def _open_fs(path):
+    return FS(path)
+
+def _set_uuid(fs, uuid):
+    fs.set_uuid(uuid)



Mime
View raw message