You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/03/09 11:08:53 UTC
svn commit: r1575685 [6/13] - in /subversion/branches/fsfs-ucsnorm: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
contrib/cgi/ contrib/client-side/emacs/ contrib/client-side/svn2cl/
contrib/hook-scripts/ contrib/server-side/svn...
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_diff/diff_memory.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_diff/diff_memory.c Sun Mar 9 10:08:46 2014
@@ -949,6 +949,25 @@ output_conflict(void *baton,
return SVN_NO_ERROR;
}
+static svn_error_t *
+output_conflict_with_context_marker(merge_output_baton_t *btn,
+ const char *label,
+ apr_off_t start,
+ apr_off_t length)
+{
+ if (length == 1)
+ SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
+ "%s (%" APR_OFF_T_FMT ")",
+ label, start + 1));
+ else
+ SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
+ "%s (%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT ")",
+ label, start + 1, length));
+
+ SVN_ERR(output_marker_eol(btn));
+
+ return SVN_NO_ERROR;
+}
static svn_error_t *
output_conflict_with_context(void *baton,
@@ -975,36 +994,24 @@ output_conflict_with_context(void *baton
btn->output_stream = btn->real_output_stream;
/* Output the conflict itself. */
- SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
- (modified_length == 1
- ? "%s (%" APR_OFF_T_FMT ")"
- : "%s (%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT ")"),
- btn->markers[1],
- modified_start + 1, modified_length));
- SVN_ERR(output_marker_eol(btn));
+ SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[1],
+ modified_start,
+ modified_length));
SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/,
modified_start, modified_length));
- SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
- (original_length == 1
- ? "%s (%" APR_OFF_T_FMT ")"
- : "%s (%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT ")"),
- btn->markers[0],
- original_start + 1, original_length));
- SVN_ERR(output_marker_eol(btn));
+ SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[0],
+ original_start,
+ original_length));
SVN_ERR(output_merge_token_range(NULL, btn, 0/*original*/,
original_start, original_length));
SVN_ERR(output_merge_marker(btn, 2/*separator*/));
SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/,
latest_start, latest_length));
- SVN_ERR(svn_stream_printf(btn->output_stream, btn->pool,
- (latest_length == 1
- ? "%s (%" APR_OFF_T_FMT ")"
- : "%s (%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT ")"),
- btn->markers[3],
- latest_start + 1, latest_length));
- SVN_ERR(output_marker_eol(btn));
+ SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[3],
+ latest_start,
+ latest_length));
/* Go into print-trailing-context mode instead. */
make_trailing_context_printer(btn);
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_diff/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_diff/util.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_diff/util.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_diff/util.c Sun Mar 9 10:08:46 2014
@@ -75,9 +75,11 @@ svn_diff_contains_diffs(svn_diff_t *diff
}
svn_error_t *
-svn_diff_output(svn_diff_t *diff,
- void *output_baton,
- const svn_diff_output_fns_t *vtable)
+svn_diff_output2(svn_diff_t *diff,
+ void *output_baton,
+ const svn_diff_output_fns_t *vtable,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton)
{
svn_error_t *(*output_fn)(void *,
apr_off_t, apr_off_t,
@@ -86,6 +88,9 @@ svn_diff_output(svn_diff_t *diff,
while (diff != NULL)
{
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
switch (diff->type)
{
case svn_diff__type_common:
@@ -570,7 +575,7 @@ svn_diff__display_prop_diffs(svn_stream_
* from the diff header. But there usually are no files which
* UNIX patch could apply the property diff to, so we use "##"
* instead of "@@" as the default hunk delimiter for property diffs.
- * We also supress the diff header. */
+ * We also suppress the diff header. */
SVN_ERR(svn_diff_mem_string_output_unified2(
outstream, diff, FALSE /* no header */, "##", NULL, NULL,
encoding, orig, val, iterpool));
Propchange: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Sun Mar 9 10:08:46 2014
@@ -8,4 +8,5 @@ Release
*~
.*~
libsvn_fs.def
-
+libsvn_fs.pc.in
+libsvn_fs.pc
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/editor.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/editor.c Sun Mar 9 10:08:46 2014
@@ -177,7 +177,7 @@ can_modify(svn_fs_root_t *txn_root,
SVN_ERR(svn_fs_node_created_rev(&created_rev, txn_root, fspath,
scratch_pool));
- /* Uncommitted nodes (eg. a descendent of a copy/move destination)
+ /* Uncommitted nodes (eg. a descendant of a copy/move destination)
have no (committed) revision number. Let the caller go ahead and
modify these nodes.
@@ -195,7 +195,7 @@ can_modify(svn_fs_root_t *txn_root,
have supplied a valid revision number [that they expect to change].
The checks further below will determine the out-of-dateness of the
specified revision. */
- /* ### ugh. descendents of copy/move destinations carry along
+ /* ### ugh. descendants of copy/move destinations carry along
### their original immutable state and (thus) a valid CREATED_REV.
### but they are logically uncommitted, so the caller will pass
### SVN_INVALID_REVNUM. (technically, the caller could provide
@@ -203,7 +203,7 @@ can_modify(svn_fs_root_t *txn_root,
### API).
###
### for now, we will assume the caller knows what they are doing
- ### and an invalid revision implies such a descendent. in the
+ ### and an invalid revision implies such a descendant. in the
### future, we could examine the ancestor chain looking for a
### copy/move-here node and allow the modification (and the
### converse: if no such ancestor, the caller must specify the
@@ -810,7 +810,7 @@ svn_fs__editor_commit(svn_revnum_t *revi
/* Copy this into the correct pool (see note above). */
*conflict_path = apr_pstrdup(result_pool, inner_conflict_path);
- /* Return sucess. The caller should inspect CONFLICT_PATH to
+ /* Return success. The caller should inspect CONFLICT_PATH to
determine this particular case. */
svn_error_clear(err);
err = SVN_NO_ERROR;
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.c Sun Mar 9 10:08:46 2014
@@ -1106,7 +1106,7 @@ svn_fs_node_relation(svn_fs_node_relatio
apr_pool_t *pool)
{
/* Different repository types? */
- if (root_a->vtable != root_b->vtable)
+ if (root_a->fs != root_b->fs)
{
*relation = svn_fs_node_unrelated;
return SVN_NO_ERROR;
@@ -1167,6 +1167,17 @@ svn_fs_change_node_prop(svn_fs_root_t *r
}
svn_error_t *
+svn_fs_props_different(svn_boolean_t *changed_p, svn_fs_root_t *root1,
+ const char *path1, svn_fs_root_t *root2,
+ const char *path2, apr_pool_t *pool)
+{
+ return svn_error_trace(root1->vtable->props_changed(changed_p,
+ root1, path1,
+ root2, path2,
+ TRUE, pool));
+}
+
+svn_error_t *
svn_fs_props_changed(svn_boolean_t *changed_p, svn_fs_root_t *root1,
const char *path1, svn_fs_root_t *root2,
const char *path2, apr_pool_t *pool)
@@ -1174,7 +1185,7 @@ svn_fs_props_changed(svn_boolean_t *chan
return svn_error_trace(root1->vtable->props_changed(changed_p,
root1, path1,
root2, path2,
- pool));
+ FALSE, pool));
}
svn_error_t *
@@ -1223,6 +1234,30 @@ svn_fs_get_mergeinfo(svn_mergeinfo_catal
}
svn_error_t *
+svn_fs__get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo,
+ svn_fs_root_t *root,
+ const char *path,
+ svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t adjust_inherited_mergeinfo,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *paths
+ = apr_array_make(scratch_pool, 1, sizeof(const char *));
+ svn_mergeinfo_catalog_t catalog;
+
+ APR_ARRAY_PUSH(paths, const char *) = path;
+
+ SVN_ERR(svn_fs_get_mergeinfo2(&catalog, root, paths,
+ inherit, FALSE /*include_descendants*/,
+ adjust_inherited_mergeinfo,
+ result_pool, scratch_pool));
+ *mergeinfo = svn_hash_gets(catalog, path);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_fs_merge(const char **conflict_p, svn_fs_root_t *source_root,
const char *source_path, svn_fs_root_t *target_root,
const char *target_path, svn_fs_root_t *ancestor_root,
@@ -1418,6 +1453,17 @@ svn_fs_apply_text(svn_stream_t **content
}
svn_error_t *
+svn_fs_contents_different(svn_boolean_t *changed_p, svn_fs_root_t *root1,
+ const char *path1, svn_fs_root_t *root2,
+ const char *path2, apr_pool_t *pool)
+{
+ return svn_error_trace(root1->vtable->contents_changed(changed_p,
+ root1, path1,
+ root2, path2,
+ TRUE, pool));
+}
+
+svn_error_t *
svn_fs_contents_changed(svn_boolean_t *changed_p, svn_fs_root_t *root1,
const char *path1, svn_fs_root_t *root2,
const char *path2, apr_pool_t *pool)
@@ -1425,7 +1471,7 @@ svn_fs_contents_changed(svn_boolean_t *c
return svn_error_trace(root1->vtable->contents_changed(changed_p,
root1, path1,
root2, path2,
- pool));
+ FALSE, pool));
}
svn_error_t *
@@ -1679,13 +1725,21 @@ svn_fs_unparse_id(const svn_fs_id_t *id,
svn_boolean_t
svn_fs_check_related(const svn_fs_id_t *a, const svn_fs_id_t *b)
{
- return (a->vtable->compare(a, b) != -1);
+ return (a->vtable->compare(a, b) != svn_fs_node_unrelated);
}
int
svn_fs_compare_ids(const svn_fs_id_t *a, const svn_fs_id_t *b)
{
- return a->vtable->compare(a, b);
+ switch (a->vtable->compare(a, b))
+ {
+ case svn_fs_node_same:
+ return 0;
+ case svn_fs_node_common_ancestor:
+ return 1;
+ default:
+ return -1;
+ }
}
svn_error_t *
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.h?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs/fs-loader.h Sun Mar 9 10:08:46 2014
@@ -29,6 +29,7 @@
#include "svn_fs.h"
#include "svn_props.h"
#include "private/svn_mutex.h"
+#include <apr_poll.h>
#ifdef __cplusplus
extern "C" {
@@ -343,7 +344,8 @@ typedef struct root_vtable_t
apr_pool_t *pool);
svn_error_t *(*props_changed)(int *changed_p, svn_fs_root_t *root1,
const char *path1, svn_fs_root_t *root2,
- const char *path2, apr_pool_t *pool);
+ const char *path2, svn_boolean_t strict,
+ apr_pool_t *pool);
/* Directories */
svn_error_t *(*dir_entries)(apr_hash_t **entries_p, svn_fs_root_t *root,
@@ -383,7 +385,8 @@ typedef struct root_vtable_t
apr_pool_t *pool);
svn_error_t *(*contents_changed)(int *changed_p, svn_fs_root_t *root1,
const char *path1, svn_fs_root_t *root2,
- const char *path2, apr_pool_t *pool);
+ const char *path2, svn_boolean_t strict,
+ apr_pool_t *pool);
svn_error_t *(*get_file_delta_stream)(svn_txdelta_stream_t **stream_p,
svn_fs_root_t *source_root,
const char *source_path,
@@ -424,8 +427,10 @@ typedef struct history_vtable_t
typedef struct id_vtable_t
{
- svn_string_t *(*unparse)(const svn_fs_id_t *id, apr_pool_t *pool);
- int (*compare)(const svn_fs_id_t *a, const svn_fs_id_t *b);
+ svn_string_t *(*unparse)(const svn_fs_id_t *id,
+ apr_pool_t *pool);
+ svn_fs_node_relation_t (*compare)(const svn_fs_id_t *a,
+ const svn_fs_id_t *b);
} id_vtable_t;
Propchange: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Sun Mar 9 10:08:46 2014
@@ -7,4 +7,5 @@ Release
*.o
*~
.*~
-
+libsvn_fs_base.pc
+libsvn_fs_base.pc.in
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/dag.c Sun Mar 9 10:08:46 2014
@@ -1654,14 +1654,8 @@ svn_fs_base__things_different(svn_boolea
/* Compare contents keys and their (optional) uniquifiers. */
if (contents_changed != NULL)
- *contents_changed =
- (! (svn_fs_base__same_keys(noderev1->data_key,
- noderev2->data_key)
- /* Technically, these uniquifiers aren't used and "keys",
- but keys are base-36 stringified numbers, so we'll take
- this liberty. */
- && (svn_fs_base__same_keys(noderev1->data_key_uniquifier,
- noderev2->data_key_uniquifier))));
+ *contents_changed = (! svn_fs_base__same_keys(noderev1->data_key,
+ noderev2->data_key));
return SVN_NO_ERROR;
}
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/id.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/id.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/id.c Sun Mar 9 10:08:46 2014
@@ -108,13 +108,14 @@ svn_fs_base__id_check_related(const svn_
}
-int
+svn_fs_node_relation_t
svn_fs_base__id_compare(const svn_fs_id_t *a,
const svn_fs_id_t *b)
{
if (svn_fs_base__id_eq(a, b))
- return 0;
- return (svn_fs_base__id_check_related(a, b) ? 1 : -1);
+ return svn_fs_node_same;
+ return (svn_fs_base__id_check_related(a, b) ? svn_fs_node_common_ancestor
+ : svn_fs_node_unrelated);
}
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/id.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/id.h?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/id.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/id.h Sun Mar 9 10:08:46 2014
@@ -53,9 +53,9 @@ svn_boolean_t svn_fs_base__id_eq(const s
svn_boolean_t svn_fs_base__id_check_related(const svn_fs_id_t *a,
const svn_fs_id_t *b);
-/* Return 0 if A and B are equal, 1 if they are related, -1 otherwise. */
-int svn_fs_base__id_compare(const svn_fs_id_t *a,
- const svn_fs_id_t *b);
+/* Return the noderev relationship between A and B. */
+svn_fs_node_relation_t svn_fs_base__id_compare(const svn_fs_id_t *a,
+ const svn_fs_id_t *b);
/* Create an ID based on NODE_ID, COPY_ID, and TXN_ID, allocated in
POOL. */
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/key-gen.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/key-gen.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/key-gen.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/key-gen.c Sun Mar 9 10:08:46 2014
@@ -39,20 +39,19 @@ void
svn_fs_base__next_key(const char *this, apr_size_t *len, char *next)
{
apr_size_t olen = *len; /* remember the first length */
- int i = olen - 1; /* initial index; we work backwards */
+ apr_size_t i; /* current index */
char c; /* current char */
svn_boolean_t carry = TRUE; /* boolean: do we have a carry or not?
We start with a carry, because we're
incrementing the number, after all. */
- /* Leading zeros are not allowed, except for the string "0". */
- if ((*len > 1) && (this[0] == '0'))
- {
- *len = 0;
- return;
- }
+ /* Empty strings and leading zeros (except for the string "0") are not
+ * allowed. Run our malfunction handler to prevent possible db corruption
+ * from being propagated further. */
+ SVN_ERR_ASSERT_NO_RETURN(olen != 0 && (olen == 1 || this[0] != '0'));
- for (i = (olen - 1); i >= 0; i--)
+ i = olen - 1; /* initial index: we work backwords */
+ while (1729)
{
c = this[i];
@@ -79,6 +78,11 @@ svn_fs_base__next_key(const char *this,
}
else
next[i] = c;
+
+ if (i == 0)
+ break;
+
+ i--;
}
/* The new length is OLEN, plus 1 if there's a carry out of the
@@ -102,22 +106,6 @@ svn_fs_base__next_key(const char *this,
}
-int
-svn_fs_base__key_compare(const char *a, const char *b)
-{
- int a_len = strlen(a);
- int b_len = strlen(b);
- int cmp;
-
- if (a_len > b_len)
- return 1;
- if (b_len > a_len)
- return -1;
- cmp = strcmp(a, b);
- return (cmp ? (cmp / abs(cmp)) : 0);
-}
-
-
svn_boolean_t
svn_fs_base__same_keys(const char *a, const char *b)
{
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/key-gen.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/key-gen.h?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/key-gen.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/key-gen.h Sun Mar 9 10:08:46 2014
@@ -78,13 +78,6 @@ extern "C" {
void svn_fs_base__next_key(const char *this, apr_size_t *len, char *next);
-/* Compare two strings A and B as base-36 alphanumeric keys.
- *
- * Return -1, 0, or 1 if A is less than, equal to, or greater than B,
- * respectively.
- */
-int svn_fs_base__key_compare(const char *a, const char *b);
-
/* Compare two strings A and B as base-36 alphanumber keys.
*
* Return TRUE iff both keys are NULL or both keys have the same
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/revs-txns.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/revs-txns.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/revs-txns.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/revs-txns.c Sun Mar 9 10:08:46 2014
@@ -912,7 +912,7 @@ delete_txn_tree(svn_fs_t *fs,
svn_error_t *err;
/* If this sucker isn't mutable, there's nothing to do. */
- if (svn_fs_base__key_compare(svn_fs_base__id_txn_id(id), txn_id) != 0)
+ if (strcmp(svn_fs_base__id_txn_id(id), txn_id) != 0)
return SVN_NO_ERROR;
/* See if the thing has dirents that need to be recursed upon. If
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/tree.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_base/tree.c Sun Mar 9 10:08:46 2014
@@ -544,7 +544,7 @@ get_copy_inheritance(copy_id_inherit_t *
parent_copy_id = svn_fs_base__id_copy_id(parent_id);
/* Easy out: if this child is already mutable, we have nothing to do. */
- if (svn_fs_base__key_compare(svn_fs_base__id_txn_id(child_id), txn_id) == 0)
+ if (strcmp(svn_fs_base__id_txn_id(child_id), txn_id) == 0)
return SVN_NO_ERROR;
/* If the child and its parent are on the same branch, then the
@@ -561,7 +561,7 @@ get_copy_inheritance(copy_id_inherit_t *
target of any copy, and therefore must be on the same branch as
its parent. */
if ((strcmp(child_copy_id, "0") == 0)
- || (svn_fs_base__key_compare(child_copy_id, parent_copy_id) == 0))
+ || (strcmp(child_copy_id, parent_copy_id) == 0))
{
*inherit_p = copy_id_inherit_parent;
return SVN_NO_ERROR;
@@ -570,7 +570,8 @@ get_copy_inheritance(copy_id_inherit_t *
{
copy_t *copy;
SVN_ERR(svn_fs_bdb__get_copy(©, fs, child_copy_id, trail, pool));
- if (svn_fs_base__id_compare(copy->dst_noderev_id, child_id) == -1)
+ if ( svn_fs_base__id_compare(copy->dst_noderev_id, child_id)
+ == svn_fs_node_unrelated)
{
*inherit_p = copy_id_inherit_parent;
return SVN_NO_ERROR;
@@ -1047,15 +1048,7 @@ base_node_relation(svn_fs_node_relation_
SVN_ERR(base_node_id(&id_a, root_a, path_a, pool));
SVN_ERR(base_node_id(&id_b, root_b, path_b, pool));
- switch (svn_fs_base__id_compare(id_a, id_b))
- {
- case 0: *relation = svn_fs_node_same;
- break;
- case 1: *relation = svn_fs_node_common_anchestor;
- break;
- default: *relation = svn_fs_node_unrelated;
- break;
- }
+ *relation = svn_fs_base__id_compare(id_a, id_b);
return SVN_NO_ERROR;
}
@@ -1402,6 +1395,7 @@ struct things_changed_args
svn_fs_root_t *root2;
const char *path1;
const char *path2;
+ svn_boolean_t strict;
apr_pool_t *pool;
};
@@ -1411,11 +1405,26 @@ txn_body_props_changed(void *baton, trai
{
struct things_changed_args *args = baton;
dag_node_t *node1, *node2;
+ apr_hash_t *proplist1, *proplist2;
SVN_ERR(get_dag(&node1, args->root1, args->path1, trail, trail->pool));
SVN_ERR(get_dag(&node2, args->root2, args->path2, trail, trail->pool));
- return svn_fs_base__things_different(args->changed_p, NULL,
- node1, node2, trail, trail->pool);
+ SVN_ERR(svn_fs_base__things_different(args->changed_p, NULL,
+ node1, node2, trail, trail->pool));
+
+ /* Is there a potential false positive and do we want to correct it? */
+ if (!args->strict || !*args->changed_p)
+ return SVN_NO_ERROR;
+
+ /* Different representations. They might still have equal contents. */
+ SVN_ERR(svn_fs_base__dag_get_proplist(&proplist1, node1,
+ trail, trail->pool));
+ SVN_ERR(svn_fs_base__dag_get_proplist(&proplist2, node2,
+ trail, trail->pool));
+
+ *args->changed_p = !svn_fs__prop_lists_equal(proplist1, proplist2,
+ trail->pool);
+ return SVN_NO_ERROR;
}
@@ -1425,6 +1434,7 @@ base_props_changed(svn_boolean_t *change
const char *path1,
svn_fs_root_t *root2,
const char *path2,
+ svn_boolean_t strict,
apr_pool_t *pool)
{
struct things_changed_args args;
@@ -1441,6 +1451,7 @@ base_props_changed(svn_boolean_t *change
args.path2 = path2;
args.changed_p = changed_p;
args.pool = pool;
+ args.strict = strict;
return svn_fs_base__retry_txn(root1->fs, txn_body_props_changed, &args,
TRUE, pool);
@@ -3154,7 +3165,7 @@ txn_body_copy(void *baton,
if ((to_parent_path->node)
&& (svn_fs_base__id_compare(svn_fs_base__dag_get_id(from_node),
svn_fs_base__dag_get_id
- (to_parent_path->node)) == 0))
+ (to_parent_path->node)) == svn_fs_node_same))
return SVN_NO_ERROR;
if (! from_root->is_txn_root)
@@ -3354,8 +3365,8 @@ txn_body_copied_from(void *baton, trail_
return SVN_NO_ERROR;
/* If NODE's copy-ID is the same as that of its predecessor... */
- if (svn_fs_base__key_compare(svn_fs_base__id_copy_id(node_id),
- svn_fs_base__id_copy_id(pred_id)) != 0)
+ if (strcmp(svn_fs_base__id_copy_id(node_id),
+ svn_fs_base__id_copy_id(pred_id)) != 0)
{
/* ... then NODE was either the target of a copy operation,
a copied subtree item. We examine the actual copy record
@@ -4004,11 +4015,53 @@ txn_body_contents_changed(void *baton, t
{
struct things_changed_args *args = baton;
dag_node_t *node1, *node2;
+ svn_checksum_t *checksum1, *checksum2;
+ svn_stream_t *stream1, *stream2;
+ svn_boolean_t same;
SVN_ERR(get_dag(&node1, args->root1, args->path1, trail, trail->pool));
SVN_ERR(get_dag(&node2, args->root2, args->path2, trail, trail->pool));
- return svn_fs_base__things_different(NULL, args->changed_p,
- node1, node2, trail, trail->pool);
+ SVN_ERR(svn_fs_base__things_different(NULL, args->changed_p,
+ node1, node2, trail, trail->pool));
+
+ /* Is there a potential false positive and do we want to correct it? */
+ if (!args->strict || !*args->changed_p)
+ return SVN_NO_ERROR;
+
+ /* Different representations. They might still have equal contents. */
+
+ /* Compare MD5 checksums. These should be readily accessible. */
+ SVN_ERR(svn_fs_base__dag_file_checksum(&checksum1, svn_checksum_md5,
+ node1, trail, trail->pool));
+ SVN_ERR(svn_fs_base__dag_file_checksum(&checksum2, svn_checksum_md5,
+ node2, trail, trail->pool));
+
+ /* Different MD5 checksums -> different contents */
+ if (!svn_checksum_match(checksum1, checksum2))
+ return SVN_NO_ERROR;
+
+ /* Paranoia. Compare SHA1 checksums because that's the level of
+ confidence we require for e.g. the working copy. */
+ SVN_ERR(svn_fs_base__dag_file_checksum(&checksum1, svn_checksum_sha1,
+ node1, trail, trail->pool));
+ SVN_ERR(svn_fs_base__dag_file_checksum(&checksum2, svn_checksum_sha1,
+ node2, trail, trail->pool));
+
+ /* Different SHA1 checksums -> different contents */
+ if (checksum1 && checksum2)
+ {
+ *args->changed_p = !svn_checksum_match(checksum1, checksum2);
+ return SVN_NO_ERROR;
+ }
+
+ /* SHA1 checksums are not available for very old reps / repositories. */
+ SVN_ERR(svn_fs_base__dag_get_contents(&stream1, node1, trail, trail->pool));
+ SVN_ERR(svn_fs_base__dag_get_contents(&stream2, node2, trail, trail->pool));
+ SVN_ERR(svn_stream_contents_same2(&same, stream1, stream2, trail->pool));
+
+ /* Now, it's definitive. */
+ *args->changed_p = !same;
+ return SVN_NO_ERROR;
}
@@ -4020,6 +4073,7 @@ base_contents_changed(svn_boolean_t *cha
const char *path1,
svn_fs_root_t *root2,
const char *path2,
+ svn_boolean_t strict,
apr_pool_t *pool)
{
struct things_changed_args args;
@@ -4051,6 +4105,7 @@ base_contents_changed(svn_boolean_t *cha
args.path2 = path2;
args.changed_p = changed_p;
args.pool = pool;
+ args.strict = strict;
return svn_fs_base__retry_txn(root1->fs, txn_body_contents_changed, &args,
TRUE, pool);
@@ -4360,8 +4415,7 @@ txn_body_history_prev(void *baton, trail
(which is either a real predecessor, or is the node itself
playing the predecessor role to an imaginary mutable successor),
then we need to report a copy. */
- if (svn_fs_base__key_compare(svn_fs_base__id_copy_id(node_id),
- end_copy_id) != 0)
+ if (strcmp(svn_fs_base__id_copy_id(node_id), end_copy_id) != 0)
{
const char *remainder;
dag_node_t *dst_node;
Propchange: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Sun Mar 9 10:08:46 2014
@@ -9,3 +9,5 @@ Release
.*~
rep-cache-db.h
revprops-db.h
+libsvn_fs_fs.pc.in
+libsvn_fs_fs.pc
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/cached_data.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/cached_data.c Sun Mar 9 10:08:46 2014
@@ -462,10 +462,13 @@ get_root_changes_offset(apr_off_t *root_
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
- apr_off_t offset;
apr_off_t rev_offset;
apr_seek_where_t seek_relative;
- svn_stringbuf_t *trailer = svn_stringbuf_create_ensure(64, pool);
+ svn_stringbuf_t *trailer;
+ char buffer[64];
+ apr_off_t start;
+ apr_off_t end;
+ apr_size_t len;
/* Determine where to seek to in the file.
@@ -479,13 +482,13 @@ get_root_changes_offset(apr_off_t *root_
if (svn_fs_fs__is_packed_rev(fs, rev)
&& ((rev + 1) % ffd->max_files_per_dir != 0))
{
- SVN_ERR(svn_fs_fs__get_packed_offset(&offset, fs, rev + 1, pool));
+ SVN_ERR(svn_fs_fs__get_packed_offset(&end, fs, rev + 1, pool));
seek_relative = APR_SET;
}
else
{
seek_relative = APR_END;
- offset = 0;
+ end = 0;
}
/* Offset of the revision from the start of the pack file, if applicable. */
@@ -496,16 +499,25 @@ get_root_changes_offset(apr_off_t *root_
/* We will assume that the last line containing the two offsets
will never be longer than 64 characters. */
- SVN_ERR(svn_io_file_seek(rev_file, seek_relative, &offset, pool));
+ SVN_ERR(svn_io_file_seek(rev_file, seek_relative, &end, pool));
- trailer->len = trailer->blocksize-1;
- SVN_ERR(aligned_seek(fs, rev_file, NULL, offset - trailer->len, pool));
+ if (end < sizeof(buffer))
+ {
+ len = (apr_size_t)end;
+ start = 0;
+ }
+ else
+ {
+ len = sizeof(buffer);
+ start = end - sizeof(buffer);
+ }
/* Read in this last block, from which we will identify the last line. */
- SVN_ERR(svn_io_file_read(rev_file, trailer->data, &trailer->len, pool));
- trailer->data[trailer->len] = 0;
+ SVN_ERR(aligned_seek(fs, rev_file, NULL, start, pool));
+ SVN_ERR(svn_io_file_read_full2(rev_file, buffer, len, NULL, NULL, pool));
/* Parse the last line. */
+ trailer = svn_stringbuf_ncreate(buffer, len, pool);
SVN_ERR(svn_fs_fs__parse_revision_trailer(root_offset,
changes_offset,
trailer,
@@ -719,10 +731,9 @@ create_rep_state_body(rep_state_t **rep_
&& ( ((*shared_file)->revision / ffd->max_files_per_dir)
== (rep->revision / ffd->max_files_per_dir));
- representation_cache_key_t key;
+ pair_cache_key_t key;
key.revision = rep->revision;
- key.is_packed = rep->revision < ffd->min_unpacked_rev;
- key.item_index = rep->item_index;
+ key.second = rep->item_index;
/* continue constructing RS and RA */
rs->size = rep->size;
@@ -1130,7 +1141,7 @@ set_cached_window(svn_txdelta_window_t *
* cache. This will be a no-op and IS_CACHED will be set to FALSE if no
* cache has been given. If a cache is available IS_CACHED will inform
* the caller about the success of the lookup. Allocations (of the window
- * in particualar) will be made from POOL.
+ * in particular) will be made from POOL.
*/
static svn_error_t *
get_cached_combined_window(svn_stringbuf_t **window_p,
@@ -1346,7 +1357,8 @@ read_delta_window(svn_txdelta_window_t *
because the block is unlikely to contain other data. */
if ( rs->chunk_index == 0
&& SVN_IS_VALID_REVNUM(rs->revision)
- && svn_fs_fs__use_log_addressing(rs->sfile->fs, rs->revision))
+ && svn_fs_fs__use_log_addressing(rs->sfile->fs, rs->revision)
+ && rs->window_cache)
{
SVN_ERR(block_read(NULL, rs->sfile->fs, rs->revision, rs->item_index,
rs->sfile->rfile, pool, pool));
@@ -2051,9 +2063,10 @@ read_dir_entries(apr_array_header_t *ent
dirent->dirent.id = svn_fs_fs__id_parse(str, strlen(str), result_pool);
/* In incremental mode, update the hash; otherwise, write to the
- * final array. */
+ * final array. Be sure to use hash keys that survive this iteration.
+ */
if (incremental)
- apr_hash_set(hash, entry.key, entry.keylen, dirent);
+ apr_hash_set(hash, dirent->name, entry.keylen, dirent);
else
APR_ARRAY_PUSH(entries, svn_fs_fs__dirent_t *) = dirent;
}
@@ -2440,62 +2453,83 @@ init_rep_state(rep_state_t *rs,
return SVN_NO_ERROR;
}
+/* Implement svn_cache__partial_getter_func_t for txdelta windows.
+ * Instead of the whole window data, return only the
+ * svn_fs_fs__txdelta_cached_window_t wrapper containing the end-offset.
+ */
+static svn_error_t *
+get_window_header(void **out,
+ const void *data,
+ apr_size_t data_len,
+ void *baton,
+ apr_pool_t *result_pool)
+{
+ *out = apr_pmemdup(result_pool, data,
+ sizeof(svn_fs_fs__txdelta_cached_window_t));
+
+ return SVN_NO_ERROR;
+}
+
/* Walk through all windows in the representation addressed by RS in FS
* (excluding the delta bases) and put those not already cached into the
- * window caches. As a side effect, return the total sum of all expanded
- * window sizes in *FULLTEXT_LEN. Use POOL for temporary allocations.
+ * window caches. If MAX_OFFSET is not -1, don't read windows that start
+ * at or beyond that offset. Use POOL for temporary allocations.
*/
static svn_error_t *
-cache_windows(svn_filesize_t *fulltext_len,
- svn_fs_t *fs,
+cache_windows(svn_fs_t *fs,
rep_state_t *rs,
+ apr_off_t max_offset,
apr_pool_t *pool)
{
- *fulltext_len = 0;
-
while (rs->current < rs->size)
{
- svn_txdelta_window_t *window;
- apr_off_t start_offset = rs->start + rs->current;
- apr_off_t end_offset;
+ svn_fs_fs__txdelta_cached_window_t *cached_window;
svn_boolean_t found = FALSE;
- /* We don't need to read the data again, if it is already in cache.
+ if (max_offset != -1 && rs->start + rs->current >= max_offset)
+ return SVN_NO_ERROR;
+
+ /* We don't need to read the data again if it is already in cache.
*/
if (rs->window_cache)
{
- window_cache_key_t key = {0};
- SVN_ERR(svn_cache__has_key(&found, rs->window_cache,
- get_window_key(&key, rs), pool));
+ window_cache_key_t key = { 0 };
+ SVN_ERR(svn_cache__get_partial((void **) &cached_window, &found,
+ rs->window_cache,
+ get_window_key(&key, rs),
+ get_window_header, NULL, pool));
}
- /* navigate to the current window */
- SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, pool));
-
- /* Skip or actually read the window - depending on cache status. */
if (found)
- SVN_ERR(svn_txdelta__read_svndiff_window_sizes(&window,
- rs->sfile->rfile->stream,
- rs->ver, pool));
+ {
+ /* Skip this window; we already have it. */
+ rs->current = cached_window->end_offset;
+ }
else
- SVN_ERR(svn_txdelta_read_svndiff_window(&window,
- rs->sfile->rfile->stream,
- rs->ver, pool));
-
- /* aggregate expanded window size */
- *fulltext_len += window->tview_len;
-
- /* determine on-disk window size */
- SVN_ERR(get_file_offset(&end_offset, rs, pool));
- rs->current = end_offset - rs->start;
+ {
+ /* Read, decode and cache the window. */
+ svn_txdelta_window_t *window;
+ apr_off_t start_offset = rs->start + rs->current;
+ apr_off_t end_offset;
+
+ /* navigate to the current window */
+ SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, pool));
+ SVN_ERR(svn_txdelta_read_svndiff_window(&window,
+ rs->sfile->rfile->stream,
+ rs->ver, pool));
+
+ /* determine on-disk window size */
+ SVN_ERR(get_file_offset(&end_offset, rs, pool));
+ rs->current = end_offset - rs->start;
+
+ /* cache the window now */
+ SVN_ERR(set_cached_window(window, rs, pool));
+ }
+
if (rs->current > rs->size)
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
- _("Reading one svndiff window read beyond "
- "the end of the representation"));
-
- /* cache the window now */
- if (!found)
- SVN_ERR(set_cached_window(window, rs, pool));
+ _("Reading one svndiff window read beyond "
+ "the end of the representation"));
rs->chunk_index++;
}
@@ -2505,7 +2539,8 @@ cache_windows(svn_filesize_t *fulltext_l
/* Read all txdelta / plain windows following REP_HEADER in FS as described
* by ENTRY. Read the data from the already open FILE and the wrapping
- * STREAM object. Use POOL for allocations.
+ * STREAM object. If MAX_OFFSET is not -1, don't read windows that start
+ * at or beyond that offset. Use POOL for allocations.
* If caching is not enabled, this is a no-op.
*/
static svn_error_t *
@@ -2513,6 +2548,7 @@ block_read_windows(svn_fs_fs__rep_header
svn_fs_t *fs,
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t* entry,
+ apr_off_t max_offset,
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
@@ -2557,8 +2593,7 @@ block_read_windows(svn_fs_fs__rep_header
}
else
{
- svn_filesize_t fulltext_len;
- SVN_ERR(cache_windows(&fulltext_len, fs, &rs, pool));
+ SVN_ERR(cache_windows(fs, &rs, max_offset, pool));
}
return SVN_NO_ERROR;
@@ -2573,7 +2608,7 @@ static svn_error_t *
read_rep_header(svn_fs_fs__rep_header_t **rep_header,
svn_fs_t *fs,
svn_stream_t *stream,
- representation_cache_key_t *key,
+ pair_cache_key_t *key,
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
@@ -2598,24 +2633,26 @@ read_rep_header(svn_fs_fs__rep_header_t
/* Fetch the representation data (header, txdelta / plain windows)
* addressed by ENTRY->ITEM in FS and cache it if caches are enabled.
* Read the data from the already open FILE and the wrapping
- * STREAM object. Use POOL for allocations.
+ * STREAM object. If MAX_OFFSET is not -1, don't read windows that start
+ * at or beyond that offset. Use POOL for allocations.
*/
static svn_error_t *
block_read_contents(svn_fs_t *fs,
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t* entry,
+ apr_off_t max_offset,
apr_pool_t *pool)
{
- representation_cache_key_t header_key = { 0 };
+ pair_cache_key_t header_key = { 0 };
svn_fs_fs__rep_header_t *rep_header;
header_key.revision = (apr_int32_t)entry->item.revision;
- header_key.is_packed = svn_fs_fs__is_packed_rev(fs, header_key.revision);
- header_key.item_index = entry->item.number;
+ header_key.second = entry->item.number;
SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key,
pool));
- SVN_ERR(block_read_windows(rep_header, fs, rev_file, entry, pool));
+ SVN_ERR(block_read_windows(rep_header, fs, rev_file, entry, max_offset,
+ pool));
return SVN_NO_ERROR;
}
@@ -2800,7 +2837,7 @@ block_read(void **result,
= svn_fs_fs__p2l_index_lookup(&entries, fs, revision_file,
revision, offset, scratch_pool);
- /* if the revision got packed in the meantime and we still need need
+ /* if the revision got packed in the meantime and we still need
* to actually read some item, we retry the whole process */
if (err &&
revision_file->is_packed != svn_fs_fs__is_packed_rev(fs, revision))
@@ -2823,7 +2860,7 @@ block_read(void **result,
/* read all items from the block */
for (i = 0; i < entries->nelts; ++i)
{
- svn_boolean_t is_result;
+ svn_boolean_t is_result, is_wanted;
apr_pool_t *pool;
svn_fs_fs__p2l_entry_t* entry;
@@ -2835,10 +2872,10 @@ block_read(void **result,
continue;
/* the item / container we were looking for? */
- is_result = result
- && entry->offset == wanted_offset
+ is_wanted = entry->offset == wanted_offset
&& entry->item.revision == revision
&& entry->item.number == item_index;
+ is_result = result && is_wanted;
/* select the pool that we want the item to be allocated in */
pool = is_result ? result_pool : iterpool;
@@ -2859,6 +2896,9 @@ block_read(void **result,
case SVN_FS_FS__ITEM_TYPE_FILE_PROPS:
case SVN_FS_FS__ITEM_TYPE_DIR_PROPS:
SVN_ERR(block_read_contents(fs, revision_file, entry,
+ is_wanted
+ ? -1
+ : block_start + ffd->block_size,
pool));
break;
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/caching.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/caching.c Sun Mar 9 10:08:46 2014
@@ -510,9 +510,9 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
1, 1000, /* ~8 bytes / entry; 1k entries total */
svn_fs_fs__serialize_rep_header,
svn_fs_fs__deserialize_rep_header,
- sizeof(representation_cache_key_t),
+ sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "REPHEADER", SVN_VA_NULL),
- SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
fs,
no_handler,
fs->pool));
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/dag.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/dag.c Sun Mar 9 10:08:46 2014
@@ -1276,29 +1276,40 @@ svn_error_t *
svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
svn_boolean_t *contents_changed,
dag_node_t *node1,
- dag_node_t *node2)
+ dag_node_t *node2,
+ svn_boolean_t strict,
+ apr_pool_t *pool)
{
node_revision_t *noderev1, *noderev2;
+ svn_fs_t *fs;
+ svn_boolean_t same;
/* If we have no place to store our results, don't bother doing
anything. */
if (! props_changed && ! contents_changed)
return SVN_NO_ERROR;
+ fs = svn_fs_fs__dag_get_fs(node1);
+
/* The node revision skels for these two nodes. */
SVN_ERR(get_node_revision(&noderev1, node1));
SVN_ERR(get_node_revision(&noderev2, node2));
/* Compare property keys. */
if (props_changed != NULL)
- *props_changed = (! svn_fs_fs__noderev_same_rep_key(noderev1->prop_rep,
- noderev2->prop_rep));
+ {
+ SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, noderev1, noderev2,
+ strict, pool));
+ *props_changed = !same;
+ }
/* Compare contents keys. */
if (contents_changed != NULL)
- *contents_changed =
- (! svn_fs_fs__noderev_same_rep_key(noderev1->data_rep,
- noderev2->data_rep));
+ {
+ SVN_ERR(svn_fs_fs__file_text_rep_equal(&same, fs, noderev1, noderev2,
+ strict, pool));
+ *contents_changed = !same;
+ }
return SVN_NO_ERROR;
}
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/dag.h?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/dag.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/dag.h Sun Mar 9 10:08:46 2014
@@ -567,27 +567,25 @@ svn_error_t *svn_fs_fs__dag_copy(dag_nod
/* Comparison */
-/* Find out what is the same between two nodes.
+/* Find out what is the same between two nodes. If STRICT is FALSE,
+ this function may report false positives, i.e. report changes even
+ if the resulting contents / props are equal.
If PROPS_CHANGED is non-null, set *PROPS_CHANGED to 1 if the two
nodes have different property lists, or to 0 if same.
If CONTENTS_CHANGED is non-null, set *CONTENTS_CHANGED to 1 if the
- two nodes have different contents, or to 0 if same. For files,
- file contents are compared; for directories, the entries lists are
- compared. If one is a file and the other is a directory, the one's
- contents will be compared to the other's entries list. (Not
- terribly useful, I suppose, but that's the caller's business.)
-
- ### todo: This function only compares rep keys at the moment. This
- may leave us with a slight chance of a false positive, though I
- don't really see how that would happen in practice. Nevertheless,
- it should probably be fixed.
+ two nodes have different contents, or to 0 if same. NODE1 and NODE2
+ must refer to files from the same filesystem.
+
+ Use POOL for temporary allocations.
*/
svn_error_t *svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
svn_boolean_t *contents_changed,
dag_node_t *node1,
- dag_node_t *node2);
+ dag_node_t *node2,
+ svn_boolean_t strict,
+ apr_pool_t *pool);
/* Set *REV and *PATH to the copyroot revision and path of node NODE, or
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs.c Sun Mar 9 10:08:46 2014
@@ -103,8 +103,11 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
SVN_ERR(svn_mutex__init(&ffsd->txn_current_lock,
SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
+ /* We also need a mutex for synchronizing access to the active
+ transaction list and free transaction pointer. This one is
+ enabled unconditionally. */
SVN_ERR(svn_mutex__init(&ffsd->txn_list_lock,
- SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
+ TRUE, common_pool));
key = apr_pstrdup(common_pool, key);
status = apr_pool_userdata_set(ffsd, key, NULL, common_pool);
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs.h?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs.h Sun Mar 9 10:08:46 2014
@@ -55,6 +55,7 @@ extern "C" {
#define PATH_UUID "uuid" /* Contains UUID */
#define PATH_CURRENT "current" /* Youngest revision */
#define PATH_LOCK_FILE "write-lock" /* Revision lock file */
+#define PATH_PACK_LOCK_FILE "pack-lock" /* Pack lock file */
#define PATH_REVS_DIR "revs" /* Directory of revisions */
#define PATH_REVPROPS_DIR "revprops" /* Directory of revprops */
#define PATH_TXNS_DIR "transactions" /* Directory of transactions */
@@ -172,6 +173,9 @@ extern "C" {
/* The minimum format number that supports packed revprops. */
#define SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT 7
+/* Minimum format number that providing a separate lock file for pack ops */
+#define SVN_FS_FS__MIN_PACK_LOCK_FORMAT 7
+
/* Minimum format number that stores mergeinfo-mode flag in changed paths */
#define SVN_FS_FS__MIN_MERGEINFO_IN_CHANGES_FORMAT 7
@@ -255,37 +259,27 @@ typedef struct fs_fs_dag_cache_t fs_fs_d
/* Key type for all caches that use revision + offset / counter as key.
- NOTE: always initialize this using calloc() or '= {0};'! This is used
- as a cache key and the padding bytes on 32 bit archs should be zero for
- cache effectiveness. */
+ Note: Cache keys should be 16 bytes for best performance and there
+ should be no padding. */
typedef struct pair_cache_key_t
{
- svn_revnum_t revision;
+ /* The object's revision. Use the 64 data type to prevent padding. */
+ apr_int64_t revision;
+ /* Sub-address: item index, revprop generation, packed flag, etc. */
apr_int64_t second;
} pair_cache_key_t;
-/* Key type that identifies a representation / rep header. */
-typedef struct representation_cache_key_t
-{
- /* Revision that contains the representation */
- apr_uint32_t revision;
-
- /* Packed or non-packed representation? */
- svn_boolean_t is_packed;
-
- /* Item index of the representation */
- apr_uint64_t item_index;
-} representation_cache_key_t;
+/* Key type that identifies a txdelta window.
-/* Key type that identifies a txdelta window. */
+ Note: Cache keys should require no padding. */
typedef struct window_cache_key_t
{
- /* Revision that contains the representation */
- apr_uint32_t revision;
+ /* The object's revision. Use the 64 data type to prevent padding. */
+ apr_int64_t revision;
- /* Window number within that representation */
- apr_int32_t chunk_index;
+ /* Window number within that representation. */
+ apr_int64_t chunk_index;
/* Item index of the representation */
apr_uint64_t item_index;
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.c Sun Mar 9 10:08:46 2014
@@ -114,9 +114,9 @@ path_lock(svn_fs_t *fs, apr_pool_t *pool
/* Get a lock on empty file LOCK_FILENAME, creating it in POOL. */
-static svn_error_t *
-get_lock_on_filesystem(const char *lock_filename,
- apr_pool_t *pool)
+svn_error_t *
+svn_fs_fs__get_lock_on_filesystem(const char *lock_filename,
+ apr_pool_t *pool)
{
svn_error_t *err = svn_io_file_lock2(lock_filename, TRUE, FALSE, pool);
@@ -160,7 +160,8 @@ with_some_lock_file(svn_fs_t *fs,
apr_pool_t *pool)
{
apr_pool_t *subpool = svn_pool_create(pool);
- svn_error_t *err = get_lock_on_filesystem(lock_filename, subpool);
+ svn_error_t *err = svn_fs_fs__get_lock_on_filesystem(lock_filename,
+ subpool);
if (!err)
{
@@ -1089,25 +1090,131 @@ svn_fs_fs__file_length(svn_filesize_t *l
return SVN_NO_ERROR;
}
-svn_boolean_t
-svn_fs_fs__noderev_same_rep_key(representation_t *a,
- representation_t *b)
-{
- if (a == b)
- return TRUE;
+svn_error_t *
+svn_fs_fs__file_text_rep_equal(svn_boolean_t *equal,
+ svn_fs_t *fs,
+ node_revision_t *a,
+ node_revision_t *b,
+ svn_boolean_t strict,
+ apr_pool_t *scratch_pool)
+{
+ svn_stream_t *contents_a, *contents_b;
+ representation_t *rep_a = a->data_rep;
+ representation_t *rep_b = b->data_rep;
+ svn_boolean_t a_empty = !rep_a || rep_a->expanded_size == 0;
+ svn_boolean_t b_empty = !rep_b || rep_b->expanded_size == 0;
+
+ /* This makes sure that neither rep will be NULL later on */
+ if (a_empty && b_empty)
+ {
+ *equal = TRUE;
+ return SVN_NO_ERROR;
+ }
+
+ if (a_empty != b_empty)
+ {
+ *equal = FALSE;
+ return SVN_NO_ERROR;
+ }
+
+ /* File text representations always know their checksums - even in a txn. */
+ if (memcmp(rep_a->md5_digest, rep_b->md5_digest, sizeof(rep_a->md5_digest)))
+ {
+ *equal = FALSE;
+ return SVN_NO_ERROR;
+ }
+
+ /* Paranoia. Compare SHA1 checksums because that's the level of
+ confidence we require for e.g. the working copy. */
+ if (rep_a->has_sha1 && rep_b->has_sha1)
+ {
+ *equal = memcmp(rep_a->sha1_digest, rep_b->sha1_digest,
+ sizeof(rep_a->sha1_digest)) == 0;
+ return SVN_NO_ERROR;
+ }
+
+ /* Same path in same rev or txn? */
+ if (svn_fs_fs__id_eq(a->id, b->id))
+ {
+ *equal = TRUE;
+ return SVN_NO_ERROR;
+ }
+
+ /* Old repositories may not have the SHA1 checksum handy.
+ This check becomes expensive. Skip it unless explicitly required. */
+ if (!strict)
+ {
+ *equal = TRUE;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_fs_fs__get_contents(&contents_a, fs, rep_a, TRUE,
+ scratch_pool));
+ SVN_ERR(svn_fs_fs__get_contents(&contents_b, fs, rep_b, TRUE,
+ scratch_pool));
+ SVN_ERR(svn_stream_contents_same2(equal, contents_a, contents_b,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__prop_rep_equal(svn_boolean_t *equal,
+ svn_fs_t *fs,
+ node_revision_t *a,
+ node_revision_t *b,
+ svn_boolean_t strict,
+ apr_pool_t *scratch_pool)
+{
+ representation_t *rep_a = a->prop_rep;
+ representation_t *rep_b = b->prop_rep;
+ apr_hash_t *proplist_a;
+ apr_hash_t *proplist_b;
+
+ /* Mainly for a==b==NULL */
+ if (rep_a == rep_b)
+ {
+ *equal = TRUE;
+ return SVN_NO_ERROR;
+ }
- if (a == NULL || b == NULL)
- return FALSE;
+ /* Committed property lists can be compared quickly */
+ if ( rep_a && rep_b
+ && !svn_fs_fs__id_txn_used(&rep_a->txn_id)
+ && !svn_fs_fs__id_txn_used(&rep_b->txn_id))
+ {
+ /* MD5 must be given. Having the same checksum is good enough for
+ accepting the prop lists as equal. */
+ *equal = memcmp(rep_a->md5_digest, rep_b->md5_digest,
+ sizeof(rep_a->md5_digest)) == 0;
+ return SVN_NO_ERROR;
+ }
- if (a->item_index != b->item_index)
- return FALSE;
+ /* Same path in same txn? */
+ if (svn_fs_fs__id_eq(a->id, b->id))
+ {
+ *equal = TRUE;
+ return SVN_NO_ERROR;
+ }
- if (a->revision != b->revision)
- return FALSE;
+ /* Skip the expensive bits unless we are in strict mode.
+ Simply assume that there is a difference. */
+ if (!strict)
+ {
+ *equal = FALSE;
+ return SVN_NO_ERROR;
+ }
- return memcmp(&a->uniquifier, &b->uniquifier, sizeof(a->uniquifier)) == 0;
+ /* At least one of the reps has been modified in a txn.
+ Fetch and compare them. */
+ SVN_ERR(svn_fs_fs__get_proplist(&proplist_a, fs, a, scratch_pool));
+ SVN_ERR(svn_fs_fs__get_proplist(&proplist_b, fs, b, scratch_pool));
+
+ *equal = svn_fs__prop_lists_equal(proplist_a, proplist_b, scratch_pool);
+ return SVN_NO_ERROR;
}
+
svn_error_t *
svn_fs_fs__file_checksum(svn_checksum_t **checksum,
node_revision_t *noderev,
@@ -1207,9 +1314,9 @@ write_revision_zero(svn_fs_t *fs)
"\x80\x80\4\1\x1D" /* 64k pages, 1 page using 29 bytes */
"\0" /* offset entry 0 page 1 */
/* len, item & type, rev, checksum */
- "\x11\x34\0\xe0\xc6\xac\xa9\x07"
- "\x59\x09\0\xc0\xfa\xf8\xc5\x04"
- "\1\x0d\0\xf2\x95\xbe\xea\x01"
+ "\x11\x34\0\xf5\xd6\x8c\x81\x06"
+ "\x59\x09\0\xc8\xfc\xf6\x81\x04"
+ "\1\x0d\0\x9d\x9e\xa9\x94\x0f"
"\x95\xff\3\x1b\0\0", /* last entry fills up 64k page */
38,
fs->pool));
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.h?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.h Sun Mar 9 10:08:46 2014
@@ -65,10 +65,29 @@ svn_error_t *svn_fs_fs__file_length(svn_
node_revision_t *noderev,
apr_pool_t *pool);
-/* Return TRUE if the representation keys in A and B both point to the
- same representation, else return FALSE. */
-svn_boolean_t svn_fs_fs__noderev_same_rep_key(representation_t *a,
- representation_t *b);
+/* Set *EQUAL to TRUE if the text representations in A and B within FS
+ have equal contents, else set it to FALSE. If STRICT is not set, allow
+ for false negatives.
+ Use SCRATCH_POOL for temporary allocations. */
+svn_error_t *
+svn_fs_fs__file_text_rep_equal(svn_boolean_t *equal,
+ svn_fs_t *fs,
+ node_revision_t *a,
+ node_revision_t *b,
+ svn_boolean_t strict,
+ apr_pool_t *scratch_pool);
+
+/* Set *EQUAL to TRUE if the property representations in A and B within FS
+ have equal contents, else set it to FALSE. If STRICT is not set, allow
+ for false negatives.
+ Use SCRATCH_POOL for temporary allocations. */
+svn_error_t *
+svn_fs_fs__prop_rep_equal(svn_boolean_t *equal,
+ svn_fs_t *fs,
+ node_revision_t *a,
+ node_revision_t *b,
+ svn_boolean_t strict,
+ apr_pool_t *scratch_pool);
/* Return a copy of the representation REP allocated from POOL. */
@@ -117,6 +136,12 @@ svn_fs_fs__write_format(svn_fs_t *fs,
svn_boolean_t overwrite,
apr_pool_t *pool);
+/* Get a lock on empty file LOCK_FILENAME, creating it in POOL;
+ releasing the lock upon POOL cleanup. */
+svn_error_t *
+svn_fs_fs__get_lock_on_filesystem(const char *lock_filename,
+ apr_pool_t *pool);
+
/* Obtain a write lock on the filesystem FS in a subpool of POOL, call
BODY with BATON and that subpool, destroy the subpool (releasing the write
lock) and return what BODY returned. */
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/hotcopy.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/hotcopy.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/hotcopy.c Sun Mar 9 10:08:46 2014
@@ -382,12 +382,6 @@ hotcopy_update_current(svn_revnum_t *dst
/* If necessary, get new current next_node and next_copy IDs. */
if (dst_ffd->format < SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT)
{
- /* Make sure NEW_YOUNGEST is a valid revision in DST_FS.
- Because a crash in hotcopy requires at least a full recovery run,
- it is safe to temporarily reset the max IDs to 0. */
- SVN_ERR(svn_fs_fs__write_current(dst_fs, new_youngest, next_node_id,
- next_copy_id, scratch_pool));
-
SVN_ERR(svn_fs_fs__find_max_ids(dst_fs, new_youngest,
&next_node_id, &next_copy_id,
scratch_pool));
@@ -586,7 +580,7 @@ struct hotcopy_body_baton {
svn_boolean_t incremental;
svn_cancel_func_t cancel_func;
void *cancel_baton;
-} hotcopy_body_baton;
+};
/* Perform a hotcopy, either normal or incremental.
*
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.c Sun Mar 9 10:08:46 2014
@@ -317,13 +317,14 @@ svn_fs_fs__id_check_related(const svn_fs
}
-int
+svn_fs_node_relation_t
svn_fs_fs__id_compare(const svn_fs_id_t *a,
const svn_fs_id_t *b)
{
if (svn_fs_fs__id_eq(a, b))
- return 0;
- return (svn_fs_fs__id_check_related(a, b) ? 1 : -1);
+ return svn_fs_node_same;
+ return (svn_fs_fs__id_check_related(a, b) ? svn_fs_node_common_ancestor
+ : svn_fs_node_unrelated);
}
int
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.h?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.h Sun Mar 9 10:08:46 2014
@@ -114,9 +114,9 @@ svn_boolean_t svn_fs_fs__id_eq(const svn
svn_boolean_t svn_fs_fs__id_check_related(const svn_fs_id_t *a,
const svn_fs_id_t *b);
-/* Return 0 if A and B are equal, 1 if they are related, -1 otherwise. */
-int svn_fs_fs__id_compare(const svn_fs_id_t *a,
- const svn_fs_id_t *b);
+/* Return the noderev relationship between A and B. */
+svn_fs_node_relation_t svn_fs_fs__id_compare(const svn_fs_id_t *a,
+ const svn_fs_id_t *b);
/* Return 0 if A and B are equal, 1 if A is "greater than" B, -1 otherwise. */
int svn_fs_fs__id_part_compare(const svn_fs_fs__id_part_t *a,
Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/index.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/index.c?rev=1575685&r1=1575684&r2=1575685&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/index.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/index.c Sun Mar 9 10:08:46 2014
@@ -71,7 +71,7 @@ typedef struct l2p_header_t
apr_size_t revision_count;
/* (max) number of entries per page */
- apr_size_t page_size;
+ apr_uint32_t page_size;
/* indexes into PAGE_TABLE that mark the first page of the respective
* revision. PAGE_TABLE_INDEX[REVISION_COUNT] points to the end of
@@ -96,7 +96,7 @@ typedef struct l2p_page_t
apr_uint64_t *offsets;
} l2p_page_t;
-/* All of the log-to-phys proto index file consist of entires of this type.
+/* All of the log-to-phys proto index file consist of entries of this type.
*/
typedef struct l2p_proto_entry_t
{
@@ -297,7 +297,7 @@ packed_stream_read(svn_fs_fs__packed_num
stream->current = 0;
return SVN_NO_ERROR;
-};
+}
/* Create and open a packed number stream reading from FILE_NAME and
* return it in *STREAM. Access the file in chunks of BLOCK_SIZE bytes.
@@ -587,6 +587,14 @@ svn_fs_fs__l2p_index_create(svn_fs_t *fs
svn_spillbuf_t *buffer
= svn_spillbuf__create(0x10000, 0x1000000, local_pool);
+ /* Paranoia check that makes later casting to int32 safe.
+ * The current implementation is limited to 2G entries per page. */
+ if (ffd->l2p_page_size > APR_INT32_MAX)
+ return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+ _("L2P index page size %" APR_UINT64_T_FMT
+ " exceeds current limit of 2G entries"),
+ ffd->l2p_page_size);
+
/* start at the beginning of the source file */
SVN_ERR(svn_io_file_open(&proto_index, proto_file_name,
APR_READ | APR_CREATE | APR_BUFFERED,
@@ -617,7 +625,9 @@ svn_fs_fs__l2p_index_create(svn_fs_t *fs
svn_pool_clear(iterpool);
- entry_count = MIN(entries->nelts - i, ffd->l2p_page_size);
+ entry_count = ffd->l2p_page_size < entries->nelts - i
+ ? (int)ffd->l2p_page_size
+ : entries->nelts - i;
SVN_ERR(encode_l2p_page(entries, i, i + entry_count,
buffer, iterpool));
@@ -636,8 +646,18 @@ svn_fs_fs__l2p_index_create(svn_fs_t *fs
}
else
{
+ int idx;
+
/* store the mapping in our array */
- int idx = (apr_size_t)proto_entry.item_index;
+ if (proto_entry.item_index > APR_INT32_MAX)
+ return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+ _("Item index %" APR_UINT64_T_FMT
+ " too large in l2p proto index for"
+ " revision %ld"),
+ proto_entry.item_index,
+ revision + page_counts->nelts);
+
+ idx = (int)proto_entry.item_index;
while (idx >= entries->nelts)
APR_ARRAY_PUSH(entries, apr_uint64_t) = 0;
@@ -651,6 +671,14 @@ svn_fs_fs__l2p_index_create(svn_fs_t *fs
/* create the target file */
SVN_ERR(index_create(&index_file, file_name, local_pool));
+ /* Paranoia check that makes later casting to int32 safe.
+ * The current implementation is limited to 2G pages per index. */
+ if (page_counts->nelts > APR_INT32_MAX)
+ return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+ _("L2P index page count %d"
+ " exceeds current limit of 2G pages"),
+ page_counts->nelts);
+
/* write header info */
SVN_ERR(svn_io_file_write_full(index_file, encoded,
encode_uint(encoded, revision),
@@ -782,7 +810,7 @@ get_l2p_header_body(l2p_header_t **heade
SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
result->first_revision = (svn_revnum_t)value;
SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
- result->page_size = (apr_size_t)value;
+ result->page_size = (apr_uint32_t)value;
SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
result->revision_count = (int)value;
SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
@@ -851,7 +879,7 @@ typedef struct l2p_page_info_baton_t
l2p_page_table_entry_t entry;
/* page number within the pages for REVISION (not l2p index global!) */
- apr_size_t page_no;
+ apr_uint32_t page_no;
/* offset of ITEM_INDEX within that page */
apr_uint32_t page_offset;
@@ -882,7 +910,7 @@ l2p_page_info_copy(l2p_page_info_baton_t
if (baton->item_index < header->page_size)
{
/* most revs fit well into a single page */
- baton->page_offset = (apr_size_t)baton->item_index;
+ baton->page_offset = (apr_uint32_t)baton->item_index;
baton->page_no = 0;
baton->entry = page_table[page_table_index[rel_revision]];
}
@@ -890,29 +918,28 @@ l2p_page_info_copy(l2p_page_info_baton_t
{
const l2p_page_table_entry_t *first_entry;
const l2p_page_table_entry_t *last_entry;
-
- /* all pages are of the same size and full, except for the last one */
- baton->page_offset = (apr_size_t)(baton->item_index % header->page_size);
- baton->page_no = (apr_uint32_t)(baton->item_index / header->page_size);
+ apr_uint64_t max_item_index;
/* range of pages for this rev */
first_entry = page_table + page_table_index[rel_revision];
last_entry = page_table + page_table_index[rel_revision + 1];
- if (last_entry - first_entry > baton->page_no)
- {
- baton->entry = first_entry[baton->page_no];
- }
- else
- {
- /* limit page index to the valid range */
- baton->entry = last_entry[-1];
+ /* do we hit a valid index page? */
+ max_item_index = (apr_uint64_t)header->page_size
+ * (last_entry - first_entry);
+ if (baton->item_index >= max_item_index)
+ return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
+ _("Item index %" APR_UINT64_T_FMT
+ " exceeds l2p limit of %" APR_UINT64_T_FMT
+ " for revision %ld"),
+ baton->item_index, max_item_index,
+ baton->revision);
- /* cause index overflow further down the road */
- baton->page_offset = header->page_size + 1;
- }
+ /* all pages are of the same size and full, except for the last one */
+ baton->page_offset = (apr_uint32_t)(baton->item_index % header->page_size);
+ baton->page_no = (apr_uint32_t)(baton->item_index / header->page_size);
}
-
+
baton->first_revision = header->first_revision;
return SVN_NO_ERROR;