You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/01/09 10:31:15 UTC
svn commit: r1556765 [8/12] - in /subversion/branches/fsfs-ucsnorm: ./
contrib/server-side/fsfsfixer/fixer/ subversion/bindings/javahl/native/
subversion/bindings/javahl/native/jniwrapper/
subversion/bindings/javahl/src/org/apache/subversion/javahl/ su...
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/util.c Thu Jan 9 09:31:10 2014
@@ -76,25 +76,6 @@
/* Read/write chunks of this size into the spillbuf. */
#define PARSE_CHUNK_SIZE 8000
-/* We will store one megabyte in memory, before switching to store content
- into a temporary file. */
-#define SPILL_SIZE 1000000
-
-
-/* This structure records pending data for the parser in memory blocks,
- and possibly into a temporary file if "too much" content arrives. */
-struct svn_ra_serf__pending_t {
- /* The spillbuf where we record the pending data. */
- svn_spillbuf_t *buf;
-
- /* This flag is set when the network has reached EOF. The PENDING
- processing can then properly detect when parsing has completed. */
- svn_boolean_t network_eof;
-};
-
-#define HAS_PENDING_DATA(p) ((p) != NULL && (p)->buf != NULL \
- && svn_spillbuf__get_size((p)->buf) != 0)
-
struct expat_ctx_t {
svn_ra_serf__xml_context_t *xmlctx;
@@ -884,6 +865,72 @@ setup_serf_req(serf_request_t *request,
}
svn_error_t *
+svn_ra_serf__context_run(svn_ra_serf__session_t *sess,
+ apr_interval_time_t *waittime_left,
+ apr_pool_t *scratch_pool)
+{
+ apr_status_t status;
+ svn_error_t *err;
+ assert(sess->pending_error == SVN_NO_ERROR);
+
+ if (sess->cancel_func)
+ SVN_ERR(sess->cancel_func(sess->cancel_baton));
+
+ status = serf_context_run(sess->context,
+ SVN_RA_SERF__CONTEXT_RUN_DURATION,
+ scratch_pool);
+
+ err = sess->pending_error;
+ sess->pending_error = SVN_NO_ERROR;
+
+ /* If the context duration timeout is up, we'll subtract that
+ duration from the total time alloted for such things. If
+ there's no time left, we fail with a message indicating that
+ the connection timed out. */
+ if (APR_STATUS_IS_TIMEUP(status))
+ {
+ status = 0;
+
+ if (sess->timeout)
+ {
+ if (*waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
+ {
+ *waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
+ }
+ else
+ {
+ return
+ svn_error_compose_create(
+ err,
+ svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+ _("Connection timed out")));
+ }
+ }
+ }
+ else
+ {
+ *waittime_left = sess->timeout;
+ }
+
+ SVN_ERR(err);
+ if (status)
+ {
+ /* ### This omits SVN_WARNING, and possibly relies on the fact that
+ ### MAX(SERF_ERROR_*) < SVN_ERR_BAD_CATEGORY_START? */
+ if (status >= SVN_ERR_BAD_CATEGORY_START && status < SVN_ERR_LAST)
+ {
+ /* apr can't translate subversion errors to text */
+ SVN_ERR_W(svn_error_create(status, NULL, NULL),
+ _("Error running context"));
+ }
+
+ return svn_ra_serf__wrap_err(status, _("Error running context"));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_ra_serf__context_run_wait(svn_boolean_t *done,
svn_ra_serf__session_t *sess,
apr_pool_t *scratch_pool)
@@ -896,65 +943,11 @@ svn_ra_serf__context_run_wait(svn_boolea
iterpool = svn_pool_create(scratch_pool);
while (!*done)
{
- apr_status_t status;
- svn_error_t *err;
int i;
svn_pool_clear(iterpool);
- if (sess->cancel_func)
- SVN_ERR((*sess->cancel_func)(sess->cancel_baton));
-
- status = serf_context_run(sess->context,
- SVN_RA_SERF__CONTEXT_RUN_DURATION,
- iterpool);
-
- err = sess->pending_error;
- sess->pending_error = SVN_NO_ERROR;
-
- /* If the context duration timeout is up, we'll subtract that
- duration from the total time alloted for such things. If
- there's no time left, we fail with a message indicating that
- the connection timed out. */
- if (APR_STATUS_IS_TIMEUP(status))
- {
- status = 0;
-
- if (sess->timeout)
- {
- if (waittime_left > SVN_RA_SERF__CONTEXT_RUN_DURATION)
- {
- waittime_left -= SVN_RA_SERF__CONTEXT_RUN_DURATION;
- }
- else
- {
- return
- svn_error_compose_create(
- err,
- svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
- _("Connection timed out")));
- }
- }
- }
- else
- {
- waittime_left = sess->timeout;
- }
-
- SVN_ERR(err);
- if (status)
- {
- /* ### This omits SVN_WARNING, and possibly relies on the fact that
- ### MAX(SERF_ERROR_*) < SVN_ERR_BAD_CATEGORY_START? */
- if (status >= SVN_ERR_BAD_CATEGORY_START && status < SVN_ERR_LAST)
- {
- /* apr can't translate subversion errors to text */
- SVN_ERR_W(svn_error_create(status, NULL, NULL),
- _("Error running context"));
- }
-
- return svn_ra_serf__wrap_err(status, _("Error running context"));
- }
+ SVN_ERR(svn_ra_serf__context_run(sess, &waittime_left, iterpool));
/* Debugging purposes only! */
for (i = 0; i < sess->num_conns; i++)
@@ -997,114 +990,10 @@ svn_ra_serf__context_run_one(svn_ra_serf
svn_ra_serf__wrap_err(status, NULL));
}
- if (handler->server_error)
- {
- err = svn_error_compose_create(err, handler->server_error->error);
- handler->server_error = NULL;
- }
-
return svn_error_trace(err);
}
-/*
- * Expat callback invoked on a start element tag for an error response.
- */
-static svn_error_t *
-start_error(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- const char **attrs,
- apr_pool_t *scratch_pool)
-{
- svn_ra_serf__server_error_t *ctx = parser->user_data;
-
- if (!ctx->in_error &&
- strcmp(name.namespace, "DAV:") == 0 &&
- strcmp(name.name, "error") == 0)
- {
- ctx->in_error = TRUE;
- }
- else if (ctx->in_error && strcmp(name.name, "human-readable") == 0)
- {
- const char *err_code;
-
- err_code = svn_xml_get_attr_value("errcode", attrs);
- if (err_code)
- {
- apr_int64_t val;
-
- SVN_ERR(svn_cstring_atoi64(&val, err_code));
- ctx->error->apr_err = (apr_status_t)val;
- }
-
- /* If there's no error code provided, or if the provided code is
- 0 (which can happen sometimes depending on how the error is
- constructed on the server-side), just pick a generic error
- code to run with. */
- if (! ctx->error->apr_err)
- {
- ctx->error->apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
- }
-
- /* Start collecting cdata. */
- svn_stringbuf_setempty(ctx->cdata);
- ctx->collect_cdata = TRUE;
- }
-
- return SVN_NO_ERROR;
-}
-
-/*
- * Expat callback invoked on an end element tag for a PROPFIND response.
- */
-static svn_error_t *
-end_error(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- apr_pool_t *scratch_pool)
-{
- svn_ra_serf__server_error_t *ctx = parser->user_data;
-
- if (ctx->in_error &&
- strcmp(name.namespace, "DAV:") == 0 &&
- strcmp(name.name, "error") == 0)
- {
- ctx->in_error = FALSE;
- }
- if (ctx->in_error && strcmp(name.name, "human-readable") == 0)
- {
- /* On the server dav_error_response_tag() will add a leading
- and trailing newline if DEBUG_CR is defined in mod_dav.h,
- so remove any such characters here. */
- svn_stringbuf_strip_whitespace(ctx->cdata);
-
- ctx->error->message = apr_pstrmemdup(ctx->error->pool, ctx->cdata->data,
- ctx->cdata->len);
- ctx->collect_cdata = FALSE;
- }
-
- return SVN_NO_ERROR;
-}
-
-/*
- * Expat callback invoked on CDATA elements in an error response.
- *
- * This callback can be called multiple times.
- */
-static svn_error_t *
-cdata_error(svn_ra_serf__xml_parser_t *parser,
- const char *data,
- apr_size_t len,
- apr_pool_t *scratch_pool)
-{
- svn_ra_serf__server_error_t *ctx = parser->user_data;
-
- if (ctx->collect_cdata)
- {
- svn_stringbuf_appendbytes(ctx->cdata, data, len);
- }
-
- return SVN_NO_ERROR;
-}
static apr_status_t
@@ -1124,28 +1013,7 @@ drain_bucket(serf_bucket_t *bucket)
}
-static svn_ra_serf__server_error_t *
-begin_error_parsing(svn_ra_serf__xml_start_element_t start,
- svn_ra_serf__xml_end_element_t end,
- svn_ra_serf__xml_cdata_chunk_handler_t cdata,
- apr_pool_t *result_pool)
-{
- svn_ra_serf__server_error_t *server_err;
-
- server_err = apr_pcalloc(result_pool, sizeof(*server_err));
- server_err->error = svn_error_create(APR_SUCCESS, NULL, NULL);
- server_err->contains_precondition_error = FALSE;
- server_err->cdata = svn_stringbuf_create_empty(server_err->error->pool);
- server_err->collect_cdata = FALSE;
- server_err->parser.pool = server_err->error->pool;
- server_err->parser.user_data = server_err;
- server_err->parser.start = start;
- server_err->parser.end = end;
- server_err->parser.cdata = cdata;
- server_err->parser.ignore_errors = TRUE;
- return server_err;
-}
/* Implements svn_ra_serf__response_handler_t */
svn_error_t *
@@ -1234,7 +1102,7 @@ svn_ra_serf__expect_empty_body(serf_requ
const char *val;
/* This function is just like handle_multistatus_only() except for the
- XML parsing callbacks. We want to look for the human-readable element. */
+ XML parsing callbacks. We want to look for the -readable element. */
/* We should see this just once, in order to initialize SERVER_ERROR.
At that point, the core error processing will take over. If we choose
@@ -1248,11 +1116,10 @@ svn_ra_serf__expect_empty_body(serf_requ
{
svn_ra_serf__server_error_t *server_err;
- server_err = begin_error_parsing(start_error, end_error, cdata_error,
- handler->handler_pool);
-
- /* Get the parser to set our DONE flag. */
- server_err->parser.done = &handler->done;
+ SVN_ERR(svn_ra_serf__setup_error_parsing(&server_err, handler,
+ FALSE,
+ handler->handler_pool,
+ handler->handler_pool));
handler->server_error = server_err;
}
@@ -1269,188 +1136,6 @@ svn_ra_serf__expect_empty_body(serf_requ
return SVN_NO_ERROR;
}
-
-/* Given a string like "HTTP/1.1 500 (status)" in BUF, parse out the numeric
- status code into *STATUS_CODE_OUT. Ignores leading whitespace. */
-static svn_error_t *
-parse_dav_status(int *status_code_out, svn_stringbuf_t *buf,
- apr_pool_t *scratch_pool)
-{
- svn_error_t *err;
- const char *token;
- char *tok_status;
- svn_stringbuf_t *temp_buf = svn_stringbuf_dup(buf, scratch_pool);
-
- svn_stringbuf_strip_whitespace(temp_buf);
- token = apr_strtok(temp_buf->data, " \t\r\n", &tok_status);
- if (token)
- token = apr_strtok(NULL, " \t\r\n", &tok_status);
- if (!token)
- return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("Malformed DAV:status CDATA '%s'"),
- buf->data);
- err = svn_cstring_atoi(status_code_out, token);
- if (err)
- return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, err,
- _("Malformed DAV:status CDATA '%s'"),
- buf->data);
-
- return SVN_NO_ERROR;
-}
-
-/*
- * Expat callback invoked on a start element tag for a 207 response.
- */
-static svn_error_t *
-start_207(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- const char **attrs,
- apr_pool_t *scratch_pool)
-{
- svn_ra_serf__server_error_t *ctx = parser->user_data;
-
- if (!ctx->in_error &&
- strcmp(name.namespace, "DAV:") == 0 &&
- strcmp(name.name, "multistatus") == 0)
- {
- ctx->in_error = TRUE;
- }
- else if (ctx->in_error && strcmp(name.name, "responsedescription") == 0)
- {
- /* Start collecting cdata. */
- svn_stringbuf_setempty(ctx->cdata);
- ctx->collect_cdata = TRUE;
- }
- else if (ctx->in_error &&
- strcmp(name.namespace, "DAV:") == 0 &&
- strcmp(name.name, "status") == 0)
- {
- /* Start collecting cdata. */
- svn_stringbuf_setempty(ctx->cdata);
- ctx->collect_cdata = TRUE;
- }
-
- return SVN_NO_ERROR;
-}
-
-/*
- * Expat callback invoked on an end element tag for a 207 response.
- */
-static svn_error_t *
-end_207(svn_ra_serf__xml_parser_t *parser,
- svn_ra_serf__dav_props_t name,
- apr_pool_t *scratch_pool)
-{
- svn_ra_serf__server_error_t *ctx = parser->user_data;
-
- if (ctx->in_error &&
- strcmp(name.namespace, "DAV:") == 0 &&
- strcmp(name.name, "multistatus") == 0)
- {
- ctx->in_error = FALSE;
- }
- if (ctx->in_error && strcmp(name.name, "responsedescription") == 0)
- {
- /* Remove leading newline added by DEBUG_CR on server */
- svn_stringbuf_strip_whitespace(ctx->cdata);
-
- ctx->collect_cdata = FALSE;
- ctx->error->message = apr_pstrmemdup(ctx->error->pool, ctx->cdata->data,
- ctx->cdata->len);
- if (ctx->contains_precondition_error)
- ctx->error->apr_err = SVN_ERR_FS_PROP_BASEVALUE_MISMATCH;
- else
- ctx->error->apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
- }
- else if (ctx->in_error &&
- strcmp(name.namespace, "DAV:") == 0 &&
- strcmp(name.name, "status") == 0)
- {
- int status_code;
-
- ctx->collect_cdata = FALSE;
-
- SVN_ERR(parse_dav_status(&status_code, ctx->cdata, parser->pool));
- if (status_code == 412)
- ctx->contains_precondition_error = TRUE;
- }
-
- return SVN_NO_ERROR;
-}
-
-/*
- * Expat callback invoked on CDATA elements in a 207 response.
- *
- * This callback can be called multiple times.
- */
-static svn_error_t *
-cdata_207(svn_ra_serf__xml_parser_t *parser,
- const char *data,
- apr_size_t len,
- apr_pool_t *scratch_pool)
-{
- svn_ra_serf__server_error_t *ctx = parser->user_data;
-
- if (ctx->collect_cdata)
- {
- svn_stringbuf_appendbytes(ctx->cdata, data, len);
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Implements svn_ra_serf__response_handler_t */
-svn_error_t *
-svn_ra_serf__handle_multistatus_only(serf_request_t *request,
- serf_bucket_t *response,
- void *baton,
- apr_pool_t *scratch_pool)
-{
- svn_ra_serf__handler_t *handler = baton;
-
- /* This function is just like expect_empty_body() except for the
- XML parsing callbacks. We are looking for very limited pieces of
- the multistatus response. */
-
- /* We should see this just once, in order to initialize SERVER_ERROR.
- At that point, the core error processing will take over. If we choose
- not to parse an error, then we'll never return here (because we
- change the response handler). */
- SVN_ERR_ASSERT(handler->server_error == NULL);
-
- {
- serf_bucket_t *hdrs;
- const char *val;
-
- hdrs = serf_bucket_response_get_headers(response);
- val = serf_bucket_headers_get(hdrs, "Content-Type");
- if (val && strncasecmp(val, "text/xml", sizeof("text/xml") - 1) == 0)
- {
- svn_ra_serf__server_error_t *server_err;
-
- server_err = begin_error_parsing(start_207, end_207, cdata_207,
- handler->handler_pool);
-
- /* Get the parser to set our DONE flag. */
- server_err->parser.done = &handler->done;
-
- handler->server_error = server_err;
- }
- else
- {
- /* The body was not text/xml, so we don't know what to do with it.
- Toss anything that arrives. */
- handler->discard_body = TRUE;
- }
- }
-
- /* Returning SVN_NO_ERROR will return APR_SUCCESS to serf, which tells it
- to call the response handler again. That will start up the XML parsing,
- or it will be dropped on the floor (per the decision above). */
- return SVN_NO_ERROR;
-}
-
-
/* Conforms to Expat's XML_StartElementHandler */
static void
start_xml(void *userData, const char *raw_name, const char **attrs)
@@ -1550,54 +1235,23 @@ add_done_item(svn_ra_serf__xml_parser_t
}
-static svn_error_t *
-write_to_pending(svn_ra_serf__xml_parser_t *ctx,
- const char *data,
- apr_size_t len,
- apr_pool_t *scratch_pool)
-{
- if (ctx->pending == NULL)
- {
- ctx->pending = apr_pcalloc(ctx->pool, sizeof(*ctx->pending));
- ctx->pending->buf = svn_spillbuf__create(PARSE_CHUNK_SIZE,
- SPILL_SIZE,
- ctx->pool);
- }
-
- /* Copy the data into one or more chunks in the spill buffer. */
- return svn_error_trace(svn_spillbuf__write(ctx->pending->buf,
- data, len,
- scratch_pool));
-}
-
-
-static svn_error_t *
-inject_to_parser(svn_ra_serf__xml_parser_t *ctx,
- const char *data,
- apr_size_t len,
- const serf_status_line *sl)
+/* svn_error_t * wrapper around XML_Parse */
+static APR_INLINE svn_error_t *
+parse_xml(XML_Parser parser, const char *data, apr_size_t len, svn_boolean_t is_final)
{
- int xml_status;
-
- xml_status = XML_Parse(ctx->xmlp, data, (int) len, 0);
-
- if (! ctx->ignore_errors)
- {
- SVN_ERR(ctx->error);
+ int xml_status = XML_Parse(parser, data, (int)len, is_final);
+ const char *msg;
- if (xml_status != XML_STATUS_OK)
- {
- if (sl == NULL)
- return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("XML parsing failed"));
+ if (xml_status == XML_STATUS_OK)
+ return SVN_NO_ERROR;
- return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("XML parsing failed: (%d %s)"),
- sl->code, sl->reason);
- }
- }
+ msg = XML_ErrorString(XML_GetErrorCode(parser));
- return SVN_NO_ERROR;
+ return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA,
+ svn_error_createf(SVN_ERR_XML_MALFORMED, NULL,
+ _("Malformed XML: %s"),
+ msg),
+ _("The XML response contains invalid XML"));
}
/* Apr pool cleanup handler to release an XML_Parser in success and error
@@ -1616,155 +1270,6 @@ xml_parser_cleanup(void *baton)
return APR_SUCCESS;
}
-/* Limit the amount of pending content to parse at once to < 100KB per
- iteration. This number is chosen somewhat arbitrarely. Making it lower
- will have a drastical negative impact on performance, whereas increasing it
- increases the risk for connection timeouts.
- */
-#define PENDING_TO_PARSE PARSE_CHUNK_SIZE * 5
-
-svn_error_t *
-svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
- svn_boolean_t *network_eof,
- apr_pool_t *scratch_pool)
-{
- svn_boolean_t pending_empty = FALSE;
- apr_size_t cur_read = 0;
-
- /* Fast path exit: already paused, nothing to do, or already done. */
- if (parser->paused || parser->pending == NULL || *parser->done)
- {
- *network_eof = parser->pending ? parser->pending->network_eof : FALSE;
- return SVN_NO_ERROR;
- }
-
- /* Parsing the pending conten in the spillbuf will result in many disc i/o
- operations. This can be so slow that we don't run the network event
- processing loop often enough, resulting in timed out connections.
-
- So we limit the amounts of bytes parsed per iteration.
- */
- while (cur_read < PENDING_TO_PARSE)
- {
- const char *data;
- apr_size_t len;
-
- /* Get a block of content, stopping the loop when we run out. */
- SVN_ERR(svn_spillbuf__read(&data, &len, parser->pending->buf,
- scratch_pool));
- if (data)
- {
- /* Inject the content into the XML parser. */
- SVN_ERR(inject_to_parser(parser, data, len, NULL));
-
- /* If the XML parsing callbacks paused us, then we're done for now. */
- if (parser->paused)
- break;
-
- cur_read += len;
- }
- else
- {
- /* The buffer is empty. */
- pending_empty = TRUE;
- break;
- }
- }
-
- /* If the PENDING structures are empty *and* we consumed all content from
- the network, then we're completely done with the parsing. */
- if (pending_empty &&
- parser->pending->network_eof)
- {
- int xml_status;
- SVN_ERR_ASSERT(parser->xmlp != NULL);
-
- /* Tell the parser that no more content will be parsed. */
- xml_status = XML_Parse(parser->xmlp, NULL, 0, 1);
-
- apr_pool_cleanup_run(parser->pool, &parser->xmlp, xml_parser_cleanup);
- parser->xmlp = NULL;
-
- if (! parser->ignore_errors)
- {
- SVN_ERR(parser->error);
-
- if (xml_status != XML_STATUS_OK)
- {
- return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
- _("XML parsing failed"));
- }
- }
-
- add_done_item(parser);
- }
-
- *network_eof = parser->pending ? parser->pending->network_eof : FALSE;
-
- return SVN_NO_ERROR;
-}
-#undef PENDING_TO_PARSE
-
-
-/* ### this is still broken conceptually. just shifting incrementally... */
-static svn_error_t *
-handle_server_error(serf_request_t *request,
- serf_bucket_t *response,
- apr_pool_t *scratch_pool)
-{
- svn_ra_serf__server_error_t server_err = { 0 };
- serf_bucket_t *hdrs;
- const char *val;
- apr_status_t err;
-
- hdrs = serf_bucket_response_get_headers(response);
- val = serf_bucket_headers_get(hdrs, "Content-Type");
- if (val && strncasecmp(val, "text/xml", sizeof("text/xml") - 1) == 0)
- {
- /* ### we should figure out how to reuse begin_error_parsing */
-
- server_err.error = svn_error_create(APR_SUCCESS, NULL, NULL);
- server_err.contains_precondition_error = FALSE;
- server_err.cdata = svn_stringbuf_create_empty(scratch_pool);
- server_err.collect_cdata = FALSE;
- server_err.parser.pool = server_err.error->pool;
- server_err.parser.user_data = &server_err;
- server_err.parser.start = start_error;
- server_err.parser.end = end_error;
- server_err.parser.cdata = cdata_error;
- server_err.parser.done = &server_err.done;
- server_err.parser.ignore_errors = TRUE;
-
- /* We don't care about any errors except for SERVER_ERR.ERROR */
- svn_error_clear(svn_ra_serf__handle_xml_parser(request,
- response,
- &server_err.parser,
- scratch_pool));
-
- /* ### checking DONE is silly. the above only parses whatever has
- ### been received at the network interface. totally wrong. but
- ### it is what we have for now (maintaining historical code),
- ### until we fully migrate. */
- if (server_err.done && server_err.error->apr_err == APR_SUCCESS)
- {
- svn_error_clear(server_err.error);
- server_err.error = SVN_NO_ERROR;
- }
-
- return svn_error_trace(server_err.error);
- }
-
- /* The only error that we will return is from the XML response body.
- Otherwise, ignore the entire body but allow SUCCESS/EOF/EAGAIN to
- surface. */
- err = drain_bucket(response);
- if (err && !SERF_BUCKET_READ_ERROR(err))
- return svn_ra_serf__wrap_err(err, NULL);
-
- return SVN_NO_ERROR;
-}
-
-
/* Implements svn_ra_serf__response_handler_t */
svn_error_t *
svn_ra_serf__handle_xml_parser(serf_request_t *request,
@@ -1772,29 +1277,10 @@ svn_ra_serf__handle_xml_parser(serf_requ
void *baton,
apr_pool_t *pool)
{
- serf_status_line sl;
apr_status_t status;
svn_ra_serf__xml_parser_t *ctx = baton;
svn_error_t *err;
- /* ### get the HANDLER rather than fetching this. */
- status = serf_bucket_response_status(response, &sl);
- if (SERF_BUCKET_READ_ERROR(status))
- {
- return svn_ra_serf__wrap_err(status, NULL);
- }
-
- /* Woo-hoo. Nothing here to see. */
- if (sl.code == 404 && !ctx->ignore_errors)
- {
- err = handle_server_error(request, response, pool);
-
- if (err && APR_STATUS_IS_EOF(err->apr_err))
- add_done_item(ctx);
-
- return svn_error_trace(err);
- }
-
if (!ctx->xmlp)
{
ctx->xmlp = XML_ParserCreate(NULL);
@@ -1819,28 +1305,10 @@ svn_ra_serf__handle_xml_parser(serf_requ
return svn_ra_serf__wrap_err(status, NULL);
}
- /* 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
- clear that flag, as appropriate, along with processing the
- content that we have placed into the PENDING buffer.
-
- We want to save arriving content into the PENDING structures if
- the parser has been paused, or we already have data in there (so
- the arriving data is appended, rather than injected out of order) */
- if (ctx->paused || HAS_PENDING_DATA(ctx->pending))
- {
- err = write_to_pending(ctx, data, len, pool);
- }
- else
- {
- err = inject_to_parser(ctx, data, len, &sl);
- if (err)
- {
- /* Should have no errors if IGNORE_ERRORS is set. */
- SVN_ERR_ASSERT(!ctx->ignore_errors);
- }
- }
+ err = parse_xml(ctx->xmlp, data, len, FALSE);
+
+ err = svn_error_compose_create(ctx->error, err);
+
if (err)
{
SVN_ERR_ASSERT(ctx->xmlp != NULL);
@@ -1857,34 +1325,17 @@ svn_ra_serf__handle_xml_parser(serf_requ
if (APR_STATUS_IS_EOF(status))
{
- if (ctx->pending != NULL)
- ctx->pending->network_eof = TRUE;
+ SVN_ERR_ASSERT(ctx->xmlp != NULL);
- /* We just hit the end of the network content. If we have nothing
- in the PENDING structures, then we're completely done. */
- if (!HAS_PENDING_DATA(ctx->pending))
- {
- int xml_status;
- SVN_ERR_ASSERT(ctx->xmlp != NULL);
+ err = parse_xml(ctx->xmlp, NULL, 0, TRUE);
- xml_status = XML_Parse(ctx->xmlp, NULL, 0, 1);
+ err = svn_error_compose_create(ctx->error, err);
- apr_pool_cleanup_run(ctx->pool, &ctx->xmlp, xml_parser_cleanup);
+ apr_pool_cleanup_run(ctx->pool, &ctx->xmlp, xml_parser_cleanup);
- if (! ctx->ignore_errors)
- {
- SVN_ERR(ctx->error);
-
- if (xml_status != XML_STATUS_OK)
- {
- return svn_error_create(
- SVN_ERR_XML_MALFORMED, NULL,
- _("The XML response contains invalid XML"));
- }
- }
+ SVN_ERR(err);
- add_done_item(ctx);
- }
+ add_done_item(ctx);
return svn_ra_serf__wrap_err(status, NULL);
}
@@ -2119,10 +1570,7 @@ handle_response(serf_request_t *request,
}
handler->conn->last_status_code = handler->sline.code;
- if (handler->sline.code == 405
- || handler->sline.code == 408
- || handler->sline.code == 409
- || handler->sline.code >= 500)
+ if (handler->sline.code >= 400)
{
/* 405 Method Not allowed.
408 Request Timeout
@@ -2137,35 +1585,22 @@ handle_response(serf_request_t *request,
{
svn_ra_serf__server_error_t *server_err;
- server_err = begin_error_parsing(start_error, end_error, cdata_error,
- handler->handler_pool);
- /* Get the parser to set our DONE flag. */
- server_err->parser.done = &handler->done;
+ SVN_ERR(svn_ra_serf__setup_error_parsing(&server_err, handler,
+ FALSE,
+ handler->handler_pool,
+ handler->handler_pool));
handler->server_error = server_err;
}
else
{
handler->discard_body = TRUE;
-
- if (!handler->session->pending_error)
- {
- apr_status_t apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
-
- /* 405 == Method Not Allowed (Occurs when trying to lock a working
- copy path which no longer exists at HEAD in the repository. */
- if (handler->sline.code == 405
- && strcmp(handler->method, "LOCK") == 0)
- apr_err = SVN_ERR_FS_OUT_OF_DATE;
-
- handler->session->pending_error =
- svn_error_createf(apr_err, NULL,
- _("%s request on '%s' failed: %d %s"),
- handler->method, handler->path,
- handler->sline.code, handler->sline.reason);
- }
}
}
+ else if (handler->sline.code <= 199)
+ {
+ handler->discard_body = TRUE;
+ }
/* Stop processing the above, on every packet arrival. */
handler->reading_body = TRUE;
@@ -2177,13 +1612,6 @@ handle_response(serf_request_t *request,
{
*serf_status = drain_bucket(response);
- /* If the handler hasn't set done (which it shouldn't have) and
- we now have the EOF, go ahead and set it so that we can stop
- our context loops.
- */
- if (!handler->done && APR_STATUS_IS_EOF(*serf_status))
- handler->done = TRUE;
-
return SVN_NO_ERROR;
}
@@ -2191,50 +1619,12 @@ handle_response(serf_request_t *request,
that now. */
if (handler->server_error != NULL)
{
- err = svn_ra_serf__handle_xml_parser(request, response,
- &handler->server_error->parser,
- scratch_pool);
-
- /* If we do not receive an error or it is a non-transient error, return
- immediately.
-
- APR_EOF will be returned when parsing is complete.
-
- APR_EAGAIN & WAIT_CONN may be intermittently returned as we proceed through
- parsing and the network has no more data right now. If we receive that,
- clear the error and return - allowing serf to wait for more data.
- */
- if (!err || SERF_BUCKET_READ_ERROR(err->apr_err))
- return svn_error_trace(err);
-
- if (!APR_STATUS_IS_EOF(err->apr_err))
- {
- *serf_status = err->apr_err;
- svn_error_clear(err);
- return SVN_NO_ERROR;
- }
-
- /* Clear the EOF. We don't need it. */
- svn_error_clear(err);
-
- /* If the parsing is done, and we did not extract an error, then
- simply toss everything, and anything else that might arrive.
- The higher-level code will need to investigate HANDLER->SLINE,
- as we have no further information for them. */
- if (handler->done
- && handler->server_error->error->apr_err == APR_SUCCESS)
- {
- svn_error_clear(handler->server_error->error);
-
- /* Stop parsing for a server error. */
- handler->server_error = NULL;
-
- /* If anything arrives after this, then just discard it. */
- handler->discard_body = TRUE;
- }
-
- *serf_status = APR_EOF;
- return SVN_NO_ERROR;
+ return svn_error_trace(
+ svn_ra_serf__handle_server_error(handler->server_error,
+ handler,
+ request, response,
+ serf_status,
+ scratch_pool));
}
/* Pass the body along to the registered response handler. */
@@ -2280,9 +1670,23 @@ handle_response_cb(serf_request_t *reque
if (!outer_status)
outer_status = inner_status;
- /* Make sure the DONE flag is set properly. */
+ /* Make sure the DONE flag is set properly and requests are cleaned up. */
if (APR_STATUS_IS_EOF(outer_status) || APR_STATUS_IS_EOF(inner_status))
- handler->done = TRUE;
+ {
+ handler->done = TRUE;
+ outer_status = APR_EOF;
+
+ save_error(handler->session,
+ handler->done_delegate(request, handler->done_delegate_baton,
+ scratch_pool));
+ }
+ else if (SERF_BUCKET_READ_ERROR(outer_status)
+ && handler->session->pending_error)
+ {
+ handler->discard_body = TRUE; /* Discard further data */
+ handler->done = TRUE; /* Mark as done */
+ return APR_EAGAIN; /* Exit context loop */
+ }
return outer_status;
}
@@ -2469,11 +1873,6 @@ svn_ra_serf__discover_vcc(const char **v
/* Okay, strip off a component from PATH. */
path = svn_urlpath__dirname(path, pool);
-
- /* An error occurred on conns. serf 0.4.0 remembers that
- the connection had a problem. We need to reset it, in
- order to use it again. */
- serf_connection_reset(conn->conn);
}
}
}
@@ -2582,7 +1981,9 @@ svn_ra_serf__error_on_status(serf_status
{
case 301:
case 302:
+ case 303:
case 307:
+ case 308:
return svn_error_createf(SVN_ERR_RA_DAV_RELOCATED, NULL,
(sline.code == 301)
? _("Repository moved permanently to '%s';"
@@ -2596,6 +1997,15 @@ svn_ra_serf__error_on_status(serf_status
case 404:
return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
_("'%s' path not found"), path);
+ case 405:
+ return svn_error_createf(SVN_ERR_FS_OUT_OF_DATE, NULL,
+ _("'%s' is out of date"), path);
+ case 409:
+ return svn_error_createf(SVN_ERR_FS_CONFLICT, NULL,
+ _("'%s' conflicts"), path);
+ case 412:
+ return svn_error_createf(SVN_ERR_RA_DAV_PRECONDITION_FAILED, NULL,
+ _("Precondition on '%s' failed"), path);
case 423:
return svn_error_createf(SVN_ERR_FS_NO_LOCK_TOKEN, NULL,
_("'%s': no lock token available"), path);
@@ -2606,21 +2016,53 @@ svn_ra_serf__error_on_status(serf_status
"server or an intermediate proxy does not accept "
"chunked encoding. Try setting 'http-chunked-requests' "
"to 'auto' or 'no' in your client configuration."));
+ case 500:
+ return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+ _("Unexpected server error %d '%s' on '%s'"),
+ sline.code, sline.reason, path);
case 501:
return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("The requested feature is not supported by "
"'%s'"), path);
}
- if (sline.code >= 300)
+ if (sline.code >= 300 || sline.code <= 199)
return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
- _("Unexpected HTTP status %d '%s' on '%s'\n"),
+ _("Unexpected HTTP status %d '%s' on '%s'"),
sline.code, sline.reason, path);
return SVN_NO_ERROR;
}
svn_error_t *
+svn_ra_serf__unexpected_status(svn_ra_serf__handler_t *handler)
+{
+ /* Is it a standard error status? */
+ SVN_ERR(svn_ra_serf__error_on_status(handler->sline,
+ handler->path,
+ handler->location));
+
+ switch (handler->sline.code)
+ {
+ case 201:
+ return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+ _("Path '%s' unexpectedly created"),
+ handler->path);
+ case 204:
+ return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
+ _("Path '%s' already exists"),
+ handler->path);
+
+ default:
+ return svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+ _("Unexpected HTTP status %d '%s' on '%s' "
+ "request to '%s'"),
+ handler->sline.code, handler->sline.reason,
+ handler->method, handler->path);
+ }
+}
+
+svn_error_t *
svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *ra_session,
svn_delta_shim_callbacks_t *callbacks)
{
@@ -2712,8 +2154,9 @@ expat_response_handler(serf_request_t *r
else
got_expected_status = (ectx->handler->sline.code == 200);
- if ((ectx->handler->sline.code < 200) || (ectx->handler->sline.code >= 300)
- || ! got_expected_status)
+ if (!ectx->handler->server_error
+ && ((ectx->handler->sline.code < 200) || (ectx->handler->sline.code >= 300)
+ || ! got_expected_status))
{
/* By deferring to expect_empty_body(), it will make a choice on
how to handle the body. Whatever the decision, the core handler
@@ -2748,7 +2191,7 @@ expat_response_handler(serf_request_t *r
apr_status_t status;
const char *data;
apr_size_t len;
- int expat_status;
+ svn_error_t *err;
svn_boolean_t at_eof = FALSE;
status = serf_bucket_read(response, PARSE_CHUNK_SIZE, &data, &len);
@@ -2767,12 +2210,11 @@ expat_response_handler(serf_request_t *r
/* ### should we have an IGNORE_ERRORS flag like the v1 parser? */
- expat_status = XML_Parse(ectx->parser, data, (int)len,
- at_eof /* isFinal */);
+ err = parse_xml(ectx->parser, data, len, at_eof /* isFinal */);
+
+ err = svn_error_compose_create(ectx->inner_error, err);
- if (at_eof
- || ectx->inner_error
- || expat_status != XML_STATUS_OK)
+ if (at_eof || err)
{
/* Release xml parser state/tables. */
apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser,
@@ -2786,14 +2228,7 @@ expat_response_handler(serf_request_t *r
If an error is not present, THEN we go ahead and look for parsing
errors. */
- SVN_ERR(ectx->inner_error);
- if (expat_status != XML_STATUS_OK)
- return svn_error_createf(SVN_ERR_XML_MALFORMED, NULL,
- _("The %s response contains invalid XML"
- " (%d %s)"),
- ectx->handler->method,
- ectx->handler->sline.code,
- ectx->handler->sline.reason);
+ SVN_ERR(err);
/* The parsing went fine. What has the bucket told us? */
@@ -2812,6 +2247,47 @@ expat_response_handler(serf_request_t *r
/* NOTREACHED */
}
+/* Shandard done_delegate handler */
+static svn_error_t *
+response_done(serf_request_t *request,
+ void *handler_baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_ra_serf__handler_t *handler = handler_baton;
+
+ assert(handler->done);
+
+ if (handler->no_fail_on_http_failure_status)
+ return SVN_NO_ERROR;
+
+ if (handler->server_error)
+ return svn_ra_serf__server_error_create(handler, scratch_pool);
+
+ if ((handler->sline.code >= 400 || handler->sline.code <= 199)
+ && !handler->session->pending_error
+ && !handler->no_fail_on_http_failure_status)
+ {
+ return svn_error_trace(svn_ra_serf__unexpected_status(handler));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_ra_serf__handler_t *
+svn_ra_serf__create_handler(apr_pool_t *result_pool)
+{
+ svn_ra_serf__handler_t *handler;
+
+ handler = apr_pcalloc(result_pool, sizeof(*handler));
+ handler->handler_pool = result_pool;
+
+ /* Setup the default done handler, to handle server errors */
+ handler->done_delegate_baton = handler;
+ handler->done_delegate = response_done;
+
+ return handler;
+}
+
svn_ra_serf__handler_t *
svn_ra_serf__create_expat_handler(svn_ra_serf__xml_context_t *xmlctx,
@@ -2828,8 +2304,7 @@ svn_ra_serf__create_expat_handler(svn_ra
ectx->cleanup_pool = result_pool;
- handler = apr_pcalloc(result_pool, sizeof(*handler));
- handler->handler_pool = result_pool;
+ handler = svn_ra_serf__create_handler(result_pool);
handler->response_handler = expat_response_handler;
handler->response_baton = ectx;
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/xml.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/xml.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/xml.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_serf/xml.c Thu Jan 9 09:31:10 2014
@@ -46,9 +46,11 @@ struct svn_ra_serf__xml_context_t {
/* Current state information. */
svn_ra_serf__xml_estate_t *current;
- /* If WAITING.NAMESPACE != NULL, wait for NAMESPACE:NAME element to be
- closed before looking for transitions from CURRENT->STATE. */
- svn_ra_serf__dav_props_t waiting;
+ /* If WAITING >= then we are waiting for an element to close before
+ resuming events. The number stored here is the amount of nested
+ elements open. The Xml parser will make sure the document is well
+ formed. */
+ int waiting;
/* The transition table. */
const svn_ra_serf__xml_transition_t *ttable;
@@ -57,7 +59,6 @@ struct svn_ra_serf__xml_context_t {
svn_ra_serf__xml_opened_t opened_cb;
svn_ra_serf__xml_closed_t closed_cb;
svn_ra_serf__xml_cdata_t cdata_cb;
- svn_ra_serf__xml_done_t done_cb;
void *baton;
/* Linked list of free states. */
@@ -141,7 +142,7 @@ define_namespaces(svn_ra_serf__ns_t **ns
/* Have we already defined this ns previously? */
for (cur_ns = *ns_list; cur_ns; cur_ns = cur_ns->next)
{
- if (strcmp(cur_ns->namespace, prefix) == 0)
+ if (strcmp(cur_ns->xmlns, prefix) == 0)
{
found = TRUE;
break;
@@ -158,7 +159,7 @@ define_namespaces(svn_ra_serf__ns_t **ns
else
pool = baton;
new_ns = apr_palloc(pool, sizeof(*new_ns));
- new_ns->namespace = apr_pstrdup(pool, prefix);
+ new_ns->xmlns = apr_pstrdup(pool, prefix);
new_ns->url = apr_pstrdup(pool, tmp_attrs[1]);
/* Push into the front of NS_LIST. Parent states will point
@@ -199,9 +200,9 @@ svn_ra_serf__expand_ns(svn_ra_serf__dav_
for (ns = ns_list; ns; ns = ns->next)
{
- if (strncmp(ns->namespace, name, colon - name) == 0)
+ if (strncmp(ns->xmlns, name, colon - name) == 0)
{
- returned_prop_name->namespace = ns->url;
+ returned_prop_name->xmlns = ns->url;
returned_prop_name->name = colon + 1;
return;
}
@@ -213,9 +214,9 @@ svn_ra_serf__expand_ns(svn_ra_serf__dav_
for (ns = ns_list; ns; ns = ns->next)
{
- if (! ns->namespace[0])
+ if (! ns->xmlns[0])
{
- returned_prop_name->namespace = ns->url;
+ returned_prop_name->xmlns = ns->url;
returned_prop_name->name = name;
return;
}
@@ -224,7 +225,7 @@ svn_ra_serf__expand_ns(svn_ra_serf__dav_
/* If the prefix is not found, then the name is NOT within a
namespace. */
- returned_prop_name->namespace = "";
+ returned_prop_name->xmlns = "";
returned_prop_name->name = name;
}
@@ -501,14 +502,6 @@ svn_ra_serf__xml_context_done(svn_ra_ser
msg);
}
- if (xmlctx->done_cb != NULL)
- {
- START_CALLBACK(xmlctx);
- SVN_ERR(xmlctx->done_cb(xmlctx->baton,
- xmlctx->scratch_pool));
- END_CALLBACK(xmlctx);
- }
-
svn_pool_destroy(xmlctx->scratch_pool);
return SVN_NO_ERROR;
}
@@ -519,7 +512,6 @@ svn_ra_serf__xml_context_create(
svn_ra_serf__xml_opened_t opened_cb,
svn_ra_serf__xml_closed_t closed_cb,
svn_ra_serf__xml_cdata_t cdata_cb,
- svn_ra_serf__xml_done_t done_cb,
void *baton,
apr_pool_t *result_pool)
{
@@ -531,7 +523,6 @@ svn_ra_serf__xml_context_create(
xmlctx->opened_cb = opened_cb;
xmlctx->closed_cb = closed_cb;
xmlctx->cdata_cb = cdata_cb;
- xmlctx->done_cb = done_cb;
xmlctx->baton = baton;
xmlctx->scratch_pool = svn_pool_create(result_pool);
@@ -640,8 +631,11 @@ svn_ra_serf__xml_cb_start(svn_ra_serf__x
/* If we're waiting for an element to close, then just ignore all
other element-opens. */
- if (xmlctx->waiting.namespace != NULL)
- return SVN_NO_ERROR;
+ if (xmlctx->waiting > 0)
+ {
+ xmlctx->waiting++;
+ return SVN_NO_ERROR;
+ }
/* Look for xmlns: attributes. Lazily create the state pool if any
were found. */
@@ -660,7 +654,7 @@ svn_ra_serf__xml_cb_start(svn_ra_serf__x
/* Found a specific transition. */
if (strcmp(elemname.name, scan->name) == 0
- && strcmp(elemname.namespace, scan->ns) == 0)
+ && strcmp(elemname.xmlns, scan->ns) == 0)
break;
}
if (scan->ns == NULL)
@@ -673,8 +667,7 @@ svn_ra_serf__xml_cb_start(svn_ra_serf__x
elemname.name);
}
- xmlctx->waiting = elemname;
- /* ### return? */
+ xmlctx->waiting++; /* Start waiting for the close tag */
return SVN_NO_ERROR;
}
@@ -750,7 +743,7 @@ svn_ra_serf__xml_cb_start(svn_ra_serf__x
/* Some basic copies to set up the new estate. */
new_xes->state = scan->to_state;
new_xes->tag.name = apr_pstrdup(new_pool, elemname.name);
- new_xes->tag.namespace = apr_pstrdup(new_pool, elemname.namespace);
+ new_xes->tag.xmlns = apr_pstrdup(new_pool, elemname.xmlns);
new_xes->custom_close = scan->custom_close;
/* Start with the parent's namespace set. */
@@ -783,30 +776,12 @@ svn_ra_serf__xml_cb_end(svn_ra_serf__xml
svn_ra_serf__expand_ns(&elemname, xes->ns_list, raw_name);
- if (xmlctx->waiting.namespace != NULL)
+ if (xmlctx->waiting > 0)
{
- /* If this element is not the closer, then keep waiting... */
- if (strcmp(elemname.name, xmlctx->waiting.name) != 0
- || strcmp(elemname.namespace, xmlctx->waiting.namespace) != 0)
- return SVN_NO_ERROR;
-
- /* Found it. Stop waiting, and go back for more. */
- xmlctx->waiting.namespace = NULL;
+ xmlctx->waiting--;
return SVN_NO_ERROR;
}
- /* We should be looking at the same tag that opened the current state.
-
- Unknown elements are simply skipped, so we wouldn't reach this check.
-
- Known elements push a new state for a given tag. Some other elemname
- would imply closing an ancestor tag (where did ours go?) or a spurious
- tag closure. */
- if (strcmp(elemname.name, xes->tag.name) != 0
- || strcmp(elemname.namespace, xes->tag.namespace) != 0)
- return svn_error_create(SVN_ERR_XML_MALFORMED, NULL,
- _("The response contains invalid XML"));
-
if (xes->custom_close)
{
const svn_string_t *cdata;
@@ -857,7 +832,7 @@ svn_ra_serf__xml_cb_cdata(svn_ra_serf__x
{
/* If we are waiting for a closing tag, then we are uninterested in
the cdata. Just return. */
- if (xmlctx->waiting.namespace != NULL)
+ if (xmlctx->waiting > 0)
return SVN_NO_ERROR;
/* If the current state is collecting cdata, then copy the cdata. */
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_svn/client.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_svn/client.c Thu Jan 9 09:31:10 2014
@@ -598,6 +598,7 @@ static svn_error_t *open_session(svn_ra_
const apr_uri_t *uri,
const char *tunnel_name,
const char **tunnel_argv,
+ apr_hash_t *config,
const svn_ra_callbacks2_t *callbacks,
void *callbacks_baton,
apr_pool_t *pool)
@@ -623,6 +624,11 @@ static svn_error_t *open_session(svn_ra_
sess->callbacks_baton = callbacks_baton;
sess->bytes_read = sess->bytes_written = 0;
+ if (config)
+ SVN_ERR(svn_config_copy_config(&sess->config, config, pool));
+ else
+ sess->config = NULL;
+
if (tunnel_name)
{
if (tunnel_argv)
@@ -823,13 +829,65 @@ static svn_error_t *ra_svn_open(svn_ra_s
/* We open the session in a subpool so we can get rid of it if we
reparent with a server that doesn't support reparenting. */
- SVN_ERR(open_session(&sess, url, &uri, tunnel, tunnel_argv,
+ SVN_ERR(open_session(&sess, url, &uri, tunnel, tunnel_argv, config,
callbacks, callback_baton, sess_pool));
session->priv = sess;
return SVN_NO_ERROR;
}
+static svn_error_t *ra_svn_dup_session(svn_ra_session_t *new_session,
+ svn_ra_session_t *old_session,
+ const char *new_session_url,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_pool_t *sess_pool = svn_pool_create(result_pool);
+ svn_ra_svn__session_baton_t *old_sess = old_session->priv;
+ svn_ra_svn__session_baton_t *new_sess;
+ const char *tunnel, **tunnel_argv;
+ apr_uri_t uri;
+ svn_config_t *cfg, *cfg_client;
+ apr_hash_t *config = old_sess->config;
+ const svn_ra_callbacks2_t *callbacks = old_sess->callbacks;
+ void *callback_baton = old_sess->callbacks_baton;
+
+ SVN_ERR(parse_url(new_session_url, &uri, sess_pool));
+
+ parse_tunnel(new_session_url, &tunnel, result_pool);
+
+ /* Use the default tunnel implementation if we got a tunnel name,
+ but either do not have tunnel handler callbacks installed, or
+ the handlers don't like the tunnel name. */
+ if (tunnel
+ && (!callbacks->open_tunnel_func
+ || (callbacks->check_tunnel_func && callbacks->open_tunnel_func
+ && !callbacks->check_tunnel_func(callbacks->tunnel_baton,
+ tunnel))))
+ SVN_ERR(find_tunnel_agent(tunnel, uri.hostinfo, &tunnel_argv,
+ config,
+ result_pool));
+ else
+ tunnel_argv = NULL;
+
+ cfg_client = config
+ ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG)
+ : NULL;
+ cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_SERVERS) : NULL;
+ svn_auth_set_parameter(callbacks->auth_baton,
+ SVN_AUTH_PARAM_CONFIG_CATEGORY_CONFIG, cfg_client);
+ svn_auth_set_parameter(callbacks->auth_baton,
+ SVN_AUTH_PARAM_CONFIG_CATEGORY_SERVERS, cfg);
+
+ /* We open the session in a subpool so we can get rid of it if we
+ reparent with a server that doesn't support reparenting. */
+ SVN_ERR(open_session(&new_sess, new_session_url, &uri, tunnel, tunnel_argv,
+ config, callbacks, callback_baton, sess_pool));
+ new_session->priv = new_sess;
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *ra_svn_reparent(svn_ra_session_t *ra_session,
const char *url,
apr_pool_t *pool)
@@ -860,7 +918,8 @@ static svn_error_t *ra_svn_reparent(svn_
err = parse_url(url, &uri, sess_pool);
if (! err)
err = open_session(&new_sess, url, &uri, sess->tunnel_name, sess->tunnel_argv,
- sess->callbacks, sess->callbacks_baton, sess_pool);
+ sess->config, sess->callbacks, sess->callbacks_baton,
+ sess_pool);
/* We destroy the new session pool on error, since it is allocated in
the main session pool. */
if (err)
@@ -2792,6 +2851,16 @@ ra_svn_get_inherited_props(svn_ra_sessio
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
apr_array_header_t *iproplist;
+ svn_boolean_t iprop_capable;
+
+ SVN_ERR(ra_svn_has_capability(session, &iprop_capable,
+ SVN_RA_CAPABILITY_INHERITED_PROPS,
+ scratch_pool));
+
+ /* If we don't support native iprop handling, use the implementation
+ in libsvn_ra */
+ if (!iprop_capable)
+ return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, NULL, NULL);
SVN_ERR(svn_ra_svn__write_cmd_get_iprops(conn, scratch_pool,
path, revision));
@@ -2808,6 +2877,7 @@ static const svn_ra__vtable_t ra_svn_vta
ra_svn_get_description,
ra_svn_get_schemes,
ra_svn_open,
+ ra_svn_dup_session,
ra_svn_reparent,
ra_svn_get_session_url,
ra_svn_get_latest_rev,
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_svn/ra_svn.h?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_ra_svn/ra_svn.h Thu Jan 9 09:31:10 2014
@@ -131,6 +131,7 @@ struct svn_ra_svn__session_baton_t {
const char **tunnel_argv;
const svn_ra_callbacks2_t *callbacks;
void *callbacks_baton;
+ apr_hash_t *config;
apr_off_t bytes_read, bytes_written; /* apr_off_t's because that's what
the callback interface uses */
const char *useragent;
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/authz_pool.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/authz_pool.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/authz_pool.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/authz_pool.c Thu Jan 9 09:31:10 2014
@@ -38,7 +38,6 @@
#include "../libsvn_subr/config_impl.h"
#include "repos.h"
-#include <apr_poll.h>
/* Currently this structure is just a wrapper around a svn_config_t.
*/
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/commit.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/commit.c Thu Jan 9 09:31:10 2014
@@ -761,6 +761,13 @@ close_edit(void *edit_baton,
if (SVN_IS_VALID_REVNUM(new_revision))
{
+ /* The actual commit succeeded, i.e. the transaction does no longer
+ exist and we can't use txn_root for conflict resolution etc.
+
+ Since close_edit is supposed to release resources, do it now. */
+ if (eb->txn_root)
+ svn_fs_close_root(eb->txn_root);
+
if (err)
{
/* If the error was in post-commit, then the commit itself
@@ -821,6 +828,10 @@ abort_edit(void *edit_baton,
eb->txn_aborted = TRUE;
+ /* Since abort_edit is supposed to release resources, do it now. */
+ if (eb->txn_root)
+ svn_fs_close_root(eb->txn_root);
+
return svn_error_trace(svn_fs_abort_txn(eb->txn, pool));
}
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/delta.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/delta.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/delta.c Thu Jan 9 09:31:10 2014
@@ -216,10 +216,9 @@ svn_repos_dir_delta2(svn_fs_root_t *src_
void *root_baton = NULL;
struct context c;
const char *src_fullpath;
- const svn_fs_id_t *src_id, *tgt_id;
svn_node_kind_t src_kind, tgt_kind;
svn_revnum_t rootrev;
- int distance;
+ svn_fs_node_relation_t relation;
const char *authz_root_path;
/* SRC_PARENT_DIR must be valid. */
@@ -319,11 +318,10 @@ svn_repos_dir_delta2(svn_fs_root_t *src_
}
/* Get and compare the node IDs for the source and target. */
- SVN_ERR(svn_fs_node_id(&tgt_id, tgt_root, tgt_fullpath, pool));
- SVN_ERR(svn_fs_node_id(&src_id, src_root, src_fullpath, pool));
- distance = svn_fs_compare_ids(src_id, tgt_id);
+ SVN_ERR(svn_fs_node_relation(&relation, tgt_root, tgt_fullpath,
+ src_root, src_fullpath, pool));
- if (distance == 0)
+ if (relation == svn_fs_node_same)
{
/* They are the same node! No-op (you gotta love those). */
goto cleanup;
@@ -334,7 +332,7 @@ svn_repos_dir_delta2(svn_fs_root_t *src_
add the other. Also, if they are completely unrelated and
our caller is interested in relatedness, we do the same thing. */
if ((src_kind != tgt_kind)
- || ((distance == -1) && (! ignore_ancestry)))
+ || ((relation == svn_fs_node_unrelated) && (! ignore_ancestry)))
{
SVN_ERR(authz_root_check(tgt_root, authz_root_path,
authz_read_func, authz_read_baton, pool));
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/dump.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/dump.c Thu Jan 9 09:31:10 2014
@@ -38,6 +38,7 @@
#include "private/svn_mergeinfo_private.h"
#include "private/svn_fs_private.h"
+#include "private/svn_sorts_private.h"
#include "private/svn_utf_private.h"
#include "private/svn_cache.h"
@@ -399,13 +400,6 @@ struct edit_baton
char buffer[SVN__STREAM_CHUNK_SIZE];
apr_size_t bufsize;
- /* map nodeID -> node kind. May be NULL.
- The key is the string representation of the node ID given in
- directory entries. If we find an entry in this cache, the
- respective node has already been verified as readable and being
- of the type stored as value in the cache. */
- svn_cache__t *verified_dirents_cache;
-
/* Structure allows us to verify the paths currently being dumped.
If NULL, validity checks are being skipped. */
path_tracker_t *path_tracker;
@@ -592,42 +586,11 @@ node_must_not_exist(struct edit_baton *e
return SVN_NO_ERROR;
}
-
+/* Unique string pointers used by verify_mergeinfo_normalization()
+ and check_name_collision() */
static const char normalized_unique[] = "normalized_unique";
static const char normalized_collision[] = "normalized_collision";
-static svn_error_t *
-check_path_normalization(const char *path,
- svn_node_kind_t kind,
- svn_repos_notify_func_t notify_func,
- void *notify_baton,
- apr_pool_t *scratch_pool)
-{
- const char *const name = svn_relpath_basename(path, scratch_pool);
- if (!svn_utf__is_normalized(name, scratch_pool))
- {
- svn_repos_notify_t *const notify =
- svn_repos_notify_create(svn_repos_notify_warning, scratch_pool);
- notify->warning = svn_repos_notify_warning_denormalized_name;
- switch (kind)
- {
- case svn_node_dir:
- notify->warning_str = apr_psprintf(
- scratch_pool, _("Denormalized directory name '%s'"), path);
- break;
- case svn_node_file:
- notify->warning_str = apr_psprintf(
- scratch_pool, _("Denormalized file name '%s'"), path);
- break;
- default:
- notify->warning_str = apr_psprintf(
- scratch_pool, _("Denormalized entry name '%s'"), path);
- }
- notify_func(notify_baton, notify, scratch_pool);
- }
- return SVN_NO_ERROR;
-}
-
/* Baton for extract_mergeinfo_paths */
struct extract_mergeinfo_paths_baton
@@ -703,18 +666,6 @@ verify_mergeinfo_normalization(void *bat
const char *found;
SVN_ERR(svn_utf__normalize(&normpath, path, klen, &vb->buffer));
- if (0 != strcmp(path, normpath))
- {
- /* Report denormlized mergeinfo path */
- svn_repos_notify_t *const notify =
- svn_repos_notify_create(svn_repos_notify_warning, iterpool);
- notify->warning = svn_repos_notify_warning_denormalized_mergeinfo;
- notify->warning_str = apr_psprintf(
- iterpool, _("Denormalized path '%s' in %s property of '%s'"),
- path, SVN_PROP_MERGEINFO, vb->path);
- vb->notify_func(vb->notify_baton, notify, iterpool);
- }
-
found = svn_hash_gets(vb->normalized_paths, normpath);
if (!found)
svn_hash_sets(vb->normalized_paths,
@@ -1370,14 +1321,11 @@ add_directory(const char *path,
/* Delete the path, it's now been dumped. */
svn_hash_sets(pb->deleted_entries, path, NULL);
- /* Check for UCS normalization and name clashes, but only if this is
- actually a new name in the parent, not a replacement. */
+ /* Check for normalized name clashes, but only if this is actually a
+ new name in the parent, not a replacement. */
if (!val && eb->verify && eb->check_normalization && eb->notify_func)
{
pb->check_name_collision = TRUE;
- SVN_ERR(check_path_normalization(
- path, svn_node_dir,
- eb->notify_func, eb->notify_baton, pool));
}
new_db->written_out = TRUE;
@@ -1479,20 +1427,17 @@ add_file(const char *path,
is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
pool));
- /* Check for UCS normalization and name clashes, but only if this is
- actually a new name in the parent, not a replacement. */
+ if (val)
+ /* delete the path, it's now been dumped. */
+ svn_hash_sets(pb->deleted_entries, path, NULL);
+
+ /* Check for normalized name clashes, but only if this is actually a
+ new name in the parent, not a replacement. */
if (!val && eb->verify && eb->check_normalization && eb->notify_func)
{
pb->check_name_collision = TRUE;
- SVN_ERR(check_path_normalization(
- path, svn_node_file,
- eb->notify_func, eb->notify_baton, pool));
}
- if (val)
- /* delete the path, it's now been dumped. */
- svn_hash_sets(pb->deleted_entries, path, NULL);
-
*file_baton = NULL; /* muhahahaha */
return SVN_NO_ERROR;
}
@@ -1657,7 +1602,6 @@ get_dump_editor(const svn_delta_editor_t
svn_boolean_t use_deltas,
svn_boolean_t verify,
svn_boolean_t check_normalization,
- svn_cache__t *verified_dirents_cache,
apr_pool_t *pool)
{
/* Allocate an edit baton to be stored in every directory baton.
@@ -1683,7 +1627,6 @@ get_dump_editor(const svn_delta_editor_t
eb->check_normalization = check_normalization;
eb->found_old_reference = found_old_reference;
eb->found_old_mergeinfo = found_old_mergeinfo;
- eb->verified_dirents_cache = verified_dirents_cache;
/* In non-verification mode, we will allow anything to be dumped because
it might be an incremental dump with possible manual intervention.
@@ -1889,7 +1832,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
&found_old_mergeinfo, NULL,
notify_func, notify_baton,
start_rev, use_deltas_for_rev, FALSE, FALSE,
- NULL, subpool));
+ subpool));
/* Drive the editor in one way or another. */
SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, subpool));
@@ -2002,55 +1945,31 @@ verify_directory_entry(void *baton, cons
struct dir_baton *db = baton;
svn_fs_dirent_t *dirent = (svn_fs_dirent_t *)val;
char *path;
- apr_hash_t *dirents;
- svn_filesize_t len;
- svn_string_t *unparsed_id;
-
- /* most directory entries will be unchanged from previous revs.
- We should find those in the cache and they must match the
- type defined in the DIRENT. */
- if (db->edit_baton->verified_dirents_cache)
- {
- svn_node_kind_t *kind;
- svn_boolean_t found;
- unparsed_id = svn_fs_unparse_id(dirent->id, pool);
-
- SVN_ERR(svn_cache__get((void **)&kind, &found,
- db->edit_baton->verified_dirents_cache,
- unparsed_id->data, pool));
-
- if (found)
- {
- if (*kind == dirent->kind)
- return SVN_NO_ERROR;
- else
- {
- path = svn_relpath_join(db->path, (const char *)key, pool);
-
- return
- svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
- _("Unexpected node kind %d for '%s'. "
- "Expected kind was %d."),
- dirent->kind, path, *kind);
- }
- }
- }
+ svn_boolean_t right_kind;
path = svn_relpath_join(db->path, (const char *)key, pool);
/* since we can't access the directory entries directly by their ID,
we need to navigate from the FS_ROOT to them (relatively expensive
- because we may start at a never rev than the last change to node). */
+ because we may start at a never rev than the last change to node).
+ We check that the node kind stored in the noderev matches the dir
+ entry. This also ensures that all entries point to valid noderevs.
+ */
switch (dirent->kind) {
case svn_node_dir:
- /* Getting this directory's contents is enough to ensure that our
- link to it is correct. */
- SVN_ERR(svn_fs_dir_entries(&dirents, db->edit_baton->fs_root, path, pool));
+ SVN_ERR(svn_fs_is_dir(&right_kind, db->edit_baton->fs_root, path, pool));
+ if (!right_kind)
+ return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+ _("Node '%s' is not a directory."),
+ path);
+
break;
case svn_node_file:
- /* Getting this file's size is enough to ensure that our link to it
- is correct. */
- SVN_ERR(svn_fs_file_length(&len, db->edit_baton->fs_root, path, pool));
+ SVN_ERR(svn_fs_is_file(&right_kind, db->edit_baton->fs_root, path, pool));
+ if (!right_kind)
+ return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+ _("Node '%s' is not a file."),
+ path);
break;
default:
return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
@@ -2058,11 +1977,6 @@ verify_directory_entry(void *baton, cons
dirent->kind, path);
}
- /* remember ID, kind pair */
- if (db->edit_baton->verified_dirents_cache)
- SVN_ERR(svn_cache__set(db->edit_baton->verified_dirents_cache,
- unparsed_id->data, &dirent->kind, pool));
-
return SVN_NO_ERROR;
}
@@ -2166,7 +2080,6 @@ verify_one_revision(svn_fs_t *fs,
svn_boolean_t check_normalization,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- svn_cache__t *verified_dirents_cache,
apr_pool_t *scratch_pool)
{
const svn_delta_editor_t *dump_editor;
@@ -2186,7 +2099,6 @@ verify_one_revision(svn_fs_t *fs,
start_rev,
FALSE, TRUE, /* use_deltas, verify */
check_normalization,
- verified_dirents_cache,
scratch_pool));
SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
dump_editor, dump_edit_baton,
@@ -2234,30 +2146,6 @@ verify_fs2_notify_func(svn_revnum_t revi
notify_baton->notify, pool);
}
-/* cache entry (de-)serialization support for svn_node_kind_t. */
-static svn_error_t *
-serialize_node_kind(void **data,
- apr_size_t *data_len,
- void *in,
- apr_pool_t *pool)
-{
- *data_len = sizeof(svn_node_kind_t);
- *data = in;
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-deserialize_node_kind(void **out,
- void *data,
- apr_size_t data_len,
- apr_pool_t *pool)
-{
- *out = data;
-
- return SVN_NO_ERROR;
-}
-
svn_error_t *
svn_repos_verify_fs3(svn_repos_t *repos,
svn_revnum_t start_rev,
@@ -2279,7 +2167,6 @@ svn_repos_verify_fs3(svn_repos_t *repos,
struct verify_fs2_notify_func_baton_t *verify_notify_baton = NULL;
svn_error_t *err;
svn_boolean_t found_corruption = FALSE;
- svn_cache__t *verified_dirents_cache = NULL;
/* Determine the current youngest revision of the filesystem. */
SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
@@ -2341,18 +2228,6 @@ svn_repos_verify_fs3(svn_repos_t *repos,
svn_error_clear(err);
}
- if (svn_cache__get_global_membuffer_cache())
- SVN_ERR(svn_cache__create_membuffer_cache
- (&verified_dirents_cache,
- svn_cache__get_global_membuffer_cache(),
- serialize_node_kind,
- deserialize_node_kind,
- APR_HASH_KEY_STRING,
- svn_uuid_generate(pool),
- SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
- FALSE,
- pool));
-
for (rev = start_rev; rev <= end_rev; rev++)
{
svn_pool_clear(iterpool);
@@ -2361,7 +2236,7 @@ svn_repos_verify_fs3(svn_repos_t *repos,
err = verify_one_revision(fs, rev, notify_func, notify_baton,
start_rev, check_normalization,
cancel_func, cancel_baton,
- verified_dirents_cache, iterpool);
+ iterpool);
if (err)
{
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/fs-wrap.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/fs-wrap.c Thu Jan 9 09:31:10 2014
@@ -37,6 +37,7 @@
#include "repos.h"
#include "private/svn_repos_private.h"
+#include "private/svn_sorts_private.h"
#include "private/svn_utf_private.h"
#include "private/svn_fspath.h"
@@ -88,7 +89,7 @@ svn_repos_fs_commit_txn(const char **con
svn_pool_destroy(iterpool);
/* Commit. */
- err = svn_fs_commit_txn2(conflict_p, new_rev, txn, TRUE, pool);
+ err = svn_fs_commit_txn(conflict_p, new_rev, txn, pool);
if (! SVN_IS_VALID_REVNUM(*new_rev))
{
/* The commit failed, try to restore the ephemeral properties. */
@@ -851,7 +852,7 @@ svn_repos_fs_get_inherited_props(apr_arr
apr_pstrdup(result_pool, parent_path + 1);
i_props->prop_hash = parent_properties;
/* Build the output array in depth-first order. */
- svn_sort__array_insert(&i_props, inherited_props, 0);
+ svn_sort__array_insert(inherited_props, &i_props, 0);
}
}
}
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/load-fs-vtable.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/load-fs-vtable.c Thu Jan 9 09:31:10 2014
@@ -501,7 +501,8 @@ new_revision_record(void **revision_bato
if ((rb->rev > 0) && (! rb->skipped))
{
/* Create a new fs txn. */
- SVN_ERR(svn_fs_begin_txn2(&(rb->txn), pb->fs, head_rev, 0, pool));
+ SVN_ERR(svn_fs_begin_txn2(&(rb->txn), pb->fs, head_rev,
+ SVN_FS_TXN_CLIENT_DATE, pool));
SVN_ERR(svn_fs_txn_root(&(rb->txn_root), rb->txn, pool));
if (pb->notify_func)
@@ -968,8 +969,7 @@ close_revision(void *baton)
}
/* Commit. */
- err = svn_fs_commit_txn2(&conflict_msg, &committed_rev, rb->txn, FALSE,
- rb->pool);
+ err = svn_fs_commit_txn(&conflict_msg, &committed_rev, rb->txn, rb->pool);
if (SVN_IS_VALID_REVNUM(committed_rev))
{
if (err)
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/rev_hunt.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_repos/rev_hunt.c Thu Jan 9 09:31:10 2014
@@ -309,11 +309,11 @@ svn_repos_deleted_rev(svn_fs_t *fs,
apr_pool_t *pool)
{
apr_pool_t *subpool;
- svn_fs_root_t *root, *copy_root;
+ svn_fs_root_t *start_root, *root, *copy_root;
const char *copy_path;
svn_revnum_t mid_rev;
- const svn_fs_id_t *start_node_id, *curr_node_id;
- svn_error_t *err;
+ svn_node_kind_t kind;
+ svn_fs_node_relation_t node_relation;
/* Validate the revision range. */
if (! SVN_IS_VALID_REVNUM(start))
@@ -334,32 +334,19 @@ svn_repos_deleted_rev(svn_fs_t *fs,
}
/* Ensure path exists in fs at start revision. */
- SVN_ERR(svn_fs_revision_root(&root, fs, start, pool));
- err = svn_fs_node_id(&start_node_id, root, path, pool);
- if (err)
+ SVN_ERR(svn_fs_revision_root(&start_root, fs, start, pool));
+ SVN_ERR(svn_fs_check_path(&kind, start_root, path, pool));
+ if (kind == svn_node_none)
{
- if (err->apr_err == SVN_ERR_FS_NOT_FOUND)
- {
- /* Path must exist in fs at start rev. */
- *deleted = SVN_INVALID_REVNUM;
- svn_error_clear(err);
- return SVN_NO_ERROR;
- }
- return svn_error_trace(err);
+ /* Path must exist in fs at start rev. */
+ *deleted = SVN_INVALID_REVNUM;
+ return SVN_NO_ERROR;
}
/* Ensure path was deleted at or before end revision. */
SVN_ERR(svn_fs_revision_root(&root, fs, end, pool));
- err = svn_fs_node_id(&curr_node_id, root, path, pool);
- if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
- {
- svn_error_clear(err);
- }
- else if (err)
- {
- return svn_error_trace(err);
- }
- else
+ SVN_ERR(svn_fs_check_path(&kind, root, path, pool));
+ if (kind != svn_node_none)
{
/* path exists in the end node and the end node is equivalent
or otherwise equivalent to the start node. This can mean
@@ -386,8 +373,9 @@ svn_repos_deleted_rev(svn_fs_t *fs,
5) The start node was deleted and replaced by a node which
it does not share any history with.
*/
- SVN_ERR(svn_fs_node_id(&curr_node_id, root, path, pool));
- if (svn_fs_compare_ids(start_node_id, curr_node_id) != -1)
+ SVN_ERR(svn_fs_node_relation(&node_relation, start_root, path,
+ root, path, pool));
+ if (node_relation != svn_fs_node_unrelated)
{
SVN_ERR(svn_fs_closest_copy(©_root, ©_path, root,
path, pool));
@@ -450,28 +438,23 @@ svn_repos_deleted_rev(svn_fs_t *fs,
/* Get revision root and node id for mid_rev at that revision. */
SVN_ERR(svn_fs_revision_root(&root, fs, mid_rev, subpool));
- err = svn_fs_node_id(&curr_node_id, root, path, subpool);
-
- if (err)
+ SVN_ERR(svn_fs_check_path(&kind, root, path, pool));
+ if (kind == svn_node_none)
{
- if (err->apr_err == SVN_ERR_FS_NOT_FOUND)
- {
- /* Case D: Look lower in the range. */
- svn_error_clear(err);
- end = mid_rev;
- mid_rev = (start + mid_rev) / 2;
- }
- else
- return svn_error_trace(err);
+ /* Case D: Look lower in the range. */
+ end = mid_rev;
+ mid_rev = (start + mid_rev) / 2;
}
else
{
/* Determine the relationship between the start node
and the current node. */
- int cmp = svn_fs_compare_ids(start_node_id, curr_node_id);
+ SVN_ERR(svn_fs_node_relation(&node_relation, start_root, path,
+ root, path, pool));
+ if (node_relation != svn_fs_node_unrelated)
SVN_ERR(svn_fs_closest_copy(©_root, ©_path, root,
path, subpool));
- if (cmp == -1 ||
+ if (node_relation == svn_fs_node_unrelated ||
(copy_root &&
(svn_fs_revision_root_revision(copy_root) > start)))
{
@@ -654,7 +637,6 @@ svn_repos_trace_node_locations(svn_fs_t
svn_revnum_t revision;
svn_boolean_t is_ancestor;
apr_pool_t *lastpool, *currpool;
- const svn_fs_id_t *id;
SVN_ERR_ASSERT(location_revisions_orig->elt_size == sizeof(svn_revnum_t));
@@ -774,20 +756,22 @@ svn_repos_trace_node_locations(svn_fs_t
the node existing at the same path. We will look up path@lrev
for each remaining location-revision and make sure it is related
to path@revision. */
- SVN_ERR(svn_fs_revision_root(&root, fs, revision, currpool));
- SVN_ERR(svn_fs_node_id(&id, root, path, pool));
+ SVN_ERR(svn_fs_revision_root(&root, fs, revision, lastpool));
while (revision_ptr < revision_ptr_end)
{
svn_node_kind_t kind;
- const svn_fs_id_t *lrev_id;
+ svn_fs_node_relation_t node_relation;
+ svn_fs_root_t *cur_rev_root;
svn_pool_clear(currpool);
- SVN_ERR(svn_fs_revision_root(&root, fs, *revision_ptr, currpool));
- SVN_ERR(svn_fs_check_path(&kind, root, path, currpool));
+ SVN_ERR(svn_fs_revision_root(&cur_rev_root, fs, *revision_ptr,
+ currpool));
+ SVN_ERR(svn_fs_check_path(&kind, cur_rev_root, path, currpool));
if (kind == svn_node_none)
break;
- SVN_ERR(svn_fs_node_id(&lrev_id, root, path, currpool));
- if (! svn_fs_check_related(id, lrev_id))
+ SVN_ERR(svn_fs_node_relation(&node_relation, root, path,
+ cur_rev_root, path, currpool));
+ if (node_relation == svn_fs_node_unrelated)
break;
/* The node exists at the same path; record that and advance. */
Propchange: subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/checksum.h
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/cmdline.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/cmdline.c Thu Jan 9 09:31:10 2014
@@ -64,6 +64,7 @@
#include "private/svn_cmdline_private.h"
#include "private/svn_utf_private.h"
+#include "private/svn_sorts_private.h"
#include "private/svn_string_private.h"
#include "win32_crashrpt.h"
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/config_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/config_auth.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/config_auth.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/config_auth.c Thu Jan 9 09:31:10 2014
@@ -89,6 +89,7 @@ svn_config_read_auth_data(apr_hash_t **h
if (kind == svn_node_file)
{
svn_stream_t *stream;
+ svn_string_t *stored_realm;
SVN_ERR_W(svn_stream_open_readonly(&stream, auth_path, pool, pool),
_("Unable to open auth file for reading"));
@@ -100,6 +101,11 @@ svn_config_read_auth_data(apr_hash_t **h
svn_dirent_local_style(auth_path, pool)));
SVN_ERR(svn_stream_close(stream));
+
+ stored_realm = svn_hash_gets(*hash, SVN_CONFIG_REALMSTRING_KEY);
+
+ if (!stored_realm || strcmp(stored_realm->data, realmstring) != 0)
+ *hash = NULL; /* Hash collision, or somebody tampering with storage */
}
return SVN_NO_ERROR;
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/error.c?rev=1556765&r1=1556764&r2=1556765&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/error.c Thu Jan 9 09:31:10 2014
@@ -261,8 +261,7 @@ svn_error_compose_create(svn_error_t *er
if (err1 && err2)
{
svn_error_compose(err1,
- svn_error_quick_wrap(err2,
- _("Additional errors:")));
+ svn_error_create(SVN_ERR_COMPOSED_ERROR, err2, NULL));
return err1;
}
return err1 ? err1 : err2;
@@ -314,7 +313,10 @@ svn_error_root_cause(svn_error_t *err)
{
while (err)
{
- if (err->child)
+ /* I don't think we can change the behavior here, but the additional
+ error chain doesn't define the root cause. Perhaps we should rev
+ this function. */
+ if (err->child /*&& err->child->apr_err != SVN_ERR_COMPOSED_ERROR*/)
err = err->child;
else
break;
Propchange: subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/fnv1a.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/fsfs-ucsnorm/subversion/libsvn_subr/fnv1a.h
------------------------------------------------------------------------------
svn:eol-style = native