On Tue, Feb 15, 2011 at 2:53 PM, Stefan Sperling <stsp_at_elego.de> wrote:
> On Tue, Feb 15, 2011 at 01:30:45PM +0100, Stefan Sperling wrote:
>> On Mon, Feb 14, 2011 at 09:48:35PM +0100, Branko Čibej wrote:
>> > On 14.02.2011 13:37, Stefan Sperling wrote:
>> > > On Tue, Feb 08, 2011 at 11:50:36PM +0100, Branko Čibej wrote:
>> > >> Well, here it is, I fixed the thinko in the actual_props query and got
>> > >> all prop_tests to pass with this version.
>> > > Just FYI, the patch doesn't apply to HEAD. I'll try to adjust it when
>> > > I find time. But maybe you'll be quicker than me? :)
>> >
>> > It got clobbered by Hyrum's changes for pdh checking, if I read the
>> > conflict diff correctly. Should really be just the one conflict in
>> > wc_db.c, probably. I'll see if I can find time to update the patch, but
>> > I can't promise anything, got my hands full right now.
>>
>> Updated version:
>
> The patch was missing a bump of SVN_WC__VERSION so auto-upgrade didn't work.
> Update below.
>
> I think we should commit this and continue working on it.
> Is it OK to bump the WC format now?
I've not reviewed the patch, but to the question about bumping the wc
format, I think you're safe to do so (so long as the upgrade code is
properly implemented / tested, etc).
The current working copy much more gracefully handles upgrades, and is
*should* Just Work.
-Hyrum
>
> Here's a log message:
>
> [[[
> Improve performance of svn proplist in a similar way as was done in r1039808.
> But, this time, avoid problems with callbacks invoked during sqlite
> transactions by storing results in a temporary table and invoking
> callbacks during a query on the temporary table.
>
> Patch by: brane
>
> * subversion/libsvn_wc/props.c
> (read_dir_props): Adjust caller of svn_wc__db_read_props_of_immediates().
> (svn_wc__prop_list_recursive): Reimplement using new wc_db APIs.
>
> * subversion/libsvn_wc/wc.h
> (SVN_WC__VERSION): Bump to 25 (format 25 adds NODES_CURRENT view).
>
> * subversion/libsvn_wc/wc-queries.sql
> (STMT_CLEAR_NODE_PROPS_CACHE, STMT_CACHE_NODE_PROPS_RECURSIVE,
> STMT_CACHE_ACTUAL_PROPS_RECURSIVE, STMT_CACHE_NODE_PROPS_OF_CHILDREN,
> STMT_CACHE_ACTUAL_PROPS_OF_CHILDREN,
> STMT_SELECT_RELEVANT_PROPS_FROM_CACHE): New queries.
>
> * subversion/libsvn_wc/wc-metadata.sql
> (NODES_CURRENT): A view on the NODES table that shows only the nodes
> with the highest op_depth.
> (STMT_UPGRADE_TO_25): Upgrade statement which creates NODES_CURRENT.
>
> * subversion/libsvn_wc/wc_db.c
> (maybe_add_child_props, read_props_of_children): Remove.
> (cache_props_baton_t): New baton type used by cache_props_recursive().
> (cache_props_recursive): New. Helper for read_props_recursive().
> (read_props_recursive): New. Recursively reads properties from wc_db.
> Recursion can be limited by depth. Uses the new queries to create
> a temporary table containing information about properties and pass
> the results to the receiver callback.
> (svn_wc__db_read_props_of_files,
> svn_wc__db_read_props_of_immediates): Call read_props_recursive() instead
> of read_props_of_children(). Add support for cancellation.
>
> * subversion/libsvn_wc/wc_db.h
> (svn_wc__db_read_props_of_files,
> svn_wc__db_read_props_of_immediates): Update declarations.
> (svn_wc__db_read_props_recursive): Declare.
>
> * subversion/libsvn_wc/upgrade.c
> (bump_to_25): New.
> (svn_wc__upgrade_sdb): Upgrade to format 25.
> ]]]
>
> Index: subversion/libsvn_wc/props.c
> ===================================================================
> --- subversion/libsvn_wc/props.c (revision 1070853)
> +++ subversion/libsvn_wc/props.c (working copy)
> @@ -1711,6 +1711,7 @@ read_dir_props(const char *local_abspath,
> SVN_ERR(svn_wc__db_read_props_of_immediates(b->db, local_abspath,
> b->receiver_func,
> b->receiver_baton,
> + NULL, NULL,
> scratch_pool));
> return SVN_NO_ERROR;
> }
> @@ -1725,47 +1726,41 @@ svn_wc__prop_list_recursive(svn_wc_context_t *wc_c
> void *cancel_baton,
> apr_pool_t *scratch_pool)
> {
> - struct read_dir_props_baton read_dir_baton;
> -
> - if (depth <= svn_depth_immediates)
> + switch (depth)
> {
> - apr_hash_t *props;
> + case svn_depth_empty:
> + {
> + apr_hash_t *props;
>
> - SVN_ERR(svn_wc__db_read_props(&props, wc_ctx->db, local_abspath,
> - scratch_pool, scratch_pool));
> - if (receiver_func && props && apr_hash_count(props) > 0)
> - SVN_ERR((*receiver_func)(receiver_baton, local_abspath, props,
> - scratch_pool));
> - if (depth == svn_depth_empty)
> - return SVN_NO_ERROR;
> - }
> -
> - if (depth == svn_depth_files)
> - {
> + SVN_ERR(svn_wc__db_read_props(&props, wc_ctx->db, local_abspath,
> + scratch_pool, scratch_pool));
> + if (receiver_func && props && apr_hash_count(props) > 0)
> + SVN_ERR((*receiver_func)(receiver_baton, local_abspath, props,
> + scratch_pool));
> + }
> + break;
> + case svn_depth_files:
> SVN_ERR(svn_wc__db_read_props_of_files(wc_ctx->db, local_abspath,
> receiver_func, receiver_baton,
> + cancel_func, cancel_baton,
> scratch_pool));
> - return SVN_NO_ERROR;
> - }
> -
> - if (depth == svn_depth_immediates)
> - {
> + break;
> + case svn_depth_immediates:
> SVN_ERR(svn_wc__db_read_props_of_immediates(wc_ctx->db, local_abspath,
> - receiver_func,
> - receiver_baton,
> + receiver_func, receiver_baton,
> + cancel_func, cancel_baton,
> scratch_pool));
> - return SVN_NO_ERROR;
> + break;
> + case svn_depth_infinity:
> + SVN_ERR(svn_wc__db_read_props_recursive(wc_ctx->db, local_abspath,
> + receiver_func, receiver_baton,
> + cancel_func, cancel_baton,
> + scratch_pool));
> + break;
> + default:
> + SVN_ERR_MALFUNCTION();
> }
>
> - read_dir_baton.db = wc_ctx->db;
> - read_dir_baton.root_abspath = local_abspath;
> - read_dir_baton.receiver_func = receiver_func;
> - read_dir_baton.receiver_baton = receiver_baton;
> -
> - SVN_ERR(svn_wc__internal_walk_children(wc_ctx->db, local_abspath, FALSE,
> - read_dir_props, &read_dir_baton,
> - depth, cancel_func, cancel_baton,
> - scratch_pool));
> return SVN_NO_ERROR;
> }
>
> Index: subversion/libsvn_wc/wc.h
> ===================================================================
> --- subversion/libsvn_wc/wc.h (revision 1070853)
> +++ subversion/libsvn_wc/wc.h (working copy)
> @@ -141,7 +141,7 @@ extern "C" {
> * Please document any further format changes here.
> */
>
> -#define SVN_WC__VERSION 24
> +#define SVN_WC__VERSION 25
>
>
> /* Formats <= this have no concept of "revert text-base/props". */
> Index: subversion/libsvn_wc/wc-queries.sql
> ===================================================================
> --- subversion/libsvn_wc/wc-queries.sql (revision 1070853)
> +++ subversion/libsvn_wc/wc-queries.sql (working copy)
> @@ -741,7 +741,62 @@ SELECT 1 FROM nodes WHERE op_depth > 0;
> UPDATE nodes SET checksum = ?4
> WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3;
>
> +/* ------------------------------------------------------------------------- */
> +/* PROOF OF CONCEPT: Complex queries for callback walks, caching results
> + in a temporary table. */
>
> +-- STMT_CLEAR_NODE_PROPS_CACHE
> +DROP TABLE IF EXISTS temp__node_props_cache;
> +
> +-- STMT_CACHE_NODE_PROPS_RECURSIVE
> +CREATE TEMPORARY TABLE temp__node_props_cache AS
> + SELECT local_relpath, kind, properties FROM nodes_current
> + WHERE wc_id = ?1
> + AND (?2 = '' OR local_relpath = ?2 OR local_relpath LIKE ?2 || '/%')
> + AND local_relpath NOT IN (
> + SELECT local_relpath FROM actual_node WHERE wc_id = ?1)
> + AND (presence = 'normal' OR presence = 'incomplete');
> +CREATE UNIQUE INDEX temp__node_props_cache_unique
> + ON temp__node_props_cache (local_relpath);
> +
> +-- STMT_CACHE_ACTUAL_PROPS_RECURSIVE
> +INSERT INTO temp__node_props_cache (local_relpath, kind, properties)
> + SELECT A.local_relpath, N.kind, A.properties
> + FROM actual_node AS A JOIN nodes_current AS N
> + ON A.wc_id = N.wc_id AND A.local_relpath = N.local_relpath
> + AND (N.presence = 'normal' OR N.presence = 'incomplete')
> + WHERE A.wc_id = ?1
> + AND (?2 = '' OR A.local_relpath = ?2 OR A.local_relpath LIKE ?2 || '/%')
> + AND A.local_relpath NOT IN
> + (SELECT local_relpath FROM temp__node_props_cache);
> +
> +-- STMT_CACHE_NODE_PROPS_OF_CHILDREN
> +CREATE TEMPORARY TABLE temp__node_props_cache AS
> + SELECT local_relpath, kind, properties FROM nodes_current
> + WHERE wc_id = ?1
> + AND (local_relpath = ?2 OR parent_relpath = ?2)
> + AND local_relpath NOT IN (
> + SELECT local_relpath FROM actual_node WHERE wc_id = ?1)
> + AND (presence = 'normal' OR presence = 'incomplete');
> +CREATE UNIQUE INDEX temp__node_props_cache_unique
> + ON temp__node_props_cache (local_relpath);
> +
> +-- STMT_CACHE_ACTUAL_PROPS_OF_CHILDREN
> +INSERT INTO temp__node_props_cache (local_relpath, kind, properties)
> + SELECT A.local_relpath, N.kind, A.properties
> + FROM actual_node AS A JOIN nodes_current AS N
> + ON A.wc_id = N.wc_id AND A.local_relpath = N.local_relpath
> + AND (N.presence = 'normal' OR N.presence = 'incomplete')
> + WHERE A.wc_id = ?1
> + AND (A.local_relpath = ?2 OR A.parent_relpath = ?2)
> + AND A.local_relpath NOT IN
> + (SELECT local_relpath FROM temp__node_props_cache);
> +
> +-- STMT_SELECT_RELEVANT_PROPS_FROM_CACHE
> +SELECT local_relpath, kind, properties FROM temp__node_props_cache
> +ORDER BY local_relpath;
> +
> +
> /* ------------------------------------------------------------------------- */
>
> /* Grab all the statements related to the schema. */
> Index: subversion/libsvn_wc/wc-metadata.sql
> ===================================================================
> --- subversion/libsvn_wc/wc-metadata.sql (revision 1070853)
> +++ subversion/libsvn_wc/wc-metadata.sql (working copy)
> @@ -483,6 +483,16 @@ CREATE TABLE NODES (
>
> CREATE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath, op_depth);
>
> +/* Many queries have to filter the nodes table to pick only that version
> + of each node with the highest (most "current") op_depth. This view
> + does the heavy lifting for such queries. */
> +CREATE VIEW NODES_CURRENT AS
> + SELECT * FROM nodes
> + JOIN (SELECT wc_id, local_relpath, MAX(op_depth) AS op_depth FROM nodes
> + GROUP BY wc_id, local_relpath) AS filter
> + ON nodes.wc_id = filter.wc_id
> + AND nodes.local_relpath = filter.local_relpath
> + AND nodes.op_depth = filter.op_depth;
>
> -- STMT_CREATE_NODES_TRIGGERS
>
> @@ -595,7 +605,22 @@ UPDATE pristine SET refcount =
>
> PRAGMA user_version = 24;
>
> +/* ------------------------------------------------------------------------- */
>
> +/* Format 25 introduces the NODES_CURRENT view. */
> +
> +-- STMT_UPGRADE_TO_25
> +DROP VIEW IF EXISTS NODES_CURRENT;
> +CREATE VIEW NODES_CURRENT AS
> + SELECT * FROM nodes
> + JOIN (SELECT wc_id, local_relpath, MAX(op_depth) AS op_depth FROM nodes
> + GROUP BY wc_id, local_relpath) AS filter
> + ON nodes.wc_id = filter.wc_id
> + AND nodes.local_relpath = filter.local_relpath
> + AND nodes.op_depth = filter.op_depth;
> +
> +PRAGMA user_version = 25;
> +
> /* ------------------------------------------------------------------------- */
>
> /* Format YYY introduces new handling for conflict information. */
> Index: subversion/libsvn_wc/wc_db.c
> ===================================================================
> --- subversion/libsvn_wc/wc_db.c (revision 1070853)
> +++ subversion/libsvn_wc/wc_db.c (working copy)
> @@ -5175,166 +5175,144 @@ svn_wc__db_read_props(apr_hash_t **props,
> return SVN_NO_ERROR;
> }
>
> -/* Parse a node's PROP_DATA (which is PROP_DATA_LEN bytes long)
> - * into a hash table keyed by property names and containing property values.
> - *
> - * If parsing succeeds, and the set of properties is not empty,
> - * add the hash table to PROPS_PER_CHILD, keyed by the absolute path
> - * of the node CHILD_RELPATH within the working copy at WCROOT_ABSPATH.
> - *
> - * If the set of properties is empty, and PROPS_PER_CHILD already contains
> - * an entry for the node, clear the entry. This facilitates overriding
> - * properties retrieved from the NODES table with empty sets of properties
> - * stored in the ACTUAL_NODE table. */
> +/* Call RECEIVER_FUNC, passing RECEIVER_BATON, an absolute path, and
> + * a hash table mapping <tt>char *</tt> names onto svn_string_t *
> + * values for any properties of immediate or recursive child nodes of
> + * LOCAL_ABSPATH, the actual query being determined by STMT_IDX.
> + * If FILES_ONLY is true, only report properties for file child nodes.
> + * Check for cancellation between calls of RECEIVER_FUNC.
> + */
> +typedef struct cache_props_baton_t
> +{
> + int stmt_node_props_ndx;
> + int stmt_actual_props_ndx;
> + apr_int64_t wc_id;
> + const char *local_relpath;
> + svn_cancel_func_t cancel_func;
> + void *cancel_baton;
> +} cache_props_baton_t;
> +
> static svn_error_t *
> -maybe_add_child_props(apr_hash_t *props_per_child,
> - const char *prop_data,
> - apr_size_t prop_data_len,
> - const char *child_relpath,
> - const char *wcroot_abspath,
> - apr_pool_t *result_pool,
> +cache_props_recursive(void *cb_baton,
> + svn_sqlite__db_t *db,
> apr_pool_t *scratch_pool)
> {
> - const char *child_abspath;
> - apr_hash_t *props;
> - svn_skel_t *prop_skel;
> + cache_props_baton_t *baton = cb_baton;
> + svn_sqlite__stmt_t *stmt;
>
> - prop_skel = svn_skel__parse(prop_data, prop_data_len, scratch_pool);
> - if (svn_skel__list_length(prop_skel) == 0)
> - return SVN_NO_ERROR;
> + SVN_ERR(svn_sqlite__get_statement(&stmt, db, baton->stmt_node_props_ndx));
> + SVN_ERR(svn_sqlite__bindf(stmt, "is", baton->wc_id, baton->local_relpath));
> + SVN_ERR(svn_sqlite__step_done(stmt));
>
> - child_abspath = svn_dirent_join(wcroot_abspath, child_relpath, result_pool);
> - SVN_ERR(svn_skel__parse_proplist(&props, prop_skel, result_pool));
> - if (apr_hash_count(props))
> - apr_hash_set(props_per_child, child_abspath, APR_HASH_KEY_STRING, props);
> - else
> - apr_hash_set(props_per_child, child_abspath, APR_HASH_KEY_STRING, NULL);
> + if (baton->cancel_func)
> + SVN_ERR(baton->cancel_func(baton->cancel_baton));
> +
> + SVN_ERR(svn_sqlite__get_statement(&stmt, db, baton->stmt_actual_props_ndx));
> + SVN_ERR(svn_sqlite__bindf(stmt, "is", baton->wc_id, baton->local_relpath));
> + SVN_ERR(svn_sqlite__step_done(stmt));
>
> return SVN_NO_ERROR;
> }
>
> -/* Call RECEIVER_FUNC, passing RECEIVER_BATON, an absolute path, and
> - * a hash table mapping <tt>char *</tt> names onto svn_string_t *
> - * values for any properties of immediate child nodes of LOCAL_ABSPATH.
> - * If FILES_ONLY is true, only report properties for file child nodes.
> - */
> static svn_error_t *
> -read_props_of_children(svn_wc__db_t *db,
> - const char *local_abspath,
> - svn_boolean_t files_only,
> - svn_wc__proplist_receiver_t receiver_func,
> - void *receiver_baton,
> - apr_pool_t *scratch_pool)
> +read_props_recursive(svn_wc__db_t *db,
> + const char *local_abspath,
> + svn_boolean_t files_only,
> + svn_boolean_t immediates_only,
> + svn_wc__proplist_receiver_t receiver_func,
> + void *receiver_baton,
> + svn_cancel_func_t cancel_func,
> + void *cancel_baton,
> + apr_pool_t *scratch_pool)
> {
> svn_wc__db_wcroot_t *wcroot;
> - const char *local_relpath;
> - const char *prev_child_relpath;
> svn_sqlite__stmt_t *stmt;
> + cache_props_baton_t baton;
> svn_boolean_t have_row;
> - apr_hash_t *props_per_child;
> - apr_hash_t *files;
> - apr_hash_t *not_present;
> - apr_hash_index_t *hi;
> + int row_number;
> apr_pool_t *iterpool;
>
> SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
> SVN_ERR_ASSERT(receiver_func);
>
> - SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db,
> - local_abspath,
> - svn_sqlite__mode_readwrite,
> - scratch_pool, scratch_pool));
> + SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &baton.local_relpath,
> + db, local_abspath,
> + svn_sqlite__mode_readwrite,
> + scratch_pool, scratch_pool));
> VERIFY_USABLE_WCROOT(wcroot);
>
> - props_per_child = apr_hash_make(scratch_pool);
> - not_present = apr_hash_make(scratch_pool);
> - if (files_only)
> - files = apr_hash_make(scratch_pool);
> + SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
> + STMT_CLEAR_NODE_PROPS_CACHE));
> +
> + if (immediates_only)
> + {
> + baton.stmt_node_props_ndx = STMT_CACHE_NODE_PROPS_OF_CHILDREN;
> + baton.stmt_actual_props_ndx = STMT_CACHE_ACTUAL_PROPS_OF_CHILDREN;
> + }
> else
> - files = NULL;
> + {
> + baton.stmt_node_props_ndx = STMT_CACHE_NODE_PROPS_RECURSIVE;
> + baton.stmt_actual_props_ndx = STMT_CACHE_ACTUAL_PROPS_RECURSIVE;
> + }
> + baton.wc_id = wcroot->wc_id;
> + baton.cancel_func = cancel_func;
> + baton.cancel_baton = cancel_baton;
> + SVN_ERR(svn_sqlite__with_transaction(wcroot->sdb,
> + cache_props_recursive,
> + &baton, scratch_pool));
>
> + iterpool = svn_pool_create(scratch_pool);
> +
> SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
> - STMT_SELECT_NODE_PROPS_OF_CHILDREN));
> - SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
> + STMT_SELECT_RELEVANT_PROPS_FROM_CACHE));
> SVN_ERR(svn_sqlite__step(&have_row, stmt));
> - prev_child_relpath = NULL;
> - while (have_row)
> + for (row_number = 0; have_row; ++row_number)
> {
> - svn_wc__db_status_t child_presence;
> - const char *child_relpath;
> const char *prop_data;
> apr_size_t len;
>
> - child_relpath = svn_sqlite__column_text(stmt, 2, scratch_pool);
> -
> - if (prev_child_relpath && strcmp(child_relpath, prev_child_relpath) == 0)
> + if (files_only && row_number > 0)
> {
> - /* Same child, but lower op_depth -- skip this row. */
> - SVN_ERR(svn_sqlite__step(&have_row, stmt));
> - continue;
> - }
> - prev_child_relpath = child_relpath;
> + svn_wc__db_kind_t child_kind;
>
> - child_presence = svn_sqlite__column_token(stmt, 1, presence_map);
> - if (child_presence != svn_wc__db_status_normal)
> - {
> - apr_hash_set(not_present, child_relpath, APR_HASH_KEY_STRING, "");
> - SVN_ERR(svn_sqlite__step(&have_row, stmt));
> - continue;
> - }
> -
> - prop_data = svn_sqlite__column_blob(stmt, 0, &len, NULL);
> - if (prop_data)
> - {
> - if (files_only)
> + child_kind = svn_sqlite__column_token(stmt, 1, kind_map);
> + if (child_kind != svn_wc__db_kind_file &&
> + child_kind != svn_wc__db_kind_symlink)
> {
> - svn_wc__db_kind_t child_kind;
> -
> - child_kind = svn_sqlite__column_token(stmt, 3, kind_map);
> - if (child_kind != svn_wc__db_kind_file &&
> - child_kind != svn_wc__db_kind_symlink)
> - {
> - SVN_ERR(svn_sqlite__step(&have_row, stmt));
> - continue;
> - }
> - apr_hash_set(files, child_relpath, APR_HASH_KEY_STRING, NULL);
> + SVN_ERR(svn_sqlite__step(&have_row, stmt));
> + continue;
> }
> -
> - SVN_ERR(maybe_add_child_props(props_per_child, prop_data, len,
> - child_relpath, wcroot->abspath,
> - scratch_pool, scratch_pool));
> }
>
> - SVN_ERR(svn_sqlite__step(&have_row, stmt));
> - }
> + svn_pool_clear(iterpool);
>
> - SVN_ERR(svn_sqlite__reset(stmt));
> + /* see if someone wants to cancel this operation. */
> + if (cancel_func)
> + SVN_ERR(cancel_func(cancel_baton));
>
> - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
> - STMT_SELECT_ACTUAL_PROPS_OF_CHILDREN));
> - SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath));
> - SVN_ERR(svn_sqlite__step(&have_row, stmt));
> - while (have_row)
> - {
> - const char *child_relpath;
> - const char *prop_data;
> - apr_size_t len;
> -
> - prop_data = svn_sqlite__column_blob(stmt, 0, &len, NULL);
> + prop_data = svn_sqlite__column_blob(stmt, 2, &len, NULL);
> if (prop_data)
> {
> - child_relpath = svn_sqlite__column_text(stmt, 1, scratch_pool);
> + svn_skel_t *prop_skel;
>
> - if (apr_hash_get(not_present, child_relpath, APR_HASH_KEY_STRING) ||
> - (files_only &&
> - apr_hash_get(files, child_relpath, APR_HASH_KEY_STRING) == NULL))
> + prop_skel = svn_skel__parse(prop_data, len, iterpool);
> + if (svn_skel__list_length(prop_skel) != 0)
> {
> - SVN_ERR(svn_sqlite__step(&have_row, stmt));
> - continue;
> + const char *child_relpath;
> + const char *child_abspath;
> + apr_hash_t *props;
> +
> + child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
> + child_abspath = svn_dirent_join(wcroot->abspath,
> + child_relpath, iterpool);
> + SVN_ERR(svn_skel__parse_proplist(&props, prop_skel, iterpool));
> + if (receiver_func && apr_hash_count(props) != 0)
> + {
> + SVN_ERR((*receiver_func)(receiver_baton,
> + child_abspath, props,
> + iterpool));
> + }
> }
> - SVN_ERR(maybe_add_child_props(props_per_child, prop_data, len,
> - child_relpath, wcroot->abspath,
> - scratch_pool, scratch_pool));
> }
>
> SVN_ERR(svn_sqlite__step(&have_row, stmt));
> @@ -5342,22 +5320,10 @@ static svn_error_t *
>
> SVN_ERR(svn_sqlite__reset(stmt));
>
> - iterpool = svn_pool_create(scratch_pool);
> - for (hi = apr_hash_first(scratch_pool, props_per_child);
> - hi;
> - hi = apr_hash_next(hi))
> - {
> - const char *child_abspath = svn__apr_hash_index_key(hi);
> - apr_hash_t *child_props = svn__apr_hash_index_val(hi);
> -
> - svn_pool_clear(iterpool);
> -
> - if (child_props)
> - SVN_ERR((*receiver_func)(receiver_baton, child_abspath, child_props,
> - iterpool));
> - }
> svn_pool_destroy(iterpool);
>
> + SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb,
> + STMT_CLEAR_NODE_PROPS_CACHE));
> return SVN_NO_ERROR;
> }
>
> @@ -5366,11 +5332,15 @@ svn_wc__db_read_props_of_files(svn_wc__db_t *db,
> const char *local_abspath,
> svn_wc__proplist_receiver_t receiver_func,
> void *receiver_baton,
> + svn_cancel_func_t cancel_func,
> + void *cancel_baton,
> apr_pool_t *scratch_pool)
> {
> - return svn_error_return(read_props_of_children(db, local_abspath, TRUE,
> - receiver_func, receiver_baton,
> - scratch_pool));
> + SVN_ERR(read_props_recursive(db, local_abspath, TRUE, TRUE,
> + receiver_func, receiver_baton,
> + cancel_func, cancel_baton,
> + scratch_pool));
> + return SVN_NO_ERROR;
> }
>
> svn_error_t *
> @@ -5378,13 +5348,32 @@ svn_wc__db_read_props_of_immediates(svn_wc__db_t *
> const char *local_abspath,
> svn_wc__proplist_receiver_t receiver_func,
> void *receiver_baton,
> + svn_cancel_func_t cancel_func,
> + void *cancel_baton,
> apr_pool_t *scratch_pool)
> {
> - return svn_error_return(read_props_of_children(db, local_abspath, FALSE,
> - receiver_func, receiver_baton,
> - scratch_pool));
> + SVN_ERR(read_props_recursive(db, local_abspath, FALSE, TRUE,
> + receiver_func, receiver_baton,
> + cancel_func, cancel_baton,
> + scratch_pool));
> + return SVN_NO_ERROR;
> }
>
> +svn_error_t *
> +svn_wc__db_read_props_recursive(svn_wc__db_t *db,
> + const char *local_abspath,
> + svn_wc__proplist_receiver_t receiver_func,
> + void *receiver_baton,
> + svn_cancel_func_t cancel_func,
> + void *cancel_baton,
> + apr_pool_t *scratch_pool)
> +{
> + SVN_ERR(read_props_recursive(db, local_abspath, FALSE, FALSE,
> + receiver_func, receiver_baton,
> + cancel_func, cancel_baton,
> + scratch_pool));
> + return SVN_NO_ERROR;
> +}
>
> static svn_error_t *
> db_read_pristine_props(apr_hash_t **props,
> Index: subversion/libsvn_wc/wc_db.h
> ===================================================================
> --- subversion/libsvn_wc/wc_db.h (revision 1070853)
> +++ subversion/libsvn_wc/wc_db.h (working copy)
> @@ -1588,9 +1588,10 @@ svn_wc__db_read_props(apr_hash_t **props,
> svn_error_t *
> svn_wc__db_read_props_of_files(svn_wc__db_t *db,
> const char *local_abspath,
> - svn_wc__proplist_receiver_t
> - receiver_func,
> + svn_wc__proplist_receiver_t receiver_func,
> void *receiver_baton,
> + svn_cancel_func_t cancel_func,
> + void *cancel_baton,
> apr_pool_t *scratch_pool);
>
> /* Call RECEIVER_FUNC, passing RECEIVER_BATON, an absolute path, and
> @@ -1600,11 +1601,25 @@ svn_wc__db_read_props_of_files(svn_wc__db_t *db,
> svn_error_t *
> svn_wc__db_read_props_of_immediates(svn_wc__db_t *db,
> const char *local_abspath,
> - svn_wc__proplist_receiver_t
> - receiver_func,
> + svn_wc__proplist_receiver_t receiver_func,
> void *receiver_baton,
> + svn_cancel_func_t cancel_func,
> + void *cancel_baton,
> apr_pool_t *scratch_pool);
>
> +/* Call RECEIVER_FUNC, passing RECEIVER_BATON, an absolute path, and
> + * a hash table mapping <tt>char *</tt> names onto svn_string_t *
> + * values for any properties of all (recursive) child nodes of LOCAL_ABSPATH.
> + */
> +svn_error_t *
> +svn_wc__db_read_props_recursive(svn_wc__db_t *db,
> + const char *local_abspath,
> + svn_wc__proplist_receiver_t receiver_func,
> + void *receiver_baton,
> + svn_cancel_func_t cancel_func,
> + void *cancel_baton,
> + apr_pool_t *scratch_pool);
> +
> /* Set *PROPS to the properties of the node LOCAL_ABSPATH in the WORKING
> tree (looking through to the BASE tree as required).
>
> Index: subversion/libsvn_wc/upgrade.c
> ===================================================================
> --- subversion/libsvn_wc/upgrade.c (revision 1070853)
> +++ subversion/libsvn_wc/upgrade.c (working copy)
> @@ -1137,7 +1137,14 @@ bump_to_24(void *baton, svn_sqlite__db_t *sdb, apr
> return SVN_NO_ERROR;
> }
>
> +static svn_error_t *
> +bump_to_25(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool)
> +{
> + SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_25));
> + return SVN_NO_ERROR;
> +}
>
> +
> struct upgrade_data_t {
> svn_sqlite__db_t *sdb;
> const char *root_abspath;
> @@ -1402,6 +1409,12 @@ svn_wc__upgrade_sdb(int *result_format,
> *result_format = 24;
> /* FALLTHROUGH */
>
> + case 24:
> + SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_25, &bb,
> + scratch_pool));
> + *result_format = 25;
> + /* FALLTHROUGH */
> +
> /* ### future bumps go here. */
> #if 0
> case XXX-1:
>
Received on 2011-02-15 16:36:26 CET