You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/04/03 21:56:21 UTC

svn commit: r1584364 [1/2] - in /subversion/branches/remote-only-status: ./ subversion/include/ subversion/libsvn_fs/ subversion/libsvn_fs_base/ subversion/libsvn_fs_fs/ subversion/libsvn_fs_x/ subversion/libsvn_ra_local/ subversion/libsvn_ra_serf/ sub...

Author: brane
Date: Thu Apr  3 19:56:20 2014
New Revision: 1584364

URL: http://svn.apache.org/r1584364
Log:
On the remote-only-status branch: sync with trunk up to r1584342.

Modified:
    subversion/branches/remote-only-status/   (props changed)
    subversion/branches/remote-only-status/COMMITTERS
    subversion/branches/remote-only-status/subversion/include/svn_fs.h
    subversion/branches/remote-only-status/subversion/include/svn_repos.h
    subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.c
    subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.h
    subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.c
    subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.h
    subversion/branches/remote-only-status/subversion/libsvn_fs_fs/cached_data.c
    subversion/branches/remote-only-status/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.c
    subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.h
    subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.c
    subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.h
    subversion/branches/remote-only-status/subversion/libsvn_fs_fs/pack.c
    subversion/branches/remote-only-status/subversion/libsvn_fs_fs/verify.c
    subversion/branches/remote-only-status/subversion/libsvn_fs_x/   (props changed)
    subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.c
    subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.h
    subversion/branches/remote-only-status/subversion/libsvn_ra_local/ra_plugin.c
    subversion/branches/remote-only-status/subversion/libsvn_ra_serf/lock.c
    subversion/branches/remote-only-status/subversion/libsvn_ra_serf/update.c
    subversion/branches/remote-only-status/subversion/libsvn_repos/fs-wrap.c
    subversion/branches/remote-only-status/subversion/libsvn_subr/error.c
    subversion/branches/remote-only-status/subversion/mod_dav_svn/version.c
    subversion/branches/remote-only-status/subversion/svnserve/serve.c
    subversion/branches/remote-only-status/subversion/tests/cmdline/authz_tests.py
    subversion/branches/remote-only-status/subversion/tests/cmdline/commit_tests.py
    subversion/branches/remote-only-status/subversion/tests/cmdline/lock_tests.py
    subversion/branches/remote-only-status/subversion/tests/libsvn_fs/locks-test.c
    subversion/branches/remote-only-status/subversion/tests/libsvn_ra/ra-test.c
    subversion/branches/remote-only-status/tools/server-side/fsfs-stats.c
    subversion/branches/remote-only-status/tools/server-side/svnpubsub/rc.d/svnpubsub.freebsd

Propchange: subversion/branches/remote-only-status/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1583804-1584342

Modified: subversion/branches/remote-only-status/COMMITTERS
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/COMMITTERS?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/COMMITTERS [UTF-8] (original)
+++ subversion/branches/remote-only-status/COMMITTERS [UTF-8] Thu Apr  3 19:56:20 2014
@@ -160,7 +160,7 @@ Commit access for specific areas:
          arwin   Arwin Arni <ar...@collab.net>               (svn-bisect)
           joes   Joe Schaefer <jo...@yahoo.com>       (svnpubsub)
      humbedooh   Daniel Gruno <hu...@apache.org>         (svnpubsub)
-      prabhugs   Prabhu Gnana Sundar <pr...@collab.net>   (verify-keep-going)
+      prabhugs   Prabhu Gnana Sundar <pp...@gmail.com>   (verify-keep-going)
         schabi   Markus Schaber <sc...@apache.org>          (testsuite)
 
 

Modified: subversion/branches/remote-only-status/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/include/svn_fs.h?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/include/svn_fs.h (original)
+++ subversion/branches/remote-only-status/subversion/include/svn_fs.h Thu Apr  3 19:56:20 2014
@@ -2512,7 +2512,7 @@ svn_fs_set_uuid(svn_fs_t *fs,
  * expiration error (depending on the API).
  */
 
-/** The @a targets hash passed to svn_fs_lock2() has <tt>const char
+/** The @a targets hash passed to svn_fs_lock_many() has <tt>const char
  * *</tt> keys and <tt>svn_fs_lock_target_t *</tt> values.
  *
  * @since New in 1.9.
@@ -2524,23 +2524,26 @@ typedef struct svn_fs_lock_target_t
 
 } svn_fs_lock_target_t;
 
-/** The @a results hash returned by svn_fs_lock2() and svn_fs_unlock2()
- * has <tt>const char *</tt> keys and <tt>svn_fs_lock_result_t *</tt>
- * values.
+/** The callback invoked by svn_fs_lock_many() and svn_fs_unlock_many().
  *
- * @since New in 1.9.
- */
-typedef struct svn_fs_lock_result_t
-{
-  svn_lock_t *lock;
-  svn_error_t *err;
-
-} svn_fs_lock_result_t;
+ * @a path and @a lock are allocated in the result_pool passed to
+ * svn_fs_lock_many/svn_fs_unlock_many and so will persist beyond the
+ * callback invocation. @a fs_err will be cleared after the callback
+ * returns, use svn_error_dup() to preserve the error.
+ *
+ * If the callback returns an error no further callbacks will be made
+ * and svn_fs_lock_many/svn_fs_unlock_many will return an error.
+ */
+typedef svn_error_t *(*svn_fs_lock_callback_t)(void *baton,
+                                               const char *path,
+                                               const svn_lock_t *lock,
+                                               svn_error_t *fs_err,
+                                               apr_pool_t *pool);
 
 /** Lock the paths in @a targets in @a fs, and set @a *results to the
  * locks or errors representing each new lock.
  *
- * @warning You may prefer to use svn_repos_fs_lock2() instead,
+ * @warning You may prefer to use svn_repos_fs_lock_many() instead,
  * which see.
  *
  * @a fs must have a username associated with it (see
@@ -2568,7 +2571,7 @@ typedef struct svn_fs_lock_result_t
  * last-changed-revision of the path (or if the path doesn't exist in
  * HEAD), yield an #SVN_ERR_FS_OUT_OF_DATE error for this path.
  *
- * If a path is already locked, then return #SVN_ERR_FS_PATH_ALREADY_LOCKED,
+ * If a path is already locked, then yield #SVN_ERR_FS_PATH_ALREADY_LOCKED,
  * unless @a steal_lock is TRUE, in which case "steal" the existing
  * lock, even if the FS access-context's username does not match the
  * current lock's owner: delete the existing lock on the path, and
@@ -2577,34 +2580,30 @@ typedef struct svn_fs_lock_result_t
  * If @a expiration_date is zero, then create a non-expiring lock.
  * Else, the lock will expire at @a expiration_date.
  *
- * The results are returned in @a *results hash where the keys are
- * <tt>const char *</tt> paths and the values are
- * <tt>svn_fs_lock_result_t *</tt>.  The error associated with each
- * path is returned as #svn_fs_lock_result_t->err. The lock associated
- * with each path is returned as #svn_fs_lock_result_t->lock; this
- * will be @c NULL if no lock was created. @a *results will always be
- * a valid hash and in all cases the caller must ensure that all
- * errors it contains are handled to avoid leaks.
+ * For each path in @a targets @a lock_callback will be invoked
+ * passing @a lock_baton and the lock and error that apply to path.
+ * @a lock_callback can be NULL in which case it is not called.
  *
- * Allocate @a *results in @a result_pool. Use @a scratch_pool for
- * temporary allocations.
+ * The lock and path passed to @a lock_callback will be allocated in
+ * @a result_pool.  Use @a scratch_pool for temporary allocations.
  *
  * @note At this time, only files can be locked.
  *
  * @since New in 1.9.
  */
 svn_error_t *
-svn_fs_lock2(apr_hash_t **results,
-             svn_fs_t *fs,
-             apr_hash_t *targets,
-             const char *comment,
-             svn_boolean_t is_dav_comment,
-             apr_time_t expiration_date,
-             svn_boolean_t steal_lock,
-             apr_pool_t *result_pool,
-             apr_pool_t *scratch_pool);
+svn_fs_lock_many(svn_fs_t *fs,
+                 apr_hash_t *targets,
+                 const char *comment,
+                 svn_boolean_t is_dav_comment,
+                 apr_time_t expiration_date,
+                 svn_boolean_t steal_lock,
+                 svn_fs_lock_callback_t lock_callback,
+                 void *lock_baton,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool);
 
-/** Similar to svn_fs_lock2() but locks only a single @a path and
+/** Similar to svn_fs_lock_many() but locks only a single @a path and
  * returns the lock in @a *lock, allocated in @a pool, or an error.
  *
  * @since New in 1.2.
@@ -2652,35 +2651,30 @@ svn_fs_generate_lock_token(const char **
  * however, don't return error; allow the lock to be "broken" in any
  * case.  In the latter case, the token shall be @c NULL.
  *
- * The results are returned in @a *results hash where the keys are
- * <tt>const char *</tt> paths and the values are
- * <tt>svn_fs_lock_result_t *</tt>.  The error associated with each
- * path is returned as #svn_fs_lock_result_t->err.  @a *results will
- * always be a valid hash and in all cases the caller must ensure that
- * all errors it contains are handled to avoid leaks.
+ * For each path in @a targets @a lock_callback will be invoked
+ * passing @a lock_baton and error that apply to path.  The @a lock
+ * passed to the callback will be NULL.  @a lock_callback can be NULL
+ * in which case it is not called.
  *
  * @note #svn_fs_lock_target_t is used to allow @c NULL tokens to be
  * passed (it is not possible to pass @c NULL as a hash value
  * directly), #svn_fs_lock_target_t->current_rev is ignored.
  *
- * @note #svn_fs_lock_result_t is used to allow @c SVN_NO_ERROR to
- * be returned (it is not possible to return @c SVN_NO_ERROR as a hash
- * value directly), #svn_fs_lock_result_t->lock is always NULL.
- *
- * Allocate @a *results in @a result_pool. Use @a scratch_pool for
- * temporary allocations.
+ * The path passed to lock_callback will be allocated in @a result_pool.
+ * Use @a scratch_pool for temporary allocations.
  *
  * @since New in 1.9.
  */
 svn_error_t *
-svn_fs_unlock2(apr_hash_t **results,
-               svn_fs_t *fs,
-               apr_hash_t *targets,
-               svn_boolean_t break_lock,
-               apr_pool_t *result_pool,
-               apr_pool_t *scratch_pool);
+svn_fs_unlock_many(svn_fs_t *fs,
+                   apr_hash_t *targets,
+                   svn_boolean_t break_lock,
+                   svn_fs_lock_callback_t lock_callback,
+                   void *lock_baton,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool);
 
-/** Similar to svn_fs_unlock2() but only unlocks a single path.
+/** Similar to svn_fs_unlock_many() but only unlocks a single path.
  *
  * @since New in 1.2.
  */

Modified: subversion/branches/remote-only-status/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/include/svn_repos.h?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/include/svn_repos.h (original)
+++ subversion/branches/remote-only-status/subversion/include/svn_repos.h Thu Apr  3 19:56:20 2014
@@ -2184,15 +2184,16 @@ svn_repos_fs_begin_txn_for_update(svn_fs
  * @{
  */
 
-/** Like svn_fs_lock2(), but invoke the @a repos's pre- and
+/** Like svn_fs_lock_many(), but invoke the @a repos's pre- and
  * post-lock hooks before and after the locking action.
  *
  * The pre-lock is run for every path in @a targets. Those targets for
- * which the pre-lock is successful are passed to svn_fs_lock2 and the
- * post-lock is run for those that are successfully locked.
+ * which the pre-lock is successful are passed to svn_fs_lock_many and
+ * the post-lock is run for those that are successfully locked.
  *
- * @a *results contains the result for each target of running the
- * pre-lock and svn_fs_lock2 if the pre-lock was successful.
+ * For each path in @a targets @a lock_callback will be invoked
+ * passing @a lock_baton and the lock and error that apply to path.
+ * @a lock_callback can be NULL in which case it is not called.
  *
  * If an error occurs when running the post-lock hook the error is
  * returned wrapped with #SVN_ERR_REPOS_POST_LOCK_HOOK_FAILED.  If the
@@ -2204,23 +2205,24 @@ svn_repos_fs_begin_txn_for_update(svn_fs
  * lock, instead of the token supplied; see the pre-lock-hook
  * documentation for more.
  *
- * Allocate @a *results in @a result_pool. Use @a scratch_pool for
- * temporary allocations.
+ * The lock and path passed to @a lock_callback will be allocated in
+ * @a result_pool.  Use @a scratch_pool for temporary allocations.
  *
  * @since New in 1.9.
  */
 svn_error_t *
-svn_repos_fs_lock2(apr_hash_t **results,
-                   svn_repos_t *repos,
-                   apr_hash_t *targets,
-                   const char *comment,
-                   svn_boolean_t is_dav_comment,
-                   apr_time_t expiration_date,
-                   svn_boolean_t steal_lock,
-                   apr_pool_t *result_pool,
-                   apr_pool_t *scratch_pool);
+svn_repos_fs_lock_many(svn_repos_t *repos,
+                       apr_hash_t *targets,
+                       const char *comment,
+                       svn_boolean_t is_dav_comment,
+                       apr_time_t expiration_date,
+                       svn_boolean_t steal_lock,
+                       svn_fs_lock_callback_t lock_callback,
+                       void *lock_baton,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool);
 
-/** Similar to svn_repos_fs_lock2() but locks only a single path.
+/** Similar to svn_repos_fs_lock_many() but locks only a single path.
  *
  * @since New in 1.2.
  */
@@ -2237,37 +2239,40 @@ svn_repos_fs_lock(svn_lock_t **lock,
                   apr_pool_t *pool);
 
 
-/** Like svn_fs_unlock2(), but invoke the @a repos's pre- and
+/** Like svn_fs_unlock_many(), but invoke the @a repos's pre- and
  * post-unlock hooks before and after the unlocking action.
  *
  * The pre-unlock hook is run for every path in @a targets. Those
  * targets for which the pre-unlock is successful are passed to
- * svn_fs_unlock2 and the post-unlock is run for those that are
+ * svn_fs_unlock_many and the post-unlock is run for those that are
  * successfully unlocked.
  *
- * @a *results contains the result for each target of running the
- * pre-unlock and svn_fs_unlock2 if the pre-unlock was successful.
-
+ * For each path in @a targets @a lock_callback will be invoked
+ * passing @a lock_baton and error that apply to path.  The lock
+ * passed to the callback will be NULL.  @a lock_callback can be NULL
+ * in which case it is not called.
+ *
  * If an error occurs when running the post-unlock hook, return the
  * original error wrapped with #SVN_ERR_REPOS_POST_UNLOCK_HOOK_FAILED.
  * If the caller sees this error, it knows that some unlocks
  * succeeded.  In all cases the caller must handle all errors in @a
  * *results to avoid leaks.
  *
- * Allocate @a *results in @a result_pool. Use @a scratch_pool for
- * temporary allocations.
+ * The path passed to @a lock_callback will be allocated in @a result_pool.
+ * Use @a scratch_pool for temporary allocations.
  *
  * @since New in 1.9.
  */
 svn_error_t *
-svn_repos_fs_unlock2(apr_hash_t **results,
-                     svn_repos_t *repos,
-                     apr_hash_t *targets,
-                     svn_boolean_t break_lock,
-                     apr_pool_t *result_pool,
-                     apr_pool_t *scratch_pool);
+svn_repos_fs_unlock_many(svn_repos_t *repos,
+                         apr_hash_t *targets,
+                         svn_boolean_t break_lock,
+                         svn_fs_lock_callback_t lock_callback,
+                         void *lock_baton,
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool);
 
-/** Similar to svn_repos_fs_unlock2() but only unlocks a single path.
+/** Similar to svn_repos_fs_unlock_many() but only unlocks a single path.
  *
  * @since New in 1.2.
  */

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.c Thu Apr  3 19:56:20 2014
@@ -1582,22 +1582,46 @@ svn_fs_set_uuid(svn_fs_t *fs, const char
   return svn_error_trace(fs->vtable->set_uuid(fs, uuid, pool));
 }
 
+struct lock_many_baton_t {
+  svn_fs_lock_callback_t lock_callback;
+  void *lock_baton;
+  svn_error_t *cb_err;
+};
+
+/* Implements svn_fs_lock_callback_t.  Used by svn_fs_lock_many and
+   svn_fs_unlock_many to forward to the supplied callback and record
+   any error from the callback. */
+static svn_error_t *
+lock_many_cb(void *lock_baton,
+             const char *path,
+             const svn_lock_t *lock,
+             svn_error_t *fs_err,
+             apr_pool_t *pool)
+{
+  struct lock_many_baton_t *b = lock_baton;
+
+  if (!b->cb_err)
+    b->cb_err = b->lock_callback(b->lock_baton, path, lock, fs_err, pool);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
-svn_fs_lock2(apr_hash_t **results,
-             svn_fs_t *fs,
-             apr_hash_t *targets,
-             const char *comment,
-             svn_boolean_t is_dav_comment,
-             apr_time_t expiration_date,
-             svn_boolean_t steal_lock,
-             apr_pool_t *result_pool,
-             apr_pool_t *scratch_pool)
+svn_fs_lock_many(svn_fs_t *fs,
+                 apr_hash_t *targets,
+                 const char *comment,
+                 svn_boolean_t is_dav_comment,
+                 apr_time_t expiration_date,
+                 svn_boolean_t steal_lock,
+                 svn_fs_lock_callback_t lock_callback,
+                 void *lock_baton,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
   apr_hash_index_t *hi;
-  apr_hash_t *ok_targets = apr_hash_make(scratch_pool), *ok_results;
-  svn_error_t *err;
-
-  *results = apr_hash_make(result_pool);
+  apr_hash_t *ok_targets = apr_hash_make(scratch_pool);
+  svn_error_t *err, *cb_err = SVN_NO_ERROR;
+  struct lock_many_baton_t baton;
 
   /* Enforce that the comment be xml-escapable. */
   if (comment)
@@ -1645,29 +1669,58 @@ svn_fs_lock2(apr_hash_t **results,
 
       if (err)
         {
-          svn_fs_lock_result_t *result
-            = apr_palloc(result_pool, sizeof(svn_fs_lock_result_t));
-
-          result->err = err;
-          result->lock = NULL;
-          svn_hash_sets(*results, svn__apr_hash_index_key(hi), result);
+          if (!cb_err)
+            cb_err = lock_callback(lock_baton, svn__apr_hash_index_key(hi),
+                                   NULL, err, scratch_pool);
+          svn_error_clear(err);
         }
       else
         svn_hash_sets(ok_targets, svn__apr_hash_index_key(hi), target);
     }
 
-  err = fs->vtable->lock(&ok_results, fs, ok_targets, comment,
-                         is_dav_comment, expiration_date,
-                         steal_lock, result_pool, scratch_pool);
-
-  for (hi = apr_hash_first(scratch_pool, ok_results);
-       hi; hi = apr_hash_next(hi))
-    svn_hash_sets(*results, svn__apr_hash_index_key(hi),
-                  svn__apr_hash_index_val(hi));
+  if (!apr_hash_count(ok_targets))
+    return svn_error_trace(cb_err);
+
+  baton.lock_callback = lock_callback;
+  baton.lock_baton = lock_baton;
+  baton.cb_err = cb_err;
+
+  err = fs->vtable->lock(fs, ok_targets, comment, is_dav_comment,
+                         expiration_date, steal_lock,
+                         lock_many_cb, &baton,
+                         result_pool, scratch_pool);
+
+  if (err && baton.cb_err)
+    svn_error_compose(err, baton.cb_err);
+  else if (!err)
+    err = baton.cb_err;
 
   return svn_error_trace(err);
 }
 
+struct lock_baton_t {
+  const svn_lock_t *lock;
+  svn_error_t *fs_err;
+};
+
+/* Implements svn_fs_lock_callback_t. Used by svn_fs_lock and
+   svn_fs_unlock to record the lock and error from svn_fs_lock_many
+   and svn_fs_unlock_many. */
+static svn_error_t *
+lock_cb(void *lock_baton,
+        const char *path,
+        const svn_lock_t *lock,
+        svn_error_t *fs_err,
+        apr_pool_t *pool)
+{
+  struct lock_baton_t *b = lock_baton;
+
+  b->lock = lock;
+  b->fs_err = svn_error_dup(fs_err);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_lock(svn_lock_t **lock, svn_fs_t *fs, const char *path,
             const char *token, const char *comment,
@@ -1675,32 +1728,28 @@ svn_fs_lock(svn_lock_t **lock, svn_fs_t 
             svn_revnum_t current_rev, svn_boolean_t steal_lock,
             apr_pool_t *pool)
 {
-  apr_hash_t *targets = apr_hash_make(pool), *results;
+  apr_hash_t *targets = apr_hash_make(pool);
   svn_fs_lock_target_t target; 
   svn_error_t *err;
+  struct lock_baton_t baton = {0};
 
   target.token = token;
   target.current_rev = current_rev;
   svn_hash_sets(targets, path, &target);
 
-  err = svn_fs_lock2(&results, fs, targets, comment, is_dav_comment,
-                     expiration_date, steal_lock, pool, pool);
-
-  if (apr_hash_count(results))
-    {
-      svn_fs_lock_result_t *result
-        = svn__apr_hash_index_val(apr_hash_first(pool, results));
-
-      if (result->lock)
-        *lock = result->lock;
-
-      if (err && result->err)
-        svn_error_compose(err, result->err);
-      else if (!err)
-        err = result->err;
-    }
+  err = svn_fs_lock_many(fs, targets, comment, is_dav_comment,
+                         expiration_date, steal_lock, lock_cb, &baton,
+                         pool, pool);
+
+  if (baton.lock)
+    *lock = (svn_lock_t*)baton.lock;
+
+  if (err && baton.fs_err)
+    svn_error_compose(err, baton.fs_err);
+  else if (!err)
+    err = baton.fs_err;
   
-  return err;
+  return svn_error_trace(err);
 }
 
 svn_error_t *
@@ -1710,14 +1759,16 @@ svn_fs_generate_lock_token(const char **
 }
 
 svn_error_t *
-svn_fs_unlock2(apr_hash_t **results,
-               svn_fs_t *fs,
-               apr_hash_t *targets,
-               svn_boolean_t break_lock,
-               apr_pool_t *result_pool,
-               apr_pool_t *scratch_pool)
+svn_fs_unlock_many(svn_fs_t *fs,
+                   apr_hash_t *targets,
+                   svn_boolean_t break_lock,
+                   svn_fs_lock_callback_t lock_callback,
+                   void *lock_baton,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
 {
-  return svn_error_trace(fs->vtable->unlock(results, fs, targets, break_lock,
+  return svn_error_trace(fs->vtable->unlock(fs, targets, break_lock,
+                                            lock_callback, lock_baton,
                                             result_pool, scratch_pool));
 }
 
@@ -1725,27 +1776,23 @@ svn_error_t *
 svn_fs_unlock(svn_fs_t *fs, const char *path, const char *token,
               svn_boolean_t break_lock, apr_pool_t *pool)
 {
-  apr_hash_t *targets = apr_hash_make(pool), *results;
+  apr_hash_t *targets = apr_hash_make(pool);
   svn_error_t *err;
+  struct lock_baton_t baton = {0};
 
   if (!token)
     token = "";
   svn_hash_sets(targets, path, token);
 
-  err = svn_fs_unlock2(&results, fs, targets, break_lock, pool, pool);
-
-  if (apr_hash_count(results))
-    {
-      svn_fs_lock_result_t *result
-        = svn__apr_hash_index_val(apr_hash_first(pool, results));
+  err = svn_fs_unlock_many(fs, targets, break_lock, lock_cb, &baton,
+                           pool, pool);
 
-      if (err && result->err)
-        svn_error_compose(err, result->err);
-      else if (!err)
-        err = result->err;
-    }
+  if (err && baton.fs_err)
+    svn_error_compose(err, baton.fs_err);
+  else if (!err)
+    err = baton.fs_err;
 
-  return err;
+  return svn_error_trace(err);
 }
 
 svn_error_t *

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.h?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs/fs-loader.h Thu Apr  3 19:56:20 2014
@@ -218,17 +218,17 @@ typedef struct fs_vtable_t
   svn_error_t *(*list_transactions)(apr_array_header_t **names_p,
                                     svn_fs_t *fs, apr_pool_t *pool);
   svn_error_t *(*deltify)(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool);
-  svn_error_t *(*lock)(apr_hash_t **results,
-                       svn_fs_t *fs,
+  svn_error_t *(*lock)(svn_fs_t *fs,
                        apr_hash_t *targets,
                        const char *comment, svn_boolean_t is_dav_comment,
                        apr_time_t expiration_date, svn_boolean_t steal_lock,
+                       svn_fs_lock_callback_t lock_callback, void *lock_baton,
                        apr_pool_t *result_pool, apr_pool_t *scratch_pool);
   svn_error_t *(*generate_lock_token)(const char **token, svn_fs_t *fs,
                                       apr_pool_t *pool);
-  svn_error_t *(*unlock)(apr_hash_t ** results,
-                         svn_fs_t *fs, apr_hash_t *targets,
+  svn_error_t *(*unlock)(svn_fs_t *fs, apr_hash_t *targets,
                          svn_boolean_t break_lock,
+                         svn_fs_lock_callback_t lock_callback, void *lock_baton,
                          apr_pool_t *result_pool, apr_pool_t *scratch_pool);
   svn_error_t *(*get_lock)(svn_lock_t **lock, svn_fs_t *fs,
                            const char *path, apr_pool_t *pool);

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.c Thu Apr  3 19:56:20 2014
@@ -217,19 +217,19 @@ txn_body_lock(void *baton, trail_t *trai
 
 
 svn_error_t *
-svn_fs_base__lock(apr_hash_t **results,
-                  svn_fs_t *fs,
+svn_fs_base__lock(svn_fs_t *fs,
                   apr_hash_t *targets,
                   const char *comment,
                   svn_boolean_t is_dav_comment,
                   apr_time_t expiration_date,
                   svn_boolean_t steal_lock,
+                  svn_fs_lock_callback_t lock_callback,
+                  void *lock_baton,
                   apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool)
 {
   apr_hash_index_t *hi;
-
-  *results = apr_hash_make(result_pool);
+  svn_error_t *cb_err = SVN_NO_ERROR;
 
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
@@ -239,8 +239,7 @@ svn_fs_base__lock(apr_hash_t **results,
       const char *path = svn__apr_hash_index_key(hi);
       const svn_fs_lock_target_t *target = svn__apr_hash_index_val(hi);
       svn_lock_t *lock;
-      svn_fs_lock_result_t *result = apr_palloc(result_pool,
-                                                sizeof(svn_fs_lock_result_t));
+      svn_error_t *err;
 
       args.lock_p = &lock;
       args.path = svn_fs__canonicalize_abspath(path, result_pool);
@@ -251,13 +250,14 @@ svn_fs_base__lock(apr_hash_t **results,
       args.expiration_date = expiration_date;
       args.current_rev = target->current_rev;
       
-      result->err = svn_fs_base__retry_txn(fs, txn_body_lock, &args, FALSE,
-                                           scratch_pool);
-      result->lock = lock;
-      svn_hash_sets(*results, args.path, result);
+      err = svn_fs_base__retry_txn(fs, txn_body_lock, &args, FALSE,
+                                   scratch_pool);
+      if (!cb_err && lock_callback)
+        cb_err = lock_callback(lock_baton, path, lock, err, scratch_pool);
+      svn_error_clear(err);
     }
 
-  return SVN_NO_ERROR;
+  return svn_error_trace(cb_err);
 }
 
 
@@ -325,16 +325,16 @@ txn_body_unlock(void *baton, trail_t *tr
 
 
 svn_error_t *
-svn_fs_base__unlock(apr_hash_t **results,
-                    svn_fs_t *fs,
+svn_fs_base__unlock(svn_fs_t *fs,
                     apr_hash_t *targets,
                     svn_boolean_t break_lock,
+                    svn_fs_lock_callback_t lock_callback,
+                    void *lock_baton,
                     apr_pool_t *result_pool,
                     apr_pool_t *scratch_pool)
 {
   apr_hash_index_t *hi;
-
-  *results = apr_hash_make(result_pool);
+  svn_error_t *cb_err = SVN_NO_ERROR;
 
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
@@ -343,16 +343,17 @@ svn_fs_base__unlock(apr_hash_t **results
       struct unlock_args args;
       const char *path = svn__apr_hash_index_key(hi);
       const char *token = svn__apr_hash_index_val(hi);
-      svn_fs_lock_result_t *result = apr_palloc(result_pool,
-                                                sizeof(svn_fs_lock_result_t));
+      svn_error_t *err;
 
       args.path = svn_fs__canonicalize_abspath(path, result_pool);
       args.token = token;
       args.break_lock = break_lock;
-      result->err = svn_fs_base__retry_txn(fs, txn_body_unlock, &args, TRUE,
-                                           scratch_pool);
-      result->lock = NULL;
-      svn_hash_sets(*results, args.path, result);
+
+      err = svn_fs_base__retry_txn(fs, txn_body_unlock, &args, TRUE,
+                                   scratch_pool);
+      if (!cb_err && lock_callback)
+        cb_err = lock_callback(lock_baton, path, NULL, err, scratch_pool);
+      svn_error_clear(err);
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.h
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.h?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.h (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_base/lock.h Thu Apr  3 19:56:20 2014
@@ -35,13 +35,14 @@ extern "C" {
 /* These functions implement part of the FS loader library's fs
    vtables.  See the public svn_fs.h for docstrings.*/
 
-svn_error_t *svn_fs_base__lock(apr_hash_t **results,
-                               svn_fs_t *fs,
+svn_error_t *svn_fs_base__lock(svn_fs_t *fs,
                                apr_hash_t *targets,
                                const char *comment,
                                svn_boolean_t is_dav_comment,
                                apr_time_t expiration_date,
                                svn_boolean_t steal_lock,
+                               svn_fs_lock_callback_t lock_callback,
+                               void *lock_baton,
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool);
 
@@ -49,10 +50,11 @@ svn_error_t *svn_fs_base__generate_lock_
                                               svn_fs_t *fs,
                                               apr_pool_t *pool);
 
-svn_error_t *svn_fs_base__unlock(apr_hash_t **results,
-                                 svn_fs_t *fs,
+svn_error_t *svn_fs_base__unlock(svn_fs_t *fs,
                                  apr_hash_t *targets,
                                  svn_boolean_t break_lock,
+                                 svn_fs_lock_callback_t lock_callback,
+                                 void *lock_baton,
                                  apr_pool_t *result_pool,
                                  apr_pool_t *scratch_pool);
 

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_fs/cached_data.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_fs/cached_data.c Thu Apr  3 19:56:20 2014
@@ -914,7 +914,7 @@ svn_fs_fs__check_rep(representation_t *r
                                  _("No representation found at offset %s "
                                    "for item %" APR_UINT64_T_FMT
                                    " in revision %ld"),
-                                 apr_off_t_toa(pool, entry->offset),
+                                 apr_off_t_toa(pool, offset),
                                  rep->item_index, rep->revision);
 
       SVN_ERR(svn_fs_fs__close_revision_file(&rev_file));
@@ -2918,10 +2918,13 @@ block_read(void **result,
    */
   do
     {
+      svn_error_t *err;
+
       /* fetch list of items in the block surrounding OFFSET */
-      svn_error_t *err
-        = svn_fs_fs__p2l_index_lookup(&entries, fs, revision_file,
-                                      revision, offset, scratch_pool);
+      block_start = offset - (offset % ffd->block_size);
+      err = svn_fs_fs__p2l_index_lookup(&entries, fs, revision_file,
+                                        revision, block_start,
+                                        ffd->block_size, scratch_pool);
 
       /* if the revision got packed in the meantime and we still need
        * to actually read some item, we retry the whole process */

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_fs/fs_fs.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_fs/fs_fs.c Thu Apr  3 19:56:20 2014
@@ -578,7 +578,7 @@ read_config(fs_fs_data_t *ffd,
       SVN_ERR(svn_config_get_int64(ffd->config, &ffd->p2l_page_size,
                                    CONFIG_SECTION_IO,
                                    CONFIG_OPTION_P2L_PAGE_SIZE,
-                                   64));
+                                   0x400));
 
       ffd->block_size *= 0x400;
       ffd->p2l_page_size *= 0x400;
@@ -588,7 +588,7 @@ read_config(fs_fs_data_t *ffd,
       /* should be irrelevant but we initialize them anyway */
       ffd->block_size = 0x1000;
       ffd->l2p_page_size = 0x2000;
-      ffd->p2l_page_size = 0x1000;
+      ffd->p2l_page_size = 0x100000;
     }
 
   if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
@@ -802,11 +802,10 @@ write_config(svn_fs_t *fs,
 "### of tens of MB each,  increasing the page size will shorten the index"   NL
 "### file at the expense of a slightly increased latency in sections with"   NL
 "### smaller changes."                                                       NL
-"### For practical reasons, this should match the block-size.  Differing"    NL
-"### values are perfectly legal but may result in some processing overhead." NL
+"### For source code repositories, this should be about 16x the block-size." NL
 "### Must be a power of 2."                                                  NL
-"### p2l-page-size is 64 kBytes by default."                                 NL
-"# " CONFIG_OPTION_P2L_PAGE_SIZE " = 64"                                     NL
+"### p2l-page-size is 1024 kBytes by default."                               NL
+"# " CONFIG_OPTION_P2L_PAGE_SIZE " = 1024"                                   NL
 ;
 #undef NL
   return svn_io_file_create(svn_dirent_join(fs->path, PATH_CONFIG, pool),

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.c Thu Apr  3 19:56:20 2014
@@ -2234,26 +2234,121 @@ get_p2l_keys(p2l_page_info_baton_t *page
   return SVN_NO_ERROR;
 }
 
-/* Body of svn_fs_fs__p2l_index_lookup.
+/* qsort-compatible compare function that compares the OFFSET of the
+ * svn_fs_fs__p2l_entry_t in *LHS with the apr_off_t in *RHS. */
+static int
+compare_start_p2l_entry(const void *lhs,
+                        const void *rhs)
+{
+  const svn_fs_fs__p2l_entry_t *entry = lhs;
+  apr_off_t start = *(const apr_off_t*)rhs;
+  apr_off_t diff = entry->offset - start;
+
+  /* restrict result to int */
+  return diff < 0 ? -1 : (diff == 0 ? 0 : 1);
+}
+
+/* From the PAGE_ENTRIES array of svn_fs_fs__p2l_entry_t, ordered
+ * by their OFFSET member, copy all elements overlapping the range
+ * [BLOCK_START, BLOCK_END) to ENTRIES. */
+static void
+append_p2l_entries(apr_array_header_t *entries,
+                   apr_array_header_t *page_entries,
+                   apr_off_t block_start,
+                   apr_off_t block_end)
+{
+  const svn_fs_fs__p2l_entry_t *entry;
+  int idx = svn_sort__bsearch_lower_bound(page_entries, &block_start,
+                                          compare_start_p2l_entry);
+
+  /* start at the first entry that overlaps with BLOCK_START */
+  if (idx > 0)
+    {
+      entry = &APR_ARRAY_IDX(page_entries, idx - 1, svn_fs_fs__p2l_entry_t);
+      if (entry->offset + entry->size > block_start)
+        --idx;
+    }
+
+  /* copy all entries covering the requested range */
+  for ( ; idx < page_entries->nelts; ++idx)
+    {
+      entry = &APR_ARRAY_IDX(page_entries, idx, svn_fs_fs__p2l_entry_t);
+      if (entry->offset >= block_end)
+        break;
+
+      APR_ARRAY_PUSH(entries, svn_fs_fs__p2l_entry_t) = *entry;
+    }
+}
+
+/* Auxilliary struct passed to p2l_entries_func selecting the relevant
+ * data range. */
+typedef struct p2l_entries_baton_t
+{
+  apr_off_t start;
+  apr_off_t end;
+} p2l_entries_baton_t;
+
+/* Implement svn_cache__partial_getter_func_t: extract p2l entries from
+ * the page in DATA which overlap the p2l_entries_baton_t in BATON.
+ * The target array is already provided in *OUT.
  */
 static svn_error_t *
-p2l_index_lookup(apr_array_header_t **entries,
+p2l_entries_func(void **out,
+                 const void *data,
+                 apr_size_t data_len,
+                 void *baton,
+                 apr_pool_t *result_pool)
+{
+  apr_array_header_t *entries = *(apr_array_header_t **)out;
+  const apr_array_header_t *raw_page = data;
+  p2l_entries_baton_t *block = baton;
+
+  /* Make PAGE a readable APR array. */
+  apr_array_header_t page = *raw_page;
+  page.elts = (void *)svn_temp_deserializer__ptr(raw_page,
+                                    (const void * const *)&raw_page->elts);
+
+  /* append relevant information to result */
+  append_p2l_entries(entries, &page, block->start, block->end);
+
+  return SVN_NO_ERROR;
+}
+
+
+/* Body of svn_fs_fs__p2l_index_lookup.  However, do a single index page
+ * lookup and append the result to the ENTRIES array provided by the caller.
+ * Use successive calls to cover larger ranges.
+ */
+static svn_error_t *
+p2l_index_lookup(apr_array_header_t *entries,
                  svn_fs_fs__revision_file_t *rev_file,
                  svn_fs_t *fs,
                  svn_revnum_t revision,
-                 apr_off_t offset,
+                 apr_off_t block_start,
+                 apr_off_t block_end,
                  apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   svn_fs_fs__page_cache_key_t key;
   svn_boolean_t is_cached = FALSE;
   p2l_page_info_baton_t page_info;
+  apr_array_header_t *local_result = entries;
 
-  /* look for this page in our cache */
-  SVN_ERR(get_p2l_keys(&page_info, &key, rev_file, fs, revision, offset,
+  /* baton selecting the relevant entries from the one page we access */
+  p2l_entries_baton_t block;
+  block.start = block_start;
+  block.end = block_end;
+
+  /* if we requested an empty range, the result would be empty */
+  SVN_ERR_ASSERT(block_start < block_end);
+
+  /* look for the fist page of the range in our cache */
+  SVN_ERR(get_p2l_keys(&page_info, &key, rev_file, fs, revision, block_start,
                        pool));
-  SVN_ERR(svn_cache__get((void**)entries, &is_cached, ffd->p2l_page_cache,
-                         &key, pool));
+  SVN_ERR(svn_cache__get_partial((void**)&local_result, &is_cached,
+                                 ffd->p2l_page_cache, &key, p2l_entries_func,
+                                 &block, pool));
+
   if (!is_cached)
     {
       svn_boolean_t end;
@@ -2261,6 +2356,7 @@ p2l_index_lookup(apr_array_header_t **en
       apr_off_t original_page_start = page_info.page_start;
       int leaking_bucket = 4;
       p2l_page_info_baton_t prefetch_info = page_info;
+      apr_array_header_t *page_entries;
 
       apr_off_t max_offset
         = APR_ALIGN(page_info.next_offset, ffd->block_size);
@@ -2286,14 +2382,18 @@ p2l_index_lookup(apr_array_header_t **en
         }
 
       /* fetch page from disk and put it into the cache */
-      SVN_ERR(get_p2l_page(entries, rev_file, fs,
+      SVN_ERR(get_p2l_page(&page_entries, rev_file, fs,
                            page_info.first_revision,
                            page_info.start_offset,
                            page_info.next_offset,
                            page_info.page_start,
-                           page_info.page_size, pool));
+                           page_info.page_size, iterpool));
 
-      SVN_ERR(svn_cache__set(ffd->p2l_page_cache, &key, *entries, pool));
+      SVN_ERR(svn_cache__set(ffd->p2l_page_cache, &key, page_entries,
+                             iterpool));
+
+      /* append relevant information to result */
+      append_p2l_entries(entries, page_entries, block_start, block_end);
 
       /* pre-fetch following pages */
       end = FALSE;
@@ -2315,6 +2415,41 @@ p2l_index_lookup(apr_array_header_t **en
       svn_pool_destroy(iterpool);
     }
 
+  /* We access a valid page (otherwise, we had seen an error in the
+   * get_p2l_keys request).  Hence, at least one entry must be found. */
+  SVN_ERR_ASSERT(entries->nelts > 0);
+
+  /* Add an "unused" entry if it extends beyond the end of the data file.
+   * Since the index page size might be smaller than the current data
+   * read block size, the trailing "unused" entry in this index may not
+   * fully cover the end of the last block. */
+  if (page_info.page_no + 1 >= page_info.page_count)
+    {
+      svn_fs_fs__p2l_entry_t *entry
+        = &APR_ARRAY_IDX(entries, entries->nelts-1, svn_fs_fs__p2l_entry_t);
+
+      apr_off_t entry_end = entry->offset + entry->size;
+      if (entry_end < block_end)
+        {
+          if (entry->type == SVN_FS_FS__ITEM_TYPE_UNUSED)
+            {
+              /* extend the terminal filler */
+              entry->size = block_end - entry->offset;
+            }
+          else
+            {
+              /* No terminal filler. Add one. */
+              entry = apr_array_push(entries);
+              entry->offset = entry_end;
+              entry->size = block_end - entry_end;
+              entry->type = SVN_FS_FS__ITEM_TYPE_UNUSED;
+              entry->fnv1_checksum = 0;
+              entry->item.revision = SVN_INVALID_REVNUM;
+              entry->item.number = SVN_FS_FS__ITEM_INDEX_UNUSED;
+            }
+        }
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -2323,12 +2458,46 @@ svn_fs_fs__p2l_index_lookup(apr_array_he
                             svn_fs_t *fs,
                             svn_fs_fs__revision_file_t *rev_file,
                             svn_revnum_t revision,
-                            apr_off_t offset,
+                            apr_off_t block_start,
+                            apr_off_t block_size,
                             apr_pool_t *pool)
 {
-  /* look for this page in our cache */
-  SVN_ERR(p2l_index_lookup(entries, rev_file, fs, revision, offset, pool));
+  apr_off_t block_end = block_start + block_size;
+
+  /* the receiving container */
+  int last_count = 0;
+  apr_array_header_t *result = apr_array_make(pool, 16,
+                                              sizeof(svn_fs_fs__p2l_entry_t));
+
+  /* Fetch entries page-by-page.  Since the p2l index is supposed to cover
+   * every single byte in the rev / pack file - even unused sections -
+   * every iteration must result in some progress. */
+  while (block_start < block_end)
+    {
+      svn_fs_fs__p2l_entry_t *entry;
+      SVN_ERR(p2l_index_lookup(result, rev_file, fs, revision, block_start,
+                               block_end, pool));
+      SVN_ERR_ASSERT(result->nelts > 0);
+
+      /* continue directly behind last item */
+      entry = &APR_ARRAY_IDX(result, result->nelts-1, svn_fs_fs__p2l_entry_t);
+      block_start = entry->offset + entry->size;
+
+      /* Some paranoia check.  Successive iterations should never return
+       * duplicates but if it did, we might get into trouble later on. */
+      if (last_count > 0 && last_count < result->nelts)
+        {
+           entry =  &APR_ARRAY_IDX(result, last_count - 1,
+                                   svn_fs_fs__p2l_entry_t);
+           SVN_ERR_ASSERT(APR_ARRAY_IDX(result, last_count,
+                                        svn_fs_fs__p2l_entry_t).offset
+                          >= entry->offset + entry->size);
+        }
+
+      last_count = result->nelts;
+    }
 
+  *entries = result;
   return SVN_NO_ERROR;
 }
 
@@ -2415,8 +2584,9 @@ svn_fs_fs__p2l_entry_lookup(svn_fs_fs__p
     {
       /* do a standard index lookup.  This is will automatically prefetch
        * data to speed up future lookups. */
-      apr_array_header_t *entries;
-      SVN_ERR(p2l_index_lookup(&entries, rev_file, fs, revision, offset, pool));
+      apr_array_header_t *entries = apr_array_make(pool, 1, sizeof(**entry_p));
+      SVN_ERR(p2l_index_lookup(entries, rev_file, fs, revision, offset,
+                               offset + 1, pool));
 
       /* Find the entry that we want. */
       *entry_p = svn_sort__array_lookup(entries, &offset, NULL,

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.h
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.h?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.h (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_fs/index.h Thu Apr  3 19:56:20 2014
@@ -149,12 +149,12 @@ svn_fs_fs__p2l_index_create(svn_fs_t *fs
                             apr_pool_t *pool);
 
 /* Use the phys-to-log mapping files in FS to build a list of entries
- * that (partly) share in the same cluster as the item at global OFFSET
- * in the rep file containing REVISION.  Return the array in *ENTRIES,
- * elements being of type svn_fs_fs__p2l_entry_t.  REV_FILE determines
- * whether to access single rev or pack file data.  If that is not
- * available anymore (neither in cache nor on disk), return an error.
- * Use POOL for allocations.
+ * that (at least partly) overlap with the range given by BLOCK_START
+ * offset and BLOCK_SIZE in the rep / pack file containing REVISION.
+ * Return the array in *ENTRIES with svn_fs_fs__p2l_entry_t as elements.
+ * REV_FILE determines whether to access single rev or pack file data.
+ * If that is not available anymore (neither in cache nor on disk),
+ * return an error.  Use POOL for allocations.
  *
  * Note that (only) the first and the last mapping may cross a cluster
  * boundary.
@@ -164,7 +164,8 @@ svn_fs_fs__p2l_index_lookup(apr_array_he
                             svn_fs_t *fs,
                             svn_fs_fs__revision_file_t *rev_file,
                             svn_revnum_t revision,
-                            apr_off_t offset,
+                            apr_off_t block_start,
+                            apr_off_t block_size,
                             apr_pool_t *pool);
 
 /* Use the phys-to-log mapping files in FS to return the entry for the

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.c Thu Apr  3 19:56:20 2014
@@ -1165,13 +1165,14 @@ unlock_single(svn_fs_t *fs,
 /*** Public API implementations ***/
 
 svn_error_t *
-svn_fs_fs__lock(apr_hash_t **results,
-                svn_fs_t *fs,
+svn_fs_fs__lock(svn_fs_t *fs,
                 apr_hash_t *targets,
                 const char *comment,
                 svn_boolean_t is_dav_comment,
                 apr_time_t expiration_date,
                 svn_boolean_t steal_lock,
+                svn_fs_lock_callback_t lock_callback,
+                void *lock_baton,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
 {
@@ -1179,11 +1180,9 @@ svn_fs_fs__lock(apr_hash_t **results,
   apr_array_header_t *sorted_targets;
   apr_hash_t *cannonical_targets = apr_hash_make(scratch_pool);
   apr_hash_index_t *hi;
-  svn_error_t *err;
+  svn_error_t *err, *cb_err = SVN_NO_ERROR;
   int i;
 
-  *results = apr_hash_make(result_pool);
-
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
   /* We need to have a username attached to the fs. */
@@ -1224,16 +1223,18 @@ svn_fs_fs__lock(apr_hash_t **results,
     {
       struct lock_info_t *info = &APR_ARRAY_IDX(lb.infos, i,
                                                 struct lock_info_t);
-      svn_fs_lock_result_t *result
-        = apr_palloc(result_pool, sizeof(svn_fs_lock_result_t));
-
-      result->lock = info->lock;
-      result->err = info->fs_err;
-
-      svn_hash_sets(*results, info->path, result);
+      if (!cb_err && lock_callback)
+        cb_err = lock_callback(lock_baton, info->path, info->lock,
+                               info->fs_err, scratch_pool);
+      svn_error_clear(info->fs_err);
     }
 
-  return err;
+  if (err && cb_err)
+    svn_error_compose(err, cb_err);
+  else if (!err)
+    err = cb_err;
+
+  return svn_error_trace(err);
 }
 
 
@@ -1254,10 +1255,11 @@ svn_fs_fs__generate_lock_token(const cha
 }
 
 svn_error_t *
-svn_fs_fs__unlock(apr_hash_t **results,
-                  svn_fs_t *fs,
+svn_fs_fs__unlock(svn_fs_t *fs,
                   apr_hash_t *targets,
                   svn_boolean_t break_lock,
+                  svn_fs_lock_callback_t lock_callback,
+                  void *lock_baton,
                   apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool)
 {
@@ -1265,11 +1267,9 @@ svn_fs_fs__unlock(apr_hash_t **results,
   apr_array_header_t *sorted_targets;
   apr_hash_t *cannonical_targets = apr_hash_make(scratch_pool);
   apr_hash_index_t *hi;
-  svn_error_t *err;
+  svn_error_t *err, *cb_err = SVN_NO_ERROR;
   int i;
 
-  *results = apr_hash_make(result_pool);
-
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
   /* We need to have a username attached to the fs. */
@@ -1304,16 +1304,18 @@ svn_fs_fs__unlock(apr_hash_t **results,
     {
       struct unlock_info_t *info = &APR_ARRAY_IDX(ub.infos, i,
                                                   struct unlock_info_t);
-      svn_fs_lock_result_t *result
-        = apr_palloc(result_pool, sizeof(svn_fs_lock_result_t));
-
-      result->lock = NULL;
-      result->err = info->fs_err;
-
-      svn_hash_sets(*results, info->path, result);
+      if (!cb_err && lock_callback)
+        cb_err = lock_callback(lock_baton, info->path, NULL, info->fs_err,
+                               scratch_pool);
+      svn_error_clear(info->fs_err);
     }
 
-  return err;
+  if (err && cb_err)
+    svn_error_compose(err, cb_err);
+  else if (!err)
+    err = cb_err;
+
+  return svn_error_trace(err);
 }
 
 

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.h
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.h?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.h (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_fs/lock.h Thu Apr  3 19:56:20 2014
@@ -32,13 +32,14 @@ extern "C" {
 /* These functions implement some of the calls in the FS loader
    library's fs vtables. */
 
-svn_error_t *svn_fs_fs__lock(apr_hash_t **results,
-                             svn_fs_t *fs,
+svn_error_t *svn_fs_fs__lock(svn_fs_t *fs,
                              apr_hash_t *targets,
                              const char *comment,
                              svn_boolean_t is_dav_comment,
                              apr_time_t expiration_date,
                              svn_boolean_t steal_lock,
+                             svn_fs_lock_callback_t lock_callback,
+                             void *lock_baton,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool);
 
@@ -46,10 +47,11 @@ svn_error_t *svn_fs_fs__generate_lock_to
                                             svn_fs_t *fs,
                                             apr_pool_t *pool);
 
-svn_error_t *svn_fs_fs__unlock(apr_hash_t **results,
-                               svn_fs_t *fs,
+svn_error_t *svn_fs_fs__unlock(svn_fs_t *fs,
                                apr_hash_t *targets,
                                svn_boolean_t break_lock,
+                               svn_fs_lock_callback_t lock_callback,
+                               void *lock_baton,
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool);
 

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_fs/pack.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_fs/pack.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_fs/pack.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_fs/pack.c Thu Apr  3 19:56:20 2014
@@ -1283,6 +1283,7 @@ static svn_error_t *
 pack_range(pack_context_t *context,
            apr_pool_t *pool)
 {
+  fs_fs_data_t *ffd = context->fs->fsap_data;
   apr_pool_t *revpool = svn_pool_create(pool);
   apr_pool_t *iterpool = svn_pool_create(pool);
   apr_pool_t *iterpool2 = svn_pool_create(pool);
@@ -1321,7 +1322,7 @@ pack_range(pack_context_t *context,
 
           SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, context->fs,
                                               rev_file, revision, offset,
-                                              iterpool));
+                                              ffd->p2l_page_size, iterpool));
 
           for (i = 0; i < entries->nelts; ++i)
             {
@@ -1420,6 +1421,7 @@ static svn_error_t *
 append_revision(pack_context_t *context,
                 apr_pool_t *pool)
 {
+  fs_fs_data_t *ffd = context->fs->fsap_data;
   apr_off_t offset = 0;
   apr_pool_t *iterpool = svn_pool_create(pool);
   svn_fs_fs__revision_file_t *rev_file;
@@ -1453,7 +1455,7 @@ append_revision(pack_context_t *context,
       svn_pool_clear(iterpool);
       SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, context->fs, rev_file,
                                           context->start_rev, offset,
-                                          iterpool));
+                                          ffd->p2l_page_size, iterpool));
 
       for (i = 0; i < entries->nelts; ++i)
         {

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_fs/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_fs/verify.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_fs/verify.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_fs/verify.c Thu Apr  3 19:56:20 2014
@@ -254,6 +254,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
                          void *cancel_baton,
                          apr_pool_t *pool)
 {
+  fs_fs_data_t *ffd = fs->fsap_data;
   apr_pool_t *iterpool = svn_pool_create(pool);
   apr_off_t max_offset;
   apr_off_t offset = 0;
@@ -278,7 +279,8 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
 
       /* get all entries for the current block */
       SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, &rev_file, start,
-                                          offset, iterpool));
+                                          offset, ffd->p2l_page_size,
+                                          iterpool));
       if (entries->nelts == 0)
         return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_CORRUPTION,
                                  NULL,
@@ -526,7 +528,8 @@ compare_p2l_to_rev(svn_fs_t *fs,
 
       /* get all entries for the current block */
       SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, rev_file, start,
-                                          offset, iterpool));
+                                          offset, ffd->p2l_page_size,
+                                          iterpool));
 
       /* process all entries (and later continue with the next block) */
       for (i = 0; i < entries->nelts; ++i)

Propchange: subversion/branches/remote-only-status/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
  Merged /subversion/trunk/subversion/libsvn_fs_x:r1583336-1584342

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.c Thu Apr  3 19:56:20 2014
@@ -1165,13 +1165,14 @@ unlock_single(svn_fs_t *fs,
 /*** Public API implementations ***/
 
 svn_error_t *
-svn_fs_x__lock(apr_hash_t **results,
-               svn_fs_t *fs,
+svn_fs_x__lock(svn_fs_t *fs,
                apr_hash_t *targets,
                const char *comment,
                svn_boolean_t is_dav_comment,
                apr_time_t expiration_date,
                svn_boolean_t steal_lock,
+               svn_fs_lock_callback_t lock_callback,
+               void *lock_baton,
                apr_pool_t *result_pool,
                apr_pool_t *scratch_pool)
 {
@@ -1179,11 +1180,9 @@ svn_fs_x__lock(apr_hash_t **results,
   apr_array_header_t *sorted_targets;
   apr_hash_t *cannonical_targets = apr_hash_make(scratch_pool);
   apr_hash_index_t *hi;
-  svn_error_t *err;
+  svn_error_t *err, *cb_err = SVN_NO_ERROR;
   int i;
 
-  *results = apr_hash_make(result_pool);
-
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
   /* We need to have a username attached to the fs. */
@@ -1224,16 +1223,18 @@ svn_fs_x__lock(apr_hash_t **results,
     {
       struct lock_info_t *info = &APR_ARRAY_IDX(lb.infos, i,
                                                 struct lock_info_t);
-      svn_fs_lock_result_t *result
-        = apr_palloc(result_pool, sizeof(svn_fs_lock_result_t));
-
-      result->lock = info->lock;
-      result->err = info->fs_err;
-
-      svn_hash_sets(*results, info->path, result);
+      if (!cb_err && lock_callback)
+        cb_err = lock_callback(lock_baton, info->path, info->lock,
+                               info->fs_err, scratch_pool);
+      svn_error_clear(info->fs_err);
     }
 
-  return err;
+  if (err && cb_err)
+    svn_error_compose(err, cb_err);
+  else if (!err)
+    err = cb_err;
+
+  return svn_error_trace(err);
 }
 
 
@@ -1254,10 +1255,11 @@ svn_fs_x__generate_lock_token(const char
 }
 
 svn_error_t *
-svn_fs_x__unlock(apr_hash_t **results,
-                 svn_fs_t *fs,
+svn_fs_x__unlock(svn_fs_t *fs,
                  apr_hash_t *targets,
                  svn_boolean_t break_lock,
+                 svn_fs_lock_callback_t lock_callback,
+                 void *lock_baton,
                  apr_pool_t *result_pool,
                  apr_pool_t *scratch_pool)
 {
@@ -1265,11 +1267,9 @@ svn_fs_x__unlock(apr_hash_t **results,
   apr_array_header_t *sorted_targets;
   apr_hash_t *cannonical_targets = apr_hash_make(scratch_pool);
   apr_hash_index_t *hi;
-  svn_error_t *err;
+  svn_error_t *err, *cb_err = SVN_NO_ERROR;
   int i;
 
-  *results = apr_hash_make(result_pool);
-
   SVN_ERR(svn_fs__check_fs(fs, TRUE));
 
   /* We need to have a username attached to the fs. */
@@ -1304,16 +1304,18 @@ svn_fs_x__unlock(apr_hash_t **results,
     {
       struct unlock_info_t *info = &APR_ARRAY_IDX(ub.infos, i,
                                                   struct unlock_info_t);
-      svn_fs_lock_result_t *result
-        = apr_palloc(result_pool, sizeof(svn_fs_lock_result_t));
-
-      result->lock = NULL;
-      result->err = info->fs_err;
-
-      svn_hash_sets(*results, info->path, result);
+      if (!cb_err && lock_callback)
+        cb_err = lock_callback(lock_baton, info->path, NULL, info->fs_err,
+                               scratch_pool);
+      svn_error_clear(info->fs_err);
     }
 
-  return err;
+  if (err && cb_err)
+    svn_error_compose(err, cb_err);
+  else if (!err)
+    err = cb_err;
+
+  return svn_error_trace(err);
 }
 
 

Modified: subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.h
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.h?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.h (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_fs_x/lock.h Thu Apr  3 19:56:20 2014
@@ -32,13 +32,14 @@ extern "C" {
 /* These functions implement some of the calls in the FS loader
    library's fs vtables. */
 
-svn_error_t *svn_fs_x__lock(apr_hash_t **results,
-                            svn_fs_t *fs,
+svn_error_t *svn_fs_x__lock(svn_fs_t *fs,
                             apr_hash_t *targets,
                             const char *comment,
                             svn_boolean_t is_dav_comment,
                             apr_time_t expiration_date,
                             svn_boolean_t steal_lock,
+                            svn_fs_lock_callback_t lock_callback,
+                            void *lock_baton,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool);
 
@@ -46,10 +47,11 @@ svn_error_t *svn_fs_x__generate_lock_tok
                                            svn_fs_t *fs,
                                            apr_pool_t *pool);
 
-svn_error_t *svn_fs_x__unlock(apr_hash_t **results,
-                              svn_fs_t *fs,
+svn_error_t *svn_fs_x__unlock(svn_fs_t *fs,
                               apr_hash_t *targets,
                               svn_boolean_t break_lock,
+                              svn_fs_lock_callback_t lock_callback,
+                              void *lock_baton,
                               apr_pool_t *result_pool,
                               apr_pool_t *scratch_pool);
   

Modified: subversion/branches/remote-only-status/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_ra_local/ra_plugin.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_ra_local/ra_plugin.c Thu Apr  3 19:56:20 2014
@@ -411,7 +411,6 @@ deltify_etc(const svn_commit_info_t *com
     {
       apr_pool_t *subpool = svn_pool_create(scratch_pool);
       apr_hash_t *targets = apr_hash_make(subpool);
-      apr_hash_t *results;
       apr_hash_index_t *hi;
 
       for (hi = apr_hash_first(subpool, deb->lock_tokens); hi;
@@ -428,14 +427,9 @@ deltify_etc(const svn_commit_info_t *com
       /* We may get errors here if the lock was broken or stolen
          after the commit succeeded.  This is fine and should be
          ignored. */
-      svn_error_clear(svn_repos_fs_unlock2(&results, deb->repos, targets,
-                                           FALSE, subpool, subpool));
-
-      for (hi = apr_hash_first(subpool, results); hi; hi = apr_hash_next(hi))
-        {
-          svn_fs_lock_result_t *result = svn__apr_hash_index_val(hi);
-          svn_error_clear(result->err);
-        }
+      svn_error_clear(svn_repos_fs_unlock_many(deb->repos, targets, FALSE,
+                                               NULL, NULL,
+                                               subpool, subpool));
 
       svn_pool_destroy(subpool);
     }
@@ -1381,6 +1375,36 @@ svn_ra_local__get_location_segments(svn_
                                           NULL, NULL, pool);
 }
 
+struct lock_baton_t {
+  svn_ra_lock_callback_t lock_func;
+  void *lock_baton;
+  const char *fs_path;
+  svn_boolean_t is_lock;
+  svn_error_t *cb_err;
+};
+
+/* Implements svn_fs_lock_callback_t.  Used by svn_ra_local__lock and
+   svn_ra_local__unlock to forward to supplied callback and record any
+   callback error. */
+static svn_error_t *
+lock_cb(void *lock_baton,
+        const char *path,
+        const svn_lock_t *lock,
+        svn_error_t *fs_err,
+        apr_pool_t *pool)
+{
+  struct lock_baton_t *b = lock_baton;
+
+  if (b && !b->cb_err && b->lock_func)
+    {
+      path = svn_fspath__skip_ancestor(b->fs_path, path);
+      b->cb_err = b->lock_func(b->lock_baton, path, b->is_lock, lock, fs_err,
+                               pool);
+    }
+  
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 svn_ra_local__lock(svn_ra_session_t *session,
                    apr_hash_t *path_revs,
@@ -1391,10 +1415,10 @@ svn_ra_local__lock(svn_ra_session_t *ses
                    apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  apr_pool_t *iterpool = svn_pool_create(pool);
-  apr_hash_t *targets = apr_hash_make(pool), *results;
+  apr_hash_t *targets = apr_hash_make(pool);
   apr_hash_index_t *hi;
-  svn_error_t *err, *err_cb = SVN_NO_ERROR;
+  svn_error_t *err;
+  struct lock_baton_t baton = {0};
 
   /* A username is absolutely required to lock a path. */
   SVN_ERR(get_username(session, pool));
@@ -1412,31 +1436,23 @@ svn_ra_local__lock(svn_ra_session_t *ses
       svn_hash_sets(targets, abs_path, target);
     }
 
-  err = svn_repos_fs_lock2(&results, sess->repos, targets, comment,
-                           FALSE /* not DAV comment */,
-                           0 /* no expiration */, force,
-                           pool, iterpool);
-
-  /* Make sure we handle all locking errors in results hash. */
-  for (hi = apr_hash_first(pool, results); hi; hi = apr_hash_next(hi))
-    {
-      const char *path = svn__apr_hash_index_key(hi);
-      svn_fs_lock_result_t *result = svn__apr_hash_index_val(hi);
-
-      svn_pool_clear(iterpool);
-
-      path = svn_fspath__skip_ancestor(sess->fs_path->data, path);
-      if (!err_cb)
-        err_cb = lock_func(lock_baton, path, TRUE, result->lock, result->err,
-                           iterpool);
-      svn_error_clear(result->err);
-    }
+  baton.lock_func = lock_func;
+  baton.lock_baton = lock_baton;
+  baton.fs_path = sess->fs_path->data;
+  baton.is_lock = TRUE;
+  baton.cb_err = SVN_NO_ERROR;
+
+  err = svn_repos_fs_lock_many(sess->repos, targets, comment,
+                               FALSE /* not DAV comment */,
+                               0 /* no expiration */, force,
+                               lock_cb, &baton,
+                               pool, pool);
 
-  svn_pool_destroy(iterpool);
-  if (err && err_cb)
-    svn_error_compose(err, err_cb);
+  if (err && baton.cb_err)
+    svn_error_compose(err, baton.cb_err);
   else if (!err)
-    err = err_cb;
+    err = baton.cb_err;
+
   return svn_error_trace(err);
 }
 
@@ -1450,10 +1466,10 @@ svn_ra_local__unlock(svn_ra_session_t *s
                      apr_pool_t *pool)
 {
   svn_ra_local__session_baton_t *sess = session->priv;
-  apr_pool_t *iterpool = svn_pool_create(pool);
-  apr_hash_t *targets = apr_hash_make(pool), *results;
+  apr_hash_t *targets = apr_hash_make(pool);
   apr_hash_index_t *hi;
-  svn_error_t *err, *err_cb = SVN_NO_ERROR;
+  svn_error_t *err;
+  struct lock_baton_t baton = {0};
 
   /* A username is absolutely required to unlock a path. */
   SVN_ERR(get_username(session, pool));
@@ -1468,29 +1484,20 @@ svn_ra_local__unlock(svn_ra_session_t *s
       svn_hash_sets(targets, abs_path, token);
     }
 
-  err = svn_repos_fs_unlock2(&results, sess->repos, targets, force,
-                             pool, iterpool);
+  baton.lock_func = lock_func;
+  baton.lock_baton = lock_baton;
+  baton.fs_path = sess->fs_path->data;
+  baton.is_lock = FALSE;
+  baton.cb_err = SVN_NO_ERROR;
 
-  /* Make sure we handle all locking errors in results hash. */
-  for (hi = apr_hash_first(pool, results); hi; hi = apr_hash_next(hi))
-    {
-      const char *path = svn__apr_hash_index_key(hi);
-      svn_fs_lock_result_t *result = svn__apr_hash_index_val(hi);
+  err = svn_repos_fs_unlock_many(sess->repos, targets, force, lock_cb, &baton,
+                                 pool, pool);
 
-      svn_pool_clear(iterpool);
-
-      path = svn_fspath__skip_ancestor(sess->fs_path->data, path);
-      if (lock_func && !err_cb)
-        err_cb = lock_func(lock_baton, path, FALSE, NULL, result->err,
-                           iterpool);
-      svn_error_clear(result->err);
-    }
-
-  svn_pool_destroy(iterpool);
-  if (err && err_cb)
-    svn_error_compose(err, err_cb);
+  if (err && baton.cb_err)
+    svn_error_compose(err, baton.cb_err);
   else if (!err)
-    err = err_cb;
+    err = baton.cb_err;
+
   return svn_error_trace(err);
 }
 

Modified: subversion/branches/remote-only-status/subversion/libsvn_ra_serf/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_ra_serf/lock.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_ra_serf/lock.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_ra_serf/lock.c Thu Apr  3 19:56:20 2014
@@ -263,6 +263,7 @@ run_locks(svn_ra_serf__session_t *sess,
                                             ctx->handler->sline.reason);
                     break;
                   case 403:
+                    /* ### Authz can also lead to 403. */
                     err = svn_error_createf(SVN_ERR_FS_LOCK_OWNER_MISMATCH,
                                             NULL,
                                             _("Unlock of '%s' failed (%d %s)"),

Modified: subversion/branches/remote-only-status/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/remote-only-status/subversion/libsvn_ra_serf/update.c?rev=1584364&r1=1584363&r2=1584364&view=diff
==============================================================================
--- subversion/branches/remote-only-status/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/remote-only-status/subversion/libsvn_ra_serf/update.c Thu Apr  3 19:56:20 2014
@@ -426,9 +426,6 @@ struct report_context_t {
      files/dirs? */
   svn_boolean_t add_props_included;
 
-  /* Path -> lock token mapping. */
-  apr_hash_t *lock_path_tokens;
-
   /* Path -> const char *repos_relpath mapping */
   apr_hash_t *switched_paths;
 
@@ -684,9 +681,6 @@ create_file_baton(file_baton_t **new_fil
   file->base_rev = SVN_INVALID_REVNUM;
   file->copyfrom_rev = SVN_INVALID_REVNUM;
 
-  file->lock_token = svn_hash_gets(ctx->lock_path_tokens,
-                                   file->relpath);
-
   *new_file = file;
 
   ctx->cur_file = file;
@@ -2198,13 +2192,6 @@ set_path(void *report_baton,
 
   SVN_ERR(svn_stream_write(report->body_template, buf->data, &buf->len));
 
-  if (lock_token)
-    {
-      svn_hash_sets(report->lock_path_tokens,
-                    apr_pstrdup(report->pool, path),
-                    apr_pstrdup(report->pool, lock_token));
-    }
-
   return SVN_NO_ERROR;
 }
 
@@ -2275,12 +2262,6 @@ link_path(void *report_baton,
   link = apr_pstrdup(report->pool, link + 1);
   svn_hash_sets(report->switched_paths, path, link);
 
-  if (lock_token)
-    {
-      svn_hash_sets(report->lock_path_tokens,
-                    path, apr_pstrdup(report->pool, lock_token));
-    }
-
   if (!path[0] && report->update_target[0])
     {
       /* The update root is switched. Make sure we store it the way
@@ -2766,7 +2747,6 @@ make_update_reporter(svn_ra_session_t *r
   report->ignore_ancestry = ignore_ancestry;
   report->send_copyfrom_args = send_copyfrom_args;
   report->text_deltas = text_deltas;
-  report->lock_path_tokens = apr_hash_make(report->pool);
   report->switched_paths = apr_hash_make(report->pool);
 
   report->source = src_path;