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

svn commit: r1339349 [13/37] - in /subversion/branches/fix-rdump-editor: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/client-side/vim/ contrib/server-side/ notes/ notes/api-errat...

Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/dag.h?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/dag.h (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/dag.h Wed May 16 20:32:43 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,40 +531,36 @@ 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.
+ */
+svn_error_t *
+svn_fs_fs__dag_update_ancestry(dag_node_t *target,
+                               dag_node_t *source,
+                               apr_pool_t *pool);
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs.c Wed May 16 20:32:43 2012
@@ -73,7 +73,8 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
      know of a better way of associating such data with the
      repository. */
 
-  key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX, ffd->uuid,
+  SVN_ERR_ASSERT(fs->uuid);
+  key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX, fs->uuid,
                     (char *) NULL);
   status = apr_pool_userdata_get(&val, key, common_pool);
   if (status)
@@ -130,7 +131,6 @@ static fs_vtable_t fs_vtable = {
   svn_fs_fs__revision_prop,
   svn_fs_fs__revision_proplist,
   svn_fs_fs__change_rev_prop,
-  svn_fs_fs__get_uuid,
   svn_fs_fs__set_uuid,
   svn_fs_fs__revision_root,
   svn_fs_fs__begin_txn,
@@ -294,10 +294,18 @@ fs_hotcopy(svn_fs_t *src_fs,
            void *cancel_baton,
            apr_pool_t *pool)
 {
+  SVN_ERR(svn_fs__check_fs(src_fs, FALSE));
   SVN_ERR(initialize_fs_struct(src_fs));
+  SVN_ERR(svn_fs_fs__open(src_fs, src_path, pool));
+  SVN_ERR(svn_fs_fs__initialize_caches(src_fs, pool));
   SVN_ERR(fs_serialized_init(src_fs, pool, pool));
+
+  SVN_ERR(svn_fs__check_fs(dst_fs, FALSE));
   SVN_ERR(initialize_fs_struct(dst_fs));
-  SVN_ERR(fs_serialized_init(dst_fs, pool, pool));
+  /* In INCREMENTAL mode, svn_fs_fs__hotcopy() will open DST_FS.
+     Otherwise, it's not an FS yet --- possibly just an empty dir --- so
+     can't be opened.
+   */
   return svn_fs_fs__hotcopy(src_fs, dst_fs, src_path, dst_path,
                             incremental, cancel_func, cancel_baton, pool);
 }

Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs.h?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs.h Wed May 16 20:32:43 2012
@@ -34,6 +34,7 @@
 #include "private/svn_fs_private.h"
 #include "private/svn_sqlite.h"
 #include "private/svn_mutex.h"
+#include "private/svn_named_atomic.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -60,6 +61,8 @@ extern "C" {
 #define PATH_LOCKS_DIR        "locks"            /* Directory of locks */
 #define PATH_MIN_UNPACKED_REV "min-unpacked-rev" /* Oldest revision which
                                                     has not been packed. */
+#define PATH_REVPROP_GENERATION "revprop-generation"
+                                                 /* Current revprop generation*/
 /* If you change this, look at tests/svn_test_fs.c(maybe_install_fsfs_conf) */
 #define PATH_CONFIG           "fsfs.conf"        /* Configuration */
 
@@ -82,6 +85,11 @@ extern "C" {
 #define CONFIG_OPTION_FAIL_STOP          "fail-stop"
 #define CONFIG_SECTION_REP_SHARING       "rep-sharing"
 #define CONFIG_OPTION_ENABLE_REP_SHARING "enable-rep-sharing"
+#define CONFIG_SECTION_DELTIFICATION     "deltification"
+#define CONFIG_OPTION_ENABLE_DIR_DELTIFICATION   "enable-dir-deltification"
+#define CONFIG_OPTION_ENABLE_PROPS_DELTIFICATION "enable-props-deltification"
+#define CONFIG_OPTION_MAX_DELTIFICATION_WALK     "max-deltification-walk"
+#define CONFIG_OPTION_MAX_LINEAR_DELTIFICATION   "max-linear-deltification"
 
 /* The format number of this filesystem.
    This is independent of the repository format number, and
@@ -118,6 +126,10 @@ extern "C" {
 /* The minimum format number that stores node kinds in changed-paths lists. */
 #define SVN_FS_FS__MIN_KIND_IN_CHANGED_FORMAT 4
 
+/* 1.8 deltification options should work with any FSFS repo but to avoid
+ * issues with very old servers, restrict those options to the 1.6+ format*/
+#define SVN_FS_FS__MIN_DELTIFICATION_FORMAT 4
+
 /* The 1.7-dev format, never released, that packed revprops into SQLite
    revprops.db . */
 #define SVN_FS_FS__PACKED_REVPROP_SQLITE_DEV_FORMAT 5
@@ -198,7 +210,8 @@ typedef struct fs_fs_shared_data_t
   apr_pool_t *common_pool;
 } fs_fs_shared_data_t;
 
-/* Private (non-shared) FSFS-specific data for each svn_fs_t object. */
+/* Private (non-shared) FSFS-specific data for each svn_fs_t object.
+   Any caches in here may be NULL. */
 typedef struct fs_fs_data_t
 {
   /* The format number of this FS. */
@@ -207,9 +220,6 @@ typedef struct fs_fs_data_t
      layouts) or zero (for linear layouts). */
   int max_files_per_dir;
 
-  /* The uuid of this FS. */
-  const char *uuid;
-
   /* The revision that was youngest, last time we checked. */
   svn_revnum_t youngest_rev_cache;
 
@@ -237,6 +247,21 @@ typedef struct fs_fs_data_t
      rep key (revision/offset) to svn_string_t. */
   svn_cache__t *fulltext_cache;
 
+  /* Access object to the atomics namespace used by revprop caching.
+     Will be NULL until the first access. */
+  svn_atomic_namespace__t *revprop_namespace;
+
+  /* Access object to the revprop "generation". Will be NULL until
+     the first access. */
+  svn_named_atomic__t *revprop_generation;
+
+  /* Access object to the revprop update timeout. Will be NULL until
+     the first access. */
+  svn_named_atomic__t *revprop_timeout;
+
+  /* Revision property cache.  Maps from (rev,generation) to apr_hash_t. */
+  svn_cache__t *revprop_cache;
+
   /* Pack manifest cache; a cache mapping (svn_revnum_t) shard number to
      a manifest; and a manifest is a mapping from (svn_revnum_t) revision
      number offset within a shard to (apr_off_t) byte-offset in the
@@ -256,7 +281,7 @@ typedef struct fs_fs_data_t
   /* If set, there are or have been more than one concurrent transaction */
   svn_boolean_t concurrent_transactions;
 
-  /* Tempoary cache for changed directories yet to be committed; maps from
+  /* Temporary cache for changed directories yet to be committed; maps from
      unparsed FS ID to ###x.  NULL outside transactions. */
   svn_cache__t *txn_dir_cache;
 
@@ -275,6 +300,19 @@ typedef struct fs_fs_data_t
   /* Whether rep-sharing is supported by the filesystem
    * and allowed by the configuration. */
   svn_boolean_t rep_sharing_allowed;
+
+  /* Whether directory nodes shall be deltified just like file nodes. */
+  svn_boolean_t deltify_directories;
+
+  /* Whether nodes properties shall be deltified. */
+  svn_boolean_t deltify_properties;
+
+  /* Restart deltification histories after each multiple of this value */
+  apr_int64_t max_deltification_walk;
+
+  /* Maximum number of length of the linear part at the top of the
+   * deltification history after which skip deltas will be used. */
+  apr_int64_t max_linear_deltification;
 } fs_fs_data_t;
 
 

Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs_fs.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs_fs.c Wed May 16 20:32:43 2012
@@ -59,7 +59,9 @@
 #include "rep-cache.h"
 #include "temp_serializer.h"
 
+#include "private/svn_string_private.h"
 #include "private/svn_fs_util.h"
+#include "private/svn_subr_private.h"
 #include "../libsvn_fs/fs-loader.h"
 
 #include "svn_private_config.h"
@@ -71,7 +73,7 @@
 
 /* The default maximum number of files per directory to store in the
    rev and revprops directory.  The number below is somewhat arbitrary,
-   and can be overriden by defining the macro while compiling; the
+   and can be overridden by defining the macro while compiling; the
    figure of 1000 is reasonable for VFAT filesystems, which are by far
    the worst performers in this area. */
 #ifndef SVN_FS_FS_DEFAULT_MAX_FILES_PER_DIR
@@ -80,7 +82,7 @@
 
 /* Begin deltification after a node history exceeded this this limit.
    Useful values are 4 to 64 with 16 being a good compromise between
-   computational overhead and pository size savings.
+   computational overhead and repository size savings.
    Should be a power of 2.
    Values < 2 will result in standard skip-delta behavior. */
 #define SVN_FS_FS_MAX_LINEAR_DELTIFICATION 16
@@ -92,6 +94,17 @@
    Values < 1 disable deltification. */
 #define SVN_FS_FS_MAX_DELTIFICATION_WALK 1023
 
+/* Give writing processes 10 seconds to replace an existing revprop
+   file with a new one. After that time, we assume that the writing
+   process got aborted and that we have re-read revprops. */
+#define REVPROP_CHANGE_TIMEOUT 10 * 1000000
+
+/* The following are names of atomics that will be used to communicate
+ * revprop updates across all processes on this machine. */
+#define ATOMIC_REVPROP_GENERATION "rev-prop-generation"
+#define ATOMIC_REVPROP_TIMEOUT    "rev-prop-timeout"
+#define ATOMIC_REVPROP_NAMESPACE  "rev-prop-atomics"
+
 /* Following are defines that specify the textual elements of the
    native filesystem directories and revision files. */
 
@@ -225,6 +238,12 @@ path_lock(svn_fs_t *fs, apr_pool_t *pool
 }
 
 static const char *
+path_revprop_generation(svn_fs_t *fs, apr_pool_t *pool)
+{
+  return svn_dirent_join(fs->path, PATH_REVPROP_GENERATION, pool);
+}
+
+static const char *
 path_rev_packed(svn_fs_t *fs, svn_revnum_t rev, const char *kind,
                 apr_pool_t *pool)
 {
@@ -432,7 +451,7 @@ path_and_offset_of(apr_file_t *file, apr
 }
 
 
-
+
 /* Functions for working with shared transaction data. */
 
 /* Return the transaction object for transaction TXN_ID from the
@@ -870,25 +889,39 @@ get_file_offset(apr_off_t *offset_p, apr
 }
 
 
-/* Check that BUF, a nul-terminated buffer of text from format file PATH,
+/* Check that BUF, a nul-terminated buffer of text from file PATH,
    contains only digits at OFFSET and beyond, raising an error if not.
+   TITLE contains a user-visible description of the file, usually the
+   short file name.
 
    Uses POOL for temporary allocation. */
 static svn_error_t *
-check_format_file_buffer_numeric(const char *buf, apr_off_t offset,
-                                 const char *path, apr_pool_t *pool)
+check_file_buffer_numeric(const char *buf, apr_off_t offset,
+                          const char *path, const char *title,
+                          apr_pool_t *pool)
 {
   const char *p;
 
   for (p = buf + offset; *p; p++)
     if (!svn_ctype_isdigit(*p))
       return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
-        _("Format file '%s' contains unexpected non-digit '%c' within '%s'"),
-        svn_dirent_local_style(path, pool), *p, buf);
+        _("%s file '%s' contains unexpected non-digit '%c' within '%s'"),
+        title, svn_dirent_local_style(path, pool), *p, buf);
 
   return SVN_NO_ERROR;
 }
 
+/* Check that BUF, a nul-terminated buffer of text from format file PATH,
+   contains only digits at OFFSET and beyond, raising an error if not.
+
+   Uses POOL for temporary allocation. */
+static svn_error_t *
+check_format_file_buffer_numeric(const char *buf, apr_off_t offset,
+                                 const char *path, apr_pool_t *pool)
+{
+  return check_file_buffer_numeric(buf, offset, path, "Format", pool);
+}
+
 /* Read the format number and maximum number of files per directory
    from PATH and return them in *PFORMAT and *MAX_FILES_PER_DIR
    respectively.
@@ -1082,6 +1115,34 @@ read_config(svn_fs_t *fs,
   else
     ffd->rep_sharing_allowed = FALSE;
 
+  /* Initialize ffd->deltify_directories. */
+  if (ffd->format >= SVN_FS_FS__MIN_DELTIFICATION_FORMAT)
+    {
+      SVN_ERR(svn_config_get_bool(ffd->config, &ffd->deltify_directories,
+                                  CONFIG_SECTION_DELTIFICATION,
+                                  CONFIG_OPTION_ENABLE_DIR_DELTIFICATION,
+                                  FALSE));
+      SVN_ERR(svn_config_get_bool(ffd->config, &ffd->deltify_properties,
+                                  CONFIG_SECTION_DELTIFICATION,
+                                  CONFIG_OPTION_ENABLE_PROPS_DELTIFICATION,
+                                  FALSE));
+      SVN_ERR(svn_config_get_int64(ffd->config, &ffd->max_deltification_walk,
+                                   CONFIG_SECTION_DELTIFICATION,
+                                   CONFIG_OPTION_MAX_DELTIFICATION_WALK,
+                                   SVN_FS_FS_MAX_DELTIFICATION_WALK));
+      SVN_ERR(svn_config_get_int64(ffd->config, &ffd->max_linear_deltification,
+                                   CONFIG_SECTION_DELTIFICATION,
+                                   CONFIG_OPTION_MAX_LINEAR_DELTIFICATION,
+                                   SVN_FS_FS_MAX_LINEAR_DELTIFICATION));
+    }
+  else
+    {
+      ffd->deltify_directories = FALSE;
+      ffd->deltify_properties = FALSE;
+      ffd->max_deltification_walk = SVN_FS_FS_MAX_DELTIFICATION_WALK;
+      ffd->max_linear_deltification = SVN_FS_FS_MAX_LINEAR_DELTIFICATION;
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -1130,7 +1191,67 @@ write_config(svn_fs_t *fs,
 "### 'svnadmin verify' will check the rep-cache regardless of this setting." NL
 "### rep-sharing is enabled by default."                                     NL
 "# " CONFIG_OPTION_ENABLE_REP_SHARING " = true"                              NL
-
+""                                                                           NL
+"[" CONFIG_SECTION_DELTIFICATION "]"                                         NL
+"### To conserve space, the filesystem stores data as differences against"   NL
+"### existing representations.  This comes at a slight cost in performance," NL
+"### as calculating differences can increase commit times.  Reading data"    NL
+"### will also create higher CPU load and the data will be fragmented."      NL
+"### Since deltification tends to save significant amounts of disk space,"   NL
+"### the overall I/O load can actually be lower."                            NL
+"###"                                                                        NL
+"### The options in this section allow for tuning the deltification"         NL
+"### strategy.  Their effects on data size and server performance may vary"  NL
+"### from one repository to another.  Versions prior to 1.8 will ignore"     NL
+"### this section."                                                          NL
+"###"                                                                        NL
+"### The following parameter enables deltification for directories. It can"  NL
+"### be switched on and off at will, but for best space-saving results"      NL
+"### should be enabled consistently over the life of the repository."        NL
+"### Repositories containing large directories will benefit greatly."        NL
+"### In rarely read repositories, the I/O overhead may be significant as"    NL
+"### cache hit rates will most likely be low"                                NL
+"### directory deltification is disabled by default."                        NL
+"# " CONFIG_OPTION_ENABLE_DIR_DELTIFICATION " = true"                        NL
+"###"                                                                        NL
+"### The following parameter enables deltification for properties on files"  NL
+"### and directories.  Overall, this is a minor tuning option but can save"  NL
+"### some disk space if frequently merge or if you frequently change node"   NL
+"### properties.  You should not activate this if rep-sharing has been"      NL
+"### disabled."                                                              NL
+"### property deltification is disabled by default."                         NL
+"# " CONFIG_OPTION_ENABLE_PROPS_DELTIFICATION " = true"                      NL
+"###"                                                                        NL
+"### During commit, the server may need to walk the whole change history of" NL
+"### of a given node to find a suitable deltification base.  This linear"    NL
+"### process can impact commit times, svnadmin load and similar operations." NL
+"### This setting limits the depth of the deltification history.  If the"    NL
+"### threshold has been reached, the node will be stored as fulltext and a"  NL
+"### new deltification history begins."                                      NL
+"### Note, this is unrelated to svn log."                                    NL
+"### Very large values rarely provide significant additional savings but"    NL
+"### can impact performance greatly - in particular if directory"            NL
+"### deltification has been activated.  Very small values may be useful in"  NL
+"### repositories that are dominated by large, changing binaries."           NL
+"### Should be a power of two minus 1.  A value of 0 will effectively"       NL
+"### disable deltification."                                                 NL
+"### For 1.8, the default value is 1023; earlier versions have no limit."    NL
+"# " CONFIG_OPTION_MAX_DELTIFICATION_WALK " = 1023"                          NL
+"###"                                                                        NL
+"### The skip-delta scheme used by FSFS tends to repeatably store redundant" NL
+"### delta information where a simple delta against the latest version is"   NL
+"### often smaller.  By default, 1.8+ will therefore use skip deltas only"   NL
+"### after the linear chain of deltas has grown beyond the threshold"        NL
+"### specified by this setting."                                             NL
+"### Values up to 64 can result in some reduction in repository size for"    NL
+"### the cost of quickly increasing I/O and CPU costs. Similarly, smaller"   NL
+"### numbers can reduce those costs at the cost of more disk space.  For"    NL
+"### rarely read repositories or those containing larger binaries, this may" NL
+"### present a better trade-off."                                            NL
+"### Should be a power of two.  A value of 1 or smaller will cause the"      NL
+"### exclusive use of skip-deltas (as in pre-1.8)."                          NL
+"### For 1.8, the default value is 16; earlier versions use 1."              NL
+"# " CONFIG_OPTION_MAX_LINEAR_DELTIFICATION " = 16"                          NL
 ;
 #undef NL
   return svn_io_file_create(svn_dirent_join(fs->path, PATH_CONFIG, pool),
@@ -1194,7 +1315,7 @@ svn_fs_fs__open(svn_fs_t *fs, const char
 
   limit = sizeof(buf);
   SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit, pool));
-  ffd->uuid = apr_pstrdup(fs->pool, buf);
+  fs->uuid = apr_pstrdup(fs->pool, buf);
 
   SVN_ERR(svn_io_file_close(uuid_file, pool));
 
@@ -2271,7 +2392,7 @@ svn_fs_fs__write_noderev(svn_stream_t *o
                               noderev->copyroot_path));
 
   if (noderev->is_fresh_txn_root)
-    SVN_ERR(svn_stream_printf(outfile, pool, HEADER_FRESHTXNRT ": y\n"));
+    SVN_ERR(svn_stream_puts(outfile, HEADER_FRESHTXNRT ": y\n"));
 
   if (include_mergeinfo)
     {
@@ -2281,10 +2402,10 @@ svn_fs_fs__write_noderev(svn_stream_t *o
                                   noderev->mergeinfo_count));
 
       if (noderev->has_mergeinfo)
-        SVN_ERR(svn_stream_printf(outfile, pool, HEADER_MINFO_HERE ": y\n"));
+        SVN_ERR(svn_stream_puts(outfile, HEADER_MINFO_HERE ": y\n"));
     }
 
-  return svn_stream_printf(outfile, pool, "\n");
+  return svn_stream_puts(outfile, "\n");
 }
 
 svn_error_t *
@@ -2687,6 +2808,301 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
   return SVN_NO_ERROR;
 }
 
+/* Revprop caching management.
+ *
+ * Revprop caching needs to be activated and will be deactivated for the
+ * respective FS instance if the necessary infrastructure could not be
+ * initialized.  In deactivated mode, there is almost no runtime overhead
+ * associated with revprop caching.  As long as no revprops are being read
+ * or changed, revprop caching imposes no overhead.
+ *
+ * When activated, we cache revprops using (revision, generation) pairs
+ * as keys with the generation being incremented upon every revprop change.
+ * Since the cache is process-local, the generation needs to be tracked
+ * for at least as long as the process lives but may be reset afterwards.
+ *
+ * To track the revprop generation, we use two-layer approach. On the lower
+ * level, we use named atomics to have a system-wide consistent value for
+ * the current revprop generation.  However, those named atomics will only
+ * remain valid for as long as at least one process / thread in the system
+ * accesses revprops in the respective repository.  The underlying shared
+ * memory gets cleaned up afterwards.
+ *
+ * On the second level, we will use a persistent file to track the latest
+ * revprop generation.  It will be written upon each revprop change but
+ * only be read if we are the first process to initialize the named atomics
+ * with that value.
+ *
+ * The overhead for the second and following accesses to revprops is
+ * almost zero on most systems.
+ */
+
+/* Read revprop generation as stored on disk for repository FS. The result
+ * is returned in *CURRENT. Default to 2 if no such file is available.
+ */
+static svn_error_t *
+read_revprop_generation_file(apr_int64_t *current,
+                             svn_fs_t *fs,
+                             apr_pool_t *pool)
+{
+  svn_error_t *err;
+  apr_file_t *file;
+  char buf[80];
+  apr_size_t len;
+  const char *path = path_revprop_generation(fs, pool);
+
+  err = svn_io_file_open(&file, path,
+                         APR_READ | APR_BUFFERED,
+                         APR_OS_DEFAULT, pool);
+  if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+    {
+      svn_error_clear(err);
+      *current = 2;
+
+      return SVN_NO_ERROR;
+    }
+  SVN_ERR(err);
+
+  len = sizeof(buf);
+  SVN_ERR(svn_io_read_length_line(file, buf, &len, pool));
+
+  /* Check that the first line contains only digits. */
+  SVN_ERR(check_file_buffer_numeric(buf, 0, path,
+                                    "Revprop Generation", pool));
+  SVN_ERR(svn_cstring_atoi64(current, buf));
+
+  return svn_io_file_close(file, pool);
+}
+
+/* Write the CURRENT revprop generation to disk for repository FS.
+ */
+static svn_error_t *
+write_revprop_generation_file(svn_fs_t *fs,
+                              apr_int64_t current,
+                              apr_pool_t *pool)
+{
+  apr_file_t *file;
+  const char *tmp_path;
+
+  char buf[SVN_INT64_BUFFER_SIZE];
+  apr_size_t len = svn__i64toa(buf, current);
+  buf[len] = '\n';
+
+  SVN_ERR(svn_io_open_unique_file3(&file, &tmp_path, fs->path,
+                                   svn_io_file_del_none, pool, pool));
+  SVN_ERR(svn_io_file_write_full(file, buf, len + 1, NULL, pool));
+  SVN_ERR(svn_io_file_close(file, pool));
+
+  return move_into_place(tmp_path, path_revprop_generation(fs, pool),
+                         tmp_path, pool);
+}
+
+/* Make sure the revprop_namespace member in FS is set. */
+static svn_error_t *
+ensure_revprop_namespace(svn_fs_t *fs)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  return ffd->revprop_namespace == NULL
+    ? svn_atomic_namespace__create(&ffd->revprop_namespace,
+                                   svn_dirent_join(fs->path,
+                                                   ATOMIC_REVPROP_NAMESPACE,
+                                                   fs->pool),
+                                   fs->pool)
+    : SVN_NO_ERROR;
+}
+
+/* Make sure the revprop_generation member in FS is set and, if necessary,
+ * initialized with the latest value stored on disk.
+ */
+static svn_error_t *
+ensure_revprop_generation(svn_fs_t *fs, apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  SVN_ERR(ensure_revprop_namespace(fs));
+  if (ffd->revprop_generation == NULL)
+    {
+      apr_int64_t current = 0;
+      
+      SVN_ERR(svn_named_atomic__get(&ffd->revprop_generation,
+                                    ffd->revprop_namespace,
+                                    ATOMIC_REVPROP_GENERATION,
+                                    TRUE));
+
+      /* If the generation is at 0, we just created a new namespace
+       * (it would be at least 2 otherwise). Read the lastest generation
+       * from disk and if we are the first one to initialize the atomic
+       * (i.e. is still 0), set it to the value just gotten.
+       */
+      SVN_ERR(svn_named_atomic__read(&current, ffd->revprop_generation));
+      if (current == 0)
+        {
+          SVN_ERR(read_revprop_generation_file(&current, fs, pool));
+          SVN_ERR(svn_named_atomic__cmpxchg(NULL, current, 0,
+                                            ffd->revprop_generation));
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Make sure the revprop_timeout member in FS is set. */
+static svn_error_t *
+ensure_revprop_timeout(svn_fs_t *fs)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  SVN_ERR(ensure_revprop_namespace(fs));
+  return ffd->revprop_timeout == NULL
+    ? svn_named_atomic__get(&ffd->revprop_timeout,
+                            ffd->revprop_namespace,
+                            ATOMIC_REVPROP_TIMEOUT,
+                            TRUE)
+    : SVN_NO_ERROR;
+}
+
+/* Test whether revprop cache and necessary infrastructure are
+   available in FS. */
+static svn_boolean_t
+has_revprop_cache(svn_fs_t *fs, apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  svn_error_t *error;
+
+  /* is the cache (still) enabled? */
+  if (ffd->revprop_cache == NULL)
+    return FALSE;
+
+  /* is it efficient? */
+  if (!svn_named_atomic__is_efficient())
+    {
+      /* access to it would be quite slow
+       * -> disable the revprop cache for good
+       */
+      ffd->revprop_cache = NULL;
+      return FALSE;
+    }
+
+  /* try to access our SHM-backed infrastructure */
+  error = ensure_revprop_generation(fs, pool);
+  if (error)
+    {
+      /* failure -> disable revprop cache for good */
+
+      svn_error_clear(error);
+      ffd->revprop_cache = NULL;
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Read the current revprop generation and return it in *GENERATION.
+   Also, detect aborted / crashed writers and recover from that.
+   Use the access object in FS to set the shared mem values. */
+static svn_error_t *
+read_revprop_generation(apr_int64_t *generation,
+                        svn_fs_t *fs,
+                        apr_pool_t *pool)
+{
+  apr_int64_t current = 0;
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  /* read the current revprop generation number */
+  SVN_ERR(ensure_revprop_generation(fs, pool));
+  SVN_ERR(svn_named_atomic__read(&current, ffd->revprop_generation));
+
+  /* is an unfinished revprop write under the way? */
+  if (current % 2)
+    {
+      apr_int64_t timeout = 0;
+
+      /* read timeout for the write operation */
+      SVN_ERR(ensure_revprop_timeout(fs));
+      SVN_ERR(svn_named_atomic__read(&timeout, ffd->revprop_timeout));
+
+      /* has the writer process been aborted,
+       * i.e. has the timeout been reached?
+       */
+      if (apr_time_now() > timeout)
+        {
+          /* Cause everyone to re-read revprops upon their next access.
+           * Keep in mind that we may not be the only one trying to do it.
+           */
+          while (current % 2)
+            SVN_ERR(svn_named_atomic__add(&current,
+                                          1,
+                                          ffd->revprop_generation));
+        }
+    }
+
+  /* return the value we just got */
+  *generation = current;
+  return SVN_NO_ERROR;
+}
+
+/* Set the revprop generation to the next odd number to indicate that
+   there is a revprop write process under way. If that times out,
+   readers shall recover from that state & re-read revprops.
+   Use the access object in FS to set the shared mem value. */
+static svn_error_t *
+begin_revprop_change(svn_fs_t *fs, apr_pool_t *pool)
+{
+  apr_int64_t current;
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  /* set the timeout for the write operation */
+  SVN_ERR(ensure_revprop_timeout(fs));
+  SVN_ERR(svn_named_atomic__write(NULL,
+                                  apr_time_now() + REVPROP_CHANGE_TIMEOUT,
+                                  ffd->revprop_timeout));
+
+  /* set the revprop generation to an odd value to indicate
+   * that a write is in progress
+   */
+  SVN_ERR(ensure_revprop_generation(fs, pool));
+  do
+    {
+      SVN_ERR(svn_named_atomic__add(&current,
+                                    1,
+                                    ffd->revprop_generation));
+    }
+  while (current % 2 == 0);
+
+  return SVN_NO_ERROR;
+}
+
+/* Set the revprop generation to the next even number to indicate that
+   a) readers shall re-read revprops, and
+   b) the write process has been completed (no recovery required)
+   Use the access object in FS to set the shared mem value. */
+static svn_error_t *
+end_revprop_change(svn_fs_t *fs, apr_pool_t *pool)
+{
+  apr_int64_t current = 1;
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  /* set the revprop generation to an even value to indicate
+   * that a write has been completed
+   */
+  SVN_ERR(ensure_revprop_generation(fs, pool));
+  do
+    {
+      SVN_ERR(svn_named_atomic__add(&current,
+                                    1,
+                                    ffd->revprop_generation));
+    }
+  while (current % 2);
+
+  /* Save the latest generation to disk. FS is currently in a "locked"
+   * state such that we can be sure the be the only ones to write that
+   * file.
+   */
+  return write_revprop_generation_file(fs, current, pool);
+}
+
 /* Set the revision property list of revision REV in filesystem FS to
    PROPLIST.  Use POOL for temporary allocations. */
 static svn_error_t *
@@ -2703,6 +3119,11 @@ set_revision_proplist(svn_fs_t *fs,
       const char *tmp_path;
       const char *perms_reference;
       svn_stream_t *stream;
+      svn_node_kind_t kind = svn_node_none;
+
+      /* test whether revprops already exist for this revision */
+      if (has_revprop_cache(fs, pool))
+        SVN_ERR(svn_io_check_path(final_path, &kind, pool));
 
       /* ### do we have a directory sitting around already? we really shouldn't
          ### have to get the dirname here. */
@@ -2717,9 +3138,17 @@ set_revision_proplist(svn_fs_t *fs,
          file won't exist and therefore can't serve as its own reference.
          (Whereas the rev file should already exist at this point.) */
       SVN_ERR(svn_fs_fs__path_rev_absolute(&perms_reference, fs, rev, pool));
+
+      /* Now, we may actually be replacing revprops. Make sure that all other
+         threads and processes will know about this. */
+      if (kind != svn_node_none)
+        SVN_ERR(begin_revprop_change(fs, pool));
+
       SVN_ERR(move_into_place(tmp_path, final_path, perms_reference, pool));
 
-      return SVN_NO_ERROR;
+      /* Indicate that the update (if relevant) has been completed. */
+      if (kind != svn_node_none)
+        SVN_ERR(end_revprop_change(fs, pool));
     }
 
   return SVN_NO_ERROR;
@@ -2732,9 +3161,26 @@ revision_proplist(apr_hash_t **proplist_
                   apr_pool_t *pool)
 {
   apr_hash_t *proplist;
+  fs_fs_data_t *ffd = fs->fsap_data;
+  const char *key;
 
   SVN_ERR(ensure_revision_exists(fs, rev, pool));
 
+  /* Try cache lookup first. */
+  if (has_revprop_cache(fs, pool))
+    {
+      apr_int64_t generation;
+      svn_boolean_t is_cached;
+
+      SVN_ERR(read_revprop_generation(&generation, fs, pool));
+
+      key = svn_fs_fs__combine_two_numbers(rev, generation, pool);
+      SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
+                             ffd->revprop_cache, key, pool));
+      if (is_cached)
+        return SVN_NO_ERROR;
+    }
+
   /* if (1); null condition for easier merging to revprop-packing */
     {
       apr_file_t *revprop_file = NULL;
@@ -2789,6 +3235,10 @@ revision_proplist(apr_hash_t **proplist_
       svn_pool_destroy(iterpool);
     }
 
+  /* Cache the result, if caching has been activated. */
+  if (has_revprop_cache(fs, pool))
+    SVN_ERR(svn_cache__set(ffd->revprop_cache, key, proplist, pool));
+
   *proplist_p = proplist;
 
   return SVN_NO_ERROR;
@@ -3538,8 +3988,9 @@ read_representation(svn_stream_t **conte
         {
           svn_stringbuf_t *fulltext;
           svn_boolean_t is_cached;
-          fulltext_cache_key = apr_psprintf(pool, "%ld/%" APR_OFF_T_FMT,
-                                      rep->revision, rep->offset);
+          fulltext_cache_key = svn_fs_fs__combine_two_numbers(rep->revision,
+                                                              rep->offset,
+                                                              pool);
           SVN_ERR(svn_cache__get((void **) &fulltext, &is_cached,
                                  ffd->fulltext_cache, fulltext_cache_key,
                                  pool));
@@ -4361,7 +4812,7 @@ read_change(change_t **change_p,
 
 /* Fetch all the changed path entries from FILE and store then in
    *CHANGED_PATHS.  Folding is done to remove redundant or unnecessary
-   *data.  Store a hash of paths to copyfrom revisions/paths in
+   *data.  Store a hash of paths to copyfrom "REV PATH" strings in
    COPYFROM_HASH if it is non-NULL.  If PREFOLDED is true, assume that
    the changed-path entries have already been folded (by
    write_final_changed_path_info) and may be out of order, so we shouldn't
@@ -4369,7 +4820,7 @@ read_change(change_t **change_p,
    allocations in POOL. */
 static svn_error_t *
 fetch_all_changes(apr_hash_t *changed_paths,
-                  apr_hash_t *copyfrom_hash,
+                  apr_hash_t *copyfrom_cache,
                   apr_file_t *file,
                   svn_boolean_t prefolded,
                   apr_pool_t *pool)
@@ -4384,7 +4835,7 @@ fetch_all_changes(apr_hash_t *changed_pa
 
   while (change)
     {
-      SVN_ERR(fold_change(changed_paths, change, copyfrom_hash));
+      SVN_ERR(fold_change(changed_paths, change, copyfrom_cache));
 
       /* Now, if our change was a deletion or replacement, we have to
          blow away any changes thus far on paths that are (or, were)
@@ -5004,6 +5455,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)
     {
@@ -5011,7 +5463,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. */
@@ -5024,7 +5477,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. */
@@ -5046,10 +5499,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;
@@ -5064,28 +5516,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
@@ -5263,6 +5718,7 @@ choose_delta_base(representation_t **rep
   int count;
   int walk;
   node_revision_t *base;
+  fs_fs_data_t *ffd = fs->fsap_data;
 
   /* If we have no predecessors, then use the empty stream as a
      base. */
@@ -5283,14 +5739,14 @@ choose_delta_base(representation_t **rep
      along very long node histories.  Close to HEAD however, we create
      a linear history to minimize delta size.  */
   walk = noderev->predecessor_count - count;
-  if (walk < SVN_FS_FS_MAX_LINEAR_DELTIFICATION)
+  if (walk < (int)ffd->max_linear_deltification)
     count = noderev->predecessor_count - 1;
 
   /* Finding the delta base over a very long distance can become extremely
      expensive for very deep histories, possibly causing client timeouts etc.
      OTOH, this is a rare operation and its gains are minimal. Lets simply
      start deltification anew close every other 1000 changes or so.  */
-  if (walk > SVN_FS_FS_MAX_DELTIFICATION_WALK)
+  if (walk > (int)ffd->max_deltification_walk)
     {
       *rep = NULL;
       return SVN_NO_ERROR;
@@ -5515,7 +5971,7 @@ rep_write_contents_close(void *baton)
   else
     {
       /* Write out our cosmetic end marker. */
-      SVN_ERR(svn_stream_printf(b->rep_stream, b->pool, "ENDREP\n"));
+      SVN_ERR(svn_stream_puts(b->rep_stream, "ENDREP\n"));
 
       b->noderev->data_rep = rep;
     }
@@ -5730,7 +6186,7 @@ write_hash_rep(representation_t *rep,
   stream = svn_stream_create(whb, pool);
   svn_stream_set_write(stream, write_hash_handler);
 
-  SVN_ERR(svn_stream_printf(whb->stream, pool, "PLAIN\n"));
+  SVN_ERR(svn_stream_puts(whb->stream, "PLAIN\n"));
 
   SVN_ERR(svn_hash_write2(hash, stream, SVN_HASH_TERMINATOR, pool));
 
@@ -5753,7 +6209,7 @@ write_hash_rep(representation_t *rep,
   else
     {
       /* Write out our cosmetic end marker. */
-      SVN_ERR(svn_stream_printf(whb->stream, pool, "ENDREP\n"));
+      SVN_ERR(svn_stream_puts(whb->stream, "ENDREP\n"));
 
       /* update the representation */
       rep->size = whb->size;
@@ -5770,7 +6226,6 @@ write_hash_rep(representation_t *rep,
    earlier reps with the same content.  When such existing reps can be found,
    we will truncate the one just written from the file and return the existing
    rep.  Perform temporary allocations in POOL. */
-#ifdef SVN_FS_FS_DELTIFY_DIRECTORIES
 static svn_error_t *
 write_hash_delta_rep(representation_t *rep,
                      apr_file_t *file,
@@ -5862,7 +6317,7 @@ write_hash_delta_rep(representation_t *r
     {
       /* Write out our cosmetic end marker. */
       SVN_ERR(get_file_offset(&rep_end, file, pool));
-      SVN_ERR(svn_stream_printf(file_stream, pool, "ENDREP\n"));
+      SVN_ERR(svn_stream_puts(file_stream, "ENDREP\n"));
 
       /* update the representation */
       rep->expanded_size = whb->size;
@@ -5871,7 +6326,6 @@ write_hash_delta_rep(representation_t *r
 
   return SVN_NO_ERROR;
 }
-#endif
 
 /* Sanity check ROOT_NODEREV, a candidate for being the root node-revision
    of (not yet committed) revision REV in FS.  Use POOL for temporary
@@ -5909,7 +6363,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
@@ -6024,14 +6478,13 @@ write_final_rev(const svn_fs_id_t **new_
           noderev->data_rep->txn_id = NULL;
           noderev->data_rep->revision = rev;
 
-#ifdef SVN_FS_FS_DELTIFY_DIRECTORIES
-          SVN_ERR(write_hash_delta_rep(noderev->data_rep, file,
-                                       str_entries, fs, noderev, NULL,
-                                       pool));
-#else
-          SVN_ERR(write_hash_rep(noderev->data_rep, file, str_entries,
-                                 fs, NULL, pool));
-#endif
+          if (ffd->deltify_directories)
+            SVN_ERR(write_hash_delta_rep(noderev->data_rep, file,
+                                         str_entries, fs, noderev, NULL,
+                                         pool));
+          else
+            SVN_ERR(write_hash_rep(noderev->data_rep, file, str_entries,
+                                   fs, NULL, pool));
         }
     }
   else
@@ -6064,14 +6517,13 @@ write_final_rev(const svn_fs_id_t **new_
       noderev->prop_rep->txn_id = NULL;
       noderev->prop_rep->revision = rev;
 
-#ifdef SVN_FS_FS_DELTIFY_PROPS
-      SVN_ERR(write_hash_delta_rep(noderev->prop_rep, file,
-                                   proplist, fs, noderev, reps_hash,
-                                   pool));
-#else
-      SVN_ERR(write_hash_rep(noderev->prop_rep, file, proplist,
-                             fs, reps_hash, pool));
-#endif
+      if (ffd->deltify_properties)
+        SVN_ERR(write_hash_delta_rep(noderev->prop_rep, file,
+                                     proplist, fs, noderev, reps_hash,
+                                     pool));
+      else
+        SVN_ERR(write_hash_rep(noderev->prop_rep, file, proplist,
+                               fs, reps_hash, pool));
     }
 
 
@@ -7170,17 +7622,6 @@ svn_fs_fs__recover(svn_fs_t *fs,
 }
 
 svn_error_t *
-svn_fs_fs__get_uuid(svn_fs_t *fs,
-                    const char **uuid_p,
-                    apr_pool_t *pool)
-{
-  fs_fs_data_t *ffd = fs->fsap_data;
-
-  *uuid_p = apr_pstrdup(pool, ffd->uuid);
-  return SVN_NO_ERROR;
-}
-
-svn_error_t *
 svn_fs_fs__set_uuid(svn_fs_t *fs,
                     const char *uuid,
                     apr_pool_t *pool)
@@ -7189,7 +7630,6 @@ svn_fs_fs__set_uuid(svn_fs_t *fs,
   apr_size_t my_uuid_len;
   const char *tmp_path;
   const char *uuid_path = path_uuid(fs, pool);
-  fs_fs_data_t *ffd = fs->fsap_data;
 
   if (! uuid)
     uuid = svn_uuid_generate(pool);
@@ -7210,7 +7650,7 @@ svn_fs_fs__set_uuid(svn_fs_t *fs,
 
   /* Remove the newline we added, and stash the UUID. */
   my_uuid[my_uuid_len - 1] = '\0';
-  ffd->uuid = my_uuid;
+  fs->uuid = my_uuid;
 
   return SVN_NO_ERROR;
 }
@@ -7946,58 +8386,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_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;
+      	svn_fs_root_t *root;
 
-        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));
+        svn_pool_clear(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);
+      	/* ### TODO: Make sure caches are disabled.
 
-        predecessor_predecessor_count = root_noderev->predecessor_count;
+      	   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));
       }
   }
 
@@ -8413,7 +8819,7 @@ hotcopy_incremental_check_preconditions(
 
   /* Make sure the UUID of source and destination match up.
    * We don't want to copy over a different repository. */
-  if (strcmp(src_ffd->uuid, dst_ffd->uuid) != 0)
+  if (strcmp(src_fs->uuid, dst_fs->uuid) != 0)
     return svn_error_create(SVN_ERR_RA_UUID_MISMATCH, NULL,
                             _("The UUID of the hotcopy source does "
                               "not match the UUID of the hotcopy "
@@ -8793,6 +9199,15 @@ hotcopy_body(void *baton, apr_pool_t *po
     SVN_ERR(svn_io_dir_file_copy(src_fs->path, dst_fs->path,
                                  PATH_TXN_CURRENT, pool));
 
+  /* If a revprop generation file exists in the source filesystem,
+   * force a fresh revprop caching namespace for the destination by
+   * setting the generation to zero. We have no idea if the revprops
+   * we copied above really belong to the currently cached generation. */
+  SVN_ERR(svn_io_check_path(path_revprop_generation(src_fs, pool),
+                            &kind, pool));
+  if (kind == svn_node_file)
+    SVN_ERR(write_revprop_generation_file(dst_fs, 0, pool));
+
   /* Hotcopied FS is complete. Stamp it with a format file. */
   SVN_ERR(write_format(svn_dirent_join(dst_fs->path, PATH_FORMAT, pool),
                        dst_ffd->format, max_files_per_dir, TRUE, pool));
@@ -8801,6 +9216,20 @@ hotcopy_body(void *baton, apr_pool_t *po
 }
 
 
+/* Set up shared data between SRC_FS and DST_FS. */
+static void
+hotcopy_setup_shared_fs_data(svn_fs_t *src_fs, svn_fs_t *dst_fs)
+{
+  fs_fs_data_t *src_ffd = src_fs->fsap_data;
+  fs_fs_data_t *dst_ffd = dst_fs->fsap_data;
+
+  /* The common pool and mutexes are shared between src and dst filesystems.
+   * During hotcopy we only grab the mutexes for the destination, so there
+   * is no risk of dead-lock. We don't write to the src filesystem. Shared
+   * data for the src_fs has already been initialised in fs_hotcopy(). */
+  dst_ffd->shared = src_ffd->shared;
+}
+
 /* Create an empty filesystem at DST_FS at DST_PATH with the same
  * configuration as SRC_FS (uuid, format, and other parameters).
  * After creation DST_FS has no revisions, not even revision zero. */
@@ -8859,7 +9288,7 @@ hotcopy_create_empty_dest(svn_fs_t *src_
 
   /* Create lock file and UUID. */
   SVN_ERR(svn_io_file_create(path_lock(dst_fs, pool), "", pool));
-  SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_ffd->uuid, pool));
+  SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_fs->uuid, pool));
 
   /* Create the min unpacked rev file. */
   if (dst_ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
@@ -8876,6 +9305,10 @@ hotcopy_create_empty_dest(svn_fs_t *src_
     }
 
   dst_ffd->youngest_rev_cache = 0;
+
+  hotcopy_setup_shared_fs_data(src_fs, dst_fs);
+  SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
+
   return SVN_NO_ERROR;
 }
 
@@ -8917,6 +9350,8 @@ svn_fs_fs__hotcopy(svn_fs_t *src_fs,
           SVN_ERR(svn_fs_fs__open(dst_fs, dst_path, pool));
           SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs,
                                                           pool));
+          hotcopy_setup_shared_fs_data(src_fs, dst_fs);
+          SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
         }
     }
   else

Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs_fs.h?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/fs_fs.h Wed May 16 20:32:43 2012
@@ -355,12 +355,6 @@ svn_error_t *svn_fs_fs__create(svn_fs_t 
                                const char *path,
                                apr_pool_t *pool);
 
-/* Store the uuid of the repository FS in *UUID.  Allocate space in
-   POOL. */
-svn_error_t *svn_fs_fs__get_uuid(svn_fs_t *fs,
-                                 const char **uuid,
-                                 apr_pool_t *pool);
-
 /* Set the uuid of repository FS to UUID, if UUID is not NULL;
    otherwise, set the uuid of FS to a newly generated UUID.  Perform
    temporary allocations in POOL. */

Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/id.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/id.c Wed May 16 20:32:43 2012
@@ -26,6 +26,7 @@
 #include "id.h"
 #include "../libsvn_fs/fs-loader.h"
 #include "private/svn_temp_serializer.h"
+#include "private/svn_string_private.h"
 
 
 typedef struct id_private_t {
@@ -88,22 +89,25 @@ svn_string_t *
 svn_fs_fs__id_unparse(const svn_fs_id_t *id,
                       apr_pool_t *pool)
 {
-  const char *txn_rev_id;
   id_private_t *pvt = id->fsap_data;
 
   if ((! pvt->txn_id))
     {
-      txn_rev_id = apr_psprintf(pool, "%ld/%"
-                                APR_OFF_T_FMT, pvt->rev, pvt->offset);
+      char rev_string[SVN_INT64_BUFFER_SIZE];
+      char offset_string[SVN_INT64_BUFFER_SIZE];
+
+      svn__i64toa(rev_string, pvt->rev);
+      svn__i64toa(offset_string, pvt->offset);
+      return svn_string_createf(pool, "%s.%s.r%s/%s",
+                                pvt->node_id, pvt->copy_id,
+                                rev_string, offset_string);
     }
   else
     {
-      txn_rev_id = pvt->txn_id;
+      return svn_string_createf(pool, "%s.%s.t%s",
+                                pvt->node_id, pvt->copy_id,
+                                pvt->txn_id);
     }
-  return svn_string_createf(pool, "%s.%s.%c%s",
-                            pvt->node_id, pvt->copy_id,
-                            (pvt->txn_id ? 't' : 'r'),
-                            txn_rev_id);
 }
 
 

Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/lock.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/lock.c Wed May 16 20:32:43 2012
@@ -493,7 +493,7 @@ get_lock(svn_lock_t **lock_p,
 
   SVN_ERR(read_digest_file(NULL, &lock, fs->path, digest_path, pool));
   if (! lock)
-    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path, pool);
+    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path);
 
   /* Don't return an expired lock. */
   if (lock->expiration_date && (apr_time_now() > lock->expiration_date))
@@ -503,7 +503,7 @@ get_lock(svn_lock_t **lock_p,
       if (have_write_lock)
         SVN_ERR(delete_lock(fs, lock, pool));
       *lock_p = NULL;
-      return SVN_FS__ERR_LOCK_EXPIRED(fs, lock->token, pool);
+      return SVN_FS__ERR_LOCK_EXPIRED(fs, lock->token);
     }
 
   *lock_p = lock;
@@ -766,7 +766,7 @@ lock_body(void *baton, apr_pool_t *pool)
   SVN_ERR(lb->fs->vtable->revision_root(&root, lb->fs, youngest, pool));
   SVN_ERR(svn_fs_fs__check_path(&kind, root, lb->path, pool));
   if (kind == svn_node_dir)
-    return SVN_FS__ERR_NOT_FILE(lb->fs, lb->path, pool);
+    return SVN_FS__ERR_NOT_FILE(lb->fs, lb->path);
 
   /* While our locking implementation easily supports the locking of
      nonexistent paths, we deliberately choose not to allow such madness. */
@@ -786,7 +786,7 @@ lock_body(void *baton, apr_pool_t *pool)
 
   /* We need to have a username attached to the fs. */
   if (!lb->fs->access_ctx || !lb->fs->access_ctx->username)
-    return SVN_FS__ERR_NO_USER(lb->fs, pool);
+    return SVN_FS__ERR_NO_USER(lb->fs);
 
   /* Is the caller attempting to lock an out-of-date working file? */
   if (SVN_IS_VALID_REVNUM(lb->current_rev))
@@ -832,7 +832,7 @@ lock_body(void *baton, apr_pool_t *pool)
       if (! lb->steal_lock)
         {
           /* Sorry, the path is already locked. */
-          return SVN_FS__ERR_PATH_ALREADY_LOCKED(lb->fs, existing_lock, pool);
+          return SVN_FS__ERR_PATH_ALREADY_LOCKED(lb->fs, existing_lock);
         }
       else
         {
@@ -888,16 +888,16 @@ unlock_body(void *baton, apr_pool_t *poo
     {
       /* Sanity check:  the incoming token should match lock->token. */
       if (strcmp(ub->token, lock->token) != 0)
-        return SVN_FS__ERR_NO_SUCH_LOCK(ub->fs, lock->path, pool);
+        return SVN_FS__ERR_NO_SUCH_LOCK(ub->fs, lock->path);
 
       /* There better be a username attached to the fs. */
       if (! (ub->fs->access_ctx && ub->fs->access_ctx->username))
-        return SVN_FS__ERR_NO_USER(ub->fs, pool);
+        return SVN_FS__ERR_NO_USER(ub->fs);
 
       /* And that username better be the same as the lock's owner. */
       if (strcmp(ub->fs->access_ctx->username, lock->owner) != 0)
         return SVN_FS__ERR_LOCK_OWNER_MISMATCH(
-           ub->fs, ub->fs->access_ctx->username, lock->owner, pool);
+           ub->fs, ub->fs->access_ctx->username, lock->owner);
     }
 
   /* Remove lock and lock token files. */

Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/rep-cache-db.sql Wed May 16 20:32:43 2012
@@ -33,11 +33,6 @@ CREATE TABLE rep_cache (
   expanded_size INTEGER NOT NULL
   );
 
-/* There isn't an implicit index on a TEXT column, so create an explicit one. */
-CREATE INDEX I_HASH on REP_CACHE (hash);
-
-/* The index didn't exist until 1.7.5; therefore, some USER_VERSION=1
-   rep-cache.db files out there DO NOT contain an I_HASH index. */
 PRAGMA USER_VERSION = 1;
 
 

Modified: subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/temp_serializer.c?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/fix-rdump-editor/subversion/libsvn_fs_fs/temp_serializer.c Wed May 16 20:32:43 2012
@@ -30,6 +30,7 @@
 
 #include "private/svn_fs_util.h"
 #include "private/svn_temp_serializer.h"
+#include "private/svn_subr_private.h"
 
 #include "temp_serializer.h"
 
@@ -64,10 +65,6 @@ encode_number(apr_int64_t number, char *
   return key_buffer;
 }
 
-/* Prepend the NUMBER to the STRING in a space efficient way that no other
- * (number,string) combination can produce the same result.
- * Allocate temporaries as well as the result from POOL.
- */
 const char*
 svn_fs_fs__combine_number_and_string(apr_int64_t number,
                                      const char *string,
@@ -91,10 +88,6 @@ svn_fs_fs__combine_number_and_string(apr
   return key;
 }
 
-/* Combine the numbers A and B a space efficient way that no other
- * combination of numbers can produce the same result.
- * Allocate temporaries as well as the result from POOL.
- */
 const char*
 svn_fs_fs__combine_two_numbers(apr_int64_t a,
                                apr_int64_t b,
@@ -184,7 +177,7 @@ serialize_checksum(svn_temp_serializer__
 /* Utility function to deserialize the checksum CS inside the BUFFER.
  */
 static void
-deserialize_checksum(void *buffer, svn_checksum_t * const *cs)
+deserialize_checksum(void *buffer, svn_checksum_t **cs)
 {
   svn_temp_deserializer__resolve(buffer, (void **)cs);
   if (*cs == NULL)
@@ -367,7 +360,7 @@ serialize_dir(apr_hash_t *entries, apr_p
 static apr_hash_t *
 deserialize_dir(void *buffer, hash_data_t *hash_data, apr_pool_t *pool)
 {
-  apr_hash_t *result = apr_hash_make(pool);
+  apr_hash_t *result = svn_hash__make(pool);
   apr_size_t i;
   apr_size_t count;
   svn_fs_dirent_t *entry;
@@ -489,7 +482,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 +515,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 +541,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 +557,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)
 {
@@ -602,7 +595,7 @@ serialize_cstring_array(svn_temp_seriali
 {
   apr_size_t i;
   const char **entries = *strings;
-  
+
   /* serialize COUNT entries pointers (the array) */
   svn_temp_serializer__push(context,
                             (const void * const *)strings,
@@ -623,7 +616,7 @@ serialize_svn_string_array(svn_temp_seri
 {
   apr_size_t i;
   const svn_string_t **entries = *strings;
-  
+
   /* serialize COUNT entries pointers (the array) */
   svn_temp_serializer__push(context,
                             (const void * const *)strings,
@@ -637,7 +630,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)
@@ -653,14 +646,14 @@ svn_fs_fs__serialize_properties(char **d
   properties.count = apr_hash_count(hash);
   properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1));
   properties.values = apr_palloc(pool, sizeof(const char*) * properties.count);
-  
+
   /* populate it with the hash entries */
   for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i)
     {
       properties.keys[i] = svn__apr_hash_index_key(hi);
       properties.values[i] = svn__apr_hash_index_val(hi);
     }
-  
+
   /* serialize it */
   context = svn_temp_serializer__init(&properties,
                                       sizeof(properties),
@@ -682,30 +675,30 @@ 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)
 {
-  apr_hash_t *hash = apr_hash_make(pool);
+  apr_hash_t *hash = svn_hash__make(pool);
   properties_data_t *properties = (properties_data_t *)data;
   size_t i;
 
   /* de-serialize our auxilliary data structure */
   svn_temp_deserializer__resolve(properties, (void**)&properties->keys);
   svn_temp_deserializer__resolve(properties, (void**)&properties->values);
-  
+
   /* de-serialize each entry and put it into the hash */
   for (i = 0; i < properties->count; ++i)
     {
       apr_size_t len = properties->keys[i+1] - properties->keys[i] - 1;
-      svn_temp_deserializer__resolve(properties->keys, 
+      svn_temp_deserializer__resolve((void*)properties->keys,
                                      (void**)&properties->keys[i]);
-      
-      deserialize_svn_string(properties->values, 
+
+      deserialize_svn_string((void*)properties->values,
                              (svn_string_t **)&properties->values[i]);
-      
-      apr_hash_set(hash, 
-                   properties->keys[i], len, 
+
+      apr_hash_set(hash,
+                   properties->keys[i], len,
                    properties->values[i]);
     }
 
@@ -716,7 +709,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 +734,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 +752,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 +777,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 +796,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 +809,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 +825,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,12 +840,12 @@ 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)
 {
-  apr_off_t *manifest = (apr_off_t *)data;
+  const apr_off_t *manifest = data;
   apr_int64_t shard_pos = *(apr_int64_t *)baton;
 
   *(apr_off_t *)out = manifest[shard_pos];
@@ -879,9 +872,9 @@ find_entry(svn_fs_dirent_t **entries,
   for (middle = upper / 2; lower < upper; middle = (upper + lower) / 2)
     {
       const svn_fs_dirent_t *entry =
-          svn_temp_deserializer__ptr(entries, (const void **)&entries[middle]);
+          svn_temp_deserializer__ptr(entries, (const void *const *)&entries[middle]);
       const char* entry_name =
-          svn_temp_deserializer__ptr(entry, (const void **)&entry->name);
+          svn_temp_deserializer__ptr(entry, (const void *const *)&entry->name);
 
       int diff = strcmp(entry_name, name);
       if (diff < 0)
@@ -895,9 +888,9 @@ find_entry(svn_fs_dirent_t **entries,
   if (lower < count)
     {
       const svn_fs_dirent_t *entry =
-          svn_temp_deserializer__ptr(entries, (const void **)&entries[lower]);
+          svn_temp_deserializer__ptr(entries, (const void *const *)&entries[lower]);
       const char* entry_name =
-          svn_temp_deserializer__ptr(entry, (const void **)&entry->name);
+          svn_temp_deserializer__ptr(entry, (const void *const *)&entry->name);
 
       if (strcmp(entry_name, name) == 0)
         *found = TRUE;
@@ -908,22 +901,22 @@ 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)
 {
-  hash_data_t *hash_data = (hash_data_t *)data;
+  const hash_data_t *hash_data = data;
   const char* name = baton;
   svn_boolean_t found;
 
   /* resolve the reference to the entries array */
   const svn_fs_dirent_t * const *entries =
-    svn_temp_deserializer__ptr(data, (const void **)&hash_data->entries);
+    svn_temp_deserializer__ptr(data, (const void *const *)&hash_data->entries);
 
   /* resolve the reference to the lengths array */
   const apr_uint32_t *lengths =
-    svn_temp_deserializer__ptr(data, (const void **)&hash_data->lengths);
+    svn_temp_deserializer__ptr(data, (const void *const *)&hash_data->lengths);
 
   /* binary search for the desired entry by name */
   apr_size_t pos = find_entry((svn_fs_dirent_t **)entries,
@@ -936,7 +929,7 @@ svn_fs_fs__extract_dir_entry(void **out,
   if (found)
     {
       const svn_fs_dirent_t *source =
-          svn_temp_deserializer__ptr(entries, (const void **)&entries[pos]);
+          svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]);
 
       /* Entries have been serialized one-by-one, each time including all
        * nestes structures and strings. Therefore, they occupy a single
@@ -961,7 +954,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 +976,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)
@@ -1007,12 +1000,12 @@ svn_fs_fs__replace_dir_entry(char **data
   /* resolve the reference to the entries array */
   entries = (svn_fs_dirent_t **)
     svn_temp_deserializer__ptr((const char *)hash_data,
-                               (const void **)&hash_data->entries);
+                               (const void *const *)&hash_data->entries);
 
   /* resolve the reference to the lengths array */
   lengths = (apr_uint32_t *)
     svn_temp_deserializer__ptr((const char *)hash_data,
-                               (const void **)&hash_data->lengths);
+                               (const void *const *)&hash_data->lengths);
 
   /* binary search for the desired entry by name */
   pos = find_entry(entries, replace_baton->name, hash_data->count, &found);
@@ -1081,7 +1074,7 @@ svn_fs_fs__replace_dir_entry(char **data
   hash_data = (hash_data_t *)*data;
   lengths = (apr_uint32_t *)
     svn_temp_deserializer__ptr((const char *)hash_data,
-                               (const void **)&hash_data->lengths);
+                               (const void *const *)&hash_data->lengths);
   lengths[pos] = length;
 
   return SVN_NO_ERROR;