Author: rhuijben
Date: Tue Nov 27 10:53:16 2012
New Revision: 1414123
URL: http://svn.apache.org/viewvc?rev=1414123&view=rev
Log:
In preparation for further performance improvements, make the retrieval of
inherited properties use a constant number of db operations.
This function is currently used from 'svn status' for every directory that
contains unversioned nodes, which makes it performance critical.
* subversion/libsvn_wc/props.c
(filter_unwanted_props): Move to wc_db.c.
(svn_wc__internal_get_iprops): Move to wc_db.c.
(svn_wc__get_iprops): Wrap svn_wc__internal_get_iprops.
* subversion/libsvn_wc/wc.h
(svn_wc__internal_get_iprops): Remove function.
* subversion/libsvn_wc/wc_db.c
(includes): Add svn_sorts.h.
(filter_unwanted_props): Moved here from props.c
(read_inherited_props_baton_t): New struct.
(db_read_inherited_props): New function, based on
the old svn_wc__internal_get_iprops.
(svn_wc__db_read_inherited_props): New function.
* subversion/libsvn_wc/wc_db.h
(svn_wc__db_read_inherited_props): New function.
Modified:
subversion/trunk/subversion/libsvn_wc/props.c
subversion/trunk/subversion/libsvn_wc/status.c
subversion/trunk/subversion/libsvn_wc/wc.h
subversion/trunk/subversion/libsvn_wc/wc_db.c
subversion/trunk/subversion/libsvn_wc/wc_db.h
Modified: subversion/trunk/subversion/libsvn_wc/props.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/props.c?rev=1414123&r1=1414122&r2=1414123&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/props.c (original)
+++ subversion/trunk/subversion/libsvn_wc/props.c Tue Nov 27 10:53:16 2012
@@ -2338,132 +2338,6 @@ svn_wc__has_magic_property(const apr_arr
return FALSE;
}
-/* Remove all prop name value pairs from PROP_HASH where the property
- name is not PROPNAME. */
-static void
-filter_unwanted_props(apr_hash_t *prop_hash,
- const char * propname,
- apr_pool_t *scratch_pool)
-{
- apr_hash_index_t *hi;
-
- for (hi = apr_hash_first(scratch_pool, prop_hash);
- hi;
- hi = apr_hash_next(hi))
- {
- const char *ipropname = svn__apr_hash_index_key(hi);
-
- if (strcmp(ipropname, propname) != 0)
- apr_hash_set(prop_hash, ipropname, APR_HASH_KEY_STRING, NULL);
- }
- return;
-}
-
-svn_error_t *
-svn_wc__internal_get_iprops(apr_array_header_t **inherited_props,
- svn_wc__db_t *db,
- const char *local_abspath,
- const char *propname,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- int i;
- apr_array_header_t *cached_iprops = NULL;
- const char *parent_abspath = local_abspath;
- svn_boolean_t is_wc_root = FALSE;
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-
- SVN_ERR_ASSERT(inherited_props);
- *inherited_props = apr_array_make(result_pool, 1,
- sizeof(svn_prop_inherited_item_t *));
-
- /* Walk up to the root of the WC looking for inherited properties. When we
- reach the WC root also check for cached inherited properties. */
- while (TRUE)
- {
- apr_hash_t *actual_props;
- svn_boolean_t is_switched;
-
- svn_pool_clear(iterpool);
-
- SVN_ERR(svn_wc__db_is_switched(&is_wc_root, &is_switched, NULL,
- db, parent_abspath, iterpool));
-
- if (is_switched || is_wc_root)
- {
- is_wc_root = TRUE;
-
- /* If the WC root is also the root of the repository then by
- definition there are no inheritable properties to be had,
- but checking for that is just as expensive as fetching them
- anyway. */
-
- /* Grab the cached inherited properties for the WC root. */
- SVN_ERR(svn_wc__db_read_cached_iprops(&cached_iprops, db,
- parent_abspath,
- scratch_pool, iterpool));
- }
-
- /* If PARENT_ABSPATH is a true parent of LOCAL_ABSPATH, then
- LOCAL_ABSPATH can inherit properties from it. */
- if (strcmp(local_abspath, parent_abspath) != 0)
- {
- SVN_ERR(svn_wc__db_read_props(&actual_props, db, parent_abspath,
- result_pool, iterpool));
- if (actual_props)
- {
- /* If we only want PROPNAME filter out any other properties. */
- if (propname)
- filter_unwanted_props(actual_props, propname, iterpool);
-
- if (apr_hash_count(actual_props))
- {
- svn_prop_inherited_item_t *iprop_elt =
- apr_pcalloc(result_pool,
- sizeof(svn_prop_inherited_item_t));
- iprop_elt->path_or_url = apr_pstrdup(result_pool,
- parent_abspath);
- iprop_elt->prop_hash = actual_props;
- /* Build the output array in depth-first order. */
- svn_sort__array_insert(&iprop_elt, *inherited_props, 0);
- }
- }
- }
-
- /* Inheritance only goes as far as the nearest WC root. */
- if (is_wc_root)
- break;
-
- /* Keep looking for the WC root. */
- parent_abspath = svn_dirent_dirname(parent_abspath, scratch_pool);
- }
-
- if (cached_iprops)
- {
- for (i = cached_iprops->nelts - 1; i >= 0; i--)
- {
- svn_prop_inherited_item_t *cached_iprop =
- APR_ARRAY_IDX(cached_iprops, i, svn_prop_inherited_item_t *);
-
- /* An empty property hash in the iprops cache means there are no
- inherited properties. */
- if (apr_hash_count(cached_iprop->prop_hash) == 0)
- continue;
-
- if (propname)
- filter_unwanted_props(cached_iprop->prop_hash, propname,
- scratch_pool);
-
- /* If we didn't filter everything then keep this iprop. */
- if (apr_hash_count(cached_iprop->prop_hash))
- svn_sort__array_insert(&cached_iprop, *inherited_props, 0);
- }
- }
-
- svn_pool_destroy(iterpool);
- return SVN_NO_ERROR;
-}
-
svn_error_t *
svn_wc__get_iprops(apr_array_header_t **inherited_props,
svn_wc_context_t *wc_ctx,
@@ -2472,9 +2346,11 @@ svn_wc__get_iprops(apr_array_header_t **
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- return svn_error_trace(svn_wc__internal_get_iprops(inherited_props,
wc_ctx->db,
- local_abspath, propname,
- result_pool, scratch_pool));
+ return svn_error_trace(
+ svn_wc__db_read_inherited_props(inherited_props,
+ wc_ctx->db, local_abspath,
+ propname,
+ result_pool, scratch_pool));
}
svn_error_t *
Modified: subversion/trunk/subversion/libsvn_wc/status.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/status.c?rev=1414123&r1=1414122&r2=1414123&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/status.c (original)
+++ subversion/trunk/subversion/libsvn_wc/status.c Tue Nov 27 10:53:16 2012
@@ -1028,9 +1028,10 @@ collect_ignore_patterns(apr_array_header
FALSE, result_pool);
}
- SVN_ERR(svn_wc__internal_get_iprops(&inherited_props, db, local_abspath,
- SVN_PROP_INHERITABLE_IGNORES,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__db_read_inherited_props(&inherited_props,
+ db, local_abspath,
+ SVN_PROP_INHERITABLE_IGNORES,
+ scratch_pool, scratch_pool));
for (i = 0; i < inherited_props->nelts; i++)
{
apr_hash_index_t *hi;
Modified: subversion/trunk/subversion/libsvn_wc/wc.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc.h?rev=1414123&r1=1414122&r2=1414123&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc.h Tue Nov 27 10:53:16 2012
@@ -607,15 +607,6 @@ svn_wc__internal_get_repos_relpath(const
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
-/* Internal version of svn_wc__get_iprops() */
-svn_error_t *
-svn_wc__internal_get_iprops(apr_array_header_t **inherited_props,
- svn_wc__db_t *db,
- const char *local_abspath,
- const char *propname,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool);
-
/* Upgrade the wc sqlite database given in SDB for the wc located at
WCROOT_ABSPATH. It's current/starting format is given by START_FORMAT.
After the upgrade is complete (to as far as the automatic upgrade will
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.c?rev=1414123&r1=1414122&r2=1414123&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.c Tue Nov 27 10:53:16 2012
@@ -32,6 +32,7 @@
#include "svn_dirent_uri.h"
#include "svn_path.h"
#include "svn_hash.h"
+#include "svn_sorts.h"
#include "svn_wc.h"
#include "svn_checksum.h"
#include "svn_pools.h"
@@ -9060,6 +9061,175 @@ svn_wc__db_read_cached_iprops(apr_array_
return SVN_NO_ERROR;
}
+/* Remove all prop name value pairs from PROP_HASH where the property
+ name is not PROPNAME. */
+static void
+filter_unwanted_props(apr_hash_t *prop_hash,
+ const char * propname,
+ apr_pool_t *scratch_pool)
+{
+ apr_hash_index_t *hi;
+
+ for (hi = apr_hash_first(scratch_pool, prop_hash);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *ipropname = svn__apr_hash_index_key(hi);
+
+ if (strcmp(ipropname, propname) != 0)
+ apr_hash_set(prop_hash, ipropname, APR_HASH_KEY_STRING, NULL);
+ }
+ return;
+}
+
+/* Baton for db_read_inherited_props */
+struct read_inherited_props_baton_t
+{
+ apr_array_header_t *iprops;
+ svn_wc__db_t *db;
+ const char *local_abspath;
+ const char *propname;
+ apr_pool_t *result_pool;
+};
+
+/* Implements svn_wc__db_txn_callback_t for svn_wc__db_read_inherited_props */
+static svn_error_t *
+db_read_inherited_props(void *baton,
+ svn_wc__db_wcroot_t *wcroot,
+ const char *local_relpath,
+ apr_pool_t *scratch_pool)
+{
+ struct read_inherited_props_baton_t *ripb = baton;
+ int i;
+ apr_array_header_t *cached_iprops = NULL;
+ const char *parent_abspath = ripb->local_abspath;
+ svn_boolean_t is_wc_root = FALSE;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_pool_t *result_pool = ripb->result_pool;
+ svn_wc__db_t *db = ripb->db;
+
+ ripb->iprops = apr_array_make(ripb->result_pool, 1,
+ sizeof(svn_prop_inherited_item_t *));
+
+ /* Walk up to the root of the WC looking for inherited properties. When we
+ reach the WC root also check for cached inherited properties. */
+ while (TRUE)
+ {
+ apr_hash_t *actual_props;
+ svn_boolean_t is_switched;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_wc__db_is_switched(&is_wc_root, &is_switched, NULL,
+ db, parent_abspath, iterpool));
+
+ if (is_switched || is_wc_root)
+ {
+ is_wc_root = TRUE;
+
+ /* If the WC root is also the root of the repository then by
+ definition there are no inheritable properties to be had,
+ but checking for that is just as expensive as fetching them
+ anyway. */
+
+ /* Grab the cached inherited properties for the WC root. */
+ SVN_ERR(svn_wc__db_read_cached_iprops(&cached_iprops, db,
+ parent_abspath,
+ scratch_pool, iterpool));
+ }
+
+ /* If PARENT_ABSPATH is a true parent of LOCAL_ABSPATH, then
+ LOCAL_ABSPATH can inherit properties from it. */
+ if (strcmp(ripb->local_abspath, parent_abspath) != 0)
+ {
+ SVN_ERR(svn_wc__db_read_props(&actual_props, db, parent_abspath,
+ result_pool, iterpool));
+ if (actual_props)
+ {
+ /* If we only want PROPNAME filter out any other properties. */
+ if (ripb->propname)
+ filter_unwanted_props(actual_props, ripb->propname, iterpool);
+
+ if (apr_hash_count(actual_props))
+ {
+ svn_prop_inherited_item_t *iprop_elt =
+ apr_pcalloc(ripb->result_pool,
+ sizeof(svn_prop_inherited_item_t));
+ iprop_elt->path_or_url = apr_pstrdup(result_pool,
+ parent_abspath);
+ iprop_elt->prop_hash = actual_props;
+ /* Build the output array in depth-first order. */
+ svn_sort__array_insert(&iprop_elt, ripb->iprops, 0);
+ }
+ }
+ }
+
+ /* Inheritance only goes as far as the nearest WC root. */
+ if (is_wc_root)
+ break;
+
+ /* Keep looking for the WC root. */
+ parent_abspath = svn_dirent_dirname(parent_abspath, scratch_pool);
+ }
+
+ if (cached_iprops)
+ {
+ for (i = cached_iprops->nelts - 1; i >= 0; i--)
+ {
+ svn_prop_inherited_item_t *cached_iprop =
+ APR_ARRAY_IDX(cached_iprops, i, svn_prop_inherited_item_t *);
+
+ /* An empty property hash in the iprops cache means there are no
+ inherited properties. */
+ if (apr_hash_count(cached_iprop->prop_hash) == 0)
+ continue;
+
+ if (ripb->propname)
+ filter_unwanted_props(cached_iprop->prop_hash, ripb->propname,
+ scratch_pool);
+
+ /* If we didn't filter everything then keep this iprop. */
+ if (apr_hash_count(cached_iprop->prop_hash))
+ svn_sort__array_insert(&cached_iprop, ripb->iprops, 0);
+ }
+ }
+
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__db_read_inherited_props(apr_array_header_t **iprops,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *propname,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_wc__db_wcroot_t *wcroot;
+ const char *local_relpath;
+ struct read_inherited_props_baton_t ripb;
+
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+ SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath,
+ db, local_abspath,
+ scratch_pool, scratch_pool));
+ VERIFY_USABLE_WCROOT(wcroot);
+
+ ripb.iprops = NULL;
+ ripb.db = db;
+ ripb.local_abspath = local_abspath;
+ ripb.propname = propname;
+ ripb.result_pool = result_pool;
+
+ SVN_ERR(svn_wc__db_with_txn(wcroot, local_relpath, db_read_inherited_props,
+ &ripb, scratch_pool));
+
+ *iprops = ripb.iprops;
+ return SVN_NO_ERROR;
+}
+
/* Baton for get_children_with_cached_iprops */
struct get_children_with_cached_baton_t
{
Modified: subversion/trunk/subversion/libsvn_wc/wc_db.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/wc_db.h?rev=1414123&r1=1414122&r2=1414123&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/trunk/subversion/libsvn_wc/wc_db.h Tue Nov 27 10:53:16 2012
@@ -2094,6 +2094,26 @@ svn_wc__db_read_pristine_props(apr_hash_
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+
+/**
+ * Set @a *inherited_props to a depth-first ordered array of
+ * #svn_prop_inherited_item_t * structures representing the properties
+ * inherited by @a local_abspath from the ACTUAL tree above
+ * @a local_abspath (looking through to the WORKING or BASE tree as
+ * required), up to and including the root of the working copy and
+ * any cached inherited properties inherited by the root.
+ *
+ * Allocate @a *inherited_props in @a result_pool. Use @a scratch_pool
+ * for temporary allocations.
+ */
+svn_error_t *
+svn_wc__db_read_inherited_props(apr_array_header_t **iprops,
+ svn_wc__db_t *db,
+ const char *local_abspath,
+ const char *propname,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
/* Read a BASE node's inherited property information.
Set *IPROPS to to a depth-first ordered array of