subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1685464 [12/43] - in /subversion/branches/fsx-1.10: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/svncopy/ doc/ notes/ subversion/bindings/javahl/ subversion/bindings/javahl/native/ subversion/b...
Date Sun, 14 Jun 2015 20:58:16 GMT
Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.c Sun Jun 14 20:58:10 2015
@@ -371,7 +371,7 @@ set_lock(const char *fs_path,
   SVN_ERR(read_digest_file(&children, NULL, fs_path, digest_path,
                            scratch_pool));
 
-  SVN_ERR(write_digest_file(children, lock, fs_path, digest_path, 
+  SVN_ERR(write_digest_file(children, lock, fs_path, digest_path,
                             perms_reference, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -423,7 +423,7 @@ add_to_digest(const char *fs_path,
     }
 
   if (apr_hash_count(children) != original_count)
-    SVN_ERR(write_digest_file(children, lock, fs_path, index_digest_path, 
+    SVN_ERR(write_digest_file(children, lock, fs_path, index_digest_path,
                               perms_reference, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -458,7 +458,7 @@ delete_from_digest(const char *fs_path,
     }
 
   if (apr_hash_count(children) || lock)
-    SVN_ERR(write_digest_file(children, lock, fs_path, index_digest_path, 
+    SVN_ERR(write_digest_file(children, lock, fs_path, index_digest_path,
                               perms_reference, scratch_pool));
   else
     SVN_ERR(svn_io_remove_file2(index_digest_path, TRUE, scratch_pool));
@@ -471,6 +471,12 @@ unlock_single(svn_fs_t *fs,
               svn_lock_t *lock,
               apr_pool_t *pool);
 
+/* Check if LOCK has been already expired. */
+static svn_boolean_t lock_expired(const svn_lock_t *lock)
+{
+  return lock->expiration_date && (apr_time_now() > lock->expiration_date);
+}
+
 /* Set *LOCK_P to the lock for PATH in FS.  HAVE_WRITE_LOCK should be
    TRUE if the caller (or one of its callers) has taken out the
    repository-wide write lock, FALSE otherwise.  If MUST_EXIST is
@@ -500,7 +506,7 @@ get_lock(svn_lock_t **lock_p,
     return must_exist ? SVN_FS__ERR_NO_SUCH_LOCK(fs, path) : SVN_NO_ERROR;
 
   /* Don't return an expired lock. */
-  if (lock->expiration_date && (apr_time_now() > lock->expiration_date))
+  if (lock_expired(lock))
     {
       /* Only remove the lock if we have the write lock.
          Read operations shouldn't change the filesystem. */
@@ -547,68 +553,17 @@ get_lock_helper(svn_fs_t *fs,
 }
 
 
-/* Baton for locks_walker(). */
-typedef struct walk_locks_baton_t
-{
-  svn_fs_get_locks_callback_t get_locks_func;
-  void *get_locks_baton;
-  svn_fs_t *fs;
-} walk_locks_baton_t;
-
-/* Implements walk_digests_callback_t. */
-static svn_error_t *
-locks_walker(void *baton,
-             const char *fs_path,
-             const char *digest_path,
-             svn_lock_t *lock,
-             svn_boolean_t have_write_lock,
-             apr_pool_t *pool)
-{
-  walk_locks_baton_t *wlb = baton;
-
-  if (lock)
-    {
-      /* Don't report an expired lock. */
-      if (lock->expiration_date == 0
-          || (apr_time_now() <= lock->expiration_date))
-        {
-          if (wlb->get_locks_func)
-            SVN_ERR(wlb->get_locks_func(wlb->get_locks_baton, lock, pool));
-        }
-      else
-        {
-          /* Only remove the lock if we have the write lock.
-             Read operations shouldn't change the filesystem. */
-          if (have_write_lock)
-            SVN_ERR(unlock_single(wlb->fs, lock, pool));
-        }
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/* Callback type for walk_digest_files().
- *
- * LOCK come from a read_digest_file(digest_path) call.
- */
-typedef svn_error_t *(*walk_digests_callback_t)(void *baton,
-                                                const char *fs_path,
-                                                const char *digest_path,
-                                                svn_lock_t *lock,
-                                                svn_boolean_t have_write_lock,
-                                                apr_pool_t *pool);
-
-/* A function that calls WALK_DIGESTS_FUNC/WALK_DIGESTS_BATON for
-   all lock digest files in and under PATH in FS.
+/* A function that calls GET_LOCKS_FUNC/GET_LOCKS_BATON for
+   all locks in and under PATH in FS.
    HAVE_WRITE_LOCK should be true if the caller (directly or indirectly)
    has the FS write lock. */
 static svn_error_t *
-walk_digest_files(const char *fs_path,
-                  const char *digest_path,
-                  walk_digests_callback_t walk_digests_func,
-                  void *walk_digests_baton,
-                  svn_boolean_t have_write_lock,
-                  apr_pool_t *pool)
+walk_locks(svn_fs_t *fs,
+           const char *digest_path,
+           svn_fs_get_locks_callback_t get_locks_func,
+           void *get_locks_baton,
+           svn_boolean_t have_write_lock,
+           apr_pool_t *pool)
 {
   apr_hash_index_t *hi;
   apr_hash_t *children;
@@ -616,10 +571,19 @@ walk_digest_files(const char *fs_path,
   svn_lock_t *lock;
 
   /* First, send up any locks in the current digest file. */
-  SVN_ERR(read_digest_file(&children, &lock, fs_path, digest_path, pool));
+  SVN_ERR(read_digest_file(&children, &lock, fs->path, digest_path, pool));
 
-  SVN_ERR(walk_digests_func(walk_digests_baton, fs_path, digest_path, lock,
-                            have_write_lock, pool));
+  if (lock && lock_expired(lock))
+    {
+      /* Only remove the lock if we have the write lock.
+         Read operations shouldn't change the filesystem. */
+      if (have_write_lock)
+        SVN_ERR(unlock_single(fs, lock, pool));
+    }
+  else if (lock)
+    {
+      SVN_ERR(get_locks_func(get_locks_baton, lock, pool));
+    }
 
   /* Now, report all the child entries (if any; bail otherwise). */
   if (! apr_hash_count(children))
@@ -631,39 +595,25 @@ walk_digest_files(const char *fs_path,
       svn_pool_clear(subpool);
 
       SVN_ERR(read_digest_file
-              (NULL, &lock, fs_path,
-               digest_path_from_digest(fs_path, digest, subpool), subpool));
+              (NULL, &lock, fs->path,
+               digest_path_from_digest(fs->path, digest, subpool), subpool));
 
-      SVN_ERR(walk_digests_func(walk_digests_baton, fs_path, digest_path, lock,
-                                have_write_lock, subpool));
+      if (lock && lock_expired(lock))
+        {
+          /* Only remove the lock if we have the write lock.
+             Read operations shouldn't change the filesystem. */
+          if (have_write_lock)
+            SVN_ERR(unlock_single(fs, lock, pool));
+        }
+      else if (lock)
+        {
+          SVN_ERR(get_locks_func(get_locks_baton, lock, pool));
+        }
     }
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
 }
 
-/* A function that calls GET_LOCKS_FUNC/GET_LOCKS_BATON for
-   all locks in and under PATH in FS.
-   HAVE_WRITE_LOCK should be true if the caller (directly or indirectly)
-   has the FS write lock. */
-static svn_error_t *
-walk_locks(svn_fs_t *fs,
-           const char *digest_path,
-           svn_fs_get_locks_callback_t get_locks_func,
-           void *get_locks_baton,
-           svn_boolean_t have_write_lock,
-           apr_pool_t *pool)
-{
-  walk_locks_baton_t wlb;
-
-  wlb.get_locks_func = get_locks_func;
-  wlb.get_locks_baton = get_locks_baton;
-  wlb.fs = fs;
-  SVN_ERR(walk_digest_files(fs->path, digest_path, locks_walker, &wlb,
-                            have_write_lock, pool));
-  return SVN_NO_ERROR;
-}
-
-
 /* Utility function:  verify that a lock can be used.  Interesting
    errors returned from this function:
 
@@ -738,6 +688,35 @@ svn_fs_x__allow_locked_operation(const c
   return SVN_NO_ERROR;
 }
 
+/* Helper function called from the lock and unlock code.
+   UPDATES is a map from "const char *" parent paths to "apr_array_header_t *"
+   arrays of child paths.  For all of the parent paths of PATH this function
+   adds PATH to the corresponding array of child paths. */
+static void
+schedule_index_update(apr_hash_t *updates,
+                      const char *path,
+                      apr_pool_t *scratch_pool)
+{
+  apr_pool_t *hashpool = apr_hash_pool_get(updates);
+  const char *parent_path = path;
+
+  while (! svn_fspath__is_root(parent_path, strlen(parent_path)))
+    {
+      apr_array_header_t *children;
+
+      parent_path = svn_fspath__dirname(parent_path, scratch_pool);
+      children = svn_hash_gets(updates, parent_path);
+
+      if (! children)
+        {
+          children = apr_array_make(hashpool, 8, sizeof(const char *));
+          svn_hash_sets(updates, apr_pstrdup(hashpool, parent_path), children);
+        }
+
+      APR_ARRAY_PUSH(children, const char *) = path;
+    }
+}
+
 /* The effective arguments for lock_body() below. */
 typedef struct lock_baton_t {
   svn_fs_t *fs;
@@ -756,6 +735,7 @@ check_lock(svn_error_t **fs_err,
            const svn_fs_lock_target_t *target,
            lock_baton_t *lb,
            svn_fs_root_t *root,
+           svn_revnum_t youngest_rev,
            apr_pool_t *pool)
 {
   svn_node_kind_t kind;
@@ -792,6 +772,15 @@ check_lock(svn_error_t **fs_err,
   if (SVN_IS_VALID_REVNUM(target->current_rev))
     {
       svn_revnum_t created_rev;
+
+      if (target->current_rev > youngest_rev)
+        {
+          *fs_err = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+                                      _("No such revision %ld"),
+                                      target->current_rev);
+          return SVN_NO_ERROR;
+        }
+
       SVN_ERR(svn_fs_x__node_created_rev(&created_rev, root, path,
                                          pool));
 
@@ -850,7 +839,6 @@ check_lock(svn_error_t **fs_err,
 
 typedef struct lock_info_t {
   const char *path;
-  const char *component;
   svn_lock_t *lock;
   svn_error_t *fs_err;
 } lock_info_t;
@@ -874,12 +862,11 @@ lock_body(void *baton,
   svn_fs_root_t *root;
   svn_revnum_t youngest;
   const char *rev_0_path;
-  int i, outstanding = 0;
+  int i;
+  apr_hash_t *index_updates = apr_hash_make(pool);
+  apr_hash_index_t *hi;
   apr_pool_t *iterpool = svn_pool_create(pool);
 
-  lb->infos = apr_array_make(lb->result_pool, lb->targets->nelts,
-                             sizeof(lock_info_t));
-
   /* Until we implement directory locks someday, we only allow locks
      on files or non-existent paths. */
   /* Use fs->vtable->foo instead of svn_fs_foo to avoid circular
@@ -891,34 +878,28 @@ lock_body(void *baton,
     {
       const svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i,
                                                     svn_sort__item_t);
-      const svn_fs_lock_target_t *target = item->value;
       lock_info_t info;
 
       svn_pool_clear(iterpool);
 
       info.path = item->key;
-      SVN_ERR(check_lock(&info.fs_err, info.path, target, lb, root, iterpool));
       info.lock = NULL;
-      info.component = NULL;
-      APR_ARRAY_PUSH(lb->infos, lock_info_t) = info;
+      info.fs_err = SVN_NO_ERROR;
+
+      SVN_ERR(check_lock(&info.fs_err, info.path, item->value, lb, root,
+                         youngest, iterpool));
+
+      /* If no error occurred while pre-checking, schedule the index updates for
+         this path. */
       if (!info.fs_err)
-        ++outstanding;
+        schedule_index_update(index_updates, info.path, iterpool);
+
+      APR_ARRAY_PUSH(lb->infos, lock_info_t) = info;
     }
 
   rev_0_path = svn_fs_x__path_rev_absolute(lb->fs, 0, pool);
 
-  /* Given the paths:
-
-       /foo/bar/f
-       /foo/bar/g
-       /zig/x
-
-     we loop through repeatedly.  The first pass sees '/' on all paths
-     and writes the '/' index.  The second pass sees '/foo' twice and
-     writes that index followed by '/zig' and that index. The third
-     pass sees '/foo/bar' twice and writes that index, and then writes
-     the lock for '/zig/x'.  The fourth pass writes the locks for
-     '/foo/bar/f' and '/foo/bar/g'.
+  /* We apply the scheduled index updates before writing the actual locks.
 
      Writing indices before locks is correct: if interrupted it leaves
      indices without locks rather than locks without indices.  An
@@ -927,91 +908,49 @@ lock_body(void *baton,
      index is inconsistent, svn_fs_x__allow_locked_operation will
      show locked on the file but unlocked on the parent. */
 
-    
-  while (outstanding)
+  for (hi = apr_hash_first(pool, index_updates); hi; hi = apr_hash_next(hi))
+    {
+      const char *path = apr_hash_this_key(hi);
+      apr_array_header_t *children = apr_hash_this_val(hi);
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(add_to_digest(lb->fs->path, children, path, rev_0_path,
+                            iterpool));
+    }
+
+  for (i = 0; i < lb->infos->nelts; ++i)
     {
-      const char *last_path = NULL;
-      apr_array_header_t *paths;
+      struct lock_info_t *info = &APR_ARRAY_IDX(lb->infos, i,
+                                                struct lock_info_t);
+      svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, svn_sort__item_t);
+      svn_fs_lock_target_t *target = item->value;
 
       svn_pool_clear(iterpool);
-      paths = apr_array_make(iterpool, 1, sizeof(const char *));
 
-      for (i = 0; i < lb->infos->nelts; ++i)
+      if (! info->fs_err)
         {
-          lock_info_t *info = &APR_ARRAY_IDX(lb->infos, i, lock_info_t);
-          const svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i,
-                                                        svn_sort__item_t);
-          const svn_fs_lock_target_t *target = item->value;
-
-          if (!info->fs_err && !info->lock)
-            {
-              if (!info->component)
-                {
-                  info->component = info->path;
-                  APR_ARRAY_PUSH(paths, const char *) = info->path;
-                  last_path = "/";
-                }
-              else
-                {
-                  info->component = strchr(info->component + 1, '/');
-                  if (!info->component)
-                    {
-                      /* The component is a path to lock, this cannot
-                         match a previous path that need to be indexed. */
-                      if (paths->nelts)
-                        {
-                          SVN_ERR(add_to_digest(lb->fs->path, paths, last_path,
-                                                rev_0_path, iterpool));
-                          apr_array_clear(paths);
-                          last_path = NULL;
-                        }
-
-                      info->lock = svn_lock_create(lb->result_pool);
-                      if (target->token)
-                        info->lock->token = target->token;
-                      else
-                        SVN_ERR(svn_fs_x__generate_lock_token(
-                                  &(info->lock->token), lb->fs,
-                                  lb->result_pool));
-                      info->lock->path = info->path;
-                      info->lock->owner = lb->fs->access_ctx->username;
-                      info->lock->comment = lb->comment;
-                      info->lock->is_dav_comment = lb->is_dav_comment;
-                      info->lock->creation_date = apr_time_now();
-                      info->lock->expiration_date = lb->expiration_date;
-
-                      info->fs_err = set_lock(lb->fs->path, info->lock,
-                                              rev_0_path, iterpool);
-                      --outstanding;
-                    }
-                  else
-                    {
-                      /* The component is a path to an index. */
-                      apr_size_t len = info->component - info->path;
-
-                      if (last_path
-                          && (strncmp(last_path, info->path, len)
-                              || strlen(last_path) != len))
-                        {
-                          /* No match to the previous paths to index. */
-                          SVN_ERR(add_to_digest(lb->fs->path, paths, last_path,
-                                                rev_0_path, iterpool));
-                          apr_array_clear(paths);
-                          last_path = NULL;
-                        }
-                      APR_ARRAY_PUSH(paths, const char *) = info->path;
-                      if (!last_path)
-                        last_path = apr_pstrndup(iterpool, info->path, len);
-                    }
-                }
-            }
-
-          if (last_path && i == lb->infos->nelts - 1)
-            SVN_ERR(add_to_digest(lb->fs->path, paths, last_path,
-                                  rev_0_path, iterpool));
+          info->lock = svn_lock_create(lb->result_pool);
+          if (target->token)
+            info->lock->token = apr_pstrdup(lb->result_pool, target->token);
+          else
+            SVN_ERR(svn_fs_x__generate_lock_token(&(info->lock->token), lb->fs,
+                                                  lb->result_pool));
+
+          /* The INFO->PATH is already allocated in LB->RESULT_POOL as a result
+             of svn_fspath__canonicalize() (see svn_fs_fs__lock()). */
+          info->lock->path = info->path;
+          info->lock->owner = apr_pstrdup(lb->result_pool,
+                                          lb->fs->access_ctx->username);
+          info->lock->comment = apr_pstrdup(lb->result_pool, lb->comment);
+          info->lock->is_dav_comment = lb->is_dav_comment;
+          info->lock->creation_date = apr_time_now();
+          info->lock->expiration_date = lb->expiration_date;
+
+          info->fs_err = set_lock(lb->fs->path, info->lock, rev_0_path,
+                                  iterpool);
         }
     }
-      
+
   return SVN_NO_ERROR;
 }
 
@@ -1052,10 +991,8 @@ check_unlock(svn_error_t **fs_err,
 
 typedef struct unlock_info_t {
   const char *path;
-  const char *component;
   svn_error_t *fs_err;
   svn_boolean_t done;
-  int components;
 } unlock_info_t;
 
 /* The body of svn_fs_x__unlock(), which see.
@@ -1077,12 +1014,11 @@ unlock_body(void *baton,
   svn_fs_root_t *root;
   svn_revnum_t youngest;
   const char *rev_0_path;
-  int i, max_components = 0, outstanding = 0;
+  int i;
+  apr_hash_t *indices_updates = apr_hash_make(pool);
+  apr_hash_index_t *hi;
   apr_pool_t *iterpool = svn_pool_create(pool);
 
-  ub->infos = apr_array_make(ub->result_pool, ub->targets->nelts,
-                             sizeof( unlock_info_t));
-
   SVN_ERR(ub->fs->vtable->youngest_rev(&youngest, ub->fs, pool));
   SVN_ERR(ub->fs->vtable->revision_root(&root, ub->fs, youngest, pool));
 
@@ -1091,95 +1027,56 @@ unlock_body(void *baton,
       const svn_sort__item_t *item = &APR_ARRAY_IDX(ub->targets, i,
                                                     svn_sort__item_t);
       const char *token = item->value;
-      unlock_info_t info = { 0 };
+      unlock_info_t info;
 
       svn_pool_clear(iterpool);
 
       info.path = item->key;
+      info.fs_err = SVN_NO_ERROR;
+      info.done = FALSE;
+
       if (!ub->skip_check)
         SVN_ERR(check_unlock(&info.fs_err, info.path, token, ub, root,
                              iterpool));
-      if (!info.fs_err)
-        {
-          const char *s;
-
-          info.components = 1;
-          info.component = info.path;
-          while((s = strchr(info.component + 1, '/')))
-            {
-              info.component = s;
-              ++info.components;
-            }
 
-          if (info.components > max_components)
-            max_components = info.components;
+      /* If no error occurred while pre-checking, schedule the index updates for
+         this path. */
+      if (!info.fs_err)
+        schedule_index_update(indices_updates, info.path, iterpool);
 
-          ++outstanding;
-        }
       APR_ARRAY_PUSH(ub->infos, unlock_info_t) = info;
     }
 
   rev_0_path = svn_fs_x__path_rev_absolute(ub->fs, 0, pool);
 
-  for (i = max_components; i >= 0; --i)
+  /* Unlike the lock_body(), we need to delete locks *before* we start to
+     update indices. */
+
+  for (i = 0; i < ub->infos->nelts; ++i)
     {
-      const char *last_path = NULL;
-      apr_array_header_t *paths;
-      int j;
+      struct unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, i,
+                                                  struct unlock_info_t);
 
       svn_pool_clear(iterpool);
-      paths = apr_array_make(pool, 1, sizeof(const char *));
 
-      for (j = 0; j < ub->infos->nelts; ++j)
+      if (! info->fs_err)
         {
-          unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, j, unlock_info_t);
+          SVN_ERR(delete_lock(ub->fs->path, info->path, iterpool));
+          info->done = TRUE;
+        }
+    }
 
-          if (!info->fs_err && info->path)
-            {
+  for (hi = apr_hash_first(pool, indices_updates); hi; hi = apr_hash_next(hi))
+    {
+      const char *path = apr_hash_this_key(hi);
+      apr_array_header_t *children = apr_hash_this_val(hi);
 
-              if (info->components == i)
-                {
-                  SVN_ERR(delete_lock(ub->fs->path, info->path, iterpool));
-                  info->done = TRUE;
-                }
-              else if (info->components > i)
-                {
-                  apr_size_t len = info->component - info->path;
-
-                  if (last_path
-                      && strcmp(last_path, "/")
-                      && (strncmp(last_path, info->path, len)
-                          || strlen(last_path) != len))
-                    {
-                      SVN_ERR(delete_from_digest(ub->fs->path, paths, last_path,
-                                                 rev_0_path, iterpool));
-                      apr_array_clear(paths);
-                      last_path = NULL;
-                    }
-                  APR_ARRAY_PUSH(paths, const char *) = info->path;
-                  if (!last_path)
-                    {
-                      if (info->component > info->path)
-                        last_path = apr_pstrndup(pool, info->path, len);
-                      else
-                        last_path = "/";
-                    }
-
-                  if (info->component > info->path)
-                    {
-                      --info->component;
-                      while(info->component[0] != '/')
-                        --info->component;
-                    }
-                }
-            }
-
-          if (last_path && j == ub->infos->nelts - 1)
-            SVN_ERR(delete_from_digest(ub->fs->path, paths, last_path,
-                                       rev_0_path, iterpool));
-        }
+      svn_pool_clear(iterpool);
+      SVN_ERR(delete_from_digest(ub->fs->path, children, path, rev_0_path,
+                                 iterpool));
     }
 
+  svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
 
@@ -1203,6 +1100,8 @@ unlock_single(svn_fs_t *fs,
 
   ub.fs = fs;
   ub.targets = targets;
+  ub.infos = apr_array_make(scratch_pool, targets->nelts,
+                            sizeof(struct unlock_info_t));
   ub.skip_check = TRUE;
   ub.result_pool = scratch_pool;
 
@@ -1231,6 +1130,7 @@ svn_fs_x__lock(svn_fs_t *fs,
   apr_array_header_t *sorted_targets;
   apr_hash_t *canonical_targets = apr_hash_make(scratch_pool);
   apr_hash_index_t *hi;
+  apr_pool_t *iterpool;
   svn_error_t *err, *cb_err = SVN_NO_ERROR;
   int i;
 
@@ -1263,29 +1163,34 @@ svn_fs_x__lock(svn_fs_t *fs,
 
   lb.fs = fs;
   lb.targets = sorted_targets;
+  lb.infos = apr_array_make(scratch_pool, sorted_targets->nelts,
+                            sizeof(struct lock_info_t));
   lb.comment = comment;
   lb.is_dav_comment = is_dav_comment;
   lb.expiration_date = expiration_date;
   lb.steal_lock = steal_lock;
   lb.result_pool = result_pool;
 
-  err = svn_fs_x__with_write_lock(fs, lock_body, &lb, scratch_pool);
+  iterpool = svn_pool_create(scratch_pool);
+  err = svn_fs_x__with_write_lock(fs, lock_body, &lb, iterpool);
   for (i = 0; i < lb.infos->nelts; ++i)
     {
       struct lock_info_t *info = &APR_ARRAY_IDX(lb.infos, i,
                                                 struct lock_info_t);
+      svn_pool_clear(iterpool);
       if (!cb_err && lock_callback)
         {
           if (!info->lock && !info->fs_err)
             info->fs_err = svn_error_createf(SVN_ERR_FS_LOCK_OPERATION_FAILED,
                                              0, _("Failed to lock '%s'"),
                                              info->path);
-                                             
+
           cb_err = lock_callback(lock_baton, info->path, info->lock,
-                                 info->fs_err, scratch_pool);
+                                 info->fs_err, iterpool);
         }
       svn_error_clear(info->fs_err);
     }
+  svn_pool_destroy(iterpool);
 
   if (err && cb_err)
     svn_error_compose(err, cb_err);
@@ -1325,6 +1230,7 @@ svn_fs_x__unlock(svn_fs_t *fs,
   apr_array_header_t *sorted_targets;
   apr_hash_t *canonical_targets = apr_hash_make(scratch_pool);
   apr_hash_index_t *hi;
+  apr_pool_t *iterpool;
   svn_error_t *err, *cb_err = SVN_NO_ERROR;
   int i;
 
@@ -1353,14 +1259,18 @@ svn_fs_x__unlock(svn_fs_t *fs,
 
   ub.fs = fs;
   ub.targets = sorted_targets;
+  ub.infos = apr_array_make(scratch_pool, sorted_targets->nelts,
+                            sizeof(struct unlock_info_t));
   ub.skip_check = FALSE;
   ub.break_lock = break_lock;
   ub.result_pool = result_pool;
 
-  err = svn_fs_x__with_write_lock(fs, unlock_body, &ub, scratch_pool);
+  iterpool = svn_pool_create(scratch_pool);
+  err = svn_fs_x__with_write_lock(fs, unlock_body, &ub, iterpool);
   for (i = 0; i < ub.infos->nelts; ++i)
     {
       unlock_info_t *info = &APR_ARRAY_IDX(ub.infos, i, unlock_info_t);
+      svn_pool_clear(iterpool);
       if (!cb_err && lock_callback)
         {
           if (!info->done && !info->fs_err)
@@ -1368,10 +1278,11 @@ svn_fs_x__unlock(svn_fs_t *fs,
                                              0, _("Failed to unlock '%s'"),
                                              info->path);
           cb_err = lock_callback(lock_baton, info->path, NULL, info->fs_err,
-                                 scratch_pool);
+                                 iterpool);
         }
       svn_error_clear(info->fs_err);
     }
+  svn_pool_destroy(iterpool);
 
   if (err && cb_err)
     svn_error_compose(err, cb_err);

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/lock.h Sun Jun 14 20:58:10 2015
@@ -60,7 +60,7 @@ svn_fs_x__unlock(svn_fs_t *fs,
                  void *lock_baton,
                  apr_pool_t *result_pool,
                  apr_pool_t *scratch_pool);
-  
+
 /* See svn_fs_get_lock(). */
 svn_error_t *
 svn_fs_x__get_lock(svn_lock_t **lock,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.c Sun Jun 14 20:58:10 2015
@@ -587,7 +587,7 @@ format_digest(const unsigned char *diges
   svn_checksum_t checksum;
   checksum.digest = digest;
   checksum.kind = kind;
-  
+
   if (is_null)
     return "(null)";
 
@@ -753,7 +753,7 @@ svn_fs_x__write_rep_header(svn_fs_x__rep
                            apr_pool_t *scratch_pool)
 {
   const char *text;
-  
+
   switch (header->type)
     {
       case svn_fs_x__rep_self_delta:
@@ -999,7 +999,7 @@ svn_fs_x__read_changes_incrementally(svn
     }
   while (change);
   svn_pool_destroy(iterpool);
-  
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/low_level.h Sun Jun 14 20:58:10 2015
@@ -49,7 +49,7 @@ extern "C" {
  * and return the start offsets of the index data in *L2P_OFFSET and
  * *P2L_OFFSET, respectively.  Also, return the expected checksums in
  * in *L2P_CHECKSUM and *P2L_CHECKSUM.
- * 
+ *
  * Note that REV is only used to construct nicer error objects that
  * mention this revision.  Allocate the checksums in RESULT_POOL.
  */
@@ -160,7 +160,7 @@ svn_fs_x__read_rep_header(svn_fs_x__rep_
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool);
 
-/* Write the representation HEADER to STREAM. 
+/* Write the representation HEADER to STREAM.
  * Use SCRATCH_POOL for allocations. */
 svn_error_t *
 svn_fs_x__write_rep_header(svn_fs_x__rep_header_t *header,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/noderevs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/noderevs.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/noderevs.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/noderevs.c Sun Jun 14 20:58:10 2015
@@ -50,7 +50,7 @@
 #define NODEREV_HAS_CPATH    0x00040
 
 /* Our internal representation of a svn_fs_x__noderev_t.
- * 
+ *
  * We will store path strings in a string container and reference them
  * from here.  Similarly, IDs and representations are being stored in
  * separate containers and then also referenced here.  This eliminates
@@ -274,7 +274,7 @@ svn_fs_x__noderevs_add(svn_fs_x__noderev
                                            0);
 
   binary_noderev.mergeinfo_count = noderev->mergeinfo_count;
-  
+
   APR_ARRAY_PUSH(container->noderevs, binary_noderev_t) = binary_noderev;
 
   return container->noderevs->nelts - 1;
@@ -574,7 +574,7 @@ svn_fs_x__write_noderevs_container(svn_s
   /* write to disk */
   SVN_ERR(svn_fs_x__write_string_table(stream, paths, scratch_pool));
   SVN_ERR(svn_packed__data_write(stream, root, scratch_pool));
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -725,7 +725,7 @@ svn_fs_x__read_noderevs_container(svn_fs
     }
 
   *container = noderevs;
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -906,7 +906,7 @@ svn_fs_x__mergeinfo_count_get_func(void
   /* Resolve all container pointers */
   resolve_apr_array_header(&noderevs, container, &container->noderevs);
   binary_noderev = &APR_ARRAY_IDX(&noderevs, idx, binary_noderev_t);
-  
+
   *(apr_int64_t *)out = binary_noderev->mergeinfo_count;
 
   return SVN_NO_ERROR;

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.c Sun Jun 14 20:58:10 2015
@@ -70,7 +70,7 @@
  * each of the 4 buckets separately.  The first three will simply order
  * their items by revision, starting with the newest once.  Placing rep
  * and noderev items is a more elaborate process documented in the code.
- * 
+ *
  * In short, we store items in the following order:
  * - changed paths lists
  * - node property
@@ -269,7 +269,7 @@ initialize_pack_context(pack_context_t *
   context->start_rev = shard_rev;
   context->end_rev = shard_rev;
   context->shard_end_rev = shard_rev + ffd->max_files_per_dir;
-  
+
   /* Create the new directory and pack file. */
   context->shard_dir = shard_dir;
   context->pack_file_dir = pack_file_dir;
@@ -346,7 +346,7 @@ reset_pack_context(pack_context_t *conte
   SVN_ERR(svn_io_file_trunc(context->reps_file, 0, scratch_pool));
 
   svn_pool_clear(context->info_pool);
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -375,7 +375,7 @@ close_pack_context(pack_context_t *conte
   SVN_ERR(svn_fs_x__add_index_data(context->fs, context->pack_file,
                                     proto_l2p_index_path,
                                     proto_p2l_index_path,
-                                    context->shard_rev, 
+                                    context->shard_rev,
                                     scratch_pool));
 
   /* remove proto index files */
@@ -401,7 +401,7 @@ copy_file_data(pack_context_t *context,
   /* most non-representation items will be small.  Minimize the buffer
    * and infrastructure overhead in that case. */
   enum { STACK_BUFFER_SIZE = 1024 };
- 
+
   if (size < STACK_BUFFER_SIZE)
     {
       /* copy small data using a fixed-size buffer on stack */
@@ -630,13 +630,14 @@ compare_dir_entries(const svn_sort__item
 apr_array_header_t *
 svn_fs_x__order_dir_entries(svn_fs_t *fs,
                             apr_hash_t *directory,
-                            apr_pool_t *pool)
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
 {
   apr_array_header_t *ordered
-    = svn_sort__hash(directory, compare_dir_entries, pool);
+    = svn_sort__hash(directory, compare_dir_entries, scratch_pool);
 
   apr_array_header_t *result
-    = apr_array_make(pool, ordered->nelts, sizeof(svn_fs_dirent_t *));
+    = apr_array_make(result_pool, ordered->nelts, sizeof(svn_fs_dirent_t *));
 
   int i;
   for (i = 0; i < ordered->nelts; ++i)
@@ -757,7 +758,7 @@ compare_p2l_info(const svn_fs_x__p2l_ent
     return (*lhs)->item_count == 0 ? 0 : -1;
   if ((*lhs)->item_count == 0)
     return 1;
-  
+
   if ((*lhs)->items[0].change_set == (*rhs)->items[0].change_set)
     return (*lhs)->items[0].number > (*rhs)->items[0].number ? -1 : 1;
 
@@ -850,7 +851,7 @@ auto_pad_block(pack_context_t *context,
                apr_pool_t *scratch_pool)
 {
   svn_fs_x__data_t *ffd = context->fs->fsap_data;
-  
+
   /* This is the maximum number of bytes "wasted" that way per block.
    * Larger items will cross the block boundaries. */
   const apr_off_t max_padding = MAX(ffd->block_size / 50, 512);
@@ -881,7 +882,7 @@ auto_pad_block(pack_context_t *context,
   return SVN_NO_ERROR;
 }
 
-/* Return the index of the first entry in CONTEXT->REFERENCES that 
+/* Return the index of the first entry in CONTEXT->REFERENCES that
  * references ITEM->ITEMS[0] if such entries exist.  All matching items
  * will be consecutive.
  */
@@ -894,7 +895,7 @@ find_first_reference(pack_context_t *con
 
   while (lower <= upper)
     {
-      int current = lower + (upper - lower) / 2; 
+      int current = lower + (upper - lower) / 2;
       reference_t *reference
         = APR_ARRAY_IDX(context->references, current, reference_t *);
 
@@ -1013,7 +1014,7 @@ reps_fit_into_containers(apr_array_heade
   return TRUE;
 }
 
-/* Write the *CONTAINER containing the noderevs described by the 
+/* Write the *CONTAINER containing the noderevs described by the
  * svn_fs_x__p2l_entry_t * in ITEMS to the pack file on CONTEXT.
  * Append a P2L entry for the container to CONTAINER->REPS.
  * Afterwards, clear ITEMS and re-allocate *CONTAINER in CONTAINER_POOL
@@ -1080,8 +1081,8 @@ write_nodes_container(pack_context_t *co
  * from TEMP_FILE and add them to *CONTAINER and NODES_IN_CONTAINER.
  * Whenever the container grows bigger than the current block in CONTEXT,
  * write the data to disk and continue in the next block.
- * 
- * Use CONTAINER_POOL to re-allocate the *CONTAINER as necessary and 
+ *
+ * Use CONTAINER_POOL to re-allocate the *CONTAINER as necessary and
  * SCRATCH_POOL to temporary allocations.
  */
 static svn_error_t *
@@ -1438,7 +1439,7 @@ copy_reps_from_temp(pack_context_t *cont
                           nodes_in_container, container_pool, iterpool));
 
       /* actually flush the noderevs to disk if the reps container is likely
-       * to fill the block, i.e. no further noderevs will be added to the 
+       * to fill the block, i.e. no further noderevs will be added to the
        * nodes container. */
       if (should_flush_nodes_container(context, nodes_container, node_parts))
         SVN_ERR(write_nodes_container(context, &nodes_container,
@@ -1739,7 +1740,7 @@ pack_range(pack_context_t *context,
 
       /* store the indirect array index */
       APR_ARRAY_PUSH(context->rev_offsets, int) = context->reps->nelts;
-  
+
       /* read the phys-to-log index file until we covered the whole rev file.
        * That index contains enough info to build both target indexes from it. */
       while (offset < l2p_index_info.start)
@@ -1834,7 +1835,7 @@ pack_range(pack_context_t *context,
   SVN_ERR(write_l2p_index(context, revpool));
 
   svn_pool_destroy(revpool);
-  
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/pack.h Sun Jun 14 20:58:10 2015
@@ -51,13 +51,15 @@ svn_fs_x__get_packed_offset(apr_off_t *r
                             apr_pool_t *scratch_pool);
 
 /* Return the svn_dir_entry_t* objects of DIRECTORY in an APR array
- * allocated in POOL with entries added in storage (on-disk) order.
- * FS format will be used to pick the optimal ordering strategy.
+ * allocated in RESULT_POOL with entries added in storage (on-disk) order.
+ * FS' format will be used to pick the optimal ordering strategy.  Use
+ * SCRATCH_POOL for temporary allocations.
  */
 apr_array_header_t *
 svn_fs_x__order_dir_entries(svn_fs_t *fs,
                             apr_hash_t *directory,
-                            apr_pool_t *pool);
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool);
 
 
 #endif

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache-db.sql?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache-db.sql (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache-db.sql Sun Jun 14 20:58:10 2015
@@ -65,3 +65,6 @@ WHERE revision > ?1
 -- STMT_LOCK_REP
 BEGIN TRANSACTION;
 INSERT INTO rep_cache VALUES ('dummy', 0, 0, 0, 0)
+
+-- STMT_UNLOCK_REP
+ROLLBACK TRANSACTION;

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.c Sun Jun 14 20:58:10 2015
@@ -369,16 +369,48 @@ svn_fs_x__del_rep_reference(svn_fs_t *fs
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_fs_x__lock_rep_cache(svn_fs_t *fs,
-                         apr_pool_t *scratch_pool)
+/* Start a transaction to take an SQLite reserved lock that prevents
+   other writes.
+
+   See unlock_rep_cache(). */
+static svn_error_t *
+lock_rep_cache(svn_fs_t *fs,
+               apr_pool_t *pool)
 {
   svn_fs_x__data_t *ffd = fs->fsap_data;
 
   if (! ffd->rep_cache_db)
-    SVN_ERR(svn_fs_x__open_rep_cache(fs, scratch_pool));
+    SVN_ERR(svn_fs_x__open_rep_cache(fs, pool));
 
   SVN_ERR(svn_sqlite__exec_statements(ffd->rep_cache_db, STMT_LOCK_REP));
 
   return SVN_NO_ERROR;
 }
+
+/* End the transaction started by lock_rep_cache(). */
+static svn_error_t *
+unlock_rep_cache(svn_fs_t *fs,
+                 apr_pool_t *pool)
+{
+  svn_fs_x__data_t *ffd = fs->fsap_data;
+
+  SVN_ERR_ASSERT(ffd->rep_cache_db); /* was opened by lock_rep_cache() */
+
+  SVN_ERR(svn_sqlite__exec_statements(ffd->rep_cache_db, STMT_UNLOCK_REP));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_x__with_rep_cache_lock(svn_fs_t *fs,
+                              svn_error_t *(*body)(void *,
+                                                   apr_pool_t *),
+                              void *baton,
+                              apr_pool_t *pool)
+{
+  svn_error_t *err;
+
+  SVN_ERR(lock_rep_cache(fs, pool));
+  err = body(baton, pool);
+  return svn_error_compose_create(err, unlock_rep_cache(fs, pool));
+}

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rep-cache.h Sun Jun 14 20:58:10 2015
@@ -88,12 +88,16 @@ svn_fs_x__del_rep_reference(svn_fs_t *fs
                             svn_revnum_t youngest,
                             apr_pool_t *scratch_pool);
 
+
 /* Start a transaction to take an SQLite reserved lock that prevents
-   other writes. */
+   other writes, call BODY, end the transaction, and return what BODY returned.
+ */
 svn_error_t *
-svn_fs_x__lock_rep_cache(svn_fs_t *fs,
-                         apr_pool_t *scratch_pool);
-
+svn_fs_x__with_rep_cache_lock(svn_fs_t *fs,
+                              svn_error_t *(*body)(void *baton,
+                                                   apr_pool_t *pool),
+                              void *baton,
+                              apr_pool_t *pool);
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/reps.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/reps.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/reps.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/reps.c Sun Jun 14 20:58:10 2015
@@ -34,7 +34,7 @@
 /* Length of the text chunks we hash and match.  The algorithm will find
  * most matches with a length of 2 * MATCH_BLOCKSIZE and only specific
  * ones that are shorter than MATCH_BLOCKSIZE.
- * 
+ *
  * This should be a power of two and must be a multiple of 8.
  * Good choices are 32, 64 and 128.
  */
@@ -55,7 +55,7 @@
 
 /* Byte strings are described by a series of copy instructions that each
  * do one of the following
- * 
+ *
  * - copy a given number of bytes from the text corpus starting at a
  *   given offset
  * - reference other instruction and specify how many of instructions of
@@ -244,7 +244,7 @@ struct svn_fs_x__rep_extractor_t
 
   /* bases (base_t) yet to process (not used ATM) */
   apr_array_header_t *bases;
-  
+
   /* missing sections (missing_t) in result->data that need to be filled,
    * yet */
   apr_array_header_t *missing;
@@ -627,7 +627,7 @@ get_text(svn_fs_x__rep_extractor_t *extr
         missing.count = instruction->count;
         missing.offset = instruction->offset;
         svn_stringbuf_appendfill(extractor->result, 0, instruction->count);
-        
+
         if (extractor->missing == NULL)
           extractor->missing = apr_array_make(extractor->pool, 1,
                                               sizeof(missing));
@@ -724,7 +724,7 @@ svn_fs_x__write_reps_container(svn_strea
 
   svn_packed__create_int_substream(instructions_stream, TRUE, TRUE);
   svn_packed__create_int_substream(instructions_stream, FALSE, FALSE);
-  
+
   /* text */
   svn_packed__add_bytes(text_stream, builder->text->data, builder->text->len);
 
@@ -761,7 +761,7 @@ svn_fs_x__write_reps_container(svn_strea
 
   /* write to stream */
   SVN_ERR(svn_packed__data_write(stream, root, scratch_pool));
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -788,7 +788,7 @@ svn_fs_x__read_reps_container(svn_fs_x__
 
   /* read from disk */
   SVN_ERR(svn_packed__data_read(&root, stream, result_pool, scratch_pool));
-  
+
   bases_stream = svn_packed__first_int_stream(root);
   reps_stream = svn_packed__next_int_stream(bases_stream);
   instructions_stream = svn_packed__next_int_stream(reps_stream);
@@ -849,7 +849,7 @@ svn_fs_x__read_reps_container(svn_fs_x__
 
   /* return result */
   *container = reps;
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -925,7 +925,7 @@ svn_fs_x__reps_get_func(void **out,
                         apr_pool_t *pool)
 {
   svn_fs_x__reps_baton_t *reps_baton = baton;
-  
+
   /* get a usable reps structure  */
   const svn_fs_x__reps_t *cached = data;
   svn_fs_x__reps_t *reps = apr_pmemdup(pool, cached, sizeof(*reps));

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rev_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rev_file.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rev_file.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/rev_file.c Sun Jun 14 20:58:10 2015
@@ -217,7 +217,7 @@ open_pack_or_rev_file(svn_fs_x__revision
 
       /* We may have to *temporarily* enable write access. */
       err = writable ? auto_make_writable(path, file_pool, scratch_pool)
-                     : SVN_NO_ERROR; 
+                     : SVN_NO_ERROR;
 
       /* open the revision file in buffered r/o or r/w mode */
       if (!err)

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.c Sun Jun 14 20:58:10 2015
@@ -574,7 +574,7 @@ typedef struct packed_revprops_t
  * our file system, the revprops belong to REVISION and the global revprop
  * GENERATION is used as well.
  *
- * The returned hash will be allocated in RESULT_POOL, SCRATCH_POOL is 
+ * The returned hash will be allocated in RESULT_POOL, SCRATCH_POOL is
  * being used for temporary allocations.
  */
 static svn_error_t *
@@ -809,7 +809,8 @@ parse_packed_revprops(svn_fs_t *fs,
    * length header to remove) */
   svn_stringbuf_t *compressed = revprops->packed_revprops;
   svn_stringbuf_t *uncompressed = svn_stringbuf_create_empty(result_pool);
-  SVN_ERR(svn__decompress(compressed, uncompressed, APR_SIZE_MAX));
+  SVN_ERR(svn__decompress(compressed->data, compressed->len,
+                          uncompressed, APR_SIZE_MAX));
 
   /* read first revision number and number of revisions in the pack */
   stream = svn_stream_from_stringbuf(uncompressed, scratch_pool);
@@ -856,7 +857,7 @@ parse_packed_revprops(svn_fs_t *fs,
   if (read_all)
     {
       /* Init / construct REVPROPS members. */
-      revprops->sizes = apr_array_make(result_pool, (int)count, 
+      revprops->sizes = apr_array_make(result_pool, (int)count,
                                        sizeof(offset));
       revprops->offsets = apr_array_make(result_pool, (int)count,
                                          sizeof(offset));
@@ -1092,20 +1093,26 @@ write_non_packed_revprop(const char **fi
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
 {
+  apr_file_t *file;
   svn_stream_t *stream;
   *final_path = svn_fs_x__path_revprops(fs, rev, result_pool);
 
   /* ### do we have a directory sitting around already? we really shouldn't
      ### have to get the dirname here. */
-  SVN_ERR(svn_stream_open_unique(&stream, tmp_path,
-                                 svn_dirent_dirname(*final_path,
-                                                    scratch_pool),
-                                 svn_io_file_del_none,
-                                 result_pool, scratch_pool));
+  SVN_ERR(svn_io_open_unique_file3(&file, tmp_path,
+                                   svn_dirent_dirname(*final_path,
+                                                      scratch_pool),
+                                   svn_io_file_del_none,
+                                   scratch_pool, scratch_pool));
+  stream = svn_stream_from_aprfile2(file, TRUE, scratch_pool);
   SVN_ERR(svn_hash_write2(proplist, stream, SVN_HASH_TERMINATOR,
                           scratch_pool));
   SVN_ERR(svn_stream_close(stream));
 
+  /* Flush temporary file to disk and close it. */
+  SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
+  SVN_ERR(svn_io_file_close(file, scratch_pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -1201,7 +1208,7 @@ serialize_revprops_header(svn_stream_t *
   return SVN_NO_ERROR;
 }
 
-/* Writes the a pack file to FILE_STREAM.  It copies the serialized data
+/* Writes the a pack file to FILE.  It copies the serialized data
  * from REVPROPS for the indexes [START,END) except for index CHANGED_INDEX.
  *
  * The data for the latter is taken from NEW_SERIALIZED.  Note, that
@@ -1219,7 +1226,7 @@ repack_revprops(svn_fs_t *fs,
                 int changed_index,
                 svn_stringbuf_t *new_serialized,
                 apr_off_t new_total_size,
-                svn_stream_t *file_stream,
+                apr_file_t *file,
                 apr_pool_t *scratch_pool)
 {
   svn_fs_x__data_t *ffd = fs->fsap_data;
@@ -1262,15 +1269,17 @@ repack_revprops(svn_fs_t *fs,
   SVN_ERR(svn_stream_close(stream));
 
   /* compress / store the data */
-  SVN_ERR(svn__compress(uncompressed,
+  SVN_ERR(svn__compress(uncompressed->data, uncompressed->len,
                         compressed,
                         ffd->compress_packed_revprops
                           ? SVN_DELTA_COMPRESSION_LEVEL_DEFAULT
                           : SVN_DELTA_COMPRESSION_LEVEL_NONE));
 
-  /* finally, write the content to the target stream and close it */
-  SVN_ERR(svn_stream_write(file_stream, compressed->data, &compressed->len));
-  SVN_ERR(svn_stream_close(file_stream));
+  /* finally, write the content to the target file, flush and close it */
+  SVN_ERR(svn_io_file_write_full(file, compressed->data, compressed->len,
+                                 NULL, scratch_pool));
+  SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
+  SVN_ERR(svn_io_file_close(file, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1278,27 +1287,26 @@ repack_revprops(svn_fs_t *fs,
 /* Allocate a new pack file name for revisions
  *     [REVPROPS->START_REVISION + START, REVPROPS->START_REVISION + END - 1]
  * of REVPROPS->MANIFEST.  Add the name of old file to FILES_TO_DELETE,
- * auto-create that array if necessary.  Return an open file stream to
- * the new file in *STREAM allocated in RESULT_POOL.  Allocate the paths
- * in *FILES_TO_DELETE from the same pool that contains the array itself.
+ * auto-create that array if necessary.  Return an open file *FILE that is
+ * allocated in RESULT_POOL.  Allocate the paths in *FILES_TO_DELETE from
+ * the same pool that contains the array itself.
  *
  * Use SCRATCH_POOL for temporary allocations.
  */
 static svn_error_t *
-repack_stream_open(svn_stream_t **stream,
-                   svn_fs_t *fs,
-                   packed_revprops_t *revprops,
-                   int start,
-                   int end,
-                   apr_array_header_t **files_to_delete,
-                   apr_pool_t *result_pool,
-                   apr_pool_t *scratch_pool)
+repack_file_open(apr_file_t **file,
+                 svn_fs_t *fs,
+                 packed_revprops_t *revprops,
+                 int start,
+                 int end,
+                 apr_array_header_t **files_to_delete,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
   apr_int64_t tag;
   const char *tag_string;
   svn_string_t *new_filename;
   int i;
-  apr_file_t *file;
   int manifest_offset
     = (int)(revprops->start_revision - revprops->manifest_start);
 
@@ -1332,13 +1340,12 @@ repack_stream_open(svn_stream_t **stream
     APR_ARRAY_IDX(revprops->manifest, i + manifest_offset, const char*)
       = new_filename->data;
 
-  /* create a file stream for the new file */
-  SVN_ERR(svn_io_file_open(&file, svn_dirent_join(revprops->folder,
-                                                  new_filename->data,
-                                                  scratch_pool),
+  /* open the file */
+  SVN_ERR(svn_io_file_open(file, svn_dirent_join(revprops->folder,
+                                                 new_filename->data,
+                                                 scratch_pool),
                            APR_WRITE | APR_CREATE, APR_OS_DEFAULT,
                            result_pool));
-  *stream = svn_stream_from_aprfile2(file, FALSE, result_pool);
 
   return SVN_NO_ERROR;
 }
@@ -1364,6 +1371,7 @@ write_packed_revprop(const char **final_
   packed_revprops_t *revprops;
   apr_int64_t generation = 0;
   svn_stream_t *stream;
+  apr_file_t *file;
   svn_stringbuf_t *serialized;
   apr_off_t new_total_size;
   int changed_index;
@@ -1401,12 +1409,12 @@ write_packed_revprop(const char **final_
 
       *final_path = svn_dirent_join(revprops->folder, revprops->filename,
                                     result_pool);
-      SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder,
-                                     svn_io_file_del_none, result_pool,
-                                     scratch_pool));
+      SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder,
+                                       svn_io_file_del_none, result_pool,
+                                       scratch_pool));
       SVN_ERR(repack_revprops(fs, revprops, 0, revprops->sizes->nelts,
                               changed_index, serialized, new_total_size,
-                              stream, scratch_pool));
+                              file, scratch_pool));
     }
   else
     {
@@ -1458,54 +1466,57 @@ write_packed_revprop(const char **final_
       /* write the new, split files */
       if (left_count)
         {
-          SVN_ERR(repack_stream_open(&stream, fs, revprops, 0,
-                                     left_count, files_to_delete,
-                                     scratch_pool, scratch_pool));
+          SVN_ERR(repack_file_open(&file, fs, revprops, 0,
+                                   left_count, files_to_delete,
+                                   scratch_pool, scratch_pool));
           SVN_ERR(repack_revprops(fs, revprops, 0, left_count,
                                   changed_index, serialized, new_total_size,
-                                  stream, scratch_pool));
+                                  file, scratch_pool));
         }
 
       if (left_count + right_count < revprops->sizes->nelts)
         {
-          SVN_ERR(repack_stream_open(&stream, fs, revprops, changed_index,
-                                     changed_index + 1, files_to_delete,
-                                     scratch_pool, scratch_pool));
+          SVN_ERR(repack_file_open(&file, fs, revprops, changed_index,
+                                   changed_index + 1, files_to_delete,
+                                   scratch_pool, scratch_pool));
           SVN_ERR(repack_revprops(fs, revprops, changed_index,
                                   changed_index + 1,
                                   changed_index, serialized, new_total_size,
-                                  stream, scratch_pool));
+                                  file, scratch_pool));
         }
 
       if (right_count)
         {
-          SVN_ERR(repack_stream_open(&stream, fs, revprops,
-                                     revprops->sizes->nelts - right_count,
-                                     revprops->sizes->nelts,
-                                     files_to_delete, scratch_pool,
-                                     scratch_pool));
+          SVN_ERR(repack_file_open(&file, fs, revprops,
+                                   revprops->sizes->nelts - right_count,
+                                   revprops->sizes->nelts,
+                                   files_to_delete, scratch_pool,
+                                   scratch_pool));
           SVN_ERR(repack_revprops(fs, revprops,
                                   revprops->sizes->nelts - right_count,
                                   revprops->sizes->nelts, changed_index,
-                                  serialized, new_total_size, stream,
+                                  serialized, new_total_size, file,
                                   scratch_pool));
         }
 
       /* write the new manifest */
       *final_path = svn_dirent_join(revprops->folder, PATH_MANIFEST,
                                     result_pool);
-      SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder,
-                                     svn_io_file_del_none, result_pool,
-                                     scratch_pool));
+      SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder,
+                                       svn_io_file_del_none, result_pool,
+                                       scratch_pool));
 
       for (i = 0; i < revprops->manifest->nelts; ++i)
         {
           const char *filename = APR_ARRAY_IDX(revprops->manifest, i,
                                                const char*);
-          SVN_ERR(svn_stream_printf(stream, scratch_pool, "%s\n", filename));
+          SVN_ERR(svn_io_file_write_full(file, filename, strlen(filename),
+                                         NULL, scratch_pool));
+          SVN_ERR(svn_io_file_putc('\n', file, scratch_pool));
         }
 
-      SVN_ERR(svn_stream_close(stream));
+      SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
+      SVN_ERR(svn_io_file_close(file, scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -1722,7 +1733,8 @@ copy_revprops(svn_fs_t *fs,
   SVN_ERR(svn_stream_close(pack_stream));
 
   /* compress the content (or just store it for COMPRESSION_LEVEL 0) */
-  SVN_ERR(svn__compress(uncompressed, compressed, compression_level));
+  SVN_ERR(svn__compress(uncompressed->data, uncompressed->len,
+                        compressed, compression_level));
 
   /* write the pack file content to disk */
   stream = svn_stream_from_aprfile2(pack_file, FALSE, scratch_pool);
@@ -1841,4 +1853,3 @@ svn_fs_x__pack_revprops_shard(svn_fs_t *
 
   return SVN_NO_ERROR;
 }
-

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/revprops.h Sun Jun 14 20:58:10 2015
@@ -64,7 +64,7 @@ svn_fs_x__set_revision_proplist(svn_fs_t
 
 /* Return TRUE, if for REVISION in FS, we can find the revprop pack file.
  * Use SCRATCH_POOL for temporary allocations.
- * Set *MISSING, if the reason is a missing manifest or pack file. 
+ * Set *MISSING, if the reason is a missing manifest or pack file.
  */
 svn_boolean_t
 svn_fs_x__packed_revprop_available(svn_boolean_t *missing,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.c Sun Jun 14 20:58:10 2015
@@ -128,7 +128,7 @@ svn_fs_x__string_table_builder_create(ap
   result->tables = apr_array_make(result_pool, 1, sizeof(builder_table_t *));
 
   add_table(result);
-  
+
   return result;
 }
 
@@ -146,7 +146,7 @@ balance(builder_table_t *table,
       node->left->right = node;
       *parent = node->left;
       node->left = temp;
-      
+
       --left_height;
     }
   else if (left_height + 1 < right_height)
@@ -370,7 +370,7 @@ svn_fs_x__string_table_builder_estimate_
   /* ZIP compression should give us a 50% reduction.
    * add some static overhead */
   return 200 + total / 2;
- 
+
 }
 
 static void
@@ -458,7 +458,7 @@ svn_fs_x__string_table_create(const stri
                               apr_pool_t *result_pool)
 {
   apr_size_t i;
-  
+
   string_table_t *result = apr_pcalloc(result_pool, sizeof(*result));
   result->size = (apr_size_t)builder->tables->nelts;
   result->sub_tables
@@ -612,7 +612,7 @@ svn_fs_x__write_string_table(svn_stream_
   svn_packed__add_uint(table_sizes, table->size);
 
   /* all short-string char data sizes */
-  
+
   for (i = 0; i < table->size; ++i)
     svn_packed__add_uint(table_sizes,
                          table->sub_tables[i].short_string_count);
@@ -662,7 +662,7 @@ svn_fs_x__read_string_table(string_table
   apr_size_t i, k;
 
   string_table_t *table = apr_palloc(result_pool, sizeof(*table));
- 
+
   svn_packed__data_root_t *root;
   svn_packed__int_stream_t *table_sizes;
   svn_packed__byte_stream_t *large_strings;
@@ -789,7 +789,7 @@ svn_fs_x__serialize_string_table(svn_tem
                                         (const void * const *)&string->data,
                                         string->len + 1);
         }
-        
+
       svn_temp_serializer__pop(context);
     }
 
@@ -804,7 +804,7 @@ svn_fs_x__deserialize_string_table(void
 {
   apr_size_t i, k;
   string_sub_table_t *sub_tables;
-  
+
   svn_temp_deserializer__resolve(buffer, (void **)table);
   if (*table == NULL)
     return;

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/string_table.h Sun Jun 14 20:58:10 2015
@@ -32,7 +32,7 @@ extern "C" {
 
 /* A string table is a very space efficient, read-only representation for
  * a set of strings with high degreed of prefix and postfix overhead.
- * 
+ *
  * Creating a string table is a two-stage process:  Use a builder class,
  * stuff all the strings in there and let it then do the heavy lifting of
  * classification and compression to create the actual string table object.
@@ -101,7 +101,7 @@ svn_error_t *
 svn_fs_x__read_string_table(string_table_t **table_p,
                             svn_stream_t *stream,
                             apr_pool_t *result_pool,
-                            apr_pool_t *scratch_pool); 
+                            apr_pool_t *scratch_pool);
 
 /* Serialize string table *ST within the serialization CONTEXT.
  */

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/transaction.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/transaction.c Sun Jun 14 20:58:10 2015
@@ -474,7 +474,7 @@ svn_fs_x__with_all_locks(svn_fs_t *fs,
                          apr_pool_t *scratch_pool)
 {
   /* Be sure to use the correct lock ordering as documented in
-     fs_fs_shared_data_t.  The lock chain is being created in 
+     fs_fs_shared_data_t.  The lock chain is being created in
      innermost (last to acquire) -> outermost (first to acquire) order. */
   with_lock_baton_t *lock_baton
     = create_lock_baton(fs, write_lock, body, baton, scratch_pool);
@@ -716,7 +716,7 @@ get_writable_proto_rev(apr_file_t **file
 
   /* We don't want unused sections (such as leftovers from failed delta
      stream) in our file.  If we use log addressing, we would need an
-     index entry for the unused section and that section would need to 
+     index entry for the unused section and that section would need to
      be all NUL by convention.  So, detect and fix those cases by truncating
      the protorev file. */
   if (!err)
@@ -1547,7 +1547,7 @@ write_next_ids(svn_fs_t *fs,
   apr_file_t *file;
   char buffer[2 * SVN_INT64_BUFFER_SIZE + 2];
   char *p = buffer;
-  
+
   p += svn__ui64tobase36(p, node_id);
   *(p++) = ' ';
   p += svn__ui64tobase36(p, copy_id);
@@ -3283,7 +3283,7 @@ svn_fs_x__add_index_data(svn_fs_t *fs,
                                      scratch_pool, scratch_pool));
 
   /* Append footer. */
-  footer = svn_fs_x__unparse_footer(l2p_offset, l2p_checksum, 
+  footer = svn_fs_x__unparse_footer(l2p_offset, l2p_checksum,
                                     p2l_offset, p2l_checksum, scratch_pool,
                                     scratch_pool);
   SVN_ERR(svn_io_file_write_full(file, footer->data, footer->len, NULL,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/tree.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/tree.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/tree.c Sun Jun 14 20:58:10 2015
@@ -317,20 +317,19 @@ x_node_relation(svn_fs_node_relation_t *
       return SVN_NO_ERROR;
     }
 
-  /* Nodes from different transactions are never related. */
-  if (root_a->is_txn_root && root_b->is_txn_root
-      && strcmp(root_a->txn, root_b->txn))
-    {
-      *relation = svn_fs_node_unrelated;
-      return SVN_NO_ERROR;
-    }
-
   /* Are both (!) root paths? Then, they are related and we only test how
    * direct the relation is. */
   if (a_is_root_dir && b_is_root_dir)
     {
-      *relation = root_a->rev == root_b->rev
-                ? svn_fs_node_same
+      svn_boolean_t different_txn
+        = root_a->is_txn_root && root_b->is_txn_root
+            && strcmp(root_a->txn, root_b->txn);
+
+      /* For txn roots, root->REV is the base revision of that TXN. */
+      *relation = (   (root_a->rev == root_b->rev)
+                   && (root_a->is_txn_root == root_b->is_txn_root)
+                   && !different_txn)
+                ? svn_fs_node_unchanged
                 : svn_fs_node_common_ancestor;
       return SVN_NO_ERROR;
     }
@@ -345,8 +344,10 @@ x_node_relation(svn_fs_node_relation_t *
   noderev_id_b = *svn_fs_x__dag_get_id(node);
   node_id_b = *svn_fs_x__dag_get_node_id(node);
 
+  /* In FSX, even in-txn IDs are globally unique.
+   * So, we can simply compare them. */
   if (svn_fs_x__id_eq(&noderev_id_a, &noderev_id_b))
-    *relation = svn_fs_node_same;
+    *relation = svn_fs_node_unchanged;
   else if (svn_fs_x__id_eq(&node_id_a, &node_id_b))
     *relation = svn_fs_node_common_ancestor;
   else
@@ -475,6 +476,20 @@ x_node_proplist(apr_hash_t **table_p,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+x_node_has_props(svn_boolean_t *has_props,
+                 svn_fs_root_t *root,
+                 const char *path,
+                 apr_pool_t *scratch_pool)
+{
+  apr_hash_t *props;
+
+  SVN_ERR(x_node_proplist(&props, root, path, scratch_pool));
+
+  *has_props = (0 < apr_hash_count(props));
+
+  return SVN_NO_ERROR;
+}
 
 static svn_error_t *
 increment_mergeinfo_up_tree(svn_fs_x__dag_path_t *pp,
@@ -659,6 +674,15 @@ compare_dir_structure(svn_boolean_t *cha
   SVN_ERR(svn_fs_x__dag_dir_entries(&rhs_entries, rhs, scratch_pool,
                                     iterpool));
 
+  /* different number of entries -> some addition / removal */
+  if (lhs_entries->nelts != rhs_entries->nelts)
+    {
+      svn_pool_destroy(iterpool);
+      *changed = TRUE;
+
+      return SVN_NO_ERROR;
+    }
+
   /* Since directories are sorted by name, we can simply compare their
      entries one-by-one without binary lookup etc. */
   for (i = 0; i < lhs_entries->nelts; ++i)
@@ -680,9 +704,9 @@ compare_dir_structure(svn_boolean_t *cha
           svn_pool_clear(iterpool);
 
           /* Modified but not copied / replaced or anything? */
-          SVN_ERR(svn_fs_x__dag_get_node(&lhs_node, fs, &lhs_entry->id, 
+          SVN_ERR(svn_fs_x__dag_get_node(&lhs_node, fs, &lhs_entry->id,
                                          iterpool, iterpool));
-          SVN_ERR(svn_fs_x__dag_get_node(&rhs_node, fs, &rhs_entry->id, 
+          SVN_ERR(svn_fs_x__dag_get_node(&rhs_node, fs, &rhs_entry->id,
                                          iterpool, iterpool));
           if (svn_fs_x__dag_same_line_of_history(lhs_node, rhs_node))
             continue;
@@ -690,7 +714,9 @@ compare_dir_structure(svn_boolean_t *cha
 
       /* This is a different entry. */
       *changed = TRUE;
-      break;
+      svn_pool_destroy(iterpool);
+
+      return SVN_NO_ERROR;
     }
 
   svn_pool_destroy(iterpool);
@@ -1377,9 +1403,11 @@ static svn_error_t *
 x_dir_optimal_order(apr_array_header_t **ordered_p,
                     svn_fs_root_t *root,
                     apr_hash_t *entries,
-                    apr_pool_t *pool)
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
 {
-  *ordered_p = svn_fs_x__order_dir_entries(root->fs, entries, pool);
+  *ordered_p = svn_fs_x__order_dir_entries(root->fs, entries, result_pool,
+                                           scratch_pool);
 
   return SVN_NO_ERROR;
 }
@@ -1666,7 +1694,7 @@ x_copy(svn_fs_root_t *from_root,
 
   SVN_ERR(copy_helper(from_root,
                       svn_fs__canonicalize_abspath(from_path, subpool),
-                      to_root, 
+                      to_root,
                       svn_fs__canonicalize_abspath(to_path, subpool),
                       TRUE, subpool));
 
@@ -1903,7 +1931,7 @@ window_consumer(svn_txdelta_window_t *wi
      cb->target_string. */
   SVN_ERR(tb->interpreter(window, tb->interpreter_baton));
 
-  /* Is the window NULL?  If so, we're done.  The stream has already been 
+  /* Is the window NULL?  If so, we're done.  The stream has already been
      closed by the interpreter. */
   if (! window)
     SVN_ERR(svn_fs_x__dag_finalize_edits(tb->node, tb->result_checksum,
@@ -3161,6 +3189,7 @@ static root_vtable_t root_vtable = {
   x_closest_copy,
   x_node_prop,
   x_node_proplist,
+  x_node_has_props,
   x_change_node_prop,
   x_props_changed,
   x_dir_entries,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/util.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/util.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/util.c Sun Jun 14 20:58:10 2015
@@ -312,7 +312,7 @@ svn_fs_x__path_txn_sha1(svn_fs_t *fs,
   svn_checksum_t checksum;
   checksum.digest = sha1;
   checksum.kind = svn_checksum_sha1;
-  
+
   return svn_dirent_join(svn_fs_x__path_txn_dir(fs, txn_id, pool),
                          svn_checksum_to_cstring(&checksum, pool),
                          pool);

Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/verify.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/verify.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/verify.c Sun Jun 14 20:58:10 2015
@@ -756,7 +756,7 @@ verify_metadata_consistency(svn_fs_t *fs
       /* Check for external corruption to the indexes. */
       err = verify_index_checksums(fs, pack_start, cancel_func,
                                    cancel_baton, iterpool);
- 
+
       /* two-way index check */
       if (!err)
         err = compare_l2p_to_p2l_index(fs, pack_start, pack_end - pack_start,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.c?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.c Sun Jun 14 20:58:10 2015
@@ -143,7 +143,7 @@ load_ra_module(svn_ra__init_func_t *func
     const char *compat_funcname;
     apr_status_t status;
 
-    libname = apr_psprintf(pool, "libsvn_ra_%s-%d.so.%d",
+    libname = apr_psprintf(pool, "libsvn_ra_%s-" SVN_DSO_SUFFIX_FMT,
                            ra_name, SVN_VER_MAJOR, SVN_SOVERSION);
     funcname = apr_psprintf(pool, "svn_ra_%s__init", ra_name);
     compat_funcname = apr_psprintf(pool, "svn_ra_%s_init", ra_name);
@@ -232,6 +232,11 @@ check_ra_version(const svn_version_t *ra
 
 svn_error_t *svn_ra_initialize(apr_pool_t *pool)
 {
+#if defined(SVN_USE_DSO) && APR_HAS_DSO
+  /* Ensure that DSO subsystem is initialized early as possible if
+     we're going to use it. */
+  SVN_ERR(svn_dso_initialize2());
+#endif
   return SVN_NO_ERROR;
 }
 
@@ -261,6 +266,7 @@ svn_error_t *svn_ra_open4(svn_ra_session
                           apr_pool_t *pool)
 {
   apr_pool_t *sesspool = svn_pool_create(pool);
+  apr_pool_t *scratch_pool = svn_pool_create(sesspool);
   svn_ra_session_t *session;
   const struct ra_lib_defn *defn;
   const svn_ra__vtable_t *vtable = NULL;
@@ -270,6 +276,7 @@ svn_error_t *svn_ra_open4(svn_ra_session
 #ifdef CHOOSABLE_DAV_MODULE
   const char *http_library = DEFAULT_HTTP_LIBRARY;
 #endif
+  svn_auth_baton_t *auth_baton;
 
   /* Initialize the return variable. */
   *session_p = NULL;
@@ -285,8 +292,12 @@ svn_error_t *svn_ra_open4(svn_ra_session
                              repos_URL);
 
   if (callbacks->auth_baton)
-    SVN_ERR(svn_auth__apply_config_for_server(callbacks->auth_baton, config,
-                                              repos_URI.hostname, sesspool));
+    SVN_ERR(svn_auth__make_session_auth(&auth_baton,
+                                        callbacks->auth_baton, config,
+                                        repos_URI.hostname,
+                                        sesspool, scratch_pool));
+  else
+    auth_baton = NULL;
 
 #ifdef CHOOSABLE_DAV_MODULE
   if (config)
@@ -339,16 +350,16 @@ svn_error_t *svn_ra_open4(svn_ra_session
 
           if (! initfunc)
             SVN_ERR(load_ra_module(&initfunc, NULL, defn->ra_name,
-                                   sesspool));
+                                   scratch_pool));
           if (! initfunc)
             /* Library not found. */
             continue;
 
-          SVN_ERR(initfunc(svn_ra_version(), &vtable, sesspool));
+          SVN_ERR(initfunc(svn_ra_version(), &vtable, scratch_pool));
 
           SVN_ERR(check_ra_version(vtable->get_version(), scheme));
 
-          if (! has_scheme_of(vtable->get_schemes(sesspool), repos_URL))
+          if (! has_scheme_of(vtable->get_schemes(scratch_pool), repos_URL))
             /* Library doesn't support the scheme at runtime. */
             continue;
 
@@ -372,10 +383,12 @@ svn_error_t *svn_ra_open4(svn_ra_session
   /* Ask the library to open the session. */
   err = vtable->open_session(session, corrected_url_p,
                              repos_URL,
-                             callbacks, callback_baton, config, sesspool);
+                             callbacks, callback_baton, auth_baton,
+                             config, sesspool, scratch_pool);
 
   if (err)
     {
+      svn_pool_destroy(sesspool); /* Includes scratch_pool */
       if (err->apr_err == SVN_ERR_RA_SESSION_URL_MISMATCH)
         return svn_error_trace(err);
 
@@ -393,7 +406,7 @@ svn_error_t *svn_ra_open4(svn_ra_session
     {
       /* *session_p = NULL; */
       *corrected_url_p = apr_pstrdup(pool, *corrected_url_p);
-      svn_pool_destroy(sesspool);
+      svn_pool_destroy(sesspool); /* Includes scratch_pool */
       return SVN_NO_ERROR;
     }
 
@@ -407,7 +420,7 @@ svn_error_t *svn_ra_open4(svn_ra_session
         {
           /* Duplicate the uuid as it is allocated in sesspool */
           repository_uuid = apr_pstrdup(pool, repository_uuid);
-          svn_pool_destroy(sesspool);
+          svn_pool_destroy(sesspool); /* includes scratch_pool */
           return svn_error_createf(SVN_ERR_RA_UUID_MISMATCH, NULL,
                                    _("Repository UUID '%s' doesn't match "
                                      "expected UUID '%s'"),
@@ -415,6 +428,7 @@ svn_error_t *svn_ra_open4(svn_ra_session
         }
     }
 
+  svn_pool_destroy(scratch_pool);
   *session_p = session;
   return SVN_NO_ERROR;
 }
@@ -582,61 +596,6 @@ svn_error_t *svn_ra_rev_prop(svn_ra_sess
   return session->vtable->rev_prop(session, rev, name, value, pool);
 }
 
-struct ccw_baton
-{
-  svn_commit_callback2_t original_callback;
-  void *original_baton;
-
-  svn_ra_session_t *session;
-};
-
-/* Wrapper which populates the repos_root field of the commit_info struct */
-static svn_error_t *
-commit_callback_wrapper(const svn_commit_info_t *commit_info,
-                        void *baton,
-                        apr_pool_t *pool)
-{
-  struct ccw_baton *ccwb = baton;
-  svn_commit_info_t *ci = svn_commit_info_dup(commit_info, pool);
-
-  SVN_ERR(svn_ra_get_repos_root2(ccwb->session, &ci->repos_root, pool));
-
-  return ccwb->original_callback(ci, ccwb->original_baton, pool);
-}
-
-
-/* Some RA layers do not correctly fill in REPOS_ROOT in commit_info, or
-   they are third-party layers conforming to an older commit_info structure.
-   Interpose a utility function to ensure the field is valid.  */
-static void
-remap_commit_callback(svn_commit_callback2_t *callback,
-                      void **callback_baton,
-                      svn_ra_session_t *session,
-                      svn_commit_callback2_t original_callback,
-                      void *original_baton,
-                      apr_pool_t *result_pool)
-{
-  if (original_callback == NULL)
-    {
-      *callback = NULL;
-      *callback_baton = NULL;
-    }
-  else
-    {
-      /* Allocate this in RESULT_POOL, since the callback will be called
-         long after this function has returned. */
-      struct ccw_baton *ccwb = apr_palloc(result_pool, sizeof(*ccwb));
-
-      ccwb->session = session;
-      ccwb->original_callback = original_callback;
-      ccwb->original_baton = original_baton;
-
-      *callback = commit_callback_wrapper;
-      *callback_baton = ccwb;
-    }
-}
-
-
 svn_error_t *svn_ra_get_commit_editor3(svn_ra_session_t *session,
                                        const svn_delta_editor_t **editor,
                                        void **edit_baton,
@@ -647,10 +606,6 @@ svn_error_t *svn_ra_get_commit_editor3(s
                                        svn_boolean_t keep_locks,
                                        apr_pool_t *pool)
 {
-  remap_commit_callback(&commit_callback, &commit_baton,
-                        session, commit_callback, commit_baton,
-                        pool);
-
   return session->vtable->get_commit_editor(session, editor, edit_baton,
                                             revprop_table,
                                             commit_callback, commit_baton,
@@ -998,6 +953,7 @@ svn_error_t *svn_ra_get_locations(svn_ra
 {
   svn_error_t *err;
 
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(peg_revision));
   SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
   err = session->vtable->get_locations(session, locations, path,
                                        peg_revision, location_revisions, pool);
@@ -1058,7 +1014,7 @@ svn_error_t *svn_ra_get_file_revs2(svn_r
   if (include_merged_revisions)
     SVN_ERR(svn_ra__assert_mergeinfo_capable_server(session, NULL, pool));
 
-  if (start > end)
+  if (start > end || !SVN_IS_VALID_REVNUM(start))
     SVN_ERR(
      svn_ra__assert_capable_server(session,
                                    SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
@@ -1068,7 +1024,8 @@ svn_error_t *svn_ra_get_file_revs2(svn_r
   err = session->vtable->get_file_revs(session, path, start, end,
                                        include_merged_revisions,
                                        handler, handler_baton, pool);
-  if (err && (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED))
+  if (err && (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
+      && !include_merged_revisions)
     {
       svn_error_clear(err);
 
@@ -1076,7 +1033,7 @@ svn_error_t *svn_ra_get_file_revs2(svn_r
       err = svn_ra__file_revs_from_log(session, path, start, end,
                                        handler, handler_baton, pool);
     }
-  return err;
+  return svn_error_trace(err);
 }
 
 svn_error_t *svn_ra_lock(svn_ra_session_t *session,
@@ -1164,6 +1121,8 @@ svn_error_t *svn_ra_replay(svn_ra_sessio
                            void *edit_baton,
                            apr_pool_t *pool)
 {
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision)
+                 && SVN_IS_VALID_REVNUM(low_water_mark));
   return session->vtable->replay(session, revision, low_water_mark,
                                  text_deltas, editor, edit_baton, pool);
 }
@@ -1231,7 +1190,14 @@ svn_ra_replay_range(svn_ra_session_t *se
                     void *replay_baton,
                     apr_pool_t *pool)
 {
-  svn_error_t *err =
+  svn_error_t *err;
+
+  SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start_revision)
+                 && SVN_IS_VALID_REVNUM(end_revision)
+                 && start_revision <= end_revision
+                 && SVN_IS_VALID_REVNUM(low_water_mark));
+
+  err =
     session->vtable->replay_range(session, start_revision, end_revision,
                                   low_water_mark, text_deltas,
                                   revstart_func, revfinish_func,
@@ -1390,11 +1356,6 @@ svn_ra__get_commit_ev2(svn_editor_t **ed
       /* The specific RA layer does not have an implementation. Use our
          default shim over the normal commit editor.  */
 
-      /* Remap for RA layers exposing Ev1.  */
-      remap_commit_callback(&commit_callback, &commit_baton,
-                            session, commit_callback, commit_baton,
-                            result_pool);
-
       return svn_error_trace(svn_ra__use_commit_shim(
                                editor,
                                session,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_ra/ra_loader.h Sun Jun 14 20:58:10 2015
@@ -61,8 +61,10 @@ typedef struct svn_ra__vtable_t {
                                const char *session_URL,
                                const svn_ra_callbacks2_t *callbacks,
                                void *callback_baton,
+                               svn_auth_baton_t *auth_baton,
                                apr_hash_t *config,
-                               apr_pool_t *pool);
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool);
   /* Backs svn_ra_dup_session */
   svn_error_t * (*dup_session)(svn_ra_session_t *new_session,
                                svn_ra_session_t *old_session,

Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra/wrapper_template.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra/wrapper_template.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_ra/wrapper_template.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_ra/wrapper_template.h Sun Jun 14 20:58:10 2015
@@ -91,7 +91,9 @@ static svn_error_t *compat_open(void **s
   callbacks2->progress_baton = NULL;
 
   SVN_ERR(VTBL.open_session(sess, &session_url, repos_URL,
-                            callbacks2, callback_baton, config, sesspool));
+                            callbacks2, callback_baton,
+                            callbacks ? callbacks->auth_baton : NULL,
+                            config, sesspool, sesspool));
 
   if (strcmp(repos_URL, session_url) != 0)
     {

Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra_local/ra_local.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra_local/ra_local.h?rev=1685464&r1=1685463&r2=1685464&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_ra_local/ra_local.h (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_ra_local/ra_local.h Sun Jun 14 20:58:10 2015
@@ -63,6 +63,9 @@ typedef struct svn_ra_local__session_bat
   const svn_ra_callbacks2_t *callbacks;
   void *callback_baton;
 
+  /* Slave auth baton */
+  svn_auth_baton_t *auth_baton;
+
   const char *useragent;
 } svn_ra_local__session_baton_t;
 



Mime
View raw message