Author: stefan2
Date: Sun Feb 14 18:29:05 2016
New Revision: 1730368

URL: http://svn.apache.org/viewvc?rev=1730368&view=rev
Log:
Tighten the pool usage in mod_dav_svn's commit response.

* subversion/mod_dav_svn/merge.c
  (do_resources): Rename the SUBPOOL to ITERPOOL.
                  Introduce SUBPOOL for everything else allocated here
                  and release it immediately at the end.

Modified:
    subversion/trunk/subversion/mod_dav_svn/merge.c

Modified: subversion/trunk/subversion/mod_dav_svn/merge.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/merge.c?rev=1730368&r1=1730367&r2=1730368&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/merge.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/merge.c Sun Feb 14 18:29:05 2016
@@ -120,18 +120,24 @@ do_resources(const dav_svn_repos *repos,
              apr_pool_t *pool)
 {
   apr_hash_t *changes;
-  apr_hash_t *sent = apr_hash_make(pool);
   apr_hash_index_t *hi;
+
+  /* Change lists can have >100000 entries, so we must make sure to release
+     any collection as soon as possible.  Allocate them in SUBPOOL. */
   apr_pool_t *subpool = svn_pool_create(pool);
+  apr_hash_t *sent = apr_hash_make(subpool);
+
+  /* Standard iteration pool. */
+  apr_pool_t *iterpool = svn_pool_create(subpool);
 
   /* Fetch the paths changed in this revision.  This will contain
      everything except otherwise-unchanged parent directories of added
      and deleted things.  Also, note that deleted things don't merit
      responses of their own -- they are considered modifications to
      their parent.  */
-  SVN_ERR(svn_fs_paths_changed2(&changes, root, pool));
+  SVN_ERR(svn_fs_paths_changed2(&changes, root, subpool));
 
-  for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(subpool, changes); hi; hi = apr_hash_next(hi))
     {
       const void *key;
       void *val;
@@ -141,7 +147,7 @@ do_resources(const dav_svn_repos *repos,
       svn_boolean_t send_self;
       svn_boolean_t send_parent;
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
       apr_hash_this(hi, &key, &path_len, &val);
       path = key;
       change = val;
@@ -174,10 +180,10 @@ do_resources(const dav_svn_repos *repos,
           if (! apr_hash_get(sent, path, path_len))
             {
               svn_node_kind_t kind;
-              SVN_ERR(svn_fs_check_path(&kind, root, path, subpool));
+              SVN_ERR(svn_fs_check_path(&kind, root, path, iterpool));
               SVN_ERR(send_response(repos, root, path,
                                     kind == svn_node_dir,
-                                    output, bb, subpool));
+                                    output, bb, iterpool));
 
               /* The paths in CHANGES are unique, i.e. they can only
                * clash with those that we end in the SEND_PARENT case.
@@ -190,16 +196,12 @@ do_resources(const dav_svn_repos *repos,
         }
       if (send_parent)
         {
-          /* If it hasn't already been sent, send the parent directory
-             (and then remember that you sent it).  Allocate parent in
-             pool, not subpool, because it stays in the sent hash
-             afterwards. */
-          const char *parent = svn_fspath__dirname(path, pool);
+          const char *parent = svn_fspath__dirname(path, iterpool);
           if (! svn_hash_gets(sent, parent))
             {
               SVN_ERR(send_response(repos, root, parent,
-                                    TRUE, output, bb, subpool));
-              svn_hash_sets(sent, parent, (void *)1);
+                                    TRUE, output, bb, iterpool));
+              svn_hash_sets(sent, apr_pstrdup(subpool, parent), (void *)1);
             }
         }
     }


Reply via email to