You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/07/22 13:22:20 UTC
svn commit: r1505660 [3/5] - in /subversion/branches/fsfs-improvements: ./
build/generator/ build/generator/swig/ build/generator/templates/
notes/http-and-webdav/ subversion/ subversion/bindings/swig/
subversion/bindings/swig/ruby/libsvn_swig_ruby/ su...
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.h?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/transaction.h Mon Jul 22 11:22:18 2013
@@ -195,12 +195,14 @@ svn_fs_fs__set_proplist(svn_fs_t *fs,
/* Commit the transaction TXN in filesystem FS and return its new
revision number in *REV. If the transaction is out of date, return
- the error SVN_ERR_FS_TXN_OUT_OF_DATE. Use POOL for temporary
- allocations. */
+ the error SVN_ERR_FS_TXN_OUT_OF_DATE. Update commit time to ensure that
+ svn:date revprops remain ordered if SET_TIMESTAMP is non-zero. Use POOL for
+ temporary allocations. */
svn_error_t *
svn_fs_fs__commit(svn_revnum_t *new_rev_p,
svn_fs_t *fs,
svn_fs_txn_t *txn,
+ svn_boolean_t set_timestamp,
apr_pool_t *pool);
/* Set *NAMES_P to an array of names which are all the active
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.c Mon Jul 22 11:22:18 2013
@@ -1991,6 +1991,7 @@ svn_error_t *
svn_fs_fs__commit_txn(const char **conflict_p,
svn_revnum_t *new_rev,
svn_fs_txn_t *txn,
+ svn_boolean_t set_timestamp,
apr_pool_t *pool)
{
/* How do commits work in Subversion?
@@ -2087,7 +2088,7 @@ svn_fs_fs__commit_txn(const char **confl
txn->base_rev = youngish_rev;
/* Try to commit. */
- err = svn_fs_fs__commit(new_rev, fs, txn, iterpool);
+ err = svn_fs_fs__commit(new_rev, fs, txn, set_timestamp, iterpool);
if (err && (err->apr_err == SVN_ERR_FS_TXN_OUT_OF_DATE))
{
/* Did someone else finish committing a new revision while we
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.h?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/tree.h Mon Jul 22 11:22:18 2013
@@ -48,10 +48,12 @@ svn_error_t *svn_fs_fs__deltify(svn_fs_t
/* Commit the transaction TXN as a new revision. Return the new
revision in *NEW_REV. If the transaction conflicts with other
changes return SVN_ERR_FS_CONFLICT and set *CONFLICT_P to a string
- that details the cause of the conflict. Perform temporary
- allocations in POOL. */
+ that details the cause of the conflict.
+ Update commit time to ensure that svn:date revprops remain ordered if
+ SET_TIMESTAMP is non-zero. Perform temporary allocations in POOL. */
svn_error_t *svn_fs_fs__commit_txn(const char **conflict_p,
svn_revnum_t *new_rev, svn_fs_txn_t *txn,
+ svn_boolean_t set_timestamp,
apr_pool_t *pool);
/* Set ROOT_P to the root directory of transaction TXN. Allocate the
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/ra_serf.h?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/ra_serf.h Mon Jul 22 11:22:18 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/branches/fsfs-improvements/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/update.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/update.c Mon Jul 22 11:22:18 2013
@@ -82,7 +82,7 @@ typedef enum report_state_e {
NEED_PROP_NAME,
TXDELTA
-#ifdef USE_TRANSITION_PARSER
+#ifdef NOT_USED_YET
,
CHECKED_IN,
@@ -390,6 +390,9 @@ struct report_context_t {
/* The path to the REPORT request */
const char *path;
+ /* Are we done parsing the REPORT response? */
+ svn_boolean_t done;
+
/* Did we receive all data from the network? */
svn_boolean_t report_received;
@@ -411,7 +414,7 @@ struct report_context_t {
#define V_ SVN_DAV_PROP_NS_DAV
static const svn_ra_serf__xml_transition_t update_ttable[] = {
{ INITIAL, S_, "update-report", UPDATE_REPORT,
- FALSE, { NULL }, TRUE },
+ FALSE, { NULL }, FALSE },
{ UPDATE_REPORT, S_, "target-revision", TARGET_REVISION,
FALSE, { "rev", NULL }, TRUE },
@@ -2565,6 +2568,7 @@ update_closed(svn_ra_serf__xml_estate_t
if (leaving_state == UPDATE_REPORT)
{
ctx->report_completed = TRUE;
+ ctx->done = TRUE;
}
else if (leaving_state == TARGET_REVISION)
{
@@ -2816,10 +2820,9 @@ finish_report(void *report_baton,
report_context_t *report = report_baton;
svn_ra_serf__session_t *sess = report->sess;
svn_ra_serf__handler_t *handler;
+ svn_ra_serf__xml_parser_t *parser_ctx;
#ifdef USE_TRANSITION_PARSER
svn_ra_serf__xml_context_t *xmlctx;
-#else
- svn_ra_serf__xml_parser_t *parser_ctx;
#endif
const char *report_target;
svn_stringbuf_t *buf = NULL;
@@ -2882,7 +2885,7 @@ finish_report(void *report_baton,
parser_ctx->start = start_report;
parser_ctx->end = end_report;
parser_ctx->cdata = cdata_report;
- parser_ctx->done = &handler->done;
+ parser_ctx->done = &report->done;
handler->response_handler = svn_ra_serf__handle_xml_parser;
handler->response_baton = parser_ctx;
@@ -2902,7 +2905,7 @@ finish_report(void *report_baton,
network or because we've spooled the entire response into our "pending"
content of the XML parser. The DONE flag will get set when all the
XML content has been received *and* parsed. */
- while (!handler->done
+ while (!report->done
|| report->num_active_fetches
|| report->num_active_propfinds)
{
@@ -3144,7 +3147,6 @@ finish_report(void *report_baton,
}
report->done_dir_propfinds = NULL;
-#ifndef USE_TRANSITION_PARSER
/* If the parser is paused, and the number of active requests has
dropped far enough, then resume parsing. */
if (parser_ctx->paused
@@ -3159,7 +3161,6 @@ finish_report(void *report_baton,
SVN_ERR(svn_ra_serf__process_pending(parser_ctx,
&report->report_received,
iterpool_inner));
-#endif
/* Debugging purposes only! */
for (i = 0; i < sess->num_conns; i++)
@@ -3280,6 +3281,7 @@ make_update_reporter(svn_ra_session_t *r
report->update_editor = update_editor;
report->update_baton = update_baton;
+ report->done = FALSE;
*reporter = &ra_serf_reporter;
*report_baton = report;
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/util.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_ra_serf/util.c Mon Jul 22 11:22:18 2013
@@ -747,8 +747,6 @@ svn_ra_serf__context_run_wait(svn_boolea
the connection timed out. */
if (APR_STATUS_IS_TIMEUP(status))
{
- svn_error_clear(err);
- err = SVN_NO_ERROR;
status = 0;
if (sess->timeout)
@@ -759,8 +757,11 @@ svn_ra_serf__context_run_wait(svn_boolea
}
else
{
- return svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
- _("Connection timed out"));
+ return
+ svn_error_compose_create(
+ err,
+ svn_error_create(SVN_ERR_RA_DAV_CONN_TIMEOUT, NULL,
+ _("Connection timed out")));
}
}
}
@@ -808,6 +809,23 @@ svn_ra_serf__context_run_one(svn_ra_serf
/* Wait until the response logic marks its DONE status. */
err = svn_ra_serf__context_run_wait(&handler->done, handler->session,
scratch_pool);
+
+ /* A callback invocation has been canceled. In this simple case of
+ context_run_one, we can keep the ra-session operational by resetting
+ the connection.
+
+ If we don't do this, the next context run will notice that the connection
+ is still in the error state and will just return SVN_ERR_CEASE_INVOCATION
+ (=the last error for the connection) again */
+ if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION)
+ {
+ apr_status_t status = serf_connection_reset(handler->conn->conn);
+
+ if (status)
+ err = svn_error_compose_create(err,
+ svn_ra_serf__wrap_err(status, NULL));
+ }
+
if (handler->server_error)
{
err = svn_error_compose_create(err, handler->server_error->error);
@@ -1606,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);
@@ -1641,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
@@ -1859,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;
}
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_ra_svn/client.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_ra_svn/client.c Mon Jul 22 11:22:18 2013
@@ -1479,16 +1479,19 @@ static svn_error_t *ra_svn_diff(svn_ra_s
}
-static svn_error_t *ra_svn_log(svn_ra_session_t *session,
- const apr_array_header_t *paths,
- svn_revnum_t start, svn_revnum_t end,
- int limit,
- svn_boolean_t discover_changed_paths,
- svn_boolean_t strict_node_history,
- svn_boolean_t include_merged_revisions,
- const apr_array_header_t *revprops,
- svn_log_entry_receiver_t receiver,
- void *receiver_baton, apr_pool_t *pool)
+static svn_error_t *
+perform_ra_svn_log(svn_error_t **outer_error,
+ svn_ra_session_t *session,
+ const apr_array_header_t *paths,
+ svn_revnum_t start, svn_revnum_t end,
+ int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_boolean_t include_merged_revisions,
+ const apr_array_header_t *revprops,
+ svn_log_entry_receiver_t receiver,
+ void *receiver_baton,
+ apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
@@ -1501,6 +1504,7 @@ static svn_error_t *ra_svn_log(svn_ra_se
svn_boolean_t want_author = FALSE;
svn_boolean_t want_message = FALSE;
svn_boolean_t want_date = FALSE;
+ int nreceived = 0;
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "log"));
if (paths)
@@ -1562,7 +1566,6 @@ static svn_error_t *ra_svn_log(svn_ra_se
svn_ra_svn_item_t *item;
apr_hash_t *cphash;
svn_revnum_t rev;
- int nreceived;
svn_pool_clear(iterpool);
SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item));
@@ -1645,9 +1648,14 @@ static svn_error_t *ra_svn_log(svn_ra_se
else
cphash = NULL;
- nreceived = 0;
- if (! (limit && (nest_level == 0) && (++nreceived > limit)))
+ /* Invoke RECEIVER
+ - Except if the server sends more than a >= 1 limit top level items
+ - Or when the callback reported a SVN_ERR_CEASE_INVOCATION
+ in an earlier invocation. */
+ if (! (limit && (nest_level == 0) && (++nreceived > limit))
+ && ! *outer_error)
{
+ svn_error_t *err;
log_entry = svn_log_entry_create(iterpool);
log_entry->changed_paths = cphash;
@@ -1671,7 +1679,15 @@ static svn_error_t *ra_svn_log(svn_ra_se
svn_hash_sets(log_entry->revprops,
SVN_PROP_REVISION_LOG, message);
- SVN_ERR(receiver(receiver_baton, log_entry, iterpool));
+ err = receiver(receiver_baton, log_entry, iterpool);
+ if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION)
+ {
+ *outer_error = svn_error_trace(
+ svn_error_compose_create(*outer_error, err));
+ }
+ else
+ SVN_ERR(err);
+
if (log_entry->has_children)
{
nest_level++;
@@ -1686,9 +1702,40 @@ static svn_error_t *ra_svn_log(svn_ra_se
svn_pool_destroy(iterpool);
/* Read the response. */
- return svn_ra_svn__read_cmd_response(conn, pool, "");
+ return svn_error_trace(svn_ra_svn__read_cmd_response(conn, pool, ""));
}
+static svn_error_t *
+ra_svn_log(svn_ra_session_t *session,
+ const apr_array_header_t *paths,
+ svn_revnum_t start, svn_revnum_t end,
+ int limit,
+ svn_boolean_t discover_changed_paths,
+ svn_boolean_t strict_node_history,
+ svn_boolean_t include_merged_revisions,
+ const apr_array_header_t *revprops,
+ svn_log_entry_receiver_t receiver,
+ void *receiver_baton, apr_pool_t *pool)
+{
+ svn_error_t *outer_error = NULL;
+ svn_error_t *err;
+
+ err = svn_error_trace(perform_ra_svn_log(&outer_error,
+ session, paths,
+ start, end,
+ limit,
+ discover_changed_paths,
+ strict_node_history,
+ include_merged_revisions,
+ revprops,
+ receiver, receiver_baton,
+ pool));
+ return svn_error_trace(
+ svn_error_compose_create(outer_error,
+ err));
+}
+
+
static svn_error_t *ra_svn_check_path(svn_ra_session_t *session,
const char *path, svn_revnum_t rev,
@@ -1963,7 +2010,7 @@ static svn_error_t *ra_svn_get_file_revs
{
svn_stream_t *stream;
- if (d_handler)
+ if (d_handler && d_handler != svn_delta_noop_window_handler)
stream = svn_txdelta_parse_svndiff(d_handler, d_baton, TRUE,
rev_pool);
else
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_ra_svn/marshal.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_ra_svn/marshal.c Mon Jul 22 11:22:18 2013
@@ -411,7 +411,7 @@ static svn_error_t *readbuf_fill(svn_ra_
return SVN_NO_ERROR;
}
-static APR_INLINE svn_error_t *
+static SVN__FORCE_INLINE svn_error_t *
readbuf_getchar(svn_ra_svn_conn_t *conn, apr_pool_t *pool, char *result)
{
if (conn->read_ptr == conn->read_end)
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_repos/load-fs-vtable.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_repos/load-fs-vtable.c Mon Jul 22 11:22:18 2013
@@ -99,6 +99,9 @@ struct revision_baton
apr_int32_t rev_offset;
svn_boolean_t skipped;
+ /* Array of svn_prop_t with revision properties. */
+ apr_array_header_t *revprops;
+
struct parse_baton *pb;
apr_pool_t *pool;
};
@@ -448,6 +451,7 @@ make_revision_baton(apr_hash_t *headers,
rb->pb = pb;
rb->pool = pool;
rb->rev = SVN_INVALID_REVNUM;
+ rb->revprops = apr_array_make(rb->pool, 8, sizeof(svn_prop_t));
if ((val = svn_hash_gets(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER)))
{
@@ -698,10 +702,12 @@ set_revision_property(void *baton,
if (rb->rev > 0)
{
- if (rb->pb->validate_props)
- SVN_ERR(svn_repos_fs_change_txn_prop(rb->txn, name, value, rb->pool));
- else
- SVN_ERR(svn_fs_change_txn_prop(rb->txn, name, value, rb->pool));
+ svn_prop_t *prop = &APR_ARRAY_PUSH(rb->revprops, svn_prop_t);
+
+ /* Collect property changes to apply them in one FS call in
+ close_revision. */
+ prop->name = apr_pstrdup(rb->pool, name);
+ prop->value = svn_string_dup(value, rb->pool);
/* Remember any datestamp that passes through! (See comment in
close_revision() below.) */
@@ -920,6 +926,21 @@ close_revision(void *baton)
if (rb->skipped || (rb->rev <= 0))
return SVN_NO_ERROR;
+ if (!rb->datestamp)
+ {
+ /* Remove 'svn:date' revision property that was set by FS layer when TXN
+ created if source dump doesn't have 'svn:date' property. */
+ svn_prop_t *prop = &APR_ARRAY_PUSH(rb->revprops, svn_prop_t);
+ prop->name = SVN_PROP_REVISION_DATE;
+ prop->value = NULL;
+ }
+
+ /* Apply revision property changes. */
+ if (rb->pb->validate_props)
+ SVN_ERR(svn_repos_fs_change_txn_props(rb->txn, rb->revprops, rb->pool));
+ else
+ SVN_ERR(svn_fs_change_txn_props(rb->txn, rb->revprops, rb->pool));
+
/* Get the txn name and hooks environment if they will be needed. */
if (pb->use_pre_commit_hook || pb->use_post_commit_hook)
{
@@ -947,7 +968,8 @@ close_revision(void *baton)
}
/* Commit. */
- err = svn_fs_commit_txn(&conflict_msg, &committed_rev, rb->txn, rb->pool);
+ err = svn_fs_commit_txn2(&conflict_msg, &committed_rev, rb->txn, FALSE,
+ rb->pool);
if (SVN_IS_VALID_REVNUM(committed_rev))
{
if (err)
@@ -1005,15 +1027,6 @@ close_revision(void *baton)
/* Deltify the predecessors of paths changed in this revision. */
SVN_ERR(svn_fs_deltify_revision(pb->fs, committed_rev, rb->pool));
- /* Grrr, svn_fs_commit_txn rewrites the datestamp property to the
- current clock-time. We don't want that, we want to preserve
- history exactly. Good thing revision props aren't versioned!
- Note that if rb->datestamp is NULL, that's fine -- if the dump
- data doesn't carry a datestamp, we want to preserve that fact in
- the load. */
- SVN_ERR(change_rev_prop(pb->repos, committed_rev, SVN_PROP_REVISION_DATE,
- rb->datestamp, pb->validate_props, rb->pool));
-
if (pb->notify_func)
{
pb->notify->action = svn_repos_notify_load_txn_committed;
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-inprocess.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-inprocess.c Mon Jul 22 11:22:18 2013
@@ -246,6 +246,37 @@ inprocess_cache_get(void **value_p,
return SVN_NO_ERROR;
}
+static svn_error_t *
+inprocess_cache_has_key_internal(svn_boolean_t *found,
+ inprocess_cache_t *cache,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ *found = apr_hash_get(cache->hash, key, cache->klen) != NULL;
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_has_key(svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ inprocess_cache_t *cache = cache_void;
+
+ if (key)
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_has_key_internal(found,
+ cache,
+ key,
+ scratch_pool));
+ else
+ *found = FALSE;
+
+ return SVN_NO_ERROR;
+}
+
/* Removes PAGE from the LRU list, removes all of its entries from
* CACHE's hash, clears its pool, and sets its entry pointer to NULL.
* Finally, puts it in the "partial page" slot in the cache and sets
@@ -604,6 +635,7 @@ inprocess_cache_get_info(void *cache_voi
static svn_cache__vtable_t inprocess_cache_vtable = {
inprocess_cache_get,
+ inprocess_cache_has_key,
inprocess_cache_set,
inprocess_cache_iter,
inprocess_cache_is_cachable,
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-membuffer.c Mon Jul 22 11:22:18 2013
@@ -361,6 +361,10 @@ typedef struct entry_t
*/
apr_uint32_t previous;
+ /* Priority of this entry. This entry will not be replaced by lower-
+ * priority items.
+ */
+ apr_uint32_t priority;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
/* Remember type, content and key hashes.
*/
@@ -1013,13 +1017,15 @@ find_entry(svn_membuffer_t *cache,
if (group->used == GROUP_SIZE)
{
/* every entry gets the same chance of being removed.
- * Otherwise, we free the first entry, fill it and
- * remove it again on the next occasion without considering
- * the other entries in this group.
+ * Otherwise, we free the first entry, fill it and remove it
+ * again on the next occasion without considering the other
+ * entries in this group. Also, apply priorities strictly.
*/
entry = &group->entries[rand() % GROUP_SIZE];
for (i = 1; i < GROUP_SIZE; ++i)
- if (entry->hit_count > group->entries[i].hit_count)
+ if ( (entry->priority > group->entries[i].priority)
+ || ( entry->priority == group->entries[i].priority
+ && entry->hit_count > group->entries[i].hit_count))
entry = &group->entries[i];
/* for the entries that don't have been removed,
@@ -1128,6 +1134,16 @@ ensure_data_insertable_l2(svn_membuffer_
apr_uint64_t average_hit_value;
apr_uint64_t threshold;
+ /* accumulated size of the entries that have been removed to make
+ * room for the new one.
+ */
+ apr_size_t moved_size = 0;
+
+ /* count the number of entries that got moved. A single large entry
+ * being moved is not enough to reject an insertion.
+ */
+ apr_size_t moved_count = 0;
+
/* accumulated "worth" of items dropped so far */
apr_size_t drop_hits = 0;
@@ -1159,10 +1175,16 @@ ensure_data_insertable_l2(svn_membuffer_
if (end >= to_fit_in->size + cache->l2.current_data)
return TRUE;
+ /* Don't be too eager to cache data. If a lot of data has been
+ * moved around, the current item has probably a relatively low
+ * priority. So, give up after some time.
+ */
+ if (moved_size > 8 * to_fit_in->size && moved_count > 3)
+ return FALSE;
+
/* if the net worth (in hits) of items removed is already larger
* than what we want to insert, reject TO_FIT_IN because it still
- * does not fit in.
- */
+ * does not fit in. */
if (drop_hits > to_fit_in->hit_count)
return FALSE;
@@ -1180,8 +1202,15 @@ ensure_data_insertable_l2(svn_membuffer_
}
else
{
+ svn_boolean_t keep;
entry = get_entry(cache, cache->l2.next);
+ /* Reject insertion for entries with low priority, if the current
+ * entry has seen recent hits. */
+ if ( entry->hit_count
+ && to_fit_in->priority < SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY)
+ return FALSE;
+
/* Keep entries that are very small. Those are likely to be data
* headers or similar management structures. So, they are probably
* important while not occupying much space.
@@ -1190,56 +1219,75 @@ ensure_data_insertable_l2(svn_membuffer_
if ( (apr_uint64_t)entry->size * cache->used_entries
< cache->data_used / 8)
{
- move_entry(cache, entry);
+ keep = TRUE;
}
else if (cache->l2.next / GROUP_SIZE == idx / GROUP_SIZE)
{
/* Special case: we cannot drop entries that are in the same
- * group as TO_FIT_IN because that might the latter to become
- * invalidated it it happens to be the highest used entry in
- * the group. So, we must keep ENTRY unconditionally.
- * (this is a very rare condition)
- */
- move_entry(cache, entry);
+ * group as TO_FIT_IN because that might the latter to become
+ * invalidated it it happens to be the highest used entry in
+ * the group. So, we must keep ENTRY unconditionally.
+ * (this is a very rare condition)
+ */
+ keep = TRUE;
}
- else
+ else if ( entry->priority < SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY
+ && to_fit_in->priority > entry->priority)
+ {
+ /* Be quick to evict low-priority entries if the one to insert
+ * is of higher priority.
+ */
+ keep = FALSE;
+ }
+ else if (to_fit_in->priority != entry->priority)
+ {
+ /* Not the same priority but the lower prio side is not a
+ * clear loser either (already checked those cases above).
+ * Keep the current entry if it has seen more hits recently
+ * or is smaller than the one to insert - both relative to
+ * their respective priority.
+ */
+ keep = to_fit_in->hit_count * to_fit_in->priority
+ < entry->hit_count * entry->priority
+ || to_fit_in->size * to_fit_in->priority
+ < entry->size * entry->priority;
+ }
+ else if (cache->hit_count > cache->used_entries)
{
- svn_boolean_t keep;
+ /* Roll the dice and determine a threshold somewhere
+ * from 0 up to 2 times the average hit count.
+ */
+ average_hit_value = cache->hit_count / cache->used_entries;
+ threshold = (average_hit_value+1) * (rand() % 4096) / 2048;
- if (cache->hit_count > cache->used_entries)
- {
- /* Roll the dice and determine a threshold somewhere from
- * 0 up to 2 times the average hit count.
- */
- average_hit_value = cache->hit_count / cache->used_entries;
- threshold = (average_hit_value+1) * (rand() % 4096) / 2048;
+ keep = entry->hit_count > threshold;
+ }
+ else
+ {
+ /* general hit count is low. Keep everything that got hit
+ * at all and assign some 50% survival chance to everything
+ * else.
+ */
+ keep = rand() & 1;
+ }
- keep = entry->hit_count >= threshold;
- }
- else
- {
- /* general hit count is low. Keep everything that got
- * hit at all and assign some 50% survival chance to
- * everything else.
- */
- keep = (entry->hit_count > 0) || (rand() & 1);
- }
+ /* keepers or destroyers? */
+ if (keep)
+ {
+ /* Moving entries around is not for free -> track costs. */
+ moved_size += entry->size;
+ moved_count++;
- /* keepers or destroyers? */
- if (keep)
- {
- /* Keep ENTRY and move the insertion window.
- */
- move_entry(cache, entry);
- }
- else
- {
- /* Drop the entry from the end of the insertion window,
- * because it had been hit less than the threshold.
- */
- drop_hits += entry->hit_count;
- drop_entry(cache, entry);
- }
+ move_entry(cache, entry);
+ }
+ else
+ {
+ /* Drop the entry from the end of the insertion window, if it
+ * has been hit less than the threshold. Otherwise, keep it and
+ * move the insertion window one entry further.
+ */
+ drop_hits += entry->hit_count;
+ drop_entry(cache, entry);
}
}
}
@@ -1582,6 +1630,7 @@ membuffer_cache_set_internal(svn_membuff
apr_uint32_t group_index,
char *buffer,
apr_size_t size,
+ apr_uint32_t priority,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
apr_pool_t *scratch_pool)
{
@@ -1594,6 +1643,7 @@ membuffer_cache_set_internal(svn_membuff
{
cache->data_used += size - entry->size;
entry->size = size;
+ entry->priority = priority;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -1624,6 +1674,7 @@ membuffer_cache_set_internal(svn_membuff
entry = find_entry(cache, group_index, to_find, TRUE);
entry->size = size;
entry->offset = cache->l1.current_data;
+ entry->priority = priority;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -1673,6 +1724,7 @@ membuffer_cache_set(svn_membuffer_t *cac
entry_key_t key,
void *item,
svn_cache__serialize_func_t serializer,
+ apr_uint32_t priority,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
apr_pool_t *scratch_pool)
{
@@ -1697,6 +1749,7 @@ membuffer_cache_set(svn_membuffer_t *cac
group_index,
buffer,
size,
+ priority,
DEBUG_CACHE_MEMBUFFER_TAG
scratch_pool));
return SVN_NO_ERROR;
@@ -1808,6 +1861,43 @@ membuffer_cache_get(svn_membuffer_t *cac
}
/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. If no item has been stored for KEY, *FOUND
+ * will be FALSE and TRUE otherwise.
+ */
+static svn_error_t *
+membuffer_cache_has_key_internal(svn_membuffer_t *cache,
+ apr_uint32_t group_index,
+ entry_key_t to_find,
+ svn_boolean_t *found)
+{
+ *found = find_entry(cache, group_index, to_find, FALSE) != NULL;
+
+ return SVN_NO_ERROR;
+}
+
+/* Look for an entry identified by KEY. If no item has been stored
+ * for KEY, *FOUND will be set to FALSE and TRUE otherwise.
+ */
+/* Implements svn_cache__has_key for membuffer caches.
+ */
+static svn_error_t *
+membuffer_cache_has_key(svn_membuffer_t *cache,
+ entry_key_t key,
+ svn_boolean_t *found)
+{
+ /* find the entry group that will hold the key.
+ */
+ apr_uint32_t group_index = get_group_index(&cache, key);
+ WITH_READ_LOCK(cache,
+ membuffer_cache_has_key_internal(cache,
+ group_index,
+ key,
+ found));
+
+ return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
* by the hash value TO_FIND. FOUND indicates whether that entry exists.
* If not found, *ITEM will be NULL.
*
@@ -2097,6 +2187,9 @@ typedef struct svn_membuffer_cache_t
*/
apr_ssize_t key_len;
+ /* priority class for all items written through this interface */
+ apr_uint32_t priority;
+
/* Temporary buffer containing the hash key for the current access
*/
entry_key_t combined_key;
@@ -2291,6 +2384,39 @@ svn_membuffer_cache_get(void **value_p,
/* return result */
*found = *value_p != NULL;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.has_key (not thread-safe)
+ */
+static svn_error_t *
+svn_membuffer_cache_has_key(svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ svn_membuffer_cache_t *cache = cache_void;
+
+ /* special case */
+ if (key == NULL)
+ {
+ *found = FALSE;
+
+ return SVN_NO_ERROR;
+ }
+
+ /* construct the full, i.e. globally unique, key by adding
+ * this cache instances' prefix
+ */
+ combine_key(cache, key, cache->key_len);
+
+ /* Look the item up. */
+ SVN_ERR(membuffer_cache_has_key(cache->membuffer,
+ cache->combined_key,
+ found));
+
+ /* return result */
return SVN_NO_ERROR;
}
@@ -2332,6 +2458,7 @@ svn_membuffer_cache_set(void *cache_void
cache->combined_key,
value,
cache->serializer,
+ cache->priority,
DEBUG_CACHE_MEMBUFFER_TAG
cache->pool);
}
@@ -2488,6 +2615,7 @@ svn_membuffer_cache_get_info(void *cache
*/
static svn_cache__vtable_t membuffer_cache_vtable = {
svn_membuffer_cache_get,
+ svn_membuffer_cache_has_key,
svn_membuffer_cache_set,
svn_membuffer_cache_iter,
svn_membuffer_cache_is_cachable,
@@ -2516,6 +2644,24 @@ svn_membuffer_cache_get_synced(void **va
return SVN_NO_ERROR;
}
+/* Implement svn_cache__vtable_t.has_key and serialize all cache access.
+ */
+static svn_error_t *
+svn_membuffer_cache_has_key_synced(svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ apr_pool_t *result_pool)
+{
+ svn_membuffer_cache_t *cache = cache_void;
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ svn_membuffer_cache_has_key(found,
+ cache_void,
+ key,
+ result_pool));
+
+ return SVN_NO_ERROR;
+}
+
/* Implement svn_cache__vtable_t.set and serialize all cache access.
*/
static svn_error_t *
@@ -2582,6 +2728,7 @@ svn_membuffer_cache_set_partial_synced(v
*/
static svn_cache__vtable_t membuffer_cache_synced_vtable = {
svn_membuffer_cache_get_synced,
+ svn_membuffer_cache_has_key_synced,
svn_membuffer_cache_set_synced,
svn_membuffer_cache_iter, /* no sync required */
svn_membuffer_cache_is_cachable, /* no sync required */
@@ -2636,6 +2783,7 @@ svn_cache__create_membuffer_cache(svn_ca
svn_cache__deserialize_func_t deserializer,
apr_ssize_t klen,
const char *prefix,
+ apr_uint32_t priority,
svn_boolean_t thread_safe,
apr_pool_t *pool)
{
@@ -2656,6 +2804,7 @@ svn_cache__create_membuffer_cache(svn_ca
? deserializer
: deserialize_svn_stringbuf;
cache->full_prefix = apr_pstrdup(pool, prefix);
+ cache->priority = priority;
cache->key_len = klen;
cache->pool = svn_pool_create(pool);
cache->alloc_counter = 0;
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-memcache.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-memcache.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-memcache.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache-memcache.c Mon Jul 22 11:22:18 2013
@@ -213,6 +213,26 @@ memcache_get(void **value_p,
return SVN_NO_ERROR;
}
+/* Implement vtable.has_key in terms of the getter.
+ */
+static svn_error_t *
+memcache_has_key(svn_boolean_t *found,
+ void *cache_void,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ char *data;
+ apr_size_t data_len;
+ SVN_ERR(memcache_internal_get(&data,
+ &data_len,
+ found,
+ cache_void,
+ key,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
/* Core functionality of our setter functions: store LENGH bytes of DATA
* to be identified by KEY in the memcached given by CACHE_VOID. Use POOL
* for temporary allocations.
@@ -371,6 +391,7 @@ memcache_get_info(void *cache_void,
static svn_cache__vtable_t memcache_vtable = {
memcache_get,
+ memcache_has_key,
memcache_set,
memcache_iter,
memcache_is_cachable,
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache.c Mon Jul 22 11:22:18 2013
@@ -96,6 +96,21 @@ svn_cache__get(void **value_p,
}
svn_error_t *
+svn_cache__has_key(svn_boolean_t *found,
+ svn_cache__t *cache,
+ const void *key,
+ apr_pool_t *scratch_pool)
+{
+ *found = FALSE;
+ return handle_error(cache,
+ (cache->vtable->has_key)(found,
+ cache->cache_internal,
+ key,
+ scratch_pool),
+ scratch_pool);
+}
+
+svn_error_t *
svn_cache__set(svn_cache__t *cache,
const void *key,
void *value,
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache.h?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/cache.h Mon Jul 22 11:22:18 2013
@@ -38,6 +38,12 @@ typedef struct svn_cache__vtable_t {
const void *key,
apr_pool_t *result_pool);
+ /* See svn_cache__has_key(). */
+ svn_error_t *(*has_key)(svn_boolean_t *found,
+ void *cache_implementation,
+ const void *key,
+ apr_pool_t *scratch_pool);
+
/* See svn_cache__set(). */
svn_error_t *(*set)(void *cache_implementation,
const void *key,
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/compress.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/compress.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/compress.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/compress.c Mon Jul 22 11:22:18 2013
@@ -78,7 +78,7 @@ svn__decode_uint(apr_uint64_t *val,
end = p + SVN__MAX_ENCODED_UINT_LEN;
/* Decode bytes until we're done. */
- while SVN__PREDICT_TRUE(p < end)
+ while (SVN__PREDICT_TRUE(p < end))
{
unsigned int c = *p++;
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/io.c Mon Jul 22 11:22:18 2013
@@ -1166,9 +1166,11 @@ svn_io_make_dir_recursively(const char *
return SVN_NO_ERROR;
}
-svn_error_t *svn_io_file_create(const char *file,
- const char *contents,
- apr_pool_t *pool)
+svn_error_t *
+svn_io_file_create_binary(const char *file,
+ const char *contents,
+ apr_size_t length,
+ apr_pool_t *pool)
{
apr_file_t *f;
apr_size_t written;
@@ -1178,25 +1180,57 @@ svn_error_t *svn_io_file_create(const ch
(APR_WRITE | APR_CREATE | APR_EXCL),
APR_OS_DEFAULT,
pool));
- if (contents && *contents)
- err = svn_io_file_write_full(f, contents, strlen(contents),
- &written, pool);
+ if (length)
+ err = svn_io_file_write_full(f, contents, length, &written, pool);
+ err = svn_error_compose_create(
+ err,
+ svn_io_file_close(f, pool));
- return svn_error_trace(
- svn_error_compose_create(err,
- svn_io_file_close(f, pool)));
+ if (err)
+ {
+ /* Our caller doesn't know if we left a file or not if we return
+ an error. Better to cleanup after ourselves if we created the
+ file. */
+ return svn_error_trace(
+ svn_error_compose_create(
+ err,
+ svn_io_remove_file2(file, TRUE, pool)));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_io_file_create(const char *file,
+ const char *contents,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_io_file_create_binary(file, contents,
+ contents
+ ? strlen(contents)
+ : 0,
+ pool));
+}
+
+svn_error_t *
+svn_io_file_create_empty(const char *file,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_io_file_create_binary(file, "", 0, pool));
}
-svn_error_t *svn_io_dir_file_copy(const char *src_path,
- const char *dest_path,
- const char *file,
- apr_pool_t *pool)
+svn_error_t *
+svn_io_dir_file_copy(const char *src_path,
+ const char *dest_path,
+ const char *file,
+ apr_pool_t *pool)
{
const char *file_dest_path = svn_dirent_join(dest_path, file, pool);
const char *file_src_path = svn_dirent_join(src_path, file, pool);
- return svn_io_copy_file(file_src_path, file_dest_path, TRUE, pool);
+ return svn_error_trace(
+ svn_io_copy_file(file_src_path, file_dest_path, TRUE, pool));
}
@@ -2300,36 +2334,35 @@ stringbuf_from_aprfile(svn_stringbuf_t *
svn_error_t *err;
svn_stringbuf_t *res = NULL;
apr_size_t res_initial_len = SVN__STREAM_CHUNK_SIZE;
- char *buf = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE);
+ char *buf;
/* If our caller wants us to check the size of the file for
efficient memory handling, we'll try to do so. */
if (check_size)
{
- apr_status_t status;
-
- /* If our caller didn't tell us the file's name, we'll ask APR
- if it knows the name. No problem if we can't figure it out. */
- if (! filename)
- {
- const char *filename_apr;
- if (! (status = apr_file_name_get(&filename_apr, file)))
- filename = filename_apr;
- }
+ apr_finfo_t finfo;
- /* If we now know the filename, try to stat(). If we succeed,
- we know how to allocate our stringbuf. */
- if (filename)
- {
- apr_finfo_t finfo;
- if (! (status = apr_stat(&finfo, filename, APR_FINFO_MIN, pool)))
- res_initial_len = (apr_size_t)finfo.size;
+ /* In some cases we get size 0 and no error for non files,
+ so we also check for the name. (= cached in apr_file_t) */
+ if (! apr_file_info_get(&finfo, APR_FINFO_SIZE | APR_FINFO_NAME, file)
+ && finfo.name != NULL)
+ {
+ /* we've got the file length. Now, read it in one go. */
+ svn_boolean_t eof;
+ res_initial_len = (apr_size_t)finfo.size;
+ res = svn_stringbuf_create_ensure(res_initial_len, pool);
+ SVN_ERR(svn_io_file_read_full2(file, res->data,
+ res_initial_len, &res->len,
+ &eof, pool));
+ res->data[res->len] = 0;
+
+ *result = res;
+ return SVN_NO_ERROR;
}
}
-
/* XXX: We should check the incoming data for being of type binary. */
-
+ buf = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE);
res = svn_stringbuf_create_ensure(res_initial_len, pool);
/* apr_file_read will not return data and eof in the same call. So this loop
@@ -2345,7 +2378,7 @@ stringbuf_from_aprfile(svn_stringbuf_t *
/* Having read all the data we *expect* EOF */
if (err && !APR_STATUS_IS_EOF(err->apr_err))
- return err;
+ return svn_error_trace(err);
svn_error_clear(err);
*result = res;
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/string.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/string.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/string.c Mon Jul 22 11:22:18 2013
@@ -1207,6 +1207,86 @@ svn__i64toa_sep(apr_int64_t number, char
return apr_pstrdup(pool, buffer);
}
+apr_size_t
+svn__ui64tobase36(char *dest, apr_uint64_t value)
+{
+ char *dest_start = dest;
+ if (value < 10)
+ {
+ /* pretty frequent and trivial case. Make it fast. */
+ *(dest++) = (char)(value) + '0';
+ }
+ else
+ {
+ char buffer[SVN_INT64_BUFFER_SIZE];
+ char *p = buffer;
+
+ /* write result as little-endian to buffer */
+ while (value > 0)
+ {
+ char c = (char)(value % 36);
+ value /= 36;
+
+ *p = (c <= 9) ? (c + '0') : (c - 10 + 'a');
+ ++p;
+ }
+
+ /* copy as big-endian to DEST */
+ while (p > buffer)
+ *(dest++) = *(--p);
+ }
+
+ *dest = '\0';
+ return dest - dest_start;
+}
+
+apr_uint64_t
+svn__base36toui64(const char **next, const char *source)
+{
+ apr_uint64_t result = 0;
+ apr_uint64_t factor = 1;
+ int i = 0;
+ char digits[SVN_INT64_BUFFER_SIZE];
+
+ /* convert digits to numerical values and count the number of places.
+ * Also, prevent buffer overflow. */
+ while (i < sizeof(digits))
+ {
+ char c = *source;
+ if (c < 'a')
+ {
+ /* includes detection of NUL terminator */
+ if (c < '0' || c > '9')
+ break;
+
+ c -= '0';
+ }
+ else
+ {
+ if (c < 'a' || c > 'z')
+ break;
+
+ c -= 'a' - 10;
+ }
+
+ digits[i++] = c;
+ source++;
+ }
+
+ /* fold digits into the result */
+ while (i > 0)
+ {
+ result += factor * (apr_uint64_t)digits[--i];
+ factor *= 36;
+ }
+
+ if (next)
+ *next = source;
+
+ return result;
+}
+
+
unsigned int
svn_cstring__similarity(const char *stra, const char *strb,
svn_membuf_t *buffer, apr_size_t *rlcs)
@@ -1312,3 +1392,67 @@ svn_string__similarity(const svn_string_
else
return 1000;
}
+
+apr_size_t
+svn_cstring__match_length(const char *a,
+ const char *b,
+ apr_size_t max_len)
+{
+ apr_size_t pos = 0;
+
+#if SVN_UNALIGNED_ACCESS_IS_OK
+
+ /* Chunky processing is so much faster ...
+ *
+ * We can't make this work on architectures that require aligned access
+ * because A and B will probably have different alignment. So, skipping
+ * the first few chars until alignment is reached is not an option.
+ */
+ for (; pos + sizeof(apr_size_t) <= max_len; pos += sizeof(apr_size_t))
+ if (*(const apr_size_t*)(a + pos) != *(const apr_size_t*)(b + pos))
+ break;
+
+#endif
+
+ for (; pos < max_len; ++pos)
+ if (a[pos] != b[pos])
+ break;
+
+ return pos;
+}
+
+apr_size_t
+svn_cstring__reverse_match_length(const char *a,
+ const char *b,
+ apr_size_t max_len)
+{
+ apr_size_t pos = 0;
+
+#if SVN_UNALIGNED_ACCESS_IS_OK
+
+ /* Chunky processing is so much faster ...
+ *
+ * We can't make this work on architectures that require aligned access
+ * because A and B will probably have different alignment. So, skipping
+ * the first few chars until alignment is reached is not an option.
+ */
+ for (pos = sizeof(apr_size_t); pos <= max_len; pos += sizeof(apr_size_t))
+ if (*(const apr_size_t*)(a - pos) != *(const apr_size_t*)(b - pos))
+ break;
+
+ pos -= sizeof(apr_size_t);
+
+#endif
+
+ /* If we find a mismatch at -pos, pos-1 characters matched.
+ */
+ while (++pos <= max_len)
+ if (a[0-pos] != b[0-pos])
+ return pos - 1;
+
+ /* No mismatch found -> at least MAX_LEN matching chars.
+ */
+ return max_len;
+}
+
+
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/subst.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/subst.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/subst.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/subst.c Mon Jul 22 11:22:18 2013
@@ -1960,7 +1960,11 @@ svn_subst_translate_string2(svn_string_t
return SVN_NO_ERROR;
}
- if (encoding)
+ if (encoding && !strcmp(encoding, "UTF-8"))
+ {
+ val_utf8 = value->data;
+ }
+ else if (encoding)
{
SVN_ERR(svn_utf_cstring_to_utf8_ex2(&val_utf8, value->data,
encoding, scratch_pool));
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/temp_serializer.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/temp_serializer.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/temp_serializer.c Mon Jul 22 11:22:18 2013
@@ -279,6 +279,26 @@ svn_temp_serializer__pop(svn_temp_serial
context->recycler = old;
}
+void
+svn_temp_serializer__add_leaf(svn_temp_serializer__context_t *context,
+ const void * const * source_struct,
+ apr_size_t struct_size)
+{
+ const void *source = *source_struct;
+
+ /* the serialized structure must be properly aligned */
+ if (source)
+ align_buffer_end(context);
+
+ /* Store the offset at which the struct data that will the appended.
+ * Write 0 for NULL pointers. */
+ store_current_end_pointer(context, source_struct);
+
+ /* finally, actually append the struct contents */
+ if (*source_struct)
+ svn_stringbuf_appendbytes(context->buffer, source, struct_size);
+}
+
/* Serialize a string referenced from the current structure within the
* serialization CONTEXT. S must be a reference to the char* pointer in
* the original structure so that the correspondence in the serialized
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/utf.c Mon Jul 22 11:22:18 2013
@@ -212,6 +212,7 @@ xlate_alloc_handle(xlate_handle_node_t *
{
apr_status_t apr_err;
apr_xlate_t *handle;
+ const char *name;
/* The error handling doesn't support the following cases, since we don't
use them currently. Catch this here. */
@@ -224,8 +225,10 @@ xlate_alloc_handle(xlate_handle_node_t *
#if defined(WIN32)
apr_err = svn_subr__win32_xlate_open((win32_xlate_t **)&handle, topage,
frompage, pool);
+ name = "win32-xlate: ";
#else
apr_err = apr_xlate_open(&handle, topage, frompage, pool);
+ name = "APR: ";
#endif
if (APR_STATUS_IS_EINVAL(apr_err) || APR_STATUS_IS_ENOTIMPL(apr_err))
@@ -233,6 +236,8 @@ xlate_alloc_handle(xlate_handle_node_t *
else if (apr_err != APR_SUCCESS)
{
const char *errstr;
+ char apr_strerr[512];
+
/* Can't use svn_error_wrap_apr here because it calls functions in
this file, leading to infinite recursion. */
if (frompage == SVN_APR_LOCALE_CHARSET)
@@ -248,7 +253,13 @@ xlate_alloc_handle(xlate_handle_node_t *
_("Can't create a character converter from "
"'%s' to '%s'"), frompage, topage);
- return svn_error_create(apr_err, NULL, errstr);
+ /* Just put the error on the stack, since svn_error_create duplicates it
+ later. APR_STRERR will be in the local encoding, not in UTF-8, though.
+ */
+ svn_strerror(apr_err, apr_strerr, sizeof(apr_strerr));
+ return svn_error_createf(SVN_ERR_PLUGIN_LOAD_FAILURE,
+ svn_error_create(apr_err, NULL, apr_strerr),
+ "%s%s", name, errstr);
}
/* Allocate and initialize the node. */
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_subr/win32_xlate.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_subr/win32_xlate.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_subr/win32_xlate.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_subr/win32_xlate.c Mon Jul 22 11:22:18 2013
@@ -118,11 +118,11 @@ get_page_id_from_name(UINT *page_id_p, c
}
err = svn_atomic__init_once(&com_initialized, initialize_com, NULL, pool);
-
if (err)
{
+ apr_status_t saved = err->apr_err;
svn_error_clear(err);
- return APR_EGENERAL;
+ return saved; /* probably SVN_ERR_ATOMIC_INIT_FAILURE */
}
hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_wc/diff_editor.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_wc/diff_editor.c Mon Jul 22 11:22:18 2013
@@ -474,14 +474,18 @@ svn_wc__diff_base_working_diff(svn_wc__d
{
const svn_io_dirent2_t *dirent;
+ /* Verify truename to mimic status for iota/IOTA difference on Windows */
SVN_ERR(svn_io_stat_dirent2(&dirent, local_abspath,
- FALSE /* verify truename */,
+ TRUE /* verify truename */,
TRUE /* ingore_enoent */,
scratch_pool, scratch_pool));
- if (dirent->kind == svn_node_file
- && dirent->filesize == recorded_size
- && dirent->mtime == recorded_time)
+ /* If a file does not exist on disk (missing/obstructed) then we
+ can't provide a text diff */
+ if (dirent->kind != svn_node_file
+ || (dirent->kind == svn_node_file
+ && dirent->filesize == recorded_size
+ && dirent->mtime == recorded_time))
{
files_same = TRUE;
}
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_wc/diff_local.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_wc/diff_local.c Mon Jul 22 11:22:18 2013
@@ -195,23 +195,15 @@ diff_status_callback(void *baton,
struct diff_baton *eb = baton;
svn_wc__db_t *db = eb->db;
- switch (status->node_status)
- {
- case svn_wc_status_unversioned:
- case svn_wc_status_ignored:
- return SVN_NO_ERROR; /* No diff */
-
- case svn_wc_status_conflicted:
- if (status->text_status == svn_wc_status_none
- && status->prop_status == svn_wc_status_none)
- {
- /* Node is an actual only node describing a tree conflict */
- return SVN_NO_ERROR;
- }
- break;
+ if (! status->versioned)
+ return SVN_NO_ERROR; /* unversioned (includes dir externals) */
- default:
- break; /* Go check other conditions */
+ if (status->node_status == svn_wc_status_conflicted
+ && status->text_status == svn_wc_status_none
+ && status->prop_status == svn_wc_status_none)
+ {
+ /* Node is an actual only node describing a tree conflict */
+ return SVN_NO_ERROR;
}
/* Not text/prop modified, not copied. Easy out */
Modified: subversion/branches/fsfs-improvements/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_wc/wc_db.h?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_wc/wc_db.h Mon Jul 22 11:22:18 2013
@@ -2124,7 +2124,7 @@ svn_wc__db_read_pristine_props(apr_hash_
* paths relative to the repository root URL for cached inherited
* properties and absolute working copy paths otherwise.
*
- * If ACTUAL_PROPS is not NULL, then set *ACTUAL_PROPS to the actual
+ * If ACTUAL_PROPS is not NULL, then set *ACTUAL_PROPS to ALL the actual
* properties stored on LOCAL_ABSPATH.
*
* Allocate @a *iprops in @a result_pool. Use @a scratch_pool
Modified: subversion/branches/fsfs-improvements/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/mod_dav_svn/repos.c?rev=1505660&r1=1505659&r2=1505660&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/fsfs-improvements/subversion/mod_dav_svn/repos.c Mon Jul 22 11:22:18 2013
@@ -2408,21 +2408,12 @@ get_parent_path(const char *path,
svn_boolean_t is_urlpath,
apr_pool_t *pool)
{
- apr_size_t len;
- char *tmp = apr_pstrdup(pool, path);
-
- len = strlen(tmp);
-
- if (len > 0)
+ if (*path != '\0') /* not an empty string */
{
- /* Remove any trailing slash; else svn_path_dirname() asserts. */
- if (tmp[len-1] == '/')
- tmp[len-1] = '\0';
-
if (is_urlpath)
- return svn_urlpath__dirname(tmp, pool);
+ return svn_urlpath__dirname(path, pool);
else
- return svn_fspath__dirname(tmp, pool);
+ return svn_fspath__dirname(path, pool);
}
return path;
@@ -2458,7 +2449,9 @@ get_parent_resource(const dav_resource *
parent->versioned = 1;
parent->hooks = resource->hooks;
parent->pool = resource->pool;
- parent->uri = get_parent_path(resource->uri, TRUE, resource->pool);
+ parent->uri = get_parent_path(svn_urlpath__canonicalize(resource->uri,
+ resource->pool),
+ TRUE, resource->pool);
parent->info = parentinfo;
parentinfo->uri_path =