[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] Trace editor should free dir_baton when it's done.

From: Yoshiki Hayashi <yoshiki_at_xemacs.org>
Date: 2002-01-24 06:14:09 CET

While I was investigating issue 602 (importing large tree
bloats memory), I found that trace editor never frees memory
before it dies. The directory with compiled Linux kernel
and source contains about 12000 directory and files so that
amounts to about 12000 * (size of dir_baton or file_baton +
length of path). I don't think it uses much memory but it
would nicer not to consume memory linear to the number of
files and directories in a tree. Here's a patch to create
and destroy subpool based on the implementation of
libsvn_ra_local/commit_editor.c

Implement freeing directory button using reference counting.

* trace-commit.c

(struct dir_baton): New member, subpool and ref_count.
(decrement_dir_ref_count): New function, copied from
  libsvn_ra_local/commit_editor.
(open_root): Create subpool corresponding the directory. Initialize refcount.
(add_directory): Create subpool. Initialize refcount. Increment parent's
  refcount.
(open_directory): Ditto.
(close_directory): Call decrement_dir_ref_count.
(clsoe_file): Ditto.
(add_file): Increase parent's refcount.
(open_file): Ditto.

Index: ./subversion/clients/cmdline/trace-commit.c
===================================================================
--- ./subversion/clients/cmdline/trace-commit.c
+++ ./subversion/clients/cmdline/trace-commit.c Thu Jan 24 13:39:53 2002
@@ -51,6 +51,8 @@
   svn_stringbuf_t *path;
   svn_boolean_t added;
   svn_boolean_t prop_changed;
+ apr_pool_t *subpool;
+ int ref_count;
 };
 
 
@@ -66,14 +68,44 @@
 
 
 static svn_error_t *
+decrement_dir_ref_count (struct dir_baton *db)
+{
+ if (db == NULL)
+ return SVN_NO_ERROR;
+
+ db->ref_count--;
+
+ /* Check to see if *any* child batons still depend on this
+ directory's pool. */
+ if (db->ref_count == 0)
+ {
+ struct dir_baton *dbparent = db->parent_dir_baton;
+
+ /* Destroy all memory used by this baton, including the baton
+ itself! */
+ svn_pool_destroy (db->subpool);
+
+ /* Tell your parent that you're gone. */
+ SVN_ERR (decrement_dir_ref_count (dbparent));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 open_root (void *edit_baton, svn_revnum_t base_revision, void **root_baton)
 {
+ apr_pool_t *subpool;
   struct edit_baton *eb = edit_baton;
- struct dir_baton *rb = apr_pcalloc (eb->pool, sizeof (*rb));
+ struct dir_baton *rb;
 
+ subpool = svn_pool_create (eb->pool);;
+ rb = apr_pcalloc (eb->pool, sizeof (*rb));
   rb->edit_baton = eb;
   rb->parent_dir_baton = NULL;
   rb->path = eb->initial_path;
+ rb->subpool = subpool;
+ rb->ref_count = 1;
 
   *root_baton = rb;
 
@@ -102,16 +134,21 @@
                svn_revnum_t copyfrom_revision,
                void **child_baton)
 {
+ apr_pool_t *subpool;
   struct dir_baton *parent_d = parent_baton;
- struct dir_baton *child_d
- = apr_pcalloc (parent_d->edit_baton->pool, sizeof (*child_d));
+ struct dir_baton *child_d;
 
+ subpool = svn_pool_create (parent_d->subpool);
+ child_d = apr_pcalloc (parent_d->edit_baton->pool, sizeof (*child_d));
   child_d->edit_baton = parent_d->edit_baton;
   child_d->parent_dir_baton = parent_d;
   child_d->path = svn_stringbuf_dup (parent_d->path,
                                      child_d->edit_baton->pool);
   svn_path_add_component (child_d->path, name);
   child_d->added = TRUE;
+ child_d->subpool = subpool;
+ child_d->ref_count = 1;
+ parent_d->ref_count++;
 
   printf ("Adding %s\n", child_d->path->data);
   *child_baton = child_d;
@@ -126,15 +163,20 @@
                 svn_revnum_t base_revision,
                 void **child_baton)
 {
+ apr_pool_t *subpool;
   struct dir_baton *parent_d = parent_baton;
- struct dir_baton *child_d
- = apr_pcalloc (parent_d->edit_baton->pool, sizeof (*child_d));
+ struct dir_baton *child_d;
 
+ subpool = svn_pool_create (parent_d->subpool);
+ child_d = apr_pcalloc (parent_d->edit_baton->pool, sizeof (*child_d));
   child_d->edit_baton = parent_d->edit_baton;
   child_d->parent_dir_baton = parent_d;
   child_d->path = svn_stringbuf_dup (parent_d->path,
                                      child_d->edit_baton->pool);
   svn_path_add_component (child_d->path, name);
+ child_d->subpool = subpool;
+ child_d->ref_count = 1;
+ parent_d->ref_count++;
 
   *child_baton = child_d;
 
@@ -153,6 +195,7 @@
   if (db->prop_changed)
     printf ("Sending %s\n", db->path->data);
 
+ decrement_dir_ref_count (db);
   return SVN_NO_ERROR;
 }
 
@@ -168,7 +211,8 @@
             fb->path->data);
   else
     printf ("Sending %s\n", fb->path->data);
-
+
+ decrement_dir_ref_count (fb->parent_dir_baton);
   return SVN_NO_ERROR;
 }
 
@@ -218,6 +262,8 @@
   child_fb->binary = FALSE;
   *file_baton = child_fb;
 
+ parent_d->ref_count++;
+
   return SVN_NO_ERROR;
 }
 
@@ -238,6 +284,8 @@
   svn_path_add_component (child_fb->path, name);
 
   *file_baton = child_fb;
+
+ parent_d->ref_count++;
 
   return SVN_NO_ERROR;
 }

-- 
Yoshiki Hayashi
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Oct 21 14:36:58 2006

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.