You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ph...@apache.org on 2014/04/02 19:55:26 UTC
svn commit: r1584114 [1/2] - in /subversion/trunk/subversion: include/
libsvn_fs/ libsvn_fs_base/ libsvn_fs_fs/ libsvn_fs_x/ libsvn_ra_local/
libsvn_repos/ mod_dav_svn/ svnserve/ tests/libsvn_fs/ tests/libsvn_ra/
Author: philip
Date: Wed Apr 2 17:55:25 2014
New Revision: 1584114
URL: http://svn.apache.org/r1584114
Log:
Convert the new multi-path lock and unlock functions to a callback API,
rename from _lock2 and _unlock2 to _lock_many and _unlock_many.
* subversion/include/svn_fs.h
(svn_fs_lock_result_t): Remove.
(svn_fs_lock_callback_t):
(svn_fs_lock2): Rename to...
(svn_fs_lock_many): ...this, change to callback API.
(svn_fs_unlock2): Rename to...
(svn_fs_unlock_many): ...this, change to callback API.
* subversion/include/svn_repos.h
(svn_repos_fs_lock2): Rename to...
(svn_repos_fs_lock_many): ...this, change to callback API.
(svn_repos_fs_unlock2): Rename to...
(svn_repos_fs_unlock_many): ...this, change to callback API.
* subversion/libsvn_fs/fs-loader.h
(struct fs_vtable_t): Change lock and unlock to callback API.
* subversion/libsvn_fs/fs-loader.c
(struct lock_many_baton_t, lock_many_cb): New.
(svn_fs_lock2): Rename to...
(svn_fs_lock_many): ...this, change to callback API.
(struct lock_baton_t, lock_cb): New.
(svn_fs_lock): Adapt to callback API.
(svn_fs_unlock2): Rename to...
(svn_fs_unlock_many): ...this, change to callback API.
(svn_fs_unlock): Adapt to callback API.
* subversion/libsvn_fs_fs/lock.h
* subversion/libsvn_fs_fs/lock.c
(svn_fs_fs__lock, svn_fs_fs__unlock): Change to callback API.
* subversion/libsvn_fs_base/lock.h
* subversion/libsvn_fs_base/lock.c
(svn_fs_base__lock, svn_fs_base__unlock): Change to callback API.
* subversion/libsvn_fs_x/lock.h
* subversion/libsvn_fs_x/lock.c
(svn_fs_x__lock, svn_fs_x__unlock): Change to callback API.
* subversion/libsvn_ra_local/ra_plugin.c
(deltify_etc): Adapt to callback API.
(struct lock_baton_t, lock_cb): New.
(svn_ra_local__lock, svn_ra_local__unlock): Adapt to callback API.
* subversion/libsvn_repos/fs-wrap.c
(struct lock_many_baton_t, lock_many_cb): New.
(svn_repos_fs_lock2): Rename to...
(svn_repos_fs_lock_many): ...this, change to callback API.
(struct lock_baton_t, lock_cb): New.
(svn_repos_fs_lock): Adapt to callback API.
(svn_repos_fs_unlock2): Rename to...
(svn_repos_fs_unlock_many): ...this, change to callback API.
(svn_repos_fs_unlock): Adapt to callback API.
* subversion/mod_dav_svn/version.c
(unlock_many_cb): New.
(release_locks): Adapt to callback API.
* subversion/svnserve/serve.c
(write_lock): Make parameter const.
(lock_cb): New.
(unlock_paths): Adapt to callback API.
(struct lock_result_t, struct lock_many_baton_t, lock_many_cb): New.
(clear_lock_result_hash): New.
(lock_many, unlock_many): Adapt to callback API.
* subversion/tests/libsvn_fs/locks-test.c
(struct lock_result_t): New.
(expect_lock, expect_error, expect_unlock, expect_unlock_error): Change
to struct lock_result_t.
(struct lock_many_baton_t, lock_many_cb): New.
(lock_multiple_paths): Adapt to callback API.
* subversion/tests/libsvn_ra/ra-test.c
(struct lock_result_t): New.
(lock_cb, expect_lock, expect_error, expect_unlock, expect_unlock_error,
lock_test): Change to struct lock_result_t.
Modified:
subversion/trunk/subversion/include/svn_fs.h
subversion/trunk/subversion/include/svn_repos.h
subversion/trunk/subversion/libsvn_fs/fs-loader.c
subversion/trunk/subversion/libsvn_fs/fs-loader.h
subversion/trunk/subversion/libsvn_fs_base/lock.c
subversion/trunk/subversion/libsvn_fs_base/lock.h
subversion/trunk/subversion/libsvn_fs_fs/lock.c
subversion/trunk/subversion/libsvn_fs_fs/lock.h
subversion/trunk/subversion/libsvn_fs_x/lock.c
subversion/trunk/subversion/libsvn_fs_x/lock.h
subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c
subversion/trunk/subversion/libsvn_repos/fs-wrap.c
subversion/trunk/subversion/mod_dav_svn/version.c
subversion/trunk/subversion/svnserve/serve.c
subversion/trunk/subversion/tests/libsvn_fs/locks-test.c
subversion/trunk/subversion/tests/libsvn_ra/ra-test.c
Modified: subversion/trunk/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_fs.h?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_fs.h (original)
+++ subversion/trunk/subversion/include/svn_fs.h Wed Apr 2 17:55:25 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/trunk/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_repos.h?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_repos.h (original)
+++ subversion/trunk/subversion/include/svn_repos.h Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs/fs-loader.c?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/trunk/subversion/libsvn_fs/fs-loader.c Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs/fs-loader.h?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/trunk/subversion/libsvn_fs/fs-loader.h Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_fs_base/lock.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/lock.c?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/trunk/subversion/libsvn_fs_base/lock.c Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_fs_base/lock.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/lock.h?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/lock.h (original)
+++ subversion/trunk/subversion/libsvn_fs_base/lock.h Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/lock.c?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/lock.c Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_fs_fs/lock.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/lock.h?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/lock.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/lock.h Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_fs_x/lock.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/lock.c?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/lock.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/lock.c Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_fs_x/lock.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/lock.h?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/lock.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/lock.h Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/trunk/subversion/libsvn_ra_local/ra_plugin.c Wed Apr 2 17:55:25 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/trunk/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/fs-wrap.c?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/trunk/subversion/libsvn_repos/fs-wrap.c Wed Apr 2 17:55:25 2014
@@ -507,28 +507,60 @@ svn_repos_fs_revision_proplist(apr_hash_
return SVN_NO_ERROR;
}
+struct lock_many_baton_t {
+ svn_boolean_t need_lock;
+ apr_array_header_t *paths;
+ svn_fs_lock_callback_t lock_callback;
+ void *lock_baton;
+ svn_error_t *cb_err;
+ apr_pool_t *pool;
+};
+
+/* Implements svn_fs_lock_callback_t. Used by svn_repos_fs_lock_many
+ and svn_repos_fs_unlock_many to record the paths for use by post-
+ hooks, forward to the supplied callback and record any callback
+ error. */
+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->lock_callback)
+ b->cb_err = b->lock_callback(b->lock_baton, path, lock, fs_err, pool);
+
+ if ((b->need_lock && lock) || (!b->need_lock && !fs_err))
+ APR_ARRAY_PUSH(b->paths, const char *) = apr_pstrdup(b->pool, path);
+
+ return SVN_NO_ERROR;
+}
+
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)
{
- svn_error_t *err;
+ svn_error_t *err, *cb_err = SVN_NO_ERROR;
svn_fs_access_t *access_ctx = NULL;
const char *username = NULL;
apr_hash_t *hooks_env;
apr_hash_t *pre_targets = apr_hash_make(scratch_pool);
apr_hash_index_t *hi;
- apr_array_header_t *paths;
- apr_hash_t *pre_results;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ struct lock_many_baton_t baton;
- *results = apr_hash_make(result_pool);
+ if (!apr_hash_count(targets))
+ return SVN_NO_ERROR;
/* Parse the hooks-env file (if any). */
SVN_ERR(svn_repos__parse_hooks_env(&hooks_env, repos->hooks_env_path,
@@ -557,11 +589,10 @@ svn_repos_fs_lock2(apr_hash_t **results,
username, comment, steal_lock, iterpool);
if (err)
{
- svn_fs_lock_result_t *result
- = apr_palloc(result_pool, sizeof(svn_fs_lock_result_t));
- result->lock = NULL;
- result->err = err;
- svn_hash_sets(*results, path, result);
+ if (!cb_err && lock_callback)
+ cb_err = lock_callback(lock_baton, path, NULL, err, iterpool);
+ svn_error_clear(err);
+
continue;
}
@@ -571,39 +602,62 @@ svn_repos_fs_lock2(apr_hash_t **results,
svn_hash_sets(pre_targets, path, target);
}
- err = svn_fs_lock2(&pre_results, repos->fs, pre_targets, comment,
- is_dav_comment, expiration_date, steal_lock,
- result_pool, iterpool);
-
- /* Combine results so the caller can handle all the errors. */
- for (hi = apr_hash_first(iterpool, pre_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(pre_targets))
+ return svn_error_trace(cb_err);
- /* If there are locks and an error should we return or run the post-lock? */
- if (err)
- return svn_error_trace(err);
+ baton.need_lock = TRUE;
+ baton.paths = apr_array_make(scratch_pool, apr_hash_count(pre_targets),
+ sizeof(const char *));
+ baton.lock_callback = lock_callback;
+ baton.lock_baton = lock_baton;
+ baton.cb_err = cb_err;
+ baton.pool = scratch_pool;
+
+ err = svn_fs_lock_many(repos->fs, pre_targets, comment,
+ is_dav_comment, expiration_date, steal_lock,
+ lock_many_cb, &baton, result_pool, iterpool);
- /* Extract paths that were successfully locked for the post-lock. */
- paths = apr_array_make(iterpool, apr_hash_count(pre_results),
- sizeof(const char *));
- for (hi = apr_hash_first(iterpool, pre_results); hi; hi = apr_hash_next(hi))
+ /* If there are locks and an error should we return or run the post-lock? */
+ if (!err && baton.paths->nelts)
{
- const char *path = svn__apr_hash_index_key(hi);
- svn_fs_lock_result_t *result = svn__apr_hash_index_val(hi);
-
- if (result->lock)
- APR_ARRAY_PUSH(paths, const char *) = path;
+ err = svn_repos__hooks_post_lock(repos, hooks_env, baton.paths, username,
+ iterpool);
+ if (err)
+ err = svn_error_create(SVN_ERR_REPOS_POST_LOCK_HOOK_FAILED, err,
+ _("Locking succeeded, but post-lock hook failed"));
}
- err = svn_repos__hooks_post_lock(repos, hooks_env, paths, username, iterpool);
- if (err)
- err = svn_error_create(SVN_ERR_REPOS_POST_LOCK_HOOK_FAILED, err,
- "Locking succeeded, but post-lock hook failed");
-
svn_pool_destroy(iterpool);
- return err;
+ if (err && cb_err)
+ svn_error_compose(err, cb_err);
+ else if (!err)
+ err = 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_repos_fs_lock and
+ svn_repos_fs_unlock to record the lock and error from
+ svn_repos_fs_lock_many and svn_repos_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 *
@@ -618,55 +672,51 @@ svn_repos_fs_lock(svn_lock_t **lock,
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_repos_fs_lock2(&results, repos, targets, comment, is_dav_comment,
- expiration_date, steal_lock,
- pool, pool);
-
- if (apr_hash_count(results))
- {
- const 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_repos_fs_lock_many(repos, 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 *
-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)
{
- svn_error_t *err;
+ svn_error_t *err, *cb_err = SVN_NO_ERROR;
svn_fs_access_t *access_ctx = NULL;
const char *username = NULL;
apr_hash_t *hooks_env;
apr_hash_t *pre_targets = apr_hash_make(scratch_pool);
apr_hash_index_t *hi;
- apr_array_header_t *paths;
- apr_hash_t *pre_results;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ struct lock_many_baton_t baton;
- *results = apr_hash_make(result_pool);
+ if (!apr_hash_count(targets))
+ return SVN_NO_ERROR;
/* Parse the hooks-env file (if any). */
SVN_ERR(svn_repos__parse_hooks_env(&hooks_env, repos->hooks_env_path,
@@ -682,7 +732,7 @@ svn_repos_fs_unlock2(apr_hash_t **result
_("Cannot unlock, no authenticated username available"));
/* Run pre-unlock hook. This could throw error, preventing
- svn_fs_unlock2() from happening for that path. */
+ svn_fs_unlock_many() from happening for that path. */
for (hi = apr_hash_first(scratch_pool, targets); hi; hi = apr_hash_next(hi))
{
const char *path = svn__apr_hash_index_key(hi);
@@ -694,49 +744,47 @@ svn_repos_fs_unlock2(apr_hash_t **result
break_lock, iterpool);
if (err)
{
- svn_fs_lock_result_t *result
- = apr_palloc(result_pool, sizeof(svn_fs_lock_result_t));
- result->lock = NULL;
- result->err = err;
- svn_hash_sets(*results, path, result);
+ if (!cb_err && lock_callback)
+ cb_err = lock_callback(lock_baton, path, NULL, err, iterpool);
+ svn_error_clear(err);
+
continue;
}
svn_hash_sets(pre_targets, path, token);
}
- err = svn_fs_unlock2(&pre_results, repos->fs, pre_targets, break_lock,
- result_pool, iterpool);
+ if (!apr_hash_count(pre_targets))
+ return svn_error_trace(cb_err);
- /* Combine results for all paths. */
- for (hi = apr_hash_first(iterpool, pre_results); hi; hi = apr_hash_next(hi))
- svn_hash_sets(*results, svn__apr_hash_index_key(hi),
- svn__apr_hash_index_val(hi));
-
- if (err)
- return svn_error_trace(err);
-
- /* Extract paths that were successfully unlocked for the post-unlock. */
- paths = apr_array_make(iterpool, apr_hash_count(pre_results),
- sizeof(const char *));
- for (hi = apr_hash_first(iterpool, pre_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);
+ baton.need_lock = FALSE;
+ baton.paths = apr_array_make(scratch_pool, apr_hash_count(pre_targets),
+ sizeof(const char *));
+ baton.lock_callback = lock_callback;
+ baton.lock_baton = lock_baton;
+ baton.cb_err = cb_err;
+ baton.pool = scratch_pool;
- if (result->lock)
- APR_ARRAY_PUSH(paths, const char *) = path;
- }
-
+ err = svn_fs_unlock_many(repos->fs, pre_targets, break_lock,
+ lock_many_cb, &baton, result_pool, iterpool);
- if ((err = svn_repos__hooks_post_unlock(repos, hooks_env, paths,
- username, iterpool)))
- err = svn_error_create(SVN_ERR_REPOS_POST_UNLOCK_HOOK_FAILED, err,
+ if (!err && baton.paths->nelts)
+ {
+ err = svn_repos__hooks_post_unlock(repos, hooks_env, baton.paths,
+ username, iterpool);
+ if (err)
+ err = svn_error_create(SVN_ERR_REPOS_POST_UNLOCK_HOOK_FAILED, err,
_("Unlock succeeded, but post-unlock hook failed"));
+ }
svn_pool_destroy(iterpool);
- return err;
+ if (err && cb_err)
+ svn_error_compose(err, cb_err);
+ else if (!err)
+ err = cb_err;
+
+ return svn_error_trace(err);
}
svn_error_t *
@@ -746,28 +794,24 @@ svn_repos_fs_unlock(svn_repos_t *repos,
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_repos_fs_unlock2(&results, repos, targets, break_lock, pool, pool);
+ err = svn_repos_fs_unlock_many(repos, targets, break_lock, lock_cb, &baton,
+ pool, pool);
- if (apr_hash_count(results))
- {
- const svn_fs_lock_result_t *result
- = svn__apr_hash_index_val(apr_hash_first(pool, results));
-
- 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);
}
Modified: subversion/trunk/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/version.c?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/version.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/version.c Wed Apr 2 17:55:25 2014
@@ -1354,6 +1354,23 @@ dav_svn__push_locks(dav_resource *resour
return NULL;
}
+/* Implements svn_fs_lock_callback_t. */
+static svn_error_t *
+unlock_many_cb(void *lock_baton,
+ const char *path,
+ const svn_lock_t *lock,
+ svn_error_t *fs_err,
+ apr_pool_t *pool)
+{
+ request_rec *r = lock_baton;
+
+ if (fs_err)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, fs_err->apr_err, r,
+ "%s", fs_err->message);
+
+ return SVN_NO_ERROR;
+}
+
/* Helper for merge(). Free every lock in LOCKS. The locks
live in REPOS. Log any errors for REQUEST. Use POOL for temporary
@@ -1367,7 +1384,6 @@ release_locks(apr_hash_t *locks,
apr_hash_index_t *hi;
apr_pool_t *subpool = svn_pool_create(pool);
apr_hash_t *targets = apr_hash_make(subpool);
- apr_hash_t *results;
svn_error_t *err;
for (hi = apr_hash_first(subpool, locks); hi; hi = apr_hash_next(hi))
@@ -1378,16 +1394,9 @@ release_locks(apr_hash_t *locks,
svn_hash_sets(targets, path, token);
}
- err = svn_repos_fs_unlock2(&results, repos, targets, FALSE, subpool, subpool);
+ err = svn_repos_fs_unlock_many(repos, targets, FALSE, unlock_many_cb, r,
+ 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);
- if (result->err)
- ap_log_rerror(APLOG_MARK, APLOG_ERR, result->err->apr_err, r,
- "%s", result->err->message);
- svn_error_clear(result->err);
- }
if (err) /* If we got an error, just log it and move along. */
ap_log_rerror(APLOG_MARK, APLOG_ERR, err->apr_err, r,
"%s", err->message);
Modified: subversion/trunk/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/serve.c?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/serve.c (original)
+++ subversion/trunk/subversion/svnserve/serve.c Wed Apr 2 17:55:25 2014
@@ -1029,7 +1029,7 @@ static svn_error_t *write_prop_diffs(svn
/* Write out a lock to the client. */
static svn_error_t *write_lock(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- svn_lock_t *lock)
+ const svn_lock_t *lock)
{
const char *cdate, *edate;
@@ -1345,6 +1345,21 @@ static svn_error_t *add_lock_tokens(cons
return SVN_NO_ERROR;
}
+/* Implements svn_fs_lock_callback_t. */
+static svn_error_t *
+lock_cb(void *baton,
+ const char *path,
+ const svn_lock_t *lock,
+ svn_error_t *fs_err,
+ apr_pool_t *pool)
+{
+ server_baton_t *sb = baton;
+
+ log_error(fs_err, sb);
+
+ return SVN_NO_ERROR;
+}
+
/* Unlock the paths with lock tokens in LOCK_TOKENS, ignoring any errors.
LOCK_TOKENS contains svn_ra_svn_item_t elements, assumed to be lists. */
static svn_error_t *unlock_paths(const apr_array_header_t *lock_tokens,
@@ -1354,8 +1369,6 @@ static svn_error_t *unlock_paths(const a
int i;
apr_pool_t *subpool = svn_pool_create(pool);
apr_hash_t *targets = apr_hash_make(subpool);
- apr_hash_t *results;
- apr_hash_index_t *hi;
svn_error_t *err;
for (i = 0; i < lock_tokens->nelts; ++i)
@@ -1378,15 +1391,8 @@ static svn_error_t *unlock_paths(const a
/* The lock may have become defunct after the commit, so ignore such
errors. */
- err = svn_repos_fs_unlock2(&results, sb->repository->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);
-
- log_error(result->err, sb);
- svn_error_clear(result->err);
- }
+ err = svn_repos_fs_unlock_many(sb->repository->repos, targets, FALSE,
+ lock_cb, sb, subpool, subpool);
log_error(err, sb);
svn_error_clear(err);
@@ -2706,6 +2712,48 @@ static svn_error_t *lock(svn_ra_svn_conn
return SVN_NO_ERROR;
}
+struct lock_result_t {
+ const svn_lock_t *lock;
+ svn_error_t *err;
+};
+
+struct lock_many_baton_t {
+ apr_hash_t *results;
+ apr_pool_t *pool;
+};
+
+/* Implements svn_fs_lock_callback_t. */
+static svn_error_t *
+lock_many_cb(void *baton,
+ const char *path,
+ const svn_lock_t *fs_lock,
+ svn_error_t *fs_err,
+ apr_pool_t *pool)
+{
+ struct lock_many_baton_t *b = baton;
+ struct lock_result_t *result = apr_palloc(b->pool,
+ sizeof(struct lock_result_t));
+
+ result->lock = fs_lock;
+ result->err = svn_error_dup(fs_err);
+ svn_hash_sets(b->results, apr_pstrdup(b->pool, path), result);
+
+ return SVN_NO_ERROR;
+}
+
+static void
+clear_lock_result_hash(apr_hash_t *results,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, results); hi; hi = apr_hash_next(hi))
+ {
+ struct lock_result_t *result = svn__apr_hash_index_val(hi);
+ svn_error_clear(result->err);
+ }
+}
+
static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_array_header_t *params, void *baton)
{
@@ -2718,8 +2766,8 @@ static svn_error_t *lock_many(svn_ra_svn
svn_error_t *err, *write_err = SVN_NO_ERROR;
apr_hash_t *targets = apr_hash_make(pool);
apr_hash_t *authz_results = apr_hash_make(pool);
- apr_hash_t *results;
apr_hash_index_t *hi;
+ struct lock_many_baton_t lmb;
SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?c)bl", &comment, &steal_lock,
&path_revs));
@@ -2774,8 +2822,8 @@ static svn_error_t *lock_many(svn_ra_svn
if (! lookup_access(subpool, b, svn_authz_write, full_path, TRUE))
{
- svn_fs_lock_result_t *result
- = apr_palloc(pool, sizeof(svn_fs_lock_result_t));
+ struct lock_result_t *result
+ = apr_palloc(pool, sizeof(struct lock_result_t));
result->lock = NULL;
result->err = error_create_and_log(SVN_ERR_RA_NOT_AUTHORIZED,
@@ -2785,10 +2833,14 @@ static svn_error_t *lock_many(svn_ra_svn
}
}
- err = svn_repos_fs_lock2(&results, b->repository->repos, targets,
- comment, FALSE,
- 0, /* No expiration time. */
- steal_lock, pool, subpool);
+ lmb.results = apr_hash_make(pool);
+ lmb.pool = pool;
+
+ err = svn_repos_fs_lock_many(b->repository->repos, targets,
+ comment, FALSE,
+ 0, /* No expiration time. */
+ steal_lock, lock_many_cb, &lmb,
+ pool, subpool);
/* The client expects results in the same order as paths were supplied. */
for (i = 0; i < path_revs->nelts; ++i)
@@ -2797,7 +2849,7 @@ static svn_error_t *lock_many(svn_ra_svn
svn_revnum_t current_rev;
svn_ra_svn_item_t *item = &APR_ARRAY_IDX(path_revs, i,
svn_ra_svn_item_t);
- svn_fs_lock_result_t *result;
+ struct lock_result_t *result;
svn_pool_clear(subpool);
@@ -2810,7 +2862,7 @@ static svn_error_t *lock_many(svn_ra_svn
svn_relpath_canonicalize(path, subpool),
subpool);
- result = svn_hash_gets(results, full_path);
+ result = svn_hash_gets(lmb.results, full_path);
if (!result)
result = svn_hash_gets(authz_results, full_path);
if (!result)
@@ -2833,16 +2885,8 @@ static svn_error_t *lock_many(svn_ra_svn
break;
}
- for (hi = apr_hash_first(subpool, authz_results); hi; hi = apr_hash_next(hi))
- {
- svn_fs_lock_result_t *result = svn__apr_hash_index_val(hi);
- svn_error_clear(result->err);
- }
- 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);
- }
+ clear_lock_result_hash(authz_results, subpool);
+ clear_lock_result_hash(lmb.results, subpool);
svn_pool_destroy(subpool);
@@ -2895,8 +2939,8 @@ static svn_error_t *unlock_many(svn_ra_s
svn_error_t *err = SVN_NO_ERROR, *write_err;
apr_hash_t *targets = apr_hash_make(pool);
apr_hash_t *authz_results = apr_hash_make(pool);
- apr_hash_t *results;
apr_hash_index_t *hi;
+ struct lock_many_baton_t lmb;
SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "bl", &break_lock,
&unlock_tokens));
@@ -2944,8 +2988,8 @@ static svn_error_t *unlock_many(svn_ra_s
if (! lookup_access(subpool, b, svn_authz_write, full_path,
! break_lock))
{
- svn_fs_lock_result_t *result
- = apr_palloc(pool, sizeof(svn_fs_lock_result_t));
+ struct lock_result_t *result
+ = apr_palloc(pool, sizeof(struct lock_result_t));
result->lock = NULL;
result->err = error_create_and_log(SVN_ERR_RA_NOT_AUTHORIZED,
@@ -2955,8 +2999,12 @@ static svn_error_t *unlock_many(svn_ra_s
}
}
- err = svn_repos_fs_unlock2(&results, b->repository->repos, targets,
- break_lock, pool, subpool);
+ lmb.results = apr_hash_make(pool);
+ lmb.pool = pool;
+
+ err = svn_repos_fs_unlock_many(b->repository->repos, targets,
+ break_lock, lock_many_cb, &lmb,
+ pool, subpool);
/* Return results in the same order as the paths were supplied. */
for (i = 0; i < unlock_tokens->nelts; ++i)
@@ -2964,7 +3012,7 @@ static svn_error_t *unlock_many(svn_ra_s
const char *path, *token, *full_path;
svn_ra_svn_item_t *item = &APR_ARRAY_IDX(unlock_tokens, i,
svn_ra_svn_item_t);
- svn_fs_lock_result_t *result;
+ struct lock_result_t *result;
svn_pool_clear(subpool);
@@ -2977,7 +3025,7 @@ static svn_error_t *unlock_many(svn_ra_s
svn_relpath_canonicalize(path, subpool),
pool);
- result = svn_hash_gets(results, full_path);
+ result = svn_hash_gets(lmb.results, full_path);
if (!result)
result = svn_hash_gets(authz_results, full_path);
if (!result)
@@ -2993,16 +3041,8 @@ static svn_error_t *unlock_many(svn_ra_s
break;
}
- for (hi = apr_hash_first(subpool, authz_results); hi; hi = apr_hash_next(hi))
- {
- svn_fs_lock_result_t *result = svn__apr_hash_index_val(hi);
- svn_error_clear(result->err);
- }
- 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);
- }
+ clear_lock_result_hash(authz_results, subpool);
+ clear_lock_result_hash(lmb.results, subpool);
svn_pool_destroy(subpool);
Modified: subversion/trunk/subversion/tests/libsvn_fs/locks-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_fs/locks-test.c?rev=1584114&r1=1584113&r2=1584114&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_fs/locks-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_fs/locks-test.c Wed Apr 2 17:55:25 2014
@@ -787,6 +787,10 @@ lock_out_of_date(const svn_test_opts_t *
return SVN_NO_ERROR;
}
+struct lock_result_t {
+ const svn_lock_t *lock;
+ svn_error_t *fs_err;
+};
static svn_error_t *
expect_lock(const char *path,
@@ -795,9 +799,9 @@ expect_lock(const char *path,
apr_pool_t *scratch_pool)
{
svn_lock_t *lock;
- svn_fs_lock_result_t *result = svn_hash_gets(results, path);
+ struct lock_result_t *result = svn_hash_gets(results, path);
- SVN_TEST_ASSERT(result && result->lock && !result->err);
+ SVN_TEST_ASSERT(result && result->lock && !result->fs_err);
SVN_ERR(svn_fs_get_lock(&lock, fs, path, scratch_pool));
SVN_TEST_ASSERT(lock);
return SVN_NO_ERROR;
@@ -810,10 +814,10 @@ expect_error(const char *path,
apr_pool_t *scratch_pool)
{
svn_lock_t *lock;
- svn_fs_lock_result_t *result = svn_hash_gets(results, path);
+ struct lock_result_t *result = svn_hash_gets(results, path);
- SVN_TEST_ASSERT(result && !result->lock && result->err);
- svn_error_clear(result->err);
+ SVN_TEST_ASSERT(result && !result->lock && result->fs_err);
+ svn_error_clear(result->fs_err);
SVN_ERR(svn_fs_get_lock(&lock, fs, path, scratch_pool));
SVN_TEST_ASSERT(!lock);
return SVN_NO_ERROR;
@@ -826,9 +830,9 @@ expect_unlock(const char *path,
apr_pool_t *scratch_pool)
{
svn_lock_t *lock;
- svn_fs_lock_result_t *result = svn_hash_gets(results, path);
+ struct lock_result_t *result = svn_hash_gets(results, path);
- SVN_TEST_ASSERT(result && !result->err);
+ SVN_TEST_ASSERT(result && !result->fs_err);
SVN_ERR(svn_fs_get_lock(&lock, fs, path, scratch_pool));
SVN_TEST_ASSERT(!lock);
return SVN_NO_ERROR;
@@ -841,15 +845,39 @@ expect_unlock_error(const char *path,
apr_pool_t *scratch_pool)
{
svn_lock_t *lock;
- svn_fs_lock_result_t *result = svn_hash_gets(results, path);
+ struct lock_result_t *result = svn_hash_gets(results, path);
- SVN_TEST_ASSERT(result && result->err);
- svn_error_clear(result->err);
+ SVN_TEST_ASSERT(result && result->fs_err);
+ svn_error_clear(result->fs_err);
SVN_ERR(svn_fs_get_lock(&lock, fs, path, scratch_pool));
SVN_TEST_ASSERT(lock);
return SVN_NO_ERROR;
}
+struct lock_many_baton_t {
+ apr_hash_t *results;
+ apr_pool_t *pool;
+};
+
+/* Implements svn_fs_lock_callback_t. */
+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;
+ struct lock_result_t *result = apr_palloc(b->pool,
+ sizeof(struct lock_result_t));
+
+ result->lock = lock;
+ result->fs_err = svn_error_dup(fs_err);
+ svn_hash_sets(b->results, apr_pstrdup(b->pool, path), result);
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
lock_multiple_paths(const svn_test_opts_t *opts,
apr_pool_t *pool)
@@ -861,8 +889,8 @@ lock_multiple_paths(const svn_test_opts_
svn_revnum_t newrev;
svn_fs_access_t *access;
svn_fs_lock_target_t target;
- apr_hash_t *lock_paths, *unlock_paths, *results;
- svn_fs_lock_result_t *result;
+ struct lock_many_baton_t baton;
+ apr_hash_t *lock_paths, *unlock_paths;
apr_hash_index_t *hi;
SVN_ERR(create_greek_fs(&fs, &newrev, "test-lock-multiple-paths",
@@ -878,10 +906,13 @@ lock_multiple_paths(const svn_test_opts_
SVN_ERR(svn_fs_copy(root, "/A/mu", txn_root, "/A/BBB/mu", pool));
SVN_ERR(svn_fs_commit_txn(&conflict, &newrev, txn, pool));
+ baton.results = apr_hash_make(pool);
+ baton.pool = pool;
lock_paths = apr_hash_make(pool);
unlock_paths = apr_hash_make(pool);
target.token = NULL;
target.current_rev = newrev;
+
svn_hash_sets(lock_paths, "/A/B/E/alpha", &target);
svn_hash_sets(lock_paths, "/A/B/E/beta", &target);
svn_hash_sets(lock_paths, "/A/B/E/zulu", &target);
@@ -893,81 +924,91 @@ lock_multiple_paths(const svn_test_opts_
svn_hash_sets(lock_paths, "/X/zulu", &target);
/* Lock some paths. */
- SVN_ERR(svn_fs_lock2(&results, fs, lock_paths, "comment", 0, 0, 0,
- pool, pool));
-
- SVN_ERR(expect_lock("/A/B/E/alpha", results, fs, pool));
- SVN_ERR(expect_lock("/A/B/E/beta", results, fs, pool));
- SVN_ERR(expect_error("/A/B/E/zulu", results, fs, pool));
- SVN_ERR(expect_lock("/A/BB/mu", results, fs, pool));
- SVN_ERR(expect_lock("/A/BBB/mu", results, fs, pool));
- SVN_ERR(expect_lock("/A/D/G/pi", results, fs, pool));
- SVN_ERR(expect_lock("/A/D/G/rho", results, fs, pool));
- SVN_ERR(expect_lock("/A/mu", results, fs, pool));
- SVN_ERR(expect_error("/X/zulu", results, fs, pool));
+ apr_hash_clear(baton.results);
+ SVN_ERR(svn_fs_lock_many(fs, lock_paths, "comment", 0, 0, 0,
+ lock_many_cb, &baton,
+ pool, pool));
+
+ SVN_ERR(expect_lock("/A/B/E/alpha", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/B/E/beta", baton.results, fs, pool));
+ SVN_ERR(expect_error("/A/B/E/zulu", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/BB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/BBB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/D/G/pi", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/D/G/rho", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/mu", baton.results, fs, pool));
+ SVN_ERR(expect_error("/X/zulu", baton.results, fs, pool));
/* Unlock without force and wrong tokens. */
for (hi = apr_hash_first(pool, lock_paths); hi; hi = apr_hash_next(hi))
svn_hash_sets(unlock_paths, svn__apr_hash_index_key(hi), "wrong-token");
- SVN_ERR(svn_fs_unlock2(&results, fs, unlock_paths, FALSE, pool, pool));
-
- SVN_ERR(expect_unlock_error("/A/B/E/alpha", results, fs, pool));
- SVN_ERR(expect_unlock_error("/A/B/E/beta", results, fs, pool));
- SVN_ERR(expect_error("/A/B/E/zulu", results, fs, pool));
- SVN_ERR(expect_unlock_error("/A/BB/mu", results, fs, pool));
- SVN_ERR(expect_unlock_error("/A/BBB/mu", results, fs, pool));
- SVN_ERR(expect_unlock_error("/A/D/G/pi", results, fs, pool));
- SVN_ERR(expect_unlock_error("/A/D/G/rho", results, fs, pool));
- SVN_ERR(expect_unlock_error("/A/mu", results, fs, pool));
- SVN_ERR(expect_error("/X/zulu", results, fs, pool));
+ apr_hash_clear(baton.results);
+ SVN_ERR(svn_fs_unlock_many(fs, unlock_paths, FALSE, lock_many_cb, &baton,
+ pool, pool));
+
+ SVN_ERR(expect_unlock_error("/A/B/E/alpha", baton.results, fs, pool));
+ SVN_ERR(expect_unlock_error("/A/B/E/beta", baton.results, fs, pool));
+ SVN_ERR(expect_error("/A/B/E/zulu", baton.results, fs, pool));
+ SVN_ERR(expect_unlock_error("/A/BB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_unlock_error("/A/BBB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_unlock_error("/A/D/G/pi", baton.results, fs, pool));
+ SVN_ERR(expect_unlock_error("/A/D/G/rho", baton.results, fs, pool));
+ SVN_ERR(expect_unlock_error("/A/mu", baton.results, fs, pool));
+ SVN_ERR(expect_error("/X/zulu", baton.results, fs, pool));
/* Force unlock. */
for (hi = apr_hash_first(pool, lock_paths); hi; hi = apr_hash_next(hi))
svn_hash_sets(unlock_paths, svn__apr_hash_index_key(hi), "");
- SVN_ERR(svn_fs_unlock2(&results, fs, unlock_paths, TRUE, pool, pool));
-
- SVN_ERR(expect_unlock("/A/B/E/alpha", results, fs, pool));
- SVN_ERR(expect_unlock("/A/B/E/beta", results, fs, pool));
- SVN_ERR(expect_error("/A/B/E/zulu", results, fs, pool));
- SVN_ERR(expect_unlock("/A/BB/mu", results, fs, pool));
- SVN_ERR(expect_unlock("/A/BBB/mu", results, fs, pool));
- SVN_ERR(expect_unlock("/A/D/G/pi", results, fs, pool));
- SVN_ERR(expect_unlock("/A/D/G/rho", results, fs, pool));
- SVN_ERR(expect_unlock("/A/mu", results, fs, pool));
- SVN_ERR(expect_error("/X/zulu", results, fs, pool));
+ apr_hash_clear(baton.results);
+ SVN_ERR(svn_fs_unlock_many(fs, unlock_paths, TRUE, lock_many_cb, &baton,
+ pool, pool));
+
+ SVN_ERR(expect_unlock("/A/B/E/alpha", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/B/E/beta", baton.results, fs, pool));
+ SVN_ERR(expect_error("/A/B/E/zulu", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/BB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/BBB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/D/G/pi", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/D/G/rho", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/mu", baton.results, fs, pool));
+ SVN_ERR(expect_error("/X/zulu", baton.results, fs, pool));
/* Lock again. */
- SVN_ERR(svn_fs_lock2(&results, fs, lock_paths, "comment", 0, 0, 0,
- pool, pool));
-
- SVN_ERR(expect_lock("/A/B/E/alpha", results, fs, pool));
- SVN_ERR(expect_lock("/A/B/E/beta", results, fs, pool));
- SVN_ERR(expect_error("/A/B/E/zulu", results, fs, pool));
- SVN_ERR(expect_lock("/A/BB/mu", results, fs, pool));
- SVN_ERR(expect_lock("/A/BBB/mu", results, fs, pool));
- SVN_ERR(expect_lock("/A/D/G/pi", results, fs, pool));
- SVN_ERR(expect_lock("/A/D/G/rho", results, fs, pool));
- SVN_ERR(expect_lock("/A/mu", results, fs, pool));
- SVN_ERR(expect_error("/X/zulu", results, fs, pool));
+ apr_hash_clear(baton.results);
+ SVN_ERR(svn_fs_lock_many(fs, lock_paths, "comment", 0, 0, 0,
+ lock_many_cb, &baton,
+ pool, pool));
+
+ SVN_ERR(expect_lock("/A/B/E/alpha", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/B/E/beta", baton.results, fs, pool));
+ SVN_ERR(expect_error("/A/B/E/zulu", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/BB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/BBB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/D/G/pi", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/D/G/rho", baton.results, fs, pool));
+ SVN_ERR(expect_lock("/A/mu", baton.results, fs, pool));
+ SVN_ERR(expect_error("/X/zulu", baton.results, fs, pool));
/* Unlock without force. */
- for (hi = apr_hash_first(pool, results); hi; hi = apr_hash_next(hi))
+ for (hi = apr_hash_first(pool, baton.results); hi; hi = apr_hash_next(hi))
{
- result = svn__apr_hash_index_val(hi);
+ struct lock_result_t *result = svn__apr_hash_index_val(hi);
svn_hash_sets(unlock_paths, svn__apr_hash_index_key(hi),
result->lock ? result->lock->token : "non-existent-token");
}
- SVN_ERR(svn_fs_unlock2(&results, fs, unlock_paths, FALSE, pool, pool));
-
- SVN_ERR(expect_unlock("/A/B/E/alpha", results, fs, pool));
- SVN_ERR(expect_unlock("/A/B/E/beta", results, fs, pool));
- SVN_ERR(expect_error("/A/B/E/zulu", results, fs, pool));
- SVN_ERR(expect_unlock("/A/BB/mu", results, fs, pool));
- SVN_ERR(expect_unlock("/A/BBB/mu", results, fs, pool));
- SVN_ERR(expect_unlock("/A/D/G/pi", results, fs, pool));
- SVN_ERR(expect_unlock("/A/D/G/rho", results, fs, pool));
- SVN_ERR(expect_unlock("/A/mu", results, fs, pool));
- SVN_ERR(expect_error("/X/zulu", results, fs, pool));
+ apr_hash_clear(baton.results);
+ SVN_ERR(svn_fs_unlock_many(fs, unlock_paths, FALSE, lock_many_cb, &baton,
+ pool, pool));
+
+ SVN_ERR(expect_unlock("/A/B/E/alpha", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/B/E/beta", baton.results, fs, pool));
+ SVN_ERR(expect_error("/A/B/E/zulu", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/BB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/BBB/mu", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/D/G/pi", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/D/G/rho", baton.results, fs, pool));
+ SVN_ERR(expect_unlock("/A/mu", baton.results, fs, pool));
+ SVN_ERR(expect_error("/X/zulu", baton.results, fs, pool));
return SVN_NO_ERROR;
}
Re: svn commit: r1584114 [1/2] - in /subversion/trunk/subversion: include/ libsvn_fs/ libsvn_fs_base/ libsvn_fs_fs/ libsvn_fs_x/ libsvn_ra_local/ libsvn_repos/ mod_dav_svn/ svnserve/ tests/libsvn_fs/ tests/libsvn_ra/
Posted by Julian Foad <ju...@btopenworld.com>.
Philip Martin wrote:
> URL: http://svn.apache.org/r1584114
> Log:
> Convert the new multi-path lock and unlock functions to a callback API,
> rename from _lock2 and _unlock2 to _lock_many and _unlock_many.
> Modified: subversion/trunk/subversion/include/svn_fs.h
> ==============================================================================
> /** Lock the paths in @a targets in @a fs, and set @a *results to the
The old 'results' parameter no longer exists.
Same in _unlock_many() and in the two similar svn_repos.h functions.
- Julian