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