You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gb...@apache.org on 2013/12/08 18:56:53 UTC

svn commit: r1549081 [6/18] - in /subversion/branches/invoke-diff-cmd-feature: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/server-side/ contrib/server-side/svncutter/ subversion/bindings/javahl/native/ subversion/bind...

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/caching.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/caching.c Sun Dec  8 17:56:46 2013
@@ -25,6 +25,7 @@
 #include "id.h"
 #include "dag.h"
 #include "tree.h"
+#include "index.h"
 #include "temp_serializer.h"
 #include "../libsvn_fs/fs-loader.h"
 
@@ -89,7 +90,7 @@ read_config(svn_memcache_t **memcache_p,
   fs_fs_data_t *ffd = fs->fsap_data;
 
   SVN_ERR(svn_cache__make_memcache_from_config(memcache_p, ffd->config,
-                                              fs->pool));
+                                               fs->pool));
 
   /* No cache namespace by default.  I.e. all FS instances share the
    * cached data.  If you specify different namespaces, the data will
@@ -143,8 +144,8 @@ read_config(svn_memcache_t **memcache_p,
                                    ""), "2"))
     *cache_revprops
       = svn_hash__get_bool(fs->config,
-                          SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
-                          FALSE);
+                           SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
+                           FALSE);
   else
     *cache_revprops = svn_named_atomic__is_efficient();
 
@@ -403,7 +404,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
    * - Data that can be reconstructed from other elements has low prio
    *   (e.g. fulltexts, directories etc.)
    * - Index data required to find any of the other data has high prio
-   *   (e.g. noderevs)
+   *   (e.g. noderevs, L2P and P2L index pages)
    * - everthing else should use default prio
    */
 
@@ -492,7 +493,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   SVN_ERR(create_cache(&(ffd->node_revision_cache),
                        NULL,
                        membuffer,
-                       0, 0, /* Do not use inprocess cache */
+                       32, 32, /* ~200 byte / entry; 1k entries total */
                        svn_fs_fs__serialize_node_revision,
                        svn_fs_fs__deserialize_node_revision,
                        sizeof(pair_cache_key_t),
@@ -506,7 +507,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   SVN_ERR(create_cache(&(ffd->rep_header_cache),
                        NULL,
                        membuffer,
-                       0, 0, /* Do not use inprocess cache */
+                       1, 1000, /* ~8 bytes / entry; 1k entries total */
                        svn_fs_fs__serialize_rep_header,
                        svn_fs_fs__deserialize_rep_header,
                        sizeof(representation_cache_key_t),
@@ -520,7 +521,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
   SVN_ERR(create_cache(&(ffd->changes_cache),
                        NULL,
                        membuffer,
-                       0, 0, /* Do not use inprocess cache */
+                       1, 8, /* 1k / entry; 8 entries total, rarely used */
                        svn_fs_fs__serialize_changes,
                        svn_fs_fs__deserialize_changes,
                        sizeof(svn_revnum_t),
@@ -655,6 +656,71 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
       ffd->combined_window_cache = NULL;
     }
 
+  if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
+    {
+      SVN_ERR(create_cache(&(ffd->l2p_header_cache),
+                           NULL,
+                           membuffer,
+                           64, 16, /* entry size varies but we must cover
+                                      a reasonable number of revisions (1k) */
+                           svn_fs_fs__serialize_l2p_header,
+                           svn_fs_fs__deserialize_l2p_header,
+                           sizeof(pair_cache_key_t),
+                           apr_pstrcat(pool, prefix, "L2P_HEADER",
+                                       (char *)NULL),
+                           SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+                           fs,
+                           no_handler,
+                           fs->pool));
+      SVN_ERR(create_cache(&(ffd->l2p_page_cache),
+                           NULL,
+                           membuffer,
+                           64, 16, /* entry size varies but we must cover
+                                      a reasonable number of revisions (1k) */
+                           svn_fs_fs__serialize_l2p_page,
+                           svn_fs_fs__deserialize_l2p_page,
+                           sizeof(svn_fs_fs__page_cache_key_t),
+                           apr_pstrcat(pool, prefix, "L2P_PAGE",
+                                       (char *)NULL),
+                           SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+                           fs,
+                           no_handler,
+                           fs->pool));
+      SVN_ERR(create_cache(&(ffd->p2l_header_cache),
+                           NULL,
+                           membuffer,
+                           4, 1, /* Large entries. Rarely used. */
+                           svn_fs_fs__serialize_p2l_header,
+                           svn_fs_fs__deserialize_p2l_header,
+                           sizeof(pair_cache_key_t),
+                           apr_pstrcat(pool, prefix, "P2L_HEADER",
+                                       (char *)NULL),
+                           SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+                           fs,
+                           no_handler,
+                           fs->pool));
+      SVN_ERR(create_cache(&(ffd->p2l_page_cache),
+                           NULL,
+                           membuffer,
+                           4, 16, /* Variably sized entries. Rarely used. */
+                           svn_fs_fs__serialize_p2l_page,
+                           svn_fs_fs__deserialize_p2l_page,
+                           sizeof(svn_fs_fs__page_cache_key_t),
+                           apr_pstrcat(pool, prefix, "P2L_PAGE",
+                                       (char *)NULL),
+                           SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+                           fs,
+                           no_handler,
+                           fs->pool));
+    }
+  else
+    {
+      ffd->l2p_header_cache = NULL;
+      ffd->l2p_page_cache = NULL;
+      ffd->p2l_header_cache = NULL;
+      ffd->p2l_page_cache = NULL;
+    }
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.c Sun Dec  8 17:56:46 2013
@@ -221,6 +221,8 @@ static svn_error_t *
 initialize_fs_struct(svn_fs_t *fs)
 {
   fs_fs_data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd));
+  ffd->min_log_addressing_rev = SVN_INVALID_REVNUM;
+
   fs->vtable = &fs_vtable;
   fs->fsap_data = ffd;
   return SVN_NO_ERROR;

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.h?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.h Sun Dec  8 17:56:46 2013
@@ -71,6 +71,10 @@ extern "C" {
 #define PATH_PACKED           "pack"             /* Packed revision data file */
 #define PATH_EXT_PACKED_SHARD ".pack"            /* Extension for packed
                                                     shards */
+#define PATH_EXT_L2P_INDEX    ".l2p"             /* extension of the log-
+                                                    to-phys index */
+#define PATH_EXT_P2L_INDEX    ".p2l"             /* extension of the phys-
+                                                    to-log index */
 /* If you change this, look at tests/svn_test_fs.c(maybe_install_fsfs_conf) */
 #define PATH_CONFIG           "fsfs.conf"        /* Configuration */
 
@@ -84,6 +88,10 @@ extern "C" {
 #define PATH_EXT_PROPS     ".props"        /* Extension for node props */
 #define PATH_EXT_REV       ".rev"          /* Extension of protorev file */
 #define PATH_EXT_REV_LOCK  ".rev-lock"     /* Extension of protorev lock file */
+#define PATH_TXN_ITEM_INDEX "itemidx"      /* File containing the current item
+                                              index number */
+#define PATH_INDEX          "index"        /* name of index files w/o ext */
+
 /* Names of files in legacy FS formats */
 #define PATH_REV           "rev"           /* Proto rev file */
 #define PATH_REV_LOCK      "rev-lock"      /* Proto rev (write) lock file */
@@ -101,11 +109,19 @@ extern "C" {
 #define CONFIG_SECTION_PACKED_REVPROPS   "packed-revprops"
 #define CONFIG_OPTION_REVPROP_PACK_SIZE  "revprop-pack-size"
 #define CONFIG_OPTION_COMPRESS_PACKED_REVPROPS  "compress-packed-revprops"
+#define CONFIG_SECTION_IO                "io"
+#define CONFIG_OPTION_BLOCK_SIZE         "block-size"
+#define CONFIG_OPTION_L2P_PAGE_SIZE      "l2p-page-size"
+#define CONFIG_OPTION_P2L_PAGE_SIZE      "p2l-page-size"
 
 /* The format number of this filesystem.
    This is independent of the repository format number, and
-   independent of any other FS back ends. */
-#define SVN_FS_FS__FORMAT_NUMBER   6
+   independent of any other FS back ends.
+
+   Note: If you bump this, please update the switch statement in
+         svn_fs_fs__create() as well.
+ */
+#define SVN_FS_FS__FORMAT_NUMBER   7
 
 /* The minimum format number that supports svndiff version 1.  */
 #define SVN_FS_FS__MIN_SVNDIFF1_FORMAT 2
@@ -148,6 +164,9 @@ extern "C" {
 /* The minimum format number that supports packed revprops. */
 #define SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT 6
 
+/* The minimum format number that supports packed revprops. */
+#define SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT 7
+
 /* Minimum format number that will record moves */
 #define SVN_FS_FS__MIN_MOVE_SUPPORT_FORMAT 7
 
@@ -244,8 +263,8 @@ typedef struct representation_cache_key_
   /* Packed or non-packed representation? */
   svn_boolean_t is_packed;
 
-  /* Item offset of the representation */
-  apr_uint64_t offset;
+  /* Item index of the representation */
+  apr_uint64_t item_index;
 } representation_cache_key_t;
 
 /* Key type that identifies a txdelta window. */
@@ -257,8 +276,8 @@ typedef struct window_cache_key_t
   /* Window number within that representation */
   apr_int32_t chunk_index;
 
-  /* Offset of the representation within REVISION */
-  apr_uint64_t offset;
+  /* Item index of the representation */
+  apr_uint64_t item_index;
 } window_cache_key_t;
 
 /* Private (non-shared) FSFS-specific data for each svn_fs_t object.
@@ -267,10 +286,26 @@ typedef struct fs_fs_data_t
 {
   /* The format number of this FS. */
   int format;
+
   /* The maximum number of files to store per directory (for sharded
      layouts) or zero (for linear layouts). */
   int max_files_per_dir;
 
+  /* The first revision that uses logical addressing.  SVN_INVALID_REVNUM
+     if there is no such revision (pre-f7 or non-sharded).  May be a
+     future revision if the current shard started with physical addressing
+     and is not complete, yet. */
+  svn_revnum_t min_log_addressing_rev;
+
+  /* Rev / pack file read granularity. */
+  apr_int64_t block_size;
+
+  /* Capacity in entries of log-to-phys index pages */
+  apr_int64_t l2p_page_size;
+
+  /* Rev / pack file granularity covered by phys-to-log index pages */
+  apr_int64_t p2l_page_size;
+  
   /* The revision that was youngest, last time we checked. */
   svn_revnum_t youngest_rev_cache;
 
@@ -332,7 +367,7 @@ typedef struct fs_fs_data_t
      the key is window_cache_key_t */
   svn_cache__t *combined_window_cache;
 
-  /* Cache for node_revision_t objects; the key is (revision, id offset) */
+  /* Cache for node_revision_t objects; the key is (revision, item_index) */
   svn_cache__t *node_revision_cache;
 
   /* Cache for change lists as APR arrays of change_t * objects; the key
@@ -340,7 +375,7 @@ typedef struct fs_fs_data_t
   svn_cache__t *changes_cache;
 
   /* Cache for svn_fs_fs__rep_header_t objects; the key is a
-     (revision, is_packed, offset) set */
+     (revision, item index) pair */
   svn_cache__t *rep_header_cache;
 
   /* Cache for svn_mergeinfo_t objects; the key is a combination of
@@ -352,6 +387,23 @@ typedef struct fs_fs_data_t
      if the node has mergeinfo, "0" if it doesn't. */
   svn_cache__t *mergeinfo_existence_cache;
 
+  /* Cache for l2p_header_t objects; the key is (revision, is-packed).
+     Will be NULL for pre-format7 repos */
+  svn_cache__t *l2p_header_cache;
+
+  /* Cache for l2p_page_t objects; the key is svn_fs_fs__page_cache_key_t.
+     Will be NULL for pre-format7 repos */
+  svn_cache__t *l2p_page_cache;
+
+  /* Cache for p2l_header_t objects; the key is (revision, is-packed).
+     Will be NULL for pre-format7 repos */
+  svn_cache__t *p2l_header_cache;
+
+  /* Cache for apr_array_header_t objects containing svn_fs_fs__p2l_entry_t
+     elements; the key is svn_fs_fs__page_cache_key_t.
+     Will be NULL for pre-format7 repos */
+  svn_cache__t *p2l_page_cache;
+
   /* TRUE while the we hold a lock on the write lock file. */
   svn_boolean_t has_write_lock;
 
@@ -449,8 +501,8 @@ typedef struct representation_t
   /* Revision where this representation is located. */
   svn_revnum_t revision;
 
-  /* Offset into the revision file where it is located. */
-  svn_filesize_t offset;
+  /* Item index with the the revision. */
+  apr_uint64_t item_index;
 
   /* The size of the representation in bytes as seen in the revision
      file. */

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.c Sun Dec  8 17:56:46 2013
@@ -42,7 +42,6 @@
 
 #include "private/svn_fs_util.h"
 #include "private/svn_string_private.h"
-#include "private/svn_subr_private.h"
 #include "../libsvn_fs/fs-loader.h"
 
 /* The default maximum number of files per directory to store in the
@@ -271,16 +270,21 @@ check_format(int format)
 }
 
 /* Read the format number and maximum number of files per directory
-   from PATH and return them in *PFORMAT and *MAX_FILES_PER_DIR
-   respectively.
+   from PATH and return them in *PFORMAT, *MAX_FILES_PER_DIR and
+   MIN_LOG_ADDRESSING_REV respectively.
 
    *MAX_FILES_PER_DIR is obtained from the 'layout' format option, and
    will be set to zero if a linear scheme should be used.
+   *MIN_LOG_ADDRESSING_REV is obtained from the 'addressing' format option,
+   and will be set to SVN_INVALID_REVNUM for physical addressing.
 
    Use POOL for temporary allocation. */
 static svn_error_t *
-read_format(int *pformat, int *max_files_per_dir,
-            const char *path, apr_pool_t *pool)
+read_format(int *pformat,
+            int *max_files_per_dir,
+            svn_revnum_t *min_log_addressing_rev,
+            const char *path,
+            apr_pool_t *pool)
 {
   svn_error_t *err;
   svn_stream_t *stream;
@@ -325,6 +329,7 @@ read_format(int *pformat, int *max_files
 
   /* Set the default values for anything that can be set via an option. */
   *max_files_per_dir = 0;
+  *min_log_addressing_rev = SVN_INVALID_REVNUM;
 
   /* Read any options. */
   while (!eos)
@@ -351,17 +356,47 @@ read_format(int *pformat, int *max_files
             }
         }
 
+      if (*pformat >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT &&
+          strncmp(buf->data, "addressing ", 11) == 0)
+        {
+          if (strcmp(buf->data + 11, "physical") == 0)
+            {
+              *min_log_addressing_rev = SVN_INVALID_REVNUM;
+              continue;
+            }
+
+          if (strncmp(buf->data + 11, "logical ", 8) == 0)
+            {
+              int value;
+
+              /* Check that the argument is numeric. */
+              SVN_ERR(check_format_file_buffer_numeric(buf->data, 19, path, pool));
+              SVN_ERR(svn_cstring_atoi(&value, buf->data + 19));
+              *min_log_addressing_rev = value;
+              continue;
+            }
+        }
+
       return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
          _("'%s' contains invalid filesystem format option '%s'"),
          svn_dirent_local_style(path, pool), buf->data);
     }
 
+  /* Non-sharded repositories never use logical addressing.
+   * If the format file is inconsistent in that respect, something
+   * probably went wrong.
+   */
+  if (*min_log_addressing_rev != SVN_INVALID_REVNUM && !*max_files_per_dir)
+    return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
+       _("'%s' specifies logical addressing for a non-sharded repository"),
+       svn_dirent_local_style(path, pool));
+
   return SVN_NO_ERROR;
 }
 
-/* Write the format number and maximum number of files per directory
-   to a new format file in PATH, possibly expecting to overwrite a
-   previously existing file.
+/* Write the format number, maximum number of files per directory and
+   the addressing scheme to a new format file in PATH, possibly expecting
+   to overwrite a previously existing file.
 
    Use POOL for temporary allocation. */
 svn_error_t *
@@ -387,6 +422,17 @@ svn_fs_fs__write_format(svn_fs_t *fs,
         svn_stringbuf_appendcstr(sb, "layout linear\n");
     }
 
+  if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
+    {
+      if (ffd->min_log_addressing_rev == SVN_INVALID_REVNUM)
+        svn_stringbuf_appendcstr(sb, "addressing physical\n");
+      else
+        svn_stringbuf_appendcstr(sb,
+                                 apr_psprintf(pool,
+                                              "addressing logical %ld\n",
+                                              ffd->min_log_addressing_rev));
+    }
+
   /* svn_io_write_version_file() does a load of magic to allow it to
      replace version files that already exist.  We only need to do
      that when we're allowed to overwrite an existing file. */
@@ -482,6 +528,32 @@ read_config(fs_fs_data_t *ffd,
       ffd->compress_packed_revprops = FALSE;
     }
 
+  if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
+    {
+      SVN_ERR(svn_config_get_int64(ffd->config, &ffd->block_size,
+                                   CONFIG_SECTION_IO,
+                                   CONFIG_OPTION_BLOCK_SIZE,
+                                   64));
+      SVN_ERR(svn_config_get_int64(ffd->config, &ffd->l2p_page_size,
+                                   CONFIG_SECTION_IO,
+                                   CONFIG_OPTION_L2P_PAGE_SIZE,
+                                   0x2000));
+      SVN_ERR(svn_config_get_int64(ffd->config, &ffd->p2l_page_size,
+                                   CONFIG_SECTION_IO,
+                                   CONFIG_OPTION_P2L_PAGE_SIZE,
+                                   64));
+
+      ffd->block_size *= 0x400;
+      ffd->p2l_page_size *= 0x400;
+    }
+  else
+    {
+      /* should be irrelevant but we initialize them anyway */
+      ffd->block_size = 0x1000;
+      ffd->l2p_page_size = 0x2000;
+      ffd->p2l_page_size = 0x1000;
+    }
+  
   return SVN_NO_ERROR;
 }
 
@@ -616,6 +688,58 @@ write_config(svn_fs_t *fs,
 "### unless you often modify revprops after packing."                        NL
 "### Compressing packed revprops is disabled by default."                    NL
 "# " CONFIG_OPTION_COMPRESS_PACKED_REVPROPS " = false"                       NL
+""                                                                           NL
+"[" CONFIG_SECTION_IO "]"                                                    NL
+"### Parameters in this section control the data access granularity in"      NL
+"### format 7 repositories and later.  The defaults should translate into"   NL
+"### decent performance over a wide range of setups."                        NL
+"###"                                                                        NL
+"### When a specific piece of information needs to be read from disk,  a"    NL
+"### data block is being read at once and its contents are being cached."    NL
+"### If the repository is being stored on a RAID,  the block size should"    NL
+"### be either 50% or 100% of RAID block size / granularity.  Also,  your"   NL
+"### file system (clusters) should be properly aligned and sized.  In that"  NL
+"### setup, each access will hit only one disk (minimizes I/O load) but"     NL
+"### uses all the data provided by the disk in a single access."             NL
+"### For SSD-based storage systems,  slightly lower values around 16 kB"     NL
+"### may improve latency while still maximizing throughput."                 NL
+"### Can be changed at any time but must be a power of 2."                   NL
+"### block-size is 64 kBytes by default."                                    NL
+"# " CONFIG_OPTION_BLOCK_SIZE " = 64"                                        NL
+"###"                                                                        NL
+"### The log-to-phys index maps data item numbers to offsets within the"     NL
+"### rev or pack file.  A revision typically contains 2 .. 5 such items"     NL
+"### per changed path.  For each revision, at least one page is being"       NL
+"### allocated in the l2p index with unused parts resulting in no wasted"    NL
+"### space."                                                                 NL
+"### Changing this parameter only affects larger revisions with thousands"   NL
+"### of changed paths.  A smaller value means that more pages need to be"    NL
+"### allocated for such revisions,  increasing the size of the page table"   NL
+"### meaning it takes longer to read that table (once).  Access to each"     NL
+"### page is then faster because less data has to read.  So, if you have"    NL
+"### several extremely large revisions (approaching 1 mio changes),  think"  NL
+"### about increasing this setting.  Reducing the value will rarely result"  NL
+"### in a net speedup."                                                      NL
+"### This is an expert setting.  Any non-zero value is possible."            NL
+"### l2p-page-size is 8192 entries by default."                              NL
+"# " CONFIG_OPTION_L2P_PAGE_SIZE " = 8192"                                   NL
+"###"                                                                        NL
+"### The phys-to-log index maps positions within the rev or pack file to"    NL
+"### to data items,  i.e. describes what piece of information is being"      NL
+"### stored at that particular offset.  The index describes the rev file"    NL
+"### in chunks (pages) and keeps a global list of all those pages.  Large"   NL
+"### pages mean a shorter page table but a larger per-page description of"   NL
+"### data items in it.  The latency sweetspot depends on the change size"    NL
+"### distribution but is relatively wide."                                   NL
+"### If the repository contains very large files,  i.e. individual changes"  NL
+"### of tens of MB each,  increasing the page size will shorten the index"   NL
+"### file at the expense of a slightly increased latency in sections with"   NL
+"### smaller changes."                                                       NL
+"### For practical reasons,  this should match block-size.  Differing"       NL
+"### values are perfectly legal but may result in some processing overhead." NL
+"### Must be a power of 2."                                                  NL
+"### p2l-page-size is 64 kBytes by default."                                 NL
+"# " CONFIG_OPTION_P2L_PAGE_SIZE " = 64"                                     NL
 ;
 #undef NL
   return svn_io_file_create(svn_dirent_join(fs->path, PATH_CONFIG, pool),
@@ -628,18 +752,20 @@ svn_fs_fs__open(svn_fs_t *fs, const char
   fs_fs_data_t *ffd = fs->fsap_data;
   apr_file_t *uuid_file;
   int format, max_files_per_dir;
+  svn_revnum_t min_log_addressing_rev;
   char buf[APR_UUID_FORMATTED_LENGTH + 2];
   apr_size_t limit;
 
   fs->path = apr_pstrdup(fs->pool, path);
 
   /* Read the FS format number. */
-  SVN_ERR(read_format(&format, &max_files_per_dir,
+  SVN_ERR(read_format(&format, &max_files_per_dir, &min_log_addressing_rev,
                       path_format(fs, pool), pool));
 
   /* Now we've got a format number no matter what. */
   ffd->format = format;
   ffd->max_files_per_dir = max_files_per_dir;
+  ffd->min_log_addressing_rev = min_log_addressing_rev;
 
   /* Read in and cache the repository uuid. */
   SVN_ERR(svn_io_file_open(&uuid_file, path_uuid(fs, pool),
@@ -694,12 +820,14 @@ upgrade_body(void *baton, apr_pool_t *po
   svn_fs_t *fs = upgrade_baton->fs;
   fs_fs_data_t *ffd = fs->fsap_data;
   int format, max_files_per_dir;
+  svn_revnum_t min_log_addressing_rev;
   const char *format_path = path_format(fs, pool);
   svn_node_kind_t kind;
   svn_boolean_t needs_revprop_shard_cleanup = FALSE;
 
   /* Read the FS format number and max-files-per-dir setting. */
-  SVN_ERR(read_format(&format, &max_files_per_dir, format_path, pool));
+  SVN_ERR(read_format(&format, &max_files_per_dir, &min_log_addressing_rev,
+                      format_path, pool));
 
   /* If the config file does not exist, create one. */
   SVN_ERR(svn_io_check_path(svn_dirent_join(fs->path, PATH_CONFIG, pool),
@@ -723,7 +851,7 @@ upgrade_body(void *baton, apr_pool_t *po
   if (format == SVN_FS_FS__FORMAT_NUMBER)
     return SVN_NO_ERROR;
 
-  /* If our filesystem predates the existance of the 'txn-current
+  /* If our filesystem predates the existence of the 'txn-current
      file', make that file and its corresponding lock file. */
   if (format < SVN_FS_FS__MIN_TXN_CURRENT_FORMAT)
     {
@@ -735,7 +863,7 @@ upgrade_body(void *baton, apr_pool_t *po
                            pool));
     }
 
-  /* If our filesystem predates the existance of the 'txn-protorevs'
+  /* If our filesystem predates the existence of the 'txn-protorevs'
      dir, make that directory.  */
   if (format < SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
     {
@@ -767,9 +895,19 @@ upgrade_body(void *baton, apr_pool_t *po
                                                pool));
     }
 
+  if (   format < SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT
+      && max_files_per_dir > 0)
+    {
+      min_log_addressing_rev
+        = (ffd->youngest_rev_cache / max_files_per_dir + 1)
+        * max_files_per_dir;
+    }
+
   /* Bump the format file. */
   ffd->format = SVN_FS_FS__FORMAT_NUMBER;
   ffd->max_files_per_dir = max_files_per_dir;
+  ffd->min_log_addressing_rev = min_log_addressing_rev;
+
   SVN_ERR(svn_fs_fs__write_format(fs, TRUE, pool));
   if (upgrade_baton->notify_func)
     SVN_ERR(upgrade_baton->notify_func(upgrade_baton->notify_baton,
@@ -892,7 +1030,7 @@ svn_fs_fs__noderev_same_rep_key(represen
   if (a == NULL || b == NULL)
     return FALSE;
 
-  if (a->offset != b->offset)
+  if (a->item_index != b->item_index)
     return FALSE;
 
   if (a->revision != b->revision)
@@ -957,17 +1095,58 @@ write_revision_zero(svn_fs_t *fs)
   svn_string_t date;
 
   /* Write out a rev file for revision 0. */
-  SVN_ERR(svn_io_file_create(path_revision_zero,
-                             "PLAIN\nEND\nENDREP\n"
-                             "id: 0.0.r0/17\n"
-                             "type: dir\n"
-                             "count: 0\n"
-                             "text: 0 0 4 4 "
-                             "2d2977d1c96f487abe4a1e202dd03b4e\n"
-                             "cpath: /\n"
-                             "\n\n17 107\n", fs->pool));
+  if (svn_fs_fs__use_log_addressing(fs, 0))
+    SVN_ERR(svn_io_file_create(path_revision_zero,
+                               "PLAIN\nEND\nENDREP\n"
+                               "id: 0.0.r0/2\n"
+                               "type: dir\n"
+                               "count: 0\n"
+                               "text: 0 3 4 4 "
+                               "2d2977d1c96f487abe4a1e202dd03b4e\n"
+                               "cpath: /\n"
+                               "\n\n", fs->pool));
+  else
+    SVN_ERR(svn_io_file_create(path_revision_zero,
+                               "PLAIN\nEND\nENDREP\n"
+                               "id: 0.0.r0/17\n"
+                               "type: dir\n"
+                               "count: 0\n"
+                               "text: 0 0 4 4 "
+                               "2d2977d1c96f487abe4a1e202dd03b4e\n"
+                               "cpath: /\n"
+                               "\n\n17 107\n", fs->pool));
+
   SVN_ERR(svn_io_set_file_read_only(path_revision_zero, FALSE, fs->pool));
 
+  if (svn_fs_fs__use_log_addressing(fs, 0))
+    {
+      const char *path = svn_fs_fs__path_l2p_index(fs, 0, FALSE, fs->pool);
+      SVN_ERR(svn_io_file_create_binary
+                 (path,
+                  "\0\x80\x40"       /* rev 0, 8k entries per page */
+                  "\1\1\1"           /* 1 rev, 1 page, 1 page in 1st rev */
+                  "\6\4"             /* page size: bytes, count */
+                  "\0\xd6\1\xb1\1\x21",  /* phys offsets + 1 */
+                  14,
+                  fs->pool));
+      SVN_ERR(svn_io_set_file_read_only(path, FALSE, fs->pool));
+
+      path = svn_fs_fs__path_p2l_index(fs, 0, FALSE, fs->pool);
+      SVN_ERR(svn_io_file_create_binary
+                 (path,
+                  "\0\x6b"              /* start rev, rev file size */
+                  "\x80\x80\4\1\x1D"    /* 64k pages, 1 page using 29 bytes */
+                  "\0"                  /* offset entry 0 page 1 */
+                                        /* len, item & type, rev, checksum */
+                  "\x11\x34\0\xe0\xc6\xac\xa9\x07"
+                  "\x59\x09\0\xc0\xfa\xf8\xc5\x04"
+                  "\1\x0d\0\xf2\x95\xbe\xea\x01"
+                  "\x95\xff\3\x1b\0\0", /* last entry fills up 64k page */
+                  38,
+                  fs->pool));
+      SVN_ERR(svn_io_set_file_read_only(path, FALSE, fs->pool));
+    }
+
   /* Set a date on revision 0. */
   date.data = svn_time_to_cstring(apr_time_now(), fs->pool);
   date.len = strlen(date.data);
@@ -988,14 +1167,36 @@ svn_fs_fs__create(svn_fs_t *fs,
   /* See if compatibility with older versions was explicitly requested. */
   if (fs->config)
     {
-      if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE))
-        format = 1;
-      else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE))
-        format = 2;
-      else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE))
-        format = 3;
-      else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE))
-        format = 4;
+      svn_version_t *compatible_version;
+      SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
+                                         pool));
+
+      /* select format number */
+      switch(compatible_version->minor)
+        {
+          case 0: return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
+                 _("FSFS is not compatible with Subversion prior to 1.1"));
+
+          case 1:
+          case 2:
+          case 3: format = 1;
+                  break;
+
+          case 4: format = 2;
+                  break;
+
+          case 5: format = 3;
+                  break;
+
+          case 6:
+          case 7: format = 4;
+                  break;
+
+          case 8: format = 6;
+                  break;
+
+          default:format = SVN_FS_FS__FORMAT_NUMBER;
+        }
     }
   ffd->format = format;
 
@@ -1003,6 +1204,12 @@ svn_fs_fs__create(svn_fs_t *fs,
   if (format >= SVN_FS_FS__MIN_LAYOUT_FORMAT_OPTION_FORMAT)
     ffd->max_files_per_dir = SVN_FS_FS_DEFAULT_MAX_FILES_PER_DIR;
 
+  /* Select the addressing mode depending on the format. */
+  if (format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
+    ffd->min_log_addressing_rev = 0;
+  else
+    ffd->min_log_addressing_rev = SVN_INVALID_REVNUM;
+
   /* Create the revision data directories. */
   if (ffd->max_files_per_dir)
     SVN_ERR(svn_io_make_dir_recursively(svn_fs_fs__path_rev_shard(fs, 0,
@@ -1045,7 +1252,12 @@ svn_fs_fs__create(svn_fs_t *fs,
 
   SVN_ERR(write_revision_zero(fs));
 
-  SVN_ERR(write_config(fs, pool));
+  /* Create the fsfs.conf file if supported.  Older server versions would
+     simply ignore the file but that might result in a different behavior
+     than with the later releases.  Also, hotcopy would ignore, i.e. not
+     copy, a fsfs.conf with old formats. */
+  if (ffd->format >= SVN_FS_FS__MIN_CONFIG_FILE)
+    SVN_ERR(write_config(fs, pool));
 
   SVN_ERR(read_config(ffd, fs->path, pool));
 
@@ -1379,8 +1591,11 @@ svn_fs_fs__info_format(int *fs_format,
     case 6:
       (*supports_version)->minor = 8;
       break;
+    case 7:
+      (*supports_version)->minor = 9;
+      break;
 #ifdef SVN_DEBUG
-# if SVN_FS_FS__FORMAT_NUMBER != 6
+# if SVN_FS_FS__FORMAT_NUMBER != 7
 #  error "Need to add a 'case' statement here"
 # endif
 #endif

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c Sun Dec  8 17:56:46 2013
@@ -228,12 +228,14 @@ hotcopy_io_copy_dir_recursively(const ch
 
 /* Copy an un-packed revision or revprop file for revision REV from SRC_SUBDIR
  * to DST_SUBDIR. Assume a sharding layout based on MAX_FILES_PER_DIR.
+ * If INCLUDE_INDEXES is set, copy rev index files as well.
  * Use SCRATCH_POOL for temporary allocations. */
 static svn_error_t *
 hotcopy_copy_shard_file(const char *src_subdir,
                         const char *dst_subdir,
                         svn_revnum_t rev,
                         int max_files_per_dir,
+                        svn_boolean_t include_indexes,
                         apr_pool_t *scratch_pool)
 {
   const char *src_subdir_shard = src_subdir,
@@ -257,6 +259,19 @@ hotcopy_copy_shard_file(const char *src_
   SVN_ERR(hotcopy_io_dir_file_copy(src_subdir_shard, dst_subdir_shard,
                                    apr_psprintf(scratch_pool, "%ld", rev),
                                    scratch_pool));
+
+  if (include_indexes)
+    {
+      SVN_ERR(hotcopy_io_dir_file_copy(src_subdir_shard, dst_subdir_shard,
+                                       apr_psprintf(scratch_pool, "%ld.l2p",
+                                                    rev),
+                                       scratch_pool));
+      SVN_ERR(hotcopy_io_dir_file_copy(src_subdir_shard, dst_subdir_shard,
+                                       apr_psprintf(scratch_pool, "%ld.p2l",
+                                                    rev),
+                                       scratch_pool));
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -312,7 +327,7 @@ hotcopy_copy_packed_shard(svn_revnum_t *
 
           SVN_ERR(hotcopy_copy_shard_file(src_subdir, dst_subdir,
                                           revprop_rev, max_files_per_dir,
-                                          iterpool));
+                                          FALSE, iterpool));
         }
       svn_pool_destroy(iterpool);
     }
@@ -321,7 +336,7 @@ hotcopy_copy_packed_shard(svn_revnum_t *
       /* revprop for revision 0 will never be packed */
       if (rev == 0)
         SVN_ERR(hotcopy_copy_shard_file(src_subdir, dst_subdir,
-                                        0, max_files_per_dir,
+                                        0, max_files_per_dir, FALSE,
                                         scratch_pool));
 
       /* packed revprops folder */
@@ -379,17 +394,33 @@ hotcopy_update_current(svn_revnum_t *dst
   return SVN_NO_ERROR;
 }
 
+/* Remove FILE in SHARD folder.  Use POOL for temporary allocations. */
+static svn_error_t *
+hotcopy_remove_file(const char *shard,
+                    const char *file,
+                    apr_pool_t *pool)
+{
+  const char *rev_path = svn_dirent_join(shard, file, pool);
+
+  /* Make the rev file writable and remove it. */
+  SVN_ERR(svn_io_set_file_read_write(rev_path, TRUE, pool));
+  SVN_ERR(svn_io_remove_file2(rev_path, TRUE, pool));
+
+  return SVN_NO_ERROR;
+}
+
 
 /* Remove revision or revprop files between START_REV (inclusive) and
- * END_REV (non-inclusive) from folder DST_SUBDIR in DST_FS.  Assume
- * sharding as per MAX_FILES_PER_DIR.
- * Use SCRATCH_POOL for temporary allocations. */
+ * END_REV (non-inclusive) from folder DST_SUBDIR in DST_FS.  Also,
+ * remove index files if REMOVE_INDEXES is set.  Assume sharding as per
+ * MAX_FILES_PER_DIR.  Use SCRATCH_POOL for temporary allocations. */
 static svn_error_t *
 hotcopy_remove_files(svn_fs_t *dst_fs,
                      const char *dst_subdir,
                      svn_revnum_t start_rev,
                      svn_revnum_t end_rev,
                      int max_files_per_dir,
+                     svn_boolean_t remove_indexes,
                      apr_pool_t *scratch_pool)
 {
   const char *shard;
@@ -404,7 +435,6 @@ hotcopy_remove_files(svn_fs_t *dst_fs,
   iterpool = svn_pool_create(scratch_pool);
   for (rev = start_rev; rev < end_rev; rev++)
     {
-      const char *path;
       svn_pool_clear(iterpool);
 
       /* If necessary, update paths for shard. */
@@ -415,13 +445,18 @@ hotcopy_remove_files(svn_fs_t *dst_fs,
         }
 
       /* remove files for REV */
-      path = svn_dirent_join(dst_subdir_shard,
-                             apr_psprintf(iterpool, "%ld", rev),
-                             iterpool);
-
-      /* Make the rev file writable and remove it. */
-      SVN_ERR(svn_io_set_file_read_write(path, TRUE, iterpool));
-      SVN_ERR(svn_io_remove_file2(path, TRUE, iterpool));
+      SVN_ERR(hotcopy_remove_file(dst_subdir_shard,
+                                  apr_psprintf(iterpool, "%ld", rev),
+                                  iterpool));
+      if (remove_indexes && svn_fs_fs__use_log_addressing(dst_fs, rev))
+        {
+          SVN_ERR(hotcopy_remove_file(dst_subdir_shard,
+                                      apr_psprintf(iterpool, "%ld.p2l", rev),
+                                      iterpool));
+          SVN_ERR(hotcopy_remove_file(dst_subdir_shard,
+                                      apr_psprintf(iterpool, "%ld.l2p", rev),
+                                      iterpool));
+        }
     }
 
   svn_pool_destroy(iterpool);
@@ -445,7 +480,7 @@ hotcopy_remove_rev_files(svn_fs_t *dst_f
                                                PATH_REVS_DIR,
                                                scratch_pool),
                                start_rev, end_rev,
-                               max_files_per_dir, scratch_pool));
+                               max_files_per_dir, TRUE, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -469,7 +504,7 @@ hotcopy_remove_revprop_files(svn_fs_t *d
                                                PATH_REVPROPS_DIR,
                                                scratch_pool),
                                start_rev ? start_rev : 1, end_rev,
-                               max_files_per_dir, scratch_pool));
+                               max_files_per_dir, FALSE, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -772,6 +807,7 @@ hotcopy_body(void *baton, apr_pool_t *po
       /* Copy the rev file. */
       err = hotcopy_copy_shard_file(src_subdir, dst_subdir,
                                     rev, max_files_per_dir,
+                                    svn_fs_fs__use_log_addressing(src_fs, rev),
                                     iterpool);
       if (err)
         {
@@ -822,7 +858,7 @@ hotcopy_body(void *baton, apr_pool_t *po
       /* Copy the revprop file. */
       SVN_ERR(hotcopy_copy_shard_file(revprop_src_subdir,
                                       revprop_dst_subdir,
-                                      rev, max_files_per_dir,
+                                      rev, max_files_per_dir, FALSE,
                                       iterpool));
 
       /* After completing a full shard, update 'current'. */
@@ -935,6 +971,7 @@ hotcopy_create_empty_dest(svn_fs_t *src_
   dst_fs->path = apr_pstrdup(pool, dst_path);
 
   dst_ffd->max_files_per_dir = src_ffd->max_files_per_dir;
+  dst_ffd->min_log_addressing_rev = src_ffd->min_log_addressing_rev;
   dst_ffd->config = src_ffd->config;
   dst_ffd->format = src_ffd->format;
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c Sun Dec  8 17:56:46 2013
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 
 #include "id.h"
+#include "index.h"
 
 #include "../libsvn_fs/fs-loader.h"
 #include "private/svn_temp_serializer.h"
@@ -41,7 +42,7 @@ typedef struct fs_fs__id_t
       svn_fs_fs__id_part_t node_id;
       svn_fs_fs__id_part_t copy_id;
       svn_fs_fs__id_part_t txn_id;
-      svn_fs_fs__id_part_t rev_offset;
+      svn_fs_fs__id_part_t rev_item;
     } private_id;
 } fs_fs__id_t;
 
@@ -214,11 +215,11 @@ svn_fs_fs__id_txn_id(const svn_fs_id_t *
 
 
 const svn_fs_fs__id_part_t *
-svn_fs_fs__id_rev_offset(const svn_fs_id_t *fs_id)
+svn_fs_fs__id_rev_item(const svn_fs_id_t *fs_id)
 {
   fs_fs__id_t *id = (fs_fs__id_t *)fs_id;
 
-  return &id->private_id.rev_offset;
+  return &id->private_id.rev_item;
 }
 
 svn_revnum_t
@@ -226,15 +227,15 @@ svn_fs_fs__id_rev(const svn_fs_id_t *fs_
 {
   fs_fs__id_t *id = (fs_fs__id_t *)fs_id;
 
-  return id->private_id.rev_offset.revision;
+  return id->private_id.rev_item.revision;
 }
 
 apr_uint64_t
-svn_fs_fs__id_offset(const svn_fs_id_t *fs_id)
+svn_fs_fs__id_item(const svn_fs_id_t *fs_id)
 {
   fs_fs__id_t *id = (fs_fs__id_t *)fs_id;
 
-  return id->private_id.rev_offset.number;
+  return id->private_id.rev_item.number;
 }
 
 svn_boolean_t
@@ -265,9 +266,9 @@ svn_fs_fs__id_unparse(const svn_fs_id_t 
   else
     {
       *(p++) = 'r';
-      p += svn__i64toa(p, id->private_id.rev_offset.revision);
+      p += svn__i64toa(p, id->private_id.rev_item.revision);
       *(p++) = '/';
-      p += svn__i64toa(p, id->private_id.rev_offset.number);
+      p += svn__i64toa(p, id->private_id.rev_item.number);
     }
 
   return svn_string_ncreate(string, p - string, pool);
@@ -355,7 +356,22 @@ svn_fs_fs__id_txn_create_root(const svn_
   /* node ID and copy ID are "0" */
   
   id->private_id.txn_id = *txn_id;
-  id->private_id.rev_offset.revision = SVN_INVALID_REVNUM;
+  id->private_id.rev_item.revision = SVN_INVALID_REVNUM;
+
+  id->generic_id.vtable = &id_vtable;
+  id->generic_id.fsap_data = &id;
+
+  return (svn_fs_id_t *)id;
+}
+
+svn_fs_id_t *svn_fs_fs__id_create_root(const svn_revnum_t revision,
+                                       apr_pool_t *pool)
+{
+  fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id));
+
+  id->private_id.txn_id.revision = SVN_INVALID_REVNUM;
+  id->private_id.rev_item.revision = revision;
+  id->private_id.rev_item.number = SVN_FS_FS__ITEM_INDEX_ROOT_NODE;
 
   id->generic_id.vtable = &id_vtable;
   id->generic_id.fsap_data = &id;
@@ -374,7 +390,7 @@ svn_fs_fs__id_txn_create(const svn_fs_fs
   id->private_id.node_id = *node_id;
   id->private_id.copy_id = *copy_id;
   id->private_id.txn_id = *txn_id;
-  id->private_id.rev_offset.revision = SVN_INVALID_REVNUM;
+  id->private_id.rev_item.revision = SVN_INVALID_REVNUM;
 
   id->generic_id.vtable = &id_vtable;
   id->generic_id.fsap_data = &id;
@@ -386,7 +402,7 @@ svn_fs_fs__id_txn_create(const svn_fs_fs
 svn_fs_id_t *
 svn_fs_fs__id_rev_create(const svn_fs_fs__id_part_t *node_id,
                          const svn_fs_fs__id_part_t *copy_id,
-                         const svn_fs_fs__id_part_t *rev_offset,
+                         const svn_fs_fs__id_part_t *rev_item,
                          apr_pool_t *pool)
 {
   fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id));
@@ -394,7 +410,7 @@ svn_fs_fs__id_rev_create(const svn_fs_fs
   id->private_id.node_id = *node_id;
   id->private_id.copy_id = *copy_id;
   id->private_id.txn_id.revision = SVN_INVALID_REVNUM;
-  id->private_id.rev_offset = *rev_offset;
+  id->private_id.rev_item = *rev_item;
 
   id->generic_id.vtable = &id_vtable;
   id->generic_id.fsap_data = &id;
@@ -471,7 +487,7 @@ svn_fs_fs__id_parse(const char *data,
       str = svn_cstring_tokenize("/", &data_copy);
       if (str == NULL)
         return NULL;
-      id->private_id.rev_offset.revision = SVN_STR_TO_REV(str);
+      id->private_id.rev_item.revision = SVN_STR_TO_REV(str);
 
       err = svn_cstring_atoi64(&val, data_copy);
       if (err)
@@ -479,13 +495,13 @@ svn_fs_fs__id_parse(const char *data,
           svn_error_clear(err);
           return NULL;
         }
-      id->private_id.rev_offset.number = (apr_uint64_t)val;
+      id->private_id.rev_item.number = (apr_uint64_t)val;
     }
   else if (str[0] == 't')
     {
       /* This is a transaction type ID */
-      id->private_id.rev_offset.revision = SVN_INVALID_REVNUM;
-      id->private_id.rev_offset.number = 0;
+      id->private_id.rev_item.revision = SVN_INVALID_REVNUM;
+      id->private_id.rev_item.number = 0;
 
       if (! txn_id_parse(&id->private_id.txn_id, str + 1))
         return NULL;

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h Sun Dec  8 17:56:46 2013
@@ -45,7 +45,7 @@ typedef struct svn_fs_fs__id_part_t
   svn_revnum_t revision;
 
   /* sub-id value relative to REVISION.  Its interpretation depends on
-     the part itself.  In rev_offset, it is the offset value, in others
+     the part itself.  In rev_item, it is the index_index value, in others
      it represents a unique counter value. */
   apr_uint64_t number;
 } svn_fs_fs__id_part_t;
@@ -88,16 +88,16 @@ const svn_fs_fs__id_part_t *svn_fs_fs__i
 /* Get the "txn id" portion of ID, or NULL if it is a permanent ID. */
 const svn_fs_fs__id_part_t *svn_fs_fs__id_txn_id(const svn_fs_id_t *id);
 
-/* Get the "rev,offset" portion of ID. */
-const svn_fs_fs__id_part_t *svn_fs_fs__id_rev_offset(const svn_fs_id_t *id);
+/* Get the "rev,item" portion of ID. */
+const svn_fs_fs__id_part_t *svn_fs_fs__id_rev_item(const svn_fs_id_t *id);
 
 /* Get the "rev" portion of ID, or SVN_INVALID_REVNUM if it is a
    transaction ID. */
 svn_revnum_t svn_fs_fs__id_rev(const svn_fs_id_t *id);
 
-/* Access the "offset" portion of the ID, or 0 if it is a transaction
+/* Access the "item" portion of the ID, or 0 if it is a transaction
    ID. */
-apr_uint64_t svn_fs_fs__id_offset(const svn_fs_id_t *id);
+apr_uint64_t svn_fs_fs__id_item(const svn_fs_id_t *id);
 
 /* Return TRUE, if this is a transaction ID. */
 svn_boolean_t svn_fs_fs__id_is_txn(const svn_fs_id_t *id);
@@ -126,6 +126,11 @@ int svn_fs_fs__id_part_compare(const svn
 svn_fs_id_t *svn_fs_fs__id_txn_create_root(const svn_fs_fs__id_part_t *txn_id,
                                            apr_pool_t *pool);
 
+/* Create the root ID for REVISION (logical addressing node only).
+   Allocate it in POOL. */
+svn_fs_id_t *svn_fs_fs__id_create_root(const svn_revnum_t revision,
+                                       apr_pool_t *pool);
+
 /* Create an ID within a transaction based on NODE_ID, COPY_ID, and
    TXN_ID, allocated in POOL. */
 svn_fs_id_t *svn_fs_fs__id_txn_create(const svn_fs_fs__id_part_t *node_id,
@@ -133,11 +138,11 @@ svn_fs_id_t *svn_fs_fs__id_txn_create(co
                                       const svn_fs_fs__id_part_t *txn_id,
                                       apr_pool_t *pool);
 
-/* Create a permanent ID based on NODE_ID, COPY_ID and REV_OFFSET,
+/* Create a permanent ID based on NODE_ID, COPY_ID and REV_ITEM,
    allocated in POOL. */
 svn_fs_id_t *svn_fs_fs__id_rev_create(const svn_fs_fs__id_part_t *node_id,
                                       const svn_fs_fs__id_part_t *copy_id,
-                                      const svn_fs_fs__id_part_t *rev_offset,
+                                      const svn_fs_fs__id_part_t *rev_item,
                                       apr_pool_t *pool);
 
 /* Return a copy of ID, allocated from POOL. */

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c Sun Dec  8 17:56:46 2013
@@ -252,24 +252,23 @@ read_digest_file(apr_hash_t **children_p
   apr_hash_t *hash;
   svn_stream_t *stream;
   const char *val;
+  svn_node_kind_t kind;
 
   if (lock_p)
     *lock_p = NULL;
   if (children_p)
     *children_p = apr_hash_make(pool);
 
-  err = svn_stream_open_readonly(&stream, digest_path, pool, pool);
-  if (err && APR_STATUS_IS_ENOENT(err->apr_err))
-    {
-      svn_error_clear(err);
-      return SVN_NO_ERROR;
-    }
-  SVN_ERR(err);
+  SVN_ERR(svn_io_check_path(digest_path, &kind, pool));
+  if (kind == svn_node_none)
+    return SVN_NO_ERROR;
 
   /* If our caller doesn't care about anything but the presence of the
      file... whatever. */
-  if (! (lock_p || children_p))
-    return svn_stream_close(stream);
+  if (kind == svn_node_file && !lock_p && !children_p)
+    return SVN_NO_ERROR;
+
+  SVN_ERR(svn_stream_open_readonly(&stream, digest_path, pool, pool));
 
   hash = apr_hash_make(pool);
   if ((err = svn_hash_read2(hash, stream, SVN_HASH_TERMINATOR, pool)))

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.c?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.c Sun Dec  8 17:56:46 2013
@@ -25,6 +25,7 @@
 #include "svn_pools.h"
 #include "svn_sorts.h"
 #include "private/svn_string_private.h"
+#include "private/svn_subr_private.h"
 
 #include "../libsvn_fs/fs-loader.h"
 
@@ -482,13 +483,14 @@ read_header_block(apr_hash_t **headers,
                   svn_stream_t *stream,
                   apr_pool_t *pool)
 {
-  *headers = apr_hash_make(pool);
+  *headers = svn_hash__make(pool);
 
   while (1)
     {
       svn_stringbuf_t *header_str;
       const char *name, *value;
-      apr_size_t i = 0;
+      apr_ssize_t i = 0;
+      apr_ssize_t name_len;
       svn_boolean_t eof;
 
       SVN_ERR(svn_stream_readline(stream, &header_str, "\n", &eof, pool));
@@ -509,6 +511,7 @@ read_header_block(apr_hash_t **headers,
       /* Create a 'name' string and point to it. */
       header_str->data[i] = '\0';
       name = header_str->data;
+      name_len = i;
 
       /* Skip over the NULL byte and the space following it. */
       i += 2;
@@ -528,7 +531,7 @@ read_header_block(apr_hash_t **headers,
 
       /* header_str is safely in our pool, so we can use bits of it as
          key and value. */
-      svn_hash_sets(*headers, name, value);
+      apr_hash_set(*headers, name, name_len, value);
     }
 
   return SVN_NO_ERROR;
@@ -571,7 +574,7 @@ svn_fs_fs__parse_representation(represen
     }
 
   SVN_ERR(svn_cstring_atoi64(&val, str));
-  rep->offset = (apr_off_t)val;
+  rep->item_index = (apr_uint64_t)val;
 
   str = svn_cstring_tokenize(" ", &string);
   if (str == NULL)
@@ -851,17 +854,17 @@ svn_fs_fs__unparse_representation(repres
 
   if (format < SVN_FS_FS__MIN_REP_SHARING_FORMAT || !rep->has_sha1)
     return svn_stringbuf_createf
-            (pool, "%ld %" APR_OFF_T_FMT " %" SVN_FILESIZE_T_FMT
+            (pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT
              " %" SVN_FILESIZE_T_FMT " %s",
-             rep->revision, rep->offset, rep->size,
+             rep->revision, rep->item_index, rep->size,
              rep->expanded_size,
              format_digest(rep->md5_digest, svn_checksum_md5, FALSE, pool));
 
   svn__ui64tobase36(buffer, rep->uniquifier.number);
   return svn_stringbuf_createf
-          (pool, "%ld %" APR_OFF_T_FMT " %" SVN_FILESIZE_T_FMT
+          (pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT
            " %" SVN_FILESIZE_T_FMT " %s %s %s/_%s",
-           rep->revision, rep->offset, rep->size,
+           rep->revision, rep->item_index, rep->size,
            rep->expanded_size,
            format_digest(rep->md5_digest, svn_checksum_md5, FALSE, pool),
            format_digest(rep->sha1_digest, svn_checksum_sha1,
@@ -985,7 +988,7 @@ svn_fs_fs__read_rep_header(svn_fs_fs__re
   if (! str)
     goto error;
   SVN_ERR(svn_cstring_atoi64(&val, str));
-  (*header)->base_offset = (apr_off_t)val;
+  (*header)->base_item_index = (apr_off_t)val;
 
   str = svn_cstring_tokenize(" ", &last_str);
   if (! str)
@@ -1020,7 +1023,7 @@ svn_fs_fs__write_rep_header(svn_fs_fs__r
       default:
         text = apr_psprintf(pool, REP_DELTA " %ld %" APR_OFF_T_FMT " %"
                             SVN_FILESIZE_T_FMT "\n",
-                            header->base_revision, header->base_offset,
+                            header->base_revision, header->base_item_index,
                             header->base_length);
     }
 

Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.h
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.h?rev=1549081&r1=1549080&r2=1549081&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.h (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.h Sun Dec  8 17:56:46 2013
@@ -142,9 +142,9 @@ typedef struct svn_fs_fs__rep_header_t
   svn_revnum_t base_revision;
 
   /* if this rep is a delta against some other rep, that base rep can
-   * be found at this offset within the base rep's revision.  Should
+   * be found at this item index within the base rep's revision.  Should
    * be 0 if there is no base rep. */
-  apr_off_t base_offset;
+  apr_off_t base_item_index;
 
   /* if this rep is a delta against some other rep, this is the (deltified)
    * size of that base rep.  Should be 0 if there is no base rep. */