You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/12/03 02:43:06 UTC

svn commit: r1547260 [2/5] - in /subversion/branches/fsfs-ucsnorm: ./ subversion/bindings/javahl/native/ subversion/include/ subversion/libsvn_fs_fs/ subversion/tests/cmdline/ subversion/tests/cmdline/svntest/ subversion/tests/libsvn_fs_fs/ tools/serve...

Modified: subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.c?rev=1547260&r1=1547259&r2=1547260&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/fs_fs.c Tue Dec  3 01:43:05 2013
@@ -270,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;
@@ -324,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)
@@ -350,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 *
@@ -386,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. */
@@ -484,6 +531,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;
+    }
+
   /* Initialize normalization settings in ffd.
 
      Note: enable-normalized-lookups does not affect the filesystem
@@ -629,6 +702,58 @@ write_config(svn_fs_t *fs,
 "### 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
+""                                                                           NL
 "[" CONFIG_SECTION_NORMALIZATION "]"                                         NL
 "### Subversion decrees that paths in the repository must be in the Unicode" NL
 "### character set, and further requires that they are encoded in UTF-8."    NL
@@ -666,18 +791,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),
@@ -732,12 +859,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),
@@ -805,9 +934,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,
@@ -930,7 +1069,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)
@@ -995,17 +1134,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);
@@ -1063,6 +1243,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,
@@ -1439,8 +1625,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/fsfs-ucsnorm/subversion/libsvn_fs_fs/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/hotcopy.c?rev=1547260&r1=1547259&r2=1547260&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/hotcopy.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/hotcopy.c Tue Dec  3 01:43:05 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/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.c?rev=1547260&r1=1547259&r2=1547260&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.c Tue Dec  3 01:43:05 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/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.h?rev=1547260&r1=1547259&r2=1547260&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/id.h Tue Dec  3 01:43:05 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/fsfs-ucsnorm/subversion/libsvn_fs_fs/low_level.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/low_level.c?rev=1547260&r1=1547259&r2=1547260&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/low_level.c (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/low_level.c Tue Dec  3 01:43:05 2013
@@ -574,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)
@@ -854,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,
@@ -988,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)
@@ -1023,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/fsfs-ucsnorm/subversion/libsvn_fs_fs/low_level.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/low_level.h?rev=1547260&r1=1547259&r2=1547260&view=diff
==============================================================================
--- subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/low_level.h (original)
+++ subversion/branches/fsfs-ucsnorm/subversion/libsvn_fs_fs/low_level.h Tue Dec  3 01:43:05 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. */