Author: rhuijben
Date: Tue Jun 5 10:51:22 2012
New Revision: 1346337
URL: http://svn.apache.org/viewvc?rev=1346337&view=rev
Log:
Make the copy helper code handle work items instead of temp paths. This allows
applying several optimizations that can't be handled on a higher layer. Reduce
the number of separate working queue items and the number of runs of the work
queue to boost copy performance.
* subversion/libsvn_wc/copy.c
(copy_to_tmpdir): Produce a working copy item. Take more arguments to make
a better decision on how to handle the copy.
(copy_versioned_file): Remove unused variable. Update caller. Only run the
queue if we do a notification now.
(copy_versioned_dir): Update caller. Only run the queue before producing a
notification. Collect workqueue items instead of installing them one at a
time.
(copy_or_move): Run the workqueue when done.
Modified:
subversion/trunk/subversion/libsvn_wc/copy.c
Modified: subversion/trunk/subversion/libsvn_wc/copy.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/copy.c?rev=1346337&r1=1346336&r2=1346337&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/copy.c (original)
+++ subversion/trunk/subversion/libsvn_wc/copy.c Tue Jun 5 10:51:22 2012
@@ -50,23 +50,32 @@
SRC_ABSPATH doesn't exist then set *DST_ABSPATH to NULL to indicate
that no copy was made. */
static svn_error_t *
-copy_to_tmpdir(const char **dst_abspath,
+copy_to_tmpdir(svn_skel_t **work_item,
svn_node_kind_t *kind,
+ svn_wc__db_t *db,
const char *src_abspath,
+ const char *dst_abspath,
const char *tmpdir_abspath,
- svn_boolean_t recursive,
+ svn_boolean_t file_copy,
+ svn_boolean_t unversioned,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_boolean_t is_special;
svn_io_file_del_t delete_when;
+ const char *dst_tmp_abspath;
+ svn_node_kind_t dsk_kind;
+ if (!kind)
+ kind = &dsk_kind;
+
+ *work_item = NULL;
SVN_ERR(svn_io_check_special_path(src_abspath, kind, &is_special,
scratch_pool));
if (*kind == svn_node_none)
{
- *dst_abspath = NULL;
return SVN_NO_ERROR;
}
else if (*kind == svn_node_unknown)
@@ -86,32 +95,64 @@ copy_to_tmpdir(const char **dst_abspath,
### handle the directory case and b) we need to be able to remove
### the cleanup before queueing the move work item. */
- /* Set DST_ABSPATH to a temporary unique path. If *KIND is file, leave a
- file there and then overwrite it; otherwise leave no node on disk at
+ if (file_copy && !unversioned)
+ {
+ svn_boolean_t modified;
+ /* It's faster to look for mods on the source now, as
+ the timestamp might match, than to examine the
+ destination later as the destination timestamp will
+ never match. */
+ SVN_ERR(svn_wc__internal_file_modified_p(&modified,
+ db, src_abspath,
+ FALSE, scratch_pool));
+ if (!modified)
+ {
+ /* Why create a temp copy if we can just reinstall from pristine? */
+ SVN_ERR(svn_wc__wq_build_file_install(work_item,
+ db, dst_abspath, NULL, FALSE,
+ TRUE,
+ result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+ }
+ }
+
+ /* Set DST_TMP_ABSPATH to a temporary unique path. If *KIND is file, leave
+ a file there and then overwrite it; otherwise leave no node on disk at
that path. In the latter case, something else might use that path
before we get around to using it a moment later, but never mind. */
- SVN_ERR(svn_io_open_unique_file3(NULL, dst_abspath, tmpdir_abspath,
+ SVN_ERR(svn_io_open_unique_file3(NULL, &dst_tmp_abspath, tmpdir_abspath,
delete_when, scratch_pool, scratch_pool));
if (*kind == svn_node_dir)
{
- if (recursive)
- SVN_ERR(svn_io_copy_dir_recursively(src_abspath,
- tmpdir_abspath,
- svn_dirent_basename(*dst_abspath,
- scratch_pool),
- TRUE, /* copy_perms */
- cancel_func, cancel_baton,
- scratch_pool));
+ if (file_copy)
+ SVN_ERR(svn_io_copy_dir_recursively(
+ src_abspath,
+ tmpdir_abspath,
+ svn_dirent_basename(dst_tmp_abspath, scratch_pool),
+ TRUE, /* copy_perms */
+ cancel_func, cancel_baton,
+ scratch_pool));
else
- SVN_ERR(svn_io_dir_make(*dst_abspath, APR_OS_DEFAULT, scratch_pool));
+ SVN_ERR(svn_io_dir_make(dst_tmp_abspath, APR_OS_DEFAULT,
scratch_pool));
}
else if (!is_special)
- SVN_ERR(svn_io_copy_file(src_abspath, *dst_abspath, TRUE, /* copy_perms */
+ SVN_ERR(svn_io_copy_file(src_abspath, dst_tmp_abspath,
+ TRUE /* copy_perms */,
scratch_pool));
else
- SVN_ERR(svn_io_copy_link(src_abspath, *dst_abspath, scratch_pool));
+ SVN_ERR(svn_io_copy_link(src_abspath, dst_tmp_abspath, scratch_pool));
+ if (file_copy)
+ {
+ /* Remove 'read-only' from the destination file; it's a local add now. */
+ SVN_ERR(svn_io_set_file_read_write(dst_tmp_abspath,
+ FALSE, scratch_pool));
+ }
+
+ SVN_ERR(svn_wc__wq_build_file_move(work_item, db, dst_abspath,
+ dst_tmp_abspath, dst_abspath,
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
}
@@ -150,7 +191,6 @@ copy_versioned_file(svn_wc__db_t *db,
apr_pool_t *scratch_pool)
{
svn_skel_t *work_items = NULL;
- const char *dir_abspath = svn_dirent_dirname(dst_abspath, scratch_pool);
/* In case we are copying from one WC to another (e.g. an external dir),
ensure the destination WC has a copy of the pristine text. */
@@ -165,10 +205,9 @@ copy_versioned_file(svn_wc__db_t *db,
copy recursively if it's a dir. */
if (!metadata_only)
{
- const char *tmp_dst_abspath;
- svn_node_kind_t disk_kind;
const char *my_src_abspath = NULL;
int i;
+ svn_boolean_t handle_as_unversioned = FALSE;
/* By default, take the copy source as given. */
my_src_abspath = src_abspath;
@@ -205,51 +244,20 @@ copy_versioned_file(svn_wc__db_t *db,
scratch_pool));
if (working_kind == svn_node_file)
- my_src_abspath = conflict_working;
- }
- }
-
- SVN_ERR(copy_to_tmpdir(&tmp_dst_abspath, &disk_kind, my_src_abspath,
- tmpdir_abspath,
- TRUE, /* recursive */
- cancel_func, cancel_baton, scratch_pool));
-
- if (tmp_dst_abspath)
- {
- svn_skel_t *work_item;
-
- SVN_ERR(svn_wc__wq_build_file_move(&work_item, db, dir_abspath,
- tmp_dst_abspath, dst_abspath,
- scratch_pool, scratch_pool));
- work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
-
- if (disk_kind == svn_node_file)
- {
- svn_boolean_t modified;
-
- /* Remove 'read-only' from the destination file;
- it's a local add now. */
- SVN_ERR(svn_io_set_file_read_write(tmp_dst_abspath,
- FALSE, scratch_pool));
-
- /* It's faster to look for mods on the source now, as
- the timestamp might match, than to examine the
- destination later as the destination timestamp will
- never match. */
- SVN_ERR(svn_wc__internal_file_modified_p(&modified,
- db, src_abspath,
- FALSE, scratch_pool));
- if (!modified)
{
- SVN_ERR(svn_wc__wq_build_record_fileinfo(&work_item,
- db, dst_abspath, 0,
- scratch_pool,
- scratch_pool));
- work_items = svn_wc__wq_merge(work_items, work_item,
- scratch_pool);
+ /* Don't perform unmodified/pristine optimization */
+ handle_as_unversioned = TRUE;
+ my_src_abspath = conflict_working;
}
}
}
+
+ SVN_ERR(copy_to_tmpdir(&work_items, NULL, db, my_src_abspath,
+ dst_abspath, tmpdir_abspath,
+ TRUE /* file_copy */,
+ handle_as_unversioned /* unversioned */,
+ cancel_func, cancel_baton,
+ scratch_pool, scratch_pool));
}
/* Copy the (single) node's metadata, and move the new filesystem node
@@ -257,8 +265,6 @@ copy_versioned_file(svn_wc__db_t *db,
SVN_ERR(svn_wc__db_op_copy(db, src_abspath, dst_abspath,
dst_op_root_abspath, is_move, work_items,
scratch_pool));
- SVN_ERR(svn_wc__wq_run(db, dir_abspath,
- cancel_func, cancel_baton, scratch_pool));
if (notify_func)
{
@@ -266,6 +272,11 @@ copy_versioned_file(svn_wc__db_t *db,
= svn_wc_create_notify(dst_abspath, svn_wc_notify_add,
scratch_pool);
notify->kind = svn_node_file;
+
+ /* When we notify that we performed a copy, make sure we already did */
+ if (work_items != NULL)
+ SVN_ERR(svn_wc__wq_run(db, dst_abspath,
+ cancel_func, cancel_baton, scratch_pool));
(*notify_func)(notify_baton, notify, scratch_pool);
}
return SVN_NO_ERROR;
@@ -307,20 +318,13 @@ copy_versioned_dir(svn_wc__db_t *db,
/* Prepare a temp copy of the single filesystem node (usually a dir). */
if (!metadata_only)
{
- const char *tmp_dst_abspath;
-
- SVN_ERR(copy_to_tmpdir(&tmp_dst_abspath, &disk_kind, src_abspath,
- tmpdir_abspath, FALSE, /* recursive */
- cancel_func, cancel_baton, scratch_pool));
- if (tmp_dst_abspath)
- {
- svn_skel_t *work_item;
-
- SVN_ERR(svn_wc__wq_build_file_move(&work_item, db, dir_abspath,
- tmp_dst_abspath, dst_abspath,
- scratch_pool, scratch_pool));
- work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
- }
+ SVN_ERR(copy_to_tmpdir(&work_items, &disk_kind,
+ db, src_abspath, dst_abspath,
+ tmpdir_abspath,
+ FALSE /* file_copy */,
+ FALSE /* unversioned */,
+ cancel_func, cancel_baton,
+ scratch_pool, scratch_pool));
}
/* Copy the (single) node's metadata, and move the new filesystem node
@@ -328,9 +332,6 @@ copy_versioned_dir(svn_wc__db_t *db,
SVN_ERR(svn_wc__db_op_copy(db, src_abspath, dst_abspath,
dst_op_root_abspath, is_move, work_items,
scratch_pool));
- if (work_items != NULL)
- SVN_ERR(svn_wc__wq_run(db, dir_abspath,
- cancel_func, cancel_baton, scratch_pool));
if (notify_func)
{
@@ -338,6 +339,12 @@ copy_versioned_dir(svn_wc__db_t *db,
= svn_wc_create_notify(dst_abspath, svn_wc_notify_add,
scratch_pool);
notify->kind = svn_node_dir;
+
+ /* When we notify that we performed a copy, make sure we already did */
+ if (work_items != NULL)
+ SVN_ERR(svn_wc__wq_run(db, dir_abspath,
+ cancel_func, cancel_baton, scratch_pool));
+
(*notify_func)(notify_baton, notify, scratch_pool);
}
@@ -466,12 +473,14 @@ copy_versioned_dir(svn_wc__db_t *db,
src_abspath, scratch_pool,
scratch_pool));
+ work_items = NULL;
+
for (hi = apr_hash_first(scratch_pool, disk_children); hi;
hi = apr_hash_next(hi))
{
const char *name = svn__apr_hash_index_key(hi);
const char *unver_src_abspath, *unver_dst_abspath;
- const char *tmp_dst_abspath;
+ svn_skel_t *work_item;
if (svn_wc_is_adm_dir(name, iterpool))
continue;
@@ -480,31 +489,23 @@ copy_versioned_dir(svn_wc__db_t *db,
apr_hash_get(marker_files, name, APR_HASH_KEY_STRING))
continue;
- svn_pool_clear(iterpool);
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
+ svn_pool_clear(iterpool);
unver_src_abspath = svn_dirent_join(src_abspath, name, iterpool);
unver_dst_abspath = svn_dirent_join(dst_abspath, name, iterpool);
- SVN_ERR(copy_to_tmpdir(&tmp_dst_abspath, &disk_kind,
- unver_src_abspath, tmpdir_abspath,
- TRUE, /* recursive */
- cancel_func, cancel_baton, iterpool));
- if (tmp_dst_abspath)
- {
- svn_skel_t *work_item;
- SVN_ERR(svn_wc__wq_build_file_move(&work_item, db, dir_abspath,
- tmp_dst_abspath,
- unver_dst_abspath,
- iterpool, iterpool));
- SVN_ERR(svn_wc__db_wq_add(db, dst_abspath, work_item,
- iterpool));
- }
+ SVN_ERR(copy_to_tmpdir(&work_item, NULL, db, unver_src_abspath,
+ unver_dst_abspath, tmpdir_abspath,
+ TRUE /* recursive */, TRUE /* unversioned */,
+ cancel_func, cancel_baton,
+ scratch_pool, iterpool));
+ if (work_item)
+ work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
}
- SVN_ERR(svn_wc__wq_run(db, dst_abspath, cancel_func, cancel_baton,
- scratch_pool));
+ SVN_ERR(svn_wc__db_wq_add(db, dst_abspath, work_items, iterpool));
}
svn_pool_destroy(iterpool);
@@ -744,6 +745,11 @@ copy_or_move(svn_wc_context_t *wc_ctx,
scratch_pool));
}
+ /* Run the work queue with the remaining work */
+ SVN_ERR(svn_wc__wq_run(db, dst_abspath,
+ cancel_func, cancel_baton,
+ scratch_pool));
+
return SVN_NO_ERROR;
}