Author: rhuijben
Date: Sun Feb 24 20:36:40 2013
New Revision: 1449546
URL: http://svn.apache.org/r1449546
Log:
Allow workqueue items to queue the recording of timestamps and sizes
until we already have a db write transaction open to mark the current
item as completed.
This saves at least 5% of every checkout on my testruns, which run on
a ramdrive. On harddisks or network drives the difference would be much
larger. (Assuming a very fast and/or local repository).
* subversion/libsvn_wc/workqueue.c
(work_item_baton_t): Add typedef.
(work_item_dispatch): Add argument to all workqueue functions.
(get_and_record_fileinfo): Change into prototype of function later
in the file. Take baton instead of db argument.
(run_base_remove,
run_file_commit,
run_postupgrade): Update arguments.
(run_file_install): Update arguments. Update caller.
(run_file_remove,
run_dir_remove,
run_file_move,
run_file_copy_translated,
run_dir_install,
run_sync_file_flags,
run_prej_install): Update arguments.
(run_record_fileinfo): Update arguments. Update caller.
(run_set_text_conflict_markers,
run_set_property_conflict_marker): Update arguments.
(dispatch_work_item): Update caller.
(svn_wc__wq_run): Create baton. Check if we should call the normal or the
extended svn_wc__db_wq_fetch_next. Update caller.
(get_and_record_fileinfo): New function.
Modified:
subversion/trunk/subversion/libsvn_wc/workqueue.c
Modified: subversion/trunk/subversion/libsvn_wc/workqueue.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/workqueue.c?rev=1449546&r1=1449545&r2=1449546&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/trunk/subversion/libsvn_wc/workqueue.c Sun Feb 24 20:36:40 2013
@@ -63,10 +63,12 @@
/* For work queue debugging. Generates output about its operation. */
/* #define SVN_DEBUG_WORK_QUEUE */
+typedef struct work_item_baton_t work_item_baton_t;
struct work_item_dispatch {
const char *name;
- svn_error_t *(*func)(svn_wc__db_t *db,
+ svn_error_t *(*func)(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -74,30 +76,12 @@ struct work_item_dispatch {
apr_pool_t *scratch_pool);
};
-
+/* Forward definition */
static svn_error_t *
-get_and_record_fileinfo(svn_wc__db_t *db,
+get_and_record_fileinfo(work_item_baton_t *wqb,
const char *local_abspath,
svn_boolean_t ignore_enoent,
- apr_pool_t *scratch_pool)
-{
- const svn_io_dirent2_t *dirent;
-
- SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, ignore_enoent,
- scratch_pool, scratch_pool));
-
- if (dirent->kind == svn_node_none)
- {
- /* Skip file not found if ignore_enoent */
- return SVN_NO_ERROR;
- }
-
- return svn_error_trace(svn_wc__db_global_record_fileinfo(
- db, local_abspath,
- dirent->filesize, dirent->mtime,
- scratch_pool));
-}
-
+ apr_pool_t *scratch_pool);
/* ------------------------------------------------------------------------ */
/* OP_REMOVE_BASE */
@@ -111,7 +95,8 @@ get_and_record_fileinfo(svn_wc__db_t *db
* See svn_wc__wq_build_remove_base() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_base_remove(svn_wc__db_t *db,
+run_base_remove(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -349,7 +334,8 @@ process_commit_file_install(svn_wc__db_t
static svn_error_t *
-run_file_commit(svn_wc__db_t *db,
+run_file_commit(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -397,7 +383,8 @@ svn_wc__wq_build_file_commit(svn_skel_t
/* OP_POSTUPGRADE */
static svn_error_t *
-run_postupgrade(svn_wc__db_t *db,
+run_postupgrade(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -465,7 +452,8 @@ svn_wc__wq_build_postupgrade(svn_skel_t
* See svn_wc__wq_build_file_install() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_install(svn_wc__db_t *db,
+run_file_install(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -665,7 +653,7 @@ run_file_install(svn_wc__db_t *db,
/* ### this should happen before we rename the file into place. */
if (record_fileinfo)
{
- SVN_ERR(get_and_record_fileinfo(db, local_abspath,
+ SVN_ERR(get_and_record_fileinfo(wqb, local_abspath,
FALSE /* ignore_enoent */,
scratch_pool));
}
@@ -717,12 +705,13 @@ svn_wc__wq_build_file_install(svn_skel_t
* See svn_wc__wq_build_file_remove() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_remove(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_file_remove(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg1 = work_item->children->next;
const char *local_relpath;
@@ -766,7 +755,8 @@ svn_wc__wq_build_file_remove(svn_skel_t
* See svn_wc__wq_build_file_remove() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_dir_remove(svn_wc__db_t *db,
+run_dir_remove(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -847,12 +837,13 @@ svn_wc__wq_build_dir_remove(svn_skel_t *
* See svn_wc__wq_build_file_move() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_move(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_file_move(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg1 = work_item->children->next;
const char *src_abspath, *dst_abspath;
@@ -929,7 +920,8 @@ svn_wc__wq_build_file_move(svn_skel_t **
* See run_file_copy_translated() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_file_copy_translated(svn_wc__db_t *db,
+run_file_copy_translated(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1023,12 +1015,13 @@ svn_wc__wq_build_file_copy_translated(sv
/* OP_DIRECTORY_INSTALL */
static svn_error_t *
-run_dir_install(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_dir_install(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg1 = work_item->children->next;
const char *local_relpath;
@@ -1072,7 +1065,8 @@ svn_wc__wq_build_dir_install(svn_skel_t
* See svn_wc__wq_build_sync_file_flags() which generates this work item.
* Implements (struct work_item_dispatch).func. */
static svn_error_t *
-run_sync_file_flags(svn_wc__db_t *db,
+run_sync_file_flags(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1117,7 +1111,8 @@ svn_wc__wq_build_sync_file_flags(svn_ske
/* OP_PREJ_INSTALL */
static svn_error_t *
-run_prej_install(svn_wc__db_t *db,
+run_prej_install(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1196,7 +1191,8 @@ svn_wc__wq_build_prej_install(svn_skel_t
static svn_error_t *
-run_record_fileinfo(svn_wc__db_t *db,
+run_record_fileinfo(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1241,7 +1237,7 @@ run_record_fileinfo(svn_wc__db_t *db,
}
- return svn_error_trace(get_and_record_fileinfo(db, local_abspath,
+ return svn_error_trace(get_and_record_fileinfo(wqb, local_abspath,
TRUE /* ignore_enoent */,
scratch_pool));
}
@@ -1252,12 +1248,13 @@ run_record_fileinfo(svn_wc__db_t *db,
static svn_error_t *
-run_set_text_conflict_markers(svn_wc__db_t *db,
- const svn_skel_t *work_item,
- const char *wri_abspath,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *scratch_pool)
+run_set_text_conflict_markers(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
+ const svn_skel_t *work_item,
+ const char *wri_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
{
const svn_skel_t *arg = work_item->children->next;
const char *local_relpath;
@@ -1346,7 +1343,8 @@ run_set_text_conflict_markers(svn_wc__db
/* OP_TMP_SET_PROPERTY_CONFLICT_MARKER */
static svn_error_t *
-run_set_property_conflict_marker(svn_wc__db_t *db,
+run_set_property_conflict_marker(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const svn_skel_t *work_item,
const char *wri_abspath,
svn_cancel_func_t cancel_func,
@@ -1432,9 +1430,19 @@ static const struct work_item_dispatch d
{ NULL }
};
+struct work_item_baton_t
+{
+ apr_pool_t *result_pool; /* Pool to allocate result in */
+
+ svn_boolean_t used; /* needs reset */
+
+ apr_hash_t *record_map; /* const char * -> svn_io_dirent2_t map */
+};
+
static svn_error_t *
-dispatch_work_item(svn_wc__db_t *db,
+dispatch_work_item(work_item_baton_t *wqb,
+ svn_wc__db_t *db,
const char *wri_abspath,
const svn_skel_t *work_item,
svn_cancel_func_t cancel_func,
@@ -1452,7 +1460,7 @@ dispatch_work_item(svn_wc__db_t *db,
#ifdef SVN_DEBUG_WORK_QUEUE
SVN_DBG(("dispatch: operation='%s'\n", scan->name));
#endif
- SVN_ERR((*scan->func)(db, work_item, wri_abspath,
+ SVN_ERR((*scan->func)(wqb, db, work_item, wri_abspath,
cancel_func, cancel_baton,
scratch_pool));
@@ -1497,6 +1505,8 @@ svn_wc__wq_run(svn_wc__db_t *db,
{
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
apr_uint64_t last_id = 0;
+ work_item_baton_t wib = { 0 };
+ wib.result_pool = svn_pool_create(scratch_pool);
#ifdef SVN_DEBUG_WORK_QUEUE
SVN_DBG(("wq_run: wri='%s'\n", wri_abspath));
@@ -1517,11 +1527,29 @@ svn_wc__wq_run(svn_wc__db_t *db,
svn_pool_clear(iterpool);
- /* Make sure to do this *early* in the loop iteration. There may
- be a LAST_ID that needs to be marked as completed, *before* we
- start worrying about anything else. */
- SVN_ERR(svn_wc__db_wq_fetch_next(&id, &work_item, db, wri_abspath,
- last_id, iterpool, iterpool));
+ if (! wib.used)
+ {
+ /* Make sure to do this *early* in the loop iteration. There may
+ be a LAST_ID that needs to be marked as completed, *before* we
+ start worrying about anything else. */
+ SVN_ERR(svn_wc__db_wq_fetch_next(&id, &work_item, db, wri_abspath,
+ last_id, iterpool, iterpool));
+ }
+ else
+ {
+ /* Make sure to do this *early* in the loop iteration. There may
+ be a LAST_ID that needs to be marked as completed, *before* we
+ start worrying about anything else. */
+ SVN_ERR(svn_wc__db_wq_record_and_fetch_next(&id, &work_item,
+ db, wri_abspath,
+ last_id, wib.record_map,
+ iterpool,
+ wib.result_pool));
+
+ svn_pool_clear(wib.result_pool);
+ wib.record_map = NULL;
+ wib.used = FALSE;
+ }
/* Stop work queue processing, if requested. A future 'svn cleanup'
should be able to continue the processing. Note that we may
@@ -1534,7 +1562,7 @@ svn_wc__wq_run(svn_wc__db_t *db,
if (work_item == NULL)
break;
- err = dispatch_work_item(db, wri_abspath, work_item,
+ err = dispatch_work_item(&wib, db, wri_abspath, work_item,
cancel_func, cancel_baton, iterpool);
if (err)
{
@@ -1604,3 +1632,29 @@ svn_wc__wq_merge(svn_skel_t *work_item1,
svn_skel__append(work_item1, work_item2->children);
return work_item1;
}
+
+
+static svn_error_t *
+get_and_record_fileinfo(work_item_baton_t *wqb,
+ const char *local_abspath,
+ svn_boolean_t ignore_enoent,
+ apr_pool_t *scratch_pool)
+{
+ const svn_io_dirent2_t *dirent;
+
+ SVN_ERR(svn_io_stat_dirent2(&dirent, local_abspath, FALSE, ignore_enoent,
+ wqb->result_pool, scratch_pool));
+
+ if (dirent->kind != svn_node_file)
+ return SVN_NO_ERROR;
+
+ wqb->used = TRUE;
+
+ if (! wqb->record_map)
+ wqb->record_map = apr_hash_make(wqb->result_pool);
+
+ svn_hash_sets(wqb->record_map, apr_pstrdup(wqb->result_pool, local_abspath),
+ dirent);
+
+ return SVN_NO_ERROR;
+}