You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2012/03/30 16:12:54 UTC

svn commit: r1307434 [3/6] - in /subversion/branches/revprop-packing: ./ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_fs_fs/ subversion/libsvn_ra_serf/ subversion/libsvn_ra_svn/ subversion/libsvn_repos/ su...

Modified: subversion/branches/revprop-packing/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_fs_fs/dag.c?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_fs_fs/dag.c Fri Mar 30 14:12:52 2012
@@ -70,6 +70,9 @@ struct dag_node_t
      things for you.  */
   node_revision_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;
 };
@@ -139,7 +142,7 @@ copy_node_revision(node_revision_t *node
 
 /* 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 POOL.
+   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
@@ -150,8 +153,7 @@ copy_node_revision(node_revision_t *node
    the structure at all.  */
 static svn_error_t *
 get_node_revision(node_revision_t **noderev_p,
-                  dag_node_t *node,
-                  apr_pool_t *pool)
+                  dag_node_t *node)
 {
   node_revision_t *noderev;
 
@@ -159,7 +161,7 @@ get_node_revision(node_revision_t **node
   if (! node->node_revision)
     {
       SVN_ERR(svn_fs_fs__get_node_revision(&noderev, node->fs,
-                                           node->id, pool));
+                                           node->id, node->node_pool));
       node->node_revision = noderev;
     }
 
@@ -190,7 +192,8 @@ svn_fs_fs__dag_get_node(dag_node_t **nod
   new_node->id = svn_fs_fs__id_copy(id, pool);
 
   /* Grab the contents so we can inspect the node's kind and created path. */
-  SVN_ERR(get_node_revision(&noderev, new_node, pool));
+  new_node->node_pool = pool;
+  SVN_ERR(get_node_revision(&noderev, new_node));
 
   /* Initialize the KIND and CREATED_PATH attributes */
   new_node->kind = noderev->kind;
@@ -227,12 +230,11 @@ svn_fs_fs__dag_get_revision(svn_revnum_t
 
 svn_error_t *
 svn_fs_fs__dag_get_predecessor_id(const svn_fs_id_t **id_p,
-                                  dag_node_t *node,
-                                  apr_pool_t *pool)
+                                  dag_node_t *node)
 {
   node_revision_t *noderev;
 
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
   *id_p = noderev->predecessor_id;
   return SVN_NO_ERROR;
 }
@@ -240,44 +242,40 @@ svn_fs_fs__dag_get_predecessor_id(const 
 
 svn_error_t *
 svn_fs_fs__dag_get_predecessor_count(int *count,
-                                     dag_node_t *node,
-                                     apr_pool_t *pool)
+                                     dag_node_t *node)
 {
   node_revision_t *noderev;
 
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
   *count = noderev->predecessor_count;
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
 svn_fs_fs__dag_get_mergeinfo_count(apr_int64_t *count,
-                                   dag_node_t *node,
-                                   apr_pool_t *pool)
+                                   dag_node_t *node)
 {
   node_revision_t *noderev;
 
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
   *count = noderev->mergeinfo_count;
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
 svn_fs_fs__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
-                             dag_node_t *node,
-                             apr_pool_t *pool)
+                             dag_node_t *node)
 {
   node_revision_t *noderev;
 
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
   *has_mergeinfo = noderev->has_mergeinfo;
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
 svn_fs_fs__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
-                                              dag_node_t *node,
-                                              apr_pool_t *pool)
+                                              dag_node_t *node)
 {
   node_revision_t *noderev;
 
@@ -287,7 +285,7 @@ svn_fs_fs__dag_has_descendants_with_merg
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
   if (noderev->mergeinfo_count > 1)
     *do_they = TRUE;
   else if (noderev->mergeinfo_count == 1 && !noderev->has_mergeinfo)
@@ -309,15 +307,13 @@ static svn_error_t *
 dir_entry_id_from_node(const svn_fs_id_t **id_p,
                        dag_node_t *parent,
                        const char *name,
-                       apr_pool_t *pool)
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
 {
   svn_fs_dirent_t *dirent;
-  apr_pool_t *subpool = svn_pool_create(pool);
 
-  SVN_ERR(svn_fs_fs__dag_dir_entry(&dirent, parent, name, subpool, pool));
-  *id_p = dirent ? svn_fs_fs__id_copy(dirent->id, pool) : NULL;
-
-  svn_pool_destroy(subpool);
+  SVN_ERR(svn_fs_fs__dag_dir_entry(&dirent, parent, name, scratch_pool));
+  *id_p = dirent ? svn_fs_fs__id_copy(dirent->id, result_pool) : NULL;
 
   return SVN_NO_ERROR;
 }
@@ -342,7 +338,7 @@ set_entry(dag_node_t *parent,
   node_revision_t *parent_noderev;
 
   /* Get the parent's node-revision. */
-  SVN_ERR(get_node_revision(&parent_noderev, parent, pool));
+  SVN_ERR(get_node_revision(&parent_noderev, parent));
 
   /* Set the new entry. */
   return svn_fs_fs__set_entry(parent->fs, txn_id, parent_noderev, name, id,
@@ -355,7 +351,7 @@ set_entry(dag_node_t *parent,
    will be a file.  The new node will be allocated in POOL.  PARENT
    must be mutable, and must not have an entry named NAME.
 
-   Use POOL for all allocations including caching the node_revision in PARENT.
+   Use POOL for all allocations, except caching the node_revision in PARENT.
  */
 static svn_error_t *
 make_entry(dag_node_t **child_p,
@@ -392,7 +388,7 @@ 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, pool);
 
-  SVN_ERR(get_node_revision(&parent_noderev, parent, pool));
+  SVN_ERR(get_node_revision(&parent_noderev, parent));
   new_noderev.copyroot_path = apr_pstrdup(pool,
                                           parent_noderev->copyroot_path);
   new_noderev.copyroot_rev = parent_noderev->copyroot_rev;
@@ -419,12 +415,11 @@ make_entry(dag_node_t **child_p,
 svn_error_t *
 svn_fs_fs__dag_dir_entries(apr_hash_t **entries,
                            dag_node_t *node,
-                           apr_pool_t *pool,
-                           apr_pool_t *node_pool)
+                           apr_pool_t *pool)
 {
   node_revision_t *noderev;
 
-  SVN_ERR(get_node_revision(&noderev, node, node_pool));
+  SVN_ERR(get_node_revision(&noderev, node));
 
   if (noderev->kind != svn_node_dir)
     return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
@@ -437,11 +432,10 @@ svn_error_t *
 svn_fs_fs__dag_dir_entry(svn_fs_dirent_t **dirent,
                          dag_node_t *node,
                          const char* name,
-                         apr_pool_t *pool,
-                         apr_pool_t *node_pool)
+                         apr_pool_t *pool)
 {
   node_revision_t *noderev;
-  SVN_ERR(get_node_revision(&noderev, node, node_pool));
+  SVN_ERR(get_node_revision(&noderev, node));
 
   if (noderev->kind != svn_node_dir)
     return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
@@ -488,7 +482,7 @@ svn_fs_fs__dag_get_proplist(apr_hash_t *
   node_revision_t *noderev;
   apr_hash_t *proplist = NULL;
 
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
 
   SVN_ERR(svn_fs_fs__get_proplist(&proplist, node->fs,
                                   noderev, pool));
@@ -517,7 +511,7 @@ svn_fs_fs__dag_set_proplist(dag_node_t *
     }
 
   /* Go get a fresh NODE-REVISION for this node. */
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
 
   /* Set the new proplist. */
   return svn_fs_fs__set_proplist(node->fs, noderev, proplist, pool);
@@ -545,7 +539,7 @@ svn_fs_fs__dag_increment_mergeinfo_count
     return SVN_NO_ERROR;
 
   /* Go get a fresh NODE-REVISION for this node. */
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
 
   noderev->mergeinfo_count += increment;
   if (noderev->mergeinfo_count < 0)
@@ -594,7 +588,7 @@ svn_fs_fs__dag_set_has_mergeinfo(dag_nod
     }
 
   /* Go get a fresh NODE-REVISION for this node. */
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
 
   noderev->has_mergeinfo = has_mergeinfo;
 
@@ -658,6 +652,7 @@ svn_fs_fs__dag_clone_child(dag_node_t **
   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 */
   svn_fs_t *fs = svn_fs_fs__dag_get_fs(parent);
+  apr_pool_t *subpool = svn_pool_create(pool);
 
   /* First check that the parent is mutable. */
   if (! svn_fs_fs__dag_check_mutable(parent))
@@ -672,7 +667,7 @@ svn_fs_fs__dag_clone_child(dag_node_t **
        "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_fs__dag_open(&cur_entry, parent, name, pool));
+  SVN_ERR(svn_fs_fs__dag_open(&cur_entry, parent, name, pool, subpool));
 
   /* Check for mutability in the node we found.  If it's mutable, we
      don't need to clone it. */
@@ -686,11 +681,11 @@ svn_fs_fs__dag_clone_child(dag_node_t **
       node_revision_t *noderev, *parent_noderev;
 
       /* Go get a fresh NODE-REVISION for current child node. */
-      SVN_ERR(get_node_revision(&noderev, cur_entry, pool));
+      SVN_ERR(get_node_revision(&noderev, cur_entry));
 
       if (is_parent_copyroot)
         {
-          SVN_ERR(get_node_revision(&parent_noderev, parent, pool));
+          SVN_ERR(get_node_revision(&parent_noderev, parent));
           noderev->copyroot_rev = parent_noderev->copyroot_rev;
           noderev->copyroot_path = apr_pstrdup(pool,
                                                parent_noderev->copyroot_path);
@@ -714,6 +709,7 @@ svn_fs_fs__dag_clone_child(dag_node_t **
     }
 
   /* Initialize the youngster. */
+  svn_pool_destroy(subpool);
   return svn_fs_fs__dag_get_node(child_p, fs, new_node_id, pool);
 }
 
@@ -778,7 +774,7 @@ svn_fs_fs__dag_delete(dag_node_t *parent
        "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, pool));
+  SVN_ERR(get_node_revision(&parent_noderev, parent));
 
   subpool = svn_pool_create(pool);
 
@@ -851,7 +847,7 @@ svn_fs_fs__dag_delete_if_mutable(svn_fs_
       apr_hash_index_t *hi;
 
       /* Loop over hash entries */
-      SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, node, pool, pool));
+      SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, node, pool));
       if (entries)
         {
           for (hi = apr_hash_first(pool, entries);
@@ -912,7 +908,7 @@ svn_fs_fs__dag_get_contents(svn_stream_t
        "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, pool));
+  SVN_ERR(get_node_revision(&noderev, file));
 
   /* Get a stream to the contents. */
   SVN_ERR(svn_fs_fs__get_contents(&contents, file->fs,
@@ -942,10 +938,10 @@ svn_fs_fs__dag_get_file_delta_stream(svn
 
   /* Go get fresh node-revisions for the nodes. */
   if (source)
-    SVN_ERR(get_node_revision(&src_noderev, source, pool));
+    SVN_ERR(get_node_revision(&src_noderev, source));
   else
     src_noderev = NULL;
-  SVN_ERR(get_node_revision(&tgt_noderev, target, pool));
+  SVN_ERR(get_node_revision(&tgt_noderev, target));
 
   /* Get the delta stream. */
   return svn_fs_fs__get_file_delta_stream(stream_p, target->fs,
@@ -967,7 +963,7 @@ svn_fs_fs__dag_file_length(svn_filesize_
        "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, pool));
+  SVN_ERR(get_node_revision(&noderev, file));
 
   return svn_fs_fs__file_length(length, noderev, pool);
 }
@@ -986,7 +982,7 @@ svn_fs_fs__dag_file_checksum(svn_checksu
       (SVN_ERR_FS_NOT_FILE, NULL,
        "Attempted to get checksum of a *non*-file node");
 
-  SVN_ERR(get_node_revision(&noderev, file, pool));
+  SVN_ERR(get_node_revision(&noderev, file));
 
   return svn_fs_fs__file_checksum(checksum, noderev, kind, pool);
 }
@@ -1013,7 +1009,7 @@ svn_fs_fs__dag_get_edit_stream(svn_strea
        "Attempted to set textual contents of an immutable node");
 
   /* Get the node revision. */
-  SVN_ERR(get_node_revision(&noderev, file, pool));
+  SVN_ERR(get_node_revision(&noderev, file));
 
   SVN_ERR(svn_fs_fs__set_contents(&ws, file->fs, noderev, pool));
 
@@ -1066,11 +1062,13 @@ svn_fs_fs__dag_dup(const dag_node_t *nod
       new_node->node_revision->is_fresh_txn_root =
           node->node_revision->is_fresh_txn_root;
     }
+  new_node->node_pool = pool;
+
   return new_node;
 }
 
 svn_error_t *
-svn_fs_fs__dag_serialize(char **data,
+svn_fs_fs__dag_serialize(void **data,
                          apr_size_t *data_len,
                          void *in,
                          apr_pool_t *pool)
@@ -1092,6 +1090,10 @@ svn_fs_fs__dag_serialize(char **data,
     svn_temp_serializer__set_null(context,
                                   (const void * const *)&node->node_revision);
 
+  /* 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_fs__id_serialize(context, (const svn_fs_id_t **)&node->id);
   svn_fs_fs__id_serialize(context, &node->fresh_root_predecessor_id);
@@ -1107,7 +1109,7 @@ svn_fs_fs__dag_serialize(char **data,
 
 svn_error_t *
 svn_fs_fs__dag_deserialize(void **out,
-                           char *data,
+                           void *data,
                            apr_size_t data_len,
                            apr_pool_t *pool)
 {
@@ -1124,6 +1126,7 @@ svn_fs_fs__dag_deserialize(void **out,
   svn_fs_fs__id_deserialize(node,
                             (svn_fs_id_t **)&node->fresh_root_predecessor_id);
   svn_fs_fs__noderev_deserialize(node, &node->node_revision);
+  node->node_pool = pool;
 
   svn_temp_deserializer__resolve(node, (void**)&node->created_path);
 
@@ -1137,12 +1140,14 @@ svn_error_t *
 svn_fs_fs__dag_open(dag_node_t **child_p,
                     dag_node_t *parent,
                     const char *name,
-                    apr_pool_t *pool)
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
 {
   const svn_fs_id_t *node_id;
 
   /* Ensure that NAME exists in PARENT's entry list. */
-  SVN_ERR(dir_entry_id_from_node(&node_id, parent, name, pool));
+  SVN_ERR(dir_entry_id_from_node(&node_id, parent, name, 
+                                 scratch_pool, scratch_pool));
   if (! node_id)
     return svn_error_createf
       (SVN_ERR_FS_NOT_FOUND, NULL,
@@ -1156,7 +1161,7 @@ svn_fs_fs__dag_open(dag_node_t **child_p
 
   /* Now get the node that was requested. */
   return svn_fs_fs__dag_get_node(child_p, svn_fs_fs__dag_get_fs(parent),
-                                 node_id, pool);
+                                 node_id, result_pool);
 }
 
 
@@ -1180,7 +1185,7 @@ svn_fs_fs__dag_copy(dag_node_t *to_node,
       svn_fs_t *fs = svn_fs_fs__dag_get_fs(from_node);
 
       /* Make a copy of the original node revision. */
-      SVN_ERR(get_node_revision(&from_noderev, from_node, pool));
+      SVN_ERR(get_node_revision(&from_noderev, from_node));
       to_noderev = copy_node_revision(from_noderev, pool);
 
       /* Reserve a copy ID for this new copy. */
@@ -1222,8 +1227,7 @@ svn_error_t *
 svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
                                 svn_boolean_t *contents_changed,
                                 dag_node_t *node1,
-                                dag_node_t *node2,
-                                apr_pool_t *pool)
+                                dag_node_t *node2)
 {
   node_revision_t *noderev1, *noderev2;
 
@@ -1233,8 +1237,8 @@ svn_fs_fs__dag_things_different(svn_bool
     return SVN_NO_ERROR;
 
   /* The node revision skels for these two nodes. */
-  SVN_ERR(get_node_revision(&noderev1, node1, pool));
-  SVN_ERR(get_node_revision(&noderev2, node2, pool));
+  SVN_ERR(get_node_revision(&noderev1, node1));
+  SVN_ERR(get_node_revision(&noderev2, node2));
 
   /* Compare property keys. */
   if (props_changed != NULL)
@@ -1253,13 +1257,12 @@ svn_fs_fs__dag_things_different(svn_bool
 svn_error_t *
 svn_fs_fs__dag_get_copyroot(svn_revnum_t *rev,
                             const char **path,
-                            dag_node_t *node,
-                            apr_pool_t *pool)
+                            dag_node_t *node)
 {
   node_revision_t *noderev;
 
   /* Go get a fresh node-revision for NODE. */
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
 
   *rev = noderev->copyroot_rev;
   *path = noderev->copyroot_path;
@@ -1269,13 +1272,12 @@ svn_fs_fs__dag_get_copyroot(svn_revnum_t
 
 svn_error_t *
 svn_fs_fs__dag_get_copyfrom_rev(svn_revnum_t *rev,
-                                dag_node_t *node,
-                                apr_pool_t *pool)
+                                dag_node_t *node)
 {
   node_revision_t *noderev;
 
   /* Go get a fresh node-revision for NODE. */
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
 
   *rev = noderev->copyfrom_rev;
 
@@ -1284,13 +1286,12 @@ svn_fs_fs__dag_get_copyfrom_rev(svn_revn
 
 svn_error_t *
 svn_fs_fs__dag_get_copyfrom_path(const char **path,
-                                 dag_node_t *node,
-                                 apr_pool_t *pool)
+                                 dag_node_t *node)
 {
   node_revision_t *noderev;
 
   /* Go get a fresh node-revision for NODE. */
-  SVN_ERR(get_node_revision(&noderev, node, pool));
+  SVN_ERR(get_node_revision(&noderev, node));
 
   *path = noderev->copyfrom_path;
 
@@ -1309,8 +1310,8 @@ svn_fs_fs__dag_update_ancestry(dag_node_
       (SVN_ERR_FS_NOT_MUTABLE, NULL,
        _("Attempted to update ancestry of non-mutable node"));
 
-  SVN_ERR(get_node_revision(&source_noderev, source, pool));
-  SVN_ERR(get_node_revision(&target_noderev, target, pool));
+  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_count = source_noderev->predecessor_count;

Modified: subversion/branches/revprop-packing/subversion/libsvn_fs_fs/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_fs_fs/dag.h?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_fs_fs/dag.h (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_fs_fs/dag.h Fri Mar 30 14:12:52 2012
@@ -81,7 +81,7 @@ svn_fs_fs__dag_dup(const dag_node_t *nod
 /* Serialize a DAG node, except don't try to preserve the 'fs' member.
    Implements svn_cache__serialize_func_t */
 svn_error_t *
-svn_fs_fs__dag_serialize(char **data,
+svn_fs_fs__dag_serialize(void **data,
                          apr_size_t *data_len,
                          void *in,
                          apr_pool_t *pool);
@@ -90,7 +90,7 @@ svn_fs_fs__dag_serialize(char **data,
    Implements svn_cache__deserialize_func_t */
 svn_error_t *
 svn_fs_fs__dag_deserialize(void **out,
-                           char *data,
+                           void *data,
                            apr_size_t data_len,
                            apr_pool_t *pool);
 
@@ -121,58 +121,39 @@ const char *svn_fs_fs__dag_get_created_p
 
 
 /* Set *ID_P to the node revision ID of NODE's immediate predecessor,
-   or NULL if NODE has no predecessor, allocating from POOL.
-
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
+   or NULL if NODE has no predecessor.
  */
 svn_error_t *svn_fs_fs__dag_get_predecessor_id(const svn_fs_id_t **id_p,
-                                               dag_node_t *node,
-                                               apr_pool_t *pool);
+                                               dag_node_t *node);
 
 
 /* Set *COUNT to the number of predecessors NODE has (recursively), or
-   -1 if not known, allocating from POOL.
-
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
+   -1 if not known.
  */
+/* ### This function is currently only used by 'verify'. */
 svn_error_t *svn_fs_fs__dag_get_predecessor_count(int *count,
-                                                  dag_node_t *node,
-                                                  apr_pool_t *pool);
+                                                  dag_node_t *node);
 
 /* Set *COUNT to the number of node under NODE (inclusive) with
-   svn:mergeinfo properties, allocating from POOL.
-
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
+   svn:mergeinfo properties.
  */
 svn_error_t *svn_fs_fs__dag_get_mergeinfo_count(apr_int64_t *count,
-                                                dag_node_t *node,
-                                                apr_pool_t *pool);
+                                                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
    svn:mergeinfo.
-
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
  */
 svn_error_t *
 svn_fs_fs__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they,
-                                              dag_node_t *node,
-                                              apr_pool_t *pool);
+                                              dag_node_t *node);
 
 /* Set *HAS_MERGEINFO to a flag indicating whether or not NODE itself
    has svn:mergeinfo set on it.
-
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
  */
 svn_error_t *
 svn_fs_fs__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo,
-                             dag_node_t *node,
-                             apr_pool_t *pool);
+                             dag_node_t *node);
 
 /* Return non-zero IFF NODE is currently mutable. */
 svn_boolean_t svn_fs_fs__dag_check_mutable(const dag_node_t *node);
@@ -188,8 +169,7 @@ svn_node_kind_t svn_fs_fs__dag_node_kind
    If properties do not exist on NODE, *PROPLIST_P will be set to
    NULL.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_get_proplist(apr_hash_t **proplist_p,
                                          dag_node_t *node,
@@ -198,8 +178,7 @@ svn_error_t *svn_fs_fs__dag_get_proplist
 /* Set the property list of NODE to PROPLIST, allocating from POOL.
    The node being changed must be mutable.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_set_proplist(dag_node_t *node,
                                          apr_hash_t *proplist,
@@ -208,8 +187,7 @@ svn_error_t *svn_fs_fs__dag_set_proplist
 /* Increment the mergeinfo_count field on NODE by INCREMENT.  The node
    being changed must be mutable.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_increment_mergeinfo_count(dag_node_t *node,
                                                       apr_int64_t increment,
@@ -218,8 +196,7 @@ svn_error_t *svn_fs_fs__dag_increment_me
 /* Set the has-mergeinfo flag on NODE to HAS_MERGEINFO.  The node
    being changed must be mutable.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   NODE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_set_has_mergeinfo(dag_node_t *node,
                                               svn_boolean_t has_mergeinfo,
@@ -274,40 +251,35 @@ svn_error_t *svn_fs_fs__dag_clone_root(d
 
 
 /* Open the node named NAME in the directory PARENT.  Set *CHILD_P to
-   the new node, allocated in POOL.  NAME must be a single path
+   the new node, allocated in RESULT_POOL.  NAME must be a single path
    component; it cannot be a slash-separated directory path.
-
-   Use POOL for all allocations, including to cache the node_revision in
-   PARENT.
  */
-svn_error_t *svn_fs_fs__dag_open(dag_node_t **child_p,
-                                 dag_node_t *parent,
-                                 const char *name,
-                                 apr_pool_t *pool);
+svn_error_t *
+svn_fs_fs__dag_open(dag_node_t **child_p,
+                    dag_node_t *parent,
+                    const char *name,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool);
 
 
 /* Set *ENTRIES_P to a hash table of NODE's entries.  The keys of the
    table are entry names, and the values are svn_fs_dirent_t's.  The
    returned table (and its keys and values) is allocated in POOL,
-   which is also used for temporary allocations.  NODE_POOL is used
-   for any allocation of memory that needs to live as long as NODE
-   lives. */
+   which is also used for temporary allocations. */
 svn_error_t *svn_fs_fs__dag_dir_entries(apr_hash_t **entries_p,
                                         dag_node_t *node,
-                                        apr_pool_t *pool,
-                                        apr_pool_t *node_pool);
+                                        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 POOL.
-   Otherwise, the *DIRENT will be set to NULL. NODE_POOL is used for
-   any allocation of memory that needs to live as long as NODE lives.
+   Otherwise, the *DIRENT will be set to NULL.
  */
+/* ### This function is currently only called from dag.c. */
 svn_error_t * svn_fs_fs__dag_dir_entry(svn_fs_dirent_t **dirent,
                                        dag_node_t *node,
                                        const char* name,
-                                       apr_pool_t *pool,
-                                       apr_pool_t *node_pool);
+                                       apr_pool_t *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
@@ -343,8 +315,7 @@ svn_error_t *svn_fs_fs__dag_set_entry(da
 
    TXN_ID is the Subversion transaction under which this occurs.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   FILE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_clone_child(dag_node_t **child_p,
                                         dag_node_t *parent,
@@ -366,8 +337,7 @@ svn_error_t *svn_fs_fs__dag_clone_child(
    If return SVN_ERR_FS_NO_SUCH_ENTRY, then there is no entry NAME in
    PARENT.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   FILE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_delete(dag_node_t *parent,
                                    const char *name,
@@ -408,8 +378,7 @@ svn_error_t *svn_fs_fs__dag_delete_if_mu
    not currently have an entry named NAME.  TXN_ID is the Subversion
    transaction under which this occurs.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   PARENT.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_make_dir(dag_node_t **child_p,
                                      dag_node_t *parent,
@@ -428,8 +397,7 @@ svn_error_t *svn_fs_fs__dag_make_dir(dag
 
    If FILE is not a file, return SVN_ERR_FS_NOT_FILE.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   FILE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_get_contents(svn_stream_t **contents,
                                          dag_node_t *file,
@@ -440,8 +408,7 @@ svn_error_t *svn_fs_fs__dag_get_contents
    the contents of TARGET, allocated in POOL.  If SOURCE is null, the empty
    string will be used.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   SOURCE and TARGET.
+   Use POOL for all allocations.
  */
 svn_error_t *
 svn_fs_fs__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
@@ -455,8 +422,7 @@ svn_fs_fs__dag_get_file_delta_stream(svn
    Any previous edits on the file will be deleted, and a new edit
    stream will be constructed.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   FILE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_get_edit_stream(svn_stream_t **contents,
                                             dag_node_t *file,
@@ -482,8 +448,7 @@ svn_error_t *svn_fs_fs__dag_finalize_edi
 
 /* Set *LENGTH to the length of the contents of FILE.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   FILE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_file_length(svn_filesize_t *length,
                                         dag_node_t *file,
@@ -495,8 +460,7 @@ svn_error_t *svn_fs_fs__dag_file_length(
    If no stored checksum is available, do not calculate the checksum,
    just put NULL into CHECKSUM.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   FILE.
+   Use POOL for all allocations.
  */
 svn_error_t *
 svn_fs_fs__dag_file_checksum(svn_checksum_t **checksum,
@@ -512,8 +476,7 @@ svn_fs_fs__dag_file_checksum(svn_checksu
    canonicalized absolute path of the parent directory.  TXN_ID is the
    Subversion transaction under which this occurs.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   PARENT.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_make_file(dag_node_t **child_p,
                                       dag_node_t *parent,
@@ -538,8 +501,7 @@ svn_error_t *svn_fs_fs__dag_make_file(da
 
    If PRESERVE_HISTORY is false, FROM_PATH and FROM_REV are ignored.
 
-   Use POOL for all allocations, including to cache the node_revision in
-   FROM_NODE.
+   Use POOL for all allocations.
  */
 svn_error_t *svn_fs_fs__dag_copy(dag_node_t *to_node,
                                  const char *entry,
@@ -569,39 +531,29 @@ svn_error_t *svn_fs_fs__dag_copy(dag_nod
    may leave us with a slight chance of a false positive, though I
    don't really see how that would happen in practice.  Nevertheless,
    it should probably be fixed.
-
-   Use POOL for all allocations, including to cache the node_revision in NODE1
-   and NODE2.
  */
 svn_error_t *svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
                                              svn_boolean_t *contents_changed,
                                              dag_node_t *node1,
-                                             dag_node_t *node2,
-                                             apr_pool_t *pool);
+                                             dag_node_t *node2);
 
 
 /* Set *REV and *PATH to the copyroot revision and path of node NODE, or
    to SVN_INVALID_REVNUM and NULL if no copyroot exists.
-   Use POOL for all allocations, including to cache the node_revision in NODE.
  */
 svn_error_t *svn_fs_fs__dag_get_copyroot(svn_revnum_t *rev,
                                          const char **path,
-                                         dag_node_t *node,
-                                         apr_pool_t *pool);
+                                         dag_node_t *node);
 
 /* Set *REV to the copyfrom revision associated with NODE.
-   Use POOL for all allocations, including to cache the node_revision in NODE.
  */
 svn_error_t *svn_fs_fs__dag_get_copyfrom_rev(svn_revnum_t *rev,
-                                             dag_node_t *node,
-                                             apr_pool_t *pool);
+                                             dag_node_t *node);
 
 /* Set *PATH to the copyfrom path associated with NODE.
-   Use POOL for all allocations, including to cache the node_revision in NODE.
  */
 svn_error_t *svn_fs_fs__dag_get_copyfrom_path(const char **path,
-                                              dag_node_t *node,
-                                              apr_pool_t *pool);
+                                              dag_node_t *node);
 
 /* Update *TARGET so that SOURCE is it's predecessor.
  */

Modified: subversion/branches/revprop-packing/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_fs_fs/fs_fs.c?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_fs_fs/fs_fs.c Fri Mar 30 14:12:52 2012
@@ -5334,6 +5334,7 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
   apr_file_t *file;
   svn_stream_t *out;
   fs_fs_data_t *ffd = fs->fsap_data;
+  apr_pool_t *subpool = svn_pool_create(pool);
 
   if (!rep || !rep->txn_id)
     {
@@ -5341,7 +5342,8 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
 
       {
         apr_hash_t *entries;
-        apr_pool_t *subpool = svn_pool_create(pool);
+
+        svn_pool_clear(subpool);
 
         /* Before we can modify the directory, we need to dump its old
            contents into a mutable representation file. */
@@ -5354,7 +5356,7 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
         out = svn_stream_from_aprfile2(file, TRUE, pool);
         SVN_ERR(svn_hash_write2(entries, out, SVN_HASH_TERMINATOR, subpool));
 
-        svn_pool_destroy(subpool);
+        svn_pool_clear(subpool);
       }
 
       /* Mark the node-rev's data rep as mutable. */
@@ -5376,10 +5378,9 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
     }
 
   /* if we have a directory cache for this transaction, update it */
+  svn_pool_clear(subpool);
   if (ffd->txn_dir_cache)
     {
-      apr_pool_t *subpool = svn_pool_create(pool);
-
       /* build parameters: (name, new entry) pair */
       const char *key =
           svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data;
@@ -5394,28 +5395,31 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
         }
 
       /* actually update the cached directory (if cached) */
-      SVN_ERR(svn_cache__set_partial(ffd->txn_dir_cache, key, svn_fs_fs__replace_dir_entry, &baton, subpool));
-
-      svn_pool_destroy(subpool);
+      SVN_ERR(svn_cache__set_partial(ffd->txn_dir_cache, key,
+                                     svn_fs_fs__replace_dir_entry, &baton,
+                                     subpool));
     }
+  svn_pool_clear(subpool);
 
   /* Append an incremental hash entry for the entry change. */
   if (id)
     {
-      const char *val = unparse_dir_entry(kind, id, pool);
+      const char *val = unparse_dir_entry(kind, id, subpool);
 
-      SVN_ERR(svn_stream_printf(out, pool, "K %" APR_SIZE_T_FMT "\n%s\n"
+      SVN_ERR(svn_stream_printf(out, subpool, "K %" APR_SIZE_T_FMT "\n%s\n"
                                 "V %" APR_SIZE_T_FMT "\n%s\n",
                                 strlen(name), name,
                                 strlen(val), val));
     }
   else
     {
-      SVN_ERR(svn_stream_printf(out, pool, "D %" APR_SIZE_T_FMT "\n%s\n",
+      SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n",
                                 strlen(name), name));
     }
 
-  return svn_io_file_close(file, pool);
+  SVN_ERR(svn_io_file_close(file, subpool));
+  svn_pool_destroy(subpool);
+  return SVN_NO_ERROR;
 }
 
 /* Write a single change entry, path PATH, change CHANGE, and copyfrom
@@ -6239,7 +6243,7 @@ validate_root_noderev(svn_fs_t *fs,
 
      This kind of corruption was seen on svn.apache.org (both on
      the root noderev and on other fspaths' noderevs); see
-       http://mid.gmane.org/20111002202833.GA12373@daniel3.local
+     issue #4129.
 
      Normally (rev == root_noderev->predecessor_count), but here we
      use a more roundabout check that should only trigger on new instances
@@ -8473,58 +8477,24 @@ svn_fs_fs__verify(svn_fs_t *fs,
                                           start, end,
                                           pool));
 
-  /* Issue #4129: bogus pred-counts on the root node-rev. */
+  /* Issue #4129: bogus pred-counts and minfo-cnt's on the root node-rev
+     (and elsewhere).  This code makes more thorough checks that the
+     commit-time checks in validate_root_noderev(). */
   {
     svn_revnum_t i;
-    int predecessor_predecessor_count;
-
-    /* Compute PREDECESSOR_PREDECESSOR_COUNT. */
-    if (start == 0)
-      /* The value that passes the if() at the end of the loop. */
-      predecessor_predecessor_count = -1;
-    else
-      {
-        svn_fs_id_t *root_id;
-        node_revision_t *root_noderev;
-        SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, start-1, iterpool));
-        SVN_ERR(svn_fs_fs__get_node_revision(&root_noderev, fs, root_id,
-                                             iterpool));
-        predecessor_predecessor_count = root_noderev->predecessor_count;
-      }
-
     for (i = start; i <= end; i++)
       {
-        /* ### Caching.
+      	svn_fs_root_t *root;
 
-           svn_fs_fs__rev_get_root() consults caches, which in verify we
-           don't want.  But we can't easily bypass that, as
-           svn_fs_revision_root()+svn_fs_node_id()'s implementation uses
-           svn_fs_fs__rev_get_root() too.
-
-           ### A future revision will make fs_verify() disable caches when it
-           ### opens ffd.
-         */
-        svn_fs_id_t *root_id;
-        node_revision_t *root_noderev;
-
-        if ((i % 128) == 0) /* uneducated guess */
-          svn_pool_clear(iterpool);
-
-        /* Fetch ROOT_NODEREV. */
-        SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, i, iterpool));
-        SVN_ERR(svn_fs_fs__get_node_revision(&root_noderev, fs, root_id,
-                                             iterpool));
-
-        /* Check correctness. (Compare validate_root_noderev().) */
-        if (1+predecessor_predecessor_count != root_noderev->predecessor_count)
-          return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                                   _("predecessor count for "
-                                     "the root node-revision is wrong: "
-                                     "r%ld has %d, but r%ld has %d"),
-                                   i, root_noderev->predecessor_count,
-                                   i-1, predecessor_predecessor_count);
+        svn_pool_clear(iterpool);
 
-        predecessor_predecessor_count = root_noderev->predecessor_count;
+      	/* ### TODO: Make sure caches are disabled.
+      	   
+      	   When this code is called in the library, we want to ensure we
+      	   use the on-disk data --- rather than some data that was read
+      	   in the possibly-distance past and cached since. */
+      	SVN_ERR(svn_fs_fs__revision_root(&root, fs, i, iterpool));
+      	SVN_ERR(svn_fs_fs__verify_root(root, iterpool));
       }
   }
 

Modified: subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.c?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.c Fri Mar 30 14:12:52 2012
@@ -489,7 +489,7 @@ serialize_txdeltawindow(svn_temp_seriali
 }
 
 svn_error_t *
-svn_fs_fs__serialize_txdelta_window(char **buffer,
+svn_fs_fs__serialize_txdelta_window(void **buffer,
                                     apr_size_t *buffer_size,
                                     void *item,
                                     apr_pool_t *pool)
@@ -522,7 +522,7 @@ svn_fs_fs__serialize_txdelta_window(char
 
 svn_error_t *
 svn_fs_fs__deserialize_txdelta_window(void **item,
-                                      char *buffer,
+                                      void *buffer,
                                       apr_size_t buffer_size,
                                       apr_pool_t *pool)
 {
@@ -548,7 +548,7 @@ svn_fs_fs__deserialize_txdelta_window(vo
 }
 
 svn_error_t *
-svn_fs_fs__serialize_manifest(char **data,
+svn_fs_fs__serialize_manifest(void **data,
                               apr_size_t *data_len,
                               void *in,
                               apr_pool_t *pool)
@@ -564,7 +564,7 @@ svn_fs_fs__serialize_manifest(char **dat
 
 svn_error_t *
 svn_fs_fs__deserialize_manifest(void **out,
-                                char *data,
+                                void *data,
                                 apr_size_t data_len,
                                 apr_pool_t *pool)
 {
@@ -637,7 +637,7 @@ serialize_svn_string_array(svn_temp_seri
 }
 
 svn_error_t *
-svn_fs_fs__serialize_properties(char **data,
+svn_fs_fs__serialize_properties(void **data,
                                 apr_size_t *data_len,
                                 void *in,
                                 apr_pool_t *pool)
@@ -682,7 +682,7 @@ svn_fs_fs__serialize_properties(char **d
 
 svn_error_t *
 svn_fs_fs__deserialize_properties(void **out,
-                                  char *data,
+                                  void *data,
                                   apr_size_t data_len,
                                   apr_pool_t *pool)
 {
@@ -716,7 +716,7 @@ svn_fs_fs__deserialize_properties(void *
 }
 
 svn_error_t *
-svn_fs_fs__serialize_id(char **data,
+svn_fs_fs__serialize_id(void **data,
                         apr_size_t *data_len,
                         void *in,
                         apr_pool_t *pool)
@@ -741,7 +741,7 @@ svn_fs_fs__serialize_id(char **data,
 
 svn_error_t *
 svn_fs_fs__deserialize_id(void **out,
-                          char *data,
+                          void *data,
                           apr_size_t data_len,
                           apr_pool_t *pool)
 {
@@ -759,10 +759,10 @@ svn_fs_fs__deserialize_id(void **out,
 /** Caching node_revision_t objects. **/
 
 svn_error_t *
-svn_fs_fs__serialize_node_revision(char **buffer,
-                                    apr_size_t *buffer_size,
-                                    void *item,
-                                    apr_pool_t *pool)
+svn_fs_fs__serialize_node_revision(void **buffer,
+                                   apr_size_t *buffer_size,
+                                   void *item,
+                                   apr_pool_t *pool)
 {
   svn_stringbuf_t *serialized;
   node_revision_t *noderev = item;
@@ -784,7 +784,7 @@ svn_fs_fs__serialize_node_revision(char 
 
 svn_error_t *
 svn_fs_fs__deserialize_node_revision(void **item,
-                                     char *buffer,
+                                     void *buffer,
                                      apr_size_t buffer_size,
                                      apr_pool_t *pool)
 {
@@ -803,7 +803,7 @@ svn_fs_fs__deserialize_node_revision(voi
  * to DATA and DATA_LEN. */
 static svn_error_t *
 return_serialized_dir_context(svn_temp_serializer__context_t *context,
-                              char **data,
+                              void **data,
                               apr_size_t *data_len)
 {
   svn_stringbuf_t *serialized = svn_temp_serializer__get(context);
@@ -816,7 +816,7 @@ return_serialized_dir_context(svn_temp_s
 }
 
 svn_error_t *
-svn_fs_fs__serialize_dir_entries(char **data,
+svn_fs_fs__serialize_dir_entries(void **data,
                                  apr_size_t *data_len,
                                  void *in,
                                  apr_pool_t *pool)
@@ -832,7 +832,7 @@ svn_fs_fs__serialize_dir_entries(char **
 
 svn_error_t *
 svn_fs_fs__deserialize_dir_entries(void **out,
-                                   char *data,
+                                   void *data,
                                    apr_size_t data_len,
                                    apr_pool_t *pool)
 {
@@ -847,7 +847,7 @@ svn_fs_fs__deserialize_dir_entries(void 
 
 svn_error_t *
 svn_fs_fs__get_sharded_offset(void **out,
-                              const char *data,
+                              const void *data,
                               apr_size_t data_len,
                               void *baton,
                               apr_pool_t *pool)
@@ -908,7 +908,7 @@ find_entry(svn_fs_dirent_t **entries,
 
 svn_error_t *
 svn_fs_fs__extract_dir_entry(void **out,
-                             const char *data,
+                             const void *data,
                              apr_size_t data_len,
                              void *baton,
                              apr_pool_t *pool)
@@ -961,7 +961,7 @@ svn_fs_fs__extract_dir_entry(void **out,
  * modification as a simply deserialize / modify / serialize sequence.
  */
 static svn_error_t *
-slowly_replace_dir_entry(char **data,
+slowly_replace_dir_entry(void **data,
                          apr_size_t *data_len,
                          void *baton,
                          apr_pool_t *pool)
@@ -983,7 +983,7 @@ slowly_replace_dir_entry(char **data,
 }
 
 svn_error_t *
-svn_fs_fs__replace_dir_entry(char **data,
+svn_fs_fs__replace_dir_entry(void **data,
                              apr_size_t *data_len,
                              void *baton,
                              apr_pool_t *pool)

Modified: subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.h?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_fs_fs/temp_serializer.h Fri Mar 30 14:12:52 2012
@@ -77,7 +77,7 @@ typedef struct
  * #svn_fs_fs__txdelta_cached_window_t.
  */
 svn_error_t *
-svn_fs_fs__serialize_txdelta_window(char **buffer,
+svn_fs_fs__serialize_txdelta_window(void **buffer,
                                     apr_size_t *buffer_size,
                                     void *item,
                                     apr_pool_t *pool);
@@ -88,7 +88,7 @@ svn_fs_fs__serialize_txdelta_window(char
  */
 svn_error_t *
 svn_fs_fs__deserialize_txdelta_window(void **item,
-                                      char *buffer,
+                                      void *buffer,
                                       apr_size_t buffer_size,
                                       apr_pool_t *pool);
 
@@ -97,7 +97,7 @@ svn_fs_fs__deserialize_txdelta_window(vo
  * (@a in is an #apr_array_header_t of apr_off_t elements).
  */
 svn_error_t *
-svn_fs_fs__serialize_manifest(char **data,
+svn_fs_fs__serialize_manifest(void **data,
                               apr_size_t *data_len,
                               void *in,
                               apr_pool_t *pool);
@@ -108,7 +108,7 @@ svn_fs_fs__serialize_manifest(char **dat
  */
 svn_error_t *
 svn_fs_fs__deserialize_manifest(void **out,
-                                char *data,
+                                void *data,
                                 apr_size_t data_len,
                                 apr_pool_t *pool);
 
@@ -117,7 +117,7 @@ svn_fs_fs__deserialize_manifest(void **o
  * (@a in is an #apr_hash_t of svn_string_t elements, keyed by const char*).
  */
 svn_error_t *
-svn_fs_fs__serialize_properties(char **data,
+svn_fs_fs__serialize_properties(void **data,
                                 apr_size_t *data_len,
                                 void *in,
                                 apr_pool_t *pool);
@@ -128,7 +128,7 @@ svn_fs_fs__serialize_properties(char **d
  */
 svn_error_t *
 svn_fs_fs__deserialize_properties(void **out,
-                                  char *data,
+                                  void *data,
                                   apr_size_t data_len,
                                   apr_pool_t *pool);
 
@@ -136,7 +136,7 @@ svn_fs_fs__deserialize_properties(void *
  * Implements #svn_cache__serialize_func_t for #svn_fs_id_t
  */
 svn_error_t *
-svn_fs_fs__serialize_id(char **data,
+svn_fs_fs__serialize_id(void **data,
                         apr_size_t *data_len,
                         void *in,
                         apr_pool_t *pool);
@@ -146,7 +146,7 @@ svn_fs_fs__serialize_id(char **data,
  */
 svn_error_t *
 svn_fs_fs__deserialize_id(void **out,
-                          char *data,
+                          void *data,
                           apr_size_t data_len,
                           apr_pool_t *pool);
 
@@ -154,7 +154,7 @@ svn_fs_fs__deserialize_id(void **out,
  * Implements #svn_cache__serialize_func_t for #node_revision_t
  */
 svn_error_t *
-svn_fs_fs__serialize_node_revision(char **buffer,
+svn_fs_fs__serialize_node_revision(void **buffer,
                                    apr_size_t *buffer_size,
                                    void *item,
                                    apr_pool_t *pool);
@@ -164,7 +164,7 @@ svn_fs_fs__serialize_node_revision(char 
  */
 svn_error_t *
 svn_fs_fs__deserialize_node_revision(void **item,
-                                     char *buffer,
+                                     void *buffer,
                                      apr_size_t buffer_size,
                                      apr_pool_t *pool);
 
@@ -172,7 +172,7 @@ svn_fs_fs__deserialize_node_revision(voi
  * Implements #svn_cache__serialize_func_t for a directory contents hash
  */
 svn_error_t *
-svn_fs_fs__serialize_dir_entries(char **data,
+svn_fs_fs__serialize_dir_entries(void **data,
                                  apr_size_t *data_len,
                                  void *in,
                                  apr_pool_t *pool);
@@ -182,7 +182,7 @@ svn_fs_fs__serialize_dir_entries(char **
  */
 svn_error_t *
 svn_fs_fs__deserialize_dir_entries(void **out,
-                                   char *data,
+                                   void *data,
                                    apr_size_t data_len,
                                    apr_pool_t *pool);
 
@@ -192,7 +192,7 @@ svn_fs_fs__deserialize_dir_entries(void 
  * serialized manifest array @a data and @a data_len. */
 svn_error_t *
 svn_fs_fs__get_sharded_offset(void **out,
-                              const char *data,
+                              const void *data,
                               apr_size_t data_len,
                               void *baton,
                               apr_pool_t *pool);
@@ -204,7 +204,7 @@ svn_fs_fs__get_sharded_offset(void **out
  */
 svn_error_t *
 svn_fs_fs__extract_dir_entry(void **out,
-                             const char *data,
+                             const void *data,
                              apr_size_t data_len,
                              void *baton,
                              apr_pool_t *pool);
@@ -230,7 +230,7 @@ typedef struct replace_baton_t
  * identified by its name in the #replace_baton_t in @a baton.
  */
 svn_error_t *
-svn_fs_fs__replace_dir_entry(char **data,
+svn_fs_fs__replace_dir_entry(void **data,
                              apr_size_t *data_len,
                              void *baton,
                              apr_pool_t *pool);

Modified: subversion/branches/revprop-packing/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_fs_fs/tree.c?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_fs_fs/tree.c Fri Mar 30 14:12:52 2012
@@ -502,7 +502,7 @@ get_copy_inheritance(copy_id_inherit_t *
      or if it is a branch point that we are accessing via its original
      copy destination path. */
   SVN_ERR(svn_fs_fs__dag_get_copyroot(&copyroot_rev, &copyroot_path,
-                                      child->node,pool));
+                                      child->node));
   SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, fs, copyroot_rev, pool));
   SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, pool));
   copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
@@ -594,6 +594,7 @@ open_path(parent_path_t **parent_path_p,
   const char *rest; /* The portion of PATH we haven't traversed yet.  */
   const char *canon_path = svn_fs__canonicalize_abspath(path, pool);
   const char *path_so_far = "/";
+  apr_pool_t *iterpool = svn_pool_create(pool);
 
   /* Make a parent_path item for the root node, using its own current
      copy id.  */
@@ -614,6 +615,8 @@ open_path(parent_path_t **parent_path_p,
       char *entry;
       dag_node_t *child;
 
+      svn_pool_clear(iterpool);
+
       /* Parse out the next entry from the path.  */
       entry = svn_fs__next_entry_name(&next, rest, pool);
 
@@ -642,7 +645,7 @@ open_path(parent_path_t **parent_path_p,
           if (cached_node)
             child = cached_node;
           else
-            err = svn_fs_fs__dag_open(&child, here, entry, pool);
+            err = svn_fs_fs__dag_open(&child, here, entry, pool, iterpool);
 
           /* "file not found" requires special handling.  */
           if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
@@ -676,14 +679,14 @@ open_path(parent_path_t **parent_path_p,
           if (txn_id)
             {
               SVN_ERR(get_copy_inheritance(&inherit, &copy_path,
-                                           fs, parent_path, txn_id, pool));
+                                           fs, parent_path, txn_id, iterpool));
               parent_path->copy_inherit = inherit;
               parent_path->copy_src_path = apr_pstrdup(pool, copy_path);
             }
 
           /* Cache the node we found (if it wasn't already cached). */
           if (! cached_node)
-            SVN_ERR(dag_node_cache_set(root, path_so_far, child, pool));
+            SVN_ERR(dag_node_cache_set(root, path_so_far, child, iterpool));
         }
 
       /* Are we finished traversing the path?  */
@@ -692,13 +695,14 @@ open_path(parent_path_t **parent_path_p,
 
       /* The path isn't finished yet; we'd better be in a directory.  */
       if (svn_fs_fs__dag_node_kind(child) != svn_node_dir)
-        SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far, pool),
-                  apr_psprintf(pool, _("Failure opening '%s'"), path));
+        SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far, iterpool),
+                  apr_psprintf(iterpool, _("Failure opening '%s'"), path));
 
       rest = next;
       here = child;
     }
 
+  svn_pool_destroy(iterpool);
   *parent_path_p = parent_path;
   return SVN_NO_ERROR;
 }
@@ -763,7 +767,7 @@ make_path_mutable(svn_fs_root_t *root,
 
       /* Determine what copyroot our new child node should use. */
       SVN_ERR(svn_fs_fs__dag_get_copyroot(&copyroot_rev, &copyroot_path,
-                                          parent_path->node, pool));
+                                          parent_path->node));
       SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, root->fs,
                                        copyroot_rev, pool));
       SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, pool));
@@ -1072,8 +1076,7 @@ fs_change_node_prop(svn_fs_root_t *root,
     {
       apr_int64_t increment = 0;
       svn_boolean_t had_mergeinfo;
-      SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&had_mergeinfo, parent_path->node,
-                                           pool));
+      SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&had_mergeinfo, parent_path->node));
 
       if (value && !had_mergeinfo)
         increment = 1;
@@ -1127,7 +1130,7 @@ fs_props_changed(svn_boolean_t *changed_
   SVN_ERR(get_dag(&node1, root1, path1, pool));
   SVN_ERR(get_dag(&node2, root2, path2, pool));
   return svn_fs_fs__dag_things_different(changed_p, NULL,
-                                         node1, node2, pool);
+                                         node1, node2);
 }
 
 
@@ -1337,9 +1340,9 @@ merge(svn_stringbuf_t *conflict_p,
   /* ### todo: it would be more efficient to simply check for a NULL
      entries hash where necessary below than to allocate an empty hash
      here, but another day, another day... */
-  SVN_ERR(svn_fs_fs__dag_dir_entries(&s_entries, source, pool, pool));
-  SVN_ERR(svn_fs_fs__dag_dir_entries(&t_entries, target, pool, pool));
-  SVN_ERR(svn_fs_fs__dag_dir_entries(&a_entries, ancestor, pool, pool));
+  SVN_ERR(svn_fs_fs__dag_dir_entries(&s_entries, source, pool));
+  SVN_ERR(svn_fs_fs__dag_dir_entries(&t_entries, target, pool));
+  SVN_ERR(svn_fs_fs__dag_dir_entries(&a_entries, ancestor, pool));
 
   /* for each entry E in a_entries... */
   iterpool = svn_pool_create(pool);
@@ -1376,8 +1379,7 @@ merge(svn_stringbuf_t *conflict_p,
             {
               apr_int64_t mergeinfo_start;
               SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_start,
-                                                         t_ent_node,
-                                                         iterpool));
+                                                         t_ent_node));
               mergeinfo_increment -= mergeinfo_start;
             }
 
@@ -1391,8 +1393,7 @@ merge(svn_stringbuf_t *conflict_p,
                 {
                   apr_int64_t mergeinfo_end;
                   SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_end,
-                                                             s_ent_node,
-                                                             iterpool));
+                                                             s_ent_node));
                   mergeinfo_increment += mergeinfo_end;
                 }
 
@@ -1505,8 +1506,7 @@ merge(svn_stringbuf_t *conflict_p,
         {
           apr_int64_t mergeinfo_s;
           SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_s,
-                                                     s_ent_node,
-                                                     iterpool));
+                                                     s_ent_node));
           mergeinfo_increment += mergeinfo_s;
         }
 
@@ -1803,7 +1803,7 @@ fs_dir_entries(apr_hash_t **table_p,
 
   /* Get the entries for this path in the caller's pool. */
   SVN_ERR(get_dag(&node, root, path, pool));
-  return svn_fs_fs__dag_dir_entries(table_p, node, pool, pool);
+  return svn_fs_fs__dag_dir_entries(table_p, node, pool);
 }
 
 
@@ -1889,8 +1889,7 @@ fs_delete_node(svn_fs_root_t *root,
   SVN_ERR(make_path_mutable(root, parent_path->parent, path, pool));
   if (svn_fs_fs__fs_supports_mergeinfo(root->fs))
     SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_count,
-                                               parent_path->node,
-                                               pool));
+                                               parent_path->node));
   SVN_ERR(svn_fs_fs__dag_delete(parent_path->parent->node,
                                 parent_path->entry,
                                 txn_id, pool));
@@ -2005,8 +2004,7 @@ copy_helper(svn_fs_root_t *from_root,
           kind = svn_fs_path_change_replace;
           if (svn_fs_fs__fs_supports_mergeinfo(to_root->fs))
             SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_start,
-                                                       to_parent_path->node,
-                                                       pool));
+                                                       to_parent_path->node));
         }
       else
         {
@@ -2016,7 +2014,7 @@ copy_helper(svn_fs_root_t *from_root,
 
       if (svn_fs_fs__fs_supports_mergeinfo(to_root->fs))
         SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_end,
-                                                   from_node, pool));
+                                                   from_node));
 
       /* Make sure the target node's parents are mutable.  */
       SVN_ERR(make_path_mutable(to_root, to_parent_path->parent,
@@ -2149,8 +2147,8 @@ fs_copied_from(svn_revnum_t *rev_p,
       /* There is no cached entry, look it up the old-fashioned
          way. */
       SVN_ERR(get_dag(&node, root, path, pool));
-      SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(&copyfrom_rev, node, pool));
-      SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(&copyfrom_path, node, pool));
+      SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(&copyfrom_rev, node));
+      SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(&copyfrom_path, node));
     }
 
   *rev_p  = copyfrom_rev;
@@ -2660,7 +2658,7 @@ fs_contents_changed(svn_boolean_t *chang
   SVN_ERR(get_dag(&node1, root1, path1, pool));
   SVN_ERR(get_dag(&node2, root2, path2, pool));
   return svn_fs_fs__dag_things_different(NULL, changed_p,
-                                         node1, node2, pool);
+                                         node1, node2);
 }
 
 
@@ -2792,7 +2790,7 @@ find_youngest_copyroot(svn_revnum_t *rev
 
   /* Find our copyroot. */
   SVN_ERR(svn_fs_fs__dag_get_copyroot(&rev_mine, &path_mine,
-                                      parent_path->node, pool));
+                                      parent_path->node));
 
   /* If a parent and child were copied to in the same revision, prefer
      the child copy target, since it is the copy relevant to the
@@ -2872,7 +2870,7 @@ static svn_error_t *fs_closest_copy(svn_
   if (created_rev == copy_dst_rev)
     {
       const svn_fs_id_t *pred;
-      SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred, copy_dst_node, pool));
+      SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred, copy_dst_node));
       if (! pred)
         return SVN_NO_ERROR;
     }
@@ -3033,7 +3031,7 @@ fs_node_origin_rev(svn_revnum_t *revisio
            value cached in the node (which is allocated in
            SUBPOOL... maybe). */
         svn_pool_clear(predidpool);
-        SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node, subpool));
+        SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node));
         pred_id = pred_id ? svn_fs_fs__id_copy(pred_id, predidpool) : NULL;
       }
     while (pred_id);
@@ -3135,7 +3133,7 @@ history_prev(void *baton, apr_pool_t *po
              no predecessor, in which case we're all done!). */
           const svn_fs_id_t *pred_id;
 
-          SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node, pool));
+          SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node));
           if (! pred_id)
             return SVN_NO_ERROR;
 
@@ -3183,8 +3181,8 @@ history_prev(void *baton, apr_pool_t *po
           /* If we get here, then our current path is the destination
              of, or the child of the destination of, a copy.  Fill
              in the return values and get outta here.  */
-          SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(&src_rev, node, pool));
-          SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(&copy_src, node, pool));
+          SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(&src_rev, node));
+          SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(&copy_src, node));
 
           dst_rev = copyroot_rev;
           src_path = svn_fspath__join(copy_src, remainder_path, pool);
@@ -3348,7 +3346,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
   SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, dir_dag,
-                                     scratch_pool, scratch_pool));
+                                     scratch_pool));
 
   for (hi = apr_hash_first(scratch_pool, entries);
        hi;
@@ -3364,9 +3362,8 @@ crawl_directory_dag_for_mergeinfo(svn_fs
       kid_path = svn_fspath__join(this_path, dirent->name, iterpool);
       SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool));
 
-      SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag, iterpool));
-      SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag,
-                                                            iterpool));
+      SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag));
+      SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag));
 
       if (has_mergeinfo)
         {
@@ -3441,7 +3438,6 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
   parent_path_t *parent_path, *nearest_ancestor;
   apr_hash_t *proplist;
   svn_string_t *mergeinfo_string;
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
 
   *mergeinfo = NULL;
 
@@ -3461,17 +3457,14 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
     {
       svn_boolean_t has_mergeinfo;
 
-      svn_pool_clear(iterpool);
-
       SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo,
-                                           nearest_ancestor->node, iterpool));
+                                           nearest_ancestor->node));
       if (has_mergeinfo)
         break;
 
       /* No need to loop if we're looking for explicit mergeinfo. */
       if (inherit == svn_mergeinfo_explicit)
         {
-          svn_pool_destroy(iterpool);
           return SVN_NO_ERROR;
         }
 
@@ -3480,13 +3473,10 @@ get_mergeinfo_for_path(svn_mergeinfo_t *
       /* Run out?  There's no mergeinfo. */
       if (!nearest_ancestor)
         {
-          svn_pool_destroy(iterpool);
           return SVN_NO_ERROR;
         }
     }
 
-  svn_pool_destroy(iterpool);
-
   SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, nearest_ancestor->node,
                                       scratch_pool));
   mergeinfo_string = apr_hash_get(proplist, SVN_PROP_MERGEINFO,
@@ -3554,8 +3544,7 @@ add_descendant_mergeinfo(svn_mergeinfo_c
 
   SVN_ERR(get_dag(&this_dag, root, path, scratch_pool));
   SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down,
-                                                        this_dag,
-                                                        scratch_pool));
+                                                        this_dag));
   if (go_down)
     SVN_ERR(crawl_directory_dag_for_mergeinfo(root,
                                               path,
@@ -3770,3 +3759,169 @@ make_txn_root(svn_fs_root_t **root_p,
   *root_p = root;
   return SVN_NO_ERROR;
 }
+
+
+
+/* Verify. */
+static APR_INLINE const char *
+stringify_node(dag_node_t *node,
+               apr_pool_t *pool)
+{
+  /* ### TODO: print some PATH@REV to it, too. */
+  return svn_fs_fs__id_unparse(svn_fs_fs__dag_get_id(node), pool)->data;
+}
+
+/* Check metadata sanity on NODE, and on its children.  Manually verify
+   information for DAG nodes in revision REV, and trust the metadata
+   accuracy for nodes belonging to older revisions. */
+static svn_error_t *
+verify_node(dag_node_t *node,
+            svn_revnum_t rev,
+            apr_pool_t *pool)
+{
+  svn_boolean_t has_mergeinfo;
+  apr_int64_t mergeinfo_count;
+  const svn_fs_id_t *pred_id;
+  svn_fs_t *fs = svn_fs_fs__dag_get_fs(node);
+  int pred_count;
+  svn_node_kind_t kind;
+  apr_pool_t *iterpool = svn_pool_create(pool);
+
+  /* Fetch some data. */
+  SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, node));
+  SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_count, node));
+  SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node));
+  SVN_ERR(svn_fs_fs__dag_get_predecessor_count(&pred_count, node));
+  kind = svn_fs_fs__dag_node_kind(node);
+
+  /* Sanity check. */
+  if (mergeinfo_count < 0)
+    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                             "Negative mergeinfo-count %" APR_INT64_T_FMT
+                             " on node '%s'",
+                             mergeinfo_count, stringify_node(node, iterpool));
+
+  /* Issue #4129. (This check will explicitly catch non-root instances too.) */
+  if (pred_id)
+    {
+      dag_node_t *pred;
+      int pred_pred_count;
+      SVN_ERR(svn_fs_fs__dag_get_node(&pred, fs, pred_id, iterpool));
+      SVN_ERR(svn_fs_fs__dag_get_predecessor_count(&pred_pred_count, pred));
+      if (pred_pred_count+1 != pred_count)
+        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                                 "Predecessor count mismatch: "
+                                 "%s has %d, but %s has %d",
+                                 stringify_node(node, iterpool), pred_count, 
+                                 stringify_node(pred, iterpool), pred_pred_count);
+    }
+
+  /* Kind-dependent verifications. */
+  if (kind == svn_node_none)
+    {
+      return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                               "Node '%s' has kind 'none'",
+                               stringify_node(node, iterpool));
+    }
+  if (kind == svn_node_file)
+    {
+      if (has_mergeinfo != mergeinfo_count) /* comparing int to bool */
+        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                                 "File node '%s' has inconsistent mergeinfo: "
+                                 "has_mergeinfo=%d, "
+                                 "mergeinfo_count=%" APR_INT64_T_FMT,
+                                 stringify_node(node, iterpool),
+                                 has_mergeinfo, mergeinfo_count);
+    }
+  if (kind == svn_node_dir)
+    {
+      apr_hash_t *entries;
+      apr_hash_index_t *hi;
+      apr_int64_t children_mergeinfo = 0;
+
+      SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, node, pool));
+
+      /* Compute CHILDREN_MERGEINFO. */
+      for (hi = apr_hash_first(pool, entries);
+           hi;
+           hi = apr_hash_next(hi))
+        {
+          svn_fs_dirent_t *dirent = svn__apr_hash_index_val(hi);
+          dag_node_t *child;
+          svn_revnum_t child_rev;
+          apr_int64_t child_mergeinfo;
+
+          svn_pool_clear(iterpool);
+
+          /* Compute CHILD_REV. */
+          SVN_ERR(svn_fs_fs__dag_get_node(&child, fs, dirent->id, iterpool));
+          SVN_ERR(svn_fs_fs__dag_get_revision(&child_rev, child, iterpool));
+
+          if (child_rev == rev)
+            SVN_ERR(verify_node(child, rev, iterpool));
+
+          SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&child_mergeinfo, child));
+          children_mergeinfo += child_mergeinfo;
+        }
+
+      /* Side-effect of issue #4129. */
+      if (children_mergeinfo+has_mergeinfo != mergeinfo_count)
+        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                                 "Mergeinfo-count discrepancy on '%s': "
+                                 "expected %" APR_INT64_T_FMT "+%d, "
+                                 "counted %" APR_INT64_T_FMT,
+                                 stringify_node(node, iterpool),
+                                 mergeinfo_count, has_mergeinfo,
+                                 children_mergeinfo);
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__verify_root(svn_fs_root_t *root,
+                       apr_pool_t *pool)
+{
+  fs_rev_root_data_t *frd;
+
+  if (root->is_txn_root)
+    /* ### Not implemented */
+    return SVN_NO_ERROR;
+  frd = root->fsap_data;
+
+  /* Recursively verify ROOT_DIR. */
+  SVN_ERR(verify_node(frd->root_dir, root->rev, pool));
+
+  /* Verify explicitly the predecessor of the root. */
+  {
+    const svn_fs_id_t *pred_id;
+    dag_node_t *pred;
+    svn_revnum_t pred_rev;
+
+    /* Only r0 should have no predecessor. */
+    SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, frd->root_dir));
+    if (!!pred_id != !!root->rev)
+      return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                               "r%ld's root node's predecessor is "
+                               "unexpectedly '%s'",
+                               root->rev,
+                               (pred_id
+                                ? svn_fs_fs__id_unparse(pred_id, pool)->data
+                                : "(null)"));
+
+    /* Check the predecessor's revision. */
+    if (pred_id)
+      {
+        SVN_ERR(svn_fs_fs__dag_get_node(&pred, root->fs, pred_id, pool));
+        SVN_ERR(svn_fs_fs__dag_get_revision(&pred_rev, pred, pool));
+        if (pred_rev+1 != root->rev)
+          /* Issue #4129. */
+          return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                                   "r%ld's root node's predecessor is r%ld",
+                                   root->rev, pred_rev);
+      }
+  }
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/revprop-packing/subversion/libsvn_fs_fs/tree.h
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_fs_fs/tree.h?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_fs_fs/tree.h (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_fs_fs/tree.h Fri Mar 30 14:12:52 2012
@@ -78,6 +78,12 @@ svn_fs_fs__node_created_rev(svn_revnum_t
                             const char *path,
                             apr_pool_t *pool);
 
+/* Verify metadata for ROOT.
+   ### Currently only implemented for revision roots. */
+svn_error_t *
+svn_fs_fs__verify_root(svn_fs_root_t *root,
+                       apr_pool_t *pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/revprop-packing/subversion/libsvn_ra_serf/sb_bucket.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_ra_serf/sb_bucket.c?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_ra_serf/sb_bucket.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_ra_serf/sb_bucket.c Fri Mar 30 14:12:52 2012
@@ -24,6 +24,7 @@
 #include <serf.h>
 #include <serf_bucket_util.h>
 
+#include "svn_private_config.h"
 #include "private/svn_subr_private.h"
 
 #include "ra_serf.h"
@@ -61,7 +62,7 @@ svn_ra_serf__copy_into_spillbuf(svn_spil
       status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len);
 
       if (status != APR_SUCCESS && status != APR_EOF)
-        return svn_error_wrap_apr(status, "Failed to read the request");
+        return svn_error_wrap_apr(status, _("Failed to read the request"));
 
       SVN_ERR(svn_spillbuf__write(*spillbuf, data, len, scratch_pool));
 

Modified: subversion/branches/revprop-packing/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/revprop-packing/subversion/libsvn_ra_serf/util.c?rev=1307434&r1=1307433&r2=1307434&view=diff
==============================================================================
--- subversion/branches/revprop-packing/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/revprop-packing/subversion/libsvn_ra_serf/util.c Fri Mar 30 14:12:52 2012
@@ -38,9 +38,11 @@
 #include "svn_private_config.h"
 #include "svn_string.h"
 #include "svn_xml.h"
+
 #include "../libsvn_ra/ra_loader.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
 
 #include "ra_serf.h"
 
@@ -54,54 +56,27 @@
 #endif
 
 
+/* Read/write chunks of this size into the spillbuf.  */
 #define PARSE_CHUNK_SIZE 8000
 
-/* As chunks of content arrive from the server, and we need to hold them
-   in memory (because the XML parser is paused), they are copied into
-   these buffers. The buffers are arranged into a linked list.  */
-struct pending_buffer_t {
-  apr_size_t size;
-  char data[PARSE_CHUNK_SIZE];
-
-  struct pending_buffer_t *next;
-};
+/* We will store one megabyte in memory, before switching to store content
+   into a temporary file.  */
+#define SPILL_SIZE 1000000
 
 
 /* This structure records pending data for the parser in memory blocks,
    and possibly into a temporary file if "too much" content arrives.  */
 struct svn_ra_serf__pending_t {
-  /* The amount of content in memory.  */
-  apr_size_t memory_size;
-
-  /* HEAD points to the first block of the linked list of buffers.
-     TAIL points to the last block, for quickly appending more blocks
-     to the overall list.  */
-  struct pending_buffer_t *head;
-  struct pending_buffer_t *tail;
-
-  /* Available blocks for storing pending data. These were allocated
-     previously, then the data consumed and returned to this list.  */
-  struct pending_buffer_t *avail;
-
-  /* Once MEMORY_SIZE exceeds SPILL_SIZE, then arriving content will be
-     appended to the (temporary) file indicated by SPILL.  */
-  apr_file_t *spill;
-
-  /* As we consume content from SPILL, this value indicates where we
-     will begin reading.  */
-  apr_off_t spill_start;
+  /* The spillbuf where we record the pending data.  */
+  svn_spillbuf_t *buf;
 
   /* This flag is set when the network has reached EOF. The PENDING
      processing can then properly detect when parsing has completed.  */
   svn_boolean_t network_eof;
 };
 
-#define HAS_PENDING_DATA(p) ((p) != NULL \
-                             && ((p)->head != NULL || (p)->spill != NULL))
-
-/* We will store one megabyte in memory, before switching to store content
-   into a temporary file.  */
-#define SPILL_SIZE 1000000
+#define HAS_PENDING_DATA(p) ((p) != NULL && (p)->buf != NULL \
+                             && svn_spillbuf__get_size((p)->buf) != 0)
 
 
 static const apr_uint32_t serf_failure_map[][2] =
@@ -1322,101 +1297,24 @@ add_done_item(svn_ra_serf__xml_parser_t 
 }
 
 
-/* Get a buffer from the parsing context. It will come from the free list,
-   or allocated as necessary.  */
-static struct pending_buffer_t *
-get_buffer(svn_ra_serf__xml_parser_t *parser)
-{
-  struct pending_buffer_t *pb;
-
-  if (parser->pending->avail == NULL)
-    return apr_palloc(parser->pool, sizeof(*pb));
-
-  pb = parser->pending->avail;
-  parser->pending->avail = pb->next;
-  return pb;
-}
-
-
-/* Return PB to the list of available buffers in PARSER.  */
-static void
-return_buffer(svn_ra_serf__xml_parser_t *parser,
-              struct pending_buffer_t *pb)
-{
-  pb->next = parser->pending->avail;
-  parser->pending->avail = pb;
-}
-
-
 static svn_error_t *
 write_to_pending(svn_ra_serf__xml_parser_t *ctx,
                  const char *data,
                  apr_size_t len,
                  apr_pool_t *scratch_pool)
 {
-  struct pending_buffer_t *pb;
-
-  /* The caller should not have provided us more than we can store into
-     a single memory block.  */
-  SVN_ERR_ASSERT(len <= PARSE_CHUNK_SIZE);
-
   if (ctx->pending == NULL)
-    ctx->pending = apr_pcalloc(ctx->pool, sizeof(*ctx->pending));
-
-  /* We do not (yet) have a spill file, but the amount stored in memory
-     has grown too large. Create the file and place the pending data into
-     the temporary file.  */
-  if (ctx->pending->spill == NULL
-      && ctx->pending->memory_size > SPILL_SIZE)
-    {
-      SVN_ERR(svn_io_open_unique_file3(&ctx->pending->spill,
-                                       NULL /* temp_path */,
-                                       NULL /* dirpath */,
-                                       svn_io_file_del_on_pool_cleanup,
-                                       ctx->pool, scratch_pool));
-    }
-
-  /* Once a spill file has been constructed, then we need to put all
-     arriving data into the file. We will no longer attempt to hold it
-     in memory.  */
-  if (ctx->pending->spill != NULL)
-    {
-      /* NOTE: we assume the file position is at the END. The caller should
-         ensure this, so that we will append.  */
-      SVN_ERR(svn_io_file_write_full(ctx->pending->spill, data, len,
-                                     NULL, scratch_pool));
-      return SVN_NO_ERROR;
-    }
-
-  /* We're still within bounds of holding the pending information in
-     memory. Get a buffer, copy the data there, and link it into our
-     pending data.  */
-  pb = get_buffer(ctx);
-  /* NOTE: *pb is uninitialized. All fields must be stored.  */
-
-  pb->size = len;
-  memcpy(pb->data, data, len);
-  pb->next = NULL;
-
-  /* Start a list of buffers, or append to the end of the linked list
-     of buffers.  */
-  if (ctx->pending->tail == NULL)
-    {
-      ctx->pending->head = pb;
-      ctx->pending->tail = pb;
-    }
-  else
     {
-      ctx->pending->tail->next = pb;
-      ctx->pending->tail = pb;
+      ctx->pending = apr_pcalloc(ctx->pool, sizeof(*ctx->pending));
+      ctx->pending->buf = svn_spillbuf__create(PARSE_CHUNK_SIZE,
+                                               SPILL_SIZE,
+                                               ctx->pool);
     }
 
-  /* We need to record how much is buffered in memory. Once we reach
-     SPILL_SIZE (or thereabouts, it doesn't have to be precise), then
-     we'll switch to putting the content into a file.  */
-  ctx->pending->memory_size += len;
-
-  return SVN_NO_ERROR;
+  /* Copy the data into one or more chunks in the spill buffer.  */
+  return svn_error_trace(svn_spillbuf__write(ctx->pending->buf,
+                                             data, len,
+                                             scratch_pool));
 }
 
 
@@ -1466,10 +1364,6 @@ svn_error_t *
 svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
                              apr_pool_t *scratch_pool)
 {
-  struct pending_buffer_t *pb;
-  svn_error_t *err;
-  apr_off_t output_unused;
-
   /* Fast path exit: already paused, nothing to do, or already done.  */
   if (parser->paused || parser->pending == NULL || *parser->done)
     return SVN_NO_ERROR;
@@ -1477,86 +1371,31 @@ svn_ra_serf__process_pending(svn_ra_serf
   /* ### it is possible that the XML parsing of the pending content is
      ### so slow, and that we don't return to reading the connection
      ### fast enough... that the server will disconnect us. right now,
-     ### that is highly improbably, but is noted for future's sake.
+     ### that is highly improbable, but is noted for future's sake.
      ### should that ever happen, the loops in this function can simply
      ### terminate after N seconds.  */
 
-  /* Empty out memory buffers until we run out, or we get paused again.  */
-  while (parser->pending->head != NULL)
-    {
-      /* Pull the HEAD buffer out of the list.  */
-      pb = parser->pending->head;
-      if (parser->pending->tail == pb)
-        parser->pending->head = parser->pending->tail = NULL;
-      else
-        parser->pending->head = pb->next;
-
-      /* We're using less memory now. If we haven't hit the spill file,
-         then we may be able to keep using memory.  */
-      parser->pending->memory_size -= pb->size;
-
-      err = inject_to_parser(parser, pb->data, pb->size, NULL);
-
-      return_buffer(parser, pb);
-
-      if (err)
-        return svn_error_trace(err);
-
-      /* If the callbacks paused us, then we're done for now.  */
-      if (parser->paused)
-        return SVN_NO_ERROR;
-    }
-
-  /* If we don't have a spill file, then we've exhausted all
-     pending content.  */
-  if (parser->pending->spill == NULL)
-    goto pending_empty;
-
-  /* Seek once to where we left off reading.  */
-  output_unused = parser->pending->spill_start;  /* ### stupid API  */
-  SVN_ERR(svn_io_file_seek(parser->pending->spill,
-                           APR_SET, &output_unused,
-                           scratch_pool));
-
-  /* We need a buffer for reading out of the file. One of these will always
-     exist by the time we start reading from the spill file.  */
-  pb = get_buffer(parser);
-
-  /* Keep reading until we hit EOF, or get paused again.  */
+  /* Try to read everything from the spillbuf.  */
   while (TRUE)
     {
-      apr_size_t len = sizeof(pb->data);
-      apr_status_t status;
-
-      /* Read some data and remember where we left off.  */
-      status = apr_file_read(parser->pending->spill, pb->data, &len);
-      if (status && !APR_STATUS_IS_EOF(status))
-        {
-          err = svn_error_wrap_apr(status, NULL);
-          break;
-        }
-      parser->pending->spill_start += len;
+      const char *data;
+      apr_size_t len;
 
-      err = inject_to_parser(parser, pb->data, len, NULL);
-      if (err)
+      /* Get a block of content, stopping the loop when we run out.  */
+      SVN_ERR(svn_spillbuf__read(&data, &len, parser->pending->buf,
+                                 scratch_pool));
+      if (data == NULL)
         break;
 
-      /* If we just consumed everything in the spill file, then we may
-         be done with the parsing.  */
-      /* ### future change: when we hit EOF, then remove the spill file.
-         ### we could go back to using memory for a while.  */
-      if (APR_STATUS_IS_EOF(status))
-        goto pending_empty;
+      /* Inject the content into the XML parser.  */
+      SVN_ERR(inject_to_parser(parser, data, len, NULL));
 
-      /* If the callbacks paused the parsing, then we're done for now.  */
+      /* If the XML parsing callbacks paused us, then we're done for now.  */
       if (parser->paused)
-        break;
+        return SVN_NO_ERROR;
     }
+  /* All stored content (memory and file) has now been exhausted.  */
 
-  return_buffer(parser, pb);
-  return svn_error_trace(err);  /* may be SVN_NO_ERROR  */
-
- pending_empty:
   /* If the PENDING structures are empty *and* we consumed all content from
      the network, then we're completely done with the parsing.  */
   if (parser->pending->network_eof)
@@ -1649,18 +1488,6 @@ svn_ra_serf__handle_xml_parser(serf_requ
         }
     }
 
-  /* If we are storing content into a spill file, then move to the end of
-     the file. We need to pre-position the file so that write_to_pending()
-     will always append the content.  */
-  if (ctx->pending != NULL && ctx->pending->spill != NULL)
-    {
-      apr_off_t output_unused = 0;  /* ### stupid API  */
-
-      SVN_ERR(svn_io_file_seek(ctx->pending->spill,
-                               APR_END, &output_unused,
-                               pool));
-    }
-
   while (1)
     {
       const char *data;
@@ -2034,43 +1861,41 @@ setup_request(serf_request_t *request,
               apr_pool_t *request_pool,
               apr_pool_t *scratch_pool)
 {
+  serf_bucket_t *body_bkt;
   serf_bucket_t *headers_bkt;
 
   /* Default response acceptor.  */
   *acceptor = accept_response;
   *acceptor_baton = ctx->session;
 
+  if (strcmp(ctx->method, "HEAD") == 0)
     {
-      serf_bucket_t *body_bkt;
-      serf_bucket_alloc_t *bkt_alloc = serf_request_get_alloc(request);
+      *acceptor = accept_head;
+    }
 
-      if (strcmp(ctx->method, "HEAD") == 0)
-        {
-          *acceptor = accept_head;
-        }
+  if (ctx->body_delegate)
+    {
+      serf_bucket_alloc_t *bkt_alloc = serf_request_get_alloc(request);
 
-      if (ctx->body_delegate)
-        {
-          /* ### should pass the scratch_pool  */
-          SVN_ERR(ctx->body_delegate(&body_bkt, ctx->body_delegate_baton,
-                                     bkt_alloc, request_pool));
-        }
-      else
-        {
-          body_bkt = NULL;
-        }
+      /* ### should pass the scratch_pool  */
+      SVN_ERR(ctx->body_delegate(&body_bkt, ctx->body_delegate_baton,
+                                 bkt_alloc, request_pool));
+    }
+  else
+    {
+      body_bkt = NULL;
+    }
 
-      SVN_ERR(setup_serf_req(request, req_bkt, &headers_bkt,
-                             ctx->conn, ctx->method, ctx->path,
-                             body_bkt, ctx->body_type,
-                             request_pool, scratch_pool));
+  SVN_ERR(setup_serf_req(request, req_bkt, &headers_bkt,
+                         ctx->conn, ctx->method, ctx->path,
+                         body_bkt, ctx->body_type,
+                         request_pool, scratch_pool));
 
-      if (ctx->header_delegate)
-        {
-          /* ### should pass the scratch_pool  */
-          SVN_ERR(ctx->header_delegate(headers_bkt, ctx->header_delegate_baton,
-                                       request_pool));
-        }
+  if (ctx->header_delegate)
+    {
+      /* ### should pass the scratch_pool  */
+      SVN_ERR(ctx->header_delegate(headers_bkt, ctx->header_delegate_baton,
+                                   request_pool));
     }
 
   *handler = handle_response_cb;