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/02/01 01:08:50 UTC

svn commit: r1441273 - /subversion/trunk/subversion/libsvn_client/repos_diff.c

Author: rhuijben
Date: Fri Feb  1 00:08:50 2013
New Revision: 1441273

URL: http://svn.apache.org/viewvc?rev=1441273&view=rev
Log:
Separate pool lifetime of the repository diff handler batons from the
ra layer pools.

* subversion/libsvn_client/repos_diff.c
  (includes): Add assert.h.

  (dir_baton): Rename parent baton variable. Add user count.
  (file_baton): Add parent baton reference.

  (make_dir_baton): Store data in dir pool. Rename argument.
  (make_file_baton): Store parent baton handle. Use parent baton for
    obtaining edit baton.

  (release_dir): New function,

  (open_root): Create root baton in editor pool.

  (diff_deleted_file): Pass parent baton.
  (diff_deleted_dir): Create dir baton. Pass baton.

  (delete_entry): Update caller.

  (add_directory,
   open_directory): Store baton in parent baton pool.

  (add_file,
   open_file): Store baton in parent pool.

  (close_file,
   close_directory): Release baton via release_dir.

Modified:
    subversion/trunk/subversion/libsvn_client/repos_diff.c

Modified: subversion/trunk/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/repos_diff.c?rev=1441273&r1=1441272&r2=1441273&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/repos_diff.c Fri Feb  1 00:08:50 2013
@@ -34,6 +34,7 @@
 
 #include <apr_uri.h>
 #include <apr_md5.h>
+#include <assert.h>
 
 #include "svn_checksum.h"
 #include "svn_hash.h"
@@ -121,7 +122,7 @@ struct dir_baton {
 
   /* The baton for the parent directory, or null if this is the root of the
      hierarchy to be compared. */
-  struct dir_baton *dir_baton;
+  struct dir_baton *parent_baton;
 
   /* The overall crawler editor baton. */
   struct edit_baton *edit_baton;
@@ -143,11 +144,17 @@ struct dir_baton {
 
   /* Base revision of directory. */
   svn_revnum_t base_revision;
+
+  /* Number of users of baton. Its pool will be destroyed 0 */
+  int users;
 };
 
 /* File level baton.
  */
 struct file_baton {
+  /* Reference to parent baton */
+  struct dir_baton *parent_baton;
+
   /* Gets set if the file is added rather than replaced. */
   svn_boolean_t added;
 
@@ -219,12 +226,12 @@ make_dir_baton(const char *path,
                struct edit_baton *edit_baton,
                svn_boolean_t added,
                svn_revnum_t base_revision,
-               apr_pool_t *pool)
+               apr_pool_t *result_pool)
 {
-  apr_pool_t *dir_pool = svn_pool_create(pool);
+  apr_pool_t *dir_pool = svn_pool_create(result_pool);
   struct dir_baton *dir_baton = apr_pcalloc(dir_pool, sizeof(*dir_baton));
 
-  dir_baton->dir_baton = parent_baton;
+  dir_baton->parent_baton = parent_baton;
   dir_baton->edit_baton = edit_baton;
   dir_baton->added = added;
   dir_baton->tree_conflicted = FALSE;
@@ -232,12 +239,38 @@ make_dir_baton(const char *path,
   dir_baton->skip_children = FALSE;
   dir_baton->pool = dir_pool;
   dir_baton->path = apr_pstrdup(dir_pool, path);
-  dir_baton->propchanges  = apr_array_make(pool, 8, sizeof(svn_prop_t));
+  dir_baton->propchanges  = apr_array_make(dir_pool, 8, sizeof(svn_prop_t));
   dir_baton->base_revision = base_revision;
+  dir_baton->users++;
+
+  if (parent_baton)
+    parent_baton->users++;
 
   return dir_baton;
 }
 
+/* New function. Called by everyone who has a reference when done */
+static svn_error_t *
+release_dir(struct dir_baton *db)
+{
+  assert(db->users > 0);
+
+  db->users--;
+  if (db->users)
+     return SVN_NO_ERROR;
+
+  {
+    struct dir_baton *pb = db->parent_baton;
+
+    svn_pool_destroy(db->pool);
+
+    if (pb != NULL)
+      SVN_ERR(release_dir(pb));
+  }
+
+  return SVN_NO_ERROR;
+}
+
 /* Create a new file baton for PATH in POOL, which is a child of
  * directory PARENT_PATH. ADDED is set if this file is being added
  * rather than replaced.  EDIT_BATON is a pointer to the global edit
@@ -245,21 +278,24 @@ make_dir_baton(const char *path,
  */
 static struct file_baton *
 make_file_baton(const char *path,
+                struct dir_baton *parent_baton,
                 svn_boolean_t added,
-                struct edit_baton *edit_baton,
-                apr_pool_t *pool)
+                apr_pool_t *result_pool)
 {
-  apr_pool_t *file_pool = svn_pool_create(pool);
+  apr_pool_t *file_pool = svn_pool_create(result_pool);
   struct file_baton *file_baton = apr_pcalloc(file_pool, sizeof(*file_baton));
 
-  file_baton->edit_baton = edit_baton;
+  file_baton->parent_baton = parent_baton;
+  file_baton->edit_baton = parent_baton->edit_baton;
   file_baton->added = added;
   file_baton->tree_conflicted = FALSE;
   file_baton->skip = FALSE;
   file_baton->pool = file_pool;
   file_baton->path = apr_pstrdup(file_pool, path);
-  file_baton->propchanges  = apr_array_make(pool, 8, sizeof(svn_prop_t));
-  file_baton->base_revision = edit_baton->revision;
+  file_baton->propchanges  = apr_array_make(file_pool, 8, sizeof(svn_prop_t));
+  file_baton->base_revision = parent_baton->edit_baton->revision;
+
+  parent_baton->users++;
 
   return file_baton;
 }
@@ -420,7 +456,7 @@ open_root(void *edit_baton,
 {
   struct edit_baton *eb = edit_baton;
   struct dir_baton *db = make_dir_baton("", NULL, eb, FALSE, base_revision,
-                                        pool);
+                                        eb->pool);
 
   db->left_source = svn_diff__source_create(eb->revision, db->pool);
   db->right_source = svn_diff__source_create(eb->target_revision, db->pool);
@@ -445,11 +481,11 @@ open_root(void *edit_baton,
  */
 static svn_error_t *
 diff_deleted_file(const char *path,
-                  void *ppdb,
-                  struct edit_baton *eb,
+                  struct dir_baton *db,
                   apr_pool_t *scratch_pool)
 {
-  struct file_baton *fb = make_file_baton(path, FALSE, eb, scratch_pool);
+  struct edit_baton *eb = db->edit_baton;
+  struct file_baton *fb = make_file_baton(path, db, FALSE, scratch_pool);
   svn_boolean_t skip = FALSE;
   svn_diff_source_t *left_source = svn_diff__source_create(eb->revision,
                                                            scratch_pool);
@@ -461,7 +497,7 @@ diff_deleted_file(const char *path,
                                      left_source,
                                      NULL /* right_source */,
                                      NULL /* copyfrom_source */,
-                                     ppdb,
+                                     db->pdb,
                                      eb->processor,
                                      scratch_pool, scratch_pool));
 
@@ -495,10 +531,11 @@ diff_deleted_file(const char *path,
 /* ### TODO: Handle depth. */
 static svn_error_t *
 diff_deleted_dir(const char *path,
-                 void *ppdb,
-                 struct edit_baton *eb,
+                 struct dir_baton *pb,
                  apr_pool_t *scratch_pool)
 {
+  struct edit_baton *eb = pb->edit_baton;
+  struct dir_baton *db;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   svn_boolean_t skip = FALSE;
   svn_boolean_t skip_children = FALSE;
@@ -506,19 +543,20 @@ diff_deleted_dir(const char *path,
   apr_hash_t *left_props = NULL;
   svn_diff_source_t *left_source = svn_diff__source_create(eb->revision,
                                                            scratch_pool);
-  void *pdb;
+  db = make_dir_baton(path, pb, pb->edit_baton, FALSE, SVN_INVALID_REVNUM,
+                      scratch_pool);
 
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(eb->revision));
 
   if (eb->cancel_func)
     SVN_ERR(eb->cancel_func(eb->cancel_baton));
 
-  SVN_ERR(eb->processor->dir_opened(&pdb, &skip, &skip_children,
+  SVN_ERR(eb->processor->dir_opened(&db->pdb, &skip, &skip_children,
                                     path,
                                     left_source,
                                     NULL /* right_source */,
                                     NULL /* copyfrom_source */,
-                                    ppdb,
+                                    pb->pdb,
                                     eb->processor,
                                     scratch_pool, iterpool));
 
@@ -553,11 +591,11 @@ diff_deleted_dir(const char *path,
 
           if (dirent->kind == svn_node_file)
             {
-              SVN_ERR(diff_deleted_file(child_path, pdb, eb, iterpool));
+              SVN_ERR(diff_deleted_file(child_path, db, iterpool));
             }
           else if (dirent->kind == svn_node_dir)
             {
-              SVN_ERR(diff_deleted_dir(child_path, pdb, eb, iterpool));
+              SVN_ERR(diff_deleted_dir(child_path, db, iterpool));
             }
         }
     }
@@ -567,11 +605,13 @@ diff_deleted_dir(const char *path,
       SVN_ERR(eb->processor->dir_deleted(path,
                                          left_source,
                                          left_props,
-                                         pdb,
+                                         db->pdb,
                                          eb->processor,
                                          scratch_pool));
     }
 
+  SVN_ERR(release_dir(db));
+
   svn_pool_destroy(iterpool);
   return SVN_NO_ERROR;
 }
@@ -602,12 +642,12 @@ delete_entry(const char *path,
     {
     case svn_node_file:
       {
-        SVN_ERR(diff_deleted_file(path, pb->pdb, eb, scratch_pool));
+        SVN_ERR(diff_deleted_file(path, pb, scratch_pool));
         break;
       }
     case svn_node_dir:
       {
-        SVN_ERR(diff_deleted_dir(path, pb->pdb, eb, scratch_pool));
+        SVN_ERR(diff_deleted_dir(path, pb, scratch_pool));
         break;
       }
     default:
@@ -634,7 +674,7 @@ add_directory(const char *path,
 
   /* ### TODO: support copyfrom? */
 
-  db = make_dir_baton(path, pb, eb, TRUE, SVN_INVALID_REVNUM, pool);
+  db = make_dir_baton(path, pb, eb, TRUE, SVN_INVALID_REVNUM, pb->pool);
   *child_baton = db;
 
   /* Skip *everything* within a newly tree-conflicted directory,
@@ -675,7 +715,7 @@ open_directory(const char *path,
   struct edit_baton *eb = pb->edit_baton;
   struct dir_baton *db;
 
-  db = make_dir_baton(path, pb, eb, FALSE, base_revision, pool);
+  db = make_dir_baton(path, pb, eb, FALSE, base_revision, pb->pool);
 
   *child_baton = db;
 
@@ -719,7 +759,7 @@ add_file(const char *path,
 
   /* ### TODO: support copyfrom? */
 
-  fb = make_file_baton(path, TRUE, pb->edit_baton, pool);
+  fb = make_file_baton(path, pb, TRUE, pb->pool);
   *file_baton = fb;
 
   /* Process Skips. */
@@ -757,7 +797,7 @@ open_file(const char *path,
   struct dir_baton *pb = parent_baton;
   struct file_baton *fb;
   struct edit_baton *eb = pb->edit_baton;
-  fb = make_file_baton(path, FALSE, pb->edit_baton, pool);
+  fb = make_file_baton(path, pb, FALSE, pb->pool);
   *file_baton = fb;
 
   /* Process Skips. */
@@ -900,6 +940,7 @@ close_file(void *file_baton,
            apr_pool_t *pool)
 {
   struct file_baton *fb = file_baton;
+  struct dir_baton *pb = fb->parent_baton;
   struct edit_baton *eb = fb->edit_baton;
   apr_pool_t *scratch_pool;
 
@@ -907,6 +948,7 @@ close_file(void *file_baton,
   if (fb->skip)
     {
       svn_pool_destroy(fb->pool);
+      SVN_ERR(release_dir(pb));
       return SVN_NO_ERROR;
     }
 
@@ -975,6 +1017,8 @@ close_file(void *file_baton,
 
   svn_pool_destroy(fb->pool); /* Destroy file and scratch pool */
 
+  SVN_ERR(release_dir(pb));
+
   return SVN_NO_ERROR;
 }
 
@@ -1058,8 +1102,7 @@ close_directory(void *dir_baton,
                                         eb->processor,
                                         db->pool));
     }
-
-  svn_pool_destroy(db->pool); /* Destroy baton and scratch_pool */
+  SVN_ERR(release_dir(db));
 
   return SVN_NO_ERROR;
 }