aboutsummaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_x/dag.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
committerPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
commit3faf8d6bffc5d0fb2525ba37bb504c53366caf9d (patch)
tree7e47911263e75034b767fe34b2f8d3d17e91f66d /subversion/libsvn_fs_x/dag.c
parenta55fb3c0d5eca7d887798125d5b95942b1f01d4b (diff)
Import Subversion-1.10.0vendor/subversion/subversion-1.10.0
Notes
Notes: svn path=/vendor/subversion/dist/; revision=333347 svn path=/vendor/subversion/subversion-1.10.0/; revision=333348; tag=vendor/subversion/subversion-1.10.0
Diffstat (limited to 'subversion/libsvn_fs_x/dag.c')
-rw-r--r--subversion/libsvn_fs_x/dag.c603
1 files changed, 159 insertions, 444 deletions
diff --git a/subversion/libsvn_fs_x/dag.c b/subversion/libsvn_fs_x/dag.c
index 2f5bcb260a6c..5656dbe60034 100644
--- a/subversion/libsvn_fs_x/dag.c
+++ b/subversion/libsvn_fs_x/dag.c
@@ -1,4 +1,4 @@
-/* dag.c : DAG-like interface filesystem, private to libsvn_fs
+/* dag.c : DAG-like interface filesystem
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
@@ -41,6 +41,7 @@
#include "svn_private_config.h"
#include "private/svn_temp_serializer.h"
#include "temp_serializer.h"
+#include "dag_cache.h"
/* Initializing a filesystem. */
@@ -50,34 +51,12 @@ struct dag_node_t
/* The filesystem this dag node came from. */
svn_fs_t *fs;
- /* The node revision ID for this dag node. */
- svn_fs_x__id_t id;
-
- /* In the special case that this node is the root of a transaction
- that has not yet been modified, the revision of this node is the
- respective txn's base rev. Otherwise, this is SVN_INVALID_REVNUM
- for txn nodes and the respective crev for committed nodes.
- (Used in svn_fs_node_created_rev.) */
- svn_revnum_t revision;
-
- /* The node's type (file, dir, etc.) */
- svn_node_kind_t kind;
-
- /* The node's NODE-REVISION, or NULL if we haven't read it in yet.
- This is allocated in this node's POOL.
-
- If you're willing to respect all the rules above, you can munge
- this yourself, but you're probably better off just calling
- `get_node_revision' and `set_node_revision', which take care of
- things for you. */
+ /* The node's NODE-REVISION. */
svn_fs_x__noderev_t *node_revision;
/* The pool to allocate NODE_REVISION in. */
apr_pool_t *node_pool;
- /* the path at which this node was created. */
- const char *created_path;
-
/* Directory entry lookup hint to speed up consecutive calls to
svn_fs_x__rep_contents_dir_entry(). Only used for directory nodes.
Any value is legal but should default to APR_SIZE_MAX. */
@@ -90,20 +69,20 @@ struct dag_node_t
svn_node_kind_t
svn_fs_x__dag_node_kind(dag_node_t *node)
{
- return node->kind;
+ return node->node_revision->kind;
}
const svn_fs_x__id_t *
svn_fs_x__dag_get_id(const dag_node_t *node)
{
- return &node->id;
+ return &node->node_revision->noderev_id;
}
const char *
svn_fs_x__dag_get_created_path(dag_node_t *node)
{
- return node->created_path;
+ return node->node_revision->created_path;
}
@@ -144,94 +123,35 @@ copy_node_revision(svn_fs_x__noderev_t *noderev,
}
-/* Set *NODEREV_P to the cached node-revision for NODE.
- If the node-revision was not already cached in NODE, read it in,
- allocating the cache in NODE->NODE_POOL.
-
- If you plan to change the contents of NODE, be careful! We're
- handing you a pointer directly to our cached node-revision, not
- your own copy. If you change it as part of some operation, but
- then some Berkeley DB function deadlocks or gets an error, you'll
- need to back out your changes, or else the cache will reflect
- changes that never got committed. It's probably best not to change
- the structure at all. */
-static svn_error_t *
-get_node_revision(svn_fs_x__noderev_t **noderev_p,
- dag_node_t *node)
-{
- /* If we've already got a copy, there's no need to read it in. */
- if (! node->node_revision)
- {
- svn_fs_x__noderev_t *noderev;
- apr_pool_t *scratch_pool = svn_pool_create(node->node_pool);
-
- SVN_ERR(svn_fs_x__get_node_revision(&noderev, node->fs, &node->id,
- node->node_pool, scratch_pool));
- node->node_revision = noderev;
- svn_pool_destroy(scratch_pool);
- }
-
- /* Now NODE->node_revision is set. */
- *noderev_p = node->node_revision;
- return SVN_NO_ERROR;
-}
-
-/* Return the node revision ID of NODE. The value returned is shared
- with NODE, and will be deallocated when NODE is. */
-svn_error_t *
-svn_fs_x__dag_get_node_id(svn_fs_x__id_t *node_id,
- dag_node_t *node)
+const svn_fs_x__id_t *
+svn_fs_x__dag_get_node_id(dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
- SVN_ERR(get_node_revision(&noderev, node));
-
- *node_id = noderev->node_id;
- return SVN_NO_ERROR;
+ return &node->node_revision->node_id;
}
-/* Return the node revision ID of NODE. The value returned is shared
- with NODE, and will be deallocated when NODE is. */
-svn_error_t *
-svn_fs_x__dag_get_copy_id(svn_fs_x__id_t *copy_id,
- dag_node_t *node)
+const svn_fs_x__id_t *
+svn_fs_x__dag_get_copy_id(dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
- SVN_ERR(get_node_revision(&noderev, node));
-
- *copy_id = noderev->copy_id;
- return SVN_NO_ERROR;
+ return &node->node_revision->copy_id;
}
-/* Return the node ID of NODE. The value returned is shared with NODE,
- and will be deallocated when NODE is. */
-svn_error_t *
-svn_fs_x__dag_related_node(svn_boolean_t *same,
- dag_node_t *lhs,
+svn_boolean_t
+svn_fs_x__dag_related_node(dag_node_t *lhs,
dag_node_t *rhs)
{
- svn_fs_x__id_t lhs_node, rhs_node;
-
- SVN_ERR(svn_fs_x__dag_get_node_id(&lhs_node, lhs));
- SVN_ERR(svn_fs_x__dag_get_node_id(&rhs_node, rhs));
- *same = svn_fs_x__id_eq(&lhs_node, &rhs_node);
-
- return SVN_NO_ERROR;
+ return svn_fs_x__id_eq(&lhs->node_revision->node_id,
+ &rhs->node_revision->node_id);
}
-svn_error_t *
-svn_fs_x__dag_same_line_of_history(svn_boolean_t *same,
- dag_node_t *lhs,
+svn_boolean_t
+svn_fs_x__dag_same_line_of_history(dag_node_t *lhs,
dag_node_t *rhs)
{
- svn_fs_x__noderev_t *lhs_noderev, *rhs_noderev;
+ svn_fs_x__noderev_t *lhs_noderev = lhs->node_revision;
+ svn_fs_x__noderev_t *rhs_noderev = rhs->node_revision;
- SVN_ERR(get_node_revision(&lhs_noderev, lhs));
- SVN_ERR(get_node_revision(&rhs_noderev, rhs));
-
- *same = svn_fs_x__id_eq(&lhs_noderev->node_id, &rhs_noderev->node_id)
- && svn_fs_x__id_eq(&lhs_noderev->copy_id, &rhs_noderev->copy_id);
-
- return SVN_NO_ERROR;
+ return svn_fs_x__id_eq(&lhs_noderev->node_id, &rhs_noderev->node_id)
+ && svn_fs_x__id_eq(&lhs_noderev->copy_id, &rhs_noderev->copy_id);
}
svn_boolean_t
@@ -240,7 +160,6 @@ svn_fs_x__dag_check_mutable(const dag_node_t *node)
return svn_fs_x__is_txn(svn_fs_x__dag_get_id(node)->change_set);
}
-
svn_error_t *
svn_fs_x__dag_get_node(dag_node_t **node,
svn_fs_t *fs,
@@ -254,7 +173,6 @@ svn_fs_x__dag_get_node(dag_node_t **node,
/* Construct the node. */
new_node = apr_pcalloc(result_pool, sizeof(*new_node));
new_node->fs = fs;
- new_node->id = *id;
new_node->hint = APR_SIZE_MAX;
/* Grab the contents so we can inspect the node's kind and created path. */
@@ -263,17 +181,6 @@ svn_fs_x__dag_get_node(dag_node_t **node,
new_node->node_pool = result_pool;
new_node->node_revision = noderev;
- /* Initialize the KIND and CREATED_PATH attributes */
- new_node->kind = noderev->kind;
- new_node->created_path = noderev->created_path;
-
- /* Support our quirky svn_fs_node_created_rev API.
- Untouched txn roots report the base rev as theirs. */
- new_node->revision
- = ( svn_fs_x__is_fresh_txn_root(noderev)
- ? svn_fs_x__get_revnum(noderev->predecessor_id.change_set)
- : svn_fs_x__get_revnum(id->change_set));
-
/* Return a fresh new node */
*node = new_node;
return SVN_NO_ERROR;
@@ -283,76 +190,50 @@ svn_fs_x__dag_get_node(dag_node_t **node,
svn_revnum_t
svn_fs_x__dag_get_revision(const dag_node_t *node)
{
- return node->revision;
+ svn_fs_x__noderev_t *noderev = node->node_revision;
+ return ( svn_fs_x__is_fresh_txn_root(noderev)
+ ? svn_fs_x__get_revnum(noderev->predecessor_id.change_set)
+ : svn_fs_x__get_revnum(noderev->noderev_id.change_set));
}
-
-svn_error_t *
-svn_fs_x__dag_get_predecessor_id(svn_fs_x__id_t *id_p,
- dag_node_t *node)
+const svn_fs_x__id_t *
+svn_fs_x__dag_get_predecessor_id(dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
-
- SVN_ERR(get_node_revision(&noderev, node));
- *id_p = noderev->predecessor_id;
-
- return SVN_NO_ERROR;
+ return &node->node_revision->predecessor_id;
}
-
-svn_error_t *
-svn_fs_x__dag_get_predecessor_count(int *count,
- dag_node_t *node)
+int
+svn_fs_x__dag_get_predecessor_count(dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
-
- SVN_ERR(get_node_revision(&noderev, node));
- *count = noderev->predecessor_count;
- return SVN_NO_ERROR;
+ return node->node_revision->predecessor_count;
}
-svn_error_t *
-svn_fs_x__dag_get_mergeinfo_count(apr_int64_t *count,
- dag_node_t *node)
+apr_int64_t
+svn_fs_x__dag_get_mergeinfo_count(dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
-
- SVN_ERR(get_node_revision(&noderev, node));
- *count = noderev->mergeinfo_count;
- return SVN_NO_ERROR;
+ return node->node_revision->mergeinfo_count;
}
-svn_error_t *
-svn_fs_x__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
- dag_node_t *node)
+svn_boolean_t
+svn_fs_x__dag_has_mergeinfo(dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
-
- SVN_ERR(get_node_revision(&noderev, node));
- *has_mergeinfo = noderev->has_mergeinfo;
- return SVN_NO_ERROR;
+ return node->node_revision->has_mergeinfo;
}
-svn_error_t *
-svn_fs_x__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
- dag_node_t *node)
+svn_boolean_t
+svn_fs_x__dag_has_descendants_with_mergeinfo(dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
+ svn_fs_x__noderev_t *noderev = node->node_revision;
- if (node->kind != svn_node_dir)
- {
- *do_they = FALSE;
- return SVN_NO_ERROR;
- }
+ if (noderev->kind != svn_node_dir)
+ return FALSE;
- SVN_ERR(get_node_revision(&noderev, node));
if (noderev->mergeinfo_count > 1)
- *do_they = TRUE;
+ return TRUE;
else if (noderev->mergeinfo_count == 1 && !noderev->has_mergeinfo)
- *do_they = TRUE;
- else
- *do_they = FALSE;
- return SVN_NO_ERROR;
+ return TRUE;
+
+ return FALSE;
}
@@ -362,16 +243,15 @@ svn_fs_x__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
/* Set *ID_P to the noderev-id for entry NAME in PARENT. If no such
entry, set *ID_P to NULL but do not error. */
-static svn_error_t *
-dir_entry_id_from_node(svn_fs_x__id_t *id_p,
+svn_error_t *
+svn_fs_x__dir_entry_id(svn_fs_x__id_t *id_p,
dag_node_t *parent,
const char *name,
apr_pool_t *scratch_pool)
{
svn_fs_x__dirent_t *dirent;
- svn_fs_x__noderev_t *noderev;
+ svn_fs_x__noderev_t *noderev = parent->node_revision;
- SVN_ERR(get_node_revision(&noderev, parent));
if (noderev->kind != svn_node_dir)
return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
_("Can't get entries of non-directory"));
@@ -411,14 +291,16 @@ set_entry(dag_node_t *parent,
svn_fs_x__txn_id_t txn_id,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *parent_noderev;
-
- /* Get the parent's node-revision. */
- SVN_ERR(get_node_revision(&parent_noderev, parent));
+ svn_fs_x__noderev_t *parent_noderev = parent->node_revision;
/* Set the new entry. */
- return svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name, id,
- kind, parent->node_pool, scratch_pool);
+ SVN_ERR(svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name, id,
+ kind, parent->node_pool, scratch_pool));
+
+ /* Update cached data. */
+ svn_fs_x__update_dag_cache(parent);
+
+ return SVN_NO_ERROR;
}
@@ -439,7 +321,8 @@ make_entry(dag_node_t **child_p,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t new_noderev, *parent_noderev;
+ svn_fs_x__noderev_t new_noderev;
+ svn_fs_x__noderev_t *parent_noderev = parent->node_revision;
/* Make sure that NAME is a single path component. */
if (! svn_path_is_single_path_component(name))
@@ -448,7 +331,7 @@ make_entry(dag_node_t **child_p,
_("Attempted to create a node with an illegal name '%s'"), name);
/* Make sure that parent is a directory */
- if (parent->kind != svn_node_dir)
+ if (parent_noderev->kind != svn_node_dir)
return svn_error_create
(SVN_ERR_FS_NOT_DIRECTORY, NULL,
_("Attempted to create entry in non-directory parent"));
@@ -464,7 +347,6 @@ make_entry(dag_node_t **child_p,
new_noderev.kind = is_dir ? svn_node_dir : svn_node_file;
new_noderev.created_path = svn_fspath__join(parent_path, name, result_pool);
- SVN_ERR(get_node_revision(&parent_noderev, parent));
new_noderev.copyroot_path = apr_pstrdup(result_pool,
parent_noderev->copyroot_path);
new_noderev.copyroot_rev = parent_noderev->copyroot_rev;
@@ -495,9 +377,7 @@ svn_fs_x__dag_dir_entries(apr_array_header_t **entries,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *noderev;
-
- SVN_ERR(get_node_revision(&noderev, node));
+ svn_fs_x__noderev_t *noderev = node->node_revision;
if (noderev->kind != svn_node_dir)
return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
@@ -517,7 +397,7 @@ svn_fs_x__dag_set_entry(dag_node_t *node,
apr_pool_t *scratch_pool)
{
/* Check it's a directory. */
- if (node->kind != svn_node_dir)
+ if (node->node_revision->kind != svn_node_dir)
return svn_error_create
(SVN_ERR_FS_NOT_DIRECTORY, NULL,
_("Attempted to set entry in non-directory node"));
@@ -541,16 +421,8 @@ svn_fs_x__dag_get_proplist(apr_hash_t **proplist_p,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *noderev;
- apr_hash_t *proplist = NULL;
-
- SVN_ERR(get_node_revision(&noderev, node));
-
- SVN_ERR(svn_fs_x__get_proplist(&proplist, node->fs, noderev, result_pool,
- scratch_pool));
-
- *proplist_p = proplist;
-
+ SVN_ERR(svn_fs_x__get_proplist(proplist_p, node->fs, node->node_revision,
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
}
@@ -560,37 +432,51 @@ svn_fs_x__dag_set_proplist(dag_node_t *node,
apr_hash_t *proplist,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *noderev;
-
/* Sanity check: this node better be mutable! */
if (! svn_fs_x__dag_check_mutable(node))
{
- svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
+ svn_string_t *idstr
+ = svn_fs_x__id_unparse(&node->node_revision->noderev_id,
+ scratch_pool);
return svn_error_createf
(SVN_ERR_FS_NOT_MUTABLE, NULL,
"Can't set proplist on *immutable* node-revision %s",
idstr->data);
}
- /* Go get a fresh NODE-REVISION for this node. */
- SVN_ERR(get_node_revision(&noderev, node));
-
/* Set the new proplist. */
- return svn_fs_x__set_proplist(node->fs, noderev, proplist, scratch_pool);
+ SVN_ERR(svn_fs_x__set_proplist(node->fs, node->node_revision, proplist,
+ scratch_pool));
+ svn_fs_x__update_dag_cache(node);
+
+ return SVN_NO_ERROR;
}
+/* Write NODE's NODEREV element to disk. Update the DAG cache.
+ Use SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+noderev_changed(dag_node_t *node,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(svn_fs_x__put_node_revision(node->fs, node->node_revision,
+ scratch_pool));
+ svn_fs_x__update_dag_cache(node);
+
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node,
apr_int64_t increment,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *noderev;
+ svn_fs_x__noderev_t *noderev = node->node_revision;
/* Sanity check: this node better be mutable! */
if (! svn_fs_x__dag_check_mutable(node))
{
- svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
+ svn_string_t *idstr = svn_fs_x__id_unparse(&noderev->noderev_id,
+ scratch_pool);
return svn_error_createf
(SVN_ERR_FS_NOT_MUTABLE, NULL,
"Can't increment mergeinfo count on *immutable* node-revision %s",
@@ -600,13 +486,11 @@ svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node,
if (increment == 0)
return SVN_NO_ERROR;
- /* Go get a fresh NODE-REVISION for this node. */
- SVN_ERR(get_node_revision(&noderev, node));
-
noderev->mergeinfo_count += increment;
if (noderev->mergeinfo_count < 0)
{
- svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
+ svn_string_t *idstr = svn_fs_x__id_unparse(&noderev->noderev_id,
+ scratch_pool);
return svn_error_createf
(SVN_ERR_FS_CORRUPT, NULL,
apr_psprintf(scratch_pool,
@@ -617,7 +501,8 @@ svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node,
}
if (noderev->mergeinfo_count > 1 && noderev->kind == svn_node_file)
{
- svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
+ svn_string_t *idstr = svn_fs_x__id_unparse(&noderev->noderev_id,
+ scratch_pool);
return svn_error_createf
(SVN_ERR_FS_CORRUPT, NULL,
apr_psprintf(scratch_pool,
@@ -628,7 +513,7 @@ svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node,
}
/* Flush it out. */
- return svn_fs_x__put_node_revision(node->fs, noderev, scratch_pool);
+ return noderev_changed(node, scratch_pool);
}
svn_error_t *
@@ -636,55 +521,38 @@ svn_fs_x__dag_set_has_mergeinfo(dag_node_t *node,
svn_boolean_t has_mergeinfo,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *noderev;
-
/* Sanity check: this node better be mutable! */
if (! svn_fs_x__dag_check_mutable(node))
{
- svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
+ svn_string_t *idstr
+ = svn_fs_x__id_unparse(&node->node_revision->noderev_id,
+ scratch_pool);
return svn_error_createf
(SVN_ERR_FS_NOT_MUTABLE, NULL,
"Can't set mergeinfo flag on *immutable* node-revision %s",
idstr->data);
}
- /* Go get a fresh NODE-REVISION for this node. */
- SVN_ERR(get_node_revision(&noderev, node));
-
- noderev->has_mergeinfo = has_mergeinfo;
+ node->node_revision->has_mergeinfo = has_mergeinfo;
/* Flush it out. */
- return svn_fs_x__put_node_revision(node->fs, noderev, scratch_pool);
+ return noderev_changed(node, scratch_pool);
}
/*** Roots. ***/
svn_error_t *
-svn_fs_x__dag_revision_root(dag_node_t **node_p,
- svn_fs_t *fs,
- svn_revnum_t rev,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- svn_fs_x__id_t root_id;
-
- svn_fs_x__init_rev_root(&root_id, rev);
- return svn_fs_x__dag_get_node(node_p, fs, &root_id, result_pool,
- scratch_pool);
-}
-
-
-svn_error_t *
-svn_fs_x__dag_txn_root(dag_node_t **node_p,
- svn_fs_t *fs,
- svn_fs_x__txn_id_t txn_id,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
+svn_fs_x__dag_root(dag_node_t **node_p,
+ svn_fs_t *fs,
+ svn_fs_x__change_set_t change_set,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_fs_x__id_t root_id;
+ root_id.change_set = change_set;
+ root_id.number = SVN_FS_X__ITEM_INDEX_ROOT_NODE;
- svn_fs_x__init_txn_root(&root_id, txn_id);
return svn_fs_x__dag_get_node(node_p, fs, &root_id, result_pool,
scratch_pool);
}
@@ -734,14 +602,11 @@ svn_fs_x__dag_clone_child(dag_node_t **child_p,
}
else
{
- svn_fs_x__noderev_t *noderev, *parent_noderev;
-
- /* Go get a fresh NODE-REVISION for current child node. */
- SVN_ERR(get_node_revision(&noderev, cur_entry));
+ svn_fs_x__noderev_t *noderev = cur_entry->node_revision;
if (is_parent_copyroot)
{
- SVN_ERR(get_node_revision(&parent_noderev, parent));
+ svn_fs_x__noderev_t *parent_noderev = parent->node_revision;
noderev->copyroot_rev = parent_noderev->copyroot_rev;
noderev->copyroot_path = apr_pstrdup(scratch_pool,
parent_noderev->copyroot_path);
@@ -796,7 +661,7 @@ delete_if_mutable(svn_fs_t *fs,
return SVN_NO_ERROR;
/* Else it's mutable. Recurse on directories... */
- if (node->kind == svn_node_dir)
+ if (node->node_revision->kind == svn_node_dir)
{
apr_array_header_t *entries;
int i;
@@ -829,13 +694,13 @@ svn_fs_x__dag_delete(dag_node_t *parent,
svn_fs_x__txn_id_t txn_id,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *parent_noderev;
+ svn_fs_x__noderev_t *parent_noderev = parent->node_revision;
svn_fs_t *fs = parent->fs;
svn_fs_x__dirent_t *dirent;
apr_pool_t *subpool;
/* Make sure parent is a directory. */
- if (parent->kind != svn_node_dir)
+ if (parent_noderev->kind != svn_node_dir)
return svn_error_createf
(SVN_ERR_FS_NOT_DIRECTORY, NULL,
"Attempted to delete entry '%s' from *non*-directory node", name);
@@ -852,9 +717,9 @@ svn_fs_x__dag_delete(dag_node_t *parent,
(SVN_ERR_FS_NOT_SINGLE_PATH_COMPONENT, NULL,
"Attempted to delete a node with an illegal name '%s'", name);
- /* Get a fresh NODE-REVISION for the parent node. */
- SVN_ERR(get_node_revision(&parent_noderev, parent));
-
+ /* We allocate a few potentially heavy temporary objects (file buffers
+ and directories). Make sure we don't keep them around for longer
+ than necessary. */
subpool = svn_pool_create(scratch_pool);
/* Search this directory for a dirent with that NAME. */
@@ -871,13 +736,13 @@ svn_fs_x__dag_delete(dag_node_t *parent,
"Delete failed--directory has no entry '%s'", name);
/* If mutable, remove it and any mutable children from db. */
- SVN_ERR(delete_if_mutable(parent->fs, &dirent->id, scratch_pool));
- svn_pool_destroy(subpool);
+ SVN_ERR(delete_if_mutable(parent->fs, &dirent->id, subpool));
/* Remove this entry from its parent's entries list. */
- return svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name,
- NULL, svn_node_unknown, parent->node_pool,
- scratch_pool);
+ SVN_ERR(set_entry(parent, name, NULL, svn_node_unknown, txn_id, subpool));
+
+ svn_pool_destroy(subpool);
+ return SVN_NO_ERROR;
}
@@ -916,23 +781,16 @@ svn_fs_x__dag_get_contents(svn_stream_t **contents_p,
dag_node_t *file,
apr_pool_t *result_pool)
{
- svn_fs_x__noderev_t *noderev;
- svn_stream_t *contents;
-
/* Make sure our node is a file. */
- if (file->kind != svn_node_file)
+ if (file->node_revision->kind != svn_node_file)
return svn_error_createf
(SVN_ERR_FS_NOT_FILE, NULL,
"Attempted to get textual contents of a *non*-file node");
- /* Go get a fresh node-revision for FILE. */
- SVN_ERR(get_node_revision(&noderev, file));
-
/* Get a stream to the contents. */
- SVN_ERR(svn_fs_x__get_contents(&contents, file->fs,
- noderev->data_rep, TRUE, result_pool));
-
- *contents_p = contents;
+ SVN_ERR(svn_fs_x__get_contents(contents_p, file->fs,
+ file->node_revision->data_rep, TRUE,
+ result_pool));
return SVN_NO_ERROR;
}
@@ -945,23 +803,16 @@ svn_fs_x__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *src_noderev;
- svn_fs_x__noderev_t *tgt_noderev;
+ svn_fs_x__noderev_t *src_noderev = source ? source->node_revision : NULL;
+ svn_fs_x__noderev_t *tgt_noderev = target->node_revision;
/* Make sure our nodes are files. */
- if ((source && source->kind != svn_node_file)
- || target->kind != svn_node_file)
+ if ((source && src_noderev->kind != svn_node_file)
+ || tgt_noderev->kind != svn_node_file)
return svn_error_createf
(SVN_ERR_FS_NOT_FILE, NULL,
"Attempted to get textual contents of a *non*-file node");
- /* Go get fresh node-revisions for the nodes. */
- if (source)
- SVN_ERR(get_node_revision(&src_noderev, source));
- else
- src_noderev = NULL;
- SVN_ERR(get_node_revision(&tgt_noderev, target));
-
/* Get the delta stream. */
return svn_fs_x__get_file_delta_stream(stream_p, target->fs,
src_noderev, tgt_noderev,
@@ -976,13 +827,8 @@ svn_fs_x__dag_try_process_file_contents(svn_boolean_t *success,
void* baton,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *noderev;
-
- /* Go get fresh node-revisions for the nodes. */
- SVN_ERR(get_node_revision(&noderev, node));
-
return svn_fs_x__try_process_file_contents(success, node->fs,
- noderev,
+ node->node_revision,
processor, baton, scratch_pool);
}
@@ -991,18 +837,13 @@ svn_error_t *
svn_fs_x__dag_file_length(svn_filesize_t *length,
dag_node_t *file)
{
- svn_fs_x__noderev_t *noderev;
-
/* Make sure our node is a file. */
- if (file->kind != svn_node_file)
+ if (file->node_revision->kind != svn_node_file)
return svn_error_createf
(SVN_ERR_FS_NOT_FILE, NULL,
"Attempted to get length of a *non*-file node");
- /* Go get a fresh node-revision for FILE, and . */
- SVN_ERR(get_node_revision(&noderev, file));
-
- return svn_fs_x__file_length(length, noderev);
+ return svn_fs_x__file_length(length, file->node_revision);
}
@@ -1012,16 +853,13 @@ svn_fs_x__dag_file_checksum(svn_checksum_t **checksum,
svn_checksum_kind_t kind,
apr_pool_t *result_pool)
{
- svn_fs_x__noderev_t *noderev;
-
- if (file->kind != svn_node_file)
+ if (file->node_revision->kind != svn_node_file)
return svn_error_createf
(SVN_ERR_FS_NOT_FILE, NULL,
"Attempted to get checksum of a *non*-file node");
- SVN_ERR(get_node_revision(&noderev, file));
-
- return svn_fs_x__file_checksum(checksum, noderev, kind, result_pool);
+ return svn_fs_x__file_checksum(checksum, file->node_revision, kind,
+ result_pool);
}
@@ -1030,11 +868,8 @@ svn_fs_x__dag_get_edit_stream(svn_stream_t **contents,
dag_node_t *file,
apr_pool_t *result_pool)
{
- svn_fs_x__noderev_t *noderev;
- svn_stream_t *ws;
-
/* Make sure our node is a file. */
- if (file->kind != svn_node_file)
+ if (file->node_revision->kind != svn_node_file)
return svn_error_createf
(SVN_ERR_FS_NOT_FILE, NULL,
"Attempted to set textual contents of a *non*-file node");
@@ -1045,13 +880,8 @@ svn_fs_x__dag_get_edit_stream(svn_stream_t **contents,
(SVN_ERR_FS_NOT_MUTABLE, NULL,
"Attempted to set textual contents of an immutable node");
- /* Get the node revision. */
- SVN_ERR(get_node_revision(&noderev, file));
-
- SVN_ERR(svn_fs_x__set_contents(&ws, file->fs, noderev, result_pool));
-
- *contents = ws;
-
+ SVN_ERR(svn_fs_x__set_contents(contents, file->fs, file->node_revision,
+ result_pool));
return SVN_NO_ERROR;
}
@@ -1072,9 +902,10 @@ svn_fs_x__dag_finalize_edits(dag_node_t *file,
return svn_checksum_mismatch_err(checksum, file_checksum,
scratch_pool,
_("Checksum mismatch for '%s'"),
- file->created_path);
+ file->node_revision->created_path);
}
+ svn_fs_x__update_dag_cache(file);
return SVN_NO_ERROR;
}
@@ -1086,101 +917,14 @@ svn_fs_x__dag_dup(const dag_node_t *node,
/* Allocate our new node. */
dag_node_t *new_node = apr_pmemdup(result_pool, node, sizeof(*new_node));
- /* Only copy cached svn_fs_x__noderev_t for immutable nodes. */
- if (node->node_revision && !svn_fs_x__dag_check_mutable(node))
- {
- new_node->node_revision = copy_node_revision(node->node_revision,
- result_pool);
- new_node->created_path = new_node->node_revision->created_path;
- }
- else
- {
- new_node->node_revision = NULL;
- new_node->created_path = apr_pstrdup(result_pool, node->created_path);
- }
-
+ /* Copy sub-structures. */
+ new_node->node_revision = copy_node_revision(node->node_revision,
+ result_pool);
new_node->node_pool = result_pool;
return new_node;
}
-dag_node_t *
-svn_fs_x__dag_copy_into_pool(dag_node_t *node,
- apr_pool_t *result_pool)
-{
- return (node->node_pool == result_pool
- ? node
- : svn_fs_x__dag_dup(node, result_pool));
-}
-
-svn_error_t *
-svn_fs_x__dag_serialize(void **data,
- apr_size_t *data_len,
- void *in,
- apr_pool_t *pool)
-{
- dag_node_t *node = in;
- svn_stringbuf_t *serialized;
-
- /* create an serialization context and serialize the dag node as root */
- svn_temp_serializer__context_t *context =
- svn_temp_serializer__init(node,
- sizeof(*node),
- 1024 - SVN_TEMP_SERIALIZER__OVERHEAD,
- pool);
-
- /* for mutable nodes, we will _never_ cache the noderev */
- if (node->node_revision && !svn_fs_x__dag_check_mutable(node))
- {
- svn_fs_x__noderev_serialize(context, &node->node_revision);
- }
- else
- {
- svn_temp_serializer__set_null(context,
- (const void * const *)&node->node_revision);
- svn_temp_serializer__add_string(context, &node->created_path);
- }
-
- /* The deserializer will use its own pool. */
- svn_temp_serializer__set_null(context,
- (const void * const *)&node->node_pool);
-
- /* return serialized data */
- serialized = svn_temp_serializer__get(context);
- *data = serialized->data;
- *data_len = serialized->len;
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_fs_x__dag_deserialize(void **out,
- void *data,
- apr_size_t data_len,
- apr_pool_t *pool)
-{
- dag_node_t *node = (dag_node_t *)data;
- if (data_len == 0)
- return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
- _("Empty noderev in cache"));
-
- /* Copy the _full_ buffer as it also contains the sub-structures. */
- node->fs = NULL;
-
- /* fixup all references to sub-structures */
- svn_fs_x__noderev_deserialize(node, &node->node_revision, pool);
- node->node_pool = pool;
-
- if (node->node_revision)
- node->created_path = node->node_revision->created_path;
- else
- svn_temp_deserializer__resolve(node, (void**)&node->created_path);
-
- /* return result */
- *out = node;
-
- return SVN_NO_ERROR;
-}
svn_error_t *
svn_fs_x__dag_open(dag_node_t **child_p,
@@ -1192,7 +936,7 @@ svn_fs_x__dag_open(dag_node_t **child_p,
svn_fs_x__id_t node_id;
/* Ensure that NAME exists in PARENT's entry list. */
- SVN_ERR(dir_entry_id_from_node(&node_id, parent, name, scratch_pool));
+ SVN_ERR(svn_fs_x__dir_entry_id(&node_id, parent, name, scratch_pool));
if (! svn_fs_x__id_used(&node_id))
{
*child_p = NULL;
@@ -1219,13 +963,12 @@ svn_fs_x__dag_copy(dag_node_t *to_node,
if (preserve_history)
{
- svn_fs_x__noderev_t *from_noderev, *to_noderev;
+ svn_fs_x__noderev_t *to_noderev;
svn_fs_x__id_t copy_id;
svn_fs_t *fs = svn_fs_x__dag_get_fs(from_node);
/* Make a copy of the original node revision. */
- SVN_ERR(get_node_revision(&from_noderev, from_node));
- to_noderev = copy_node_revision(from_noderev, scratch_pool);
+ to_noderev = copy_node_revision(from_node->node_revision, scratch_pool);
/* Reserve a copy ID for this new copy. */
SVN_ERR(svn_fs_x__reserve_copy_id(&copy_id, fs, txn_id, scratch_pool));
@@ -1253,7 +996,8 @@ svn_fs_x__dag_copy(dag_node_t *to_node,
}
/* Set the entry in to_node to the new id. */
- return svn_fs_x__dag_set_entry(to_node, entry, id, from_node->kind,
+ return svn_fs_x__dag_set_entry(to_node, entry, id,
+ from_node->node_revision->kind,
txn_id, scratch_pool);
}
@@ -1269,7 +1013,8 @@ svn_fs_x__dag_things_different(svn_boolean_t *props_changed,
svn_boolean_t strict,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *noderev1, *noderev2;
+ svn_fs_x__noderev_t *noderev1 = node1->node_revision;
+ svn_fs_x__noderev_t *noderev2 = node2->node_revision;
svn_fs_t *fs;
svn_boolean_t same;
@@ -1280,10 +1025,6 @@ svn_fs_x__dag_things_different(svn_boolean_t *props_changed,
fs = svn_fs_x__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)
{
@@ -1300,48 +1041,25 @@ svn_fs_x__dag_things_different(svn_boolean_t *props_changed,
return SVN_NO_ERROR;
}
-svn_error_t *
+void
svn_fs_x__dag_get_copyroot(svn_revnum_t *rev,
const char **path,
dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
-
- /* Go get a fresh node-revision for NODE. */
- SVN_ERR(get_node_revision(&noderev, node));
-
- *rev = noderev->copyroot_rev;
- *path = noderev->copyroot_path;
-
- return SVN_NO_ERROR;
+ *rev = node->node_revision->copyroot_rev;
+ *path = node->node_revision->copyroot_path;
}
-svn_error_t *
-svn_fs_x__dag_get_copyfrom_rev(svn_revnum_t *rev,
- dag_node_t *node)
+svn_revnum_t
+svn_fs_x__dag_get_copyfrom_rev(dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
-
- /* Go get a fresh node-revision for NODE. */
- SVN_ERR(get_node_revision(&noderev, node));
-
- *rev = noderev->copyfrom_rev;
-
- return SVN_NO_ERROR;
+ return node->node_revision->copyfrom_rev;
}
-svn_error_t *
-svn_fs_x__dag_get_copyfrom_path(const char **path,
- dag_node_t *node)
+const char *
+svn_fs_x__dag_get_copyfrom_path(dag_node_t *node)
{
- svn_fs_x__noderev_t *noderev;
-
- /* Go get a fresh node-revision for NODE. */
- SVN_ERR(get_node_revision(&noderev, node));
-
- *path = noderev->copyfrom_path;
-
- return SVN_NO_ERROR;
+ return node->node_revision->copyfrom_path;
}
svn_error_t *
@@ -1349,20 +1067,17 @@ svn_fs_x__dag_update_ancestry(dag_node_t *target,
dag_node_t *source,
apr_pool_t *scratch_pool)
{
- svn_fs_x__noderev_t *source_noderev, *target_noderev;
+ svn_fs_x__noderev_t *source_noderev = source->node_revision;
+ svn_fs_x__noderev_t *target_noderev = target->node_revision;
if (! svn_fs_x__dag_check_mutable(target))
return svn_error_createf
(SVN_ERR_FS_NOT_MUTABLE, NULL,
_("Attempted to update ancestry of non-mutable node"));
- SVN_ERR(get_node_revision(&source_noderev, source));
- SVN_ERR(get_node_revision(&target_noderev, target));
-
target_noderev->predecessor_id = source_noderev->noderev_id;
target_noderev->predecessor_count = source_noderev->predecessor_count;
target_noderev->predecessor_count++;
- return svn_fs_x__put_node_revision(target->fs, target_noderev,
- scratch_pool);
+ return noderev_changed(target, scratch_pool);
}