You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/01/20 18:52:21 UTC

svn commit: r1653314 [5/20] - in /subversion/branches/move-tracking-2: ./ notes/ subversion/ subversion/bindings/swig/ subversion/bindings/swig/include/ subversion/bindings/swig/perl/native/ subversion/bindings/swig/perl/native/t/ subversion/bindings/s...

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/dag.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/dag.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/dag.c Tue Jan 20 17:52:18 2015
@@ -31,7 +31,7 @@
 #include "dag.h"
 #include "fs.h"
 #include "fs_x.h"
-#include "id.h"
+#include "fs_id.h"
 #include "cached_data.h"
 #include "transaction.h"
 
@@ -50,14 +50,15 @@ struct dag_node_t
   /* The filesystem this dag node came from. */
   svn_fs_t *fs;
 
-  /* The node revision ID for this dag node, allocated in POOL.  */
-  svn_fs_id_t *id;
+  /* 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 node revision ID for this dag
-     node's predecessor; otherwise NULL. (Used in
-     svn_fs_node_created_rev.) */
-  const svn_fs_id_t *fresh_root_predecessor_id;
+     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;
@@ -69,28 +70,33 @@ struct dag_node_t
      this yourself, but you're probably better off just calling
      `get_node_revision' and `set_node_revision', which take care of
      things for you.  */
-  node_revision_t *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. */
+  apr_size_t hint;
 };
 
 
 
 /* Trivial helper/accessor functions. */
-svn_node_kind_t svn_fs_x__dag_node_kind(dag_node_t *node)
+svn_node_kind_t
+svn_fs_x__dag_node_kind(dag_node_t *node)
 {
   return node->kind;
 }
 
-
-const svn_fs_id_t *
+const svn_fs_x__id_t *
 svn_fs_x__dag_get_id(const dag_node_t *node)
 {
-  return node->id;
+  return &node->id;
 }
 
 
@@ -108,35 +114,32 @@ svn_fs_x__dag_get_fs(dag_node_t *node)
 }
 
 void
-svn_fs_x__dag_set_fs(dag_node_t *node, svn_fs_t *fs)
+svn_fs_x__dag_set_fs(dag_node_t *node,
+                     svn_fs_t *fs)
 {
   node->fs = fs;
 }
 
 
-/* Dup NODEREV and all associated data into POOL.
+/* Dup NODEREV and all associated data into RESULT_POOL.
    Leaves the id and is_fresh_txn_root fields as zero bytes. */
-static node_revision_t *
-copy_node_revision(node_revision_t *noderev,
-                   apr_pool_t *pool)
-{
-  node_revision_t *nr = apr_pcalloc(pool, sizeof(*nr));
-  nr->kind = noderev->kind;
-  if (noderev->predecessor_id)
-    nr->predecessor_id = svn_fs_x__id_copy(noderev->predecessor_id, pool);
-  nr->predecessor_count = noderev->predecessor_count;
+static svn_fs_x__noderev_t *
+copy_node_revision(svn_fs_x__noderev_t *noderev,
+                   apr_pool_t *result_pool)
+{
+  svn_fs_x__noderev_t *nr = apr_pmemdup(result_pool, noderev,
+                                        sizeof(*noderev));
+
   if (noderev->copyfrom_path)
-    nr->copyfrom_path = apr_pstrdup(pool, noderev->copyfrom_path);
-  nr->copyfrom_rev = noderev->copyfrom_rev;
-  nr->copyroot_path = apr_pstrdup(pool, noderev->copyroot_path);
-  nr->copyroot_rev = noderev->copyroot_rev;
-  nr->data_rep = svn_fs_x__rep_copy(noderev->data_rep, pool);
-  nr->prop_rep = svn_fs_x__rep_copy(noderev->prop_rep, pool);
-  nr->mergeinfo_count = noderev->mergeinfo_count;
-  nr->has_mergeinfo = noderev->has_mergeinfo;
+    nr->copyfrom_path = apr_pstrdup(result_pool, noderev->copyfrom_path);
+
+  nr->copyroot_path = apr_pstrdup(result_pool, noderev->copyroot_path);
+  nr->data_rep = svn_fs_x__rep_copy(noderev->data_rep, result_pool);
+  nr->prop_rep = svn_fs_x__rep_copy(noderev->prop_rep, result_pool);
 
   if (noderev->created_path)
-    nr->created_path = apr_pstrdup(pool, noderev->created_path);
+    nr->created_path = apr_pstrdup(result_pool, noderev->created_path);
+
   return nr;
 }
 
@@ -153,18 +156,17 @@ copy_node_revision(node_revision_t *node
    changes that never got committed.  It's probably best not to change
    the structure at all.  */
 static svn_error_t *
-get_node_revision(node_revision_t **noderev_p,
+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)
     {
-      node_revision_t *noderev;
+      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));
+      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);
     }
@@ -174,39 +176,100 @@ get_node_revision(node_revision_t **node
   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)
+{
+  svn_fs_x__noderev_t *noderev;
+  SVN_ERR(get_node_revision(&noderev, node));
+
+  *node_id = noderev->node_id;
+  return SVN_NO_ERROR;
+}
 
-svn_boolean_t svn_fs_x__dag_check_mutable(const dag_node_t *node)
+/* 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)
 {
-  return svn_fs_x__id_is_txn(svn_fs_x__dag_get_id(node));
+  svn_fs_x__noderev_t *noderev;
+  SVN_ERR(get_node_revision(&noderev, node));
+
+  *copy_id = noderev->copy_id;
+  return SVN_NO_ERROR;
+}
+
+/* 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,
+                           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;
+}
+
+svn_error_t *
+svn_fs_x__dag_same_line_of_history(svn_boolean_t *same,
+                                   dag_node_t *lhs,
+                                   dag_node_t *rhs)
+{
+  svn_fs_x__noderev_t *lhs_noderev, *rhs_noderev;
+
+  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;
+}
+
+svn_boolean_t
+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,
-                       const svn_fs_id_t *id,
-                       apr_pool_t *pool)
+                       const svn_fs_x__id_t *id,
+                       apr_pool_t *result_pool)
 {
   dag_node_t *new_node;
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   /* Construct the node. */
-  new_node = apr_pcalloc(pool, sizeof(*new_node));
+  new_node = apr_pcalloc(result_pool, sizeof(*new_node));
   new_node->fs = fs;
-  new_node->id = svn_fs_x__id_copy(id, pool);
+  new_node->id = *id;
+  new_node->hint = APR_SIZE_MAX;
 
   /* Grab the contents so we can inspect the node's kind and created path. */
-  new_node->node_pool = pool;
+  new_node->node_pool = result_pool;
   SVN_ERR(get_node_revision(&noderev, new_node));
 
   /* Initialize the KIND and CREATED_PATH attributes */
   new_node->kind = noderev->kind;
-  new_node->created_path = apr_pstrdup(pool, noderev->created_path);
+  new_node->created_path = apr_pstrdup(result_pool, noderev->created_path);
 
-  if (noderev->is_fresh_txn_root)
-    new_node->fresh_root_predecessor_id = noderev->predecessor_id;
-  else
-    new_node->fresh_root_predecessor_id = NULL;
+  /* Support our quirky svn_fs_node_created_rev API.
+     Untouched txn roots report the base rev as theirs. */
+  new_node->revision
+    = (  noderev->is_fresh_txn_root
+       ? 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;
@@ -214,32 +277,22 @@ svn_fs_x__dag_get_node(dag_node_t **node
 }
 
 
-svn_error_t *
-svn_fs_x__dag_get_revision(svn_revnum_t *rev,
-                           dag_node_t *node,
-                           apr_pool_t *pool)
+svn_revnum_t
+svn_fs_x__dag_get_revision(const dag_node_t *node)
 {
-  /* In the special case that this is an unmodified transaction root,
-     we need to actually get the revision of the noderev's predecessor
-     (the revision root); see Issue #2608. */
-  const svn_fs_id_t *correct_id = node->fresh_root_predecessor_id
-    ? node->fresh_root_predecessor_id : node->id;
-
-  /* Look up the committed revision from the Node-ID. */
-  *rev = svn_fs_x__id_rev(correct_id);
-
-  return SVN_NO_ERROR;
+  return node->revision;
 }
 
 
 svn_error_t *
-svn_fs_x__dag_get_predecessor_id(const svn_fs_id_t **id_p,
+svn_fs_x__dag_get_predecessor_id(svn_fs_x__id_t *id_p,
                                  dag_node_t *node)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   SVN_ERR(get_node_revision(&noderev, node));
   *id_p = noderev->predecessor_id;
+
   return SVN_NO_ERROR;
 }
 
@@ -248,7 +301,7 @@ svn_error_t *
 svn_fs_x__dag_get_predecessor_count(int *count,
                                     dag_node_t *node)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   SVN_ERR(get_node_revision(&noderev, node));
   *count = noderev->predecessor_count;
@@ -259,7 +312,7 @@ svn_error_t *
 svn_fs_x__dag_get_mergeinfo_count(apr_int64_t *count,
                                   dag_node_t *node)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   SVN_ERR(get_node_revision(&noderev, node));
   *count = noderev->mergeinfo_count;
@@ -270,7 +323,7 @@ svn_error_t *
 svn_fs_x__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
                             dag_node_t *node)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   SVN_ERR(get_node_revision(&noderev, node));
   *has_mergeinfo = noderev->has_mergeinfo;
@@ -281,7 +334,7 @@ svn_error_t *
 svn_fs_x__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
                                              dag_node_t *node)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   if (node->kind != svn_node_dir)
     {
@@ -304,28 +357,37 @@ svn_fs_x__dag_has_descendants_with_merge
 
 /* Some of these are helpers for functions outside this section. */
 
-/* Set *ID_P to the node-id for entry NAME in PARENT.  If no such
-   entry, set *ID_P to NULL but do not error.  The node-id is
-   allocated in POOL. */
+/* 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(const svn_fs_id_t **id_p,
+dir_entry_id_from_node(svn_fs_x__id_t *id_p,
                        dag_node_t *parent,
                        const char *name,
-                       apr_pool_t *result_pool,
                        apr_pool_t *scratch_pool)
 {
-  svn_fs_dirent_t *dirent;
+  svn_fs_x__dirent_t *dirent;
+  svn_fs_x__noderev_t *noderev;
+
+  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"));
 
-  SVN_ERR(svn_fs_x__dag_dir_entry(&dirent, parent, name, result_pool,
-                                  scratch_pool));
-  *id_p = dirent ? dirent->id : NULL;
+  /* Get a dirent hash for this directory. */
+  SVN_ERR(svn_fs_x__rep_contents_dir_entry(&dirent, parent->fs, noderev,
+                                           name, &parent->hint,
+                                           scratch_pool, scratch_pool));
+  if (dirent)
+    *id_p = dirent->id;
+  else
+    svn_fs_x__id_reset(id_p);
 
   return SVN_NO_ERROR;
 }
 
 
 /* Add or set in PARENT a directory entry NAME pointing to ID.
-   Allocations are done in POOL.
+   Temporary allocations are done in SCRATCH_POOL.
 
    Assumptions:
    - PARENT is a mutable directory.
@@ -335,28 +397,28 @@ dir_entry_id_from_node(const svn_fs_id_t
 static svn_error_t *
 set_entry(dag_node_t *parent,
           const char *name,
-          const svn_fs_id_t *id,
+          const svn_fs_x__id_t *id,
           svn_node_kind_t kind,
           svn_fs_x__txn_id_t txn_id,
-          apr_pool_t *pool)
+          apr_pool_t *scratch_pool)
 {
-  node_revision_t *parent_noderev;
+  svn_fs_x__noderev_t *parent_noderev;
 
   /* Get the parent's node-revision. */
   SVN_ERR(get_node_revision(&parent_noderev, parent));
 
   /* Set the new entry. */
   return svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name, id,
-                             kind, pool);
+                             kind, parent->node_pool, scratch_pool);
 }
 
 
 /* Make a new entry named NAME in PARENT.  If IS_DIR is true, then the
    node revision the new entry points to will be a directory, else it
-   will be a file.  The new node will be allocated in POOL.  PARENT
+   will be a file.  The new node will be allocated in RESULT_POOL.  PARENT
    must be mutable, and must not have an entry named NAME.
 
-   Use POOL for all allocations, except caching the node_revision in PARENT.
+   Use SCRATCH_POOL for all temporary allocations.
  */
 static svn_error_t *
 make_entry(dag_node_t **child_p,
@@ -365,10 +427,10 @@ make_entry(dag_node_t **child_p,
            const char *name,
            svn_boolean_t is_dir,
            svn_fs_x__txn_id_t txn_id,
-           apr_pool_t *pool)
+           apr_pool_t *result_pool,
+           apr_pool_t *scratch_pool)
 {
-  const svn_fs_id_t *new_node_id;
-  node_revision_t new_noderev, *parent_noderev;
+  svn_fs_x__noderev_t new_noderev, *parent_noderev;
 
   /* Make sure that NAME is a single path component. */
   if (! svn_path_is_single_path_component(name))
@@ -391,38 +453,39 @@ make_entry(dag_node_t **child_p,
   /* Create the new node's NODE-REVISION */
   memset(&new_noderev, 0, sizeof(new_noderev));
   new_noderev.kind = is_dir ? svn_node_dir : svn_node_file;
-  new_noderev.created_path = svn_fspath__join(parent_path, name, pool);
+  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(pool,
+  new_noderev.copyroot_path = apr_pstrdup(result_pool,
                                           parent_noderev->copyroot_path);
   new_noderev.copyroot_rev = parent_noderev->copyroot_rev;
   new_noderev.copyfrom_rev = SVN_INVALID_REVNUM;
   new_noderev.copyfrom_path = NULL;
+  svn_fs_x__id_reset(&new_noderev.predecessor_id);
 
   SVN_ERR(svn_fs_x__create_node
-          (&new_node_id, svn_fs_x__dag_get_fs(parent), &new_noderev,
-           svn_fs_x__id_copy_id(svn_fs_x__dag_get_id(parent)),
-           txn_id, pool));
+          (svn_fs_x__dag_get_fs(parent), &new_noderev,
+           &parent_noderev->copy_id, txn_id, scratch_pool));
 
   /* Create a new dag_node_t for our new node */
   SVN_ERR(svn_fs_x__dag_get_node(child_p, svn_fs_x__dag_get_fs(parent),
-                                 new_node_id, pool));
+                                 &new_noderev.noderev_id, result_pool));
 
   /* We can safely call set_entry because we already know that
      PARENT is mutable, and we just created CHILD, so we know it has
      no ancestors (therefore, PARENT cannot be an ancestor of CHILD) */
-  return set_entry(parent, name, svn_fs_x__dag_get_id(*child_p),
-                   new_noderev.kind, txn_id, pool);
+  return set_entry(parent, name, &new_noderev.noderev_id,
+                   new_noderev.kind, txn_id, scratch_pool);
 }
 
 
 svn_error_t *
 svn_fs_x__dag_dir_entries(apr_array_header_t **entries,
                           dag_node_t *node,
-                          apr_pool_t *pool)
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   SVN_ERR(get_node_revision(&noderev, node));
 
@@ -430,36 +493,18 @@ svn_fs_x__dag_dir_entries(apr_array_head
     return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
                             _("Can't get entries of non-directory"));
 
-  return svn_fs_x__rep_contents_dir(entries, node->fs, noderev, pool, pool);
-}
-
-svn_error_t *
-svn_fs_x__dag_dir_entry(svn_fs_dirent_t **dirent,
-                         dag_node_t *node,
-                         const char* name,
-                         apr_pool_t *result_pool,
-                         apr_pool_t *scratch_pool)
-{
-  node_revision_t *noderev;
-  SVN_ERR(get_node_revision(&noderev, node));
-
-  if (noderev->kind != svn_node_dir)
-    return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
-                            _("Can't get entries of non-directory"));
-
-  /* Get a dirent hash for this directory. */
-  return svn_fs_x__rep_contents_dir_entry(dirent, node->fs, noderev, name,
-                                          result_pool, scratch_pool);
+  return svn_fs_x__rep_contents_dir(entries, node->fs, noderev, result_pool,
+                                    scratch_pool);
 }
 
 
 svn_error_t *
 svn_fs_x__dag_set_entry(dag_node_t *node,
                         const char *entry_name,
-                        const svn_fs_id_t *id,
+                        const svn_fs_x__id_t *id,
                         svn_node_kind_t kind,
                         svn_fs_x__txn_id_t txn_id,
-                        apr_pool_t *pool)
+                        apr_pool_t *scratch_pool)
 {
   /* Check it's a directory. */
   if (node->kind != svn_node_dir)
@@ -473,7 +518,7 @@ svn_fs_x__dag_set_entry(dag_node_t *node
       (SVN_ERR_FS_NOT_MUTABLE, NULL,
        _("Attempted to set entry in immutable node"));
 
-  return set_entry(node, entry_name, id, kind, txn_id, pool);
+  return set_entry(node, entry_name, id, kind, txn_id, scratch_pool);
 }
 
 
@@ -483,14 +528,16 @@ svn_fs_x__dag_set_entry(dag_node_t *node
 svn_error_t *
 svn_fs_x__dag_get_proplist(apr_hash_t **proplist_p,
                            dag_node_t *node,
-                           apr_pool_t *pool)
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
 {
-  node_revision_t *noderev;
+  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, pool));
+  SVN_ERR(svn_fs_x__get_proplist(&proplist, node->fs, noderev, result_pool,
+                                 scratch_pool));
 
   *proplist_p = proplist;
 
@@ -501,14 +548,14 @@ svn_fs_x__dag_get_proplist(apr_hash_t **
 svn_error_t *
 svn_fs_x__dag_set_proplist(dag_node_t *node,
                            apr_hash_t *proplist,
-                           apr_pool_t *pool)
+                           apr_pool_t *scratch_pool)
 {
-  node_revision_t *noderev;
+  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, pool);
+      svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
       return svn_error_createf
         (SVN_ERR_FS_NOT_MUTABLE, NULL,
          "Can't set proplist on *immutable* node-revision %s",
@@ -519,21 +566,21 @@ svn_fs_x__dag_set_proplist(dag_node_t *n
   SVN_ERR(get_node_revision(&noderev, node));
 
   /* Set the new proplist. */
-  return svn_fs_x__set_proplist(node->fs, noderev, proplist, pool);
+  return svn_fs_x__set_proplist(node->fs, noderev, proplist, scratch_pool);
 }
 
 
 svn_error_t *
 svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node,
                                         apr_int64_t increment,
-                                        apr_pool_t *pool)
+                                        apr_pool_t *scratch_pool)
 {
-  node_revision_t *noderev;
+  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, pool);
+      svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
       return svn_error_createf
         (SVN_ERR_FS_NOT_MUTABLE, NULL,
          "Can't increment mergeinfo count on *immutable* node-revision %s",
@@ -549,10 +596,10 @@ svn_fs_x__dag_increment_mergeinfo_count(
   noderev->mergeinfo_count += increment;
   if (noderev->mergeinfo_count < 0)
     {
-      svn_string_t *idstr = svn_fs_x__id_unparse(node->id, pool);
+      svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
       return svn_error_createf
         (SVN_ERR_FS_CORRUPT, NULL,
-         apr_psprintf(pool,
+         apr_psprintf(scratch_pool,
                       _("Can't increment mergeinfo count on node-revision %%s "
                         "to negative value %%%s"),
                       APR_INT64_T_FMT),
@@ -560,10 +607,10 @@ svn_fs_x__dag_increment_mergeinfo_count(
     }
   if (noderev->mergeinfo_count > 1 && noderev->kind == svn_node_file)
     {
-      svn_string_t *idstr = svn_fs_x__id_unparse(node->id, pool);
+      svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
       return svn_error_createf
         (SVN_ERR_FS_CORRUPT, NULL,
-         apr_psprintf(pool,
+         apr_psprintf(scratch_pool,
                       _("Can't increment mergeinfo count on *file* "
                         "node-revision %%s to %%%s (> 1)"),
                       APR_INT64_T_FMT),
@@ -571,21 +618,20 @@ svn_fs_x__dag_increment_mergeinfo_count(
     }
 
   /* Flush it out. */
-  return svn_fs_x__put_node_revision(node->fs, noderev->id,
-                                     noderev, FALSE, pool);
+  return svn_fs_x__put_node_revision(node->fs, noderev, FALSE, scratch_pool);
 }
 
 svn_error_t *
 svn_fs_x__dag_set_has_mergeinfo(dag_node_t *node,
-                                 svn_boolean_t has_mergeinfo,
-                                 apr_pool_t *pool)
+                                svn_boolean_t has_mergeinfo,
+                                apr_pool_t *scratch_pool)
 {
-  node_revision_t *noderev;
+  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, pool);
+      svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool);
       return svn_error_createf
         (SVN_ERR_FS_NOT_MUTABLE, NULL,
          "Can't set mergeinfo flag on *immutable* node-revision %s",
@@ -598,8 +644,7 @@ svn_fs_x__dag_set_has_mergeinfo(dag_node
   noderev->has_mergeinfo = has_mergeinfo;
 
   /* Flush it out. */
-  return svn_fs_x__put_node_revision(node->fs, noderev->id,
-                                     noderev, FALSE, pool);
+  return svn_fs_x__put_node_revision(node->fs, noderev, FALSE, scratch_pool);
 }
 
 
@@ -609,22 +654,23 @@ 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 *pool)
+                            apr_pool_t *result_pool)
 {
   dag_node_t *new_node;
 
   /* Construct the node. */
-  new_node = apr_pcalloc(pool, sizeof(*new_node));
+  new_node = apr_pcalloc(result_pool, sizeof(*new_node));
   new_node->fs = fs;
-  SVN_ERR(svn_fs_x__rev_get_root(&new_node->id, fs, rev, pool, pool));
+  new_node->revision = rev;
+  svn_fs_x__init_rev_root(&new_node->id, rev);
 
   /* Grab the contents so we can inspect the node's kind and created path. */
-  new_node->node_pool = pool;
+  new_node->node_pool = result_pool;
 
   /* Initialize the KIND and CREATED_PATH attributes */
   new_node->kind = svn_node_dir;
   new_node->created_path = "/";
-  new_node->fresh_root_predecessor_id = NULL;
+  new_node->hint = APR_SIZE_MAX;
 
   /* Return a fresh new node */
   *node_p = new_node;
@@ -636,12 +682,12 @@ 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 *pool)
+                       apr_pool_t *result_pool)
 {
-  const svn_fs_id_t *root_id, *ignored;
+  svn_fs_x__id_t root_id;
 
-  SVN_ERR(svn_fs_x__get_txn_ids(&root_id, &ignored, fs, txn_id, pool));
-  return svn_fs_x__dag_get_node(node_p, fs, root_id, pool);
+  svn_fs_x__init_txn_root(&root_id, txn_id);
+  return svn_fs_x__dag_get_node(node_p, fs, &root_id, result_pool);
 }
 
 
@@ -649,12 +695,16 @@ svn_error_t *
 svn_fs_x__dag_txn_base_root(dag_node_t **node_p,
                             svn_fs_t *fs,
                             svn_fs_x__txn_id_t txn_id,
-                            apr_pool_t *pool)
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
 {
-  const svn_fs_id_t *base_root_id, *ignored;
+  svn_fs_x__id_t base_root_id;
+  svn_revnum_t base_rev;
+
+  SVN_ERR(svn_fs_x__get_base_rev(&base_rev, fs, txn_id, scratch_pool));
 
-  SVN_ERR(svn_fs_x__get_txn_ids(&ignored, &base_root_id, fs, txn_id, pool));
-  return svn_fs_x__dag_get_node(node_p, fs, base_root_id, pool);
+  svn_fs_x__init_rev_root(&base_root_id, base_rev);
+  return svn_fs_x__dag_get_node(node_p, fs, &base_root_id, result_pool);
 }
 
 
@@ -663,15 +713,15 @@ svn_fs_x__dag_clone_child(dag_node_t **c
                           dag_node_t *parent,
                           const char *parent_path,
                           const char *name,
-                          const svn_fs_x__id_part_t *copy_id,
+                          const svn_fs_x__id_t *copy_id,
                           svn_fs_x__txn_id_t txn_id,
                           svn_boolean_t is_parent_copyroot,
-                          apr_pool_t *pool)
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
 {
   dag_node_t *cur_entry; /* parent's current entry named NAME */
-  const svn_fs_id_t *new_node_id; /* node id we'll put into NEW_NODE */
+  const svn_fs_x__id_t *new_node_id; /* node id we'll put into NEW_NODE */
   svn_fs_t *fs = svn_fs_x__dag_get_fs(parent);
-  apr_pool_t *subpool = svn_pool_create(pool);
 
   /* First check that the parent is mutable. */
   if (! svn_fs_x__dag_check_mutable(parent))
@@ -686,7 +736,8 @@ svn_fs_x__dag_clone_child(dag_node_t **c
        "Attempted to make a child clone with an illegal name '%s'", name);
 
   /* Find the node named NAME in PARENT's entries list if it exists. */
-  SVN_ERR(svn_fs_x__dag_open(&cur_entry, parent, name, pool, subpool));
+  SVN_ERR(svn_fs_x__dag_open(&cur_entry, parent, name, scratch_pool,
+                             scratch_pool));
   if (! cur_entry)
     return svn_error_createf
       (SVN_ERR_FS_NOT_FOUND, NULL,
@@ -697,11 +748,11 @@ svn_fs_x__dag_clone_child(dag_node_t **c
   if (svn_fs_x__dag_check_mutable(cur_entry))
     {
       /* This has already been cloned */
-      new_node_id = cur_entry->id;
+      new_node_id = svn_fs_x__dag_get_id(cur_entry);
     }
   else
     {
-      node_revision_t *noderev, *parent_noderev;
+      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));
@@ -710,30 +761,33 @@ svn_fs_x__dag_clone_child(dag_node_t **c
         {
           SVN_ERR(get_node_revision(&parent_noderev, parent));
           noderev->copyroot_rev = parent_noderev->copyroot_rev;
-          noderev->copyroot_path = apr_pstrdup(pool,
+          noderev->copyroot_path = apr_pstrdup(scratch_pool,
                                                parent_noderev->copyroot_path);
         }
 
       noderev->copyfrom_path = NULL;
       noderev->copyfrom_rev = SVN_INVALID_REVNUM;
 
-      noderev->predecessor_id = svn_fs_x__id_copy(cur_entry->id, pool);
-      if (noderev->predecessor_count != -1)
-        noderev->predecessor_count++;
-      noderev->created_path = svn_fspath__join(parent_path, name, pool);
-
-      SVN_ERR(svn_fs_x__create_successor(&new_node_id, fs, cur_entry->id,
-                                          noderev, copy_id, txn_id, pool));
+      noderev->predecessor_id = noderev->noderev_id;
+      noderev->predecessor_count++;
+      noderev->created_path = svn_fspath__join(parent_path, name,
+                                               scratch_pool);
+
+      if (copy_id == NULL)
+        copy_id = &noderev->copy_id;
+
+      SVN_ERR(svn_fs_x__create_successor(fs, noderev, copy_id, txn_id,
+                                         scratch_pool));
+      new_node_id = &noderev->noderev_id;
 
       /* Replace the ID in the parent's ENTRY list with the ID which
          refers to the mutable clone of this child. */
       SVN_ERR(set_entry(parent, name, new_node_id, noderev->kind, txn_id,
-                        pool));
+                        scratch_pool));
     }
 
   /* Initialize the youngster. */
-  svn_pool_destroy(subpool);
-  return svn_fs_x__dag_get_node(child_p, fs, new_node_id, pool);
+  return svn_fs_x__dag_get_node(child_p, fs, new_node_id, result_pool);
 }
 
 
@@ -742,26 +796,62 @@ svn_error_t *
 svn_fs_x__dag_clone_root(dag_node_t **root_p,
                          svn_fs_t *fs,
                          svn_fs_x__txn_id_t txn_id,
-                         apr_pool_t *pool)
+                         apr_pool_t *result_pool)
 {
-  const svn_fs_id_t *base_root_id, *root_id;
-
-  /* Get the node ID's of the root directories of the transaction and
-     its base revision.  */
-  SVN_ERR(svn_fs_x__get_txn_ids(&root_id, &base_root_id, fs, txn_id, pool));
-
-  /* Oh, give me a clone...
-     (If they're the same, we haven't cloned the transaction's root
-     directory yet.)  */
-  SVN_ERR_ASSERT(!svn_fs_x__id_eq(root_id, base_root_id));
-
-  /*
-   * (Sung to the tune of "Home, Home on the Range", with thanks to
-   * Randall Garrett and Isaac Asimov.)
-   */
+  svn_fs_x__id_t root_id;
+  svn_fs_x__init_txn_root(&root_id, txn_id);
 
   /* One way or another, root_id now identifies a cloned root node. */
-  return svn_fs_x__dag_get_node(root_p, fs, root_id, pool);
+  return svn_fs_x__dag_get_node(root_p, fs, &root_id, result_pool);
+}
+
+
+/* Delete all mutable node revisions reachable from node ID, including
+   ID itself, from FS's `nodes' table.  Also delete any mutable
+   representations and strings associated with that node revision.
+   ID may refer to a file or directory, which may be mutable or immutable.
+
+   Use SCRATCH_POOL for temporary allocations.
+ */
+static svn_error_t *
+delete_if_mutable(svn_fs_t *fs,
+                  const svn_fs_x__id_t *id,
+                  apr_pool_t *scratch_pool)
+{
+  dag_node_t *node;
+
+  /* Get the node. */
+  SVN_ERR(svn_fs_x__dag_get_node(&node, fs, id, scratch_pool));
+
+  /* If immutable, do nothing and return immediately. */
+  if (! svn_fs_x__dag_check_mutable(node))
+    return SVN_NO_ERROR;
+
+  /* Else it's mutable.  Recurse on directories... */
+  if (node->kind == svn_node_dir)
+    {
+      apr_array_header_t *entries;
+      int i;
+      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+      /* Loop over directory entries */
+      SVN_ERR(svn_fs_x__dag_dir_entries(&entries, node, scratch_pool,
+                                        iterpool));
+      for (i = 0; i < entries->nelts; ++i)
+        {
+          const svn_fs_x__id_t *noderev_id
+            = &APR_ARRAY_IDX(entries, i, svn_fs_x__dirent_t *)->id;
+
+          svn_pool_clear(iterpool);
+          SVN_ERR(delete_if_mutable(fs, noderev_id, iterpool));
+        }
+
+      svn_pool_destroy(iterpool);
+    }
+
+  /* ... then delete the node itself, after deleting any mutable
+     representations and strings it points to. */
+  return svn_fs_x__delete_node_revision(fs, id, scratch_pool);
 }
 
 
@@ -769,12 +859,11 @@ svn_error_t *
 svn_fs_x__dag_delete(dag_node_t *parent,
                      const char *name,
                      svn_fs_x__txn_id_t txn_id,
-                     apr_pool_t *pool)
+                     apr_pool_t *scratch_pool)
 {
-  node_revision_t *parent_noderev;
+  svn_fs_x__noderev_t *parent_noderev;
   svn_fs_t *fs = parent->fs;
-  svn_fs_dirent_t *dirent;
-  svn_fs_id_t *id;
+  svn_fs_x__dirent_t *dirent;
   apr_pool_t *subpool;
 
   /* Make sure parent is a directory. */
@@ -798,11 +887,12 @@ svn_fs_x__dag_delete(dag_node_t *parent,
   /* Get a fresh NODE-REVISION for the parent node. */
   SVN_ERR(get_node_revision(&parent_noderev, parent));
 
-  subpool = svn_pool_create(pool);
+  subpool = svn_pool_create(scratch_pool);
 
   /* Search this directory for a dirent with that NAME. */
   SVN_ERR(svn_fs_x__rep_contents_dir_entry(&dirent, fs, parent_noderev,
-                                           name, subpool, subpool));
+                                           name, &parent->hint,
+                                           subpool, subpool));
 
   /* If we never found ID in ENTRIES (perhaps because there are no
      ENTRIES, perhaps because ID just isn't in the existing ENTRIES
@@ -812,84 +902,29 @@ svn_fs_x__dag_delete(dag_node_t *parent,
       (SVN_ERR_FS_NO_SUCH_ENTRY, NULL,
        "Delete failed--directory has no entry '%s'", name);
 
-  /* Copy the ID out of the subpool and release the rest of the
-     directory listing. */
-  id = svn_fs_x__id_copy(dirent->id, pool);
-  svn_pool_destroy(subpool);
-
   /* If mutable, remove it and any mutable children from db. */
-  SVN_ERR(svn_fs_x__dag_delete_if_mutable(parent->fs, id, pool));
+  SVN_ERR(delete_if_mutable(parent->fs, &dirent->id, scratch_pool));
+  svn_pool_destroy(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, pool);
+                             NULL, svn_node_unknown, parent->node_pool,
+                             scratch_pool);
 }
 
 
 svn_error_t *
-svn_fs_x__dag_remove_node(svn_fs_t *fs,
-                          const svn_fs_id_t *id,
-                          apr_pool_t *pool)
-{
-  dag_node_t *node;
-
-  /* Fetch the node. */
-  SVN_ERR(svn_fs_x__dag_get_node(&node, fs, id, pool));
-
-  /* If immutable, do nothing and return immediately. */
-  if (! svn_fs_x__dag_check_mutable(node))
-    return svn_error_createf(SVN_ERR_FS_NOT_MUTABLE, NULL,
-                             "Attempted removal of immutable node");
-
-  /* Delete the node revision. */
-  return svn_fs_x__delete_node_revision(fs, id, pool);
-}
-
-
-svn_error_t *
-svn_fs_x__dag_delete_if_mutable(svn_fs_t *fs,
-                                const svn_fs_id_t *id,
-                                apr_pool_t *pool)
-{
-  dag_node_t *node;
-
-  /* Get the node. */
-  SVN_ERR(svn_fs_x__dag_get_node(&node, fs, id, pool));
-
-  /* If immutable, do nothing and return immediately. */
-  if (! svn_fs_x__dag_check_mutable(node))
-    return SVN_NO_ERROR;
-
-  /* Else it's mutable.  Recurse on directories... */
-  if (node->kind == svn_node_dir)
-    {
-      apr_array_header_t *entries;
-      int i;
-
-      /* Loop over directory entries */
-      SVN_ERR(svn_fs_x__dag_dir_entries(&entries, node, pool));
-      if (entries)
-        for (i = 0; i < entries->nelts; ++i)
-          SVN_ERR(svn_fs_x__dag_delete_if_mutable(fs,
-                        APR_ARRAY_IDX(entries, i, svn_fs_dirent_t *)->id,
-                        pool));
-    }
-
-  /* ... then delete the node itself, after deleting any mutable
-     representations and strings it points to. */
-  return svn_fs_x__dag_remove_node(fs, id, pool);
-}
-
-svn_error_t *
 svn_fs_x__dag_make_file(dag_node_t **child_p,
                         dag_node_t *parent,
                         const char *parent_path,
                         const char *name,
                         svn_fs_x__txn_id_t txn_id,
-                        apr_pool_t *pool)
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
 {
   /* Call our little helper function */
-  return make_entry(child_p, parent, parent_path, name, FALSE, txn_id, pool);
+  return make_entry(child_p, parent, parent_path, name, FALSE, txn_id,
+                    result_pool, scratch_pool);
 }
 
 
@@ -899,19 +934,21 @@ svn_fs_x__dag_make_dir(dag_node_t **chil
                        const char *parent_path,
                        const char *name,
                        svn_fs_x__txn_id_t txn_id,
-                       apr_pool_t *pool)
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
 {
   /* Call our little helper function */
-  return make_entry(child_p, parent, parent_path, name, TRUE, txn_id, pool);
+  return make_entry(child_p, parent, parent_path, name, TRUE, txn_id,
+                    result_pool, scratch_pool);
 }
 
 
 svn_error_t *
 svn_fs_x__dag_get_contents(svn_stream_t **contents_p,
                            dag_node_t *file,
-                           apr_pool_t *pool)
+                           apr_pool_t *result_pool)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
   svn_stream_t *contents;
 
   /* Make sure our node is a file. */
@@ -925,7 +962,7 @@ svn_fs_x__dag_get_contents(svn_stream_t
 
   /* Get a stream to the contents. */
   SVN_ERR(svn_fs_x__get_contents(&contents, file->fs,
-                                 noderev->data_rep, TRUE, pool));
+                                 noderev->data_rep, TRUE, result_pool));
 
   *contents_p = contents;
 
@@ -937,10 +974,11 @@ svn_error_t *
 svn_fs_x__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
                                     dag_node_t *source,
                                     dag_node_t *target,
-                                    apr_pool_t *pool)
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool)
 {
-  node_revision_t *src_noderev;
-  node_revision_t *tgt_noderev;
+  svn_fs_x__noderev_t *src_noderev;
+  svn_fs_x__noderev_t *tgt_noderev;
 
   /* Make sure our nodes are files. */
   if ((source && source->kind != svn_node_file)
@@ -958,7 +996,8 @@ svn_fs_x__dag_get_file_delta_stream(svn_
 
   /* Get the delta stream. */
   return svn_fs_x__get_file_delta_stream(stream_p, target->fs,
-                                         src_noderev, tgt_noderev, pool);
+                                         src_noderev, tgt_noderev,
+                                         result_pool, scratch_pool);
 }
 
 
@@ -967,25 +1006,24 @@ svn_fs_x__dag_try_process_file_contents(
                                         dag_node_t *node,
                                         svn_fs_process_contents_func_t processor,
                                         void* baton,
-                                        apr_pool_t *pool)
+                                        apr_pool_t *scratch_pool)
 {
-  node_revision_t *noderev;
+  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,
-                                             processor, baton, pool);
+                                             processor, baton, scratch_pool);
 }
 
 
 svn_error_t *
 svn_fs_x__dag_file_length(svn_filesize_t *length,
-                          dag_node_t *file,
-                          apr_pool_t *pool)
+                          dag_node_t *file)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   /* Make sure our node is a file. */
   if (file->kind != svn_node_file)
@@ -996,7 +1034,7 @@ svn_fs_x__dag_file_length(svn_filesize_t
   /* Go get a fresh node-revision for FILE, and . */
   SVN_ERR(get_node_revision(&noderev, file));
 
-  return svn_fs_x__file_length(length, noderev, pool);
+  return svn_fs_x__file_length(length, noderev);
 }
 
 
@@ -1004,9 +1042,9 @@ svn_error_t *
 svn_fs_x__dag_file_checksum(svn_checksum_t **checksum,
                             dag_node_t *file,
                             svn_checksum_kind_t kind,
-                            apr_pool_t *pool)
+                            apr_pool_t *result_pool)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   if (file->kind != svn_node_file)
     return svn_error_createf
@@ -1015,16 +1053,16 @@ svn_fs_x__dag_file_checksum(svn_checksum
 
   SVN_ERR(get_node_revision(&noderev, file));
 
-  return svn_fs_x__file_checksum(checksum, noderev, kind, pool);
+  return svn_fs_x__file_checksum(checksum, noderev, kind, result_pool);
 }
 
 
 svn_error_t *
 svn_fs_x__dag_get_edit_stream(svn_stream_t **contents,
                               dag_node_t *file,
-                              apr_pool_t *pool)
+                              apr_pool_t *result_pool)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
   svn_stream_t *ws;
 
   /* Make sure our node is a file. */
@@ -1042,7 +1080,7 @@ svn_fs_x__dag_get_edit_stream(svn_stream
   /* Get the node revision. */
   SVN_ERR(get_node_revision(&noderev, file));
 
-  SVN_ERR(svn_fs_x__set_contents(&ws, file->fs, noderev, pool));
+  SVN_ERR(svn_fs_x__set_contents(&ws, file->fs, noderev, result_pool));
 
   *contents = ws;
 
@@ -1054,16 +1092,17 @@ svn_fs_x__dag_get_edit_stream(svn_stream
 svn_error_t *
 svn_fs_x__dag_finalize_edits(dag_node_t *file,
                              const svn_checksum_t *checksum,
-                             apr_pool_t *pool)
+                             apr_pool_t *scratch_pool)
 {
   if (checksum)
     {
       svn_checksum_t *file_checksum;
 
       SVN_ERR(svn_fs_x__dag_file_checksum(&file_checksum, file,
-                                          checksum->kind, pool));
+                                          checksum->kind, scratch_pool));
       if (!svn_checksum_match(checksum, file_checksum))
-        return svn_checksum_mismatch_err(checksum, file_checksum, pool,
+        return svn_checksum_mismatch_err(checksum, file_checksum,
+                                         scratch_pool,
                                          _("Checksum mismatch for '%s'"),
                                          file->created_path);
     }
@@ -1074,30 +1113,38 @@ svn_fs_x__dag_finalize_edits(dag_node_t
 
 dag_node_t *
 svn_fs_x__dag_dup(const dag_node_t *node,
-                  apr_pool_t *pool)
+                  apr_pool_t *result_pool)
 {
   /* Allocate our new node. */
-  dag_node_t *new_node = apr_pcalloc(pool, sizeof(*new_node));
-
-  new_node->fs = node->fs;
-  new_node->id = svn_fs_x__id_copy(node->id, pool);
-  new_node->kind = node->kind;
-  new_node->created_path = apr_pstrdup(pool, node->created_path);
+  dag_node_t *new_node = apr_pmemdup(result_pool, node, sizeof(*new_node));
 
-  /* Only copy cached node_revision_t for immutable nodes. */
+  /* 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, pool);
-      new_node->node_revision->id =
-          svn_fs_x__id_copy(node->node_revision->id, pool);
-      new_node->node_revision->is_fresh_txn_root =
-          node->node_revision->is_fresh_txn_root;
+      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);
     }
-  new_node->node_pool = 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,
@@ -1116,20 +1163,20 @@ svn_fs_x__dag_serialize(void **data,
 
   /* 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);
+    {
+      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__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);
 
-  /* serialize other sub-structures */
-  svn_fs_x__id_serialize(context, (const svn_fs_id_t **)&node->id);
-  svn_fs_x__id_serialize(context, &node->fresh_root_predecessor_id);
-  svn_temp_serializer__add_string(context, &node->created_path);
-
   /* return serialized data */
   serialized = svn_temp_serializer__get(context);
   *data = serialized->data;
@@ -1153,14 +1200,13 @@ svn_fs_x__dag_deserialize(void **out,
   node->fs = NULL;
 
   /* fixup all references to sub-structures */
-  svn_fs_x__id_deserialize(node, &node->id, pool);
-  svn_fs_x__id_deserialize(node,
-                           (svn_fs_id_t **)&node->fresh_root_predecessor_id,
-                           pool);
   svn_fs_x__noderev_deserialize(node, &node->node_revision, pool);
   node->node_pool = pool;
 
-  svn_temp_deserializer__resolve(node, (void**)&node->created_path);
+  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;
@@ -1175,12 +1221,11 @@ svn_fs_x__dag_open(dag_node_t **child_p,
                    apr_pool_t *result_pool,
                    apr_pool_t *scratch_pool)
 {
-  const svn_fs_id_t *node_id;
+  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, scratch_pool));
-  if (! node_id)
+  SVN_ERR(dir_entry_id_from_node(&node_id, parent, name, scratch_pool));
+  if (! svn_fs_x__id_used(&node_id))
     {
       *child_p = NULL;
       return SVN_NO_ERROR;
@@ -1194,7 +1239,7 @@ svn_fs_x__dag_open(dag_node_t **child_p,
 
   /* Now get the node that was requested. */
   return svn_fs_x__dag_get_node(child_p, svn_fs_x__dag_get_fs(parent),
-                                node_id, result_pool);
+                                &node_id, result_pool);
 }
 
 
@@ -1206,41 +1251,39 @@ svn_fs_x__dag_copy(dag_node_t *to_node,
                    svn_revnum_t from_rev,
                    const char *from_path,
                    svn_fs_x__txn_id_t txn_id,
-                   apr_pool_t *pool)
+                   apr_pool_t *scratch_pool)
 {
-  const svn_fs_id_t *id;
+  const svn_fs_x__id_t *id;
 
   if (preserve_history)
     {
-      node_revision_t *from_noderev, *to_noderev;
-      svn_fs_x__id_part_t copy_id;
-      const svn_fs_id_t *src_id = svn_fs_x__dag_get_id(from_node);
+      svn_fs_x__noderev_t *from_noderev, *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, pool);
+      to_noderev = copy_node_revision(from_noderev, scratch_pool);
 
       /* Reserve a copy ID for this new copy. */
-      SVN_ERR(svn_fs_x__reserve_copy_id(&copy_id, fs, txn_id, pool));
+      SVN_ERR(svn_fs_x__reserve_copy_id(&copy_id, fs, txn_id, scratch_pool));
 
       /* Create a successor with its predecessor pointing at the copy
          source. */
-      to_noderev->predecessor_id = svn_fs_x__id_copy(src_id, pool);
-      if (to_noderev->predecessor_count != -1)
-        to_noderev->predecessor_count++;
+      to_noderev->predecessor_id = to_noderev->noderev_id;
+      to_noderev->predecessor_count++;
       to_noderev->created_path =
         svn_fspath__join(svn_fs_x__dag_get_created_path(to_node), entry,
-                         pool);
-      to_noderev->copyfrom_path = apr_pstrdup(pool, from_path);
+                         scratch_pool);
+      to_noderev->copyfrom_path = apr_pstrdup(scratch_pool, from_path);
       to_noderev->copyfrom_rev = from_rev;
 
       /* Set the copyroot equal to our own id. */
       to_noderev->copyroot_path = NULL;
 
-      SVN_ERR(svn_fs_x__create_successor(&id, fs, src_id, to_noderev,
-                                         &copy_id, txn_id, pool));
-
+      SVN_ERR(svn_fs_x__create_successor(fs, to_noderev,
+                                         &copy_id, txn_id, scratch_pool));
+      id = &to_noderev->noderev_id;
     }
   else  /* don't preserve history */
     {
@@ -1249,7 +1292,7 @@ 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,
-                                 txn_id, pool);
+                                 txn_id, scratch_pool);
 }
 
 
@@ -1262,9 +1305,9 @@ svn_fs_x__dag_things_different(svn_boole
                                dag_node_t *node1,
                                dag_node_t *node2,
                                svn_boolean_t strict,
-                               apr_pool_t *pool)
+                               apr_pool_t *scratch_pool)
 {
-  node_revision_t *noderev1, *noderev2;
+  svn_fs_x__noderev_t *noderev1, *noderev2;
   svn_fs_t *fs;
   svn_boolean_t same;
 
@@ -1283,7 +1326,7 @@ svn_fs_x__dag_things_different(svn_boole
   if (props_changed != NULL)
     {
       SVN_ERR(svn_fs_x__prop_rep_equal(&same, fs, noderev1, noderev2,
-                                       strict, pool));
+                                       strict, scratch_pool));
       *props_changed = !same;
     }
 
@@ -1300,7 +1343,7 @@ svn_fs_x__dag_get_copyroot(svn_revnum_t
                            const char **path,
                            dag_node_t *node)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   /* Go get a fresh node-revision for NODE. */
   SVN_ERR(get_node_revision(&noderev, node));
@@ -1315,7 +1358,7 @@ svn_error_t *
 svn_fs_x__dag_get_copyfrom_rev(svn_revnum_t *rev,
                                dag_node_t *node)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   /* Go get a fresh node-revision for NODE. */
   SVN_ERR(get_node_revision(&noderev, node));
@@ -1329,7 +1372,7 @@ svn_error_t *
 svn_fs_x__dag_get_copyfrom_path(const char **path,
                                 dag_node_t *node)
 {
-  node_revision_t *noderev;
+  svn_fs_x__noderev_t *noderev;
 
   /* Go get a fresh node-revision for NODE. */
   SVN_ERR(get_node_revision(&noderev, node));
@@ -1342,9 +1385,9 @@ svn_fs_x__dag_get_copyfrom_path(const ch
 svn_error_t *
 svn_fs_x__dag_update_ancestry(dag_node_t *target,
                               dag_node_t *source,
-                              apr_pool_t *pool)
+                              apr_pool_t *scratch_pool)
 {
-  node_revision_t *source_noderev, *target_noderev;
+  svn_fs_x__noderev_t *source_noderev, *target_noderev;
 
   if (! svn_fs_x__dag_check_mutable(target))
     return svn_error_createf
@@ -1354,11 +1397,10 @@ svn_fs_x__dag_update_ancestry(dag_node_t
   SVN_ERR(get_node_revision(&source_noderev, source));
   SVN_ERR(get_node_revision(&target_noderev, target));
 
-  target_noderev->predecessor_id = source->id;
+  target_noderev->predecessor_id = source_noderev->noderev_id;
   target_noderev->predecessor_count = source_noderev->predecessor_count;
-  if (target_noderev->predecessor_count != -1)
-    target_noderev->predecessor_count++;
+  target_noderev->predecessor_count++;
 
-  return svn_fs_x__put_node_revision(target->fs, target->id, target_noderev,
-                                     FALSE, pool);
+  return svn_fs_x__put_node_revision(target->fs, target_noderev, FALSE,
+                                     scratch_pool);
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_x/dag.h?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_x/dag.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_x/dag.h Tue Jan 20 17:52:18 2015
@@ -27,6 +27,7 @@
 #include "svn_delta.h"
 #include "private/svn_cache.h"
 
+#include "fs.h"
 #include "id.h"
 
 #ifdef __cplusplus
@@ -64,21 +65,27 @@ extern "C" {
 typedef struct dag_node_t dag_node_t;
 
 /* Fill *NODE with a dag_node_t representing node revision ID in FS,
-   allocating in POOL.  */
+   allocating in RESULT_POOL.  */
 svn_error_t *
 svn_fs_x__dag_get_node(dag_node_t **node,
                        svn_fs_t *fs,
-                       const svn_fs_id_t *id,
-                       apr_pool_t *pool);
+                       const svn_fs_x__id_t *id,
+                       apr_pool_t *result_pool);
 
 
 /* Return a new dag_node_t object referring to the same node as NODE,
-   allocated in POOL.  If you're trying to build a structure in a
+   allocated in RESULT_POOL.  If you're trying to build a structure in a
    pool that wants to refer to dag nodes that may have been allocated
    elsewhere, you can call this function and avoid inter-pool pointers. */
 dag_node_t *
 svn_fs_x__dag_dup(const dag_node_t *node,
-                  apr_pool_t *pool);
+                  apr_pool_t *result_pool);
+
+/* If NODE has been allocated in POOL, return NODE.  Otherwise, return
+   a copy created in RESULT_POOL with svn_fs_fs__dag_dup. */
+dag_node_t *
+svn_fs_x__dag_copy_into_pool(dag_node_t *node,
+                             apr_pool_t *result_pool);
 
 /* Serialize a DAG node, except don't try to preserve the 'fs' member.
    Implements svn_cache__serialize_func_t */
@@ -97,50 +104,78 @@ svn_fs_x__dag_deserialize(void **out,
                           apr_pool_t *pool);
 
 /* Return the filesystem containing NODE.  */
-svn_fs_t *svn_fs_x__dag_get_fs(dag_node_t *node);
+svn_fs_t *
+svn_fs_x__dag_get_fs(dag_node_t *node);
 
 /* Changes the filesystem containing NODE to FS.  (Used when pulling
    nodes out of a shared cache, say.) */
-void svn_fs_x__dag_set_fs(dag_node_t *node, svn_fs_t *fs);
+void
+svn_fs_x__dag_set_fs(dag_node_t *node,
+                     svn_fs_t *fs);
 
 
-/* Set *REV to NODE's revision number, allocating in POOL.  If NODE
-   has never been committed as part of a revision, set *REV to
-   SVN_INVALID_REVNUM.  */
-svn_error_t *svn_fs_x__dag_get_revision(svn_revnum_t *rev,
-                                        dag_node_t *node,
-                                        apr_pool_t *pool);
+/* Return NODE's revision number.  If NODE has never been committed as
+   part of a revision, set *REV to SVN_INVALID_REVNUM.  */
+svn_revnum_t
+svn_fs_x__dag_get_revision(const dag_node_t *node);
 
 
 /* Return the node revision ID of NODE.  The value returned is shared
    with NODE, and will be deallocated when NODE is.  */
-const svn_fs_id_t *svn_fs_x__dag_get_id(const dag_node_t *node);
+const svn_fs_x__id_t *
+svn_fs_x__dag_get_id(const dag_node_t *node);
+
+/* 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_get_node_id(svn_fs_x__id_t *node_id,
+                          dag_node_t *node);
+
+/* Return the copy 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);
+
+/* Set *SAME to TRUE, if nodes LHS and RHS have the same node ID. */
+svn_error_t *
+svn_fs_x__dag_related_node(svn_boolean_t *same,
+                           dag_node_t *lhs,
+                           dag_node_t *rhs);
 
+/* Set *SAME to TRUE, if nodes LHS and RHS have the same node and copy IDs.
+ */
+svn_error_t *
+svn_fs_x__dag_same_line_of_history(svn_boolean_t *same,
+                                   dag_node_t *lhs,
+                                   dag_node_t *rhs);
 
 /* Return the created path of NODE.  The value returned is shared
    with NODE, and will be deallocated when NODE is.  */
-const char *svn_fs_x__dag_get_created_path(dag_node_t *node);
+const char *
+svn_fs_x__dag_get_created_path(dag_node_t *node);
 
 
-/* Set *ID_P to the node revision ID of NODE's immediate predecessor,
-   or NULL if NODE has no predecessor.
+/* Set *ID_P to the node revision ID of NODE's immediate predecessor.
  */
-svn_error_t *svn_fs_x__dag_get_predecessor_id(const svn_fs_id_t **id_p,
-                                              dag_node_t *node);
+svn_error_t *
+svn_fs_x__dag_get_predecessor_id(svn_fs_x__id_t *id_p,
+                                 dag_node_t *node);
 
 
-/* Set *COUNT to the number of predecessors NODE has (recursively), or
-   -1 if not known.
+/* Set *COUNT to the number of predecessors NODE has (recursively).
  */
 /* ### This function is currently only used by 'verify'. */
-svn_error_t *svn_fs_x__dag_get_predecessor_count(int *count,
-                                                 dag_node_t *node);
+svn_error_t *
+svn_fs_x__dag_get_predecessor_count(int *count,
+                                    dag_node_t *node);
 
 /* Set *COUNT to the number of node under NODE (inclusive) with
    svn:mergeinfo properties.
  */
-svn_error_t *svn_fs_x__dag_get_mergeinfo_count(apr_int64_t *count,
-                                               dag_node_t *node);
+svn_error_t *
+svn_fs_x__dag_get_mergeinfo_count(apr_int64_t *count,
+                                  dag_node_t *node);
 
 /* Set *DO_THEY to a flag indicating whether or not NODE is a
    directory with at least one descendant (not including itself) with
@@ -158,10 +193,12 @@ svn_fs_x__dag_has_mergeinfo(svn_boolean_
                             dag_node_t *node);
 
 /* Return non-zero IFF NODE is currently mutable. */
-svn_boolean_t svn_fs_x__dag_check_mutable(const dag_node_t *node);
+svn_boolean_t
+svn_fs_x__dag_check_mutable(const dag_node_t *node);
 
 /* Return the node kind of NODE. */
-svn_node_kind_t svn_fs_x__dag_node_kind(dag_node_t *node);
+svn_node_kind_t
+svn_fs_x__dag_node_kind(dag_node_t *node);
 
 /* Set *PROPLIST_P to a PROPLIST hash representing the entire property
    list of NODE, allocating from POOL.  The hash has const char *
@@ -171,38 +208,43 @@ svn_node_kind_t svn_fs_x__dag_node_kind(
    If properties do not exist on NODE, *PROPLIST_P will be set to
    NULL.
 
-   Use POOL for all allocations.
+   Allocate the result in RESULT_POOL and use SCRATCH_POOL for temporaries. 
  */
-svn_error_t *svn_fs_x__dag_get_proplist(apr_hash_t **proplist_p,
-                                        dag_node_t *node,
-                                        apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_get_proplist(apr_hash_t **proplist_p,
+                           dag_node_t *node,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool);
 
 /* Set the property list of NODE to PROPLIST, allocating from POOL.
    The node being changed must be mutable.
 
-   Use POOL for all allocations.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_set_proplist(dag_node_t *node,
-                                        apr_hash_t *proplist,
-                                        apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_set_proplist(dag_node_t *node,
+                           apr_hash_t *proplist,
+                           apr_pool_t *scratch_pool);
 
 /* Increment the mergeinfo_count field on NODE by INCREMENT.  The node
    being changed must be mutable.
 
-   Use POOL for all allocations.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node,
-                                                     apr_int64_t increment,
-                                                     apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node,
+                                        apr_int64_t increment,
+                                        apr_pool_t *scratch_pool);
 
 /* Set the has-mergeinfo flag on NODE to HAS_MERGEINFO.  The node
    being changed must be mutable.
 
-   Use POOL for all allocations.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_set_has_mergeinfo(dag_node_t *node,
-                                             svn_boolean_t has_mergeinfo,
-                                             apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_set_has_mergeinfo(dag_node_t *node,
+                                svn_boolean_t has_mergeinfo,
+                                apr_pool_t *scratch_pool);
 
 
 
@@ -210,42 +252,48 @@ svn_error_t *svn_fs_x__dag_set_has_merge
 
 
 /* Open the root of revision REV of filesystem FS, allocating from
-   POOL.  Set *NODE_P to the new node.  */
-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 *pool);
+   RESULT_POOL.  Set *NODE_P to the new node. */
+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);
 
 
 /* Set *NODE_P to the root of transaction TXN_ID in FS, allocating
-   from POOL.
+   from RESULT_POOL.
 
    Note that the root node of TXN_ID is not necessarily mutable.  If
    no changes have been made in the transaction, then it may share its
    root directory with its base revision.  To get a mutable root node
    for a transaction, call svn_fs_x__dag_clone_root.  */
-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 *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);
 
 
 /* Set *NODE_P to the base root of transaction TXN_ID in FS,
-   allocating from POOL.  Allocate the node in TRAIL->pool.  */
-svn_error_t *svn_fs_x__dag_txn_base_root(dag_node_t **node_p,
-                                         svn_fs_t *fs,
-                                         svn_fs_x__txn_id_t txn_id,
-                                         apr_pool_t *pool);
+   allocating from RESULT_POOL.  Allocate the node in TRAIL->pool.
+   Use SCRATCH_POOL for temporaries. */
+svn_error_t *
+svn_fs_x__dag_txn_base_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);
 
 
 /* Clone the root directory of TXN_ID in FS, and update the
    `transactions' table entry to point to it, unless this has been
    done already.  In either case, set *ROOT_P to a reference to the
-   root directory clone.  Allocate *ROOT_P in POOL.  */
-svn_error_t *svn_fs_x__dag_clone_root(dag_node_t **root_p,
-                                      svn_fs_t *fs,
-                                      svn_fs_x__txn_id_t txn_id,
-                                      apr_pool_t *pool);
+   root directory clone.  Allocate *ROOT_P in RESULT_POOL.  */
+svn_error_t *
+svn_fs_x__dag_clone_root(dag_node_t **root_p,
+                         svn_fs_t *fs,
+                         svn_fs_x__txn_id_t txn_id,
+                         apr_pool_t *result_pool);
 
 
 
@@ -266,24 +314,13 @@ svn_fs_x__dag_open(dag_node_t **child_p,
 
 
 /* Set *ENTRIES_P to an array of NODE's entries, sorted by entry names,
-   and the values are svn_fs_dirent_t's.  The returned table (and elements)
-   is allocated in POOL, which is also used for temporary allocations. */
-svn_error_t *svn_fs_x__dag_dir_entries(apr_array_header_t **entries_p,
-                                       dag_node_t *node,
-                                       apr_pool_t *pool);
-
-/* Fetches the NODE's entries and returns a copy of the entry selected
-   by the key value given in NAME and set *DIRENT to a copy of that
-   entry. If such entry was found, the copy will be allocated in
-   RESULT_POOL.  Temporary data will be used in SCRATCH_POOL.
-   Otherwise, the *DIRENT will be set to NULL.
- */
-/* ### This function is currently only called from dag.c. */
-svn_error_t * svn_fs_x__dag_dir_entry(svn_fs_dirent_t **dirent,
-                                      dag_node_t *node,
-                                      const char* name,
-                                      apr_pool_t *result_pool,
-                                      apr_pool_t *scratch_pool);
+   and the values are svn_fs_x__dirent_t. The returned table (and elements)
+   is allocated in RESULT_POOL, temporaries in SCRATCH_POOL. */
+svn_error_t *
+svn_fs_x__dag_dir_entries(apr_array_header_t **entries_p,
+                          dag_node_t *node,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool);
 
 /* Set ENTRY_NAME in NODE to point to ID (with kind KIND), allocating
    from POOL.  NODE must be a mutable directory.  ID can refer to a
@@ -291,15 +328,15 @@ svn_error_t * svn_fs_x__dag_dir_entry(sv
    be created.  TXN_ID is the Subversion transaction under which this
    occurs.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_set_entry(dag_node_t *node,
-                                     const char *entry_name,
-                                     const svn_fs_id_t *id,
-                                     svn_node_kind_t kind,
-                                     svn_fs_x__txn_id_t txn_id,
-                                     apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_set_entry(dag_node_t *node,
+                        const char *entry_name,
+                        const svn_fs_x__id_t *id,
+                        svn_node_kind_t kind,
+                        svn_fs_x__txn_id_t txn_id,
+                        apr_pool_t *scratch_pool);
 
 
 /* Make a new mutable clone of the node named NAME in PARENT, and
@@ -319,16 +356,18 @@ svn_error_t *svn_fs_x__dag_set_entry(dag
 
    TXN_ID is the Subversion transaction under which this occurs.
 
-   Use POOL for all allocations.
+   Allocate *CHILD_P in RESULT_POOL and use SCRATCH_POOL for temporaries.
  */
-svn_error_t *svn_fs_x__dag_clone_child(dag_node_t **child_p,
-                                       dag_node_t *parent,
-                                       const char *parent_path,
-                                       const char *name,
-                                       const svn_fs_x__id_part_t *copy_id,
-                                       svn_fs_x__txn_id_t txn_id,
-                                       svn_boolean_t is_parent_copyroot,
-                                       apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_clone_child(dag_node_t **child_p,
+                          dag_node_t *parent,
+                          const char *parent_path,
+                          const char *name,
+                          const svn_fs_x__id_t *copy_id,
+                          svn_fs_x__txn_id_t txn_id,
+                          svn_boolean_t is_parent_copyroot,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool);
 
 
 /* Delete the directory entry named NAME from PARENT, allocating from
@@ -341,40 +380,17 @@ svn_error_t *svn_fs_x__dag_clone_child(d
    If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
    PARENT.
 
-   Use POOL for all allocations.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_delete(dag_node_t *parent,
-                                  const char *name,
-                                  svn_fs_x__txn_id_t txn_id,
-                                  apr_pool_t *pool);
-
-
-/* Delete the node revision assigned to node ID from FS's `nodes'
-   table, allocating from POOL.  Also delete any mutable
-   representations and strings associated with that node revision.  ID
-   may refer to a file or directory, which must be mutable.
-
-   NOTE: If ID represents a directory, and that directory has mutable
-   children, you risk orphaning those children by leaving them
-   dangling, disconnected from all DAG trees.  It is assumed that
-   callers of this interface know what in the world they are doing.  */
-svn_error_t *svn_fs_x__dag_remove_node(svn_fs_t *fs,
-                                       const svn_fs_id_t *id,
-                                       apr_pool_t *pool);
-
-
-/* Delete all mutable node revisions reachable from node ID, including
-   ID itself, from FS's `nodes' table, allocating from POOL.  Also
-   delete any mutable representations and strings associated with that
-   node revision.  ID may refer to a file or directory, which may be
-   mutable or immutable. */
-svn_error_t *svn_fs_x__dag_delete_if_mutable(svn_fs_t *fs,
-                                             const svn_fs_id_t *id,
-                                             apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_delete(dag_node_t *parent,
+                     const char *name,
+                     svn_fs_x__txn_id_t txn_id,
+                     apr_pool_t *scratch_pool);
 
 
 /* Create a new mutable directory named NAME in PARENT.  Set *CHILD_P
-   to a reference to the new node, allocated in POOL.  The new
+   to a reference to the new node, allocated in RESULT_POOL.  The new
    directory has no contents, and no properties.  PARENT must be
    mutable.  NAME must be a single path component; it cannot be a
    slash-separated directory path.  PARENT_PATH must be the
@@ -382,14 +398,16 @@ svn_error_t *svn_fs_x__dag_delete_if_mut
    not currently have an entry named NAME.  TXN_ID is the Subversion
    transaction under which this occurs.
 
-   Use POOL for all allocations.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_make_dir(dag_node_t **child_p,
-                                    dag_node_t *parent,
-                                    const char *parent_path,
-                                    const char *name,
-                                    svn_fs_x__txn_id_t txn_id,
-                                    apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_make_dir(dag_node_t **child_p,
+                       dag_node_t *parent,
+                       const char *parent_path,
+                       const char *name,
+                       svn_fs_x__txn_id_t txn_id,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool);
 
 
 
@@ -397,57 +415,56 @@ svn_error_t *svn_fs_x__dag_make_dir(dag_
 
 
 /* Set *CONTENTS to a readable generic stream which yields the
-   contents of FILE.  Allocate the stream in POOL.
+   contents of FILE.  Allocate the stream in RESULT_POOL.
 
    If FILE is not a file, return SVN_ERR_FS_NOT_FILE.
-
-   Use POOL for all allocations.
  */
-svn_error_t *svn_fs_x__dag_get_contents(svn_stream_t **contents,
-                                        dag_node_t *file,
-                                        apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_get_contents(svn_stream_t **contents,
+                           dag_node_t *file,
+                           apr_pool_t *result_pool);
 
 /* Attempt to fetch the contents of NODE and pass it along with the BATON
    to the PROCESSOR.   Set *SUCCESS only of the data could be provided
    and the processor had been called.
 
-   Use POOL for all allocations.
+   Use SCRATCH_POOL for temporary allocations.
  */
 svn_error_t *
 svn_fs_x__dag_try_process_file_contents(svn_boolean_t *success,
                                         dag_node_t *node,
                                         svn_fs_process_contents_func_t processor,
                                         void* baton,
-                                        apr_pool_t *pool);
+                                        apr_pool_t *scratch_pool);
 
 
 /* Set *STREAM_P to a delta stream that will turn the contents of SOURCE into
-   the contents of TARGET, allocated in POOL.  If SOURCE is null, the empty
-   string will be used.
+   the contents of TARGET, allocated in RESULT_POOL.  If SOURCE is null, the
+   empty string will be used is its stead.
 
-   Use POOL for all allocations.
+   Use SCRATCH_POOL for temporary allocations.
  */
 svn_error_t *
 svn_fs_x__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
                                     dag_node_t *source,
                                     dag_node_t *target,
-                                    apr_pool_t *pool);
+                                    apr_pool_t *result_pool,
+                                    apr_pool_t *scratch_pool);
 
 /* Return a generic writable stream in *CONTENTS with which to set the
-   contents of FILE.  Allocate the stream in POOL.
+   contents of FILE.  Allocate the stream in RESULT_POOL.
 
    Any previous edits on the file will be deleted, and a new edit
    stream will be constructed.
-
-   Use POOL for all allocations.
  */
-svn_error_t *svn_fs_x__dag_get_edit_stream(svn_stream_t **contents,
-                                           dag_node_t *file,
-                                           apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_get_edit_stream(svn_stream_t **contents,
+                              dag_node_t *file,
+                              apr_pool_t *result_pool);
 
 
 /* Signify the completion of edits to FILE made using the stream
-   returned by svn_fs_x__dag_get_edit_stream, allocating from POOL.
+   returned by svn_fs_x__dag_get_edit_stream.
 
    If CHECKSUM is non-null, it must match the checksum for FILE's
    contents (note: this is not recalculated, the recorded checksum is
@@ -455,60 +472,57 @@ svn_error_t *svn_fs_x__dag_get_edit_stre
 
    This operation is a no-op if no edits are present.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   FILE.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_finalize_edits(dag_node_t *file,
-                                          const svn_checksum_t *checksum,
-                                          apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_finalize_edits(dag_node_t *file,
+                             const svn_checksum_t *checksum,
+                             apr_pool_t *scratch_pool);
 
 
 /* Set *LENGTH to the length of the contents of FILE.
-
-   Use POOL for all allocations.
  */
-svn_error_t *svn_fs_x__dag_file_length(svn_filesize_t *length,
-                                       dag_node_t *file,
-                                       apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_file_length(svn_filesize_t *length,
+                          dag_node_t *file);
 
 /* Put the recorded checksum of type KIND for FILE into CHECKSUM, allocating
-   from POOL.
+   from RESULT_POOL.
 
    If no stored checksum is available, do not calculate the checksum,
    just put NULL into CHECKSUM.
-
-   Use POOL for all allocations.
  */
 svn_error_t *
 svn_fs_x__dag_file_checksum(svn_checksum_t **checksum,
                             dag_node_t *file,
                             svn_checksum_kind_t kind,
-                            apr_pool_t *pool);
+                            apr_pool_t *result_pool);
 
 /* Create a new mutable file named NAME in PARENT.  Set *CHILD_P to a
-   reference to the new node, allocated in POOL.  The new file's
+   reference to the new node, allocated in RESULT_POOL.  The new file's
    contents are the empty string, and it has no properties.  PARENT
    must be mutable.  NAME must be a single path component; it cannot
    be a slash-separated directory path.  PARENT_PATH must be the
    canonicalized absolute path of the parent directory.  TXN_ID is the
    Subversion transaction under which this occurs.
 
-   Use POOL for all allocations.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_make_file(dag_node_t **child_p,
-                                     dag_node_t *parent,
-                                     const char *parent_path,
-                                     const char *name,
-                                     svn_fs_x__txn_id_t txn_id,
-                                     apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_make_file(dag_node_t **child_p,
+                        dag_node_t *parent,
+                        const char *parent_path,
+                        const char *name,
+                        svn_fs_x__txn_id_t txn_id,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool);
 
 
 
 /* Copies */
 
-/* Make ENTRY in TO_NODE be a copy of FROM_NODE, allocating from POOL.
-   TO_NODE must be mutable.  TXN_ID is the Subversion transaction
-   under which this occurs.
+/* Make ENTRY in TO_NODE be a copy of FROM_NODE.  TO_NODE must be mutable.
+   TXN_ID is the Subversion transaction under which this occurs.
 
    If PRESERVE_HISTORY is true, the new node will record that it was
    copied from FROM_PATH in FROM_REV; therefore, FROM_NODE should be
@@ -518,16 +532,17 @@ svn_error_t *svn_fs_x__dag_make_file(dag
 
    If PRESERVE_HISTORY is false, FROM_PATH and FROM_REV are ignored.
 
-   Use POOL for all allocations.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_copy(dag_node_t *to_node,
-                                const char *entry,
-                                dag_node_t *from_node,
-                                svn_boolean_t preserve_history,
-                                svn_revnum_t from_rev,
-                                const char *from_path,
-                                svn_fs_x__txn_id_t txn_id,
-                                apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_copy(dag_node_t *to_node,
+                   const char *entry,
+                   dag_node_t *from_node,
+                   svn_boolean_t preserve_history,
+                   svn_revnum_t from_rev,
+                   const char *from_path,
+                   svn_fs_x__txn_id_t txn_id,
+                   apr_pool_t *scratch_pool);
 
 
 /* Comparison */
@@ -543,39 +558,45 @@ svn_error_t *svn_fs_x__dag_copy(dag_node
    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.
+   Use SCRATCH_POOL for temporary allocations.
  */
-svn_error_t *svn_fs_x__dag_things_different(svn_boolean_t *props_changed,
-                                            svn_boolean_t *contents_changed,
-                                            dag_node_t *node1,
-                                            dag_node_t *node2,
-                                            svn_boolean_t strict,
-                                            apr_pool_t *pool);
+svn_error_t *
+svn_fs_x__dag_things_different(svn_boolean_t *props_changed,
+                               svn_boolean_t *contents_changed,
+                               dag_node_t *node1,
+                               dag_node_t *node2,
+                               svn_boolean_t strict,
+                               apr_pool_t *scratch_pool);
 
 
 /* Set *REV and *PATH to the copyroot revision and path of node NODE, or
    to SVN_INVALID_REVNUM and NULL if no copyroot exists.
  */
-svn_error_t *svn_fs_x__dag_get_copyroot(svn_revnum_t *rev,
-                                        const char **path,
-                                        dag_node_t *node);
+svn_error_t *
+svn_fs_x__dag_get_copyroot(svn_revnum_t *rev,
+                           const char **path,
+                           dag_node_t *node);
 
 /* Set *REV to the copyfrom revision associated with NODE.
  */
-svn_error_t *svn_fs_x__dag_get_copyfrom_rev(svn_revnum_t *rev,
-                                            dag_node_t *node);
+svn_error_t *
+svn_fs_x__dag_get_copyfrom_rev(svn_revnum_t *rev,
+                               dag_node_t *node);
 
 /* Set *PATH to the copyfrom path associated with NODE.
  */
-svn_error_t *svn_fs_x__dag_get_copyfrom_path(const char **path,
-                                             dag_node_t *node);
+svn_error_t *
+svn_fs_x__dag_get_copyfrom_path(const char **path,
+                                dag_node_t *node);
 
 /* Update *TARGET so that SOURCE is it's predecessor.
+
+   Use SCRATCH_POOL for temporary allocations.
  */
 svn_error_t *
 svn_fs_x__dag_update_ancestry(dag_node_t *target,
                               dag_node_t *source,
-                              apr_pool_t *pool);
+                              apr_pool_t *scratch_pool);
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */