You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by iv...@apache.org on 2015/09/19 17:22:51 UTC

svn commit: r1704048 - in /subversion/trunk: ./ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs_x/ tools/dev/

Author: ivan
Date: Sat Sep 19 15:22:50 2015
New Revision: 1704048

URL: http://svn.apache.org/viewvc?rev=1704048&view=rev
Log:
Introduce RA session pool in libsvn_client for managing and reusing RA session
for different URLs.

Discussion: "Merge ra-reuse-session branch to trunk or not?" [1]

More details are available in branch history [2].

[1] http://svn.haxx.se/dev/archive-2015-09/0173.shtml
[2] ^/subversion/branches/reuse-ra-session@1704029

* subversion/include/private/svn_client_private.h
  (svn_client__ra_session_from_path2): Update docstring to mention that RA
   session may be returned back to RA session pool by
   svn_client__ra_session_release() function.
  (svn_client__ra_session_release): New function declaration.

* subversion/libsvn_client/add.c
* subversion/libsvn_client/blame.c
* subversion/libsvn_client/cat.c
* subversion/libsvn_client/checkout.c
  (mkdir_urls, svn_client_blame5, svn_client_cat3,
   svn_client__checkout_internal): Release locally created sessions if there
   were no errors.
  
* subversion/libsvn_client/client.h
  (svn_client__ra_cache_t): Add new type declare.
  (svn_client__private_ctx_t): Add RA_CACHE field.

* subversion/libsvn_client/commit.c
  (check_url_kind_baton): Remove POOL, SESSION and REPOS_ROOT_URL -- they
   were used as local RA session pool.
  (check_url_kind): Just use svn_client_open_ra_session2() and
   svn_client__ra_session_release() instead of trying to reparent existing
   RA session.
  (svn_client_commit6): Update baton initialization and release locally
   created sessions if there were no errors.

* subversion/libsvn_client/copy.c
* subversion/libsvn_client/copy_foreign.c
* subversion/libsvn_client/ctx.c
* subversion/libsvn_client/delete.c
* subversion/libsvn_client/diff.c
* subversion/libsvn_client/export.c
* subversion/libsvn_client/externals.c
* subversion/libsvn_client/import.c
* subversion/libsvn_client/info.c
* subversion/libsvn_client/iprops.c
* subversion/libsvn_client/list.c
* subversion/libsvn_client/locking_commands.c
* subversion/libsvn_client/log.c
* subversion/libsvn_client/mtcc.c
* subversion/libsvn_client/prop_commands.c
  (pin_externals_prop, repos_to_repos_copy,  repos_to_repos_copy,
   wc_to_repos_copy,  repos_to_wc_copy,  svn_client__copy_foreign,
   delete_urls_multi_repos, diff_repos_repos, diff_repos_wc,
   svn_client_export5, handle_external_item_change, svn_client_import5,
   svn_client_info4, get_inheritable_props,  list_internal, release_locks,
   svn_client__get_copy_source, svn_client_log5, svn_client__mtcc_commit,
   propset_on_url): Release locally created sessions if there were no errors.

* subversion/libsvn_client/merge.c
  (ensure_ra_session_url): Add TODO comment to use release RA sessions back
   to RA session pool.
  (do_merge): Reduce scope of second RA session and return it early back to
   RA session pool.
  (merge_locked, merge_peg_locked, find_automatic_merge_no_wc,
   client_find_automatic_merge, do_automatic_merge_locked): Release locally
   created sessions if there were no errors.

* subversion/libsvn_client/mergeinfo.c
  (svn_client__get_wc_or_repos_mergeinfo_catalog, get_mergeinfo,
   logs_for_mergeinfo_rangelist, svn_client__mergeinfo_log,
   svn_client_suggest_merge_sources): Release locally created sessions if
   there were no errors.

* subversion/libsvn_client/ra.c
  (): Include "ra_cache.h"
  (svn_client__open_ra_session_internal): Use
   svn_client__ra_cache_open_session() to open RA session, instead of direct
   call to svn_ra_open4().
  (svn_client__repos_locations, svn_client__get_youngest_common_ancestor):
   Release RA sessions after we finished using them.
  (svn_client__ra_session_release): New.

* subversion/libsvn_client/ra_cache.c
* subversion/libsvn_client/ra_cache.h
  (MAX_INACTIVE_SESSIONS, INACTIVE_SESSION_TIMEOUT, cache_entry_t,
   open_tmp_file, get_wc_prop, set_wc_prop, push_wc_prop, invalidate_wc_props,
   progress_func, cancel_func, get_client_string,  get_wc_contents,
   check_tunnel_func,  open_tunnel_func,  cleanup_ra_cache,
   svn_client__ra_cache_init, close_ra_session, remove_inactive_entry,
   expunge_cache_entries, find_session_by_url, open_new_session,
   get_private_ra_cache, svn_client__ra_cache_open_session,
   svn_client__ra_cache_release_session): New.

* subversion/libsvn_client/status.c
* subversion/libsvn_client/switch.c
* subversion/libsvn_client/update.c
* subversion/libsvn_client/util.c
  (reporter_finish_report, svn_client_status6, switch_internal,
   svn_client__update_internal, svn_client_get_repos_root): Release locally
   created sessions if there were no errors.

* tools/dev/ra-cache-summary.py: New script to analyze debugging output of
  RA session reuse.

Added:
    subversion/trunk/subversion/libsvn_client/ra_cache.c
      - copied unchanged from r1704029, subversion/branches/reuse-ra-session/subversion/libsvn_client/ra_cache.c
    subversion/trunk/subversion/libsvn_client/ra_cache.h
      - copied unchanged from r1704029, subversion/branches/reuse-ra-session/subversion/libsvn_client/ra_cache.h
    subversion/trunk/tools/dev/ra-cache-summary.py
      - copied unchanged from r1704029, subversion/branches/reuse-ra-session/tools/dev/ra-cache-summary.py
Modified:
    subversion/trunk/   (props changed)
    subversion/trunk/subversion/include/private/svn_client_private.h
    subversion/trunk/subversion/libsvn_client/add.c
    subversion/trunk/subversion/libsvn_client/blame.c
    subversion/trunk/subversion/libsvn_client/cat.c
    subversion/trunk/subversion/libsvn_client/checkout.c
    subversion/trunk/subversion/libsvn_client/client.h
    subversion/trunk/subversion/libsvn_client/commit.c
    subversion/trunk/subversion/libsvn_client/copy.c
    subversion/trunk/subversion/libsvn_client/copy_foreign.c
    subversion/trunk/subversion/libsvn_client/ctx.c
    subversion/trunk/subversion/libsvn_client/delete.c
    subversion/trunk/subversion/libsvn_client/diff.c
    subversion/trunk/subversion/libsvn_client/export.c
    subversion/trunk/subversion/libsvn_client/externals.c
    subversion/trunk/subversion/libsvn_client/import.c
    subversion/trunk/subversion/libsvn_client/info.c
    subversion/trunk/subversion/libsvn_client/iprops.c
    subversion/trunk/subversion/libsvn_client/list.c
    subversion/trunk/subversion/libsvn_client/locking_commands.c
    subversion/trunk/subversion/libsvn_client/log.c
    subversion/trunk/subversion/libsvn_client/merge.c
    subversion/trunk/subversion/libsvn_client/mergeinfo.c
    subversion/trunk/subversion/libsvn_client/mtcc.c
    subversion/trunk/subversion/libsvn_client/prop_commands.c
    subversion/trunk/subversion/libsvn_client/ra.c
    subversion/trunk/subversion/libsvn_client/status.c
    subversion/trunk/subversion/libsvn_client/switch.c
    subversion/trunk/subversion/libsvn_client/update.c
    subversion/trunk/subversion/libsvn_client/util.c
    subversion/trunk/subversion/libsvn_fs_x/   (props changed)

Propchange: subversion/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Sep 19 15:22:50 2015
@@ -69,6 +69,7 @@
 /subversion/branches/ra_serf-digest-authn:875693-876404
 /subversion/branches/reintegrate-improvements:873853-874164
 /subversion/branches/remote-only-status:1581845-1586090
+/subversion/branches/reuse-ra-session:1501802-1704029
 /subversion/branches/revprop-cache:1298521-1326293
 /subversion/branches/revprop-caching-ng:1620597,1620599
 /subversion/branches/revprop-packing:1143907,1143971,1143997,1144017,1144499,1144568,1146145

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=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_client_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_client_private.h Sat Sep 19 15:22:50 2015
@@ -183,6 +183,10 @@ svn_client__pathrev_fspath(const svn_cli
    Use authentication baton cached in CTX to authenticate against the
    repository.
 
+   The caller may return *RA_SESSION_P to RA session cache by explicit
+   svn_client__ra_session_release() call. Otherwise RA session will be
+   closed on pool cleanup and will not be reused.
+
    Use POOL for all allocations. */
 svn_error_t *
 svn_client__ra_session_from_path2(svn_ra_session_t **ra_session_p,
@@ -194,6 +198,18 @@ svn_client__ra_session_from_path2(svn_ra
                                  svn_client_ctx_t *ctx,
                                  apr_pool_t *pool);
 
+/* Release repository access SESSION back to CTX's session cache.
+
+   The caller *MUST* ensure that SESSION is in a valid state:
+     - it has a valid connection to the server;
+     - if using a stateful protocol (i.e., ra_svn), a new series
+       of commands can be safely begun;
+     - any previous errors did not make the session unusable.
+*/
+svn_error_t *
+svn_client__ra_session_release(svn_client_ctx_t *ctx,
+                               svn_ra_session_t *session);
+
 /* Given PATH_OR_URL, which contains either a working copy path or an
    absolute URL, a peg revision PEG_REVISION, and a desired revision
    REVISION, find the path at which that object exists in REVISION,

Modified: subversion/trunk/subversion/libsvn_client/add.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/add.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/add.c (original)
+++ subversion/trunk/subversion/libsvn_client/add.c Sat Sep 19 15:22:50 2015
@@ -1198,7 +1198,9 @@ mkdir_urls(const apr_array_header_t *url
     }
 
   /* Close the edit. */
-  return svn_error_trace(editor->close_edit(edit_baton, pool));
+  SVN_ERR(editor->close_edit(edit_baton, pool));
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+  return SVN_NO_ERROR;
 }
 
 

Modified: subversion/trunk/subversion/libsvn_client/blame.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/blame.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/blame.c (original)
+++ subversion/trunk/subversion/libsvn_client/blame.c Sat Sep 19 15:22:50 2015
@@ -972,5 +972,6 @@ svn_client_blame5(const char *target,
     }
   svn_pool_destroy(iterpool);
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/libsvn_client/cat.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/cat.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/cat.c (original)
+++ subversion/trunk/subversion/libsvn_client/cat.c Sat Sep 19 15:22:50 2015
@@ -333,5 +333,6 @@ svn_client_cat3(apr_hash_t **returned_pr
     /* Close the interjected stream */
     SVN_ERR(svn_stream_close(output));
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/libsvn_client/checkout.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/checkout.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/checkout.c (original)
+++ subversion/trunk/subversion/libsvn_client/checkout.c Sat Sep 19 15:22:50 2015
@@ -81,6 +81,7 @@ svn_client__checkout_internal(svn_revnum
 {
   svn_node_kind_t kind;
   svn_client__pathrev_t *pathrev;
+  svn_boolean_t new_ra_session = FALSE;
 
   /* Sanity check.  Without these, the checkout is meaningless. */
   SVN_ERR_ASSERT(local_abspath != NULL);
@@ -122,6 +123,7 @@ svn_client__checkout_internal(svn_revnum
       SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &pathrev,
                                                 url, NULL, peg_revision,
                                                 revision, ctx, scratch_pool));
+      new_ra_session = TRUE;
     }
 
   SVN_ERR(svn_ra_check_path(ra_session, "", pathrev->rev, &kind, scratch_pool));
@@ -192,6 +194,8 @@ svn_client__checkout_internal(svn_revnum
                                       FALSE, FALSE, ra_session,
                                       ctx, scratch_pool));
 
+  if (new_ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/client.h?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/client.h (original)
+++ subversion/trunk/subversion/libsvn_client/client.h Sat Sep 19 15:22:50 2015
@@ -46,6 +46,9 @@ extern "C" {
 #endif /* __cplusplus */
 
 
+/* RA session cache */
+typedef struct svn_client__ra_cache_t svn_client__ra_cache_t;
+
 /* Private client context.
  *
  * This is what is actually allocated by svn_client_create_context2(),
@@ -63,6 +66,9 @@ typedef struct svn_client__private_ctx_t
   /* Total number of bytes transferred over network across all RA sessions. */
   apr_off_t total_progress;
 
+  /* The RA session cache. */
+  svn_client__ra_cache_t *ra_cache;
+
   /* The public context. */
   svn_client_ctx_t public_ctx;
 } svn_client__private_ctx_t;

Modified: subversion/trunk/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/commit.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/commit.c (original)
+++ subversion/trunk/subversion/libsvn_client/commit.c Sat Sep 19 15:22:50 2015
@@ -386,9 +386,6 @@ determine_lock_targets(apr_array_header_
 /* Baton for check_url_kind */
 struct check_url_kind_baton
 {
-  apr_pool_t *pool;
-  svn_ra_session_t *session;
-  const char *repos_root_url;
   svn_client_ctx_t *ctx;
 };
 
@@ -401,21 +398,19 @@ check_url_kind(void *baton,
                apr_pool_t *scratch_pool)
 {
   struct check_url_kind_baton *cukb = baton;
+  svn_ra_session_t *ra_session;
 
-  /* If we don't have a session or can't use the session, get one */
-  if (!cukb->session || !svn_uri__is_ancestor(cukb->repos_root_url, url))
-    {
-      SVN_ERR(svn_client_open_ra_session2(&cukb->session, url, NULL, cukb->ctx,
-                                          cukb->pool, scratch_pool));
-      SVN_ERR(svn_ra_get_repos_root2(cukb->session, &cukb->repos_root_url,
-                                     cukb->pool));
-    }
-  else
-    SVN_ERR(svn_ra_reparent(cukb->session, url, scratch_pool));
+  /* Open RA session: RA session cache framework will reuse existing
+     session if possible. */
+  SVN_ERR(svn_client_open_ra_session2(&ra_session, url, NULL, cukb->ctx,
+                                      scratch_pool, scratch_pool));
+
+  SVN_ERR(svn_ra_check_path(ra_session, "", revision, kind, scratch_pool));
+
+  /* Release RA session to cache. */
+  SVN_ERR(svn_client__ra_session_release(cukb->ctx, ra_session));
 
-  return svn_error_trace(
-                svn_ra_check_path(cukb->session, "", revision,
-                                  kind, scratch_pool));
+  return SVN_NO_ERROR;
 }
 
 /* Recurse into every target in REL_TARGETS, finding committable externals
@@ -518,7 +513,7 @@ svn_client_commit6(const apr_array_heade
   const svn_delta_editor_t *editor;
   void *edit_baton;
   struct capture_baton_t cb;
-  svn_ra_session_t *ra_session;
+  svn_ra_session_t *ra_session = NULL;
   const char *log_msg;
   const char *base_abspath;
   const char *base_url;
@@ -619,9 +614,6 @@ svn_client_commit6(const apr_array_heade
     struct check_url_kind_baton cukb;
 
     /* Prepare for when we have a copy containing not-present nodes. */
-    cukb.pool = iterpool;
-    cukb.session = NULL; /* ### Can we somehow reuse session? */
-    cukb.repos_root_url = NULL;
     cukb.ctx = ctx;
 
     cmt_err = svn_error_trace(
@@ -988,6 +980,10 @@ svn_client_commit6(const apr_array_heade
 
   svn_pool_destroy(iterpool);
 
-  return svn_error_trace(reconcile_errors(cmt_err, unlock_err, bump_err,
-                                          pool));
+  SVN_ERR(reconcile_errors(cmt_err, unlock_err, bump_err, pool));
+
+  if (ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+
+  return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/copy.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/copy.c (original)
+++ subversion/trunk/subversion/libsvn_client/copy.c Sat Sep 19 15:22:50 2015
@@ -435,6 +435,8 @@ pin_externals_prop(svn_string_t **pinned
               SVN_ERR(svn_ra_get_latest_revnum(external_ra_session,
                                                &latest_revnum,
                                                iterpool));
+              SVN_ERR(svn_client__ra_session_release(ctx,
+                                                     external_ra_session));
 
               external_pegrev.kind = svn_opt_revision_number;
               external_pegrev.value.number = latest_revnum;
@@ -1782,7 +1784,10 @@ repos_to_repos_copy(const apr_array_head
       SVN_ERR(svn_client__get_log_msg(&message, &tmp_file, commit_items,
                                       ctx, pool));
       if (! message)
-        return SVN_NO_ERROR;
+        {
+          SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+          return SVN_NO_ERROR;
+        }
     }
   else
     message = "";
@@ -1869,7 +1874,9 @@ repos_to_repos_copy(const apr_array_head
     }
 
   /* Close the edit. */
-  return svn_error_trace(editor->close_edit(edit_baton, pool));
+  SVN_ERR(editor->close_edit(edit_baton, pool));
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+  return SVN_NO_ERROR;
 }
 
 /* Baton for check_url_kind */
@@ -2223,6 +2230,7 @@ wc_to_repos_copy(const apr_array_header_
                                       ctx, scratch_pool));
       if (! message)
         {
+          SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
           svn_pool_destroy(iterpool);
           svn_pool_destroy(session_pool);
           return SVN_NO_ERROR;
@@ -2288,6 +2296,7 @@ wc_to_repos_copy(const apr_array_header_
                                   NULL, ctx, session_pool, session_pool),
             _("Commit failed (details follow):"));
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   svn_pool_destroy(iterpool);
   svn_pool_destroy(session_pool);
 
@@ -2743,6 +2752,8 @@ repos_to_wc_copy(svn_boolean_t *timestam
                             pin_externals, externals_to_pin,
                             ra_session, ctx, pool),
     ctx->wc_ctx, lock_abspath, FALSE, pool);
+
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_client/copy_foreign.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/copy_foreign.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/copy_foreign.c (original)
+++ subversion/trunk/subversion/libsvn_client/copy_foreign.c Sat Sep 19 15:22:50 2015
@@ -571,5 +571,6 @@ svn_client__copy_foreign(const char *url
                                  scratch_pool));
     }
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/libsvn_client/ctx.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/ctx.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/ctx.c (original)
+++ subversion/trunk/subversion/libsvn_client/ctx.c Sat Sep 19 15:22:50 2015
@@ -34,8 +34,8 @@
 #include "svn_error.h"
 
 #include "private/svn_wc_private.h"
-
 #include "client.h"
+#include "ra_cache.h"
 
 
 /*** Code. ***/
@@ -122,6 +122,7 @@ svn_client_create_context2(svn_client_ct
 
   SVN_ERR(svn_wc_context_create(&public_ctx->wc_ctx, cfg_config,
                                 pool, pool));
+  svn_client__ra_cache_init(private_ctx, cfg_hash, pool);
   *ctx = public_ctx;
 
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/delete.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/delete.c (original)
+++ subversion/trunk/subversion/libsvn_client/delete.c Sat Sep 19 15:22:50 2015
@@ -411,6 +411,15 @@ delete_urls_multi_repos(const apr_array_
                                   revprop_table, commit_callback,
                                   commit_baton, ctx, iterpool));
     }
+
+  /* Release all RA sessions. */
+  for (hi = apr_hash_first(pool, deletables); hi; hi = apr_hash_next(hi))
+    {
+      struct repos_deletables_t *repos_deletables = apr_hash_this_val(hi);
+      SVN_ERR(svn_client__ra_session_release(ctx,
+                                             repos_deletables->ra_session));
+    }
+
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Sat Sep 19 15:22:50 2015
@@ -1847,8 +1847,9 @@ diff_repos_repos(const char **root_relpa
                              FALSE, NULL,
                              scratch_pool));
 
-  return svn_error_trace(
-                  reporter->finish_report(reporter_baton, scratch_pool));
+  SVN_ERR(reporter->finish_report(reporter_baton, scratch_pool));
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+  return SVN_NO_ERROR;
 }
 
 /* Perform a diff between a repository path and a working-copy path.
@@ -2134,6 +2135,7 @@ diff_repos_wc(const char **root_relpath,
                                       scratch_pool));
     }
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/export.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/export.c (original)
+++ subversion/trunk/subversion/libsvn_client/export.c Sat Sep 19 15:22:50 2015
@@ -1448,6 +1448,8 @@ svn_client_export5(svn_revnum_t *result_
                                    from_path_or_url);
         }
       /* kind == svn_node_unknown not handled */
+
+      SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
     }
   else
     {

Modified: subversion/trunk/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/externals.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/externals.c (original)
+++ subversion/trunk/subversion/libsvn_client/externals.c Sat Sep 19 15:22:50 2015
@@ -724,6 +724,7 @@ handle_external_item_change(svn_client_c
   svn_client__pathrev_t *new_loc;
   const char *new_url;
   svn_node_kind_t ext_kind;
+  svn_boolean_t new_ra_session = FALSE;
 
   SVN_ERR_ASSERT(repos_root_url && parent_dir_url);
   SVN_ERR_ASSERT(new_item != NULL);
@@ -769,11 +770,14 @@ handle_external_item_change(svn_client_c
     }
 
   if (!ra_session)
-    SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &new_loc,
-                                              new_url, NULL,
-                                              &(new_item->peg_revision),
-                                              &(new_item->revision), ctx,
-                                              scratch_pool));
+    {
+      SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &new_loc,
+                                                new_url, NULL,
+                                                &(new_item->peg_revision),
+                                                &(new_item->revision), ctx,
+                                                scratch_pool));
+      new_ra_session = TRUE;
+    }
 
   SVN_ERR(svn_ra_check_path(ra_session, "", new_loc->rev, &ext_kind,
                             scratch_pool));
@@ -871,12 +875,15 @@ handle_external_item_change(svn_client_c
             new_url = svn_path_url_add_component2(local_repos_root_url,
                                                   ext_repos_relpath,
                                                   scratch_pool);
+            if (new_ra_session)
+              SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
             SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &new_loc,
                                                       new_url,
                                                       NULL,
                                                       &(new_item->peg_revision),
                                                       &(new_item->revision),
                                                       ctx, scratch_pool));
+            new_ra_session = TRUE;
           }
 
         SVN_ERR(switch_file_external(local_abspath,
@@ -895,6 +902,8 @@ handle_external_item_change(svn_client_c
         break;
     }
 
+  if (new_ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_client/import.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/import.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/import.c (original)
+++ subversion/trunk/subversion/libsvn_client/import.c Sat Sep 19 15:22:50 2015
@@ -1006,6 +1006,7 @@ svn_client_import5(const char *path,
                     editor->abort_edit(edit_baton, scratch_pool));
     }
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_client/info.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/info.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/info.c (original)
+++ subversion/trunk/subversion/libsvn_client/info.c Sat Sep 19 15:22:50 2015
@@ -457,6 +457,7 @@ svn_client_info4(const char *abspath_or_
                             depth, ctx, locks, pool));
     }
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_client/iprops.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/iprops.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/iprops.c (original)
+++ subversion/trunk/subversion/libsvn_client/iprops.c Sat Sep 19 15:22:50 2015
@@ -139,6 +139,7 @@ get_inheritable_props(apr_hash_t **wcroo
   apr_hash_index_t *hi;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   apr_pool_t *session_pool = NULL;
+  const svn_boolean_t new_ra_session = !ra_session;
   *wcroot_iprops = apr_hash_make(result_pool);
 
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
@@ -212,14 +213,19 @@ get_inheritable_props(apr_hash_t **wcroo
             {
               if (err->apr_err != SVN_ERR_FS_NOT_FOUND)
                 return svn_error_trace(err);
-
               svn_error_clear(err);
+
+              if (new_ra_session)
+                SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
               continue;
             }
 
           svn_hash_sets(*wcroot_iprops,
                         apr_pstrdup(result_pool, child_abspath),
                         inherited_props);
+
+          if (new_ra_session)
+            SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
         }
 
 

Modified: subversion/trunk/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/list.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/list.c (original)
+++ subversion/trunk/subversion/libsvn_client/list.c Sat Sep 19 15:22:50 2015
@@ -317,6 +317,7 @@ list_internal(const char *path_or_url,
                              ctx, pool));
     }
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/locking_commands.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/trunk/subversion/libsvn_client/locking_commands.c Sat Sep 19 15:22:50 2015
@@ -571,6 +571,8 @@ release_locks:
         }
     }
 
+  if (!err)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return svn_error_trace(err);
 }
 
@@ -644,6 +646,8 @@ release_locks:
         }
     }
 
+  if (!err)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return svn_error_trace(err);
 }
 

Modified: subversion/trunk/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/log.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/log.c (original)
+++ subversion/trunk/subversion/libsvn_client/log.c Sat Sep 19 15:22:50 2015
@@ -106,6 +106,7 @@ svn_client__get_copy_source(const char *
   apr_pool_t *sesspool = svn_pool_create(scratch_pool);
   svn_client__pathrev_t *at_loc;
   const char *old_session_url = NULL;
+  svn_boolean_t new_ra_session = FALSE;
 
   copyfrom_info.is_first = TRUE;
   copyfrom_info.path = NULL;
@@ -118,6 +119,7 @@ svn_client__get_copy_source(const char *
                                                 path_or_url, NULL,
                                                 revision, revision,
                                                 ctx, sesspool));
+      new_ra_session = TRUE;
     }
   else
     {
@@ -162,6 +164,8 @@ svn_client__get_copy_source(const char *
                     err,
                     svn_ra_reparent(ra_session, old_session_url, sesspool));
 
+  if (!err && new_ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   svn_pool_destroy(sesspool);
 
   if (err)
@@ -830,6 +834,9 @@ run_ra_get_log(apr_array_header_t *revis
     }
   svn_pool_destroy(iterpool);
 
+  if (rb.ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, rb.ra_session));
+
   return SVN_NO_ERROR;
 }
 
@@ -946,5 +953,6 @@ svn_client_log5(const apr_array_header_t
                          include_merged_revisions, revprops,
                          real_receiver, real_receiver_baton, ctx, pool));
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }

Modified: subversion/trunk/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/merge.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/merge.c (original)
+++ subversion/trunk/subversion/libsvn_client/merge.c Sat Sep 19 15:22:50 2015
@@ -9683,6 +9683,10 @@ ensure_ra_session_url(svn_ra_session_t *
   if (! *ra_session || (err && err->apr_err == SVN_ERR_RA_ILLEGAL_URL))
     {
       svn_error_clear(err);
+      /* RA_CACHE TODO: release RA session
+         The patch to rework RA session handling in merge is going to
+         be committed in trunk after merging:
+         http://svn.haxx.se/dev/archive-2015-02/0054.shtml */
       err = svn_client_open_ra_session2(ra_session, url, wri_abspath,
                                         ctx, pool, pool);
     }
@@ -9793,7 +9797,7 @@ do_merge(apr_hash_t **modified_subtrees,
   const char *preserved_exts_str;
   int i;
   svn_boolean_t checked_mergeinfo_capability = FALSE;
-  svn_ra_session_t *ra_session1 = NULL, *ra_session2 = NULL;
+  svn_ra_session_t *ra_session1 = NULL;
   const char *old_src_session_url = NULL;
   apr_pool_t *iterpool;
   const svn_diff_tree_processor_t *processor;
@@ -9925,6 +9929,7 @@ do_merge(apr_hash_t **modified_subtrees,
       merge_source_t *source =
         APR_ARRAY_IDX(merge_sources, i, merge_source_t *);
       single_range_conflict_report_t *conflicted_range_report;
+      svn_ra_session_t *ra_session2;
 
       svn_pool_clear(iterpool);
 
@@ -9937,8 +9942,10 @@ do_merge(apr_hash_t **modified_subtrees,
       /* Establish RA sessions to our URLs, reuse where possible. */
       SVN_ERR(ensure_ra_session_url(&ra_session1, source->loc1->url,
                                     target->abspath, ctx, scratch_pool));
-      SVN_ERR(ensure_ra_session_url(&ra_session2, source->loc2->url,
-                                    target->abspath, ctx, scratch_pool));
+
+      SVN_ERR(svn_client_open_ra_session2(&ra_session2, source->loc2->url,
+                                          target->abspath, ctx, iterpool,
+                                          iterpool));
 
       /* Populate the portions of the merge context baton that need to
          be reset for each merge source iteration. */
@@ -10014,6 +10021,8 @@ do_merge(apr_hash_t **modified_subtrees,
         }
       while (source);
 
+      SVN_ERR(svn_client__ra_session_release(ctx, ra_session2));
+
       /* The final mergeinfo on TARGET_WCPATH may itself elide. */
       if (! dry_run)
         SVN_ERR(svn_client__elide_mergeinfo(target->abspath, NULL,
@@ -10594,6 +10603,11 @@ merge_locked(conflict_report_t **conflic
                  ctx, result_pool, scratch_pool);
 
   /* Close our temporary RA sessions. */
+  if (!err)
+    {
+      SVN_ERR(svn_client__ra_session_release(ctx, ra_session2));
+      SVN_ERR(svn_client__ra_session_release(ctx, ra_session1));
+    }
   svn_pool_destroy(sesspool);
 
   if (use_sleep)
@@ -11758,6 +11772,12 @@ merge_reintegrate_locked(conflict_report
                                                ctx,
                                                result_pool, scratch_pool);
 
+  if (!err)
+    {
+      SVN_ERR(svn_client__ra_session_release(ctx, source_ra_session));
+      SVN_ERR(svn_client__ra_session_release(ctx, target_ra_session));
+    }
+
   if (use_sleep)
     svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
 
@@ -11865,6 +11885,8 @@ merge_peg_locked(conflict_report_t **con
                  ctx, result_pool, scratch_pool);
 
   /* We're done with our RA session. */
+  if (!err)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   svn_pool_destroy(sesspool);
 
   if (use_sleep)
@@ -12547,6 +12569,9 @@ find_automatic_merge_no_wc(automatic_mer
   SVN_ERR(find_automatic_merge(&merge->base, &merge->is_reintegrate_like, s_t,
                                ctx, result_pool, scratch_pool));
 
+  SVN_ERR(svn_client__ra_session_release(ctx, s_t->target_ra_session));
+  SVN_ERR(svn_client__ra_session_release(ctx, s_t->source_ra_session));
+
   merge->right = s_t->source;
   merge->target = &s_t->target->loc;
   merge->yca = s_t->yca;
@@ -12627,6 +12652,10 @@ client_find_automatic_merge(automatic_me
 
   SVN_ERR(find_automatic_merge(&merge->base, &merge->is_reintegrate_like, s_t,
                                ctx, result_pool, scratch_pool));
+
+  SVN_ERR(svn_client__ra_session_release(ctx, s_t->source_ra_session));
+  SVN_ERR(svn_client__ra_session_release(ctx, s_t->target_ra_session));
+
   merge->yca = s_t->yca;
   merge->right = s_t->source;
   merge->target = &s_t->target->loc;
@@ -12636,8 +12665,6 @@ client_find_automatic_merge(automatic_me
 
   *merge_p = merge;
 
-  /* TODO: Close the source and target sessions here? */
-
   return SVN_NO_ERROR;
 }
 
@@ -12697,9 +12724,8 @@ do_automatic_merge_locked(conflict_repor
   if (reintegrate_like)
     {
       merge_source_t source;
-      svn_ra_session_t *base_ra_session = NULL;
-      svn_ra_session_t *right_ra_session = NULL;
-      svn_ra_session_t *target_ra_session = NULL;
+      svn_ra_session_t *base_ra_session;
+      svn_ra_session_t *right_ra_session;
 
       if (record_only)
         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
@@ -12719,29 +12745,38 @@ do_automatic_merge_locked(conflict_repor
                                   "and the force_delete option "
                                   "cannot be used with this kind of merge"));
 
-      SVN_ERR(ensure_ra_session_url(&base_ra_session, merge->base->url,
-                                    target->abspath, ctx, scratch_pool));
-      SVN_ERR(ensure_ra_session_url(&right_ra_session, merge->right->url,
-                                    target->abspath, ctx, scratch_pool));
-      SVN_ERR(ensure_ra_session_url(&target_ra_session, target->loc.url,
-                                    target->abspath, ctx, scratch_pool));
+      SVN_ERR(svn_client_open_ra_session2(&right_ra_session, merge->right->url,
+                                          target->abspath, ctx, scratch_pool,
+                                          scratch_pool));
 
       /* Check for and reject any abnormalities -- such as revisions that
        * have not yet been merged in the opposite direction -- that a
        * 'reintegrate' merge would have rejected. */
       {
         merge_source_t *source2;
+        svn_ra_session_t *target_ra_session;
+
+        SVN_ERR(svn_client_open_ra_session2(&target_ra_session,
+                                            target->loc.url, target->abspath,
+                                            ctx, scratch_pool, scratch_pool));
 
         SVN_ERR(find_reintegrate_merge(&source2, NULL,
                                        right_ra_session, merge->right,
                                        target_ra_session, target,
                                        ctx, scratch_pool, scratch_pool));
+
+        SVN_ERR(svn_client__ra_session_release(ctx, target_ra_session));
       }
 
       source.loc1 = merge->base;
       source.loc2 = merge->right;
       source.ancestral = ! merge->is_reintegrate_like;
 
+      SVN_ERR(svn_client_open_ra_session2(&base_ra_session,
+                                          merge->base->url,
+                                          target->abspath, ctx, scratch_pool,
+                                          scratch_pool));
+
       err = merge_cousins_and_supplement_mergeinfo(conflict_report,
                                                    &use_sleep,
                                                    target,
@@ -12756,6 +12791,11 @@ do_automatic_merge_locked(conflict_repor
                                                    merge_options,
                                                    ctx,
                                                    result_pool, scratch_pool);
+      if (!err)
+        {
+          SVN_ERR(svn_client__ra_session_release(ctx, base_ra_session));
+          SVN_ERR(svn_client__ra_session_release(ctx, right_ra_session));
+        }
     }
   else /* ! merge->is_reintegrate_like */
     {
@@ -12769,12 +12809,13 @@ do_automatic_merge_locked(conflict_repor
          find the base for each sutree, and then here use the oldest base
          among all subtrees. */
       apr_array_header_t *merge_sources;
-      svn_ra_session_t *ra_session = NULL;
+      svn_ra_session_t *ra_session;
 
       /* Normalize our merge sources, do_merge() requires this.  See the
          'MERGEINFO MERGE SOURCE NORMALIZATION' global comment. */
-      SVN_ERR(ensure_ra_session_url(&ra_session, merge->right->url,
-                                    target->abspath, ctx, scratch_pool));
+      SVN_ERR(svn_client_open_ra_session2(&ra_session, merge->right->url,
+                                          target->abspath, ctx, scratch_pool,
+                                          scratch_pool));
       SVN_ERR(normalize_merge_sources_internal(
         &merge_sources, merge->right,
         svn_rangelist__initialize(merge->yca->rev, merge->right->rev, TRUE,
@@ -12788,6 +12829,8 @@ do_automatic_merge_locked(conflict_repor
                      force_delete, dry_run,
                      record_only, NULL, FALSE, FALSE, depth, merge_options,
                      ctx, result_pool, scratch_pool);
+      if (!err)
+        SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
     }
 
   if (use_sleep)

Modified: subversion/trunk/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mergeinfo.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/trunk/subversion/libsvn_client/mergeinfo.c Sat Sep 19 15:22:50 2015
@@ -679,15 +679,12 @@ svn_client__get_wc_or_repos_mergeinfo_ca
                                             result_pool, scratch_pool));
           if (!svn_hash_gets(original_props, SVN_PROP_MERGEINFO))
             {
-              apr_pool_t *sesspool = NULL;
+              const svn_boolean_t new_ra_session = !ra_session;
 
-              if (! ra_session)
-                {
-                  sesspool = svn_pool_create(scratch_pool);
-                  SVN_ERR(svn_client_open_ra_session2(&ra_session, url, NULL,
-                                                      ctx,
-                                                      sesspool, sesspool));
-                }
+              if (new_ra_session)
+                SVN_ERR(svn_client_open_ra_session2(
+                            &ra_session, url, NULL, ctx,
+                            scratch_pool, scratch_pool));
 
               SVN_ERR(svn_client__get_repos_mergeinfo_catalog(
                         &target_mergeinfo_cat_repos, ra_session,
@@ -707,10 +704,8 @@ svn_client__get_wc_or_repos_mergeinfo_ca
               /* If we created an RA_SESSION above, destroy it.
                  Otherwise, if reparented an existing session, point
                  it back where it was when we were called. */
-              if (sesspool)
-                {
-                  svn_pool_destroy(sesspool);
-                }
+              if (new_ra_session)
+                SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
             }
         }
     }
@@ -1043,6 +1038,7 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
   const char *local_abspath;
   svn_boolean_t use_url = svn_path_is_url(path_or_url);
   svn_client__pathrev_t *peg_loc;
+  svn_boolean_t new_ra_session = FALSE;
 
   if (ra_session && svn_path_is_url(path_or_url))
     {
@@ -1059,6 +1055,7 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
                                                 path_or_url, NULL,
                                                 peg_revision,
                                                 peg_revision, ctx, scratch_pool));
+      new_ra_session = TRUE;
     }
 
   /* If PATH_OR_URL is as working copy path determine if we will need to
@@ -1097,6 +1094,8 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
         result_pool, scratch_pool));
     }
 
+  if (new_ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 
@@ -1517,6 +1516,7 @@ logs_for_mergeinfo_rangelist(const char
   svn_merge_range_t *oldest_range, *youngest_range;
   svn_revnum_t oldest_rev, youngest_rev;
   struct filter_log_entry_baton_t fleb;
+  svn_boolean_t new_ra_session = FALSE;
 
   if (! rangelist->nelts)
     return SVN_NO_ERROR;
@@ -1552,9 +1552,12 @@ logs_for_mergeinfo_rangelist(const char
   fleb.ctx = ctx;
 
   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));
+    {
+      SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, source_url,
+                                                   NULL, NULL, FALSE, FALSE, ctx,
+                                                   scratch_pool, scratch_pool));
+      new_ra_session = TRUE;
+    }
   else
     SVN_ERR(svn_ra_reparent(ra_session, source_url, scratch_pool));
 
@@ -1575,6 +1578,9 @@ logs_for_mergeinfo_rangelist(const char
                             scratch_pool));
   }
 
+  if (new_ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+
   /* Check for cancellation. */
   if (ctx->cancel_func)
     SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
@@ -1706,6 +1712,7 @@ svn_client__mergeinfo_log(svn_boolean_t
   apr_hash_index_t *hi;
   apr_pool_t *iterpool;
   svn_boolean_t oldest_revs_first = TRUE;
+  svn_boolean_t new_target_session = FALSE;
   apr_pool_t *subpool;
 
   /* We currently only support depth = empty | infinity. */
@@ -1773,6 +1780,7 @@ svn_client__mergeinfo_log(svn_boolean_t
                                                         target_peg_revision,
                                                         target_peg_revision,
                                                         ctx, subpool));
+              new_target_session = TRUE;
             }
           SVN_ERR(svn_ra_get_repos_root2(target_session, &repos_root,
                                          scratch_pool));
@@ -1849,16 +1857,20 @@ svn_client__mergeinfo_log(svn_boolean_t
    * should share a single session, tracking the two URLs separately. */
   {
     svn_ra_session_t *source_session;
+    svn_boolean_t new_source_session = FALSE;
     svn_revnum_t start_rev, end_rev, youngest_rev = SVN_INVALID_REVNUM;
 
     if (! finding_merged)
       {
         if (!target_session)
-          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_client__ra_session_from_path2(&target_session, &pathrev,
+                                                      target_path_or_url, NULL,
+                                                      target_peg_revision,
+                                                      target_peg_revision,
+                                                      ctx, subpool));
+            new_target_session = TRUE;
+          }
         SVN_ERR(svn_client__get_history_as_mergeinfo(&target_history, NULL,
                                                      pathrev,
                                                      SVN_INVALID_REVNUM,
@@ -1888,6 +1900,7 @@ svn_client__mergeinfo_log(svn_boolean_t
                                                   source_peg_revision,
                                                   source_peg_revision,
                                                   ctx, subpool));
+        new_source_session = TRUE;
       }
     SVN_ERR(svn_client__get_revision_number(&start_rev, &youngest_rev,
                                             ctx->wc_ctx, source_path_or_url,
@@ -1907,6 +1920,10 @@ svn_client__mergeinfo_log(svn_boolean_t
                                                  scratch_pool));
     if (start_rev > end_rev)
       oldest_revs_first = FALSE;
+
+    /* Release the source session */
+    if (new_source_session)
+      SVN_ERR(svn_client__ra_session_release(ctx, source_session));
   }
 
   /* Separate the explicit or inherited mergeinfo on TARGET_PATH_OR_URL,
@@ -2177,7 +2194,9 @@ svn_client__mergeinfo_log(svn_boolean_t
                                        log_receiver, log_receiver_baton,
                                        ctx, target_session, scratch_pool);
 
-    /* Close the source and target sessions. */
+    /* Release or close the target session. */
+    if (!err && new_target_session)
+      SVN_ERR(svn_client__ra_session_release(ctx, target_session));
     svn_pool_destroy(subpool); /* For SVN_ERR_CEASE_INVOCATION */
 
     return svn_error_trace(err);
@@ -2291,6 +2310,7 @@ svn_client_suggest_merge_sources(apr_arr
         }
     }
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   svn_pool_destroy(session_pool);
 
   *suggestions = list;

Modified: subversion/trunk/subversion/libsvn_client/mtcc.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mtcc.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mtcc.c (original)
+++ subversion/trunk/subversion/libsvn_client/mtcc.c Sat Sep 19 15:22:50 2015
@@ -1423,6 +1423,8 @@ svn_client__mtcc_commit(apr_hash_t *revp
     err = svn_error_compose_create(err,
                                    editor->abort_edit(edit_baton, scratch_pool));
 
+  if (!err)
+    SVN_ERR(svn_client__ra_session_release(mtcc->ctx, mtcc->ra_session));
   svn_pool_destroy(mtcc->pool);
 
   return svn_error_trace(err);

Modified: subversion/trunk/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/prop_commands.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/trunk/subversion/libsvn_client/prop_commands.c Sat Sep 19 15:22:50 2015
@@ -250,7 +250,9 @@ propset_on_url(const char *propname,
       ctx->notify_func2(ctx->notify_baton2, notify, pool);
     }
   /* Close the edit. */
-  return editor->close_edit(edit_baton, pool);
+  SVN_ERR(editor->close_edit(edit_baton, pool));
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+  return SVN_NO_ERROR;
 }
 
 /* Check that PROPNAME is a valid name for a versioned property.  Return an
@@ -511,6 +513,8 @@ svn_client_revprop_set2(const char *prop
                                     original_propval, propval, pool));
     }
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+
   if (ctx->notify_func2)
     {
       svn_wc_notify_t *notify = svn_wc_create_notify_url(URL,
@@ -855,7 +859,6 @@ svn_client_propget5(apr_hash_t **props,
   if ((inherited_props && !local_iprops)
       || !local_explicit_props)
     {
-      svn_ra_session_t *ra_session;
       svn_node_kind_t kind;
       svn_opt_revision_t new_operative_rev;
       svn_opt_revision_t new_peg_rev;
@@ -933,6 +936,7 @@ svn_client_propget5(apr_hash_t **props,
       /* Do we still have anything to ask the repository about? */
       if (!local_explicit_props || !local_iprops)
         {
+          svn_ra_session_t *ra_session;
           svn_client__pathrev_t *loc;
 
           /* Get an RA plugin for this filesystem object. */
@@ -955,6 +959,7 @@ svn_client_propget5(apr_hash_t **props,
                                  kind, loc->rev, ra_session,
                                  depth, result_pool, scratch_pool));
           revnum = loc->rev;
+          SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
         }
     }
 
@@ -990,6 +995,8 @@ svn_client_revprop_get(const char *propn
   err = svn_ra_rev_prop(ra_session, *set_rev, propname, propval, pool);
 
   /* Close RA session */
+  if (!err)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   svn_pool_destroy(subpool);
   return svn_error_trace(err);
 }
@@ -1358,6 +1365,8 @@ get_remote_props(const char *path_or_url
                           depth, receiver, receiver_baton,
                           ctx->cancel_func, ctx->cancel_baton,
                           scratch_pool));
+
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 
@@ -1568,6 +1577,10 @@ svn_client_revprop_list(apr_hash_t **pro
   err = svn_ra_rev_proplist(ra_session, *set_rev, &proplist, pool);
 
   *props = proplist;
-  svn_pool_destroy(subpool); /* Close RA session */
+
+  /* Close RA session */
+  if (!err)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+  svn_pool_destroy(subpool);
   return svn_error_trace(err);
 }

Modified: subversion/trunk/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/ra.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/ra.c (original)
+++ subversion/trunk/subversion/libsvn_client/ra.c Sat Sep 19 15:22:50 2015
@@ -38,6 +38,7 @@
 #include "svn_mergeinfo.h"
 #include "client.h"
 #include "mergeinfo.h"
+#include "ra_cache.h"
 
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
@@ -418,10 +419,10 @@ svn_client__open_ra_session_internal(svn
 
           /* Try to open the RA session.  If this is our last attempt,
              don't accept corrected URLs from the RA provider. */
-          SVN_ERR(svn_ra_open4(ra_session,
-                               attempts_left == 0 ? NULL : &corrected,
-                               base_url, uuid, cbtable, cb, ctx->config,
-                               result_pool));
+          SVN_ERR(svn_client__ra_cache_open_session(
+                      ra_session, attempts_left == 0 ? NULL : &corrected,
+                      ctx, base_url, uuid, cbtable, cb,
+                      result_pool, scratch_pool));
 
           /* No error and no corrected URL?  We're done here. */
           if (! corrected)
@@ -453,8 +454,9 @@ svn_client__open_ra_session_internal(svn
     }
   else
     {
-      SVN_ERR(svn_ra_open4(ra_session, NULL, base_url,
-                           uuid, cbtable, cb, ctx->config, result_pool));
+      SVN_ERR(svn_client__ra_cache_open_session(
+                  ra_session, NULL, ctx, base_url, uuid, cbtable,
+                  cb, result_pool, scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -800,6 +802,7 @@ svn_client__repos_locations(const char *
   svn_revnum_t peg_revnum = SVN_INVALID_REVNUM;
   svn_revnum_t start_revnum, end_revnum;
   svn_revnum_t youngest_rev = SVN_INVALID_REVNUM;
+  svn_boolean_t new_ra_session = FALSE;
   apr_pool_t *subpool = svn_pool_create(pool);
 
   /* Ensure that we are given some real revision data to work with.
@@ -880,8 +883,11 @@ svn_client__repos_locations(const char *
 
   /* Open a RA session to this URL if we don't have one already. */
   if (! ra_session)
-    SVN_ERR(svn_client_open_ra_session2(&ra_session, url, NULL,
-                                        ctx, subpool, subpool));
+    {
+      SVN_ERR(svn_client_open_ra_session2(&ra_session, url, NULL,
+                                          ctx, subpool, subpool));
+      new_ra_session = TRUE;
+    }
 
   /* Resolve the opt_revision_ts. */
   if (peg_revnum == SVN_INVALID_REVNUM)
@@ -913,6 +919,9 @@ svn_client__repos_locations(const char *
                           ra_session, url, peg_revnum,
                           start_revnum, end_revnum, youngest_rev,
                           pool, subpool));
+
+  if (new_ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
 }
@@ -999,10 +1008,10 @@ svn_client__get_youngest_common_ancestor
                                          apr_pool_t *result_pool,
                                          apr_pool_t *scratch_pool)
 {
-  apr_pool_t *sesspool = NULL;
   apr_hash_t *history1, *history2;
   svn_boolean_t has_rev_zero_history1;
   svn_boolean_t has_rev_zero_history2;
+  svn_boolean_t new_ra_session = FALSE;
 
   if (strcmp(loc1->repos_root_url, loc2->repos_root_url) != 0)
     {
@@ -1013,9 +1022,9 @@ svn_client__get_youngest_common_ancestor
   /* Open an RA session for the two locations. */
   if (session == NULL)
     {
-      sesspool = svn_pool_create(scratch_pool);
       SVN_ERR(svn_client_open_ra_session2(&session, loc1->url, NULL, ctx,
-                                          sesspool, sesspool));
+                                          scratch_pool, scratch_pool));
+      new_ra_session = TRUE;
     }
 
   /* We're going to cheat and use history-as-mergeinfo because it
@@ -1032,9 +1041,10 @@ svn_client__get_youngest_common_ancestor
                                                SVN_INVALID_REVNUM,
                                                SVN_INVALID_REVNUM,
                                                session, ctx, scratch_pool));
+
   /* Close the ra session if we opened one. */
-  if (sesspool)
-    svn_pool_destroy(sesspool);
+  if (new_ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, session));
 
   SVN_ERR(svn_client__calc_youngest_common_ancestor(ancestor_p,
                                                     loc1, history1,
@@ -1188,3 +1198,11 @@ svn_client__ra_make_cb_baton(svn_wc_cont
 
   return reb;
 }
+
+svn_error_t *
+svn_client__ra_session_release(svn_client_ctx_t *ctx,
+                               svn_ra_session_t *session)
+{
+    svn_client__ra_cache_release_session(ctx, session);
+    return SVN_NO_ERROR;
+}

Modified: subversion/trunk/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/status.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/status.c (original)
+++ subversion/trunk/subversion/libsvn_client/status.c Sat Sep 19 15:22:50 2015
@@ -185,13 +185,11 @@ reporter_finish_report(void *report_bato
   svn_ra_session_t *ras;
   apr_hash_t *locks;
   const char *repos_root;
-  apr_pool_t *subpool = svn_pool_create(pool);
   svn_error_t *err = SVN_NO_ERROR;
 
-  /* Open an RA session to our common ancestor and grab the locks under it.
-   */
+  /* Open an RA session to our common ancestor and grab the locks under it. */
   SVN_ERR(svn_client_open_ra_session2(&ras, rb->ancestor, NULL,
-                                      rb->ctx, subpool, subpool));
+                                      rb->ctx, pool, pool));
 
   /* The locks need to live throughout the edit.  Note that if the
      server doesn't support lock discovery, we'll just not do locky
@@ -208,7 +206,7 @@ reporter_finish_report(void *report_bato
   SVN_ERR(svn_ra_get_repos_root2(ras, &repos_root, rb->pool));
 
   /* Close the RA session. */
-  svn_pool_destroy(subpool);
+  SVN_ERR(svn_client__ra_session_release(rb->ctx, ras));
 
   SVN_ERR(svn_wc_status_set_repos_locks(rb->set_locks_baton, locks,
                                         repos_root, rb->pool));
@@ -571,6 +569,8 @@ svn_client_status6(svn_revnum_t *result_
                                           NULL, NULL, pool));
         }
 
+      SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+
       if (ctx->notify_func2)
         {
           svn_wc_notify_t *notify

Modified: subversion/trunk/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/switch.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/switch.c (original)
+++ subversion/trunk/subversion/libsvn_client/switch.c Sat Sep 19 15:22:50 2015
@@ -369,6 +369,8 @@ switch_internal(svn_revnum_t *result_rev
                                            ctx, pool));
     }
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
+
   /* Let everyone know we're finished here. */
   if (ctx->notify_func2)
     {

Modified: subversion/trunk/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/update.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/update.c (original)
+++ subversion/trunk/subversion/libsvn_client/update.c Sat Sep 19 15:22:50 2015
@@ -570,6 +570,7 @@ svn_client__update_internal(svn_revnum_t
   svn_opt_revision_t peg_revision = *revision;
   apr_hash_t *conflicted_paths
     = ctx->conflict_func2 ? apr_hash_make(pool) : NULL;
+  const svn_boolean_t new_ra_session = !ra_session;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(! (innerupdate && make_parents));
@@ -665,6 +666,8 @@ svn_client__update_internal(svn_revnum_t
             err,
             svn_wc__release_write_lock(ctx->wc_ctx, lockroot_abspath, pool));
 
+  if (!err && new_ra_session && ra_session)
+    SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return svn_error_trace(err);
 }
 

Modified: subversion/trunk/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/util.c?rev=1704048&r1=1704047&r2=1704048&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/util.c (original)
+++ subversion/trunk/subversion/libsvn_client/util.c Sat Sep 19 15:22:50 2015
@@ -288,6 +288,7 @@ svn_client_get_repos_root(const char **r
   if (repos_uuid)
     SVN_ERR(svn_ra_get_uuid2(ra_session, repos_uuid, result_pool));
 
+  SVN_ERR(svn_client__ra_session_release(ctx, ra_session));
   return SVN_NO_ERROR;
 }
 

Propchange: subversion/trunk/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Sep 19 15:22:50 2015
@@ -67,6 +67,7 @@
 /subversion/branches/ra_serf-digest-authn/subversion/libsvn_fs_x:875693-876404
 /subversion/branches/reintegrate-improvements/subversion/libsvn_fs_x:873853-874164
 /subversion/branches/remote-only-status/subversion/libsvn_fs_x:1581845-1586090
+/subversion/branches/reuse-ra-session/subversion/libsvn_fs_x:1516837-1704029
 /subversion/branches/revprop-cache/subversion/libsvn_fs_x:1298521-1326293
 /subversion/branches/revprop-caching-ng/subversion/libsvn_fs_fs:1619782-1620595
 /subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x:1620597