Philip Martin <philip.martin_at_wandisco.com> writes:
> Suppose serf were to keep track of the number of outstanding requests
> (it may already do that I haven't checked). Then if the number of
> outstanding requests is zero when the 411 is received the downgrade to
> HTTP/1.0 will be OK. Lots of client operations start with multiple
> requests in serial before switching to pipelined requests, so in all
> those cases the downgrade will work.
I've been experimenting with the following patch to implement the above
strategy. It's sufficient to allow me to checkout and commit through an
nginx proxy that does not support chunked encoding. I had hoped to run
the regression tests through nginx but for some reason the greek tree
import fails, although the same import run manually outside the
testsuite works. I'm not sure why that happens.
Index: subversion/libsvn_ra_serf/options.c
===================================================================
--- subversion/libsvn_ra_serf/options.c (revision 1497686)
+++ subversion/libsvn_ra_serf/options.c (working copy)
@@ -380,7 +380,14 @@ options_response_handler(serf_request_t *request,
return opt_ctx->inner_handler(request, response, opt_ctx->inner_baton, pool);
}
+static void
+request_reset(void *reset_baton)
+{
+ options_context_t *opt_ctx = reset_baton;
+ opt_ctx->headers_processed = FALSE;
+}
+
static svn_error_t *
create_options_req(options_context_t **opt_ctx,
svn_ra_serf__session_t *session,
@@ -417,6 +424,8 @@ create_options_req(options_context_t **opt_ctx,
new_ctx->inner_baton = handler->response_baton;
handler->response_handler = options_response_handler;
handler->response_baton = new_ctx;
+ handler->reset = request_reset;
+ handler->reset_baton = new_ctx;
*opt_ctx = new_ctx;
Index: subversion/libsvn_ra_serf/ra_serf.h
===================================================================
--- subversion/libsvn_ra_serf/ra_serf.h (revision 1497686)
+++ subversion/libsvn_ra_serf/ra_serf.h (working copy)
@@ -147,6 +147,8 @@ struct svn_ra_serf__session_t {
/* Should we use Transfer-Encoding: chunked for HTTP/1.1 servers. */
svn_boolean_t using_chunked_requests;
+ int requests_outstanding;
+
/* Our Version-Controlled-Configuration; may be NULL until we know it. */
const char *vcc_url;
@@ -410,6 +412,9 @@ typedef svn_error_t *
int status_code,
void *baton);
+typedef void
+(*svn_ra_serf__request_reset_t)(void *baton);
+
/* ### we should reorder the types in this file. */
typedef struct svn_ra_serf__server_error_t svn_ra_serf__server_error_t;
@@ -478,10 +483,15 @@ typedef struct svn_ra_serf__handler_t {
svn_ra_serf__request_body_delegate_t body_delegate;
void *body_delegate_baton;
+ svn_ra_serf__request_reset_t reset;
+ void *reset_baton;
+
/* The connection and session to be used for this request. */
svn_ra_serf__connection_t *conn;
svn_ra_serf__session_t *session;
+ svn_boolean_t response_seen;
+
/* Internal flag to indicate we've parsed the headers. */
svn_boolean_t reading_body;
Index: subversion/libsvn_ra_serf/util.c
===================================================================
--- subversion/libsvn_ra_serf/util.c (revision 1497686)
+++ subversion/libsvn_ra_serf/util.c (working copy)
@@ -800,7 +800,9 @@ svn_ra_serf__context_run_one(svn_ra_serf__handler_
apr_pool_t *scratch_pool)
{
svn_error_t *err;
+ svn_boolean_t first_time = TRUE;
+ retry:
/* Create a serf request based on HANDLER. */
svn_ra_serf__request_create(handler);
@@ -813,6 +815,17 @@ svn_ra_serf__context_run_one(svn_ra_serf__handler_
handler->server_error = NULL;
}
+ if (handler->sline.code == 411 && first_time)
+ {
+ handler->session->using_chunked_requests = FALSE;
+
+ if (!err && !handler->session->requests_outstanding)
+ {
+ first_time = FALSE;
+ goto retry;
+ }
+ }
+
return svn_error_trace(err);
}
@@ -1826,6 +1839,12 @@ handle_response(serf_request_t *request,
### ignored by the caller. */
*serf_status = APR_SUCCESS;
+ if (!handler->response_seen)
+ {
+ handler->response_seen = TRUE;
+ --handler->session->requests_outstanding;
+ }
+
if (!response)
{
/* Uh-oh. Our connection died. */
@@ -2207,8 +2226,12 @@ svn_ra_serf__request_create(svn_ra_serf__handler_t
handler->server_error = NULL;
handler->sline.version = 0;
handler->location = NULL;
+ handler->response_seen = FALSE;
handler->reading_body = FALSE;
handler->discard_body = FALSE;
+ ++handler->session->requests_outstanding;
+ if (handler->reset)
+ handler->reset(handler->reset_baton);
/* ### do we ever alter the >response_handler? */
--
Philip Martin | Subversion Committer
WANdisco | Non-Stop Data
www.wandisco.com
Received on 2013-06-28 17:18:22 CEST