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 2013/07/13 18:04:16 UTC

svn commit: r1502811 - in /subversion/trunk/subversion: include/private/svn_client_private.h libsvn_client/merge.c libsvn_client/mergeinfo.c

Author: rhuijben
Date: Sat Jul 13 16:04:16 2013
New Revision: 1502811

URL: http://svn.apache.org/r1502811
Log:
Optimize the ra session usage in the mergeinfo obtain code in general and
in the automatic merge calculation in particular.

This reduces the typical required ra sessions for calculating an automatic
merge to just 2 from about 8-10 before this patch. It should be possible
to reduce this number to 1 as for automatic merges the source and target
repository must be the same repository.

* subversion/include/private/svn_client_private.h
  (svn_client__mergeinfo_log): Add ra_session argument.

* subversion/libsvn_client/merge.c
  (short_circuit_mergeinfo_log): Pass ra session to svn_client__mergeinfo_log
    and restore old session url.
  (find_last_merged_location): Forward ra_session.
  (find_base_on_source): Pass ra_session.

* subversion/libsvn_client/mergeinfo.c
  (get_mergeinfo): Reuse ra session if provided.

  (logs_for_mergeinfo_rangelist): Reuse ra session by calling svn_ra_get_log2
    directly instead of performing more work to delegate everything to
    svn_client_log5, which then needs to perform more ra calls to obtain
    the same result.

  (svn_client_mergeinfo_get_merged): Update caller.

  (svn_client__mergeinfo_log): Accept ra session to avoid creating target
    and if possible also source ra sessions. Keep the session pool alive longer
    to allow using the same ra session to run the log on.

  (svn_client_mergeinfo_log2,
   svn_client_suggest_merge_sources): Update caller.

Modified:
    subversion/trunk/subversion/include/private/svn_client_private.h
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/libsvn_client/mergeinfo.c

Modified: subversion/trunk/subversion/include/private/svn_client_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_client_private.h?rev=1502811&r1=1502810&r2=1502811&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_client_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_client_private.h Sat Jul 13 16:04:16 2013
@@ -283,6 +283,11 @@ svn_client__copy_foreign(const char *url
  * The keys for the subtree mergeinfo are the repository root-relative
  * paths of TARGET_PATH_OR_URL and/or its subtrees, regardless of whether
  * TARGET_PATH_OR_URL is a URL or WC path.
+ *
+ * If RA_SESSION is not NULL, use it to obtain merge information instead of
+ * opening a new session. The session might be reparented after usage, so
+ * callers should reparent the session back to their original location if
+ * needed.
  */
 svn_error_t *
 svn_client__mergeinfo_log(svn_boolean_t finding_merged,
@@ -299,6 +304,7 @@ svn_client__mergeinfo_log(svn_boolean_t 
                           svn_depth_t depth,
                           const apr_array_header_t *revprops,
                           svn_client_ctx_t *ctx,
+                          svn_ra_session_t *ra_session,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool);
 

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1502811&r1=1502810&r2=1502811&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Sat Jul 13 16:04:16 2013
@@ -12050,11 +12050,15 @@ short_circuit_mergeinfo_log(svn_mergeinf
                             svn_log_entry_receiver_t receiver,
                             svn_revnum_t *revision,
                             svn_client_ctx_t *ctx,
+                            svn_ra_session_t *ra_session,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool)
 {
   apr_array_header_t *revprops;
   svn_error_t *err;
+  const char *session_url;
+
+  SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, scratch_pool));
 
   revprops = apr_array_make(scratch_pool, 0, sizeof(const char *));
   err = svn_client__mergeinfo_log(finding_merged,
@@ -12067,8 +12071,12 @@ short_circuit_mergeinfo_log(svn_mergeinf
                                   source_end_revision,
                                   receiver, revision,
                                   TRUE, svn_depth_infinity,
-                                  revprops, ctx, result_pool,
-                                  scratch_pool);
+                                  revprops, ctx, ra_session,
+                                  result_pool, scratch_pool);
+
+  err = svn_error_compose_create(
+                  err,
+                  svn_ra_reparent(ra_session, session_url, scratch_pool));
 
   if (err)
     {
@@ -12132,6 +12140,7 @@ find_last_merged_location(svn_client__pa
                           const branch_history_t *source_branch,
                           svn_client__pathrev_t *target,
                           svn_client_ctx_t *ctx,
+                          svn_ra_session_t *ra_session,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
 {
@@ -12159,7 +12168,8 @@ find_last_merged_location(svn_client__pa
                                       &source_end_rev, &source_start_rev,
                                       operative_rev_receiver,
                                       &youngest_merged_rev,
-                                      ctx, result_pool, scratch_pool));
+                                      ctx, ra_session,
+                                      result_pool, scratch_pool));
 
   if (!SVN_IS_VALID_REVNUM(youngest_merged_rev))
     {
@@ -12194,7 +12204,8 @@ find_last_merged_location(svn_client__pa
                                           &source_start_rev, &source_end_rev,
                                           operative_rev_receiver,
                                           &oldest_eligible_rev,
-                                          ctx, scratch_pool, scratch_pool));
+                                          ctx, ra_session,
+                                          scratch_pool, scratch_pool));
 
       /* If there are revisions eligible for merging, use the oldest one
          to calculate the base.  Otherwise there are no operative revisions
@@ -12248,7 +12259,9 @@ find_base_on_source(svn_client__pathrev_
                                     s_t->yca,
                                     &s_t->source_branch,
                                     s_t->target_branch.tip,
-                                    ctx, result_pool, scratch_pool));
+                                    ctx,
+                                    s_t->source_ra_session,
+                                    result_pool, scratch_pool));
   return SVN_NO_ERROR;
 }
 
@@ -12281,7 +12294,9 @@ find_base_on_target(svn_client__pathrev_
                                     s_t->yca,
                                     &s_t->target_branch,
                                     s_t->source,
-                                    ctx, result_pool, scratch_pool));
+                                    ctx,
+                                    s_t->target_ra_session,
+                                    result_pool, scratch_pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mergeinfo.c?rev=1502811&r1=1502810&r2=1502811&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_client/mergeinfo.c Sat Jul 13 16:04:16 2013
@@ -1021,6 +1021,11 @@ svn_client__elide_mergeinfo(const char *
    Set *REPOS_ROOT to the root URL of the repository associated with
    PATH_OR_URL.
 
+   If RA_SESSION is NOT NULL and PATH_OR_URL refers to a URL, RA_SESSION
+   (which must be of the repository containing PATH_OR_URL) will be used
+   instead of a temporary RA session. Caller is responsible for reparenting
+   the session if it wants to use it after the call.
+
    Allocate *MERGEINFO_CATALOG and all its contents in RESULT_POOL.  Use
    SCRATCH_POOL for all temporary allocations.
 
@@ -1034,17 +1039,30 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
               svn_boolean_t include_descendants,
               svn_boolean_t ignore_invalid_mergeinfo,
               svn_client_ctx_t *ctx,
+              svn_ra_session_t *ra_session,
               apr_pool_t *result_pool,
               apr_pool_t *scratch_pool)
 {
-  svn_ra_session_t *ra_session;
   const char *local_abspath;
   svn_boolean_t use_url = svn_path_is_url(path_or_url);
   svn_client__pathrev_t *peg_loc;
 
-  SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &peg_loc,
-                                            path_or_url, NULL, peg_revision,
-                                            peg_revision, ctx, scratch_pool));
+  if (ra_session && svn_path_is_url(path_or_url))
+    {
+      SVN_ERR(svn_ra_reparent(ra_session, path_or_url, scratch_pool));
+      SVN_ERR(svn_client__resolve_rev_and_url(&peg_loc, ra_session,
+                                              path_or_url,
+                                              peg_revision,
+                                              peg_revision,
+                                              ctx, scratch_pool));
+    }
+  else
+    {
+      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &peg_loc,
+                                                path_or_url, NULL,
+                                                peg_revision,
+                                                peg_revision, ctx, scratch_pool));
+    }
 
   /* If PATH_OR_URL is as working copy path determine if we will need to
      contact the repository for the requested PEG_REVISION. */
@@ -1064,10 +1082,6 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
       }
     }
 
-  /* Check server Merge Tracking capability. */
-  SVN_ERR(svn_ra__assert_mergeinfo_capable_server(ra_session, path_or_url,
-                                                  scratch_pool));
-
   SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool));
 
   if (use_url)
@@ -1496,29 +1510,22 @@ logs_for_mergeinfo_rangelist(const char 
                              svn_log_entry_receiver_t log_receiver,
                              void *log_receiver_baton,
                              svn_client_ctx_t *ctx,
+                             svn_ra_session_t *ra_session,
                              apr_pool_t *scratch_pool)
 {
-  apr_array_header_t *target;
   svn_merge_range_t *oldest_range, *youngest_range;
-  apr_array_header_t *revision_ranges;
-  svn_opt_revision_t oldest_rev, youngest_rev;
+  svn_revnum_t oldest_rev, youngest_rev;
   struct filter_log_entry_baton_t fleb;
 
   if (! rangelist->nelts)
     return SVN_NO_ERROR;
 
-  /* Build a single-member log target list using SOURCE_URL. */
-  target = apr_array_make(scratch_pool, 1, sizeof(const char *));
-  APR_ARRAY_PUSH(target, const char *) = source_url;
-
   /* Calculate and construct the bounds of our log request. */
   youngest_range = APR_ARRAY_IDX(rangelist, rangelist->nelts - 1,
                                  svn_merge_range_t *);
-  youngest_rev.kind = svn_opt_revision_number;
-  youngest_rev.value.number = youngest_range->end;
+  youngest_rev = youngest_range->end;
   oldest_range = APR_ARRAY_IDX(rangelist, 0, svn_merge_range_t *);
-  oldest_rev.kind = svn_opt_revision_number;
-  oldest_rev.value.number = oldest_range->start;
+  oldest_rev = oldest_range->start;
 
   if (! target_mergeinfo_catalog)
     target_mergeinfo_catalog = apr_hash_make(scratch_pool);
@@ -1543,19 +1550,29 @@ logs_for_mergeinfo_rangelist(const char 
   fleb.log_receiver_baton = log_receiver_baton;
   fleb.ctx = ctx;
 
-  /* Drive the log. */
-  revision_ranges = apr_array_make(scratch_pool, 1,
-                                   sizeof(svn_opt_revision_range_t *));
-  if (oldest_revs_first)
-    APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *)
-      = svn_opt__revision_range_create(&oldest_rev, &youngest_rev, scratch_pool);
+  if (!ra_session)
+    SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, source_url,
+                                                 NULL, NULL, FALSE, FALSE, ctx,
+                                                 scratch_pool, scratch_pool));
   else
-    APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *)
-      = svn_opt__revision_range_create(&youngest_rev, &oldest_rev, scratch_pool);
-  SVN_ERR(svn_client_log5(target, &youngest_rev, revision_ranges,
-                          0, discover_changed_paths, FALSE, FALSE, revprops,
-                          filter_log_entry_with_rangelist, &fleb, ctx,
-                          scratch_pool));
+    SVN_ERR(svn_ra_reparent(ra_session, source_url, scratch_pool));
+
+  {
+    apr_array_header_t *target;
+    target = apr_array_make(scratch_pool, 1, sizeof(const char *));
+    APR_ARRAY_PUSH(target, const char *) = "";
+
+    SVN_ERR(svn_ra_get_log2(ra_session, target,
+                            oldest_revs_first ? oldest_rev : youngest_rev,
+                            oldest_revs_first ? youngest_rev : oldest_rev,
+                            0 /* limit */,
+                            discover_changed_paths,
+                            FALSE /* strict_node_history */,
+                            FALSE /* include_merged_revisions */,
+                            revprops,
+                            filter_log_entry_with_rangelist, &fleb,
+                            scratch_pool));
+  }
 
   /* Check for cancellation. */
   if (ctx->cancel_func)
@@ -1616,7 +1633,7 @@ svn_client_mergeinfo_get_merged(apr_hash
   svn_mergeinfo_t mergeinfo;
 
   SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url,
-                        peg_revision, FALSE, FALSE, ctx, pool, pool));
+                        peg_revision, FALSE, FALSE, ctx, NULL, pool, pool));
   if (mergeinfo_cat)
     {
       const char *repos_relpath;
@@ -1662,6 +1679,7 @@ svn_client__mergeinfo_log(svn_boolean_t 
                           svn_depth_t depth,
                           const apr_array_header_t *revprops,
                           svn_client_ctx_t *ctx,
+                          svn_ra_session_t *ra_session,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
 {
@@ -1715,6 +1733,9 @@ svn_client__mergeinfo_log(svn_boolean_t 
 
   subpool = svn_pool_create(scratch_pool);
 
+  if (ra_session)
+    target_session = ra_session;
+
   /* We need the union of TARGET_PATH_OR_URL@TARGET_PEG_REVISION's mergeinfo
      and MERGE_SOURCE_URL's history.  It's not enough to do path
      matching, because renames in the history of MERGE_SOURCE_URL
@@ -1731,11 +1752,27 @@ svn_client__mergeinfo_log(svn_boolean_t 
              it ourselves.  We do need to get the repos_root
              though, because get_mergeinfo() won't do it for us. */
           target_mergeinfo_cat = *target_mergeinfo_catalog;
-          SVN_ERR(svn_client__ra_session_from_path2(&target_session, &pathrev,
-                                                    target_path_or_url, NULL,
-                                                    target_peg_revision,
-                                                    target_peg_revision,
-                                                    ctx, subpool));
+
+          if (ra_session && svn_path_is_url(target_path_or_url))
+            {
+              SVN_ERR(svn_ra_reparent(ra_session, target_path_or_url, subpool));
+              SVN_ERR(svn_client__resolve_rev_and_url(&pathrev, ra_session,
+                                                      target_path_or_url,
+                                                      target_peg_revision,
+                                                      target_peg_revision,
+                                                      ctx, subpool));
+              target_session = ra_session;
+            }
+          else
+            {
+              SVN_ERR(svn_client__ra_session_from_path2(&target_session,
+                                                        &pathrev,
+                                                        target_path_or_url,
+                                                        NULL,
+                                                        target_peg_revision,
+                                                        target_peg_revision,
+                                                        ctx, subpool));
+            }
           SVN_ERR(svn_ra_get_repos_root2(target_session, &repos_root,
                                          scratch_pool));
         }
@@ -1747,7 +1784,7 @@ svn_client__mergeinfo_log(svn_boolean_t 
           SVN_ERR(get_mergeinfo(target_mergeinfo_catalog, &repos_root,
                                 target_path_or_url, target_peg_revision,
                                 depth == svn_depth_infinity, TRUE,
-                                ctx, result_pool, scratch_pool));
+                                ctx, ra_session, result_pool, scratch_pool));
           target_mergeinfo_cat = *target_mergeinfo_catalog;
         }
     }
@@ -1759,7 +1796,7 @@ svn_client__mergeinfo_log(svn_boolean_t 
       SVN_ERR(get_mergeinfo(&target_mergeinfo_cat, &repos_root,
                             target_path_or_url, target_peg_revision,
                             depth == svn_depth_infinity, TRUE,
-                            ctx, scratch_pool, scratch_pool));
+                            ctx, ra_session, scratch_pool, scratch_pool));
     }
 
   if (!svn_path_is_url(target_path_or_url))
@@ -1829,11 +1866,28 @@ svn_client__mergeinfo_log(svn_boolean_t 
                                                      scratch_pool));
       }
 
-    SVN_ERR(svn_client__ra_session_from_path2(&source_session, &pathrev,
-                                              source_path_or_url, NULL,
-                                              source_peg_revision,
-                                              source_peg_revision,
-                                              ctx, subpool));
+    if (target_session
+        && svn_path_is_url(source_path_or_url)
+        && repos_root
+        && svn_uri_skip_ancestor(repos_root, source_path_or_url, subpool))
+      {
+        /* We can re-use the existing session */
+        source_session = target_session;
+        SVN_ERR(svn_ra_reparent(source_session, source_path_or_url, subpool));
+        SVN_ERR(svn_client__resolve_rev_and_url(&pathrev, source_session,
+                                                source_path_or_url,
+                                                source_peg_revision,
+                                                source_peg_revision,
+                                                ctx, subpool));
+      }
+    else
+      {
+        SVN_ERR(svn_client__ra_session_from_path2(&source_session, &pathrev,
+                                                  source_path_or_url, NULL,
+                                                  source_peg_revision,
+                                                  source_peg_revision,
+                                                  ctx, subpool));
+      }
     SVN_ERR(svn_client__get_revision_number(&start_rev, &youngest_rev,
                                             ctx->wc_ctx, source_path_or_url,
                                             source_session,
@@ -1852,9 +1906,6 @@ svn_client__mergeinfo_log(svn_boolean_t 
                                                  scratch_pool));
     if (start_rev > end_rev)
       oldest_revs_first = FALSE;
-
-    /* Close the source and target sessions. */
-    svn_pool_destroy(subpool);
   }
 
   /* Separate the explicit or inherited mergeinfo on TARGET_PATH_OR_URL,
@@ -2111,7 +2162,10 @@ svn_client__mergeinfo_log(svn_boolean_t 
   log_target = svn_path_url_add_component2(repos_root, log_target + 1,
                                            scratch_pool);
 
-  SVN_ERR(logs_for_mergeinfo_rangelist(log_target, merge_source_fspaths,
+  {
+    svn_error_t *err;
+
+    err = logs_for_mergeinfo_rangelist(log_target, merge_source_fspaths,
                                        finding_merged,
                                        master_inheritable_rangelist,
                                        oldest_revs_first,
@@ -2122,8 +2176,13 @@ svn_client__mergeinfo_log(svn_boolean_t 
                                        discover_changed_paths,
                                        revprops,
                                        log_receiver, log_receiver_baton,
-                                       ctx, scratch_pool));
-  return SVN_NO_ERROR;
+                                       ctx, target_session, scratch_pool);
+
+    /* Close the source and target sessions. */
+    svn_pool_destroy(subpool); /* For SVN_ERR_CEASE_INVOCATION */
+
+    return svn_error_trace(err);
+  }
 }
 
 svn_error_t *
@@ -2142,13 +2201,15 @@ svn_client_mergeinfo_log2(svn_boolean_t 
                           svn_client_ctx_t *ctx,
                           apr_pool_t *scratch_pool)
 {
-  return svn_client__mergeinfo_log(finding_merged, target_path_or_url,
+  return svn_error_trace(
+         svn_client__mergeinfo_log(finding_merged, target_path_or_url,
                                    target_peg_revision, NULL,
                                    source_path_or_url, source_peg_revision,
                                    source_start_revision, source_end_revision,
                                    log_receiver, log_receiver_baton,
                                    discover_changed_paths, depth, revprops,
-                                   ctx, scratch_pool, scratch_pool);
+                                   ctx, NULL,
+                                   scratch_pool, scratch_pool));
 }
 
 svn_error_t *
@@ -2186,7 +2247,7 @@ svn_client_suggest_merge_sources(apr_arr
 
   /* ### TODO: Share ra_session batons to improve efficiency? */
   SVN_ERR(get_mergeinfo(&mergeinfo_cat, &repos_root, path_or_url,
-                        peg_revision, FALSE, FALSE, ctx, pool, pool));
+                        peg_revision, FALSE, FALSE, ctx, NULL, pool, pool));
 
   if (mergeinfo_cat && apr_hash_count(mergeinfo_cat))
     {