Are you sure the pool arguments are in the right order here? The usual order is result_pool, scratch_pool while most of the calls here appear to use the opposite order.
Bert Sent from Mail for Windows 10 From: stef...@apache.org Sent: maandag 15 februari 2016 22:47 To: comm...@subversion.apache.org Subject: svn commit: r1730617 -/subversion/trunk/subversion/libsvn_repos/log.c Author: stefan2 Date: Mon Feb 15 21:47:00 2016 New Revision: 1730617 URL: http://svn.apache.org/viewvc?rev=1730617&view=rev Log: Continue work on the svn_repos_get_logs4 to svn_repos_get_logs5 migration: Switch the last svn_fs_paths_changed2 call to svn_fs_paths_changed3. * subversion/libsvn_repos/log.c (fs_mergeinfo_changed): No longer fetch the whole changes list. However, we need to iterate twice for best total performance and we need to minimize FS iterator lifetimes. Modified: subversion/trunk/subversion/libsvn_repos/log.c Modified: subversion/trunk/subversion/libsvn_repos/log.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/log.c?rev=1730617&r1=1730616&r2=1730617&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_repos/log.c (original) +++ subversion/trunk/subversion/libsvn_repos/log.c Mon Feb 15 21:47:00 2016 @@ -631,11 +631,11 @@ fs_mergeinfo_changed(svn_mergeinfo_catal apr_pool_t *scratch_pool) { svn_fs_root_t *root; - apr_pool_t *iterpool; - apr_hash_index_t *hi; + apr_pool_t *iterpool, *iterator_pool; + svn_fs_path_change_iterator_t *iterator; + svn_fs_path_change3_t *change; svn_boolean_t any_mergeinfo = FALSE; svn_boolean_t any_copy = FALSE; - apr_hash_t *changes; /* Initialize return variables. */ *deleted_mergeinfo_catalog = svn_hash__make(result_pool); @@ -645,55 +645,69 @@ fs_mergeinfo_changed(svn_mergeinfo_catal if (rev == 0) return SVN_NO_ERROR; + /* FS iterators are potentially heavy objects. + * Hold them in a separate pool to clean them up asap. */ + iterator_pool = svn_pool_create(scratch_pool); + /* We're going to use the changed-paths information for REV to narrow down our search. */ SVN_ERR(svn_fs_revision_root(&root, fs, rev, scratch_pool)); - SVN_ERR(svn_fs_paths_changed2(&changes, root, scratch_pool)); + SVN_ERR(svn_fs_paths_changed3(&iterator, root, iterator_pool, + scratch_pool)); + SVN_ERR(svn_fs_path_change_get(&change, iterator)); /* Look for copies and (potential) mergeinfo changes. - We will use both flags to take shortcuts further down the road. */ - for (hi = apr_hash_first(scratch_pool, changes); - hi; - hi = apr_hash_next(hi)) - { - svn_fs_path_change2_t *change = apr_hash_this_val(hi); + We will use both flags to take shortcuts further down the road. + The critical information here is whether there are any copies + because that greatly influences the costs for log processing. + So, it is faster to iterate over the changes twice - in the worst + case b/c most times there is no m/i at all and we exit out early + without any overhead. + */ + while (change && (!any_mergeinfo || !any_copy)) + { /* If there was a prop change and we are not positive that _no_ mergeinfo change happened, we must assume that it might have. */ if (change->mergeinfo_mod != svn_tristate_false && change->prop_mod) any_mergeinfo = TRUE; - switch (change->change_kind) - { - case svn_fs_path_change_add: - case svn_fs_path_change_replace: - any_copy = TRUE; - break; + if ( (change->change_kind == svn_fs_path_change_add) + || (change->change_kind == svn_fs_path_change_replace)) + any_copy = TRUE; - default: - break; - } + SVN_ERR(svn_fs_path_change_get(&change, iterator)); } /* No potential mergeinfo changes? We're done. */ if (! any_mergeinfo) - return SVN_NO_ERROR; + { + svn_pool_destroy(iterator_pool); + return SVN_NO_ERROR; + } + + /* There is or may be some m/i change. Look closely now. */ + svn_pool_clear(iterator_pool); + SVN_ERR(svn_fs_paths_changed3(&iterator, root, iterator_pool, + scratch_pool)); /* Loop over changes, looking for anything that might carry an svn:mergeinfo change and is one of our paths of interest, or a child or [grand]parent directory thereof. */ iterpool = svn_pool_create(scratch_pool); - for (hi = apr_hash_first(scratch_pool, changes); - hi; - hi = apr_hash_next(hi)) + while (TRUE) { const char *changed_path; - svn_fs_path_change2_t *change = apr_hash_this_val(hi); const char *base_path = NULL; svn_revnum_t base_rev = SVN_INVALID_REVNUM; svn_fs_root_t *base_root = NULL; svn_string_t *prev_mergeinfo_value = NULL, *mergeinfo_value; + /* Next change. */ + SVN_ERR(svn_fs_path_change_get(&change, iterator)); + if (!change) + break; + /* Cheap pre-checks that don't require memory allocation etc. */ /* No mergeinfo change? -> nothing to do here. */ @@ -705,7 +719,7 @@ fs_mergeinfo_changed(svn_mergeinfo_catal continue; /* Begin actual processing */ - changed_path = apr_hash_this_key(hi); + changed_path = change->path.data; svn_pool_clear(iterpool); switch (change->change_kind) @@ -863,6 +877,8 @@ fs_mergeinfo_changed(svn_mergeinfo_catal } svn_pool_destroy(iterpool); + svn_pool_destroy(iterator_pool); + return SVN_NO_ERROR; }