You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by iv...@apache.org on 2015/02/09 12:23:43 UTC
svn commit: r1658362 [21/34] - in
/subversion/branches/remove-log-addressing: ./ build/ build/generator/
build/generator/templates/ notes/ subversion/bindings/cxxhl/include/svncxxhl/
subversion/bindings/javahl/native/ subversion/bindings/javahl/native/...
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_repos/dump.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_repos/dump.c Mon Feb 9 11:23:39 2015
@@ -38,6 +38,7 @@
#include "svn_props.h"
#include "svn_sorts.h"
+#include "private/svn_repos_private.h"
#include "private/svn_mergeinfo_private.h"
#include "private/svn_fs_private.h"
#include "private/svn_sorts_private.h"
@@ -356,6 +357,7 @@ store_delta(apr_file_t **tempfile, svn_f
with message WARNING_FMT formatted with the remaining variable arguments.
Send it by calling NOTIFY_FUNC (if not null) with NOTIFY_BATON.
*/
+__attribute__((format(printf, 5, 6)))
static void
notify_warning(apr_pool_t *scratch_pool,
svn_repos_notify_func_t notify_func,
@@ -382,6 +384,231 @@ notify_warning(apr_pool_t *scratch_pool,
/*----------------------------------------------------------------------*/
+/* Write to STREAM the header in HEADERS named KEY, if present.
+ */
+static svn_error_t *
+write_header(svn_stream_t *stream,
+ apr_hash_t *headers,
+ const char *key,
+ apr_pool_t *scratch_pool)
+{
+ const char *val = svn_hash_gets(headers, key);
+
+ if (val)
+ {
+ SVN_ERR(svn_stream_printf(stream, scratch_pool,
+ "%s: %s\n", key, val));
+ }
+ return SVN_NO_ERROR;
+}
+
+/* Write headers, in arbitrary order.
+ * ### TODO: use a stable order
+ * ### Modifies HEADERS.
+ */
+static svn_error_t *
+write_revision_headers(svn_stream_t *stream,
+ apr_hash_t *headers,
+ apr_pool_t *scratch_pool)
+{
+ const char **h;
+ apr_hash_index_t *hi;
+
+ static const char *revision_headers_order[] =
+ {
+ SVN_REPOS_DUMPFILE_REVISION_NUMBER, /* must be first */
+ NULL
+ };
+
+ /* Write some headers in a given order */
+ for (h = revision_headers_order; *h; h++)
+ {
+ SVN_ERR(write_header(stream, headers, *h, scratch_pool));
+ svn_hash_sets(headers, *h, NULL);
+ }
+
+ /* Write any and all remaining headers except Content-length.
+ * ### TODO: use a stable order
+ */
+ for (hi = apr_hash_first(scratch_pool, headers); hi; hi = apr_hash_next(hi))
+ {
+ const char *key = apr_hash_this_key(hi);
+
+ if (strcmp(key, SVN_REPOS_DUMPFILE_CONTENT_LENGTH) != 0)
+ SVN_ERR(write_header(stream, headers, key, scratch_pool));
+ }
+
+ /* Content-length must be last */
+ SVN_ERR(write_header(stream, headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+apr_array_header_t *
+svn_repos__dumpfile_headers_create(apr_pool_t *pool)
+{
+ apr_array_header_t *headers
+ = apr_array_make(pool, 5, sizeof(svn_repos__dumpfile_header_entry_t));
+
+ return headers;
+}
+
+void
+svn_repos__dumpfile_header_push(apr_array_header_t *headers,
+ const char *key,
+ const char *val)
+{
+ svn_repos__dumpfile_header_entry_t *h
+ = &APR_ARRAY_PUSH(headers, svn_repos__dumpfile_header_entry_t);
+
+ h->key = apr_pstrdup(headers->pool, key);
+ h->val = apr_pstrdup(headers->pool, val);
+}
+
+void
+svn_repos__dumpfile_header_pushf(apr_array_header_t *headers,
+ const char *key,
+ const char *val_fmt,
+ ...)
+{
+ va_list ap;
+ svn_repos__dumpfile_header_entry_t *h
+ = &APR_ARRAY_PUSH(headers, svn_repos__dumpfile_header_entry_t);
+
+ h->key = apr_pstrdup(headers->pool, key);
+ va_start(ap, val_fmt);
+ h->val = apr_pvsprintf(headers->pool, val_fmt, ap);
+ va_end(ap);
+}
+
+svn_error_t *
+svn_repos__dump_headers(svn_stream_t *stream,
+ apr_array_header_t *headers,
+ svn_boolean_t terminate,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+
+ for (i = 0; i < headers->nelts; i++)
+ {
+ svn_repos__dumpfile_header_entry_t *h
+ = &APR_ARRAY_IDX(headers, i, svn_repos__dumpfile_header_entry_t);
+
+ SVN_ERR(svn_stream_printf(stream, scratch_pool,
+ "%s: %s\n", h->key, h->val));
+ }
+
+ /* End of headers */
+ if (terminate)
+ SVN_ERR(svn_stream_puts(stream, "\n"));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_repos__dump_revision_record(svn_stream_t *dump_stream,
+ svn_revnum_t revision,
+ apr_hash_t *extra_headers,
+ apr_hash_t *revprops,
+ svn_boolean_t props_section_always,
+ apr_pool_t *scratch_pool)
+{
+ svn_stringbuf_t *propstring = NULL;
+ apr_hash_t *headers;
+
+ if (extra_headers)
+ headers = apr_hash_copy(scratch_pool, extra_headers);
+ else
+ headers = apr_hash_make(scratch_pool);
+
+ /* ### someday write a revision-content-checksum */
+
+ svn_hash_sets(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER,
+ apr_psprintf(scratch_pool, "%ld", revision));
+
+ if (apr_hash_count(revprops) || props_section_always)
+ {
+ svn_stream_t *propstream;
+
+ propstring = svn_stringbuf_create_empty(scratch_pool);
+ propstream = svn_stream_from_stringbuf(propstring, scratch_pool);
+ SVN_ERR(svn_hash_write2(revprops, propstream, "PROPS-END", scratch_pool));
+ SVN_ERR(svn_stream_close(propstream));
+
+ svn_hash_sets(headers, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH,
+ apr_psprintf(scratch_pool,
+ "%" APR_SIZE_T_FMT, propstring->len));
+ }
+
+ /* Write out a regular Content-length header for the benefit of
+ non-Subversion RFC-822 parsers. */
+ svn_hash_sets(headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+ apr_psprintf(scratch_pool,
+ "%" APR_SIZE_T_FMT, propstring->len));
+ SVN_ERR(write_revision_headers(dump_stream, headers, scratch_pool));
+
+ /* End of headers */
+ SVN_ERR(svn_stream_puts(dump_stream, "\n"));
+
+ /* Property data. */
+ if (propstring)
+ {
+ SVN_ERR(svn_stream_write(dump_stream, propstring->data, &propstring->len));
+ }
+
+ /* put an end to revision */
+ SVN_ERR(svn_stream_puts(dump_stream, "\n"));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_repos__dump_node_record(svn_stream_t *dump_stream,
+ apr_array_header_t *headers,
+ svn_stringbuf_t *props_str,
+ svn_boolean_t has_text,
+ svn_filesize_t text_content_length,
+ svn_boolean_t content_length_always,
+ apr_pool_t *scratch_pool)
+{
+ svn_filesize_t content_length = 0;
+
+ /* add content-length headers */
+ if (props_str)
+ {
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH,
+ "%" APR_SIZE_T_FMT, props_str->len);
+ content_length += props_str->len;
+ }
+ if (has_text)
+ {
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH,
+ "%" SVN_FILESIZE_T_FMT, text_content_length);
+ content_length += text_content_length;
+ }
+ if (content_length_always || props_str || has_text)
+ {
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_CONTENT_LENGTH,
+ "%" SVN_FILESIZE_T_FMT, content_length);
+ }
+
+ /* write the headers */
+ SVN_ERR(svn_repos__dump_headers(dump_stream, headers, TRUE, scratch_pool));
+
+ /* write the props */
+ if (props_str)
+ {
+ SVN_ERR(svn_stream_write(dump_stream, props_str->data, &props_str->len));
+ }
+ return SVN_NO_ERROR;
+}
+
+/*----------------------------------------------------------------------*/
+
/** An editor which dumps node-data in 'dumpfile format' to a file. **/
/* Look, mom! No file batons! */
@@ -426,10 +653,6 @@ struct edit_baton
revisions older than OLDEST_DUMPED_REV. */
svn_boolean_t *found_old_mergeinfo;
- /* reusable buffer for writing file contents */
- char buffer[SVN__STREAM_CHUNK_SIZE];
- apr_size_t bufsize;
-
/* Structure allows us to verify the paths currently being dumped.
If NULL, validity checks are being skipped. */
path_tracker_t *path_tracker;
@@ -438,10 +661,6 @@ struct edit_baton
struct dir_baton
{
struct edit_baton *edit_baton;
- struct dir_baton *parent_dir_baton;
-
- /* is this directory a new addition to this revision? */
- svn_boolean_t added;
/* has this directory been written to the output stream? */
svn_boolean_t written_out;
@@ -481,21 +700,19 @@ struct dir_baton
path, SVN_INVALID_REVNUM for the rev), just compare this directory
PATH against itself in the previous revision.
- PARENT_DIR_BATON is the directory baton of this directory's parent,
- or NULL if this is the top-level directory of the edit. ADDED
- indicated if this directory is newly added in this revision.
+ PB is the directory baton of this directory's parent,
+ or NULL if this is the top-level directory of the edit.
+
Perform all allocations in POOL. */
static struct dir_baton *
make_dir_baton(const char *path,
const char *cmp_path,
svn_revnum_t cmp_rev,
void *edit_baton,
- void *parent_dir_baton,
- svn_boolean_t added,
+ struct dir_baton *pb,
apr_pool_t *pool)
{
struct edit_baton *eb = edit_baton;
- struct dir_baton *pb = parent_dir_baton;
struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
const char *full_path;
@@ -513,11 +730,9 @@ make_dir_baton(const char *path,
cmp_path = svn_relpath_canonicalize(cmp_path, pool);
new_db->edit_baton = eb;
- new_db->parent_dir_baton = pb;
new_db->path = full_path;
new_db->cmp_path = cmp_path;
new_db->cmp_rev = cmp_rev;
- new_db->added = added;
new_db->written_out = FALSE;
new_db->deleted_entries = apr_hash_make(pool);
new_db->check_name_collision = FALSE;
@@ -693,7 +908,6 @@ extract_mergeinfo_paths(void *baton, con
struct filter_mergeinfo_paths_baton
{
apr_hash_t *paths;
- svn_membuf_t buffer;
};
/* Compare two sets of denormalized paths from mergeinfo entries,
@@ -800,7 +1014,6 @@ check_mergeinfo_normalization(const char
normalized_paths = extract_baton.result;
filter_baton.paths = added_paths;
- filter_baton.buffer = extract_baton.buffer;
SVN_ERR(svn_iter_apr_hash(NULL, oldinfo,
filter_mergeinfo_paths,
&filter_baton, pool));
@@ -821,12 +1034,40 @@ check_mergeinfo_normalization(const char
}
+/* A special case of dump_node(), for a delete record.
+ *
+ * The only thing special about this version is it only writes one blank
+ * line, not two, after the headers. Why? Historical precedent for the
+ * case where a delete record is used as part of a (delete + add-with-history)
+ * in implementing a replacement.
+ *
+ * Also it doesn't do a path-tracker check.
+ */
+static svn_error_t *
+dump_node_delete(svn_stream_t *stream,
+ const char *node_relpath,
+ apr_pool_t *pool)
+{
+ apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool);
+
+ /* Node-path: ... */
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_PATH, node_relpath);
+
+ /* Node-action: delete */
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete");
+
+ SVN_ERR(svn_repos__dump_headers(stream, headers, TRUE, pool));
+ return SVN_NO_ERROR;
+}
+
/* This helper is the main "meat" of the editor -- it does all the
work of writing a node record.
Write out a node record for PATH of type KIND under EB->FS_ROOT.
ACTION describes what is happening to the node (see enum svn_node_action).
- Write record to writable EB->STREAM, using EB->BUFFER to write in chunks.
+ Write record to writable EB->STREAM.
If the node was itself copied, IS_COPY is TRUE and the
path/revision of the copy source are in CMP_PATH/CMP_REV. If
@@ -844,13 +1085,14 @@ dump_node(struct edit_baton *eb,
apr_pool_t *pool)
{
svn_stringbuf_t *propstring;
- svn_filesize_t content_length = 0;
apr_size_t len;
svn_boolean_t must_dump_text = FALSE, must_dump_props = FALSE;
const char *compare_path = path;
svn_revnum_t compare_rev = eb->current_rev - 1;
svn_fs_root_t *compare_root = NULL;
apr_file_t *delta_file = NULL;
+ apr_array_header_t *headers = svn_repos__dumpfile_headers_create(pool);
+ svn_filesize_t textlen;
/* Maybe validate the path. */
if (eb->verify || eb->notify_func)
@@ -879,15 +1121,14 @@ dump_node(struct edit_baton *eb,
}
/* Write out metadata headers for this file node. */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n",
- path));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_PATH, path);
if (kind == svn_node_file)
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_KIND ": file\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_KIND, "file");
else if (kind == svn_node_dir)
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_KIND, "dir");
/* Remove leading slashes from copyfrom paths. */
if (cmp_path)
@@ -900,15 +1141,16 @@ dump_node(struct edit_baton *eb,
compare_rev = cmp_rev;
}
- if (action == svn_node_action_change)
+ switch (action)
{
+ case svn_node_action_change:
if (eb->path_tracker)
SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
apr_psprintf(pool, _("Change invalid path '%s' in r%ld"),
path, eb->current_rev));
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "change");
/* either the text or props changed, or possibly both. */
SVN_ERR(svn_fs_revision_root(&compare_root,
@@ -922,9 +1164,27 @@ dump_node(struct edit_baton *eb,
SVN_ERR(svn_fs_contents_different(&must_dump_text,
compare_root, compare_path,
eb->fs_root, path, pool));
- }
- else if (action == svn_node_action_replace)
- {
+ break;
+
+ case svn_node_action_delete:
+ if (eb->path_tracker)
+ {
+ SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
+ apr_psprintf(pool, _("Deleting invalid path '%s' in r%ld"),
+ path, eb->current_rev));
+ tracker_path_delete(eb->path_tracker, path);
+ }
+
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete");
+
+ /* we can leave this routine quietly now, don't need to dump
+ any content. */
+ must_dump_text = FALSE;
+ must_dump_props = FALSE;
+ break;
+
+ case svn_node_action_replace:
if (eb->path_tracker)
SVN_ERR_W(node_must_exist(eb, path, eb->current_rev,
svn_node_unknown, pool),
@@ -938,77 +1198,43 @@ dump_node(struct edit_baton *eb,
tracker_path_replace(eb->path_tracker, path);
/* a simple delete+add, implied by a single 'replace' action. */
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION
- ": replace\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "replace");
/* definitely need to dump all content for a replace. */
if (kind == svn_node_file)
must_dump_text = TRUE;
must_dump_props = TRUE;
+ break;
}
else
{
+ /* more complex: delete original, then add-with-history. */
+ /* ### Why not write a 'replace' record? Don't know. */
+
if (eb->path_tracker)
{
- SVN_ERR_W(node_must_exist(eb, compare_path, compare_rev,
- kind, pool),
- apr_psprintf(pool,
- _("Replacing path '%s' in r%ld "
- "with invalid path"),
- path, eb->current_rev));
-
- /* we will call dump_node again with an addition further
- down the road */
tracker_path_delete(eb->path_tracker, path);
}
- /* more complex: delete original, then add-with-history. */
+ /* ### Unusually, we end this 'delete' node record with only a single
+ blank line after the header block -- no extra blank line. */
+ SVN_ERR(dump_node_delete(eb->stream, path, pool));
- /* the path & kind headers have already been printed; just
- add a delete action, and end the current record.*/
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION
- ": delete\n\n"));
-
- /* recurse: print an additional add-with-history record. */
- SVN_ERR(dump_node(eb, path, kind, svn_node_action_add,
- is_copy, compare_path, compare_rev, pool));
-
- /* we can leave this routine quietly now, don't need to dump
- any content; that was already done in the second record. */
- must_dump_text = FALSE;
- must_dump_props = FALSE;
+ /* The remaining action is a non-replacing add-with-history */
+ /* action = svn_node_action_add; */
}
- }
- else if (action == svn_node_action_delete)
- {
- if (eb->path_tracker)
- {
- SVN_ERR_W(node_must_exist(eb, path, eb->current_rev, kind, pool),
- apr_psprintf(pool, _("Deleting invalid path '%s' in r%ld"),
- path, eb->current_rev));
- tracker_path_delete(eb->path_tracker, path);
- }
-
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n"));
+ /* FALL THROUGH to 'add' */
- /* we can leave this routine quietly now, don't need to dump
- any content. */
- must_dump_text = FALSE;
- must_dump_props = FALSE;
- }
- else if (action == svn_node_action_add)
- {
+ case svn_node_action_add:
if (eb->path_tracker)
SVN_ERR_W(node_must_not_exist(eb, path, eb->current_rev, pool),
apr_psprintf(pool,
_("Adding already existing path '%s' in r%ld"),
path, eb->current_rev));
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "add");
if (! is_copy)
{
@@ -1049,12 +1275,10 @@ dump_node(struct edit_baton *eb,
*eb->found_old_reference = TRUE;
}
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV
- ": %ld\n"
- SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH
- ": %s\n",
- cmp_rev, cmp_path));
+ svn_repos__dumpfile_header_pushf(
+ headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV, "%ld", cmp_rev);
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH, cmp_path);
SVN_ERR(svn_fs_revision_root(&compare_root,
svn_fs_root_fs(eb->fs_root),
@@ -1078,20 +1302,19 @@ dump_node(struct edit_baton *eb,
FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_MD5
- ": %s\n", hex_digest));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_MD5, hex_digest);
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
compare_root, compare_path,
FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_SHA1
- ": %s\n", hex_digest));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_SHA1, hex_digest);
}
}
+ break;
}
if ((! must_dump_text) && (! must_dump_props))
@@ -1101,8 +1324,9 @@ dump_node(struct edit_baton *eb,
then our dumpstream format demands that at a *minimum*, we
see a lone "PROPS-END" as a divider between text and props
content within the content-block. */
- len = 2;
- return svn_stream_write(eb->stream, "\n\n", &len); /* ### needed? */
+ SVN_ERR(svn_repos__dump_headers(eb->stream, headers, TRUE, pool));
+ len = 1;
+ return svn_stream_write(eb->stream, "\n", &len); /* ### needed? */
}
/*** Start prepping content to dump... ***/
@@ -1113,7 +1337,6 @@ dump_node(struct edit_baton *eb,
if (must_dump_props)
{
apr_hash_t *prophash, *oldhash = NULL;
- apr_size_t proplen;
svn_stream_t *propstream;
SVN_ERR(svn_fs_node_proplist(&prophash, eb->fs_root, path, pool));
@@ -1171,8 +1394,8 @@ dump_node(struct edit_baton *eb,
if (!oldhash) /* May have been set for normalization check */
SVN_ERR(svn_fs_node_proplist(&oldhash, compare_root, compare_path,
pool));
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_PROP_DELTA ": true\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_PROP_DELTA, "true");
}
else
oldhash = apr_hash_make(pool);
@@ -1181,11 +1404,6 @@ dump_node(struct edit_baton *eb,
SVN_ERR(svn_hash_write_incremental(prophash, oldhash, propstream,
"PROPS-END", pool));
SVN_ERR(svn_stream_close(propstream));
- proplen = propstring->len;
- content_length += proplen;
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n", proplen));
}
/* If we are supposed to dump text, write out a text length header
@@ -1194,7 +1412,6 @@ dump_node(struct edit_baton *eb,
{
svn_checksum_t *checksum;
const char *hex_digest;
- svn_filesize_t textlen;
if (eb->use_deltas)
{
@@ -1203,8 +1420,8 @@ dump_node(struct edit_baton *eb,
saying our text contents are a delta. */
SVN_ERR(store_delta(&delta_file, &textlen, compare_root,
compare_path, eb->fs_root, path, pool));
- SVN_ERR(svn_stream_puts(eb->stream,
- SVN_REPOS_DUMPFILE_TEXT_DELTA ": true\n"));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_DELTA, "true");
if (compare_root)
{
@@ -1213,18 +1430,16 @@ dump_node(struct edit_baton *eb,
FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5
- ": %s\n", hex_digest));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5, hex_digest);
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
compare_root, compare_path,
FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_SHA1
- ": %s\n", hex_digest));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_SHA1, hex_digest);
}
}
else
@@ -1233,42 +1448,30 @@ dump_node(struct edit_baton *eb,
SVN_ERR(svn_fs_file_length(&textlen, eb->fs_root, path, pool));
}
- content_length += textlen;
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH
- ": %" SVN_FILESIZE_T_FMT "\n", textlen));
-
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
eb->fs_root, path, FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5
- ": %s\n", hex_digest));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5, hex_digest);
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1,
eb->fs_root, path, FALSE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
if (hex_digest)
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_TEXT_CONTENT_SHA1
- ": %s\n", hex_digest));
+ svn_repos__dumpfile_header_push(
+ headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_SHA1, hex_digest);
}
/* 'Content-length:' is the last header before we dump the content,
and is the sum of the text and prop contents lengths. We write
this only for the benefit of non-Subversion RFC-822 parsers. */
- SVN_ERR(svn_stream_printf(eb->stream, pool,
- SVN_REPOS_DUMPFILE_CONTENT_LENGTH
- ": %" SVN_FILESIZE_T_FMT "\n\n",
- content_length));
-
- /* Dump property content if we're supposed to do so. */
- if (must_dump_props)
- {
- len = propstring->len;
- SVN_ERR(svn_stream_write(eb->stream, propstring->data, &len));
- }
+ SVN_ERR(svn_repos__dump_node_record(eb->stream, headers,
+ must_dump_props ? propstring : NULL,
+ must_dump_text,
+ must_dump_text ? textlen : 0,
+ TRUE /*content_length_always*/,
+ pool));
/* Dump text content */
if (must_dump_text && (kind == svn_node_file))
@@ -1300,7 +1503,7 @@ open_root(void *edit_baton,
void **root_baton)
{
*root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, FALSE, pool);
+ edit_baton, NULL, pool);
return SVN_NO_ERROR;
}
@@ -1331,13 +1534,13 @@ add_directory(const char *path,
{
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
- void *val;
+ void *was_deleted;
svn_boolean_t is_copy = FALSE;
struct dir_baton *new_db
- = make_dir_baton(path, copyfrom_path, copyfrom_rev, eb, pb, TRUE, pool);
+ = make_dir_baton(path, copyfrom_path, copyfrom_rev, eb, pb, pool);
/* This might be a replacement -- is the path already deleted? */
- val = svn_hash_gets(pb->deleted_entries, path);
+ was_deleted = svn_hash_gets(pb->deleted_entries, path);
/* Detect an add-with-history. */
is_copy = ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev);
@@ -1345,19 +1548,19 @@ add_directory(const char *path,
/* Dump the node. */
SVN_ERR(dump_node(eb, path,
svn_node_dir,
- val ? svn_node_action_replace : svn_node_action_add,
+ was_deleted ? svn_node_action_replace : svn_node_action_add,
is_copy,
is_copy ? copyfrom_path : NULL,
is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
pool));
- if (val)
+ if (was_deleted)
/* 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)
+ if (!was_deleted && eb->verify && eb->check_normalization && eb->notify_func)
{
pb->check_name_collision = TRUE;
}
@@ -1391,7 +1594,7 @@ open_directory(const char *path,
cmp_rev = pb->cmp_rev;
}
- new_db = make_dir_baton(path, cmp_path, cmp_rev, eb, pb, FALSE, pool);
+ new_db = make_dir_baton(path, cmp_path, cmp_rev, eb, pb, pool);
*child_baton = new_db;
return SVN_NO_ERROR;
}
@@ -1443,11 +1646,11 @@ add_file(const char *path,
{
struct dir_baton *pb = parent_baton;
struct edit_baton *eb = pb->edit_baton;
- void *val;
+ void *was_deleted;
svn_boolean_t is_copy = FALSE;
/* This might be a replacement -- is the path already deleted? */
- val = svn_hash_gets(pb->deleted_entries, path);
+ was_deleted = svn_hash_gets(pb->deleted_entries, path);
/* Detect add-with-history. */
is_copy = ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev);
@@ -1455,19 +1658,19 @@ add_file(const char *path,
/* Dump the node. */
SVN_ERR(dump_node(eb, path,
svn_node_file,
- val ? svn_node_action_replace : svn_node_action_add,
+ was_deleted ? svn_node_action_replace : svn_node_action_add,
is_copy,
is_copy ? copyfrom_path : NULL,
is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
pool));
- if (val)
+ if (was_deleted)
/* 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)
+ if (!was_deleted && eb->verify && eb->check_normalization && eb->notify_func)
{
pb->check_name_collision = TRUE;
}
@@ -1518,11 +1721,16 @@ change_dir_prop(void *parent_baton,
/* This function is what distinguishes between a directory that is
opened to merely get somewhere, vs. one that is opened because it
- *actually* changed by itself. */
+ *actually* changed by itself.
+
+ Instead of recording the prop changes here, we just use this method
+ to trigger writing the node; dump_node() finds all the changes. */
if (! db->written_out)
{
SVN_ERR(dump_node(eb, db->path,
svn_node_dir, svn_node_action_change,
+ /* ### We pass is_copy=FALSE; this might be wrong
+ but the parameter isn't used when action=change. */
FALSE, db->cmp_path, db->cmp_rev, pool));
db->written_out = TRUE;
}
@@ -1651,7 +1859,6 @@ get_dump_editor(const svn_delta_editor_t
eb->notify_func = notify_func;
eb->notify_baton = notify_baton;
eb->oldest_dumped_rev = oldest_dumped_rev;
- eb->bufsize = sizeof(eb->buffer);
eb->path = apr_pstrdup(pool, root_path);
SVN_ERR(svn_fs_revision_root(&(eb->fs_root), fs, to_rev, pool));
eb->fs = fs;
@@ -1712,15 +1919,10 @@ write_revision_record(svn_stream_t *stre
svn_revnum_t rev,
apr_pool_t *pool)
{
- apr_size_t len;
apr_hash_t *props;
- svn_stringbuf_t *encoded_prophash;
apr_time_t timetemp;
svn_string_t *datevalue;
- svn_stream_t *propstream;
- /* Read the revision props even if we're aren't going to dump
- them for verification purposes */
SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, pool));
/* Run revision date properties through the time conversion to
@@ -1735,33 +1937,10 @@ write_revision_record(svn_stream_t *stre
svn_hash_sets(props, SVN_PROP_REVISION_DATE, datevalue);
}
- encoded_prophash = svn_stringbuf_create_ensure(0, pool);
- propstream = svn_stream_from_stringbuf(encoded_prophash, pool);
- SVN_ERR(svn_hash_write2(props, propstream, "PROPS-END", pool));
- SVN_ERR(svn_stream_close(propstream));
-
- /* ### someday write a revision-content-checksum */
-
- SVN_ERR(svn_stream_printf(stream, pool,
- SVN_REPOS_DUMPFILE_REVISION_NUMBER
- ": %ld\n", rev));
- SVN_ERR(svn_stream_printf(stream, pool,
- SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n",
- encoded_prophash->len));
-
- /* Write out a regular Content-length header for the benefit of
- non-Subversion RFC-822 parsers. */
- SVN_ERR(svn_stream_printf(stream, pool,
- SVN_REPOS_DUMPFILE_CONTENT_LENGTH
- ": %" APR_SIZE_T_FMT "\n\n",
- encoded_prophash->len));
-
- len = encoded_prophash->len;
- SVN_ERR(svn_stream_write(stream, encoded_prophash->data, &len));
-
- len = 1;
- return svn_stream_write(stream, "\n", &len);
+ SVN_ERR(svn_repos__dump_revision_record(stream, rev, NULL, props,
+ TRUE /*props_section_always*/,
+ pool));
+ return SVN_NO_ERROR;
}
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_repos/hooks.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_repos/hooks.c Mon Feb 9 11:23:39 2015
@@ -522,10 +522,19 @@ lock_token_content(apr_file_t **handle,
const char *token = apr_hash_this_key(hi);
const char *path = apr_hash_this_val(hi);
+ if (path == (const char *) 1)
+ {
+ /* Special handling for svn_fs_access_t * created by using deprecated
+ svn_fs_access_add_lock_token() function. */
+ path = "";
+ }
+ else
+ {
+ path = svn_path_uri_autoescape(path, pool);
+ }
+
svn_stringbuf_appendstr(lock_str,
- svn_stringbuf_createf(pool, "%s|%s\n",
- svn_path_uri_autoescape(path, pool),
- token));
+ svn_stringbuf_createf(pool, "%s|%s\n", path, token));
}
svn_stringbuf_appendcstr(lock_str, "\n");
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_repos/load-fs-vtable.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_repos/load-fs-vtable.c Mon Feb 9 11:23:39 2015
@@ -31,11 +31,9 @@
#include "svn_string.h"
#include "svn_props.h"
#include "repos.h"
-#include "svn_private_config.h"
#include "svn_mergeinfo.h"
#include "svn_checksum.h"
#include "svn_subst.h"
-#include "svn_ctype.h"
#include "svn_dirent_uri.h"
#include <apr_lib.h>
@@ -43,6 +41,7 @@
#include "private/svn_fspath.h"
#include "private/svn_dep_compat.h"
#include "private/svn_mergeinfo_private.h"
+#include "private/svn_repos_private.h"
/*----------------------------------------------------------------------*/
@@ -84,9 +83,9 @@ struct parse_baton
SVN_INVALID_REVNUM. */
svn_revnum_t last_rev_mapped;
- /* The oldest old revision loaded from the dump stream. If no revisions
+ /* The oldest revision loaded from the dump stream. If no revisions
have been loaded yet, this is set to SVN_INVALID_REVNUM. */
- svn_revnum_t oldest_old_rev;
+ svn_revnum_t oldest_dumpstream_rev;
};
struct revision_baton
@@ -194,8 +193,6 @@ change_node_prop(svn_fs_root_t *txn_root
/* Prepend the mergeinfo source paths in MERGEINFO_ORIG with PARENT_DIR, and
return it in *MERGEINFO_VAL. */
-/* ### FIXME: Consider somehow sharing code with
- ### svnrdump/load_editor.c:prefix_mergeinfo_paths() */
static svn_error_t *
prefix_mergeinfo_paths(svn_string_t **mergeinfo_val,
const svn_string_t *mergeinfo_orig,
@@ -227,13 +224,20 @@ prefix_mergeinfo_paths(svn_string_t **me
/* Examine the mergeinfo in INITIAL_VAL, renumber revisions in rangelists
as appropriate, and return the (possibly new) mergeinfo in *FINAL_VAL
- (allocated from POOL). */
-/* ### FIXME: Consider somehow sharing code with
- ### svnrdump/load_editor.c:renumber_mergeinfo_revs() */
+ (allocated from POOL).
+
+ Adjust any mergeinfo revisions not older than OLDEST_DUMPSTREAM_REV by
+ using REV_MAP which maps (svn_revnum_t) old rev to (svn_revnum_t) new rev.
+
+ Adjust any mergeinfo revisions older than OLDEST_DUMPSTREAM_REV by
+ (-OLDER_REVS_OFFSET), dropping any that become <= 0.
+ */
static svn_error_t *
renumber_mergeinfo_revs(svn_string_t **final_val,
const svn_string_t *initial_val,
- struct revision_baton *rb,
+ apr_hash_t *rev_map,
+ svn_revnum_t oldest_dumpstream_rev,
+ apr_int32_t older_revs_offset,
apr_pool_t *pool)
{
apr_pool_t *subpool = svn_pool_create(pool);
@@ -248,19 +252,22 @@ renumber_mergeinfo_revs(svn_string_t **f
Remove mergeinfo older than the oldest revision in the dump stream
and adjust its revisions by the difference between the head rev of
the target repository and the current dump stream rev. */
- if (rb->pb->oldest_old_rev > 1)
+ if (oldest_dumpstream_rev > 1)
{
+ /* predates_stream_mergeinfo := mergeinfo that refers to revs before
+ oldest_dumpstream_rev */
SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
&predates_stream_mergeinfo, mergeinfo,
- rb->pb->oldest_old_rev - 1, 0,
+ oldest_dumpstream_rev - 1, 0,
TRUE, subpool, subpool));
+ /* mergeinfo := mergeinfo that refers to revs >= oldest_dumpstream_rev */
SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
&mergeinfo, mergeinfo,
- rb->pb->oldest_old_rev - 1, 0,
+ oldest_dumpstream_rev - 1, 0,
FALSE, subpool, subpool));
SVN_ERR(svn_mergeinfo__adjust_mergeinfo_rangelists(
&predates_stream_mergeinfo, predates_stream_mergeinfo,
- -rb->rev_offset, subpool, subpool));
+ -older_revs_offset, subpool, subpool));
}
else
{
@@ -271,7 +278,6 @@ renumber_mergeinfo_revs(svn_string_t **f
{
const char *merge_source = apr_hash_this_key(hi);
svn_rangelist_t *rangelist = apr_hash_this_val(hi);
- struct parse_baton *pb = rb->pb;
int i;
/* Possibly renumber revisions in merge source's rangelist. */
@@ -280,27 +286,27 @@ renumber_mergeinfo_revs(svn_string_t **f
svn_revnum_t rev_from_map;
svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, i,
svn_merge_range_t *);
- rev_from_map = get_revision_mapping(pb->rev_map, range->start);
+ rev_from_map = get_revision_mapping(rev_map, range->start);
if (SVN_IS_VALID_REVNUM(rev_from_map))
{
range->start = rev_from_map;
}
- else if (range->start == pb->oldest_old_rev - 1)
+ else if (range->start == oldest_dumpstream_rev - 1)
{
/* Since the start revision of svn_merge_range_t are not
inclusive there is one possible valid start revision that
- won't be found in the PB->REV_MAP mapping of load stream
+ won't be found in the REV_MAP mapping of load stream
revsions to loaded revisions: The revision immediately
preceding the oldest revision from the load stream.
This is a valid revision for mergeinfo, but not a valid
- copy from revision (which PB->REV_MAP also maps for) so it
+ copy from revision (which REV_MAP also maps for) so it
will never be in the mapping.
If that is what we have here, then find the mapping for the
oldest rev from the load stream and subtract 1 to get the
renumbered, non-inclusive, start revision. */
- rev_from_map = get_revision_mapping(pb->rev_map,
- pb->oldest_old_rev);
+ rev_from_map = get_revision_mapping(rev_map,
+ oldest_dumpstream_rev);
if (SVN_IS_VALID_REVNUM(rev_from_map))
range->start = rev_from_map - 1;
}
@@ -317,7 +323,7 @@ renumber_mergeinfo_revs(svn_string_t **f
continue;
}
- rev_from_map = get_revision_mapping(pb->rev_map, range->end);
+ rev_from_map = get_revision_mapping(rev_map, range->end);
if (SVN_IS_VALID_REVNUM(rev_from_map))
range->end = rev_from_map;
}
@@ -325,19 +331,12 @@ renumber_mergeinfo_revs(svn_string_t **f
}
if (predates_stream_mergeinfo)
+ {
SVN_ERR(svn_mergeinfo_merge2(final_mergeinfo, predates_stream_mergeinfo,
subpool, subpool));
+ }
- SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
-
- /* Mergeinfo revision sources for r0 and r1 are invalid; you can't merge r0
- or r1. However, svndumpfilter can be abused to produce r1 merge source
- revs. So if we encounter any, then strip them out, no need to put them
- into the load target. */
- SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(&final_mergeinfo,
- final_mergeinfo,
- 1, 0, FALSE,
- subpool, subpool));
+ SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool));
SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool));
svn_pool_destroy(subpool);
@@ -350,6 +349,12 @@ renumber_mergeinfo_revs(svn_string_t **f
/** vtable for doing commits to a fs **/
+/* Make a node baton, parsing the relevant HEADERS.
+ *
+ * If RB->pb->parent_dir:
+ * prefix it to NB->path
+ * prefix it to NB->copyfrom_path (if present)
+ */
static svn_error_t *
make_node_baton(struct node_baton **node_baton_p,
apr_hash_t *headers,
@@ -436,6 +441,10 @@ make_node_baton(struct node_baton **node
return SVN_NO_ERROR;
}
+/* Make a revision baton, parsing the relevant HEADERS.
+ *
+ * Set RB->skipped iff the revision number is outside the range given in PB.
+ */
static struct revision_baton *
make_revision_baton(apr_hash_t *headers,
struct parse_baton *pb,
@@ -514,8 +523,8 @@ new_revision_record(void **revision_bato
}
/* Stash the oldest "old" revision committed from the load stream. */
- if (!SVN_IS_VALID_REVNUM(pb->oldest_old_rev))
- pb->oldest_old_rev = rb->rev;
+ if (!SVN_IS_VALID_REVNUM(pb->oldest_dumpstream_rev))
+ pb->oldest_dumpstream_rev = rb->rev;
}
/* If we're skipping this revision, try to notify someone. */
@@ -542,7 +551,11 @@ new_revision_record(void **revision_bato
-/* Factorized helper func for new_node_record() */
+/* Perform a copy or a plain add.
+ *
+ * For a copy, also adjust the copy-from rev, check any copy-source checksum,
+ * and send a notification.
+ */
static svn_error_t *
maybe_add_with_history(struct node_baton *nb,
struct revision_baton *rb,
@@ -753,6 +766,67 @@ set_revision_property(void *baton,
}
+svn_error_t *
+svn_repos__adjust_mergeinfo_property(svn_string_t **new_value_p,
+ const svn_string_t *old_value,
+ const char *parent_dir,
+ apr_hash_t *rev_map,
+ svn_revnum_t oldest_dumpstream_rev,
+ apr_int32_t older_revs_offset,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_string_t prop_val = *old_value;
+
+ /* Tolerate mergeinfo with "\r\n" line endings because some
+ dumpstream sources might contain as much. If so normalize
+ the line endings to '\n' and notify that we have made this
+ correction. */
+ if (strstr(prop_val.data, "\r"))
+ {
+ const char *prop_eol_normalized;
+
+ SVN_ERR(svn_subst_translate_cstring2(prop_val.data,
+ &prop_eol_normalized,
+ "\n", /* translate to LF */
+ FALSE, /* no repair */
+ NULL, /* no keywords */
+ FALSE, /* no expansion */
+ result_pool));
+ prop_val.data = prop_eol_normalized;
+ prop_val.len = strlen(prop_eol_normalized);
+
+ if (notify_func)
+ {
+ svn_repos_notify_t *notify
+ = svn_repos_notify_create(
+ svn_repos_notify_load_normalized_mergeinfo,
+ scratch_pool);
+
+ notify_func(notify_baton, notify, scratch_pool);
+ }
+ }
+
+ /* Renumber mergeinfo as appropriate. */
+ SVN_ERR(renumber_mergeinfo_revs(new_value_p, &prop_val,
+ rev_map, oldest_dumpstream_rev,
+ older_revs_offset,
+ result_pool));
+
+ if (parent_dir)
+ {
+ /* Prefix the merge source paths with PARENT_DIR. */
+ /* ASSUMPTION: All source paths are included in the dump stream. */
+ SVN_ERR(prefix_mergeinfo_paths(new_value_p, *new_value_p,
+ parent_dir, result_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
static svn_error_t *
set_node_property(void *baton,
const char *name,
@@ -766,55 +840,49 @@ set_node_property(void *baton,
if (rb->skipped)
return SVN_NO_ERROR;
+ /* Adjust mergeinfo. If this fails, presumably because the mergeinfo
+ property has an ill-formed value, then we must not fail to load
+ the repository (at least if it's a simple load with no revision
+ offset adjustments, path changes, etc.) so just warn and leave it
+ as it is. */
if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
{
- svn_string_t prop_val = *value;
- svn_string_t *renumbered_mergeinfo;
+ svn_string_t *new_value;
+ svn_error_t *err;
- /* Tolerate mergeinfo with "\r\n" line endings because some
- dumpstream sources might contain as much. If so normalize
- the line endings to '\n' and make a notification to
- PARSE_BATON->FEEDBACK_STREAM that we have made this
- correction. */
- if (strstr(prop_val.data, "\r"))
+ err = svn_repos__adjust_mergeinfo_property(&new_value, value,
+ pb->parent_dir,
+ pb->rev_map,
+ pb->oldest_dumpstream_rev,
+ rb->rev_offset,
+ pb->notify_func, pb->notify_baton,
+ nb->pool, pb->notify_pool);
+ svn_pool_clear(pb->notify_pool);
+ if (err)
{
- const char *prop_eol_normalized;
-
- SVN_ERR(svn_subst_translate_cstring2(prop_val.data,
- &prop_eol_normalized,
- "\n", /* translate to LF */
- FALSE, /* no repair */
- NULL, /* no keywords */
- FALSE, /* no expansion */
- nb->pool));
- prop_val.data = prop_eol_normalized;
- prop_val.len = strlen(prop_eol_normalized);
-
+ if (pb->validate_props)
+ {
+ return svn_error_quick_wrap(
+ err,
+ _("Invalid svn:mergeinfo value"));
+ }
if (pb->notify_func)
{
- /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
svn_repos_notify_t *notify
- = svn_repos_notify_create(
- svn_repos_notify_load_normalized_mergeinfo,
- pb->notify_pool);
+ = svn_repos_notify_create(svn_repos_notify_warning,
+ pb->notify_pool);
+ notify->warning = svn_repos_notify_warning_invalid_mergeinfo;
+ notify->warning_str = _("Invalid svn:mergeinfo value; "
+ "leaving unchanged");
pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
svn_pool_clear(pb->notify_pool);
}
+ svn_error_clear(err);
}
-
- /* Renumber mergeinfo as appropriate. */
- SVN_ERR(renumber_mergeinfo_revs(&renumbered_mergeinfo, &prop_val, rb,
- nb->pool));
- value = renumbered_mergeinfo;
- if (pb->parent_dir)
+ else
{
- /* Prefix the merge source paths with PB->parent_dir. */
- /* ASSUMPTION: All source paths are included in the dump stream. */
- svn_string_t *mergeinfo_val;
- SVN_ERR(prefix_mergeinfo_paths(&mergeinfo_val, value,
- pb->parent_dir, nb->pool));
- value = mergeinfo_val;
+ value = new_value;
}
}
@@ -1082,7 +1150,7 @@ close_revision(void *baton)
svn_error_t *
-svn_repos_get_fs_build_parser4(const svn_repos_parse_fns3_t **callbacks,
+svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **callbacks,
void **parse_baton,
svn_repos_t *repos,
svn_revnum_t start_rev,
@@ -1091,6 +1159,9 @@ svn_repos_get_fs_build_parser4(const svn
svn_boolean_t validate_props,
enum svn_repos_load_uuid uuid_action,
const char *parent_dir,
+ svn_boolean_t use_pre_commit_hook,
+ svn_boolean_t use_post_commit_hook,
+ svn_boolean_t ignore_dates,
svn_repos_notify_func_t notify_func,
void *notify_baton,
apr_pool_t *pool)
@@ -1132,10 +1203,13 @@ svn_repos_get_fs_build_parser4(const svn
pb->pool = pool;
pb->notify_pool = svn_pool_create(pool);
pb->rev_map = apr_hash_make(pool);
- pb->oldest_old_rev = SVN_INVALID_REVNUM;
+ pb->oldest_dumpstream_rev = SVN_INVALID_REVNUM;
pb->last_rev_mapped = SVN_INVALID_REVNUM;
pb->start_rev = start_rev;
pb->end_rev = end_rev;
+ pb->use_pre_commit_hook = use_pre_commit_hook;
+ pb->use_post_commit_hook = use_post_commit_hook;
+ pb->ignore_dates = ignore_dates;
*callbacks = parser;
*parse_baton = pb;
@@ -1162,28 +1236,23 @@ svn_repos_load_fs5(svn_repos_t *repos,
{
const svn_repos_parse_fns3_t *parser;
void *parse_baton;
- struct parse_baton *pb;
/* This is really simple. */
- SVN_ERR(svn_repos_get_fs_build_parser4(&parser, &parse_baton,
+ SVN_ERR(svn_repos_get_fs_build_parser5(&parser, &parse_baton,
repos,
start_rev, end_rev,
TRUE, /* look for copyfrom revs */
validate_props,
uuid_action,
parent_dir,
+ use_pre_commit_hook,
+ use_post_commit_hook,
+ ignore_dates,
notify_func,
notify_baton,
pool));
- /* Heh. We know this is a parse_baton. This file made it. So
- cast away, and set our hook booleans. */
- pb = parse_baton;
- pb->use_pre_commit_hook = use_pre_commit_hook;
- pb->use_post_commit_hook = use_post_commit_hook;
- pb->ignore_dates = ignore_dates;
-
return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE,
cancel_func, cancel_baton, pool);
}
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_repos/log.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_repos/log.c Mon Feb 9 11:23:39 2015
@@ -168,18 +168,23 @@ svn_repos_check_revision_access(svn_repo
* AUTHZ_READ_BATON and FS) to check whether each changed-path (and
* copyfrom_path) is readable:
*
+ * - If absolutely every changed-path (and copyfrom_path) is
+ * readable, then return the full CHANGED hash, and set
+ * *ACCESS_LEVEL to svn_repos_revision_access_full.
+ *
* - If some paths are readable and some are not, then silently
- * omit the unreadable paths from the CHANGED hash, and return
- * SVN_ERR_AUTHZ_PARTIALLY_READABLE.
+ * omit the unreadable paths from the CHANGED hash, and set
+ * *ACCESS_LEVEL to svn_repos_revision_access_partial.
*
* - If absolutely every changed-path (and copyfrom_path) is
- * unreadable, then return an empty CHANGED hash and
- * SVN_ERR_AUTHZ_UNREADABLE. (This is to distinguish a revision
- * which truly has no changed paths from a revision in which all
- * paths are unreadable.)
+ * unreadable, then return an empty CHANGED hash, and set
+ * *ACCESS_LEVEL to svn_repos_revision_access_none. (This is
+ * to distinguish a revision which truly has no changed paths
+ * from a revision in which all paths are unreadable.)
*/
static svn_error_t *
-detect_changed(apr_hash_t **changed,
+detect_changed(svn_repos_revision_access_level_t *access_level,
+ apr_hash_t **changed,
svn_fs_root_t *root,
svn_fs_t *fs,
apr_hash_t *prefetched_changes,
@@ -213,9 +218,12 @@ detect_changed(apr_hash_t **changed,
}
if (apr_hash_count(changes) == 0)
- /* No paths changed in this revision? Uh, sure, I guess the
- revision is readable, then. */
- return SVN_NO_ERROR;
+ {
+ /* No paths changed in this revision? Uh, sure, I guess the
+ revision is readable, then. */
+ *access_level = svn_repos_revision_access_full;
+ return SVN_NO_ERROR;
+ }
iterpool = svn_pool_create(pool);
for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi))
@@ -364,16 +372,21 @@ detect_changed(apr_hash_t **changed,
svn_pool_destroy(iterpool);
if (! found_readable)
- /* Every changed-path was unreadable. */
- return svn_error_create(SVN_ERR_AUTHZ_UNREADABLE,
- NULL, NULL);
-
- if (found_unreadable)
- /* At least one changed-path was unreadable. */
- return svn_error_create(SVN_ERR_AUTHZ_PARTIALLY_READABLE,
- NULL, NULL);
+ {
+ /* Every changed-path was unreadable. */
+ *access_level = svn_repos_revision_access_none;
+ }
+ else if (found_unreadable)
+ {
+ /* At least one changed-path was unreadable. */
+ *access_level = svn_repos_revision_access_partial;
+ }
+ else
+ {
+ /* Every changed-path was readable. */
+ *access_level = svn_repos_revision_access_full;
+ }
- /* Every changed-path was readable. */
return SVN_NO_ERROR;
}
@@ -1070,6 +1083,7 @@ fill_log_entry(svn_log_entry_t *log_entr
{
apr_hash_t *r_props, *changed_paths = NULL;
svn_boolean_t get_revprops = TRUE, censor_revprops = FALSE;
+ svn_boolean_t want_revprops = !revprops || revprops->nelts;
/* Discover changed paths if the user requested them
or if we need to check that they are readable. */
@@ -1077,33 +1091,27 @@ fill_log_entry(svn_log_entry_t *log_entr
&& (authz_read_func || discover_changed_paths))
{
svn_fs_root_t *newroot;
- svn_error_t *patherr;
+ svn_repos_revision_access_level_t access_level;
SVN_ERR(svn_fs_revision_root(&newroot, fs, rev, pool));
- patherr = detect_changed(&changed_paths,
- newroot, fs, prefetched_changes,
- authz_read_func, authz_read_baton,
- pool);
+ SVN_ERR(detect_changed(&access_level, &changed_paths,
+ newroot, fs, prefetched_changes,
+ authz_read_func, authz_read_baton,
+ pool));
- if (patherr
- && patherr->apr_err == SVN_ERR_AUTHZ_UNREADABLE)
+ if (access_level == svn_repos_revision_access_none)
{
/* All changed-paths are unreadable, so clear all fields. */
- svn_error_clear(patherr);
changed_paths = NULL;
get_revprops = FALSE;
}
- else if (patherr
- && patherr->apr_err == SVN_ERR_AUTHZ_PARTIALLY_READABLE)
+ else if (access_level == svn_repos_revision_access_partial)
{
/* At least one changed-path was unreadable, so censor all
but author and date. (The unreadable paths are already
missing from the hash.) */
- svn_error_clear(patherr);
censor_revprops = TRUE;
}
- else if (patherr)
- return patherr;
/* It may be the case that an authz func was passed in, but
the user still doesn't want to see any changed-paths. */
@@ -1111,7 +1119,7 @@ fill_log_entry(svn_log_entry_t *log_entr
changed_paths = NULL;
}
- if (get_revprops)
+ if (get_revprops && want_revprops)
{
/* User is allowed to see at least some revprops. */
SVN_ERR(svn_fs_revision_proplist(&r_props, fs, rev, pool));
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_repos/reporter.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_repos/reporter.c Mon Feb 9 11:23:39 2015
@@ -495,8 +495,8 @@ get_revision_info(report_baton_t *b,
/* Create a result object */
info = apr_palloc(b->pool, sizeof(*info));
info->rev = rev;
- info->date = cdate ? svn_string_dup(cdate, b->pool) : NULL;
- info->author = author ? svn_string_dup(author, b->pool) : NULL;
+ info->date = svn_string_dup(cdate, b->pool);
+ info->author = svn_string_dup(author, b->pool);
/* Cache it */
apr_hash_set(b->revision_infos, &info->rev, sizeof(info->rev), info);
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_repos/rev_hunt.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_repos/rev_hunt.c Mon Feb 9 11:23:39 2015
@@ -1386,7 +1386,7 @@ send_path_revision(struct path_revision
/* Compute and send delta if client asked for it.
Note that this was initialized to NULL, so if !contents_changed,
no deltas will be computed. */
- if (delta_handler)
+ if (delta_handler && delta_handler != svn_delta_noop_window_handler)
{
/* Get the content delta. */
SVN_ERR(svn_fs_get_file_delta_stream(&delta_stream,
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_subr/auth.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_subr/auth.c Mon Feb 9 11:23:39 2015
@@ -685,3 +685,167 @@ svn_auth_get_platform_specific_client_pr
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_auth__apply_config_for_server(svn_auth_baton_t *auth_baton,
+ apr_hash_t *config,
+ const char *server_name,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t store_passwords = SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS;
+ svn_boolean_t store_auth_creds = SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS;
+ const char *store_plaintext_passwords
+ = SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS;
+ svn_boolean_t store_pp = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP;
+ const char *store_pp_plaintext
+ = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT;
+ svn_config_t *servers = NULL;
+ const char *server_group = NULL;
+
+ /* The 'store-passwords' and 'store-auth-creds' parameters used to
+ * live in SVN_CONFIG_CATEGORY_CONFIG. For backward compatibility,
+ * if values for these parameters have already been set by our
+ * callers, we use those values as defaults.
+ *
+ * Note that we can only catch the case where users explicitly set
+ * "store-passwords = no" or 'store-auth-creds = no".
+ *
+ * However, since the default value for both these options is
+ * currently (and has always been) "yes", users won't know
+ * the difference if they set "store-passwords = yes" or
+ * "store-auth-creds = yes" -- they'll get the expected behaviour.
+ */
+
+ if (svn_auth_get_parameter(auth_baton,
+ SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL)
+ store_passwords = FALSE;
+
+ if (svn_auth_get_parameter(auth_baton,
+ SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL)
+ store_auth_creds = FALSE;
+
+ /* All the svn_auth_set_parameter() calls below this not only affect the
+ to be created ra session, but also all the ra sessions that are already
+ use this auth baton!
+
+ Please try to key things based on the realm string instead of this
+ construct.
+ */
+
+ if (config)
+ {
+ /* Grab the 'servers' config. */
+ servers = svn_hash_gets(config, SVN_CONFIG_CATEGORY_SERVERS);
+ if (servers)
+ {
+ /* First, look in the global section. */
+
+ SVN_ERR(svn_config_get_bool
+ (servers, &store_passwords, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_PASSWORDS,
+ store_passwords));
+
+ SVN_ERR(svn_config_get_yes_no_ask
+ (servers, &store_plaintext_passwords, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
+ SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS));
+
+ SVN_ERR(svn_config_get_bool
+ (servers, &store_pp, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
+ store_pp));
+
+ SVN_ERR(svn_config_get_yes_no_ask
+ (servers, &store_pp_plaintext,
+ SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
+ SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT));
+
+ SVN_ERR(svn_config_get_bool
+ (servers, &store_auth_creds, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
+ store_auth_creds));
+
+ /* Find out where we're about to connect to, and
+ * try to pick a server group based on the destination. */
+ server_group = svn_config_find_group(servers, server_name,
+ SVN_CONFIG_SECTION_GROUPS,
+ scratch_pool);
+
+ if (server_group)
+ {
+ /* Override global auth caching parameters with the ones
+ * for the server group, if any. */
+ SVN_ERR(svn_config_get_bool(servers, &store_auth_creds,
+ server_group,
+ SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
+ store_auth_creds));
+
+ SVN_ERR(svn_config_get_bool(servers, &store_passwords,
+ server_group,
+ SVN_CONFIG_OPTION_STORE_PASSWORDS,
+ store_passwords));
+
+ SVN_ERR(svn_config_get_yes_no_ask
+ (servers, &store_plaintext_passwords, server_group,
+ SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
+ store_plaintext_passwords));
+
+ SVN_ERR(svn_config_get_bool
+ (servers, &store_pp,
+ server_group, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
+ store_pp));
+
+ SVN_ERR(svn_config_get_yes_no_ask
+ (servers, &store_pp_plaintext, server_group,
+ SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
+ store_pp_plaintext));
+ }
+ }
+ }
+
+ /* Save auth caching parameters in the auth parameter hash. */
+ if (! store_passwords)
+ svn_auth_set_parameter(auth_baton,
+ SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, "");
+
+ svn_auth_set_parameter(auth_baton,
+ SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
+ store_plaintext_passwords);
+
+ if (! store_pp)
+ svn_auth_set_parameter(auth_baton,
+ SVN_AUTH_PARAM_DONT_STORE_SSL_CLIENT_CERT_PP,
+ "");
+
+ svn_auth_set_parameter(auth_baton,
+ SVN_AUTH_PARAM_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
+ store_pp_plaintext);
+
+ if (! store_auth_creds)
+ svn_auth_set_parameter(auth_baton,
+ SVN_AUTH_PARAM_NO_AUTH_CACHE, "");
+
+ /* ### This setting may have huge side-effects when the auth baton is shared
+ ### between different ra sessions, as it will change which server settings
+ ### will be used for all future auth requests.
+ ###
+ ### E.g. when you connect using a ssl client cert that is specified in the
+ ### config file, you might have it when you first connect... but if you
+ ### then connect to another repository, you might not see the same
+ ### settings when the SSL connection is built up again later on.
+ ###
+ ### Most current usages should probably have been keyed on the realm
+ ### string instead of this magic flag that changes when multiple repositories
+ ### are used.
+ ###
+ ### This especially affects long living ra sessions, such as those on the
+ ### reuse-ra-session branch.
+ */
+ if (server_group)
+ svn_auth_set_parameter(auth_baton,
+ SVN_AUTH_PARAM_SERVER_GROUP,
+ apr_pstrdup(auth_baton->pool, server_group));
+
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache-membuffer.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache-membuffer.c Mon Feb 9 11:23:39 2015
@@ -31,6 +31,7 @@
#include "cache.h"
#include "svn_string.h"
#include "svn_sorts.h" /* get the MIN macro */
+#include "private/svn_atomic.h"
#include "private/svn_dep_compat.h"
#include "private/svn_mutex.h"
#include "private/svn_pseudo_md5.h"
@@ -122,7 +123,7 @@
* Use a simple mutex on Windows. Because there is one mutex per segment,
* large machines should (and usually can) be configured with large caches
* such that read contention is kept low. This is basically the situation
- * we head before 1.8.
+ * we had before 1.8.
*/
#ifdef WIN32
# define USE_SIMPLE_MUTEX 1
@@ -364,7 +365,7 @@ typedef struct entry_t
/* Number of (read) hits for this entry. Will be reset upon write.
* Only valid for used entries.
*/
- apr_uint32_t hit_count;
+ svn_atomic_t hit_count;
/* Reference to the next used entry in the order defined by offset.
* NO_INDEX indicates the end of the list; this entry must be referenced
@@ -557,19 +558,14 @@ struct svn_membuffer_t
*/
cache_level_t l2;
+
/* Number of used dictionary entries, i.e. number of cached items.
- * In conjunction with hit_count, this is used calculate the average
- * hit count as part of the randomized LFU algorithm.
+ * Purely statistical information that may be used for profiling only.
+ * Updates are not synchronized and values may be nonsensicle on some
+ * platforms.
*/
apr_uint32_t used_entries;
- /* Sum of (read) hit counts of all used dictionary entries.
- * In conjunction used_entries used_entries, this is used calculate
- * the average hit count as part of the randomized LFU algorithm.
- */
- apr_uint64_t hit_count;
-
-
/* Total number of calls to membuffer_cache_get.
* Purely statistical information that may be used for profiling only.
* Updates are not synchronized and values may be nonsensicle on some
@@ -591,16 +587,15 @@ struct svn_membuffer_t
*/
apr_uint64_t total_hits;
-#if APR_HAS_THREADS
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe.
*/
-# if USE_SIMPLE_MUTEX
svn_mutex__t *lock;
-# else
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
+ /* Same for read-write lock. */
apr_thread_rwlock_t *lock;
-# endif
/* If set, write access will wait until they get exclusive access.
* Otherwise, they will become no-ops if the segment is currently
@@ -608,12 +603,6 @@ struct svn_membuffer_t
*/
svn_boolean_t allow_blocking_writes;
#endif
-
- /* All counters that have consistency requirements on thems (currently,
- * that's only the hit counters) must use this mutex to serialize their
- * updates.
- */
- svn_mutex__t *counter_mutex;
};
/* Align integer VALUE to the next ITEM_ALIGNMENT boundary.
@@ -629,33 +618,32 @@ struct svn_membuffer_t
static svn_error_t *
read_lock_cache(svn_membuffer_t *cache)
{
-#if APR_HAS_THREADS
-# if USE_SIMPLE_MUTEX
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
return svn_mutex__lock(cache->lock);
-# else
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
if (cache->lock)
{
apr_status_t status = apr_thread_rwlock_rdlock(cache->lock);
if (status)
return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
}
-# endif
-#endif
+
+ return SVN_NO_ERROR;
+#else
return SVN_NO_ERROR;
+#endif
}
/* If locking is supported for CACHE, acquire a write lock for it.
+ * Set *SUCCESS to FALSE, if we couldn't acquire the write lock;
+ * leave it untouched otherwise.
*/
static svn_error_t *
write_lock_cache(svn_membuffer_t *cache, svn_boolean_t *success)
{
-#if APR_HAS_THREADS
-# if USE_SIMPLE_MUTEX
-
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
return svn_mutex__lock(cache->lock);
-
-# else
-
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
if (cache->lock)
{
apr_status_t status;
@@ -678,9 +666,10 @@ write_lock_cache(svn_membuffer_t *cache,
_("Can't write-lock cache mutex"));
}
-# endif
-#endif
return SVN_NO_ERROR;
+#else
+ return SVN_NO_ERROR;
+#endif
}
/* If locking is supported for CACHE, acquire an unconditional write lock
@@ -689,36 +678,29 @@ write_lock_cache(svn_membuffer_t *cache,
static svn_error_t *
force_write_lock_cache(svn_membuffer_t *cache)
{
-#if APR_HAS_THREADS
-# if USE_SIMPLE_MUTEX
-
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
return svn_mutex__lock(cache->lock);
-
-# else
-
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
apr_status_t status = apr_thread_rwlock_wrlock(cache->lock);
if (status)
return svn_error_wrap_apr(status,
_("Can't write-lock cache mutex"));
-# endif
-#endif
return SVN_NO_ERROR;
+#else
+ return SVN_NO_ERROR;
+#endif
}
/* If locking is supported for CACHE, release the current lock
- * (read or write).
+ * (read or write). Return ERR upon success.
*/
static svn_error_t *
unlock_cache(svn_membuffer_t *cache, svn_error_t *err)
{
-#if APR_HAS_THREADS
-# if USE_SIMPLE_MUTEX
-
- return svn_mutex__unlock(cache->lock, SVN_NO_ERROR);
-
-# else
-
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
+ return svn_mutex__unlock(cache->lock, err);
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
if (cache->lock)
{
apr_status_t status = apr_thread_rwlock_unlock(cache->lock);
@@ -729,13 +711,14 @@ unlock_cache(svn_membuffer_t *cache, svn
return svn_error_wrap_apr(status, _("Can't unlock cache mutex"));
}
-# endif
-#endif
return err;
+#else
+ return err;
+#endif
}
-/* If supported, guard the execution of EXPR with a read lock to cache.
- * Macro has been modeled after SVN_MUTEX__WITH_LOCK.
+/* If supported, guard the execution of EXPR with a read lock to CACHE.
+ * The macro has been modeled after SVN_MUTEX__WITH_LOCK.
*/
#define WITH_READ_LOCK(cache, expr) \
do { \
@@ -743,8 +726,8 @@ do {
SVN_ERR(unlock_cache(cache, (expr))); \
} while (0)
-/* If supported, guard the execution of EXPR with a write lock to cache.
- * Macro has been modeled after SVN_MUTEX__WITH_LOCK.
+/* If supported, guard the execution of EXPR with a write lock to CACHE.
+ * The macro has been modeled after SVN_MUTEX__WITH_LOCK.
*
* The write lock process is complicated if we don't allow to wait for
* the lock: If we didn't get the lock, we may still need to remove an
@@ -1027,7 +1010,6 @@ drop_entry(svn_membuffer_t *cache, entry
/* update global cache usage counters
*/
cache->used_entries--;
- cache->hit_count -= entry->hit_count;
cache->data_used -= entry->size;
/* extend the insertion window, if the entry happens to border it
@@ -1163,7 +1145,6 @@ let_entry_age(svn_membuffer_t *cache, en
if (hits_removed)
{
- cache->hit_count -= hits_removed;
entry->hit_count -= hits_removed;
}
else
@@ -1795,7 +1776,6 @@ svn_cache__membuffer_cache_create(svn_me
c[seg].max_entry_size = max_entry_size;
c[seg].used_entries = 0;
- c[seg].hit_count = 0;
c[seg].total_reads = 0;
c[seg].total_writes = 0;
c[seg].total_hits = 0;
@@ -1810,17 +1790,14 @@ svn_cache__membuffer_cache_create(svn_me
return svn_error_wrap_apr(APR_ENOMEM, "OOM");
}
-#if APR_HAS_THREADS
+#if (APR_HAS_THREADS && USE_SIMPLE_MUTEX)
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe.
*/
-# if USE_SIMPLE_MUTEX
-
SVN_ERR(svn_mutex__init(&c[seg].lock, thread_safe, pool));
-
-# else
-
+#elif (APR_HAS_THREADS && !USE_SIMPLE_MUTEX)
+ /* Same for read-write lock. */
c[seg].lock = NULL;
if (thread_safe)
{
@@ -1830,17 +1807,10 @@ svn_cache__membuffer_cache_create(svn_me
return svn_error_wrap_apr(status, _("Can't create cache mutex"));
}
-# endif
-
/* Select the behavior of write operations.
*/
c[seg].allow_blocking_writes = allow_blocking_writes;
#endif
-
- /* Since a simple mutex already guarantees fully serialized access,
- we need this mutex only when we use multple-reader-1-writer locks. */
- SVN_ERR(svn_mutex__init(&c[seg].counter_mutex,
- thread_safe && !USE_SIMPLE_MUTEX, pool));
}
/* done here
@@ -2067,21 +2037,17 @@ membuffer_cache_set(svn_membuffer_t *cac
/* Count a hit in ENTRY within CACHE.
*/
-static svn_error_t *
+static void
increment_hit_counters(svn_membuffer_t *cache, entry_t *entry)
{
/* To minimize the memory footprint of the cache index, we limit local
- * hit counters to 32 bits. These may overflow and we must make sure that
- * the global sums are still the sum of all local counters. */
- if (++entry->hit_count == 0)
- cache->hit_count -= APR_UINT32_MAX;
- else
- cache->hit_count++;
+ * hit counters to 32 bits. These may overflow but we don't really
+ * care because at worst, ENTRY will be dropped from cache once every
+ * few billion hits. */
+ svn_atomic_inc(&entry->hit_count);
/* That one is for stats only. */
cache->total_hits++;
-
- return SVN_NO_ERROR;
}
/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
@@ -2140,8 +2106,7 @@ membuffer_cache_get_internal(svn_membuff
/* update hit statistics
*/
- SVN_MUTEX__WITH_LOCK(cache->counter_mutex,
- increment_hit_counters(cache, entry));
+ increment_hit_counters(cache, entry);
*item_size = entry->size;
return SVN_NO_ERROR;
@@ -2205,9 +2170,7 @@ membuffer_cache_has_key_internal(svn_mem
again. While items in L1 are well protected for a while, L2
items may get evicted soon. Thus, mark all them as "hit" to give
them a higher chance of survival. */
- SVN_MUTEX__WITH_LOCK(cache->counter_mutex,
- increment_hit_counters(cache, entry));
-
+ increment_hit_counters(cache, entry);
*found = TRUE;
}
else
@@ -2276,9 +2239,7 @@ membuffer_cache_get_partial_internal(svn
else
{
*found = TRUE;
-
- SVN_MUTEX__WITH_LOCK(cache->counter_mutex,
- increment_hit_counters(cache, entry));
+ increment_hit_counters(cache, entry);
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -2368,8 +2329,7 @@ membuffer_cache_set_partial_internal(svn
char *orig_data = data;
apr_size_t size = entry->size;
- SVN_MUTEX__WITH_LOCK(cache->counter_mutex,
- increment_hit_counters(cache, entry));
+ increment_hit_counters(cache, entry);
cache->total_writes++;
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -2398,6 +2358,8 @@ membuffer_cache_set_partial_internal(svn
* We better drop that.
*/
drop_entry(cache, entry);
+
+ return err;
}
else
{
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache.c Mon Feb 9 11:23:39 2015
@@ -259,15 +259,15 @@ svn_cache__format_info(const svn_cache__
int i;
int count = sizeof(info->histogram) / sizeof(info->histogram[0]);
- for (i = 0; i < count; ++i)
+ for (i = count - 1; i >= 0; --i)
if (info->histogram[i] > 0 || text->len > 0)
text = svn_stringbuf_createf(result_pool,
i == count - 1
- ? "%12" APR_UINT64_T_FMT
- " buckets with >%d entries\n%s"
- : "%12" APR_UINT64_T_FMT
- " buckets with %d entries\n%s",
- info->histogram[i], i, text->data);
+ ? "%s%12" APR_UINT64_T_FMT
+ " buckets with >%d entries\n"
+ : "%s%12" APR_UINT64_T_FMT
+ " buckets with %d entries\n",
+ text->data, info->histogram[i], i);
histogram = text->data;
}
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache_config.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache_config.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache_config.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_subr/cache_config.c Mon Feb 9 11:23:39 2015
@@ -27,6 +27,7 @@
#include "private/svn_cache.h"
#include "svn_pools.h"
+#include "svn_sorts.h"
/* The cache settings as a process-wide singleton.
*/
@@ -80,7 +81,13 @@ initialize_cache(void *baton, apr_pool_t
svn_membuffer_t **cache_p = baton;
svn_membuffer_t *cache = NULL;
- apr_uint64_t cache_size = cache_settings.cache_size;
+ /* Limit the cache size to about half the available address space
+ * (typ. 1G under 32 bits).
+ */
+ apr_uint64_t cache_size = MIN(cache_settings.cache_size,
+ (apr_uint64_t)SVN_MAX_OBJECT_SIZE / 2);
+
+ /* Create caches at all? */
if (cache_size)
{
svn_error_t *err;
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_subr/checksum.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_subr/checksum.c?rev=1658362&r1=1658361&r2=1658362&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_subr/checksum.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_subr/checksum.c Mon Feb 9 11:23:39 2015
@@ -165,12 +165,15 @@ checksum_create_without_digest(svn_check
return checksum;
}
+/* Return a checksum object, allocated in POOL. The checksum will be of
+ * type KIND and contain the given DIGEST.
+ */
static svn_checksum_t *
checksum_create(svn_checksum_kind_t kind,
- apr_size_t digest_size,
const unsigned char *digest,
apr_pool_t *pool)
{
+ apr_size_t digest_size = DIGESTSIZE(kind);
svn_checksum_t *checksum = checksum_create_without_digest(kind, digest_size,
pool);
memcpy((unsigned char *)checksum->digest, digest, digest_size);
@@ -206,32 +209,28 @@ svn_checksum_t *
svn_checksum__from_digest_md5(const unsigned char *digest,
apr_pool_t *result_pool)
{
- return checksum_create(svn_checksum_md5, APR_MD5_DIGESTSIZE, digest,
- result_pool);
+ return checksum_create(svn_checksum_md5, digest, result_pool);
}
svn_checksum_t *
svn_checksum__from_digest_sha1(const unsigned char *digest,
apr_pool_t *result_pool)
{
- return checksum_create(svn_checksum_sha1, APR_SHA1_DIGESTSIZE, digest,
- result_pool);
+ return checksum_create(svn_checksum_sha1, digest, result_pool);
}
svn_checksum_t *
svn_checksum__from_digest_fnv1a_32(const unsigned char *digest,
apr_pool_t *result_pool)
{
- return checksum_create(svn_checksum_fnv1a_32, sizeof(digest), digest,
- result_pool);
+ return checksum_create(svn_checksum_fnv1a_32, digest, result_pool);
}
svn_checksum_t *
svn_checksum__from_digest_fnv1a_32x4(const unsigned char *digest,
apr_pool_t *result_pool)
{
- return checksum_create(svn_checksum_fnv1a_32x4, sizeof(digest), digest,
- result_pool);
+ return checksum_create(svn_checksum_fnv1a_32x4, digest, result_pool);
}
svn_error_t *
@@ -428,10 +427,7 @@ svn_checksum_dup(const svn_checksum_t *c
case svn_checksum_sha1:
case svn_checksum_fnv1a_32:
case svn_checksum_fnv1a_32x4:
- return checksum_create(checksum->kind,
- digest_sizes[checksum->kind],
- checksum->digest,
- pool);
+ return checksum_create(checksum->kind, checksum->digest, pool);
default:
SVN_ERR_MALFUNCTION_NO_RETURN();
@@ -492,10 +488,7 @@ svn_checksum_empty_checksum(svn_checksum
case svn_checksum_sha1:
case svn_checksum_fnv1a_32:
case svn_checksum_fnv1a_32x4:
- return checksum_create(kind,
- digest_sizes[kind],
- empty_string_digests[kind],
- pool);
+ return checksum_create(kind, empty_string_digests[kind], pool);
default:
/* We really shouldn't get here, but if we do... */