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