Author: rhuijben
Date: Mon Aug 8 23:59:41 2011
New Revision: 1155160
URL: http://svn.apache.org/viewvc?rev=1155160&view=rev
Log:
Make serf capable of checking out from Subversion 1.3 repositories with the/a
"lost response" with lingering close bug. (See also r858579)
This code is not pretty but it is a safe and local fix to this problem.
Fixing this problem in a clean way probably requires some design changes to
the request creation in ra_serf.
Before fixing the calculation bug in r1154733 checking out neon from its
repository was completely impossible. But after that fix checkout still failed
in about 30-50% of the cases. This patch fixes those remaining failures by
applying the same fix to the xml requests.
* subversion/libsvn_ra_serf/ra_serf.h
(svn_ra_serf__xml_parser_t): Add 3 variables to allow tracking restarted
connections.
* subversion/libsvn_ra_serf/util.c
(svn_ra_serf__handle_xml_parser): Detect restarted requests by checking if
the response headers changed since the last invocation. If so apply the same
skip trick as used in ra_serf/update.c to avoid reading the same xml twice,
which makes the xml invalid as <?xml is only valid at the start of the xml.
Modified:
subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
subversion/trunk/subversion/libsvn_ra_serf/util.c
Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=1155160&r1=1155159&r2=1155160&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Mon Aug 8 23:59:41
2011
@@ -629,6 +629,11 @@ struct svn_ra_serf__xml_parser_t {
See libsvn_ra_serf/util.c */
struct svn_ra_serf__pending_t *pending;
+
+ /* Response restart support */
+ const void *headers_baton; /* Last pointer to headers */
+ apr_off_t skip_size; /* Number of bytes to skip */
+ apr_off_t read_size; /* Number of bytes read from response */
};
/*
Modified: subversion/trunk/subversion/libsvn_ra_serf/util.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/util.c?rev=1155160&r1=1155159&r2=1155160&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/util.c Mon Aug 8 23:59:41 2011
@@ -1705,6 +1705,22 @@ svn_ra_serf__handle_xml_parser(serf_requ
return SVN_NO_ERROR;
}
+ if (ctx->headers_baton == NULL)
+ ctx->headers_baton = serf_bucket_response_get_headers(response);
+ else if (ctx->headers_baton != serf_bucket_response_get_headers(response))
+ {
+ /* We got a new response to an existing parser...
+ This tells us the connection has restarted and we should continue
+ where we stopped last time.
+ */
+
+ /* Is this a second attempt?? */
+ if (!ctx->skip_size)
+ ctx->skip_size = ctx->read_size;
+
+ ctx->read_size = 0; /* New request, nothing read */
+ }
+
if (!ctx->xmlp)
{
ctx->xmlp = XML_ParserCreate(NULL);
@@ -1749,6 +1765,35 @@ svn_ra_serf__handle_xml_parser(serf_requ
return svn_error_wrap_apr(status, NULL);
}
+ ctx->read_size += len;
+
+ if (ctx->skip_size)
+ {
+ /* Handle restarted requests correctly: Skip what we already read */
+ apr_size_t skip;
+
+ if (ctx->skip_size >= ctx->read_size)
+ {
+ /* Eek. What did the file shrink or something? */
+ if (APR_STATUS_IS_EOF(status))
+ {
+ SVN_ERR_MALFUNCTION();
+ }
+
+ /* Skip on to the next iteration of this loop. */
+ if (APR_STATUS_IS_EAGAIN(status))
+ {
+ return svn_error_wrap_apr(status, NULL);
+ }
+ continue;
+ }
+
+ skip = (apr_size_t)(len - (ctx->read_size - ctx->skip_size));
+ data += skip;
+ len -= skip;
+ ctx->skip_size = 0;
+ }
+
/* Ensure that the parser's PAUSED state is correct before we test
the flag. */
PBTEST_SET_PAUSED(ctx);