summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_fs
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-04-29 19:16:59 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-04-29 19:16:59 +0000
commitc94cceea9c2262c5b2ad5f215bb9a8ae48b02764 (patch)
treedbb8174cbf6f1cc45b8de8031b18adb4030509a8 /subversion/libsvn_fs_fs
parentdc5d469d6574e9fb03bdd793658bb371315b306a (diff)
Notes
Diffstat (limited to 'subversion/libsvn_fs_fs')
-rw-r--r--subversion/libsvn_fs_fs/cached_data.c8
-rw-r--r--subversion/libsvn_fs_fs/dag.c54
-rw-r--r--subversion/libsvn_fs_fs/fs.h12
-rw-r--r--subversion/libsvn_fs_fs/fs_fs.c86
-rw-r--r--subversion/libsvn_fs_fs/fs_fs.h13
-rw-r--r--subversion/libsvn_fs_fs/rep-cache-db.h2
-rw-r--r--subversion/libsvn_fs_fs/transaction.c3
-rw-r--r--subversion/libsvn_fs_fs/tree.c4
8 files changed, 98 insertions, 84 deletions
diff --git a/subversion/libsvn_fs_fs/cached_data.c b/subversion/libsvn_fs_fs/cached_data.c
index 1618f07d40a5..948870e6be1a 100644
--- a/subversion/libsvn_fs_fs/cached_data.c
+++ b/subversion/libsvn_fs_fs/cached_data.c
@@ -2558,8 +2558,12 @@ svn_fs_fs__rep_contents_dir(apr_array_header_t **entries_p,
SVN_ERR(get_dir_contents(entries_p, fs, noderev, result_pool,
scratch_pool));
- /* Update the cache, if we are to use one. */
- if (cache)
+ /* Update the cache, if we are to use one.
+ *
+ * Don't even attempt to serialize very large directories; it would cause
+ * an unnecessary memory allocation peak. 150 bytes/entry is about right.
+ */
+ if (cache && svn_cache__is_cachable(cache, 150 * (*entries_p)->nelts))
SVN_ERR(svn_cache__set(cache, key, *entries_p, scratch_pool));
return SVN_NO_ERROR;
diff --git a/subversion/libsvn_fs_fs/dag.c b/subversion/libsvn_fs_fs/dag.c
index 78d1b23e3583..d21c17c4b9aa 100644
--- a/subversion/libsvn_fs_fs/dag.c
+++ b/subversion/libsvn_fs_fs/dag.c
@@ -1307,34 +1307,58 @@ svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
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)
+ if (strict)
{
- SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, noderev1, noderev2,
- strict, pool));
- *props_changed = !same;
- }
+ /* In strict mode, compare text and property representations in the
+ svn_fs_contents_different() / svn_fs_props_different() manner.
- /* Compare contents keys. */
- if (contents_changed != NULL)
+ See the "No-op changes no longer dumped by 'svnadmin dump' in 1.9"
+ discussion (http://svn.haxx.se/dev/archive-2015-09/0269.shtml) and
+ issue #4598 (https://issues.apache.org/jira/browse/SVN-4598). */
+ svn_fs_t *fs = svn_fs_fs__dag_get_fs(node1);
+ svn_boolean_t same;
+
+ /* Compare property keys. */
+ if (props_changed != NULL)
+ {
+ SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, noderev1,
+ noderev2, pool));
+ *props_changed = !same;
+ }
+
+ /* Compare contents keys. */
+ if (contents_changed != NULL)
+ {
+ SVN_ERR(svn_fs_fs__file_text_rep_equal(&same, fs, noderev1,
+ noderev2, pool));
+ *contents_changed = !same;
+ }
+ }
+ else
{
- SVN_ERR(svn_fs_fs__file_text_rep_equal(&same, fs, noderev1, noderev2,
- strict, pool));
- *contents_changed = !same;
+ /* Otherwise, compare representation keys -- as in Subversion 1.8. */
+
+ /* Compare property keys. */
+ if (props_changed != NULL)
+ *props_changed =
+ !svn_fs_fs__noderev_same_rep_key(noderev1->prop_rep,
+ noderev2->prop_rep);
+
+ /* Compare contents keys. */
+ if (contents_changed != NULL)
+ *contents_changed =
+ !svn_fs_fs__noderev_same_rep_key(noderev1->data_rep,
+ noderev2->data_rep);
}
return SVN_NO_ERROR;
diff --git a/subversion/libsvn_fs_fs/fs.h b/subversion/libsvn_fs_fs/fs.h
index 221db1a17c12..c75eafbd5c09 100644
--- a/subversion/libsvn_fs_fs/fs.h
+++ b/subversion/libsvn_fs_fs/fs.h
@@ -478,10 +478,6 @@ typedef struct fs_fs_data_t
/*** Filesystem Transaction ***/
typedef struct transaction_t
{
- /* property list (const char * name, svn_string_t * value).
- may be NULL if there are no properties. */
- apr_hash_t *proplist;
-
/* node revision id of the root node. */
const svn_fs_id_t *root_id;
@@ -536,13 +532,7 @@ typedef struct representation_t
/* For rep-sharing, we need a way of uniquifying node-revs which share the
same representation (see svn_fs_fs__noderev_same_rep_key() ). So, we
store the original txn of the node rev (not the rep!), along with some
- intra-node uniqification content.
-
- This is no longer used by the 1.9 code but we have to keep
- reading and writing it for old formats to remain compatible with
- 1.8, and earlier, that require it. We also read/write it in
- format 7 even though it is not currently required by any code
- that handles that format. */
+ intra-node uniqification content. */
struct
{
/* unique context, i.e. txn ID, in which the noderev (!) got created */
diff --git a/subversion/libsvn_fs_fs/fs_fs.c b/subversion/libsvn_fs_fs/fs_fs.c
index c2eaf5c04d48..1d32672b87f9 100644
--- a/subversion/libsvn_fs_fs/fs_fs.c
+++ b/subversion/libsvn_fs_fs/fs_fs.c
@@ -1414,19 +1414,37 @@ svn_fs_fs__file_length(svn_filesize_t *length,
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;
+
+ if (a == NULL || b == NULL)
+ return FALSE;
+
+ if (a->item_index != b->item_index)
+ return FALSE;
+
+ if (a->revision != b->revision)
+ return FALSE;
+
+ return memcmp(&a->uniquifier, &b->uniquifier, sizeof(a->uniquifier)) == 0;
+}
+
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;
+ svn_boolean_t a_empty = !rep_a;
+ svn_boolean_t b_empty = !rep_b;
/* This makes sure that neither rep will be NULL later on */
if (a_empty && b_empty)
@@ -1435,28 +1453,6 @@ svn_fs_fs__file_text_rep_equal(svn_boolean_t *equal,
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))
{
@@ -1464,17 +1460,28 @@ svn_fs_fs__file_text_rep_equal(svn_boolean_t *equal,
return SVN_NO_ERROR;
}
- /* Old repositories may not have the SHA1 checksum handy.
- This check becomes expensive. Skip it unless explicitly required.
-
- We already have seen that the ID is different, so produce a likely
- false negative as allowed by the API description - even though the
- MD5 matched, there is an extremely slim chance that the SHA1 wouldn't.
- */
- if (!strict)
+ /* Beware of the combination NULL rep and possibly empty rep.
+ * Due to EXPANDED_SIZE not being reliable, we can't easily detect empty
+ * reps. So, we can only take further shortcuts if both reps are given. */
+ 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;
+ }
}
SVN_ERR(svn_fs_fs__get_contents(&contents_a, fs, rep_a, TRUE,
@@ -1492,7 +1499,6 @@ 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;
@@ -1526,14 +1532,6 @@ svn_fs_fs__prop_rep_equal(svn_boolean_t *equal,
return SVN_NO_ERROR;
}
- /* 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;
- }
-
/* 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));
diff --git a/subversion/libsvn_fs_fs/fs_fs.h b/subversion/libsvn_fs_fs/fs_fs.h
index 1be993a931bd..b6c94c7e7ff3 100644
--- a/subversion/libsvn_fs_fs/fs_fs.h
+++ b/subversion/libsvn_fs_fs/fs_fs.h
@@ -81,28 +81,29 @@ svn_error_t *svn_fs_fs__file_length(svn_filesize_t *length,
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.
+ have equal contents, else set it to FALSE.
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.
+ have equal contents, else set it to FALSE.
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);
diff --git a/subversion/libsvn_fs_fs/rep-cache-db.h b/subversion/libsvn_fs_fs/rep-cache-db.h
index 037585964994..56692c92e6d0 100644
--- a/subversion/libsvn_fs_fs/rep-cache-db.h
+++ b/subversion/libsvn_fs_fs/rep-cache-db.h
@@ -1,4 +1,4 @@
-/* This file is automatically generated from rep-cache-db.sql and .dist_sandbox/subversion-1.9.2/subversion/libsvn_fs_fs/token-map.h.
+/* This file is automatically generated from rep-cache-db.sql and .dist_sandbox/subversion-1.9.4/subversion/libsvn_fs_fs/token-map.h.
* Do not edit this file -- edit the source and rerun gen-make.py */
#define STMT_CREATE_SCHEMA 0
diff --git a/subversion/libsvn_fs_fs/transaction.c b/subversion/libsvn_fs_fs/transaction.c
index c6b2d25c251b..3968c6fa5deb 100644
--- a/subversion/libsvn_fs_fs/transaction.c
+++ b/subversion/libsvn_fs_fs/transaction.c
@@ -1247,9 +1247,6 @@ svn_fs_fs__get_txn(transaction_t **txn_p,
svn_fs_id_t *root_id;
txn = apr_pcalloc(pool, sizeof(*txn));
- txn->proplist = apr_hash_make(pool);
-
- SVN_ERR(get_txn_proplist(txn->proplist, fs, txn_id, pool));
root_id = svn_fs_fs__id_txn_create_root(txn_id, pool);
SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, root_id, pool, pool));
diff --git a/subversion/libsvn_fs_fs/tree.c b/subversion/libsvn_fs_fs/tree.c
index 66de1f8ca313..0047bef251fc 100644
--- a/subversion/libsvn_fs_fs/tree.c
+++ b/subversion/libsvn_fs_fs/tree.c
@@ -1900,13 +1900,13 @@ merge(svn_stringbuf_t *conflict_p,
/* Now compare the prop-keys of the skels. Note that just because
the keys are different -doesn't- mean the proplists have
different contents. */
- SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, src_nr, anc_nr, TRUE, pool));
+ SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, src_nr, anc_nr, pool));
if (! same)
return conflict_err(conflict_p, target_path);
/* The directory entries got changed in the repository but the directory
properties did not. */
- SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, tgt_nr, anc_nr, TRUE, pool));
+ SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, tgt_nr, anc_nr, pool));
if (! same)
{
/* There is an incoming prop change for this directory.