You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by vm...@apache.org on 2012/05/29 03:39:49 UTC

svn commit: r1343447 [8/27] - in /subversion/branches/javahl-ra: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/server-side/ notes/ notes/api-errata/1.8/ notes/merge-tracking/ subv...

Modified: subversion/branches/javahl-ra/subversion/libsvn_delta/path_driver.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_delta/path_driver.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_delta/path_driver.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_delta/path_driver.c Tue May 29 01:39:41 2012
@@ -44,15 +44,13 @@ typedef struct dir_stack_t
 } dir_stack_t;
 
 
-/* Call EDITOR's open_directory() function with the PATH and REVISION
- * arguments, and then add the resulting dir baton to the dir baton
- * stack.
+/* Call EDITOR's open_directory() function with the PATH argument, then
+ * add the resulting dir baton to the dir baton stack.
  */
 static svn_error_t *
 open_dir(apr_array_header_t *db_stack,
          const svn_delta_editor_t *editor,
          const char *path,
-         svn_revnum_t revision,
          apr_pool_t *pool)
 {
   void *parent_db, *db;
@@ -69,7 +67,8 @@ open_dir(apr_array_header_t *db_stack,
   /* Call the EDITOR's open_directory function to get a new directory
      baton. */
   subpool = svn_pool_create(pool);
-  SVN_ERR(editor->open_directory(path, parent_db, revision, subpool, &db));
+  SVN_ERR(editor->open_directory(path, parent_db, SVN_INVALID_REVNUM, subpool,
+                                 &db));
 
   /* Now add the dir baton to the stack. */
   item = apr_pcalloc(subpool, sizeof(*item));
@@ -131,13 +130,12 @@ count_components(const char *path)
 
 /*** Public interfaces ***/
 svn_error_t *
-svn_delta_path_driver(const svn_delta_editor_t *editor,
-                      void *edit_baton,
-                      svn_revnum_t revision,
-                      const apr_array_header_t *paths,
-                      svn_delta_path_driver_cb_func_t callback_func,
-                      void *callback_baton,
-                      apr_pool_t *pool)
+svn_delta_path_driver2(const svn_delta_editor_t *editor,
+                       void *edit_baton,
+                       const apr_array_header_t *paths,
+                       svn_delta_path_driver_cb_func_t callback_func,
+                       void *callback_baton,
+                       apr_pool_t *pool)
 {
   apr_array_header_t *db_stack = apr_array_make(pool, 4, sizeof(void *));
   const char *last_path = NULL;
@@ -155,9 +153,6 @@ svn_delta_path_driver(const svn_delta_ed
   iterpool = svn_pool_create(pool);
   item = apr_pcalloc(subpool, sizeof(*item));
 
-  /* Sort the paths in a depth-first directory-ish order. */
-  qsort(paths->elts, paths->nelts, paths->elt_size, svn_sort_compare_paths);
-
   /* If the root of the edit is also a target path, we want to call
      the callback function to let the user open the root directory and
      do what needs to be done.  Otherwise, we'll do the open_root()
@@ -171,7 +166,7 @@ svn_delta_path_driver(const svn_delta_ed
     }
   else
     {
-      SVN_ERR(editor->open_root(edit_baton, revision, subpool, &db));
+      SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM, subpool, &db));
     }
   item->pool = subpool;
   item->dir_baton = db;
@@ -238,7 +233,7 @@ svn_delta_path_driver(const svn_delta_ed
                 rel = apr_pstrmemdup(iterpool, pdir, piece - pdir);
 
               /* Open the subdirectory. */
-              SVN_ERR(open_dir(db_stack, editor, rel, revision, pool));
+              SVN_ERR(open_dir(db_stack, editor, rel, pool));
 
               /* If we found a '/', advance our PIECE pointer to
                  character just after that '/'.  Otherwise, we're

Modified: subversion/branches/javahl-ra/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_delta/text_delta.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_delta/text_delta.c Tue May 29 01:39:41 2012
@@ -904,29 +904,54 @@ svn_error_t *svn_txdelta_send_stream(svn
                                      unsigned char *digest,
                                      apr_pool_t *pool)
 {
-  svn_txdelta_stream_t *txstream;
-  svn_error_t *err;
+  svn_txdelta_window_t delta_window = { 0 };
+  svn_txdelta_op_t delta_op;
+  svn_string_t window_data;
+  char read_buf[SVN__STREAM_CHUNK_SIZE + 1];
+  svn_checksum_ctx_t *md5_checksum_ctx;
 
-  /* ### this is a hack. we should simply read from the stream, construct
-     ### some windows, and pass those to the handler. there isn't any reason
-     ### to crank up a full "diff" algorithm just to copy a stream.
-     ###
-     ### will fix RSN. */
-
-  /* Create a delta stream which converts an *empty* bytestream into the
-     target bytestream. */
-  svn_txdelta(&txstream, svn_stream_empty(pool), stream, pool);
-  err = svn_txdelta_send_txstream(txstream, handler, handler_baton, pool);
+  if (digest)
+    md5_checksum_ctx = svn_checksum_ctx_create(svn_checksum_md5, pool);
 
-  if (digest && (! err))
+  while (1)
     {
-      const unsigned char *result_md5;
-      result_md5 = svn_txdelta_md5_digest(txstream);
-      /* Since err is null, result_md5 "cannot" be null. */
-      memcpy(digest, result_md5, APR_MD5_DIGESTSIZE);
+      apr_size_t read_len = SVN__STREAM_CHUNK_SIZE;
+      
+      SVN_ERR(svn_stream_read(stream, read_buf, &read_len));
+      if (read_len == 0)
+        break;
+      
+      window_data.data = read_buf;
+      window_data.len = read_len;
+      
+      delta_op.action_code = svn_txdelta_new;
+      delta_op.offset = 0;
+      delta_op.length = read_len;
+      
+      delta_window.tview_len = read_len;
+      delta_window.num_ops = 1;
+      delta_window.ops = &delta_op;
+      delta_window.new_data = &window_data;
+      
+      SVN_ERR(handler(&delta_window, handler_baton));
+
+      if (digest)
+        SVN_ERR(svn_checksum_update(md5_checksum_ctx, read_buf, read_len));
+      
+      if (read_len < SVN__STREAM_CHUNK_SIZE)
+        break;
     }
+  SVN_ERR(handler(NULL, handler_baton));
 
-  return err;
+  if (digest)
+    {
+      svn_checksum_t *md5_checksum;
+
+      SVN_ERR(svn_checksum_final(&md5_checksum, md5_checksum_ctx, pool));
+      memcpy(digest, md5_checksum->digest, APR_MD5_DIGESTSIZE);
+    }
+  
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *svn_txdelta_send_txstream(svn_txdelta_stream_t *txstream,

Modified: subversion/branches/javahl-ra/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_diff/diff_file.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_diff/diff_file.c Tue May 29 01:39:41 2012
@@ -2043,8 +2043,7 @@ output_line(svn_diff3__file_output_baton
 static svn_error_t *
 output_marker_eol(svn_diff3__file_output_baton_t *btn)
 {
-  apr_size_t len = strlen(btn->marker_eol);
-  return svn_stream_write(btn->output_stream, btn->marker_eol, &len);
+  return svn_stream_puts(btn->output_stream, btn->marker_eol);
 }
 
 static svn_error_t *
@@ -2127,7 +2126,7 @@ output_conflict_with_context(svn_diff3__
   if (btn->output_stream == btn->context_saver->stream)
     {
       if (btn->context_saver->total_written > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
-        SVN_ERR(svn_stream_printf(btn->real_output_stream, btn->pool, "@@\n"));
+        SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n"));
       SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream));
     }
 
@@ -2179,7 +2178,6 @@ output_conflict(void *baton,
                 svn_diff_t *diff)
 {
   svn_diff3__file_output_baton_t *file_baton = baton;
-  apr_size_t len;
 
   svn_diff_conflict_display_style_t style = file_baton->conflict_style;
 
@@ -2201,33 +2199,28 @@ output_conflict(void *baton,
   if (style == svn_diff_conflict_display_modified_latest ||
       style == svn_diff_conflict_display_modified_original_latest)
     {
-      len = strlen(file_baton->conflict_modified);
-      SVN_ERR(svn_stream_write(file_baton->output_stream,
-                               file_baton->conflict_modified,
-                               &len));
+      SVN_ERR(svn_stream_puts(file_baton->output_stream,
+                               file_baton->conflict_modified));
       SVN_ERR(output_marker_eol(file_baton));
 
       SVN_ERR(output_hunk(baton, 1, modified_start, modified_length));
 
       if (style == svn_diff_conflict_display_modified_original_latest)
         {
-          len = strlen(file_baton->conflict_original);
-          SVN_ERR(svn_stream_write(file_baton->output_stream,
-                                   file_baton->conflict_original, &len));
+          SVN_ERR(svn_stream_puts(file_baton->output_stream,
+                                   file_baton->conflict_original));
           SVN_ERR(output_marker_eol(file_baton));
           SVN_ERR(output_hunk(baton, 0, original_start, original_length));
         }
 
-      len = strlen(file_baton->conflict_separator);
-      SVN_ERR(svn_stream_write(file_baton->output_stream,
-                               file_baton->conflict_separator, &len));
+      SVN_ERR(svn_stream_puts(file_baton->output_stream,
+                              file_baton->conflict_separator));
       SVN_ERR(output_marker_eol(file_baton));
 
       SVN_ERR(output_hunk(baton, 2, latest_start, latest_length));
 
-      len = strlen(file_baton->conflict_latest);
-      SVN_ERR(svn_stream_write(file_baton->output_stream,
-                               file_baton->conflict_latest, &len));
+      SVN_ERR(svn_stream_puts(file_baton->output_stream,
+                              file_baton->conflict_latest));
       SVN_ERR(output_marker_eol(file_baton));
     }
   else if (style == svn_diff_conflict_display_modified)

Modified: subversion/branches/javahl-ra/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_diff/diff_memory.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_diff/diff_memory.c Tue May 29 01:39:41 2012
@@ -808,15 +808,13 @@ output_merge_token_range(apr_size_t *lin
 static svn_error_t *
 output_marker_eol(merge_output_baton_t *btn)
 {
-  apr_size_t len = strlen(btn->marker_eol);
-  return svn_stream_write(btn->output_stream, btn->marker_eol, &len);
+  return svn_stream_puts(btn->output_stream, btn->marker_eol);
 }
 
 static svn_error_t *
 output_merge_marker(merge_output_baton_t *btn, int idx)
 {
-  apr_size_t len = strlen(btn->markers[idx]);
-  SVN_ERR(svn_stream_write(btn->output_stream, btn->markers[idx], &len));
+  SVN_ERR(svn_stream_puts(btn->output_stream, btn->markers[idx]));
   return output_marker_eol(btn);
 }
 
@@ -924,7 +922,7 @@ output_conflict_with_context(void *baton
   if (btn->output_stream == btn->context_saver->stream)
     {
       if (btn->context_saver->total_written > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
-        SVN_ERR(svn_stream_printf(btn->real_output_stream, btn->pool, "@@\n"));
+        SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n"));
       SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream));
     }
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs/editor.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs/editor.c Tue May 29 01:39:41 2012
@@ -28,44 +28,699 @@
 #include "svn_pools.h"
 #include "svn_editor.h"
 #include "svn_fs.h"
+#include "svn_props.h"
+
+#include "svn_private_config.h"
 
 #include "fs-loader.h"
 
+#include "private/svn_fspath.h"
+
 
 struct edit_baton {
+  /* The transaction associated with this editor.  */
   svn_fs_txn_t *txn;
-  svn_boolean_t no_autocommit;
+
+  /* Has this editor been completed?  */
+  svn_boolean_t completed;
+
+  /* We sometimes need the cancellation beyond what svn_editor_t provides  */
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
+
+  /* The pool that the txn lives within. When we create a ROOT, it will
+     be allocated within a subpool of this. The root will be closed in
+     complete/abort and that subpool will be destroyed.
+
+     This pool SHOULD NOT be used for any allocations.  */
+  apr_pool_t *txn_pool;
+
+  /* This is the root from the txn. Use get_root() to fetch/create this
+     member as appropriate.  */
+  svn_fs_root_t *root;
 };
 
+#define FSPATH(relpath, pool) apr_pstrcat(pool, "/", relpath, NULL)
+#define UNUSED(x) ((void)(x))
+
+
+static svn_error_t *
+get_root(svn_fs_root_t **root,
+         struct edit_baton *eb)
+{
+  if (eb->root == NULL)
+    SVN_ERR(svn_fs_txn_root(&eb->root, eb->txn, eb->txn_pool));
+  *root = eb->root;
+  return SVN_NO_ERROR;
+}
+
+
+/* Apply each property in PROPS to the node at FSPATH in ROOT.  */
+static svn_error_t *
+add_new_props(svn_fs_root_t *root,
+              const char *fspath,
+              apr_hash_t *props,
+              apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_index_t *hi;
+
+  /* ### it would be nice to have svn_fs_set_node_props(). but since we
+     ### don't... add each property to the node. this is a new node, so
+     ### we don't need to worry about deleting props. just adding.  */
+
+  for (hi = apr_hash_first(scratch_pool, props); hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *name = svn__apr_hash_index_key(hi);
+      const svn_string_t *value = svn__apr_hash_index_val(hi);
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_fs_change_node_prop(root, fspath, name, value, iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+alter_props(svn_fs_root_t *root,
+            const char *fspath,
+            apr_hash_t *props,
+            apr_pool_t *scratch_pool)
+{
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  apr_hash_t *old_props;
+  apr_array_header_t *propdiffs;
+  int i;
+
+  SVN_ERR(svn_fs_node_proplist(&old_props, root, fspath, scratch_pool));
+
+  SVN_ERR(svn_prop_diffs(&propdiffs, props, old_props, scratch_pool));
+
+  for (i = 0; i < propdiffs->nelts; ++i)
+    {
+      const svn_prop_t *prop = &APR_ARRAY_IDX(propdiffs, i, svn_prop_t);
+
+      svn_pool_clear(iterpool);
+
+      /* Add, change, or delete properties.  */
+      SVN_ERR(svn_fs_change_node_prop(root, fspath, prop->name, prop->value,
+                                      iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+set_text(svn_fs_root_t *root,
+         const char *fspath,
+         const svn_checksum_t *checksum,
+         svn_stream_t *contents,
+         svn_cancel_func_t cancel_func,
+         void *cancel_baton,
+         apr_pool_t *scratch_pool)
+{
+  svn_stream_t *fs_contents;
+
+  /* ### We probably don't have an MD5 checksum, so no digest is available
+     ### for svn_fs_apply_text() to validate. It would be nice to have an
+     ### FS API that takes our CHECKSUM/CONTENTS pair (and PROPS!).  */
+  SVN_ERR(svn_fs_apply_text(&fs_contents, root, fspath,
+                            NULL /* result_checksum */,
+                            scratch_pool));
+  SVN_ERR(svn_stream_copy3(contents, fs_contents,
+                           cancel_func, cancel_baton,
+                           scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+/* The caller wants to modify REVISION of FSPATH. Is that allowed?  */
+static svn_error_t *
+can_modify(svn_fs_root_t *txn_root,
+           const char *fspath,
+           svn_revnum_t revision,
+           apr_pool_t *scratch_pool)
+{
+  svn_revnum_t created_rev;
+
+  /* Out-of-dateness check:  compare the created-rev of the node
+     in the txn against the created-rev of FSPATH.  */
+  SVN_ERR(svn_fs_node_created_rev(&created_rev, txn_root, fspath,
+                                  scratch_pool));
+
+  /* Uncommitted nodes (eg. a descendent of a copy/move/rotate destination)
+     have no (committed) revision number. Let the caller go ahead and
+     modify these nodes.
+
+     Note: strictly speaking, they might be performing an "illegal" edit
+     in certain cases, but let's just assume they're Good Little Boys.
+
+     If CREATED_REV is invalid, that means it's already mutable in the
+     txn, which means it has already passed this out-of-dateness check.
+     (Usually, this happens when looking at a parent directory of an
+     already-modified node)  */
+  if (!SVN_IS_VALID_REVNUM(created_rev))
+    return SVN_NO_ERROR;
+
+  /* If the node is immutable (has a revision), then the caller should
+     have supplied a valid revision number [that they expect to change].
+     The checks further below will determine the out-of-dateness of the
+     specified revision.  */
+  /* ### ugh. descendents of copy/move/rotate destinations carry along
+     ### their original immutable state and (thus) a valid CREATED_REV.
+     ### but they are logically uncommitted, so the caller will pass
+     ### SVN_INVALID_REVNUM. (technically, the caller could provide
+     ### ORIGINAL_REV, but that is semantically incorrect for the Ev2
+     ### API).
+     ###
+     ### for now, we will assume the caller knows what they are doing
+     ### and an invalid revision implies such a descendent. in the
+     ### future, we could examine the ancestor chain looking for a
+     ### copy/move/rotate-here node and allow the modification (and the
+     ### converse: if no such ancestor, the caller must specify the
+     ### correct/intended revision to modify).
+  */
+#if 1
+  if (!SVN_IS_VALID_REVNUM(revision))
+    return SVN_NO_ERROR;
+#else
+  if (!SVN_IS_VALID_REVNUM(revision))
+    /* ### use a custom error code?  */
+    return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                             N_("Revision for modifying '%s' is required"),
+                             fspath);
+#endif
+
+  if (revision < created_rev)
+    {
+      /* We asked to change a node that is *older* than what we found
+         in the transaction. The client is out of date.  */
+      return svn_error_createf(SVN_ERR_FS_OUT_OF_DATE, NULL,
+                               _("'%s' is out of date; try updating"),
+                               fspath);
+    }
+
+  if (revision > created_rev)
+    {
+      /* We asked to change a node that is *newer* than what we found
+         in the transaction. Given that the transaction was based off
+         of 'youngest', then either:
+         - the caller asked to modify a future node
+         - the caller has committed more revisions since this txn
+         was constructed, and is asking to modify a node in one
+         of those new revisions.
+         In either case, the node may not have changed in those new
+         revisions; use the node's ID to determine this case.  */
+      const svn_fs_id_t *txn_noderev_id;
+      svn_fs_root_t *rev_root;
+      const svn_fs_id_t *new_noderev_id;
+
+      /* The ID of the node that we would be modifying in the txn  */
+      SVN_ERR(svn_fs_node_id(&txn_noderev_id, txn_root, fspath,
+                             scratch_pool));
+
+      /* Get the ID from the future/new revision.  */
+      SVN_ERR(svn_fs_revision_root(&rev_root, svn_fs_root_fs(txn_root),
+                                   revision, scratch_pool));
+      SVN_ERR(svn_fs_node_id(&new_noderev_id, rev_root, fspath,
+                             scratch_pool));
+      svn_fs_close_root(rev_root);
+
+      /* Has the target node changed in the future?  */
+      if (svn_fs_compare_ids(txn_noderev_id, new_noderev_id) != 0)
+        {
+          /* Restarting the commit will base the txn on the future/new
+             revision, allowing the modification at REVISION.  */
+          /* ### use a custom error code  */
+          return svn_error_createf(SVN_ERR_FS_CONFLICT, NULL,
+                                   _("'%s' has been modified since the "
+                                     "commit began (restart the commit)"),
+                                   fspath);
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* Can we create a node at FSPATH in TXN_ROOT? If something already exists
+   at that path, then the client MAY be out of date. We then have to see if
+   the path was created/modified in this transaction. IOW, it is new and
+   can be replaced without problem.
+
+   Note: the editor protocol disallows double-modifications. This is to
+   ensure somebody does not accidentally overwrite another file due to
+   being out-of-date.  */
+static svn_error_t *
+can_create(svn_fs_root_t *txn_root,
+           const char *fspath,
+           apr_pool_t *scratch_pool)
+{
+  svn_node_kind_t kind;
+  const char *cur_fspath;
+
+  SVN_ERR(svn_fs_check_path(&kind, txn_root, fspath, scratch_pool));
+  if (kind == svn_node_none)
+    return SVN_NO_ERROR;
+
+  /* ### I'm not sure if this works perfectly. We might have an ancestor
+     ### that was modified as a result of a change on a cousin. We might
+     ### misinterpret that as a *-here node which brought along this
+     ### child. Need to write a test to verify. We may also be able to
+     ### test the ancestor to determine if it has been *-here in this
+     ### txn, or just a simple modification.  */
+
+  /* Are any of the parents copied/moved/rotated-here?  */
+  for (cur_fspath = fspath;
+       strlen(cur_fspath) > 1;  /* not the root  */
+       cur_fspath = svn_fspath__dirname(cur_fspath, scratch_pool))
+    {
+      svn_revnum_t created_rev;
+
+      SVN_ERR(svn_fs_node_created_rev(&created_rev, txn_root, cur_fspath,
+                                      scratch_pool));
+      if (!SVN_IS_VALID_REVNUM(created_rev))
+        {
+          /* The node has no created revision, meaning it is uncommitted.
+             Thus, it was created in this transaction, or it has already
+             been modified in some way (implying it has already passed a
+             modification check.  */
+          /* ### verify the node has been *-here ??  */
+          return SVN_NO_ERROR;
+        }
+    }
+
+  return svn_error_createf(SVN_ERR_FS_OUT_OF_DATE, NULL,
+                           _("'%s' already exists, so may be out"
+                             " of date; try updating"),
+                           fspath);
+}
+
+
+/* This implements svn_editor_cb_add_directory_t */
+static svn_error_t *
+add_directory_cb(void *baton,
+                 const char *relpath,
+                 const apr_array_header_t *children,
+                 apr_hash_t *props,
+                 svn_revnum_t replaces_rev,
+                 apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  const char *fspath = FSPATH(relpath, scratch_pool);
+  svn_fs_root_t *root;
+
+  /* Note: we ignore CHILDREN. We have no "incomplete" state to worry about,
+     so we don't need to be aware of what children will be created.  */
+
+  SVN_ERR(get_root(&root, eb));
+
+  if (SVN_IS_VALID_REVNUM(replaces_rev))
+    {
+      SVN_ERR(can_modify(root, fspath, replaces_rev, scratch_pool));
+      SVN_ERR(svn_fs_delete(root, fspath, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(can_create(root, fspath, scratch_pool));
+    }
+
+  SVN_ERR(svn_fs_make_dir(root, fspath, scratch_pool));
+  SVN_ERR(add_new_props(root, fspath, props, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_add_file_t */
+static svn_error_t *
+add_file_cb(void *baton,
+            const char *relpath,
+            const svn_checksum_t *checksum,
+            svn_stream_t *contents,
+            apr_hash_t *props,
+            svn_revnum_t replaces_rev,
+            apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  const char *fspath = FSPATH(relpath, scratch_pool);
+  svn_fs_root_t *root;
+
+  SVN_ERR(get_root(&root, eb));
+
+  if (SVN_IS_VALID_REVNUM(replaces_rev))
+    {
+      SVN_ERR(can_modify(root, fspath, replaces_rev, scratch_pool));
+      SVN_ERR(svn_fs_delete(root, fspath, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(can_create(root, fspath, scratch_pool));
+    }
+
+  SVN_ERR(svn_fs_make_file(root, fspath, scratch_pool));
+
+  SVN_ERR(set_text(root, fspath, checksum, contents,
+                   eb->cancel_func, eb->cancel_baton, scratch_pool));
+  SVN_ERR(add_new_props(root, fspath, props, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_add_symlink_t */
+static svn_error_t *
+add_symlink_cb(void *baton,
+               const char *relpath,
+               const char *target,
+               apr_hash_t *props,
+               svn_revnum_t replaces_rev,
+               apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  const char *fspath = FSPATH(relpath, scratch_pool);
+  svn_fs_root_t *root;
+
+  SVN_ERR(get_root(&root, eb));
+
+  if (SVN_IS_VALID_REVNUM(replaces_rev))
+    {
+      SVN_ERR(can_modify(root, fspath, replaces_rev, scratch_pool));
+      SVN_ERR(svn_fs_delete(root, fspath, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(can_create(root, fspath, scratch_pool));
+    }
+
+  /* ### we probably need to construct a file with specific contents
+     ### (until the FS grows some symlink APIs)  */
+#if 0
+  SVN_ERR(svn_fs_make_file(root, fspath, scratch_pool));
+  SVN_ERR(svn_fs_apply_text(&fs_contents, root, fspath,
+                            NULL /* result_checksum */,
+                            scratch_pool));
+  /* ### SVN_ERR(svn_stream_printf(fs_contents, ..., scratch_pool));  */
+  apr_hash_set(props, SVN_PROP_SPECIAL, APR_HASH_KEY_STRING,
+               SVN_PROP_SPECIAL_VALUE);
+
+  SVN_ERR(add_new_props(root, fspath, props, scratch_pool));
+#endif
+
+  SVN__NOT_IMPLEMENTED();
+}
+
+
+/* This implements svn_editor_cb_add_absent_t */
+static svn_error_t *
+add_absent_cb(void *baton,
+              const char *relpath,
+              svn_kind_t kind,
+              svn_revnum_t replaces_rev,
+              apr_pool_t *scratch_pool)
+{
+  /* This is a programming error. Code should not attempt to create these
+     kinds of nodes within the FS.  */
+  /* ### use a custom error code  */
+  return svn_error_create(
+           SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+           N_("The filesystem does not support 'absent' nodes"));
+}
+
+
+/* This implements svn_editor_cb_alter_directory_t */
+static svn_error_t *
+alter_directory_cb(void *baton,
+                   const char *relpath,
+                   svn_revnum_t revision,
+                   const apr_array_header_t *children,
+                   apr_hash_t *props,
+                   apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  const char *fspath = FSPATH(relpath, scratch_pool);
+  svn_fs_root_t *root;
+
+  /* Note: we ignore CHILDREN. We have no "incomplete" state to worry about,
+     so we don't need to be aware of what children will be created.  */
+
+  SVN_ERR(get_root(&root, eb));
+  SVN_ERR(can_modify(root, fspath, revision, scratch_pool));
+
+  SVN_ERR(alter_props(root, fspath, props, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_alter_file_t */
+static svn_error_t *
+alter_file_cb(void *baton,
+              const char *relpath,
+              svn_revnum_t revision,
+              apr_hash_t *props,
+              const svn_checksum_t *checksum,
+              svn_stream_t *contents,
+              apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  const char *fspath = FSPATH(relpath, scratch_pool);
+  svn_fs_root_t *root;
+
+  SVN_ERR(get_root(&root, eb));
+  SVN_ERR(can_modify(root, fspath, revision, scratch_pool));
+
+  if (contents != NULL)
+    {
+      SVN_ERR_ASSERT(checksum != NULL);
+      SVN_ERR(set_text(root, fspath, checksum, contents,
+                       eb->cancel_func, eb->cancel_baton, scratch_pool));
+    }
+
+  if (props != NULL)
+    {
+      SVN_ERR(alter_props(root, fspath, props, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_alter_symlink_t */
+static svn_error_t *
+alter_symlink_cb(void *baton,
+                 const char *relpath,
+                 svn_revnum_t revision,
+                 apr_hash_t *props,
+                 const char *target,
+                 apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+
+  UNUSED(eb); SVN__NOT_IMPLEMENTED();
+}
+
+
+/* This implements svn_editor_cb_delete_t */
+static svn_error_t *
+delete_cb(void *baton,
+          const char *relpath,
+          svn_revnum_t revision,
+          apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  const char *fspath = FSPATH(relpath, scratch_pool);
+  svn_fs_root_t *root;
+
+  SVN_ERR(get_root(&root, eb));
+  SVN_ERR(can_modify(root, fspath, revision, scratch_pool));
+
+  SVN_ERR(svn_fs_delete(root, fspath, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_copy_t */
+static svn_error_t *
+copy_cb(void *baton,
+        const char *src_relpath,
+        svn_revnum_t src_revision,
+        const char *dst_relpath,
+        svn_revnum_t replaces_rev,
+        apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  const char *src_fspath = FSPATH(src_relpath, scratch_pool);
+  const char *dst_fspath = FSPATH(dst_relpath, scratch_pool);
+  svn_fs_root_t *root;
+  svn_fs_root_t *src_root;
+
+  SVN_ERR(get_root(&root, eb));
+
+  /* Check if we can we replace the maybe-specified destination (revision).  */
+  if (SVN_IS_VALID_REVNUM(replaces_rev))
+    {
+      SVN_ERR(can_modify(root, dst_fspath, replaces_rev, scratch_pool));
+      SVN_ERR(svn_fs_delete(root, dst_fspath, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(can_create(root, dst_fspath, scratch_pool));
+    }
+
+  SVN_ERR(svn_fs_revision_root(&src_root, svn_fs_root_fs(root), src_revision,
+                               scratch_pool));
+  SVN_ERR(svn_fs_copy(src_root, src_fspath, root, dst_fspath, scratch_pool));
+  svn_fs_close_root(src_root);
+
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_move_t */
+static svn_error_t *
+move_cb(void *baton,
+        const char *src_relpath,
+        svn_revnum_t src_revision,
+        const char *dst_relpath,
+        svn_revnum_t replaces_rev,
+        apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  const char *src_fspath = FSPATH(src_relpath, scratch_pool);
+  const char *dst_fspath = FSPATH(dst_relpath, scratch_pool);
+  svn_fs_root_t *root;
+  svn_fs_root_t *src_root;
+
+  SVN_ERR(get_root(&root, eb));
+
+  /* Check if we delete the specified source (revision), and can we replace
+     the maybe-specified destination (revision).  */
+  SVN_ERR(can_modify(root, src_fspath, src_revision, scratch_pool));
+  if (SVN_IS_VALID_REVNUM(replaces_rev))
+    {
+      SVN_ERR(can_modify(root, dst_fspath, replaces_rev, scratch_pool));
+      SVN_ERR(svn_fs_delete(root, dst_fspath, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(can_create(root, dst_fspath, scratch_pool));
+    }
+
+  /* ### would be nice to have svn_fs_move()  */
+
+  /* Copy the src to the dst. */
+  SVN_ERR(svn_fs_revision_root(&src_root, svn_fs_root_fs(root), src_revision,
+                               scratch_pool));
+  SVN_ERR(svn_fs_copy(src_root, src_fspath, root, dst_fspath, scratch_pool));
+  svn_fs_close_root(src_root);
+
+  /* Notice: we're deleting the src repos path from the dst root. */
+  SVN_ERR(svn_fs_delete(root, src_fspath, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_rotate_t */
+static svn_error_t *
+rotate_cb(void *baton,
+          const apr_array_header_t *relpaths,
+          const apr_array_header_t *revisions,
+          apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+
+  UNUSED(eb); SVN__NOT_IMPLEMENTED();
+}
+
+
+/* This implements svn_editor_cb_complete_t */
+static svn_error_t *
+complete_cb(void *baton,
+            apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+
+  /* Watch out for a following call to svn_fs_editor_commit(). Note that
+     we are likely here because svn_fs_editor_commit() was called, and it
+     invoked svn_editor_complete().  */
+  eb->completed = TRUE;
+
+  if (eb->root != NULL)
+    {
+      svn_fs_close_root(eb->root);
+      eb->root = NULL;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* This implements svn_editor_cb_abort_t */
+static svn_error_t *
+abort_cb(void *baton,
+         apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = baton;
+  svn_error_t *err;
+
+  /* Don't allow a following call to svn_fs_editor_commit().  */
+  eb->completed = TRUE;
+
+  if (eb->root != NULL)
+    {
+      svn_fs_close_root(eb->root);
+      eb->root = NULL;
+    }
+
+  /* ### should we examine the error and attempt svn_fs_purge_txn() ?  */
+  err = svn_fs_abort_txn(eb->txn, scratch_pool);
+
+  /* For safety, clear the now-useless txn.  */
+  eb->txn = NULL;
+
+  return svn_error_trace(err);
+}
+
 
 static svn_error_t *
 make_editor(svn_editor_t **editor,
             svn_fs_txn_t *txn,
-            svn_boolean_t no_autocommit,
             svn_cancel_func_t cancel_func,
             void *cancel_baton,
             apr_pool_t *result_pool,
             apr_pool_t *scratch_pool)
 {
   static const svn_editor_cb_many_t editor_cbs = {
-    NULL /* add_directory_cb */,
-    NULL /* add_file_cb */,
-    NULL /* add_symlink_cb */,
-    NULL /* add_absent_cb */,
-    NULL /* alter_directory_cb */,
-    NULL /* alter_file_cb */,
-    NULL /* alter_symlink_cb */,
-    NULL /* delete_cb */,
-    NULL /* copy_cb */,
-    NULL /* move_cb */,
-    NULL /* rotate_cb */,
-    NULL /* complete_cb */,
-    NULL /* abort_cb */
+    add_directory_cb,
+    add_file_cb,
+    add_symlink_cb,
+    add_absent_cb,
+    alter_directory_cb,
+    alter_file_cb,
+    alter_symlink_cb,
+    delete_cb,
+    copy_cb,
+    move_cb,
+    rotate_cb,
+    complete_cb,
+    abort_cb
   };
-  struct edit_baton *eb = apr_palloc(result_pool, sizeof(*eb));
+  struct edit_baton *eb = apr_pcalloc(result_pool, sizeof(*eb));
 
   eb->txn = txn;
-  eb->no_autocommit = no_autocommit;
+  eb->cancel_func = cancel_func;
+  eb->cancel_baton = cancel_baton;
+  eb->txn_pool = result_pool;
 
   SVN_ERR(svn_editor_create(editor, eb, cancel_func, cancel_baton,
                             result_pool, scratch_pool));
@@ -79,19 +734,19 @@ svn_error_t *
 svn_fs_editor_create(svn_editor_t **editor,
                      const char **txn_name,
                      svn_fs_t *fs,
-                     svn_revnum_t revision,
                      apr_uint32_t flags,
                      svn_cancel_func_t cancel_func,
                      void *cancel_baton,
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool)
 {
+  svn_revnum_t revision;
   svn_fs_txn_t *txn;
-  svn_boolean_t no_autocommit = (flags & SVN_FS_TXN_NO_AUTOCOMMIT) != 0;
 
+  SVN_ERR(svn_fs_youngest_rev(&revision, fs, scratch_pool));
   SVN_ERR(svn_fs_begin_txn2(&txn, fs, revision, flags, result_pool));
   SVN_ERR(svn_fs_txn_name(txn_name, txn, result_pool));
-  return svn_error_trace(make_editor(editor, txn, no_autocommit,
+  return svn_error_trace(make_editor(editor, txn,
                                      cancel_func, cancel_baton,
                                      result_pool, scratch_pool));
 }
@@ -109,8 +764,84 @@ svn_fs_editor_create_for(svn_editor_t **
   svn_fs_txn_t *txn;
 
   SVN_ERR(svn_fs_open_txn(&txn, fs, txn_name, result_pool));
-  return svn_error_trace(make_editor(editor, txn, TRUE /* no_autocommit */,
+  return svn_error_trace(make_editor(editor, txn,
                                      cancel_func, cancel_baton,
                                      result_pool, scratch_pool));
 }
 
+
+svn_error_t *
+svn_fs_editor_commit(svn_revnum_t *revision,
+                     svn_error_t **post_commit_err,
+                     const char **conflict_path,
+                     svn_editor_t *editor,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
+{
+  struct edit_baton *eb = svn_editor_get_baton(editor);
+  const char *inner_conflict_path;
+  svn_error_t *err = NULL;
+
+  /* make sure people are using the correct sequencing.  */
+  if (eb->completed)
+    return svn_error_create(SVN_ERR_FS_INCORRECT_EDITOR_COMPLETION,
+                            NULL, NULL);
+
+  *revision = SVN_INVALID_REVNUM;
+  *post_commit_err = NULL;
+  *conflict_path = NULL;
+
+  /* Clean up internal resources (eg. eb->root). This also allows the
+     editor infrastructure to know this editor is "complete".  */
+  err = svn_editor_complete(editor);
+
+  /* Note: docco for svn_fs_commit_txn() states that CONFLICT_PATH will
+     be allocated in the txn's pool. But it lies. Regardless, we want
+     it placed into RESULT_POOL.  */
+
+  if (!err)
+    err = svn_fs_commit_txn(&inner_conflict_path,
+                            revision,
+                            eb->txn,
+                            scratch_pool);
+  if (SVN_IS_VALID_REVNUM(*revision))
+    {
+      if (err)
+        {
+          /* Case 3. ERR is a post-commit (cleanup) error.  */
+
+          /* Pass responsibility via POST_COMMIT_ERR.  */
+          *post_commit_err = err;
+          err = SVN_NO_ERROR;
+        }
+      /* else: Case 1.  */
+    }
+  else
+    {
+      SVN_ERR_ASSERT(err != NULL);
+      if (err->apr_err == SVN_ERR_FS_CONFLICT)
+        {
+          /* Case 2.  */
+
+          /* Copy this into the correct pool (see note above).  */
+          *conflict_path = apr_pstrdup(result_pool, inner_conflict_path);
+
+          /* Return sucess. The caller should inspect CONFLICT_PATH to
+             determine this particular case.  */
+          svn_error_clear(err);
+          err = SVN_NO_ERROR;
+        }
+      /* else: Case 4.  */
+
+      /* Abort the TXN. Nobody wants to use it.  */
+      /* ### should we examine the error and attempt svn_fs_purge_txn() ?  */
+      err = svn_error_compose_create(
+        err,
+        svn_fs_abort_txn(eb->txn, scratch_pool));
+    }
+
+  /* For safety, clear the now-useless txn.  */
+  eb->txn = NULL;
+
+  return svn_error_trace(err);
+}

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.c Tue May 29 01:39:41 2012
@@ -44,6 +44,7 @@
 #include "private/svn_fs_util.h"
 #include "private/svn_utf_private.h"
 #include "private/svn_mutex.h"
+#include "private/svn_subr_private.h"
 
 #include "fs-loader.h"
 #include "svn_hash.h"
@@ -336,6 +337,7 @@ fs_new(apr_hash_t *fs_config, apr_pool_t
   fs->access_ctx = NULL;
   fs->vtable = NULL;
   fs->fsap_data = NULL;
+  fs->uuid = NULL;
   return fs;
 }
 
@@ -645,6 +647,7 @@ svn_error_t *
 svn_fs_commit_txn(const char **conflict_p, svn_revnum_t *new_rev,
                   svn_fs_txn_t *txn, apr_pool_t *pool)
 {
+  svn_error_t *err;
 #ifdef PACK_AFTER_EVERY_COMMIT
   svn_fs_root_t *txn_root;
   svn_fs_t *fs;
@@ -656,11 +659,25 @@ svn_fs_commit_txn(const char **conflict_
   fs_path = svn_fs_path(fs, pool);
 #endif
 
-  SVN_ERR(txn->vtable->commit(conflict_p, new_rev, txn, pool));
+  err = txn->vtable->commit(conflict_p, new_rev, txn, pool);
+
+#ifdef SVN_DEBUG
+  /* Check postconditions. */
+  if (conflict_p)
+    {
+      SVN_ERR_ASSERT_E(! (SVN_IS_VALID_REVNUM(*new_rev) && *conflict_p != NULL),
+                       err);
+      SVN_ERR_ASSERT_E((*conflict_p != NULL)
+                       == (err && err->apr_err == SVN_ERR_FS_CONFLICT),
+                       err);
+    }
+#endif
+
+  SVN_ERR(err);
 
 #ifdef PACK_AFTER_EVERY_COMMIT
   {
-    svn_error_t *err = svn_fs_pack(fs_path, NULL, NULL, NULL, NULL, pool);
+    err = svn_fs_pack(fs_path, NULL, NULL, NULL, NULL, pool);
     if (err && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
       /* Pre-1.6 filesystem. */
       svn_error_clear(err);
@@ -1218,7 +1235,9 @@ svn_fs_get_file_delta_stream(svn_txdelta
 svn_error_t *
 svn_fs_get_uuid(svn_fs_t *fs, const char **uuid, apr_pool_t *pool)
 {
-  return svn_error_trace(fs->vtable->get_uuid(fs, uuid, pool));
+  /* If you change this, consider changing svn_fs__identifier(). */
+  *uuid = apr_pstrdup(pool, fs->uuid);
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.h?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs/fs-loader.h Tue May 29 01:39:41 2012
@@ -172,7 +172,7 @@ typedef struct fs_vtable_t
                                   const svn_string_t *const *old_value_p,
                                   const svn_string_t *value,
                                   apr_pool_t *pool);
-  svn_error_t *(*get_uuid)(svn_fs_t *fs, const char **uuid, apr_pool_t *pool);
+  /* There is no get_uuid(); see svn_fs_t.uuid docstring. */
   svn_error_t *(*set_uuid)(svn_fs_t *fs, const char *uuid, apr_pool_t *pool);
   svn_error_t *(*revision_root)(svn_fs_root_t **root_p, svn_fs_t *fs,
                                 svn_revnum_t rev, apr_pool_t *pool);
@@ -391,6 +391,9 @@ struct svn_fs_t
   /* FSAP-specific vtable and private data */
   fs_vtable_t *vtable;
   void *fsap_data;
+
+  /* UUID, stored by open(), create(), and set_uuid(). */
+  const char *uuid;
 };
 
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/bdb/lock-tokens-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/bdb/lock-tokens-table.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/bdb/lock-tokens-table.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/bdb/lock-tokens-table.c Tue May 29 01:39:41 2012
@@ -104,7 +104,7 @@ svn_fs_bdb__lock_token_delete(svn_fs_t *
   svn_fs_base__trail_debug(trail, "lock-tokens", "del");
   db_err = bfd->lock_tokens->del(bfd->lock_tokens, trail->db_txn, &key, 0);
   if (db_err == DB_NOTFOUND)
-    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path, pool);
+    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path);
   return BDB_WRAP(fs, "deleting entry from 'lock-tokens' table", db_err);
 }
 
@@ -131,7 +131,7 @@ svn_fs_bdb__lock_token_get(const char **
   svn_fs_base__track_dbt(&value, pool);
 
   if (db_err == DB_NOTFOUND)
-    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path, pool);
+    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path);
   SVN_ERR(BDB_WRAP(fs, "reading lock token", db_err));
 
   lock_token = apr_pstrmemdup(pool, value.data, value.size);

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/bdb/locks-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/bdb/locks-table.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/bdb/locks-table.c Tue May 29 01:39:41 2012
@@ -153,7 +153,7 @@ svn_fs_bdb__lock_get(svn_lock_t **lock_p
   if (lock->expiration_date && (apr_time_now() > lock->expiration_date))
     {
       SVN_ERR(svn_fs_bdb__lock_delete(fs, lock_token, trail, pool));
-      return SVN_FS__ERR_LOCK_EXPIRED(fs, lock_token, pool);
+      return SVN_FS__ERR_LOCK_EXPIRED(fs, lock_token);
     }
 
   *lock_p = lock;

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/err.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/err.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/err.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/err.c Tue May 29 01:39:41 2012
@@ -62,10 +62,11 @@ svn_fs_base__err_dangling_id(svn_fs_t *f
 svn_error_t *
 svn_fs_base__err_dangling_rev(svn_fs_t *fs, svn_revnum_t rev)
 {
+  /* Log the UUID as this error may be reported to the client. */
   return svn_error_createf
     (SVN_ERR_FS_NO_SUCH_REVISION, 0,
      _("No such revision %ld in filesystem '%s'"),
-     rev, fs->path);
+     rev, fs->uuid);
 }
 
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/fs.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/fs.c Tue May 29 01:39:41 2012
@@ -473,15 +473,6 @@ bdb_write_config(svn_fs_t *fs)
 
 
 
-static svn_error_t *
-base_serialized_init(svn_fs_t *fs, apr_pool_t *common_pool, apr_pool_t *pool)
-{
-  /* Nothing to do here. */
-  return SVN_NO_ERROR;
-}
-
-
-
 /* Creating a new filesystem */
 
 static fs_vtable_t fs_vtable = {
@@ -489,7 +480,6 @@ static fs_vtable_t fs_vtable = {
   svn_fs_base__revision_prop,
   svn_fs_base__revision_proplist,
   svn_fs_base__change_rev_prop,
-  svn_fs_base__get_uuid,
   svn_fs_base__set_uuid,
   svn_fs_base__revision_root,
   svn_fs_base__begin_txn,
@@ -656,6 +646,15 @@ open_databases(svn_fs_t *fs,
 }
 
 
+/* Called by functions that initialize an svn_fs_t struct, after that 
+   initialization is done, to populate svn_fs_t->uuid. */
+static svn_error_t *
+populate_opened_fs(svn_fs_t *fs, apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_fs_base__populate_uuid(fs, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 base_create(svn_fs_t *fs, const char *path, apr_pool_t *pool,
             apr_pool_t *common_pool)
@@ -691,7 +690,9 @@ base_create(svn_fs_t *fs, const char *pa
   if (svn_err) goto error;
 
   ((base_fs_data_t *) fs->fsap_data)->format = format;
-  return base_serialized_init(fs, common_pool, pool);
+
+  SVN_ERR(populate_opened_fs(fs, pool));
+  return SVN_NO_ERROR;;
 
 error:
   svn_error_clear(cleanup_fs(fs));
@@ -775,7 +776,8 @@ base_open(svn_fs_t *fs, const char *path
       if (svn_err) goto error;
     }
 
-  return base_serialized_init(fs, common_pool, pool);
+  SVN_ERR(populate_opened_fs(fs, pool));
+  return SVN_NO_ERROR;
 
  error:
   svn_error_clear(cleanup_fs(fs));

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/fs.h?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/fs.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/fs.h Tue May 29 01:39:41 2012
@@ -108,9 +108,6 @@ typedef struct base_fs_data_t
      transaction trail alive. */
   svn_boolean_t in_txn_trail;
 
-  /* The filesystem UUID (or NULL if not-yet-known; see svn_fs_get_uuid). */
-  const char *uuid;
-
   /* The format number of this FS. */
   int format;
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/lock.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/lock.c Tue May 29 01:39:41 2012
@@ -93,7 +93,7 @@ txn_body_lock(void *baton, trail_t *trai
   /* Until we implement directory locks someday, we only allow locks
      on files or non-existent paths. */
   if (kind == svn_node_dir)
-    return SVN_FS__ERR_NOT_FILE(trail->fs, args->path, trail->pool);
+    return SVN_FS__ERR_NOT_FILE(trail->fs, args->path);
 
   /* While our locking implementation easily supports the locking of
      nonexistent paths, we deliberately choose not to allow such madness. */
@@ -113,7 +113,7 @@ txn_body_lock(void *baton, trail_t *trai
 
   /* There better be a username attached to the fs. */
   if (!trail->fs->access_ctx || !trail->fs->access_ctx->username)
-    return SVN_FS__ERR_NO_USER(trail->fs, trail->pool);
+    return SVN_FS__ERR_NO_USER(trail->fs);
 
   /* Is the caller attempting to lock an out-of-date working file? */
   if (SVN_IS_VALID_REVNUM(args->current_rev))
@@ -179,8 +179,7 @@ txn_body_lock(void *baton, trail_t *trai
         {
           /* Sorry, the path is already locked. */
           return SVN_FS__ERR_PATH_ALREADY_LOCKED(trail->fs,
-                                                 existing_lock,
-                                                 trail->pool);
+                                                 existing_lock);
         }
       else
         {
@@ -282,22 +281,21 @@ txn_body_unlock(void *baton, trail_t *tr
       if (args->token == NULL)
         return svn_fs_base__err_no_lock_token(trail->fs, args->path);
       else if (strcmp(lock_token, args->token) != 0)
-        return SVN_FS__ERR_NO_SUCH_LOCK(trail->fs, args->path, trail->pool);
+        return SVN_FS__ERR_NO_SUCH_LOCK(trail->fs, args->path);
 
       SVN_ERR(svn_fs_bdb__lock_get(&lock, trail->fs, lock_token,
                                    trail, trail->pool));
 
       /* There better be a username attached to the fs. */
       if (!trail->fs->access_ctx || !trail->fs->access_ctx->username)
-        return SVN_FS__ERR_NO_USER(trail->fs, trail->pool);
+        return SVN_FS__ERR_NO_USER(trail->fs);
 
       /* And that username better be the same as the lock's owner. */
       if (strcmp(trail->fs->access_ctx->username, lock->owner) != 0)
         return SVN_FS__ERR_LOCK_OWNER_MISMATCH(
            trail->fs,
            trail->fs->access_ctx->username,
-           lock->owner,
-           trail->pool);
+           lock->owner);
     }
 
   /* Remove a row from each of the locking tables. */

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/tree.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/tree.c Tue May 29 01:39:41 2012
@@ -431,7 +431,7 @@ mutable_root_node(dag_node_t **node_p,
                                        trail, pool);
   else
     /* If it's not a transaction root, we can't change its contents.  */
-    return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path, pool);
+    return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path);
 }
 
 
@@ -769,7 +769,7 @@ open_path(parent_path_t **parent_path_p,
 
       /* The path isn't finished yet; we'd better be in a directory.  */
       if (svn_fs_base__dag_node_kind(child) != svn_node_dir)
-        SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far, pool),
+        SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far),
                   apr_psprintf(pool, _("Failure opening '%s'"), path));
 
       rest = next;
@@ -2926,7 +2926,7 @@ txn_body_make_dir(void *baton,
   /* If there's already a sub-directory by that name, complain.  This
      also catches the case of trying to make a subdirectory named `/'.  */
   if (parent_path->node)
-    return SVN_FS__ALREADY_EXISTS(root, path, trail->pool);
+    return SVN_FS__ALREADY_EXISTS(root, path);
 
   /* Check to see if some lock is 'reserving' a file-path or dir-path
      at that location, or even some child-path;  if so, check that we
@@ -3192,17 +3192,7 @@ fs_same_p(svn_boolean_t *same_p,
           svn_fs_t *fs2,
           apr_pool_t *pool)
 {
-  const char *uuid1;
-  const char *uuid2;
-
-  /* Random thought: if fetching UUIDs to compare filesystems is too
-     expensive, one solution would be to cache the UUID in each fs
-     object (copying the UUID into fs->pool, of course). */
-
-  SVN_ERR(fs1->vtable->get_uuid(fs1, &uuid1, pool));
-  SVN_ERR(fs2->vtable->get_uuid(fs2, &uuid2, pool));
-
-  *same_p = ! strcmp(uuid1, uuid2);
+  *same_p = ! strcmp(fs1->uuid, fs2->uuid);
   return SVN_NO_ERROR;
 }
 
@@ -3379,7 +3369,7 @@ txn_body_make_file(void *baton,
   /* If there's already a file by that name, complain.
      This also catches the case of trying to make a file named `/'.  */
   if (parent_path->node)
-    return SVN_FS__ALREADY_EXISTS(root, path, trail->pool);
+    return SVN_FS__ALREADY_EXISTS(root, path);
 
   /* Check to see if some lock is 'reserving' a file-path or dir-path
      at that location, or even some child-path;  if so, check that we

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/uuid.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/uuid.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/uuid.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/uuid.c Tue May 29 01:39:41 2012
@@ -48,39 +48,27 @@ txn_body_get_uuid(void *baton, trail_t *
 
 
 svn_error_t *
-svn_fs_base__get_uuid(svn_fs_t *fs,
-                      const char **uuid,
-                      apr_pool_t *pool)
+svn_fs_base__populate_uuid(svn_fs_t *fs,
+                           apr_pool_t *scratch_pool)
 {
-  base_fs_data_t *bfd = fs->fsap_data;
 
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
-  /* Check for a cached UUID first.  Failing that, we hit the
-     database. */
-  if (bfd->uuid)
-    {
-      *uuid = apr_pstrdup(pool, bfd->uuid);
-    }
-  else
+  /* We hit the database. */
     {
+      const char *uuid;
       struct get_uuid_args args;
-      apr_pool_t *scratch_pool = svn_pool_create(pool);
 
       args.idx = 1;
-      args.uuid = uuid;
+      args.uuid = &uuid;
       SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_get_uuid, &args,
                                      FALSE, scratch_pool));
 
-      if (*uuid)
+      if (uuid)
         {
-          *uuid = apr_pstrdup(pool, *uuid);
-
           /* Toss what we find into the cache. */
-          bfd->uuid = apr_pstrdup(fs->pool, *uuid);
+          fs->uuid = apr_pstrdup(fs->pool, uuid);
         }
-
-      svn_pool_destroy(scratch_pool);
     }
 
   return SVN_NO_ERROR;
@@ -109,7 +97,6 @@ svn_fs_base__set_uuid(svn_fs_t *fs,
                       apr_pool_t *pool)
 {
   struct set_uuid_args args;
-  base_fs_data_t *bfd = fs->fsap_data;
 
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
@@ -122,7 +109,7 @@ svn_fs_base__set_uuid(svn_fs_t *fs,
 
   /* Toss our value into the cache. */
   if (uuid)
-    bfd->uuid = apr_pstrdup(fs->pool, uuid);
+    fs->uuid = apr_pstrdup(fs->pool, uuid);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_base/uuid.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_base/uuid.h?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_base/uuid.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_base/uuid.h Tue May 29 01:39:41 2012
@@ -29,12 +29,15 @@ extern "C" {
 
 
 
+/* Set FS->UUID to the the value read from the database, allocated
+   in FS->POOL.  Use SCRATCH_POOL for temporary allocations. */
+svn_error_t *svn_fs_base__populate_uuid(svn_fs_t *fs,
+                                        apr_pool_t *scratch_pool);
+
+
 /* These functions implement some of the calls in the FS loader
    library's fs vtable. */
 
-svn_error_t *svn_fs_base__get_uuid(svn_fs_t *fs, const char **uuid,
-                                   apr_pool_t *pool);
-
 svn_error_t *svn_fs_base__set_uuid(svn_fs_t *fs, const char *uuid,
                                    apr_pool_t *pool);
 

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/caching.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/caching.c Tue May 29 01:39:41 2012
@@ -33,6 +33,7 @@
 #include "svn_private_config.h"
 #include "svn_hash.h"
 #include "private/svn_debug.h"
+#include "private/svn_subr_private.h"
 
 /* Return a memcache in *MEMCACHE_P for FS if it's configured to use
    memcached, or NULL otherwise.  Also, sets *FAIL_STOP to a boolean
@@ -252,7 +253,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   const char *prefix = apr_pstrcat(pool,
-                                   "fsfs:", ffd->uuid,
+                                   "fsfs:", fs->uuid,
                                    "/", fs->path, ":",
                                    (char *)NULL);
   svn_memcache_t *memcache;
@@ -495,7 +496,7 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
      to start a new transaction later that receives the same id.
      Therefore, throw in a uuid as well - just to be sure. */
   const char *prefix = apr_pstrcat(pool,
-                                   "fsfs:", ffd->uuid,
+                                   "fsfs:", fs->uuid,
                                    "/", fs->path,
                                    ":", txn_id,
                                    ":", svn_uuid_generate(pool), ":",

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/dag.c Tue May 29 01:39:41 2012
@@ -778,11 +778,9 @@ svn_fs_fs__dag_delete(dag_node_t *parent
 
   subpool = svn_pool_create(pool);
 
-  /* Get a dirent hash for this directory. */
-  SVN_ERR(svn_fs_fs__rep_contents_dir(&entries, fs, parent_noderev, subpool));
-
-  /* Find name in the ENTRIES hash. */
-  dirent = apr_hash_get(entries, name, APR_HASH_KEY_STRING);
+  /* Search this directory for a dirent with that NAME. */
+  SVN_ERR(svn_fs_fs__rep_contents_dir_entry(&dirent, fs, parent_noderev,
+                                            name, subpool, subpool));
 
   /* If we never found ID in ENTRIES (perhaps because there are no
      ENTRIES, perhaps because ID just isn't in the existing ENTRIES

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.c Tue May 29 01:39:41 2012
@@ -73,7 +73,8 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
      know of a better way of associating such data with the
      repository. */
 
-  key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX, ffd->uuid,
+  SVN_ERR_ASSERT(fs->uuid);
+  key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX, fs->uuid,
                     (char *) NULL);
   status = apr_pool_userdata_get(&val, key, common_pool);
   if (status)
@@ -130,7 +131,6 @@ static fs_vtable_t fs_vtable = {
   svn_fs_fs__revision_prop,
   svn_fs_fs__revision_proplist,
   svn_fs_fs__change_rev_prop,
-  svn_fs_fs__get_uuid,
   svn_fs_fs__set_uuid,
   svn_fs_fs__revision_root,
   svn_fs_fs__begin_txn,
@@ -294,10 +294,18 @@ fs_hotcopy(svn_fs_t *src_fs,
            void *cancel_baton,
            apr_pool_t *pool)
 {
+  SVN_ERR(svn_fs__check_fs(src_fs, FALSE));
   SVN_ERR(initialize_fs_struct(src_fs));
+  SVN_ERR(svn_fs_fs__open(src_fs, src_path, pool));
+  SVN_ERR(svn_fs_fs__initialize_caches(src_fs, pool));
   SVN_ERR(fs_serialized_init(src_fs, pool, pool));
+
+  SVN_ERR(svn_fs__check_fs(dst_fs, FALSE));
   SVN_ERR(initialize_fs_struct(dst_fs));
-  SVN_ERR(fs_serialized_init(dst_fs, pool, pool));
+  /* In INCREMENTAL mode, svn_fs_fs__hotcopy() will open DST_FS.
+     Otherwise, it's not an FS yet --- possibly just an empty dir --- so
+     can't be opened.
+   */
   return svn_fs_fs__hotcopy(src_fs, dst_fs, src_path, dst_path,
                             incremental, cancel_func, cancel_baton, pool);
 }

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.h?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs.h Tue May 29 01:39:41 2012
@@ -61,6 +61,8 @@ extern "C" {
 #define PATH_LOCKS_DIR        "locks"            /* Directory of locks */
 #define PATH_MIN_UNPACKED_REV "min-unpacked-rev" /* Oldest revision which
                                                     has not been packed. */
+#define PATH_REVPROP_GENERATION "revprop-generation"
+                                                 /* Current revprop generation*/
 /* If you change this, look at tests/svn_test_fs.c(maybe_install_fsfs_conf) */
 #define PATH_CONFIG           "fsfs.conf"        /* Configuration */
 
@@ -218,9 +220,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/javahl-ra/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs_fs.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs_fs.c Tue May 29 01:39:41 2012
@@ -59,7 +59,9 @@
 #include "rep-cache.h"
 #include "temp_serializer.h"
 
+#include "private/svn_string_private.h"
 #include "private/svn_fs_util.h"
+#include "private/svn_subr_private.h"
 #include "../libsvn_fs/fs-loader.h"
 
 #include "svn_private_config.h"
@@ -236,6 +238,12 @@ path_lock(svn_fs_t *fs, apr_pool_t *pool
 }
 
 static const char *
+path_revprop_generation(svn_fs_t *fs, apr_pool_t *pool)
+{
+  return svn_dirent_join(fs->path, PATH_REVPROP_GENERATION, pool);
+}
+
+static const char *
 path_rev_packed(svn_fs_t *fs, svn_revnum_t rev, const char *kind,
                 apr_pool_t *pool)
 {
@@ -1307,7 +1315,7 @@ svn_fs_fs__open(svn_fs_t *fs, const char
 
   limit = sizeof(buf);
   SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit, pool));
-  ffd->uuid = apr_pstrdup(fs->pool, buf);
+  fs->uuid = apr_pstrdup(fs->pool, buf);
 
   SVN_ERR(svn_io_file_close(uuid_file, pool));
 
@@ -2384,7 +2392,7 @@ svn_fs_fs__write_noderev(svn_stream_t *o
                               noderev->copyroot_path));
 
   if (noderev->is_fresh_txn_root)
-    SVN_ERR(svn_stream_printf(outfile, pool, HEADER_FRESHTXNRT ": y\n"));
+    SVN_ERR(svn_stream_puts(outfile, HEADER_FRESHTXNRT ": y\n"));
 
   if (include_mergeinfo)
     {
@@ -2394,10 +2402,10 @@ svn_fs_fs__write_noderev(svn_stream_t *o
                                   noderev->mergeinfo_count));
 
       if (noderev->has_mergeinfo)
-        SVN_ERR(svn_stream_printf(outfile, pool, HEADER_MINFO_HERE ": y\n"));
+        SVN_ERR(svn_stream_puts(outfile, HEADER_MINFO_HERE ": y\n"));
     }
 
-  return svn_stream_printf(outfile, pool, "\n");
+  return svn_stream_puts(outfile, "\n");
 }
 
 svn_error_t *
@@ -2800,6 +2808,95 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
   return SVN_NO_ERROR;
 }
 
+/* Revprop caching management.
+ *
+ * Revprop caching needs to be activated and will be deactivated for the
+ * respective FS instance if the necessary infrastructure could not be
+ * initialized.  In deactivated mode, there is almost no runtime overhead
+ * associated with revprop caching.  As long as no revprops are being read
+ * or changed, revprop caching imposes no overhead.
+ *
+ * When activated, we cache revprops using (revision, generation) pairs
+ * as keys with the generation being incremented upon every revprop change.
+ * Since the cache is process-local, the generation needs to be tracked
+ * for at least as long as the process lives but may be reset afterwards.
+ *
+ * To track the revprop generation, we use two-layer approach. On the lower
+ * level, we use named atomics to have a system-wide consistent value for
+ * the current revprop generation.  However, those named atomics will only
+ * remain valid for as long as at least one process / thread in the system
+ * accesses revprops in the respective repository.  The underlying shared
+ * memory gets cleaned up afterwards.
+ *
+ * On the second level, we will use a persistent file to track the latest
+ * revprop generation.  It will be written upon each revprop change but
+ * only be read if we are the first process to initialize the named atomics
+ * with that value.
+ *
+ * The overhead for the second and following accesses to revprops is
+ * almost zero on most systems.
+ */
+
+/* Read revprop generation as stored on disk for repository FS. The result
+ * is returned in *CURRENT. Default to 2 if no such file is available.
+ */
+static svn_error_t *
+read_revprop_generation_file(apr_int64_t *current,
+                             svn_fs_t *fs,
+                             apr_pool_t *pool)
+{
+  svn_error_t *err;
+  apr_file_t *file;
+  char buf[80];
+  apr_size_t len;
+  const char *path = path_revprop_generation(fs, pool);
+
+  err = svn_io_file_open(&file, path,
+                         APR_READ | APR_BUFFERED,
+                         APR_OS_DEFAULT, pool);
+  if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+    {
+      svn_error_clear(err);
+      *current = 2;
+
+      return SVN_NO_ERROR;
+    }
+  SVN_ERR(err);
+
+  len = sizeof(buf);
+  SVN_ERR(svn_io_read_length_line(file, buf, &len, pool));
+
+  /* Check that the first line contains only digits. */
+  SVN_ERR(check_file_buffer_numeric(buf, 0, path,
+                                    "Revprop Generation", pool));
+  SVN_ERR(svn_cstring_atoi64(current, buf));
+
+  return svn_io_file_close(file, pool);
+}
+
+/* Write the CURRENT revprop generation to disk for repository FS.
+ */
+static svn_error_t *
+write_revprop_generation_file(svn_fs_t *fs,
+                              apr_int64_t current,
+                              apr_pool_t *pool)
+{
+  apr_file_t *file;
+  const char *tmp_path;
+
+  char buf[SVN_INT64_BUFFER_SIZE];
+  apr_size_t len = svn__i64toa(buf, current);
+  buf[len] = '\n';
+
+  SVN_ERR(svn_io_open_unique_file3(&file, &tmp_path, fs->path,
+                                   svn_io_file_del_none, pool, pool));
+  SVN_ERR(svn_io_file_write_full(file, buf, len + 1, NULL, pool));
+  SVN_ERR(svn_io_file_close(file, pool));
+
+  return move_into_place(tmp_path, path_revprop_generation(fs, pool),
+                         tmp_path, pool);
+}
+
 /* Make sure the revprop_namespace member in FS is set. */
 static svn_error_t *
 ensure_revprop_namespace(svn_fs_t *fs)
@@ -2815,19 +2912,39 @@ ensure_revprop_namespace(svn_fs_t *fs)
     : SVN_NO_ERROR;
 }
 
-/* Make sure the revprop_generation member in FS is set. */
+/* Make sure the revprop_generation member in FS is set and, if necessary,
+ * initialized with the latest value stored on disk.
+ */
 static svn_error_t *
-ensure_revprop_generation(svn_fs_t *fs)
+ensure_revprop_generation(svn_fs_t *fs, apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
 
   SVN_ERR(ensure_revprop_namespace(fs));
-  return ffd->revprop_generation == NULL
-    ? svn_named_atomic__get(&ffd->revprop_generation,
-                            ffd->revprop_namespace,
-                            ATOMIC_REVPROP_GENERATION,
-                            TRUE)
-    : SVN_NO_ERROR;
+  if (ffd->revprop_generation == NULL)
+    {
+      apr_int64_t current = 0;
+      
+      SVN_ERR(svn_named_atomic__get(&ffd->revprop_generation,
+                                    ffd->revprop_namespace,
+                                    ATOMIC_REVPROP_GENERATION,
+                                    TRUE));
+
+      /* If the generation is at 0, we just created a new namespace
+       * (it would be at least 2 otherwise). Read the lastest generation
+       * from disk and if we are the first one to initialize the atomic
+       * (i.e. is still 0), set it to the value just gotten.
+       */
+      SVN_ERR(svn_named_atomic__read(&current, ffd->revprop_generation));
+      if (current == 0)
+        {
+          SVN_ERR(read_revprop_generation_file(&current, fs, pool));
+          SVN_ERR(svn_named_atomic__cmpxchg(NULL, current, 0,
+                                            ffd->revprop_generation));
+        }
+    }
+
+  return SVN_NO_ERROR;
 }
 
 /* Make sure the revprop_timeout member in FS is set. */
@@ -2848,7 +2965,7 @@ ensure_revprop_timeout(svn_fs_t *fs)
 /* Test whether revprop cache and necessary infrastructure are
    available in FS. */
 static svn_boolean_t
-has_revprop_cache(svn_fs_t *fs)
+has_revprop_cache(svn_fs_t *fs, apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   svn_error_t *error;
@@ -2868,7 +2985,7 @@ has_revprop_cache(svn_fs_t *fs)
     }
 
   /* try to access our SHM-backed infrastructure */
-  error = ensure_revprop_generation(fs);
+  error = ensure_revprop_generation(fs, pool);
   if (error)
     {
       /* failure -> disable revprop cache for good */
@@ -2887,13 +3004,14 @@ has_revprop_cache(svn_fs_t *fs)
    Use the access object in FS to set the shared mem values. */
 static svn_error_t *
 read_revprop_generation(apr_int64_t *generation,
-                        svn_fs_t *fs)
+                        svn_fs_t *fs,
+                        apr_pool_t *pool)
 {
   apr_int64_t current = 0;
   fs_fs_data_t *ffd = fs->fsap_data;
 
   /* read the current revprop generation number */
-  SVN_ERR(ensure_revprop_generation(fs));
+  SVN_ERR(ensure_revprop_generation(fs, pool));
   SVN_ERR(svn_named_atomic__read(&current, ffd->revprop_generation));
 
   /* is an unfinished revprop write under the way? */
@@ -2930,7 +3048,7 @@ read_revprop_generation(apr_int64_t *gen
    readers shall recover from that state & re-read revprops.
    Use the access object in FS to set the shared mem value. */
 static svn_error_t *
-begin_revprop_change(svn_fs_t *fs)
+begin_revprop_change(svn_fs_t *fs, apr_pool_t *pool)
 {
   apr_int64_t current;
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -2944,7 +3062,7 @@ begin_revprop_change(svn_fs_t *fs)
   /* set the revprop generation to an odd value to indicate
    * that a write is in progress
    */
-  SVN_ERR(ensure_revprop_generation(fs));
+  SVN_ERR(ensure_revprop_generation(fs, pool));
   do
     {
       SVN_ERR(svn_named_atomic__add(&current,
@@ -2961,7 +3079,7 @@ begin_revprop_change(svn_fs_t *fs)
    b) the write process has been completed (no recovery required)
    Use the access object in FS to set the shared mem value. */
 static svn_error_t *
-end_revprop_change(svn_fs_t *fs)
+end_revprop_change(svn_fs_t *fs, apr_pool_t *pool)
 {
   apr_int64_t current = 1;
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -2969,7 +3087,7 @@ end_revprop_change(svn_fs_t *fs)
   /* set the revprop generation to an even value to indicate
    * that a write has been completed
    */
-  SVN_ERR(ensure_revprop_generation(fs));
+  SVN_ERR(ensure_revprop_generation(fs, pool));
   do
     {
       SVN_ERR(svn_named_atomic__add(&current,
@@ -2978,7 +3096,11 @@ end_revprop_change(svn_fs_t *fs)
     }
   while (current % 2);
 
-  return SVN_NO_ERROR;
+  /* Save the latest generation to disk. FS is currently in a "locked"
+   * state such that we can be sure the be the only ones to write that
+   * file.
+   */
+  return write_revprop_generation_file(fs, current, pool);
 }
 
 /* Set the revision property list of revision REV in filesystem FS to
@@ -3000,7 +3122,7 @@ set_revision_proplist(svn_fs_t *fs,
       svn_node_kind_t kind = svn_node_none;
 
       /* test whether revprops already exist for this revision */
-      if (has_revprop_cache(fs))
+      if (has_revprop_cache(fs, pool))
         SVN_ERR(svn_io_check_path(final_path, &kind, pool));
 
       /* ### do we have a directory sitting around already? we really shouldn't
@@ -3020,13 +3142,13 @@ set_revision_proplist(svn_fs_t *fs,
       /* Now, we may actually be replacing revprops. Make sure that all other
          threads and processes will know about this. */
       if (kind != svn_node_none)
-        SVN_ERR(begin_revprop_change(fs));
+        SVN_ERR(begin_revprop_change(fs, pool));
 
       SVN_ERR(move_into_place(tmp_path, final_path, perms_reference, pool));
 
       /* Indicate that the update (if relevant) has been completed. */
       if (kind != svn_node_none)
-        SVN_ERR(end_revprop_change(fs));
+        SVN_ERR(end_revprop_change(fs, pool));
     }
 
   return SVN_NO_ERROR;
@@ -3045,12 +3167,12 @@ revision_proplist(apr_hash_t **proplist_
   SVN_ERR(ensure_revision_exists(fs, rev, pool));
 
   /* Try cache lookup first. */
-  if (has_revprop_cache(fs))
+  if (has_revprop_cache(fs, pool))
     {
       apr_int64_t generation;
       svn_boolean_t is_cached;
 
-      SVN_ERR(read_revprop_generation(&generation, fs));
+      SVN_ERR(read_revprop_generation(&generation, fs, pool));
 
       key = svn_fs_fs__combine_two_numbers(rev, generation, pool);
       SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
@@ -3114,7 +3236,7 @@ revision_proplist(apr_hash_t **proplist_
     }
 
   /* Cache the result, if caching has been activated. */
-  if (has_revprop_cache(fs))
+  if (has_revprop_cache(fs, pool))
     SVN_ERR(svn_cache__set(ffd->revprop_cache, key, proplist, pool));
 
   *proplist_p = proplist;
@@ -4729,20 +4851,37 @@ fetch_all_changes(apr_hash_t *changed_pa
         {
           apr_hash_index_t *hi;
 
+          /* a potential child path must contain at least 2 more chars
+             (the path separator plus at least one char for the name).
+             Also, we should not assume that all paths have been normalized
+             i.e. some might have trailing path separators.
+          */
+          apr_ssize_t change_path_len = strlen(change->path);
+          apr_ssize_t min_child_len = change_path_len == 0
+                                    ? 1
+                                    : change->path[change_path_len-1] == '/'
+                                        ? change_path_len + 1
+                                        : change_path_len + 2;
+
+          /* CAUTION: This is the inner loop of an O(n^2) algorithm.
+             The number of changes to process may be >> 1000.
+             Therefore, keep the inner loop as tight as possible.
+          */
           for (hi = apr_hash_first(iterpool, changed_paths);
                hi;
                hi = apr_hash_next(hi))
             {
               /* KEY is the path. */
-              const char *path = svn__apr_hash_index_key(hi);
-              apr_ssize_t klen = svn__apr_hash_index_klen(hi);
-
-              /* If we come across our own path, ignore it. */
-              if (strcmp(change->path, path) == 0)
-                continue;
-
-              /* If we come across a child of our path, remove it. */
-              if (svn_dirent_is_child(change->path, path, iterpool))
+              const void *path;
+              apr_ssize_t klen;
+              apr_hash_this(hi, &path, &klen, NULL);
+
+              /* If we come across a child of our path, remove it.
+                 Call svn_dirent_is_child only if there is a chance that
+                 this is actually a sub-path.
+               */
+              if (   klen >= min_child_len
+                  && svn_dirent_is_child(change->path, path, iterpool))
                 apr_hash_set(changed_paths, path, klen, NULL);
             }
         }
@@ -5849,7 +5988,7 @@ rep_write_contents_close(void *baton)
   else
     {
       /* Write out our cosmetic end marker. */
-      SVN_ERR(svn_stream_printf(b->rep_stream, b->pool, "ENDREP\n"));
+      SVN_ERR(svn_stream_puts(b->rep_stream, "ENDREP\n"));
 
       b->noderev->data_rep = rep;
     }
@@ -6064,7 +6203,7 @@ write_hash_rep(representation_t *rep,
   stream = svn_stream_create(whb, pool);
   svn_stream_set_write(stream, write_hash_handler);
 
-  SVN_ERR(svn_stream_printf(whb->stream, pool, "PLAIN\n"));
+  SVN_ERR(svn_stream_puts(whb->stream, "PLAIN\n"));
 
   SVN_ERR(svn_hash_write2(hash, stream, SVN_HASH_TERMINATOR, pool));
 
@@ -6087,7 +6226,7 @@ write_hash_rep(representation_t *rep,
   else
     {
       /* Write out our cosmetic end marker. */
-      SVN_ERR(svn_stream_printf(whb->stream, pool, "ENDREP\n"));
+      SVN_ERR(svn_stream_puts(whb->stream, "ENDREP\n"));
 
       /* update the representation */
       rep->size = whb->size;
@@ -6195,7 +6334,7 @@ write_hash_delta_rep(representation_t *r
     {
       /* Write out our cosmetic end marker. */
       SVN_ERR(get_file_offset(&rep_end, file, pool));
-      SVN_ERR(svn_stream_printf(file_stream, pool, "ENDREP\n"));
+      SVN_ERR(svn_stream_puts(file_stream, "ENDREP\n"));
 
       /* update the representation */
       rep->expanded_size = whb->size;
@@ -7500,17 +7639,6 @@ svn_fs_fs__recover(svn_fs_t *fs,
 }
 
 svn_error_t *
-svn_fs_fs__get_uuid(svn_fs_t *fs,
-                    const char **uuid_p,
-                    apr_pool_t *pool)
-{
-  fs_fs_data_t *ffd = fs->fsap_data;
-
-  *uuid_p = apr_pstrdup(pool, ffd->uuid);
-  return SVN_NO_ERROR;
-}
-
-svn_error_t *
 svn_fs_fs__set_uuid(svn_fs_t *fs,
                     const char *uuid,
                     apr_pool_t *pool)
@@ -7519,7 +7647,6 @@ svn_fs_fs__set_uuid(svn_fs_t *fs,
   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);
@@ -7540,7 +7667,7 @@ svn_fs_fs__set_uuid(svn_fs_t *fs,
 
   /* Remove the newline we added, and stash the UUID. */
   my_uuid[my_uuid_len - 1] = '\0';
-  ffd->uuid = my_uuid;
+  fs->uuid = my_uuid;
 
   return SVN_NO_ERROR;
 }
@@ -8709,7 +8836,7 @@ hotcopy_incremental_check_preconditions(
 
   /* Make sure the UUID of source and destination match up.
    * We don't want to copy over a different repository. */
-  if (strcmp(src_ffd->uuid, dst_ffd->uuid) != 0)
+  if (strcmp(src_fs->uuid, dst_fs->uuid) != 0)
     return svn_error_create(SVN_ERR_RA_UUID_MISMATCH, NULL,
                             _("The UUID of the hotcopy source does "
                               "not match the UUID of the hotcopy "
@@ -9089,6 +9216,15 @@ hotcopy_body(void *baton, apr_pool_t *po
     SVN_ERR(svn_io_dir_file_copy(src_fs->path, dst_fs->path,
                                  PATH_TXN_CURRENT, pool));
 
+  /* If a revprop generation file exists in the source filesystem,
+   * force a fresh revprop caching namespace for the destination by
+   * setting the generation to zero. We have no idea if the revprops
+   * we copied above really belong to the currently cached generation. */
+  SVN_ERR(svn_io_check_path(path_revprop_generation(src_fs, pool),
+                            &kind, pool));
+  if (kind == svn_node_file)
+    SVN_ERR(write_revprop_generation_file(dst_fs, 0, pool));
+
   /* Hotcopied FS is complete. Stamp it with a format file. */
   SVN_ERR(write_format(svn_dirent_join(dst_fs->path, PATH_FORMAT, pool),
                        dst_ffd->format, max_files_per_dir, TRUE, pool));
@@ -9097,6 +9233,20 @@ hotcopy_body(void *baton, apr_pool_t *po
 }
 
 
+/* Set up shared data between SRC_FS and DST_FS. */
+static void
+hotcopy_setup_shared_fs_data(svn_fs_t *src_fs, svn_fs_t *dst_fs)
+{
+  fs_fs_data_t *src_ffd = src_fs->fsap_data;
+  fs_fs_data_t *dst_ffd = dst_fs->fsap_data;
+
+  /* The common pool and mutexes are shared between src and dst filesystems.
+   * During hotcopy we only grab the mutexes for the destination, so there
+   * is no risk of dead-lock. We don't write to the src filesystem. Shared
+   * data for the src_fs has already been initialised in fs_hotcopy(). */
+  dst_ffd->shared = src_ffd->shared;
+}
+
 /* Create an empty filesystem at DST_FS at DST_PATH with the same
  * configuration as SRC_FS (uuid, format, and other parameters).
  * After creation DST_FS has no revisions, not even revision zero. */
@@ -9155,7 +9305,7 @@ hotcopy_create_empty_dest(svn_fs_t *src_
 
   /* Create lock file and UUID. */
   SVN_ERR(svn_io_file_create(path_lock(dst_fs, pool), "", pool));
-  SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_ffd->uuid, pool));
+  SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_fs->uuid, pool));
 
   /* Create the min unpacked rev file. */
   if (dst_ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
@@ -9172,6 +9322,10 @@ hotcopy_create_empty_dest(svn_fs_t *src_
     }
 
   dst_ffd->youngest_rev_cache = 0;
+
+  hotcopy_setup_shared_fs_data(src_fs, dst_fs);
+  SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -9213,6 +9367,8 @@ svn_fs_fs__hotcopy(svn_fs_t *src_fs,
           SVN_ERR(svn_fs_fs__open(dst_fs, dst_path, pool));
           SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs,
                                                           pool));
+          hotcopy_setup_shared_fs_data(src_fs, dst_fs);
+          SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
         }
     }
   else

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs_fs.h?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/fs_fs.h Tue May 29 01:39:41 2012
@@ -131,8 +131,9 @@ svn_error_t *svn_fs_fs__rep_contents_dir
                                          apr_pool_t *pool);
 
 /* Set *DIRENT to the entry identified by NAME in the directory given
-   by NODEREV in filesystem FS.  The returned object is allocated in
-   RESULT_POOL; SCRATCH_POOL used for temporary allocations. */
+   by NODEREV in filesystem FS.  If no such entry exits, *DIRENT will
+   be NULL. The returned object is allocated in RESULT_POOL; SCRATCH_POOL
+   used for temporary allocations. */
 svn_error_t *
 svn_fs_fs__rep_contents_dir_entry(svn_fs_dirent_t **dirent,
                                   svn_fs_t *fs,
@@ -355,12 +356,6 @@ svn_error_t *svn_fs_fs__create(svn_fs_t 
                                const char *path,
                                apr_pool_t *pool);
 
-/* Store the uuid of the repository FS in *UUID.  Allocate space in
-   POOL. */
-svn_error_t *svn_fs_fs__get_uuid(svn_fs_t *fs,
-                                 const char **uuid,
-                                 apr_pool_t *pool);
-
 /* Set the uuid of repository FS to UUID, if UUID is not NULL;
    otherwise, set the uuid of FS to a newly generated UUID.  Perform
    temporary allocations in POOL. */

Modified: subversion/branches/javahl-ra/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_fs_fs/lock.c?rev=1343447&r1=1343446&r2=1343447&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_fs_fs/lock.c Tue May 29 01:39:41 2012
@@ -493,7 +493,7 @@ get_lock(svn_lock_t **lock_p,
 
   SVN_ERR(read_digest_file(NULL, &lock, fs->path, digest_path, pool));
   if (! lock)
-    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path, pool);
+    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path);
 
   /* Don't return an expired lock. */
   if (lock->expiration_date && (apr_time_now() > lock->expiration_date))
@@ -503,7 +503,7 @@ get_lock(svn_lock_t **lock_p,
       if (have_write_lock)
         SVN_ERR(delete_lock(fs, lock, pool));
       *lock_p = NULL;
-      return SVN_FS__ERR_LOCK_EXPIRED(fs, lock->token, pool);
+      return SVN_FS__ERR_LOCK_EXPIRED(fs, lock->token);
     }
 
   *lock_p = lock;
@@ -766,7 +766,7 @@ lock_body(void *baton, apr_pool_t *pool)
   SVN_ERR(lb->fs->vtable->revision_root(&root, lb->fs, youngest, pool));
   SVN_ERR(svn_fs_fs__check_path(&kind, root, lb->path, pool));
   if (kind == svn_node_dir)
-    return SVN_FS__ERR_NOT_FILE(lb->fs, lb->path, pool);
+    return SVN_FS__ERR_NOT_FILE(lb->fs, lb->path);
 
   /* While our locking implementation easily supports the locking of
      nonexistent paths, we deliberately choose not to allow such madness. */
@@ -786,7 +786,7 @@ lock_body(void *baton, apr_pool_t *pool)
 
   /* We need to have a username attached to the fs. */
   if (!lb->fs->access_ctx || !lb->fs->access_ctx->username)
-    return SVN_FS__ERR_NO_USER(lb->fs, pool);
+    return SVN_FS__ERR_NO_USER(lb->fs);
 
   /* Is the caller attempting to lock an out-of-date working file? */
   if (SVN_IS_VALID_REVNUM(lb->current_rev))
@@ -832,7 +832,7 @@ lock_body(void *baton, apr_pool_t *pool)
       if (! lb->steal_lock)
         {
           /* Sorry, the path is already locked. */
-          return SVN_FS__ERR_PATH_ALREADY_LOCKED(lb->fs, existing_lock, pool);
+          return SVN_FS__ERR_PATH_ALREADY_LOCKED(lb->fs, existing_lock);
         }
       else
         {
@@ -888,16 +888,16 @@ unlock_body(void *baton, apr_pool_t *poo
     {
       /* Sanity check:  the incoming token should match lock->token. */
       if (strcmp(ub->token, lock->token) != 0)
-        return SVN_FS__ERR_NO_SUCH_LOCK(ub->fs, lock->path, pool);
+        return SVN_FS__ERR_NO_SUCH_LOCK(ub->fs, lock->path);
 
       /* There better be a username attached to the fs. */
       if (! (ub->fs->access_ctx && ub->fs->access_ctx->username))
-        return SVN_FS__ERR_NO_USER(ub->fs, pool);
+        return SVN_FS__ERR_NO_USER(ub->fs);
 
       /* And that username better be the same as the lock's owner. */
       if (strcmp(ub->fs->access_ctx->username, lock->owner) != 0)
         return SVN_FS__ERR_LOCK_OWNER_MISMATCH(
-           ub->fs, ub->fs->access_ctx->username, lock->owner, pool);
+           ub->fs, ub->fs->access_ctx->username, lock->owner);
     }
 
   /* Remove lock and lock token files. */