You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by cm...@apache.org on 2012/11/16 18:57:40 UTC

svn commit: r1410510 - /subversion/branches/issue-4194-dev/subversion/libsvn_ra_serf/update.c

Author: cmpilato
Date: Fri Nov 16 17:57:40 2012
New Revision: 1410510

URL: http://svn.apache.org/viewvc?rev=1410510&view=rev
Log:
On the 'issue-4194-dev' branch:  Commit the current snapshot of my
branch code.  As with previous attempts at introducing more aggressive
directory closure, this too suffers from some as-yet-undetermined
memory management bug.  *sigh*

* subversion/libsvn_ra_serf/update.c
  (report_context_t): Add new 'done_dir_propfinds' and
    'active_dir_propfinds' list members.
  (maybe_close_dir_chain): Look through the 'active_dir_propfinds'
    list and make sure we aren't about to close a directory which is
    still being referred to from within that list.
  (end_report): Track directory PROPFINDs in separate lists now, the
    new 'done_dir_propfinds' and 'active_dir_propfinds' lists.
  (finish_report): Re-order some logic to try to avoid referencing
    free'd memory.  Call maybe_close_dir_chain() after processing
    files for which we only fetched properties.  Process the
    'done_dir_propfinds' list, too, closing completed directories
    opportunistically.

Modified:
    subversion/branches/issue-4194-dev/subversion/libsvn_ra_serf/update.c

Modified: subversion/branches/issue-4194-dev/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/issue-4194-dev/subversion/libsvn_ra_serf/update.c?rev=1410510&r1=1410509&r2=1410510&view=diff
==============================================================================
--- subversion/branches/issue-4194-dev/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/issue-4194-dev/subversion/libsvn_ra_serf/update.c Fri Nov 16 17:57:40 2012
@@ -357,6 +357,10 @@ struct report_context_t {
 
   /* completed PROPFIND requests (contains svn_ra_serf__handler_t) */
   svn_ra_serf__list_t *done_propfinds;
+  svn_ra_serf__list_t *done_dir_propfinds;
+
+  /* list of outstanding prop changes (contains report_dir_t) */
+  svn_ra_serf__list_t *active_dir_propfinds;
 
   /* list of files that only have prop changes (contains report_info_t) */
   svn_ra_serf__list_t *file_propchanges_only;
@@ -1347,6 +1351,24 @@ maybe_close_dir_chain(report_dir_t *dir)
     {
       report_dir_t *parent = cur_dir->parent_dir;
       report_context_t *report_context = cur_dir->report_context;
+      svn_boolean_t propfind_in_done_list = FALSE;
+      svn_ra_serf__list_t *done_list;
+
+      /* Make sure there are no references to this dir in the
+         active_dir_propfinds list.  If there are, don't close the
+         directory, and don't  -- we should be able to */
+      done_list = report_context->active_dir_propfinds;
+      while (done_list)
+        {
+          if (done_list->data == cur_dir)
+            {
+              propfind_in_done_list = TRUE;
+              break;
+            }
+          done_list = done_list->next;
+        }
+      if (propfind_in_done_list)
+        break;
 
       SVN_ERR(close_dir(cur_dir));
       if (parent)
@@ -2126,13 +2148,15 @@ end_report(svn_ra_serf__xml_parser_t *pa
        */
       if (info->dir->fetch_props)
         {
+          svn_ra_serf__list_t *list_item;
+ 
           SVN_ERR(svn_ra_serf__deliver_props(&info->dir->propfind_handler,
                                              info->dir->props, ctx->sess,
                                              get_best_connection(ctx),
                                              info->dir->url,
                                              ctx->target_rev, "0",
                                              all_props,
-                                             &ctx->done_propfinds,
+                                             &ctx->done_dir_propfinds,
                                              info->dir->pool));
           SVN_ERR_ASSERT(info->dir->propfind_handler);
 
@@ -2141,6 +2165,11 @@ end_report(svn_ra_serf__xml_parser_t *pa
 
           ctx->num_active_propfinds++;
 
+          list_item = apr_pcalloc(info->dir->pool, sizeof(*list_item));
+          list_item->data = info->dir;
+          list_item->next = ctx->active_dir_propfinds;
+          ctx->active_dir_propfinds = list_item;
+
           if (ctx->num_active_fetches + ctx->num_active_propfinds
               > REQUEST_COUNT_TO_PAUSE)
             ctx->parser_ctx->paused = TRUE;
@@ -2692,10 +2721,12 @@ finish_report(void *report_baton,
         SVN_ERR(open_connection_if_needed(sess, report->num_active_fetches +
                                           report->num_active_propfinds));
 
-      /* prune our propfind list if they are done. */
+      /* Prune completed file PROPFINDs. */
       done_list = report->done_propfinds;
       while (done_list)
         {
+          svn_ra_serf__list_t *next_done = done_list->next;
+
           svn_pool_clear(iterpool_inner);
 
           report->num_active_propfinds--;
@@ -2751,18 +2782,23 @@ finish_report(void *report_baton,
                     {
                       prev->next = cur->next;
                     }
+
+                  /* See if the parent directory of this fetched item (and
+                     perhaps even parents of that) can be closed now. */
+                  SVN_ERR(maybe_close_dir_chain(info->dir));
                 }
             }
 
-          done_list = done_list->next;
+          done_list = next_done;
         }
       report->done_propfinds = NULL;
 
-      /* Prune completely fetches from our list. */
+      /* Prune completed fetches from our list. */
       done_list = report->done_fetches;
       while (done_list)
         {
           report_fetch_t *done_fetch = done_list->data;
+          svn_ra_serf__list_t *next_done = done_list->next;
           report_dir_t *cur_dir;
 
           /* Decrease the refcount in the parent directory of the file
@@ -2773,14 +2809,69 @@ finish_report(void *report_baton,
           /* Decrement our active fetch count. */
           report->num_active_fetches--;
 
-          done_list = done_list->next;
-
           /* See if the parent directory of this fetched item (and
              perhaps even parents of that) can be closed now. */
           SVN_ERR(maybe_close_dir_chain(cur_dir));
+
+          done_list = next_done;
         }
       report->done_fetches = NULL;
 
+      /* Prune completed directory PROPFINDs. */
+      done_list = report->done_dir_propfinds;
+      while (done_list)
+        {
+          svn_ra_serf__list_t *next_done = done_list->next;
+
+          report->num_active_propfinds--;
+
+          if (report->active_dir_propfinds)
+            {
+              svn_ra_serf__list_t *cur, *prev;
+
+              prev = NULL;
+              cur = report->active_dir_propfinds;
+
+              while (cur)
+                {
+                  report_dir_t *item = cur->data;
+
+                  if (item->propfind_handler == done_list->data)
+                    {
+                      break;
+                    }
+
+                  prev = cur;
+                  cur = cur->next;
+                }
+              SVN_ERR_ASSERT(cur); /* we expect to find a matching propfind! */
+
+              /* If we found a match, set the new props and remove this
+               * propchange from our list.
+               */
+              if (cur)
+                {
+                  report_dir_t *cur_dir = cur->data;
+
+                  if (!prev)
+                    {
+                      report->active_dir_propfinds = cur->next;
+                    }
+                  else
+                    {
+                      prev->next = cur->next;
+                    }
+
+                  /* See if this directory (and perhaps even parents of that)
+                     can be closed now. */
+                  SVN_ERR(maybe_close_dir_chain(cur_dir));
+                }
+            }
+
+          done_list = next_done;
+        }
+      report->done_dir_propfinds = NULL;
+
       /* If the parser is paused, and the number of active requests has
          dropped far enough, then resume parsing.  */
       if (parser_ctx->paused