Author: cmpilato
Date: Wed Nov 28 20:18:45 2012
New Revision: 1414894
URL: http://svn.apache.org/viewvc?rev=1414894&view=rev
Log:
Reintegrate the 'issue-4194-dev' branch into the trunk.
Modified:
subversion/trunk/ (props changed)
subversion/trunk/subversion/libsvn_ra_serf/update.c
Propchange: subversion/trunk/
------------------------------------------------------------------------------
Merged /subversion/branches/issue-4194-dev:r1410507-1414880
Modified: subversion/trunk/subversion/libsvn_ra_serf/update.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/update.c?rev=1414894&r1=1414893&r2=1414894&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/update.c Wed Nov 28 20:18:45 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,27 @@ 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 -- which would delete the pool from which the
+ relevant active_dir_propfinds list item is allocated -- and
+ of course don't crawl upward to check the parents for
+ a closure opportunity, either. */
+ 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)
@@ -1377,6 +1402,10 @@ handle_propchange_only(report_info_t *in
info->dir->ref_count--;
+ /* See if the parent directory of this file (and perhaps even
+ parents of that) can be closed now. */
+ SVN_ERR(maybe_close_dir_chain(info->dir));
+
return SVN_NO_ERROR;
}
@@ -1401,6 +1430,10 @@ handle_local_content(report_info_t *info
info->dir->ref_count--;
+ /* 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));
+
return SVN_NO_ERROR;
}
@@ -1565,12 +1598,7 @@ fetch_file(report_context_t *ctx, report
}
else
{
- /* No propfind or GET request. Just handle the prop changes now.
-
- Note: we'll use INFO->POOL for the scratch_pool here since it will
- be destroyed at the end of handle_propchange_only(). That pool
- would be quite fine, but it is unclear how long INFO->POOL will
- stick around since its lifetime and usage are unclear. */
+ /* No propfind or GET request. Just handle the prop changes now. */
SVN_ERR(handle_propchange_only(info, info->pool));
}
@@ -2126,13 +2154,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 +2171,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;
@@ -2150,6 +2185,12 @@ end_report(svn_ra_serf__xml_parser_t *pa
info->dir->propfind_handler = NULL;
}
+ /* See if this directory (and perhaps even parents of that) can
+ be closed now. This is likely to be the case only if we
+ didn't need to contact the server for supplemental
+ information required to handle any of this directory's
+ children. */
+ SVN_ERR(maybe_close_dir_chain(info->dir));
svn_ra_serf__xml_pop_state(parser);
}
else if (state == OPEN_FILE && strcmp(name.name, "open-file") == 0)
@@ -2695,10 +2736,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--;
@@ -2733,39 +2776,46 @@ finish_report(void *report_baton,
{
report_info_t *info = cur->data;
- /* If we've got cached file content for this file,
- take care of the locally collected properties and
- file content at once. Otherwise, just deal with
- the collected properties. */
- if (info->cached_contents)
+ if (!prev)
{
- SVN_ERR(handle_local_content(info, iterpool_inner));
+ report->file_propchanges_only = cur->next;
}
else
{
- SVN_ERR(handle_propchange_only(info, iterpool_inner));
+ prev->next = cur->next;
}
- if (!prev)
+ /* If we've got cached file content for this file,
+ take care of the locally collected properties and
+ file content at once. Otherwise, just deal with
+ the collected properties.
+
+ NOTE: These functions below could delete
+ info->dir->pool (via maybe_close_dir_chain()),
+ from which is allocated the list item in
+ report->file_propchanges_only.
+ */
+ if (info->cached_contents)
{
- report->file_propchanges_only = cur->next;
+ SVN_ERR(handle_local_content(info, iterpool_inner));
}
else
{
- prev->next = cur->next;
+ SVN_ERR(handle_propchange_only(info, iterpool_inner));
}
}
}
- 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
@@ -2776,14 +2826,77 @@ 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. */
+ perhaps even parents of that) can be closed now.
+
+ NOTE: This could delete cur_dir->pool, from which is
+ allocated the list item in report->done_fetches.
+ */
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.
+
+ NOTE: This could delete cur_dir->pool, from which is
+ allocated the list item in report->active_dir_propfinds.
+ */
+ 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