You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2011/03/16 23:13:21 UTC
svn commit: r1082320 - in /subversion/trunk/subversion/libsvn_wc:
adm_crawler.c wc-queries.sql wc_db.c wc_db.h
Author: rhuijben
Date: Wed Mar 16 22:13:21 2011
New Revision: 1082320
URL: http://svn.apache.org/viewvc?rev=1082320&view=rev
Log:
Remove at least one more read transaction and in most cases a filestat for
every BASE node in a working copy when updating, by querying the data the
adm crawler needs per directory, like how philipm implemented that for
status a few months ago.
* subversion/libsvn_wc/adm_crawler.c
(report_revisions_and_depths): Use svn_wc__db_base_get_children_info instead
of svn_wc__db_base_get_children to avoid a svn_wc__db_base_get_info()
call for all nodes found.
* subversion/libsvn_wc/wc-queries.sql
(STMT_SELECT_BASE_CHILDREN_INFO): New query.
* subversion/libsvn_wc/wc_db.c
(svn_wc__db_base_get_children_info): New function.
* subversion/libsvn_wc/wc_db.h
(svn_wc__db_base_info_t): New struct.
(svn_wc__db_base_get_children_info): New function.
Modified:
subversion/trunk/subversion/libsvn_wc/adm_crawler.c
subversion/trunk/subversion/libsvn_wc/wc-queries.sql
subversion/trunk/subversion/libsvn_wc/wc_db.c
subversion/trunk/subversion/libsvn_wc/wc_db.h
Modified: subversion/trunk/subversion/libsvn_wc/adm_crawler.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/adm_crawler.c?rev=1082320&r1=1082319&r2=1082320&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/adm_crawler.c (original)
+++ subversion/trunk/subversion/libsvn_wc/adm_crawler.c Wed Mar 16 22:13:21 2011
@@ -285,10 +285,10 @@ report_revisions_and_depths(svn_wc__db_t
apr_pool_t *scratch_pool)
{
const char *dir_abspath;
- const apr_array_header_t *base_children;
+ apr_hash_t *base_children;
apr_hash_t *dirents;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- int i;
+ apr_hash_index_t *hi;
const char *dir_repos_root, *dir_repos_relpath;
svn_depth_t dir_depth;
svn_error_t *err;
@@ -298,8 +298,8 @@ report_revisions_and_depths(svn_wc__db_t
notice that we're picking up hidden entries too (read_children never
hides children). */
dir_abspath = svn_dirent_join(anchor_abspath, dir_path, scratch_pool);
- SVN_ERR(svn_wc__db_base_get_children(&base_children, db, dir_abspath,
- scratch_pool, iterpool));
+ SVN_ERR(svn_wc__db_base_get_children_info(&base_children, db, dir_abspath,
+ scratch_pool, iterpool));
err = svn_io_get_dirents3(&dirents, dir_abspath, TRUE,
scratch_pool, scratch_pool);
@@ -336,18 +336,21 @@ report_revisions_and_depths(svn_wc__db_t
external_baton, dir_depth, iterpool));
/* Looping over current directory's BASE children: */
- for (i = 0; i < base_children->nelts; ++i)
+ for (hi = apr_hash_first(scratch_pool, base_children);
+ hi != NULL;
+ hi = apr_hash_next(hi))
{
- const char *child = APR_ARRAY_IDX(base_children, i, const char *);
+ const char *child = svn__apr_hash_index_key(hi);
const char *this_path, *this_abspath;
- const char *this_repos_root_url, *this_repos_relpath;
- svn_wc__db_status_t this_status;
- svn_wc__db_kind_t this_kind;
- svn_revnum_t this_rev;
- svn_depth_t this_depth;
- svn_wc__db_lock_t *this_lock;
+
+ //svn_wc__db_status_t this_status;
+ //svn_wc__db_kind_t this_kind;
+ //svn_revnum_t this_rev;
+ //svn_depth_t this_depth;
+ //svn_wc__db_lock_t *this_lock;
svn_boolean_t this_switched = FALSE;
- svn_boolean_t this_file_external = FALSE;
+ //svn_boolean_t this_file_external = FALSE;
+ struct svn_wc__db_base_info_t *ths = svn__apr_hash_index_val(hi);
/* Clear the iteration subpool here because the loop has a bunch
of 'continue' jump statements. */
@@ -357,16 +360,16 @@ report_revisions_and_depths(svn_wc__db_t
this_path = svn_dirent_join(dir_path, child, iterpool);
this_abspath = svn_dirent_join(dir_abspath, child, iterpool);
- SVN_ERR(svn_wc__db_base_get_info(&this_status, &this_kind, &this_rev,
- &this_repos_relpath,
- &this_repos_root_url,
- NULL, NULL, NULL, NULL, NULL,
- &this_depth,
- NULL, NULL, NULL, &this_lock, NULL,
- db, this_abspath, iterpool, iterpool));
+ //SVN_ERR(svn_wc__db_base_get_info(&this_status, &this_kind, &this_rev,
+ // &this_repos_relpath,
+ // &this_repos_root_url,
+ // NULL, NULL, NULL, NULL, NULL,
+ // &this_depth,
+ // NULL, NULL, NULL, &this_lock, NULL,
+ // db, this_abspath, iterpool, iterpool));
/* First check for exclusion */
- if (this_status == svn_wc__db_status_excluded)
+ if (ths->status == svn_wc__db_status_excluded)
{
if (honor_depth_exclude)
{
@@ -399,8 +402,8 @@ report_revisions_and_depths(svn_wc__db_t
}
/*** The Big Tests: ***/
- if (this_status == svn_wc__db_status_absent
- || this_status == svn_wc__db_status_not_present)
+ if (ths->status == svn_wc__db_status_absent
+ || ths->status == svn_wc__db_status_not_present)
{
/* If the entry is 'absent' or 'not-present', make sure the server
knows it's gone...
@@ -459,55 +462,44 @@ report_revisions_and_depths(svn_wc__db_t
}
/* And finally prepare for reporting */
- if (!this_repos_relpath)
+ if (!ths->repos_relpath)
{
- this_repos_relpath = svn_relpath_join(dir_repos_relpath, child,
+ ths->repos_relpath = svn_relpath_join(dir_repos_relpath, child,
iterpool);
}
else
{
const char *childname = svn_relpath_is_child(dir_repos_relpath,
- this_repos_relpath,
+ ths->repos_relpath,
NULL);
if (childname == NULL || strcmp(childname, child) != 0)
{
- const char *file_ext_str;
-
this_switched = TRUE;
-
- /* This could be a file external! We need to know
- that. */
- SVN_ERR(svn_wc__db_temp_get_file_external(&file_ext_str, db,
- this_abspath,
- scratch_pool,
- scratch_pool));
- if (file_ext_str)
- this_file_external = TRUE;
}
}
/* Tweak THIS_DEPTH to a useful value. */
- if (this_depth == svn_depth_unknown)
- this_depth = svn_depth_infinity;
+ if (ths->depth == svn_depth_unknown)
+ ths->depth = svn_depth_infinity;
/* Obstructed nodes might report SVN_INVALID_REVNUM. Tweak it.
### it seems that obstructed nodes should be handled quite a
### bit differently. maybe reported as missing, like not-present
### or absent nodes? */
- if (!SVN_IS_VALID_REVNUM(this_rev))
- this_rev = dir_rev;
+ if (!SVN_IS_VALID_REVNUM(ths->revnum))
+ ths->revnum = dir_rev;
/*** File Externals **/
- if (this_file_external)
+ if (ths->update_root)
{
/* File externals are ... special. We ignore them. */;
}
/*** Files ***/
- else if (this_kind == svn_wc__db_kind_file ||
- this_kind == svn_wc__db_kind_symlink)
+ else if (ths->kind == svn_wc__db_kind_file ||
+ ths->kind == svn_wc__db_kind_symlink)
{
if (report_everything)
{
@@ -517,19 +509,19 @@ report_revisions_and_depths(svn_wc__db_t
this_path,
svn_path_url_add_component2(
dir_repos_root,
- this_repos_relpath, iterpool),
- this_rev,
- this_depth,
+ ths->repos_relpath, iterpool),
+ ths->revnum,
+ ths->depth,
FALSE,
- this_lock ? this_lock->token : NULL,
+ ths->lock ? ths->lock->token : NULL,
iterpool));
else
SVN_ERR(reporter->set_path(report_baton,
this_path,
- this_rev,
- this_depth,
+ ths->revnum,
+ ths->depth,
FALSE,
- this_lock ? this_lock->token : NULL,
+ ths->lock ? ths->lock->token : NULL,
iterpool));
}
@@ -539,40 +531,40 @@ report_revisions_and_depths(svn_wc__db_t
this_path,
svn_path_url_add_component2(
dir_repos_root,
- this_repos_relpath, iterpool),
- this_rev,
- this_depth,
+ ths->repos_relpath, iterpool),
+ ths->revnum,
+ ths->depth,
FALSE,
- this_lock ? this_lock->token : NULL,
+ ths->lock ? ths->lock->token : NULL,
iterpool));
/* ... or perhaps just a differing revision or lock token,
or the mere presence of the file in a depth-empty dir. */
- else if (this_rev != dir_rev
- || this_lock
+ else if (ths->revnum != dir_rev
+ || ths->lock
|| dir_depth == svn_depth_empty)
SVN_ERR(reporter->set_path(report_baton,
this_path,
- this_rev,
- this_depth,
+ ths->revnum,
+ ths->depth,
FALSE,
- this_lock ? this_lock->token : NULL,
+ ths->lock ? ths->lock->token : NULL,
iterpool));
} /* end file case */
/*** Directories (in recursive mode) ***/
- else if (this_kind == svn_wc__db_kind_dir
+ else if (ths->kind == svn_wc__db_kind_dir
&& (depth > svn_depth_files
|| depth == svn_depth_unknown))
{
svn_boolean_t is_incomplete;
svn_boolean_t start_empty;
- is_incomplete = (this_status == svn_wc__db_status_incomplete);
+ is_incomplete = (ths->status == svn_wc__db_status_incomplete);
start_empty = is_incomplete;
if (depth_compatibility_trick
- && this_depth <= svn_depth_files
- && depth > this_depth)
+ && ths->depth <= svn_depth_files
+ && depth > ths->depth)
{
start_empty = TRUE;
}
@@ -585,20 +577,20 @@ report_revisions_and_depths(svn_wc__db_t
this_path,
svn_path_url_add_component2(
dir_repos_root,
- this_repos_relpath, iterpool),
- this_rev,
- this_depth,
+ ths->repos_relpath, iterpool),
+ ths->revnum,
+ ths->depth,
start_empty,
- this_lock ? this_lock->token
+ ths->lock ? ths->lock->token
: NULL,
iterpool));
else
SVN_ERR(reporter->set_path(report_baton,
this_path,
- this_rev,
- this_depth,
+ ths->revnum,
+ ths->depth,
start_empty,
- this_lock ? this_lock->token : NULL,
+ ths->lock ? ths->lock->token : NULL,
iterpool));
}
else if (this_switched)
@@ -608,21 +600,21 @@ report_revisions_and_depths(svn_wc__db_t
this_path,
svn_path_url_add_component2(
dir_repos_root,
- this_repos_relpath, iterpool),
- this_rev,
- this_depth,
+ ths->repos_relpath, iterpool),
+ ths->revnum,
+ ths->depth,
start_empty,
- this_lock ? this_lock->token : NULL,
+ ths->lock ? ths->lock->token : NULL,
iterpool));
}
- else if (this_rev != dir_rev
- || this_lock
+ else if (ths->revnum != dir_rev
+ || ths->lock
|| is_incomplete
|| dir_depth == svn_depth_empty
|| dir_depth == svn_depth_files
|| (dir_depth == svn_depth_immediates
- && this_depth != svn_depth_empty)
- || (this_depth < svn_depth_infinity
+ && ths->depth != svn_depth_empty)
+ || (ths->depth < svn_depth_infinity
&& depth == svn_depth_infinity))
{
/* ... or perhaps just a differing revision, lock token,
@@ -633,10 +625,10 @@ report_revisions_and_depths(svn_wc__db_t
trying to set depth to infinity. */
SVN_ERR(reporter->set_path(report_baton,
this_path,
- this_rev,
- this_depth,
+ ths->revnum,
+ ths->depth,
start_empty,
- this_lock ? this_lock->token : NULL,
+ ths->lock ? ths->lock->token : NULL,
iterpool));
}
@@ -645,7 +637,7 @@ report_revisions_and_depths(svn_wc__db_t
SVN_ERR(report_revisions_and_depths(db,
anchor_abspath,
this_path,
- this_rev,
+ ths->revnum,
reporter, report_baton,
external_func, external_baton,
notify_func, notify_baton,
Modified: subversion/trunk/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc-queries.sql?rev=1082320&r1=1082319&r2=1082320&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/trunk/subversion/libsvn_wc/wc-queries.sql Wed Mar 16 22:13:21 2011
@@ -62,6 +62,15 @@ LEFT OUTER JOIN lock ON nodes.repos_id =
AND nodes.repos_path = lock.repos_relpath
WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
+-- STMT_SELECT_BASE_CHILDREN_INFO
+SELECT local_relpath, nodes.repos_id, nodes.repos_path, presence, kind,
+ revision, depth, file_external IS NOT NULL,
+ lock_token, lock_owner, lock_comment, lock_date
+FROM nodes
+LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id
+ AND nodes.repos_path = lock.repos_relpath
+WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0;
+
-- STMT_SELECT_WORKING_NODE
SELECT op_depth, presence, kind, checksum, translated_size,
changed_revision, changed_date, changed_author, depth, symlink_target,
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1082320&r1=1082319&r2=1082320&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Wed Mar 16 22:13:21 2011
@@ -1935,6 +1935,76 @@ svn_wc__db_base_get_info(svn_wc__db_stat
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_wc__db_base_get_children_info(apr_hash_t **nodes,
+ svn_wc__db_t *db,
+ const char *dir_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+ svn_sqlite__stmt_t *stmt;
+ svn_boolean_t have_row;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath));
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
+ dir_abspath, svn_sqlite__mode_readonly,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ *nodes = apr_hash_make(result_pool);
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+ STMT_SELECT_BASE_CHILDREN_INFO));
+ SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ while (have_row)
+ {
+ struct svn_wc__db_base_info_t *info;
+ svn_error_t *err;
+ apr_int64_t repos_id;
+ const char *depth_str;
+ const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+ const char *name = svn_relpath_basename(child_relpath, result_pool);
+
+ info = apr_pcalloc(result_pool, sizeof(*info));
+
+ repos_id = svn_sqlite__column_int64(stmt, 1);
+ info->repos_relpath = svn_sqlite__column_text(stmt, 2, result_pool);
+ info->status = svn_sqlite__column_token(stmt, 3, presence_map);
+ info->kind = svn_sqlite__column_token(stmt, 4, kind_map);
+ info->revnum = svn_sqlite__column_revnum(stmt, 5);
+
+ depth_str = svn_sqlite__column_text(stmt, 6, NULL);
+
+ info->depth = (depth_str != NULL) ? svn_depth_from_word(depth_str)
+ : svn_depth_unknown;
+ info->update_root = svn_sqlite__column_boolean(stmt, 7);
+
+ info->lock = lock_from_columns(stmt, 8, 9, 10, 11, result_pool);
+
+ err = fetch_repos_info(&info->repos_root_url, NULL, wcroot->sdb,
+ repos_id, result_pool);
+
+ if (err)
+ return svn_error_return(
+ svn_error_compose_create(err,
+ svn_sqlite__reset(stmt)));
+
+
+ apr_hash_set(*nodes, name, APR_HASH_KEY_STRING, info);
+
+ SVN_ERR(svn_sqlite__step(&have_row, stmt));
+ }
+
+ SVN_ERR(svn_sqlite__reset(stmt));
+
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_wc__db_base_get_prop(const svn_string_t **propval,
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1082320&r1=1082319&r2=1082320&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Wed Mar 16 22:13:21 2011
@@ -747,6 +747,29 @@ svn_wc__db_base_get_info(svn_wc__db_stat
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/* Structure returned by svn_wc__db_base_get_children_info. Only has the
+ fields needed by the adm crawler. */
+struct svn_wc__db_base_info_t {
+ svn_wc__db_status_t status;
+ svn_wc__db_kind_t kind;
+ svn_revnum_t revnum;
+ const char *repos_relpath;
+ const char *repos_root_url;
+ svn_depth_t depth;
+ svn_boolean_t update_root;
+ svn_wc__db_lock_t *lock;
+};
+
+/* Return in *NODES a hash mapping name->struct svn_wc__db_base_info_t for
+ the children of DIR_ABSPATH at op_depth 0.
+ */
+svn_error_t *
+svn_wc__db_base_get_children_info(apr_hash_t **nodes,
+ svn_wc__db_t *db,
+ const char *dir_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* Set *PROPVAL to the value of the property named PROPNAME of the node
LOCAL_ABSPATH in the BASE tree.