Author: ivan Date: Mon Jul 15 16:05:27 2013 New Revision: 1503318 URL: http://svn.apache.org/r1503318 Log: ra_serf: Do not retry HTTP requests if we started to parse them. There is absolutely no guarantee that REPORT or PROPFIND responses will be equal for every request. Especially with taking to account hash randomization.
* subversion/libsvn_ra_serf/ra_serf.h (svn_ra_serf__xml_parser_t): Remove HEADERS_BATON, SKIP_SIZE and READ_SIZE. * subversion/libsvn_ra_serf/util.c (svn_ra_serf__handle_xml_parser): Remove code to skip partially received responses. (handle_response): Requeue request if RESPONSE_ERROR handler is configured and didn't return error or we didn't start reading response body. 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=1503318&r1=1503317&r2=1503318&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original) +++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Mon Jul 15 16:05:27 2013 @@ -658,11 +658,6 @@ 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=1503318&r1=1503317&r2=1503318&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_ra_serf/util.c (original) +++ subversion/trunk/subversion/libsvn_ra_serf/util.c Mon Jul 15 16:05:27 2013 @@ -1624,22 +1624,6 @@ svn_ra_serf__handle_xml_parser(serf_requ return svn_error_trace(err); } - 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); @@ -1659,41 +1643,11 @@ svn_ra_serf__handle_xml_parser(serf_requ apr_size_t len; status = serf_bucket_read(response, PARSE_CHUNK_SIZE, &data, &len); - if (SERF_BUCKET_READ_ERROR(status)) { return svn_ra_serf__wrap_err(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_ra_serf__wrap_err(status, NULL); - } - continue; - } - - skip = (apr_size_t)(len - (ctx->read_size - ctx->skip_size)); - data += skip; - len -= skip; - ctx->skip_size = 0; - } - /* Note: once the callbacks invoked by inject_to_parser() sets the PAUSED flag, then it will not be cleared. write_to_pending() will only save the content. Logic outside of serf_context_run() will @@ -1877,12 +1831,26 @@ handle_response(serf_request_t *request, { /* Uh-oh. Our connection died. */ if (handler->response_error) - SVN_ERR(handler->response_error(request, response, 0, - handler->response_error_baton)); - - /* Requeue another request for this handler. - ### how do we know if the handler can deal with this?! */ - svn_ra_serf__request_create(handler); + { + /* Give a handler chance to prevent request requeue. */ + SVN_ERR(handler->response_error(request, response, 0, + handler->response_error_baton)); + + svn_ra_serf__request_create(handler); + } + /* Response error callback is not configured. Requeue another request + for this handler only if we didn't started to process body. + Return error otherwise. */ + else if (!handler->reading_body) + { + svn_ra_serf__request_create(handler); + } + else + { + return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL, + _("%s request on '%s' failed"), + handler->method, handler->path); + } return SVN_NO_ERROR; }