You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/05/08 18:43:18 UTC
svn commit: r1335628 [1/2] - in /subversion/branches/ev2-export: ./ build/
subversion/include/ subversion/libsvn_client/ subversion/libsvn_fs/
subversion/libsvn_fs_fs/ subversion/libsvn_ra_serf/ subversion/libsvn_subr/
subversion/tests/cmdline/ subvers...
Author: hwright
Date: Tue May 8 16:43:17 2012
New Revision: 1335628
URL: http://svn.apache.org/viewvc?rev=1335628&view=rev
Log:
On the ev2-export branch:
Out daily sync merge: bring up-to-date with trunk.
Modified:
subversion/branches/ev2-export/ (props changed)
subversion/branches/ev2-export/build/run_tests.py
subversion/branches/ev2-export/subversion/include/svn_io.h
subversion/branches/ev2-export/subversion/include/svn_ra.h
subversion/branches/ev2-export/subversion/libsvn_client/locking_commands.c
subversion/branches/ev2-export/subversion/libsvn_client/update.c
subversion/branches/ev2-export/subversion/libsvn_fs/editor.c
subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c
subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h
subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c
subversion/branches/ev2-export/subversion/libsvn_ra_serf/locks.c
subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h
subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c
subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c
subversion/branches/ev2-export/subversion/libsvn_subr/stream.c
subversion/branches/ev2-export/subversion/tests/cmdline/basic_tests.py
subversion/branches/ev2-export/subversion/tests/cmdline/lock_tests.py
subversion/branches/ev2-export/subversion/tests/cmdline/svnadmin_tests.py
subversion/branches/ev2-export/subversion/tests/cmdline/svntest/main.py
subversion/branches/ev2-export/win-tests.py
Propchange: subversion/branches/ev2-export/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1335225-1335623
Modified: subversion/branches/ev2-export/build/run_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/build/run_tests.py?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/build/run_tests.py (original)
+++ subversion/branches/ev2-export/build/run_tests.py Tue May 8 16:43:17 2012
@@ -453,6 +453,11 @@ class TestHarness:
if self.milestone_filter is not None:
svntest.main.options.milestone_filter = self.milestone_filter
if self.set_log_level is not None:
+ # Somehow the logger is not setup correctly from win-tests.py, so
+ # setting the log level would fail. ### Please fix
+ if svntest.main.logger is None:
+ import logging
+ svntest.main.logger = logging.getLogger()
svntest.main.logger.setLevel(self.set_log_level)
if self.svn_bin is not None:
svntest.main.options.svn_bin = self.svn_bin
Modified: subversion/branches/ev2-export/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_io.h?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_io.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_io.h Tue May 8 16:43:17 2012
@@ -1329,6 +1329,34 @@ svn_string_from_stream(svn_string_t **re
apr_pool_t *scratch_pool);
+/** A function type provided for use as a callback from
+ * @c svn_stream_lazyopen_create().
+ *
+ * @since New in 1.8.
+ */
+typedef svn_error_t *
+(*svn_stream_lazyopen_func_t)(svn_stream_t **stream,
+ void *baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+/** Set @a *stream to a generic stream which wraps another primary
+ * stream, delaying the "opening" of that stream until the first time
+ * the stream is accessed.
+ *
+ * @a open_func and @a open_baton are a callback function/baton pair
+ * invoked upon the first read of @a *stream which are used to open the
+ * "real" source stream.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_stream_lazyopen_create(svn_stream_t **stream,
+ svn_stream_lazyopen_func_t open_func,
+ void *open_baton,
+ apr_pool_t *result_pool);
+
/** @} */
/** Set @a *result to a string containing the contents of @a
Modified: subversion/branches/ev2-export/subversion/include/svn_ra.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/include/svn_ra.h?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/include/svn_ra.h (original)
+++ subversion/branches/ev2-export/subversion/include/svn_ra.h Tue May 8 16:43:17 2012
@@ -124,11 +124,14 @@ typedef svn_error_t *(*svn_ra_invalidate
* cached pristine file contents whose SHA1 checksum is @a
* sha1_checksum, if any. @a *contents will be a read stream
* containing those contents if they are found; NULL otherwise.
+ *
+ * @since New in 1.8.
*/
-typedef svn_error_t *(*svn_ra_get_wc_contents_func_t)(void *baton,
- svn_stream_t **contents,
- const svn_checksum_t *sha1_checksum,
- apr_pool_t *pool);
+typedef svn_error_t *
+(*svn_ra_get_wc_contents_func_t)(void *baton,
+ svn_stream_t **contents,
+ const svn_checksum_t *sha1_checksum,
+ apr_pool_t *pool);
/** A function type for retrieving the youngest revision from a repos. */
Modified: subversion/branches/ev2-export/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/locking_commands.c?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/locking_commands.c Tue May 8 16:43:17 2012
@@ -44,7 +44,7 @@
/* For use with store_locks_callback, below. */
struct lock_baton
{
- const char *base_path;
+ const char *base_dir_abspath;
apr_hash_t *urls_to_paths;
svn_client_ctx_t *ctx;
apr_pool_t *pool;
@@ -55,8 +55,8 @@ struct lock_baton
* BATON is a 'struct lock_baton *', PATH is the path being locked,
* and LOCK is the lock itself.
*
- * If BATON->base_path is not null, then this function either stores
- * the LOCK on REL_URL or removes any lock tokens from REL_URL
+ * If BATON->base_dir_abspath is not null, then this function either
+ * stores the LOCK on REL_URL or removes any lock tokens from REL_URL
* (depending on whether DO_LOCK is true or false respectively), but
* only if RA_ERR is null, or (in the unlock case) is something other
* than SVN_ERR_FS_LOCK_OWNER_MISMATCH.
@@ -86,20 +86,17 @@ store_locks_callback(void *baton,
notify->lock = lock;
notify->err = ra_err;
- if (lb->base_path)
+ if (lb->base_dir_abspath)
{
char *path = apr_hash_get(lb->urls_to_paths, rel_url,
APR_HASH_KEY_STRING);
const char *local_abspath;
- SVN_ERR(svn_dirent_get_absolute(&local_abspath,
- svn_dirent_join(lb->base_path,
- path, pool),
- pool));
+ local_abspath = svn_dirent_join(lb->base_dir_abspath, path, pool);
/* Notify a valid working copy path */
notify->path = local_abspath;
- notify->path_prefix = lb->base_path;
+ notify->path_prefix = lb->base_dir_abspath;
if (do_lock)
{
@@ -457,7 +454,7 @@ svn_client_lock(const apr_array_header_t
NULL, FALSE, FALSE,
ctx, pool));
- cb.base_path = base_dir;
+ cb.base_dir_abspath = base_dir_abspath;
cb.urls_to_paths = urls_to_paths;
cb.ctx = ctx;
cb.pool = pool;
@@ -504,7 +501,7 @@ svn_client_unlock(const apr_array_header
if (! base_dir && !break_lock)
SVN_ERR(fetch_tokens(ra_session, path_tokens, pool));
- cb.base_path = base_dir;
+ cb.base_dir_abspath = base_dir_abspath;
cb.urls_to_paths = urls_to_paths;
cb.ctx = ctx;
cb.pool = pool;
Modified: subversion/branches/ev2-export/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/update.c?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/update.c Tue May 8 16:43:17 2012
@@ -194,7 +194,7 @@ update_internal(svn_revnum_t *result_rev
const char *anchor_url;
const char *corrected_url;
const char *target;
- const char *repos_root;
+ const char *repos_root_url;
const char *repos_relpath;
svn_error_t *err;
svn_revnum_t revnum;
@@ -223,7 +223,7 @@ update_internal(svn_revnum_t *result_rev
target = "";
/* Check if our anchor exists in BASE. If it doesn't we can't update. */
- SVN_ERR(svn_wc__node_get_base(&revnum, &repos_relpath, &repos_root, NULL,
+ SVN_ERR(svn_wc__node_get_base(&revnum, &repos_relpath, &repos_root_url, NULL,
ctx->wc_ctx, anchor_abspath, pool, pool));
/* It does not make sense to update conflict victims. */
@@ -263,7 +263,8 @@ update_internal(svn_revnum_t *result_rev
_("'%s' has no URL"),
svn_dirent_local_style(anchor_abspath, pool));
- anchor_url = svn_path_url_add_component2(repos_root, repos_relpath, pool);
+ anchor_url = svn_path_url_add_component2(repos_root_url, repos_relpath,
+ pool);
/* We may need to crop the tree if the depth is sticky */
if (depth_is_sticky && depth < svn_depth_infinity)
@@ -340,18 +341,19 @@ update_internal(svn_revnum_t *result_rev
relocate our working copy first. */
if (corrected_url)
{
- const char *current_repos_root;
- const char *current_uuid;
+ const char *new_repos_root_url;
/* To relocate everything inside our repository we need the old and new
- repos root. ### And we should only perform relocates on the wcroot */
- SVN_ERR(svn_wc__node_get_repos_info(¤t_repos_root, ¤t_uuid,
- ctx->wc_ctx, anchor_abspath,
- pool, pool));
-
- /* ### Check uuid here before calling relocate? */
- SVN_ERR(svn_client_relocate2(anchor_abspath, current_repos_root,
- repos_root, ignore_externals, ctx, pool));
+ repos root. */
+ SVN_ERR(svn_ra_get_repos_root2(ra_session, &new_repos_root_url, pool));
+
+ /* svn_client_relocate2() will check the uuid */
+ SVN_ERR(svn_client_relocate2(anchor_abspath, repos_root_url,
+ new_repos_root_url, ignore_externals,
+ ctx, pool));
+
+ /* Store updated repository root for externals */
+ repos_root_url = new_repos_root_url;
anchor_url = corrected_url;
}
@@ -428,7 +430,7 @@ update_internal(svn_revnum_t *result_rev
SVN_ERR(svn_client__handle_externals(new_externals,
new_depths,
- repos_root, local_abspath,
+ repos_root_url, local_abspath,
depth, use_sleep,
ctx, pool));
}
Modified: subversion/branches/ev2-export/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/editor.c?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/editor.c Tue May 8 16:43:17 2012
@@ -216,53 +216,53 @@ can_modify(svn_fs_root_t *txn_root,
fspath);
#endif
- if (revision < created_rev)
+ if (revision < created_rev)
+ {
+ /* We asked to change a node that is *older* than what we found
+ in the transaction. The client is out of date. */
+ return svn_error_createf(SVN_ERR_FS_OUT_OF_DATE, NULL,
+ _("'%s' is out of date; try updating"),
+ fspath);
+ }
+
+ if (revision > created_rev)
+ {
+ /* We asked to change a node that is *newer* than what we found
+ in the transaction. Given that the transaction was based off
+ of 'youngest', then either:
+ - the caller asked to modify a future node
+ - the caller has committed more revisions since this txn
+ was constructed, and is asking to modify a node in one
+ of those new revisions.
+ In either case, the node may not have changed in those new
+ revisions; use the node's ID to determine this case. */
+ const svn_fs_id_t *txn_noderev_id;
+ svn_fs_root_t *rev_root;
+ const svn_fs_id_t *new_noderev_id;
+
+ /* The ID of the node that we would be modifying in the txn */
+ SVN_ERR(svn_fs_node_id(&txn_noderev_id, txn_root, fspath,
+ scratch_pool));
+
+ /* Get the ID from the future/new revision. */
+ SVN_ERR(svn_fs_revision_root(&rev_root, svn_fs_root_fs(txn_root),
+ revision, scratch_pool));
+ SVN_ERR(svn_fs_node_id(&new_noderev_id, rev_root, fspath,
+ scratch_pool));
+ svn_fs_close_root(rev_root);
+
+ /* Has the target node changed in the future? */
+ if (svn_fs_compare_ids(txn_noderev_id, new_noderev_id) != 0)
{
- /* We asked to change a node that is *older* than what we found
- in the transaction. The client is out of date. */
- return svn_error_createf(SVN_ERR_FS_OUT_OF_DATE, NULL,
- _("'%s' is out of date; try updating"),
+ /* Restarting the commit will base the txn on the future/new
+ revision, allowing the modification at REVISION. */
+ /* ### use a custom error code */
+ return svn_error_createf(SVN_ERR_FS_CONFLICT, NULL,
+ _("'%s' has been modified since the "
+ "commit began (restart the commit)"),
fspath);
}
-
- if (revision > created_rev)
- {
- /* We asked to change a node that is *newer* than what we found
- in the transaction. Given that the transaction was based off
- of 'youngest', then either:
- - the caller asked to modify a future node
- - the caller has committed more revisions since this txn
- was constructed, and is asking to modify a node in one
- of those new revisions.
- In either case, the node may not have changed in those new
- revisions; use the node's ID to determine this case. */
- const svn_fs_id_t *txn_noderev_id;
- svn_fs_root_t *rev_root;
- const svn_fs_id_t *new_noderev_id;
-
- /* The ID of the node that we would be modifying in the txn */
- SVN_ERR(svn_fs_node_id(&txn_noderev_id, txn_root, fspath,
- scratch_pool));
-
- /* Get the ID from the future/new revision. */
- SVN_ERR(svn_fs_revision_root(&rev_root, svn_fs_root_fs(txn_root),
- revision, scratch_pool));
- SVN_ERR(svn_fs_node_id(&new_noderev_id, rev_root, fspath,
- scratch_pool));
- svn_fs_close_root(rev_root);
-
- /* Has the target node changed in the future? */
- if (svn_fs_compare_ids(txn_noderev_id, new_noderev_id) != 0)
- {
- /* Restarting the commit will base the txn on the future/new
- revision, allowing the modification at REVISION. */
- /* ### use a custom error code */
- return svn_error_createf(SVN_ERR_FS_CONFLICT, NULL,
- _("'%s' has been modified since the "
- "commit began (restart the commit)"),
- fspath);
- }
- }
+ }
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c Tue May 8 16:43:17 2012
@@ -294,33 +294,18 @@ fs_hotcopy(svn_fs_t *src_fs,
void *cancel_baton,
apr_pool_t *pool)
{
- {
- svn_fs_t *fs = src_fs;
- const char *path = src_path;
-
- SVN_ERR(svn_fs__check_fs(fs, FALSE));
- SVN_ERR(initialize_fs_struct(fs));
- SVN_ERR(svn_fs_fs__open(fs, path, pool));
- SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
- SVN_ERR(fs_serialized_init(fs, pool, pool));
- }
-
- {
- svn_fs_t *fs = dst_fs;
-
- SVN_ERR(svn_fs__check_fs(fs, FALSE));
- SVN_ERR(initialize_fs_struct(fs));
-#if 0
- /* In INCREMENTAL mode, svn_fs_fs__hotcopy() will open DST_FS.
- Otherwise, it's not an FS yet --- possibly just an empty dir --- so
- can't be opened.
- */
- SVN_ERR(svn_fs_fs__open(fs, path, pool));
- SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
-#endif
- SVN_ERR(fs_serialized_init(fs, pool, pool));
- }
-
+ SVN_ERR(svn_fs__check_fs(src_fs, FALSE));
+ SVN_ERR(initialize_fs_struct(src_fs));
+ SVN_ERR(svn_fs_fs__open(src_fs, src_path, pool));
+ SVN_ERR(svn_fs_fs__initialize_caches(src_fs, pool));
+ SVN_ERR(fs_serialized_init(src_fs, pool, pool));
+
+ SVN_ERR(svn_fs__check_fs(dst_fs, FALSE));
+ SVN_ERR(initialize_fs_struct(dst_fs));
+ /* In INCREMENTAL mode, svn_fs_fs__hotcopy() will open DST_FS.
+ Otherwise, it's not an FS yet --- possibly just an empty dir --- so
+ can't be opened.
+ */
return svn_fs_fs__hotcopy(src_fs, dst_fs, src_path, dst_path,
incremental, cancel_func, cancel_baton, pool);
}
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h Tue May 8 16:43:17 2012
@@ -61,7 +61,7 @@ extern "C" {
#define PATH_LOCKS_DIR "locks" /* Directory of locks */
#define PATH_MIN_UNPACKED_REV "min-unpacked-rev" /* Oldest revision which
has not been packed. */
-#define PATH_REVPROP_GENERATION "revprop-geneneration"
+#define PATH_REVPROP_GENERATION "revprop-generation"
/* Current revprop generation*/
/* If you change this, look at tests/svn_test_fs.c(maybe_install_fsfs_conf) */
#define PATH_CONFIG "fsfs.conf" /* Configuration */
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c Tue May 8 16:43:17 2012
@@ -9199,6 +9199,15 @@ hotcopy_body(void *baton, apr_pool_t *po
SVN_ERR(svn_io_dir_file_copy(src_fs->path, dst_fs->path,
PATH_TXN_CURRENT, pool));
+ /* If a revprop generation file exists in the source filesystem,
+ * force a fresh revprop caching namespace for the destination by
+ * setting the generation to zero. We have no idea if the revprops
+ * we copied above really belong to the currently cached generation. */
+ SVN_ERR(svn_io_check_path(path_revprop_generation(src_fs, pool),
+ &kind, pool));
+ if (kind == svn_node_file)
+ SVN_ERR(write_revprop_generation_file(dst_fs, 0, pool));
+
/* Hotcopied FS is complete. Stamp it with a format file. */
SVN_ERR(write_format(svn_dirent_join(dst_fs->path, PATH_FORMAT, pool),
dst_ffd->format, max_files_per_dir, TRUE, pool));
@@ -9207,6 +9216,20 @@ hotcopy_body(void *baton, apr_pool_t *po
}
+/* Set up shared data between SRC_FS and DST_FS. */
+static void
+hotcopy_setup_shared_fs_data(svn_fs_t *src_fs, svn_fs_t *dst_fs)
+{
+ fs_fs_data_t *src_ffd = src_fs->fsap_data;
+ fs_fs_data_t *dst_ffd = dst_fs->fsap_data;
+
+ /* The common pool and mutexes are shared between src and dst filesystems.
+ * During hotcopy we only grab the mutexes for the destination, so there
+ * is no risk of dead-lock. We don't write to the src filesystem. Shared
+ * data for the src_fs has already been initialised in fs_hotcopy(). */
+ dst_ffd->shared = src_ffd->shared;
+}
+
/* Create an empty filesystem at DST_FS at DST_PATH with the same
* configuration as SRC_FS (uuid, format, and other parameters).
* After creation DST_FS has no revisions, not even revision zero. */
@@ -9282,6 +9305,10 @@ hotcopy_create_empty_dest(svn_fs_t *src_
}
dst_ffd->youngest_rev_cache = 0;
+
+ hotcopy_setup_shared_fs_data(src_fs, dst_fs);
+ SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
+
return SVN_NO_ERROR;
}
@@ -9323,6 +9350,8 @@ svn_fs_fs__hotcopy(svn_fs_t *src_fs,
SVN_ERR(svn_fs_fs__open(dst_fs, dst_path, pool));
SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs,
pool));
+ hotcopy_setup_shared_fs_data(src_fs, dst_fs);
+ SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
}
}
else
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c Tue May 8 16:43:17 2012
@@ -56,7 +56,6 @@ typedef struct checkout_context_t {
NULL for resources implicitly checked out (ie. an ancestor was
checked out). */
svn_ra_serf__handler_t *handler;
- svn_ra_serf__simple_request_context_t progress;
apr_pool_t *result_pool;
const char *activity_url;
@@ -113,7 +112,6 @@ typedef struct proppatch_context_t {
/* In HTTP v2, this is the file/directory version we think we're changing. */
svn_revnum_t base_revision;
- svn_ra_serf__simple_request_context_t progress;
} proppatch_context_t;
typedef struct delete_context_t {
@@ -125,7 +123,6 @@ typedef struct delete_context_t {
apr_hash_t *lock_token_hash;
svn_boolean_t keep_locks;
- svn_ra_serf__simple_request_context_t progress;
} delete_context_t;
/* Represents a directory. */
@@ -222,8 +219,7 @@ typedef struct file_context_t {
/* Setup routines and handlers for various requests we'll invoke. */
static svn_error_t *
-return_response_err(svn_ra_serf__handler_t *handler,
- svn_error_t *server_err)
+return_response_err(svn_ra_serf__handler_t *handler)
{
svn_error_t *err;
@@ -232,7 +228,9 @@ return_response_err(svn_ra_serf__handler
/* Ye Olde Fallback Error */
err = svn_error_compose_create(
- server_err,
+ handler->server_error != NULL
+ ? handler->server_error->error
+ : SVN_NO_ERROR,
svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("%s of '%s': %d %s"),
handler->method, handler->path,
@@ -290,8 +288,8 @@ handle_checkout(serf_request_t *request,
checkout_context_t *ctx = baton;
svn_ra_serf__handler_t *handler = ctx->handler;
- svn_error_t *err = svn_ra_serf__handle_status_only(request, response,
- &ctx->progress, pool);
+ svn_error_t *err = svn_ra_serf__expect_empty_body(request, response,
+ handler, pool);
/* These handler functions are supposed to return an APR_EOF status
wrapped in a svn_error_t to indicate to serf that the response was
@@ -301,7 +299,7 @@ handle_checkout(serf_request_t *request,
return err;
/* Get the resulting location. */
- if (ctx->progress.done && handler->sline.code == 201)
+ if (handler->done && handler->sline.code == 201)
{
serf_bucket_t *hdrs;
apr_uri_t uri;
@@ -366,7 +364,6 @@ checkout_dir(dir_context_t *dir)
checkout_ctx = apr_pcalloc(dir->pool, sizeof(*checkout_ctx));
checkout_ctx->handler = handler;
- checkout_ctx->progress.pool = dir->pool;
checkout_ctx->result_pool = dir->pool;
checkout_ctx->activity_url = dir->commit->activity_url;
@@ -395,11 +392,7 @@ checkout_dir(dir_context_t *dir)
handler->method = "CHECKOUT";
handler->path = checkout_url;
- svn_ra_serf__request_create(handler);
-
- err = svn_ra_serf__context_run_wait(&checkout_ctx->progress.done,
- dir->commit->session,
- dir->pool);
+ err = svn_ra_serf__context_run_one(handler, dir->pool);
if (err)
{
if (err->apr_err == SVN_ERR_FS_CONFLICT)
@@ -411,9 +404,7 @@ checkout_dir(dir_context_t *dir)
if (handler->sline.code != 201)
{
- return svn_error_trace(return_response_err(
- handler,
- checkout_ctx->progress.server_error.error));
+ return svn_error_trace(return_response_err(handler));
}
return SVN_NO_ERROR;
@@ -555,7 +546,6 @@ checkout_file(file_context_t *file)
file->checkout = apr_pcalloc(file->pool, sizeof(*file->checkout));
file->checkout->handler = handler;
- file->checkout->progress.pool = file->pool;
file->checkout->result_pool = file->pool;
file->checkout->activity_url = file->commit->activity_url;
@@ -574,14 +564,10 @@ checkout_file(file_context_t *file)
handler->method = "CHECKOUT";
handler->path = checkout_url;
- svn_ra_serf__request_create(handler);
-
/* There's no need to wait here as we only need this when we start the
* PROPPATCH or PUT of the file.
*/
- err = svn_ra_serf__context_run_wait(&file->checkout->progress.done,
- file->commit->session,
- file->pool);
+ err = svn_ra_serf__context_run_one(handler, file->pool);
if (err)
{
if (err->apr_err == SVN_ERR_FS_CONFLICT)
@@ -593,9 +579,7 @@ checkout_file(file_context_t *file)
if (handler->sline.code != 201)
{
- return svn_error_trace(return_response_err(
- handler,
- file->checkout->progress.server_error.error));
+ return svn_error_trace(return_response_err(handler));
}
return SVN_NO_ERROR;
@@ -960,11 +944,7 @@ proppatch_resource(proppatch_context_t *
{
return svn_error_create(
SVN_ERR_RA_DAV_PROPPATCH_FAILED,
- return_response_err(handler,
- handler->server_error != NULL
- ? handler->server_error->error
- : SVN_NO_ERROR
- ),
+ return_response_err(handler),
_("At least one property change failed; repository"
" is unchanged"));
}
@@ -1221,7 +1201,7 @@ setup_post_headers(serf_bucket_t *header
/* Handler baton for POST request. */
typedef struct post_response_ctx_t
{
- svn_ra_serf__simple_request_context_t *request_ctx;
+ svn_ra_serf__handler_t *handler;
commit_context_t *commit_ctx;
} post_response_ctx_t;
@@ -1266,14 +1246,15 @@ post_headers_iterator_callback(void *bat
/* A custom serf_response_handler_t which is mostly a wrapper around
- svn_ra_serf__handle_status_only -- it just notices POST response
+ svn_ra_serf__expect_empty_body -- it just notices POST response
headers, too.
+
Implements svn_ra_serf__response_handler_t */
static svn_error_t *
post_response_handler(serf_request_t *request,
serf_bucket_t *response,
void *baton,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
post_response_ctx_t *prc = baton;
serf_bucket_t *hdrs = serf_bucket_response_get_headers(response);
@@ -1282,8 +1263,8 @@ post_response_handler(serf_request_t *re
serf_bucket_headers_do(hdrs, post_headers_iterator_callback, prc);
/* Execute the 'real' response handler to XML-parse the repsonse body. */
- return svn_ra_serf__handle_status_only(request, response,
- prc->request_ctx, pool);
+ return svn_ra_serf__expect_empty_body(request, response,
+ prc->handler, scratch_pool);
}
@@ -1305,7 +1286,6 @@ open_root(void *edit_baton,
if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(ctx->session))
{
- svn_ra_serf__simple_request_context_t *post_ctx;
post_response_ctx_t *prc;
const char *rel_path;
@@ -1322,20 +1302,14 @@ open_root(void *edit_baton,
handler->conn = ctx->session->conns[0];
handler->session = ctx->session;
- post_ctx = apr_pcalloc(ctx->pool, sizeof(*post_ctx));
- post_ctx->pool = ctx->pool;
-
prc = apr_pcalloc(ctx->pool, sizeof(*prc));
- prc->request_ctx = post_ctx;
+ prc->handler = handler;
prc->commit_ctx = ctx;
handler->response_handler = post_response_handler;
handler->response_baton = prc;
- svn_ra_serf__request_create(handler);
-
- SVN_ERR(svn_ra_serf__context_run_wait(&post_ctx->done, ctx->session,
- ctx->pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, ctx->pool));
if (handler->sline.code != 201)
{
@@ -1388,7 +1362,6 @@ open_root(void *edit_baton,
else
{
svn_ra_serf__options_context_t *opt_ctx;
- svn_ra_serf__simple_request_context_t *mkact_ctx;
const char *activity_str;
SVN_ERR(svn_ra_serf__create_options_req(&opt_ctx, ctx->session,
@@ -1418,16 +1391,10 @@ open_root(void *edit_baton,
handler->conn = ctx->session->conns[0];
handler->session = ctx->session;
- mkact_ctx = apr_pcalloc(ctx->pool, sizeof(*mkact_ctx));
- mkact_ctx->pool = ctx->pool;
+ handler->response_handler = svn_ra_serf__expect_empty_body;
+ handler->response_baton = handler;
- handler->response_handler = svn_ra_serf__handle_status_only;
- handler->response_baton = mkact_ctx;
-
- svn_ra_serf__request_create(handler);
-
- SVN_ERR(svn_ra_serf__context_run_wait(&mkact_ctx->done, ctx->session,
- ctx->pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, ctx->pool));
if (handler->sline.code != 201)
{
@@ -1482,7 +1449,6 @@ open_root(void *edit_baton,
/* PROPPATCH our revprops and pass them along. */
proppatch_ctx = apr_pcalloc(ctx->pool, sizeof(*proppatch_ctx));
proppatch_ctx->pool = dir_pool;
- proppatch_ctx->progress.pool = dir_pool;
proppatch_ctx->commit = ctx;
proppatch_ctx->path = proppatch_target;
proppatch_ctx->changed_props = apr_hash_make(proppatch_ctx->pool);
@@ -1552,7 +1518,6 @@ delete_entry(const char *path,
/* DELETE our entry */
delete_ctx = apr_pcalloc(pool, sizeof(*delete_ctx));
- delete_ctx->progress.pool = pool;
delete_ctx->path = apr_pstrdup(pool, path);
delete_ctx->revision = revision;
delete_ctx->lock_token_hash = dir->commit->lock_tokens;
@@ -1563,8 +1528,8 @@ delete_entry(const char *path,
handler->session = dir->commit->session;
handler->conn = dir->commit->conn;
- handler->response_handler = svn_ra_serf__handle_status_only;
- handler->response_baton = &delete_ctx->progress;
+ handler->response_handler = svn_ra_serf__expect_empty_body;
+ handler->response_baton = handler;
handler->header_delegate = setup_delete_headers;
handler->header_delegate_baton = delete_ctx;
@@ -1572,10 +1537,7 @@ delete_entry(const char *path,
handler->method = "DELETE";
handler->path = delete_target;
- svn_ra_serf__request_create(handler);
-
- err = svn_ra_serf__context_run_wait(&delete_ctx->progress.done,
- dir->commit->session, pool);
+ err = svn_ra_serf__context_run_one(handler, pool);
if (err &&
(err->apr_err == SVN_ERR_FS_BAD_LOCK_TOKEN ||
@@ -1593,12 +1555,7 @@ delete_entry(const char *path,
handler->body_delegate_baton = delete_ctx;
handler->body_type = "text/xml";
- svn_ra_serf__request_create(handler);
-
- delete_ctx->progress.done = 0;
-
- SVN_ERR(svn_ra_serf__context_run_wait(&delete_ctx->progress.done,
- dir->commit->session, pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
}
else if (err)
{
@@ -1608,9 +1565,7 @@ delete_entry(const char *path,
/* 204 No Content: item successfully deleted */
if (handler->sline.code != 204)
{
- return svn_error_trace(return_response_err(
- handler,
- delete_ctx->progress.server_error.error));
+ return svn_error_trace(return_response_err(handler));
}
apr_hash_set(dir->commit->deleted_entries,
@@ -1631,7 +1586,6 @@ add_directory(const char *path,
dir_context_t *parent = parent_baton;
dir_context_t *dir;
svn_ra_serf__handler_t *handler;
- svn_ra_serf__simple_request_context_t *add_dir_ctx;
apr_status_t status;
const char *mkcol_target;
@@ -1672,11 +1626,8 @@ add_directory(const char *path,
handler->conn = dir->commit->conn;
handler->session = dir->commit->session;
- add_dir_ctx = apr_pcalloc(dir->pool, sizeof(*add_dir_ctx));
- add_dir_ctx->pool = dir->pool;
-
- handler->response_handler = svn_ra_serf__handle_status_only;
- handler->response_baton = add_dir_ctx;
+ handler->response_handler = svn_ra_serf__expect_empty_body;
+ handler->response_baton = handler;
if (!dir->copy_path)
{
handler->method = "MKCOL";
@@ -1710,10 +1661,7 @@ add_directory(const char *path,
handler->header_delegate_baton = dir;
}
- svn_ra_serf__request_create(handler);
-
- SVN_ERR(svn_ra_serf__context_run_wait(&add_dir_ctx->done,
- dir->commit->session, dir->pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, dir->pool));
switch (handler->sline.code)
{
@@ -1722,12 +1670,14 @@ add_directory(const char *path,
break;
case 403:
- SVN_ERR(add_dir_ctx->server_error.error);
+ if (handler->server_error)
+ SVN_ERR(handler->server_error->error);
return svn_error_createf(SVN_ERR_RA_DAV_FORBIDDEN, NULL,
_("Access to '%s' forbidden"),
handler->path);
default:
- SVN_ERR(add_dir_ctx->server_error.error);
+ if (handler->server_error)
+ SVN_ERR(handler->server_error->error);
return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("Adding directory failed: %s on %s "
"(%d %s)"),
@@ -1849,7 +1799,6 @@ close_directory(void *dir_baton,
proppatch_ctx = apr_pcalloc(pool, sizeof(*proppatch_ctx));
proppatch_ctx->pool = pool;
- proppatch_ctx->progress.pool = pool;
proppatch_ctx->commit = dir->commit;
proppatch_ctx->relpath = dir->relpath;
proppatch_ctx->changed_props = dir->changed_props;
@@ -1930,12 +1879,8 @@ add_file(const char *path,
if (! ((dir->added && !dir->copy_path) ||
(deleted_parent && deleted_parent[0] != '\0')))
{
- svn_ra_serf__simple_request_context_t *head_ctx;
svn_ra_serf__handler_t *handler;
- head_ctx = apr_pcalloc(new_file->pool, sizeof(*head_ctx));
- head_ctx->pool = new_file->pool;
-
handler = apr_pcalloc(new_file->pool, sizeof(*handler));
handler->handler_pool = new_file->pool;
handler->session = new_file->commit->session;
@@ -1944,13 +1889,10 @@ add_file(const char *path,
handler->path = svn_path_url_add_component2(
dir->commit->session->session_url.path,
path, new_file->pool);
- handler->response_handler = svn_ra_serf__handle_status_only;
- handler->response_baton = head_ctx;
- svn_ra_serf__request_create(handler);
-
- SVN_ERR(svn_ra_serf__context_run_wait(&head_ctx->done,
- new_file->commit->session,
- new_file->pool));
+ handler->response_handler = svn_ra_serf__expect_empty_body;
+ handler->response_baton = handler;
+
+ SVN_ERR(svn_ra_serf__context_run_one(handler, new_file->pool));
if (handler->sline.code != 404)
{
@@ -2095,7 +2037,6 @@ close_file(void *file_baton,
if (ctx->copy_path)
{
svn_ra_serf__handler_t *handler;
- svn_ra_serf__simple_request_context_t *copy_ctx;
apr_uri_t uri;
const char *rel_copy_path, *basecoll_url, *req_url;
@@ -2121,25 +2062,17 @@ close_file(void *file_baton,
handler->conn = ctx->commit->conn;
handler->session = ctx->commit->session;
- copy_ctx = apr_pcalloc(pool, sizeof(*copy_ctx));
- copy_ctx->pool = pool;
-
- handler->response_handler = svn_ra_serf__handle_status_only;
- handler->response_baton = copy_ctx;
+ handler->response_handler = svn_ra_serf__expect_empty_body;
+ handler->response_baton = handler;
handler->header_delegate = setup_copy_file_headers;
handler->header_delegate_baton = ctx;
- svn_ra_serf__request_create(handler);
-
- SVN_ERR(svn_ra_serf__context_run_wait(©_ctx->done,
- ctx->commit->session, pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
if (handler->sline.code != 201 && handler->sline.code != 204)
{
- return svn_error_trace(return_response_err(
- handler,
- copy_ctx->server_error.error));
+ return svn_error_trace(return_response_err(handler));
}
}
@@ -2153,7 +2086,6 @@ close_file(void *file_baton,
if (ctx->stream || put_empty_file)
{
svn_ra_serf__handler_t *handler;
- svn_ra_serf__simple_request_context_t *put_ctx;
handler = apr_pcalloc(pool, sizeof(*handler));
handler->handler_pool = pool;
@@ -2162,11 +2094,8 @@ close_file(void *file_baton,
handler->conn = ctx->commit->conn;
handler->session = ctx->commit->session;
- put_ctx = apr_pcalloc(pool, sizeof(*put_ctx));
- put_ctx->pool = pool;
-
- handler->response_handler = svn_ra_serf__handle_status_only;
- handler->response_baton = put_ctx;
+ handler->response_handler = svn_ra_serf__expect_empty_body;
+ handler->response_baton = handler;
if (put_empty_file)
{
@@ -2184,16 +2113,11 @@ close_file(void *file_baton,
handler->header_delegate = setup_put_headers;
handler->header_delegate_baton = ctx;
- svn_ra_serf__request_create(handler);
-
- SVN_ERR(svn_ra_serf__context_run_wait(&put_ctx->done,
- ctx->commit->session, pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
if (handler->sline.code != 204 && handler->sline.code != 201)
{
- return svn_error_trace(return_response_err(
- handler,
- put_ctx->server_error.error));
+ return svn_error_trace(return_response_err(handler));
}
}
@@ -2208,7 +2132,6 @@ close_file(void *file_baton,
proppatch = apr_pcalloc(ctx->pool, sizeof(*proppatch));
proppatch->pool = ctx->pool;
- proppatch->progress.pool = pool;
proppatch->relpath = ctx->relpath;
proppatch->path = ctx->url;
proppatch->commit = ctx->commit;
@@ -2228,7 +2151,6 @@ close_edit(void *edit_baton,
{
commit_context_t *ctx = edit_baton;
svn_ra_serf__merge_context_t *merge_ctx;
- svn_ra_serf__simple_request_context_t *delete_ctx;
svn_ra_serf__handler_t *handler;
svn_boolean_t *merge_done;
const char *merge_target =
@@ -2269,16 +2191,10 @@ close_edit(void *edit_baton,
handler->conn = ctx->conn;
handler->session = ctx->session;
- delete_ctx = apr_pcalloc(pool, sizeof(*delete_ctx));
- delete_ctx->pool = pool;
-
- handler->response_handler = svn_ra_serf__handle_status_only;
- handler->response_baton = delete_ctx;
+ handler->response_handler = svn_ra_serf__expect_empty_body;
+ handler->response_baton = handler;
- svn_ra_serf__request_create(handler);
-
- SVN_ERR(svn_ra_serf__context_run_wait(&delete_ctx->done, ctx->session,
- pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
SVN_ERR_ASSERT(handler->sline.code == 204);
}
@@ -2292,7 +2208,6 @@ abort_edit(void *edit_baton,
{
commit_context_t *ctx = edit_baton;
svn_ra_serf__handler_t *handler;
- svn_ra_serf__simple_request_context_t *delete_ctx;
/* If an activity or transaction wasn't even created, don't bother
trying to delete it. */
@@ -2310,21 +2225,15 @@ abort_edit(void *edit_baton,
handler->conn = ctx->session->conns[0];
handler->session = ctx->session;
- delete_ctx = apr_pcalloc(pool, sizeof(*delete_ctx));
- delete_ctx->pool = pool;
-
- handler->response_handler = svn_ra_serf__handle_status_only;
- handler->response_baton = delete_ctx;
+ handler->response_handler = svn_ra_serf__expect_empty_body;
+ handler->response_baton = handler;
if (USING_HTTPV2_COMMIT_SUPPORT(ctx)) /* HTTP v2 */
handler->path = ctx->txn_url;
else
handler->path = ctx->activity_url;
- svn_ra_serf__request_create(handler);
-
- SVN_ERR(svn_ra_serf__context_run_wait(&delete_ctx->done, ctx->session,
- pool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
/* 204 if deleted,
403 if DELETE was forbidden (indicates MKACTIVITY was forbidden too),
@@ -2483,7 +2392,6 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
/* PROPPATCH our log message and pass it along. */
proppatch_ctx = apr_pcalloc(pool, sizeof(*proppatch_ctx));
proppatch_ctx->pool = pool;
- proppatch_ctx->progress.pool = pool;
proppatch_ctx->commit = commit;
proppatch_ctx->path = proppatch_target;
proppatch_ctx->changed_props = apr_hash_make(proppatch_ctx->pool);
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/locks.c?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/locks.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/locks.c Tue May 8 16:43:17 2012
@@ -72,8 +72,6 @@ typedef struct lock_info_t {
svn_ra_serf__handler_t *handler;
- /* are we done? */
- svn_boolean_t done;
} lock_info_t;
@@ -331,6 +329,42 @@ set_lock_headers(serf_bucket_t *headers,
return APR_SUCCESS;
}
+
+/* Register an error within the session. If something is already there,
+ then it will take precedence. */
+static svn_error_t *
+determine_error(svn_ra_serf__handler_t *handler,
+ svn_error_t *err)
+{
+ /* If we found an error in the response, then blend it in. */
+ if (handler->server_error)
+ {
+ /* Client-side error takes precedence. */
+ err = svn_error_compose_create(err, handler->server_error->error);
+ }
+ else
+ {
+ apr_status_t errcode;
+
+ if (handler->sline.code == 423)
+ errcode = SVN_ERR_FS_PATH_ALREADY_LOCKED;
+ else if (handler->sline.code == 403)
+ errcode = SVN_ERR_RA_DAV_FORBIDDEN;
+ else
+ return err;
+
+ /* The server did not send us a detailed human-readable error.
+ Provide a generic error. */
+ err = svn_error_createf(errcode, err,
+ _("Lock request failed: %d %s"),
+ handler->sline.code,
+ handler->sline.reason);
+ }
+
+ return err;
+}
+
+
/* Implements svn_ra_serf__response_handler_t */
static svn_error_t *
handle_lock(serf_request_t *request,
@@ -340,30 +374,24 @@ handle_lock(serf_request_t *request,
{
svn_ra_serf__xml_parser_t *xml_ctx = handler_baton;
lock_info_t *ctx = xml_ctx->user_data;
- svn_error_t *err;
+
+ /* 403 (Forbidden) when a lock doesn't exist.
+ 423 (Locked) when a lock already exists. */
+ if (ctx->handler->sline.code == 403
+ || ctx->handler->sline.code == 423)
+ {
+ /* Go look in the body for a server-provided error. This will
+ reset flags for the core handler to Do The Right Thing. We
+ won't be back to this handler again. */
+ return svn_error_trace(svn_ra_serf__expect_empty_body(
+ request, response, ctx->handler, pool));
+ }
if (ctx->read_headers == FALSE)
{
serf_bucket_t *headers;
const char *val;
- /* 423 == Locked */
- if (ctx->handler->sline.code == 423)
- {
- /* Older servers may not give a descriptive error, so we'll
- make one of our own if we can't find one in the response. */
- err = svn_ra_serf__handle_server_error(request, response, pool);
- if (!err)
- {
- err = svn_error_createf(SVN_ERR_FS_PATH_ALREADY_LOCKED,
- NULL,
- _("Lock request failed: %d %s"),
- ctx->handler->sline.code,
- ctx->handler->sline.reason);
- }
- return err;
- }
-
headers = serf_bucket_response_get_headers(response);
val = serf_bucket_headers_get(headers, SVN_DAV_LOCK_OWNER_HEADER);
@@ -382,24 +410,6 @@ handle_lock(serf_request_t *request,
ctx->read_headers = TRUE;
}
- /* Forbidden when a lock doesn't exist. */
- if (ctx->handler->sline.code == 403)
- {
- /* If we get an "unexpected EOF" error, we'll wrap it with
- generic request failure error. */
- err = svn_ra_serf__handle_discard_body(request, response, NULL, pool);
- if (err && APR_STATUS_IS_EOF(err->apr_err))
- {
- ctx->done = TRUE;
- err = svn_error_createf(SVN_ERR_RA_DAV_FORBIDDEN,
- err,
- _("Lock request failed: %d %s"),
- ctx->handler->sline.code,
- ctx->handler->sline.reason);
- }
- return err;
- }
-
return svn_ra_serf__handle_xml_parser(request, response,
handler_baton, pool);
}
@@ -513,7 +523,7 @@ svn_ra_serf__get_lock(svn_ra_session_t *
parser_ctx->start = start_lock;
parser_ctx->end = end_lock;
parser_ctx->cdata = cdata_lock;
- parser_ctx->done = &lock_ctx->done;
+ parser_ctx->done = &handler->done;
handler->body_delegate = create_getlock_body;
handler->body_delegate_baton = lock_ctx;
@@ -526,8 +536,8 @@ svn_ra_serf__get_lock(svn_ra_session_t *
lock_ctx->handler = handler;
- svn_ra_serf__request_create(handler);
- err = svn_ra_serf__context_run_wait(&lock_ctx->done, session, pool);
+ err = svn_ra_serf__context_run_one(handler, pool);
+ err = determine_error(handler, err);
if (handler->sline.code == 404)
{
@@ -608,7 +618,7 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
parser_ctx->start = start_lock;
parser_ctx->end = end_lock;
parser_ctx->cdata = cdata_lock;
- parser_ctx->done = &lock_ctx->done;
+ parser_ctx->done = &handler->done;
handler->header_delegate = set_lock_headers;
handler->header_delegate_baton = lock_ctx;
@@ -621,8 +631,8 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
lock_ctx->handler = handler;
- svn_ra_serf__request_create(handler);
- err = svn_ra_serf__context_run_wait(&lock_ctx->done, session, iterpool);
+ err = svn_ra_serf__context_run_one(handler, iterpool);
+ err = determine_error(handler, err);
if (lock_func)
new_err = lock_func(lock_baton, lock_ctx->path, TRUE, lock_ctx->lock,
@@ -674,13 +684,15 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
iterpool = svn_pool_create(scratch_pool);
/* ### TODO for issue 2263: Send all the locks over the wire at once. This
- loop is just a temporary shim. */
+ ### loop is just a temporary shim.
+ ### an alternative, which is backwards-compat with all servers is to
+ ### pipeline these requests. ie. stop using run_wait/run_one. */
+
for (hi = apr_hash_first(scratch_pool, path_tokens);
hi;
hi = apr_hash_next(hi))
{
svn_ra_serf__handler_t *handler;
- svn_ra_serf__simple_request_context_t *ctx;
const char *req_url, *path, *token;
svn_lock_t *existing_lock = NULL;
struct unlock_context_t unlock_ctx;
@@ -690,9 +702,6 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
svn_pool_clear(iterpool);
- ctx = apr_pcalloc(iterpool, sizeof(*ctx));
- ctx->pool = iterpool;
-
path = svn__apr_hash_index_key(hi);
token = svn__apr_hash_index_val(hi);
@@ -743,11 +752,10 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
handler->header_delegate = set_unlock_headers;
handler->header_delegate_baton = &unlock_ctx;
- handler->response_handler = svn_ra_serf__handle_status_only;
- handler->response_baton = ctx;
+ handler->response_handler = svn_ra_serf__expect_empty_body;
+ handler->response_baton = handler;
- svn_ra_serf__request_create(handler);
- SVN_ERR(svn_ra_serf__context_run_wait(&ctx->done, session, iterpool));
+ SVN_ERR(svn_ra_serf__context_run_one(handler, iterpool));
switch (handler->sline.code)
{
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h Tue May 8 16:43:17 2012
@@ -456,6 +456,11 @@ typedef struct svn_ra_serf__handler_t {
/* Internal flag to indicate we've parsed the headers. */
svn_boolean_t reading_body;
+ /* When this flag will be set, the core handler will discard any unread
+ portion of the response body. The registered response handler will
+ no longer be called. */
+ svn_boolean_t discard_body;
+
/* Pool for allocating SLINE.REASON and LOCATION. If this pool is NULL,
then the requestor does not care about SLINE and LOCATION. */
apr_pool_t *handler_pool;
@@ -659,29 +664,6 @@ struct svn_ra_serf__server_error_t {
svn_ra_serf__xml_parser_t parser;
};
-/* A simple request context that can be passed to handle_status_only. */
-typedef struct svn_ra_serf__simple_request_context_t {
- apr_pool_t *pool;
-
- /* This value is set to TRUE when the response is completed. */
- svn_boolean_t done;
-
- /* If an error occurred, this value will be initialized. */
- svn_ra_serf__server_error_t server_error;
-} svn_ra_serf__simple_request_context_t;
-
-/*
- * Serf handler for @a request / @a response pair that takes in a
- * @a baton (@see svn_ra_serf__simple_request_context_t).
- * Implements svn_ra_serf__response_handler_t.
- *
- * Temporary allocations are made in @a pool.
- */
-svn_error_t *
-svn_ra_serf__handle_status_only(serf_request_t *request,
- serf_bucket_t *response,
- void *baton,
- apr_pool_t *pool);
/*
* Handler that discards the entire @a response body associated with a
@@ -698,16 +680,6 @@ svn_ra_serf__handle_discard_body(serf_re
void *baton,
apr_pool_t *pool);
-/*
- * Handler that retrieves the embedded XML error response from the
- * the @a response body associated with a @a request.
- *
- * All temporary allocations will be made in a @a pool.
- */
-svn_error_t *
-svn_ra_serf__handle_server_error(serf_request_t *request,
- serf_bucket_t *response,
- apr_pool_t *pool);
/*
* Handler that retrieves the embedded XML multistatus response from the
@@ -726,6 +698,28 @@ svn_ra_serf__handle_multistatus_only(ser
void *baton,
apr_pool_t *scratch_pool);
+
+/* Handler that expects an empty body.
+
+ If a body IS present, and it is text/xml, then it will be parsed for
+ a server-side error.
+
+ BATON should be the svn_ra_serf__handler_t running REQUEST.
+
+ Status line information will be in HANDLER->SLINE.
+
+ Any parsed errors will be left in HANDLER->SERVER_ERROR. That member
+ may be NULL if no body was present, or a problem occurred trying to
+ parse the body.
+
+ All temporary allocations will be made in SCRATCH_POOL. */
+svn_error_t *
+svn_ra_serf__expect_empty_body(serf_request_t *request,
+ serf_bucket_t *response,
+ void *baton,
+ apr_pool_t *scratch_pool);
+
+
/*
* This function will feed the RESPONSE body into XMLP. When parsing is
* completed (i.e. an EOF is received), *DONE is set to TRUE.
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c?rev=1335628&r1=1335627&r2=1335628&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c Tue May 8 16:43:17 2012
@@ -256,6 +256,9 @@ typedef struct report_info_t
*/
typedef struct report_fetch_t {
+ /* The handler representing this particular fetch. */
+ svn_ra_serf__handler_t *handler;
+
/* The session we should use to fetch the file. */
svn_ra_serf__session_t *sess;
@@ -805,6 +808,105 @@ error_fetch(serf_request_t *request,
return err;
}
+/* Wield the editor referenced by INFO to open (or add) the file
+ file also associated with INFO, setting properties on the file and
+ calling the editor's apply_textdelta() function on it if necessary
+ (or if FORCE_APPLY_TEXTDELTA is set).
+
+ Callers will probably want to also see the function that serves
+ the opposite purpose of this one, close_updated_file(). */
+static svn_error_t *
+open_updated_file(report_info_t *info,
+ svn_boolean_t force_apply_textdelta,
+ apr_pool_t *scratch_pool)
+{
+ const svn_delta_editor_t *update_editor = info->dir->update_editor;
+
+ /* Ensure our parent is open. */
+ SVN_ERR(open_dir(info->dir));
+ info->editor_pool = svn_pool_create(info->dir->dir_baton_pool);
+
+ /* Expand our full name now if we haven't done so yet. */
+ if (!info->name)
+ {
+ info->name = svn_relpath_join(info->dir->name, info->base_name,
+ info->editor_pool);
+ }
+
+ /* Open (or add) the file. */
+ if (SVN_IS_VALID_REVNUM(info->base_rev))
+ {
+ SVN_ERR(update_editor->open_file(info->name,
+ info->dir->dir_baton,
+ info->base_rev,
+ info->editor_pool,
+ &info->file_baton));
+ }
+ else
+ {
+ SVN_ERR(update_editor->add_file(info->name,
+ info->dir->dir_baton,
+ info->copyfrom_path,
+ info->copyfrom_rev,
+ info->editor_pool,
+ &info->file_baton));
+ }
+
+ /* Check for lock information. */
+ if (info->lock_token)
+ check_lock(info);
+
+ /* Set all of the properties we received */
+ SVN_ERR(svn_ra_serf__walk_all_props(info->props,
+ info->base_name,
+ info->base_rev,
+ set_file_props, info,
+ scratch_pool));
+ SVN_ERR(svn_ra_serf__walk_all_props(info->dir->removed_props,
+ info->base_name,
+ info->base_rev,
+ remove_file_props, info,
+ scratch_pool));
+ if (info->fetch_props)
+ {
+ SVN_ERR(svn_ra_serf__walk_all_props(info->props,
+ info->url,
+ info->target_rev,
+ set_file_props, info,
+ scratch_pool));
+ }
+
+ /* Get (maybe) a textdelta window handler for transmitting file
+ content changes. */
+ if (info->fetch_file || force_apply_textdelta)
+ {
+ SVN_ERR(update_editor->apply_textdelta(info->file_baton,
+ info->base_checksum,
+ info->editor_pool,
+ &info->textdelta,
+ &info->textdelta_baton));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Close the file associated with INFO->file_baton, and cleanup other
+ bits of that structure managed by open_updated_file(). */
+static svn_error_t *
+close_updated_file(report_info_t *info,
+ apr_pool_t *scratch_pool)
+{
+ /* Close the file via the editor. */
+ SVN_ERR(info->dir->update_editor->close_file(info->file_baton,
+ info->final_checksum,
+ scratch_pool));
+
+ /* We're done with our editor pool. */
+ svn_pool_destroy(info->editor_pool);
+
+ return SVN_NO_ERROR;
+}
+
/* Implements svn_ra_serf__response_handler_t */
static svn_error_t *
handle_fetch(serf_request_t *request,
@@ -817,7 +919,9 @@ handle_fetch(serf_request_t *request,
apr_status_t status;
report_fetch_t *fetch_ctx = handler_baton;
svn_error_t *err;
- serf_status_line sl;
+
+ /* ### new field. make sure we didn't miss some initialization. */
+ SVN_ERR_ASSERT(fetch_ctx->handler != NULL);
if (fetch_ctx->read_headers == FALSE)
{
@@ -829,50 +933,8 @@ handle_fetch(serf_request_t *request,
val = serf_bucket_headers_get(hdrs, "Content-Type");
info = fetch_ctx->info;
- err = open_dir(info->dir);
- if (err)
- {
- return error_fetch(request, fetch_ctx, err);
- }
-
- info->editor_pool = svn_pool_create(info->dir->dir_baton_pool);
-
- /* Expand our full name now if we haven't done so yet. */
- if (!info->name)
- {
- info->name = svn_relpath_join(info->dir->name, info->base_name,
- info->editor_pool);
- }
-
- if (SVN_IS_VALID_REVNUM(info->base_rev))
- {
- err = info->dir->update_editor->open_file(info->name,
- info->dir->dir_baton,
- info->base_rev,
- info->editor_pool,
- &info->file_baton);
- }
- else
- {
- err = info->dir->update_editor->add_file(info->name,
- info->dir->dir_baton,
- info->copyfrom_path,
- info->copyfrom_rev,
- info->editor_pool,
- &info->file_baton);
- }
-
- if (err)
- {
- return error_fetch(request, fetch_ctx, err);
- }
-
- err = info->dir->update_editor->apply_textdelta(info->file_baton,
- info->base_checksum,
- info->editor_pool,
- &info->textdelta,
- &info->textdelta_baton);
-
+ /* Open the file for editing. */
+ err = open_updated_file(info, FALSE, info->pool);
if (err)
{
return error_fetch(request, fetch_ctx, err);
@@ -895,16 +957,12 @@ handle_fetch(serf_request_t *request,
/* If the error code wasn't 200, something went wrong. Don't use the returned
data as its probably an error message. Just bail out instead. */
- status = serf_bucket_response_status(response, &sl);
- if (SERF_BUCKET_READ_ERROR(status))
- {
- return svn_error_wrap_apr(status, NULL);
- }
- if (sl.code != 200)
+ if (fetch_ctx->handler->sline.code != 200)
{
err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("GET request failed: %d %s"),
- sl.code, sl.reason);
+ fetch_ctx->handler->sline.code,
+ fetch_ctx->handler->sline.reason);
return error_fetch(request, fetch_ctx, err);
}
@@ -987,51 +1045,17 @@ handle_fetch(serf_request_t *request,
{
report_info_t *info = fetch_ctx->info;
- /* ### this doesn't feel quite right. but it gets tossed at the
- ### end of this block, so it will work for now. */
- apr_pool_t *scratch_pool = info->editor_pool;
-
if (fetch_ctx->delta_stream)
err = svn_error_trace(svn_stream_close(fetch_ctx->delta_stream));
else
err = svn_error_trace(info->textdelta(NULL,
info->textdelta_baton));
-
if (err)
{
return error_fetch(request, fetch_ctx, err);
}
- if (info->lock_token)
- check_lock(info);
-
- /* set all of the properties we received */
- err = svn_ra_serf__walk_all_props(info->props,
- info->base_name,
- info->base_rev,
- set_file_props, info,
- scratch_pool);
-
- if (!err)
- err = svn_ra_serf__walk_all_props(info->dir->removed_props,
- info->base_name,
- info->base_rev,
- remove_file_props, info,
- scratch_pool);
- if (!err && info->fetch_props)
- {
- err = svn_ra_serf__walk_all_props(info->props,
- info->url,
- info->target_rev,
- set_file_props, info,
- scratch_pool);
- }
-
- if (!err)
- err = info->dir->update_editor->close_file(info->file_baton,
- info->final_checksum,
- scratch_pool);
-
+ err = close_updated_file(info, info->pool);
if (err)
{
return svn_error_trace(error_fetch(request, fetch_ctx, err));
@@ -1043,8 +1067,7 @@ handle_fetch(serf_request_t *request,
fetch_ctx->done_item.next = *fetch_ctx->done_list;
*fetch_ctx->done_list = &fetch_ctx->done_item;
- /* We're done with our pools. */
- svn_pool_destroy(info->editor_pool);
+ /* We're done with our pool. */
svn_pool_destroy(info->pool);
if (status)
@@ -1066,26 +1089,22 @@ handle_stream(serf_request_t *request,
apr_pool_t *pool)
{
report_fetch_t *fetch_ctx = handler_baton;
- serf_status_line sl;
const char *location;
svn_error_t *err;
apr_status_t status;
- status = serf_bucket_response_status(response, &sl);
- if (SERF_BUCKET_READ_ERROR(status))
- {
- return svn_error_wrap_apr(status, NULL);
- }
+ /* ### new field. make sure we didn't miss some initialization. */
+ SVN_ERR_ASSERT(fetch_ctx->handler != NULL);
/* Woo-hoo. Nothing here to see. */
location = svn_ra_serf__response_get_location(response, pool);
- err = svn_ra_serf__error_on_status(sl.code,
+ err = svn_ra_serf__error_on_status(fetch_ctx->handler->sline.code,
fetch_ctx->info->name,
location);
if (err)
{
- fetch_ctx->done = TRUE;
+ fetch_ctx->handler->done = TRUE;
err = svn_error_compose_create(
err,
@@ -1161,71 +1180,13 @@ static svn_error_t *
handle_propchange_only(report_info_t *info,
apr_pool_t *scratch_pool)
{
- /* Ensure our parent is open. */
- SVN_ERR(open_dir(info->dir));
-
- info->editor_pool = svn_pool_create(info->dir->dir_baton_pool);
-
- /* Expand our full name now if we haven't done so yet. */
- if (!info->name)
- {
- info->name = svn_relpath_join(info->dir->name, info->base_name,
- info->editor_pool);
- }
-
- if (SVN_IS_VALID_REVNUM(info->base_rev))
- {
- SVN_ERR(info->dir->update_editor->open_file(info->name,
- info->dir->dir_baton,
- info->base_rev,
- info->editor_pool,
- &info->file_baton));
- }
- else
- {
- SVN_ERR(info->dir->update_editor->add_file(info->name,
- info->dir->dir_baton,
- info->copyfrom_path,
- info->copyfrom_rev,
- info->editor_pool,
- &info->file_baton));
- }
-
- if (info->fetch_file)
- {
- SVN_ERR(info->dir->update_editor->apply_textdelta(info->file_baton,
- info->base_checksum,
- info->editor_pool,
- &info->textdelta,
- &info->textdelta_baton));
- }
-
- if (info->lock_token)
- check_lock(info);
-
- /* set all of the properties we received */
- SVN_ERR(svn_ra_serf__walk_all_props(info->props,
- info->base_name, info->base_rev,
- set_file_props, info,
- scratch_pool));
- SVN_ERR(svn_ra_serf__walk_all_props(info->dir->removed_props,
- info->base_name, info->base_rev,
- remove_file_props, info,
- scratch_pool));
- if (info->fetch_props)
- {
- SVN_ERR(svn_ra_serf__walk_all_props(info->props, info->url,
- info->target_rev,
- set_file_props, info,
- scratch_pool));
- }
-
- SVN_ERR(info->dir->update_editor->close_file(info->file_baton,
- info->final_checksum,
- scratch_pool));
-
- /* We're done with our pools. */
- svn_pool_destroy(info->editor_pool);
+ /* Open the file for editing (without forcing an apply_textdelta),
+ pass along any propchanges we've recorded for it, and then close
+ the file. */
+ SVN_ERR(open_updated_file(info, FALSE, scratch_pool));
+ SVN_ERR(close_updated_file(info, scratch_pool));
+
+ /* We're done with our pool. */
svn_pool_destroy(info->pool);
info->dir->ref_count--;
@@ -1238,80 +1199,18 @@ handle_propchange_only(report_info_t *in
server), and feed the information through the associated update
editor. */
static svn_error_t *
-local_fetch(report_info_t *info)
+local_fetch(report_info_t *info,
+ apr_pool_t *scratch_pool)
{
- const svn_delta_editor_t *update_editor = info->dir->update_editor;
+ SVN_ERR(open_updated_file(info, TRUE, scratch_pool));
- SVN_ERR(open_dir(info->dir));
- info->editor_pool = svn_pool_create(info->dir->dir_baton_pool);
-
- /* Expand our full name now if we haven't done so yet. */
- if (!info->name)
- {
- info->name = svn_relpath_join(info->dir->name, info->base_name,
- info->editor_pool);
- }
-
- if (SVN_IS_VALID_REVNUM(info->base_rev))
- {
- SVN_ERR(update_editor->open_file(info->name,
- info->dir->dir_baton,
- info->base_rev,
- info->editor_pool,
- &info->file_baton));
- }
- else
- {
- SVN_ERR(update_editor->add_file(info->name,
- info->dir->dir_baton,
- info->copyfrom_path,
- info->copyfrom_rev,
- info->editor_pool,
- &info->file_baton));
- }
-
- SVN_ERR(update_editor->apply_textdelta(info->file_baton,
- info->base_checksum,
- info->editor_pool,
- &info->textdelta,
- &info->textdelta_baton));
-
SVN_ERR(svn_txdelta_send_stream(info->cached_contents, info->textdelta,
- info->textdelta_baton, NULL, info->pool));
-
+ info->textdelta_baton, NULL, scratch_pool));
SVN_ERR(svn_stream_close(info->cached_contents));
info->cached_contents = NULL;
+ SVN_ERR(close_updated_file(info, scratch_pool));
- if (info->lock_token)
- check_lock(info);
-
- /* set all of the properties we received */
- SVN_ERR(svn_ra_serf__walk_all_props(info->props,
- info->base_name,
- info->base_rev,
- set_file_props, info,
- info->pool));
-
- SVN_ERR(svn_ra_serf__walk_all_props(info->dir->removed_props,
- info->base_name,
- info->base_rev,
- remove_file_props, info,
- info->pool));
- if (info->fetch_props)
- {
- SVN_ERR(svn_ra_serf__walk_all_props(info->props,
- info->url,
- info->target_rev,
- set_file_props, info,
- info->pool));
- }
-
- SVN_ERR(info->dir->update_editor->close_file(info->file_baton,
- info->final_checksum,
- info->pool));
-
- /* We're done with our pools. */
- svn_pool_destroy(info->editor_pool);
+ /* We're done with our pool. */
svn_pool_destroy(info->pool);
return SVN_NO_ERROR;
@@ -1326,23 +1225,21 @@ handle_local_fetch(serf_request_t *reque
{
report_fetch_t *fetch_ctx = handler_baton;
apr_status_t status;
- serf_status_line sl;
svn_error_t *err;
const char *data;
apr_size_t len;
+ /* ### new field. make sure we didn't miss some initialization. */
+ SVN_ERR_ASSERT(fetch_ctx->handler != NULL);
+
/* If the error code wasn't 200, something went wrong. Don't use the returned
data as its probably an error message. Just bail out instead. */
- status = serf_bucket_response_status(response, &sl);
- if (SERF_BUCKET_READ_ERROR(status))
- {
- return svn_error_wrap_apr(status, NULL);
- }
- if (sl.code != 200)
+ if (fetch_ctx->handler->sline.code != 200)
{
err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("HEAD request failed: %d %s"),
- sl.code, sl.reason);
+ fetch_ctx->handler->sline.code,
+ fetch_ctx->handler->sline.reason);
return error_fetch(request, fetch_ctx, err);
}
@@ -1355,7 +1252,7 @@ handle_local_fetch(serf_request_t *reque
}
if (APR_STATUS_IS_EOF(status))
{
- err = local_fetch(fetch_ctx->info);
+ err = local_fetch(fetch_ctx->info, fetch_ctx->info->pool);
if (err)
{
return error_fetch(request, fetch_ctx, err);
@@ -1474,6 +1371,8 @@ fetch_file(report_context_t *ctx, report
handler->response_handler = handle_local_fetch;
handler->response_baton = fetch_ctx;
+ fetch_ctx->handler = handler;
+
svn_ra_serf__request_create(handler);
ctx->active_fetches++;
@@ -1506,6 +1405,8 @@ fetch_file(report_context_t *ctx, report
handler->response_error = cancel_fetch;
handler->response_error_baton = fetch_ctx;
+ fetch_ctx->handler = handler;
+
svn_ra_serf__request_create(handler);
ctx->active_fetches++;
@@ -3074,6 +2975,8 @@ svn_ra_serf__get_file(svn_ra_session_t *
handler->response_error = cancel_fetch;
handler->response_error_baton = stream_ctx;
+ stream_ctx->handler = handler;
+
svn_ra_serf__request_create(handler);
SVN_ERR(svn_ra_serf__context_run_wait(&stream_ctx->done, session, pool));