Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c?rev=1641647&r1=1641646&r2=1641647&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c Tue Nov 
25 16:26:48 2014
@@ -71,13 +71,13 @@ typedef enum rep_kind_t
 typedef struct rep_stats_t
 {
   /* absolute offset in the file */
-  apr_size_t offset;
+  apr_off_t offset;
 
   /* item length in bytes */
-  apr_size_t size;
+  apr_uint64_t size;
 
   /* item length after de-deltification */
-  apr_size_t expanded_size;
+  apr_uint64_t expanded_size;
 
   /* revision that contains this representation
    * (may be referenced by other revisions, though) */
@@ -104,34 +104,35 @@ typedef struct revision_info_t
   /* pack file offset (manifest value), 0 for non-packed files */
   apr_off_t offset;
 
-  /* offset of the changes list relative to OFFSET */
-  apr_size_t changes;
-
   /* length of the changes list on bytes */
-  apr_size_t changes_len;
+  apr_uint64_t changes_len;
 
   /* offset of the changes list relative to OFFSET */
-  apr_size_t change_count;
+  apr_uint64_t change_count;
 
   /* first offset behind the revision data in the pack file (file length
    * for non-packed revs) */
   apr_off_t end;
 
   /* number of directory noderevs in this revision */
-  apr_size_t dir_noderev_count;
+  apr_uint64_t dir_noderev_count;
 
   /* number of file noderevs in this revision */
-  apr_size_t file_noderev_count;
+  apr_uint64_t file_noderev_count;
 
   /* total size of directory noderevs (i.e. the structs - not the rep) */
-  apr_size_t dir_noderev_size;
+  apr_uint64_t dir_noderev_size;
 
   /* total size of file noderevs (i.e. the structs - not the rep) */
-  apr_size_t file_noderev_size;
+  apr_uint64_t file_noderev_size;
 
   /* all rep_stats_t of this revision (in no particular order),
    * i.e. those that point back to this struct */
   apr_array_header_t *representations;
+
+  /* Temporary rev / pack file access object, used in phys. addressing
+   * mode only.  NULL when done reading this revision. */
+  svn_fs_fs__revision_file_t *rev_file;
 } revision_info_t;
 
 /* Root data structure containing all information about a given repository.
@@ -175,97 +176,45 @@ typedef struct query_t
   void *cancel_baton;
 } query_t;
 
-/* Open the file containing revision REV in QUERY and return it in *FILE.
+/* Return the length of REV_FILE in *FILE_SIZE.
+ * Use SCRATCH_POOL for temporary allocations.
  */
 static svn_error_t *
-open_rev_or_pack_file(apr_file_t **file,
-                      query_t *query,
-                      svn_revnum_t rev,
-                      apr_pool_t *pool)
-{
-  svn_fs_fs__revision_file_t *rev_file;
-  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, query->fs, rev,
-                                           pool, pool));
-
-  *file = rev_file->file;
-  return SVN_NO_ERROR;
-}
-
-/* Return the length of FILE in *FILE_SIZE.  Use POOL for allocations.
-*/
-static svn_error_t *
 get_file_size(apr_off_t *file_size,
-              apr_file_t *file,
-              apr_pool_t *pool)
+              svn_fs_fs__revision_file_t *rev_file,
+              apr_pool_t *scratch_pool)
 {
   apr_finfo_t finfo;
 
-  SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, file, pool));
+  SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, rev_file->file,
+                               scratch_pool));
 
   *file_size = finfo.size;
   return SVN_NO_ERROR;
 }
 
-/* Get the file content of revision REVISION in QUERY and return it in
- * *CONTENT.  Read the LEN bytes starting at file OFFSET.  When provided,
- * use FILE as packed or plain rev file.
- * Use POOL for temporary allocations.
- */
-static svn_error_t *
-get_content(svn_stringbuf_t **content,
-            apr_file_t *file,
-            query_t *query,
-            svn_revnum_t revision,
-            apr_off_t offset,
-            apr_size_t len,
-            apr_pool_t *pool)
-{
-  apr_pool_t * file_pool = svn_pool_create(pool);
-  apr_size_t large_buffer_size = 0x10000;
-
-  if (file == NULL)
-    SVN_ERR(open_rev_or_pack_file(&file, query, revision, file_pool));
-
-  *content = svn_stringbuf_create_ensure(len, pool);
-  (*content)->len = len;
-
-  /* for better efficiency use larger buffers on large reads */
-  if (   (len >= large_buffer_size)
-      && (apr_file_buffer_size_get(file) < large_buffer_size))
-    apr_file_buffer_set(file,
-                        apr_palloc(apr_file_pool_get(file),
-                                   large_buffer_size),
-                        large_buffer_size);
-
-  SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, pool));
-  SVN_ERR(svn_io_file_read_full2(file, (*content)->data, len,
-                                 NULL, NULL, pool));
-  svn_pool_destroy(file_pool);
-
-  return SVN_NO_ERROR;
-}
-
 /* Initialize the LARGEST_CHANGES member in STATS with a capacity of COUNT
- * entries.  Use POOL for allocations.
+ * entries.  Allocate the result in RESULT_POOL.
  */
 static void
 initialize_largest_changes(svn_fs_fs__stats_t *stats,
                            apr_size_t count,
-                           apr_pool_t *pool)
+                           apr_pool_t *result_pool)
 {
   apr_size_t i;
 
-  stats->largest_changes = apr_pcalloc(pool, sizeof(*stats->largest_changes));
+  stats->largest_changes = apr_pcalloc(result_pool,
+                                       sizeof(*stats->largest_changes));
   stats->largest_changes->count = count;
   stats->largest_changes->min_size = 1;
   stats->largest_changes->changes
-    = apr_palloc(pool, count * sizeof(*stats->largest_changes->changes));
+    = apr_palloc(result_pool, count * 
sizeof(*stats->largest_changes->changes));
 
   /* allocate *all* entries before the path stringbufs.  This increases
    * cache locality and enhances performance significantly. */
   for (i = 0; i < count; ++i)
     stats->largest_changes->changes[i]
-      = apr_palloc(pool, sizeof(**stats->largest_changes->changes));
+      = apr_palloc(result_pool, sizeof(**stats->largest_changes->changes));
 
   /* now initialize them and allocate the stringbufs */
   for (i = 0; i < count; ++i)
@@ -273,7 +222,7 @@ initialize_largest_changes(svn_fs_fs__st
       stats->largest_changes->changes[i]->size = 0;
       stats->largest_changes->changes[i]->revision = SVN_INVALID_REVNUM;
       stats->largest_changes->changes[i]->path
-        = svn_stringbuf_create_ensure(1024, pool);
+        = svn_stringbuf_create_ensure(1024, result_pool);
     }
 }
 
@@ -398,75 +347,19 @@ add_change(svn_fs_fs__stats_t *stats,
     }
 }
 
-/* Read header information for the revision stored in FILE_CONTENT (one
- * whole revision).  Return the offsets within FILE_CONTENT for the
- * *ROOT_NODEREV, the list of *CHANGES and its len in *CHANGES_LEN.
- * Use POOL for temporary allocations. */
-static svn_error_t *
-read_revision_header(apr_size_t *changes,
-                     apr_size_t *changes_len,
-                     apr_size_t *root_noderev,
-                     svn_stringbuf_t *file_content,
-                     apr_pool_t *pool)
-{
-  char buf[64];
-  const char *line;
-  char *space;
-  apr_uint64_t val;
-  apr_size_t len;
-
-  /* Read in this last block, from which we will identify the last line. */
-  len = sizeof(buf);
-  if (len > file_content->len)
-    len = file_content->len;
-
-  memcpy(buf, file_content->data + file_content->len - len, len);
-
-  /* The last byte should be a newline. */
-  if (buf[(apr_ssize_t)len - 1] != '\n')
-    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                            _("Revision lacks trailing newline"));
-
-  /* Look for the next previous newline. */
-  buf[len - 1] = 0;
-  line = strrchr(buf, '\n');
-  if (line == NULL)
-    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                            _("Final line in revision file longer "
-                              "than 64 characters"));
-
-  space = strchr(line, ' ');
-  if (space == NULL)
-    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                            _("Final line in revision file missing space"));
-
-  /* terminate the header line */
-  *space = 0;
-
-  /* extract information */
-  SVN_ERR(svn_cstring_strtoui64(&val, line+1, 0, APR_SIZE_MAX, 10));
-  *root_noderev = (apr_size_t)val;
-  SVN_ERR(svn_cstring_strtoui64(&val, space+1, 0, APR_SIZE_MAX, 10));
-  *changes = (apr_size_t)val;
-  *changes_len = file_content->len - *changes - (buf + len - line) + 1;
-
-  return SVN_NO_ERROR;
-}
-
 /* Comparator used for binary search comparing the absolute file offset
  * of a representation to some other offset. DATA is a *rep_stats_t,
- * KEY is a pointer to an apr_size_t.
+ * KEY is a pointer to an apr_off_t.
  */
 static int
 compare_representation_offsets(const void *data, const void *key)
 {
-  apr_ssize_t diff = (*(const rep_stats_t *const *)data)->offset
-                     - *(const apr_size_t *)key;
+  apr_off_t lhs = (*(const rep_stats_t *const *)data)->offset;
+  apr_off_t rhs = *(const apr_off_t *)key;
 
-  /* sizeof(int) may be < sizeof(ssize_t) */
-  if (diff < 0)
+  if (lhs < rhs)
     return -1;
-  return diff > 0 ? 1 : 0;
+  return (lhs > rhs ? 1 : 0);
 }
 
 /* Find the revision_info_t object to the given REVISION in QUERY and
@@ -483,7 +376,7 @@ find_representation(int *idx,
                     query_t *query,
                     revision_info_t **revision_info,
                     svn_revnum_t revision,
-                    apr_size_t offset)
+                    apr_off_t offset)
 {
   revision_info_t *info;
   *idx = -1;
@@ -519,19 +412,17 @@ find_representation(int *idx,
 }
 
 /* Find / auto-construct the representation stats for REP in QUERY and
- * return it in *REPRESENTATION.  To be able to parse the base rep, we
- * pass the FILE_CONTENT as well.
+ * return it in *REPRESENTATION.
  *
- * If necessary, allocate the result in POOL; use SCRATCH_POOL for temp.
- * allocations.
+ * If necessary, allocate the result in RESULT_POOL; use SCRATCH_POOL for
+ * temporary allocations.
  */
 static svn_error_t *
 parse_representation(rep_stats_t **representation,
                      query_t *query,
-                     svn_stringbuf_t *file_content,
                      representation_t *rep,
                      revision_info_t *revision_info,
-                     apr_pool_t *pool,
+                     apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool)
 {
   rep_stats_t *result;
@@ -541,31 +432,32 @@ parse_representation(rep_stats_t **repre
 
   /* look it up */
   result = find_representation(&idx, query, &revision_info, rep->revision,
-                               (apr_size_t)rep->item_index);
+                               (apr_off_t)rep->item_index);
   if (!result)
     {
       /* not parsed, yet (probably a rep in the same revision).
        * Create a new rep object and determine its base rep as well.
        */
-      result = apr_pcalloc(pool, sizeof(*result));
+      result = apr_pcalloc(result_pool, sizeof(*result));
       result->revision = rep->revision;
-      result->expanded_size = (apr_size_t)(rep->expanded_size
-                                             ? rep->expanded_size
-                                             : rep->size);
-      result->offset = (apr_size_t)rep->item_index;
-      result->size = (apr_size_t)rep->size;
-
-      if (!svn_fs_fs__use_log_addressing(query->fs, rep->revision))
+      result->expanded_size = (rep->expanded_size ? rep->expanded_size
+                                                  : rep->size);
+      result->offset = (apr_off_t)rep->item_index;
+      result->size = rep->size;
+
+      /* In phys. addressing mode, follow link to the actual representation.
+       * In log. addressing mode, we will find it already as part of our
+       * linear walk through the whole file. */
+      if (!svn_fs_fs__use_log_addressing(query->fs))
         {
           svn_fs_fs__rep_header_t *header;
-          svn_stream_t *stream;
+          apr_off_t offset = revision_info->offset + result->offset;
 
-          svn_string_t content;
-          content.data = file_content->data + (apr_size_t)rep->item_index;
-          content.len = file_content->len - (apr_size_t)rep->item_index;
-
-          stream = svn_stream_from_string(&content, scratch_pool);
-          SVN_ERR(svn_fs_fs__read_rep_header(&header, stream,
+          SVN_ERR_ASSERT(revision_info->rev_file);
+          SVN_ERR(svn_io_file_seek(revision_info->rev_file->file, APR_SET,
+                                   &offset, scratch_pool));
+          SVN_ERR(svn_fs_fs__read_rep_header(&header,
+                                             revision_info->rev_file->stream,
                                              scratch_pool, scratch_pool));
 
           result->header_size = header->header_size;
@@ -583,33 +475,79 @@ parse_representation(rep_stats_t **repre
 /* forward declaration */
 static svn_error_t *
 read_noderev(query_t *query,
-             svn_stringbuf_t *file_content,
-             apr_size_t offset,
+             svn_stringbuf_t *noderev_str,
              revision_info_t *revision_info,
-             apr_pool_t *pool,
+             apr_pool_t *result_pool,
              apr_pool_t *scratch_pool);
 
-/* Starting at the directory in NODEREV's text in FILE_CONTENT, read all
- * DAG nodes, directories and representations linked in that tree structure.
+/* Read the noderev item at OFFSET in REVISION_INFO from the filesystem
+ * provided by QUERY.  Return it in *NODEREV, allocated in RESULT_POOL.
+ * Use SCRATCH_POOL for temporary allocations.
+ *
+ * The textual representation of the noderev will be used to determine
+ * the on-disk size of the noderev.  Only called in phys. addressing mode.
+ */
+static svn_error_t *
+read_phsy_noderev(svn_stringbuf_t **noderev,
+                  query_t *query,
+                  apr_off_t offset,
+                  revision_info_t *revision_info,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  svn_stringbuf_t *noderev_str = svn_stringbuf_create_empty(result_pool);
+  svn_stringbuf_t *line;
+  svn_boolean_t eof;
+
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  /* Navigate the file stream to the start of noderev. */
+  SVN_ERR_ASSERT(revision_info->rev_file);
+
+  offset += revision_info->offset;
+  SVN_ERR(svn_io_file_seek(revision_info->rev_file->file, APR_SET,
+                           &offset, scratch_pool));
+
+  /* Read it (terminated by an empty line) */
+  do
+    {
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_stream_readline(revision_info->rev_file->stream, &line,
+                                  "\n", &eof, iterpool));
+      svn_stringbuf_appendstr(noderev_str, line);
+      svn_stringbuf_appendbyte(noderev_str, '\n');
+    }
+  while (line->len > 0 && !eof);
+
+  /* Return the result. */
+  *noderev = noderev_str;
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+/* Starting at the directory in NODEREV's text, read all DAG nodes,
+ * directories and representations linked in that tree structure.
  * Store them in QUERY and REVISION_INFO.  Also, read them only once.
  *
- * Use POOL for persistent allocations and SCRATCH_POOL for temporaries.
+ * Use RESULT_POOL for persistent allocations and SCRATCH_POOL for
+ * temporaries.
  */
 static svn_error_t *
 parse_dir(query_t *query,
-          svn_stringbuf_t *file_content,
           node_revision_t *noderev,
           revision_info_t *revision_info,
-          apr_pool_t *pool,
+          apr_pool_t *result_pool,
           apr_pool_t *scratch_pool)
 {
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-  apr_pool_t *subpool = svn_pool_create(scratch_pool);
 
   int i;
   apr_array_header_t *entries;
   SVN_ERR(svn_fs_fs__rep_contents_dir(&entries, query->fs, noderev,
-                                      subpool, subpool));
+                                      scratch_pool, scratch_pool));
 
   for (i = 0; i < entries->nelts; ++i)
     {
@@ -617,55 +555,49 @@ parse_dir(query_t *query,
 
       if (svn_fs_fs__id_rev(dirent->id) == revision_info->revision)
         {
+          svn_stringbuf_t *noderev_str;
           svn_pool_clear(iterpool);
-          SVN_ERR(read_noderev(query, file_content,
-                               (apr_size_t)svn_fs_fs__id_item(dirent->id),
-                               revision_info, pool, iterpool));
+
+          SVN_ERR(read_phsy_noderev(&noderev_str, query,
+                                    svn_fs_fs__id_item(dirent->id),
+                                    revision_info, iterpool, iterpool));
+          SVN_ERR(read_noderev(query, noderev_str, revision_info,
+                               result_pool, iterpool));
         }
     }
 
   svn_pool_destroy(iterpool);
-  svn_pool_destroy(subpool);
 
   return SVN_NO_ERROR;
 }
 
-/* Starting at the noderev at OFFSET in FILE_CONTENT, read all DAG nodes,
- * directories and representations linked in that tree structure.  Store
- * them in QUERY and REVISION_INFO.  Also, read them only once.  Return the
- * result in *NODEREV.
+/* Parse the noderev given as NODEREV_STR and store the info in QUERY and
+ * REVISION_INFO.  In phys. addressing mode, continue reading all DAG nodes,
+ * directories and representations linked in that tree structure.
  *
- * Use POOL for persistent allocations and SCRATCH_POOL for temporaries.
+ * Use RESULT_POOL for persistent allocations and SCRATCH_POOL for
+ * temporaries.
  */
 static svn_error_t *
 read_noderev(query_t *query,
-             svn_stringbuf_t *file_content,
-             apr_size_t offset,
+             svn_stringbuf_t *noderev_str,
              revision_info_t *revision_info,
-             apr_pool_t *pool,
+             apr_pool_t *result_pool,
              apr_pool_t *scratch_pool)
 {
-  const char *end_marker = "\n\n";
-  const char *noderev_end = strstr(file_content->data + offset, end_marker);
-  apr_size_t noderev_len = noderev_end ? (noderev_end - file_content->data -
-                                          offset + strlen(end_marker))
-                                       : (file_content->len - offset);
-
   rep_stats_t *text = NULL;
   rep_stats_t *props = NULL;
-
   node_revision_t *noderev;
-  apr_pool_t *subpool = svn_pool_create(scratch_pool);
 
-  svn_stream_t *stream = svn_stream_from_stringbuf(file_content, subpool);
-  svn_stream_skip(stream, offset);
-  SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, subpool, subpool));
+  svn_stream_t *stream = svn_stream_from_stringbuf(noderev_str, scratch_pool);
+  SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, scratch_pool,
+                                  scratch_pool));
 
   if (noderev->data_rep)
     {
-      SVN_ERR(parse_representation(&text, query, file_content,
+      SVN_ERR(parse_representation(&text, query,
                                    noderev->data_rep, revision_info,
-                                   pool, subpool));
+                                   result_pool, scratch_pool));
 
       /* if we are the first to use this rep, mark it as "text rep" */
       if (++text->ref_count == 1)
@@ -674,9 +606,9 @@ read_noderev(query_t *query,
 
   if (noderev->prop_rep)
     {
-      SVN_ERR(parse_representation(&props, query, file_content,
+      SVN_ERR(parse_representation(&props, query,
                                    noderev->prop_rep, revision_info,
-                                   pool, subpool));
+                                   result_pool, scratch_pool));
 
       /* if we are the first to use this rep, mark it as "prop rep" */
       if (++props->ref_count == 1)
@@ -697,67 +629,121 @@ read_noderev(query_t *query,
   /* if this is a directory and has not been processed, yet, read and
    * process it recursively */
   if (   noderev->kind == svn_node_dir && text && text->ref_count == 1
-      && !svn_fs_fs__use_log_addressing(query->fs, revision_info->revision))
-    SVN_ERR(parse_dir(query, file_content, noderev, revision_info,
-                      pool, subpool));
+      && !svn_fs_fs__use_log_addressing(query->fs))
+    SVN_ERR(parse_dir(query, noderev, revision_info, result_pool,
+                      scratch_pool));
 
   /* update stats */
   if (noderev->kind == svn_node_dir)
     {
-      revision_info->dir_noderev_size += noderev_len;
+      revision_info->dir_noderev_size += noderev_str->len;
       revision_info->dir_noderev_count++;
     }
   else
     {
-      revision_info->file_noderev_size += noderev_len;
+      revision_info->file_noderev_size += noderev_str->len;
       revision_info->file_noderev_count++;
     }
-  svn_pool_destroy(subpool);
 
   return SVN_NO_ERROR;
 }
 
-/* Given the unparsed changes list in CHANGES with LEN chars, return the
- * number of changed paths encoded in it.
+/* For the revision given as REVISION_INFO within QUERY, determine the number
+ * of entries in its changed paths list and store that info in REVISION_INFO.
+ * Use SCRATCH_POOL for temporary allocations.
  */
-static apr_size_t
-get_change_count(const char *changes,
-                 apr_size_t len)
-{
-  apr_size_t lines = 0;
-  const char *end = changes + len;
+static svn_error_t *
+get_phys_change_count(query_t *query,
+                      revision_info_t *revision_info,
+                      apr_pool_t *scratch_pool)
+{
+  /* We are going to use our own sub-pool here because the changes object
+   * may well be >100MB and SCRATCH_POOL may not get cleared until all other
+   * info has been read by read_phys_revision().  Therefore, tidy up early.
+   */
+  apr_pool_t *subpool = svn_pool_create(scratch_pool);
+  apr_array_header_t *changes;
 
-  /* line count */
-  for (; changes < end; ++changes)
-    if (*changes == '\n')
-      ++lines;
+  SVN_ERR(svn_fs_fs__get_changes(&changes, query->fs,
+                                 revision_info->revision, subpool));
+  revision_info->change_count = changes->nelts;
 
-  /* two lines per change */
-  return lines / 2;
+  /* Release potentially tons of memory. */
+  svn_pool_destroy(subpool);
+
+  return SVN_NO_ERROR;
+}
+
+/* Read header information for the revision stored in FILE_CONTENT (one
+ * whole revision).  Return the offsets within FILE_CONTENT for the
+ * *ROOT_NODEREV, the list of *CHANGES and its len in *CHANGES_LEN.
+ * Use POOL for temporary allocations. */
+static svn_error_t *
+read_phys_revision(query_t *query,
+                   revision_info_t *info,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
+{
+  char buf[64];
+  apr_off_t root_node_offset;
+  apr_off_t changes_offset;
+  svn_stringbuf_t *trailer;
+  svn_stringbuf_t *noderev_str;
+
+  /* Read the last 64 bytes of the revision (if long enough). */
+  apr_off_t start = MAX(info->offset, info->end - sizeof(buf));
+  apr_size_t len = (apr_size_t)(info->end - start);
+  SVN_ERR(svn_io_file_seek(info->rev_file->file, APR_SET, &start,
+                           scratch_pool));
+  SVN_ERR(svn_io_file_read_full2(info->rev_file->file, buf, len, NULL, NULL,
+                                 scratch_pool));
+  trailer = svn_stringbuf_ncreate(buf, len, scratch_pool);
+
+  /* Parse that trailer. */
+  SVN_ERR(svn_fs_fs__parse_revision_trailer(&root_node_offset, 
+                                            &changes_offset, trailer,
+                                            info->revision));
+  SVN_ERR(get_phys_change_count(query, info, scratch_pool));
+
+  /* Calculate the length of the changes list. */
+  trailer = svn_fs_fs__unparse_revision_trailer(root_node_offset,
+                                                changes_offset,
+                                                scratch_pool);
+  info->changes_len = info->end - info->offset - changes_offset
+                    - trailer->len;
+
+  /* Recursively read nodes added in this rev. */
+  SVN_ERR(read_phsy_noderev(&noderev_str, query, root_node_offset, info,
+                            scratch_pool, scratch_pool));
+  SVN_ERR(read_noderev(query, noderev_str, info, result_pool, scratch_pool));
+
+  return SVN_NO_ERROR;
 }
 
 /* Read the content of the pack file staring at revision BASE physical
- * addressing mode and store it in QUERY.  Use POOL for allocations.
+ * addressing mode and store it in QUERY.
+ *
+ * Use RESULT_POOL for persistent allocations and SCRATCH_POOL for
+ * temporaries.
  */
 static svn_error_t *
 read_phys_pack_file(query_t *query,
                     svn_revnum_t base,
-                    apr_pool_t *pool)
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
 {
-  apr_pool_t *local_pool = svn_pool_create(pool);
-  apr_pool_t *iterpool = svn_pool_create(local_pool);
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   int i;
   apr_off_t file_size = 0;
-  apr_file_t *file;
+  svn_fs_fs__revision_file_t *rev_file;
 
-  SVN_ERR(open_rev_or_pack_file(&file, query, base, local_pool));
-  SVN_ERR(get_file_size(&file_size, file, local_pool));
+  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, query->fs, base,
+                                           scratch_pool, scratch_pool));
+  SVN_ERR(get_file_size(&file_size, rev_file, scratch_pool));
 
   /* process each revision in the pack file */
   for (i = 0; i < query->shard_size; ++i)
     {
-      apr_size_t root_node_offset;
-      svn_stringbuf_t *rev_content;
       revision_info_t *info;
 
       /* cancellation support */
@@ -765,133 +751,139 @@ read_phys_pack_file(query_t *query,
         SVN_ERR(query->cancel_func(query->cancel_baton));
 
       /* create the revision info for the current rev */
-      info = apr_pcalloc(pool, sizeof(*info));
-      info->representations = apr_array_make(iterpool, 4, 
sizeof(rep_stats_t*));
+      info = apr_pcalloc(result_pool, sizeof(*info));
+      info->representations = apr_array_make(result_pool, 4,
+                                             sizeof(rep_stats_t*));
+      info->rev_file = rev_file;
 
       info->revision = base + i;
       SVN_ERR(svn_fs_fs__get_packed_offset(&info->offset, query->fs, base + i,
                                            iterpool));
       if (i + 1 == query->shard_size)
-        SVN_ERR(svn_io_file_seek(file, APR_END, &info->end, iterpool));
+        info->end = file_size;
       else
         SVN_ERR(svn_fs_fs__get_packed_offset(&info->end, query->fs,
                                              base + i + 1, iterpool));
 
-      SVN_ERR(get_content(&rev_content, file, query, info->revision,
-                          info->offset,
-                          info->end - info->offset,
-                          iterpool));
-
-      SVN_ERR(read_revision_header(&info->changes,
-                                   &info->changes_len,
-                                   &root_node_offset,
-                                   rev_content,
-                                   iterpool));
-
-      info->change_count
-        = get_change_count(rev_content->data + info->changes,
-                           info->changes_len);
-      SVN_ERR(read_noderev(query, rev_content,
-                           root_node_offset, info, pool, iterpool));
+      SVN_ERR(read_phys_revision(query, info, result_pool, iterpool));
+
+      info->representations = apr_array_copy(result_pool,
+                                             info->representations);
 
-      info->representations = apr_array_copy(pool, info->representations);
+      /* Done with this revision. */
+      info->rev_file = NULL;
+
+      /* put it into our container */
       APR_ARRAY_PUSH(query->revisions, revision_info_t*) = info;
 
       /* destroy temps */
       svn_pool_clear(iterpool);
     }
 
+  /* Done with this pack file. */
+  SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
+
   /* one more pack file processed */
   if (query->progress_func)
-    query->progress_func(base, query->progress_baton, local_pool);
-
-  svn_pool_destroy(local_pool);
+    query->progress_func(base, query->progress_baton, scratch_pool);
 
   return SVN_NO_ERROR;
 }
 
 /* Read the content of the file for REVISION in physical addressing mode
- * and store its contents in QUERY.  Use POOL for allocations.
+ * and store its contents in QUERY.
+ *
+ * Use RESULT_POOL for persistent allocations and SCRATCH_POOL for
+ * temporaries.
  */
 static svn_error_t *
 read_phys_revision_file(query_t *query,
                         svn_revnum_t revision,
-                        apr_pool_t *pool)
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
 {
-  apr_size_t root_node_offset;
-  apr_pool_t *local_pool = svn_pool_create(pool);
-  svn_stringbuf_t *rev_content;
-  revision_info_t *info = apr_pcalloc(pool, sizeof(*info));
+  revision_info_t *info = apr_pcalloc(result_pool, sizeof(*info));
   apr_off_t file_size = 0;
-  apr_file_t *file;
+  svn_fs_fs__revision_file_t *rev_file;
 
   /* cancellation support */
   if (query->cancel_func)
     SVN_ERR(query->cancel_func(query->cancel_baton));
 
   /* read the whole pack file into memory */
-  SVN_ERR(open_rev_or_pack_file(&file, query, revision, local_pool));
-  SVN_ERR(get_file_size(&file_size, file, local_pool));
+  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, query->fs, revision,
+                                           scratch_pool, scratch_pool));
+  SVN_ERR(get_file_size(&file_size, rev_file, scratch_pool));
 
   /* create the revision info for the current rev */
-  info->representations = apr_array_make(pool, 4, sizeof(rep_stats_t*));
+  info->representations = apr_array_make(result_pool, 4, sizeof(rep_stats_t*));
 
+  info->rev_file = rev_file;
   info->revision = revision;
   info->offset = 0;
   info->end = file_size;
 
-  SVN_ERR(get_content(&rev_content, file, query, revision, 0, file_size,
-                      local_pool));
+  SVN_ERR(read_phys_revision(query, info, result_pool, scratch_pool));
 
-  SVN_ERR(read_revision_header(&info->changes,
-                               &info->changes_len,
-                               &root_node_offset,
-                               rev_content,
-                               local_pool));
+  /* Done with this revision. */
+  SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
+  info->rev_file = NULL;
 
-  /* put it into our containers */
+  /* put it into our container */
   APR_ARRAY_PUSH(query->revisions, revision_info_t*) = info;
 
-  info->change_count
-    = get_change_count(rev_content->data + info->changes,
-                       info->changes_len);
-
-  /* parse the revision content recursively. */
-  SVN_ERR(read_noderev(query, rev_content,
-                       root_node_offset, info,
-                       pool, local_pool));
-
   /* show progress every 1000 revs or so */
   if (query->progress_func)
     {
       if (query->shard_size && (revision % query->shard_size == 0))
-        query->progress_func(revision, query->progress_baton, local_pool);
+        query->progress_func(revision, query->progress_baton, scratch_pool);
       if (!query->shard_size && (revision % 1000 == 0))
-        query->progress_func(revision, query->progress_baton, local_pool);
+        query->progress_func(revision, query->progress_baton, scratch_pool);
     }
 
-  svn_pool_destroy(local_pool);
-
   return SVN_NO_ERROR;
 }
 
-/* Read the item described by ENTRY from the REV_FILE and return
- * the respective byte sequence in *CONTENTS allocated in POOL.
+/* Given the unparsed changes list in CHANGES with LEN chars, return the
+ * number of changed paths encoded in it.  Only used in log. addressing
+ * mode.
+ */
+static apr_uint64_t
+get_log_change_count(const char *changes,
+                     apr_size_t len)
+{
+  apr_size_t lines = 0;
+  const char *end = changes + len;
+
+  /* line count */
+  for (; changes < end; ++changes)
+    if (*changes == '\n')
+      ++lines;
+
+  /* two lines per change */
+  return lines / 2;
+}
+
+/* Read the item described by ENTRY from the REV_FILE and return the
+ * respective byte sequence in *CONTENTS, allocated in RESULT_POOL.
+ * Use SCRATCH_POOL for temporary allocations
  */
 static svn_error_t *
 read_item(svn_stringbuf_t **contents,
           svn_fs_fs__revision_file_t *rev_file,
           svn_fs_fs__p2l_entry_t *entry,
-          apr_pool_t *pool)
+          apr_pool_t *result_pool,
+          apr_pool_t *scratch_pool)
 {
-  svn_stringbuf_t *item = svn_stringbuf_create_ensure(entry->size, pool);
+  svn_stringbuf_t *item = svn_stringbuf_create_ensure(entry->size,
+                                                      result_pool);
   item->len = entry->size;
   item->data[item->len] = 0;
 
   SVN_ERR(svn_io_file_aligned_seek(rev_file->file, rev_file->block_size,
-                                   NULL, entry->offset, pool));
+                                   NULL, entry->offset, scratch_pool));
   SVN_ERR(svn_io_file_read_full2(rev_file->file, item->data, item->len,
-                                 NULL, NULL, pool));
+                                 NULL, NULL, scratch_pool));
 
   *contents = item;
 
@@ -899,17 +891,20 @@ read_item(svn_stringbuf_t **contents,
 }
 
 /* Process the logically addressed revision contents of revisions BASE to
- * BASE + COUNT - 1 in QUERY.  Use POOL for allocations.
+ * BASE + COUNT - 1 in QUERY.
+ *
+ * Use RESULT_POOL for persistent allocations and SCRATCH_POOL for
+ * temporaries.
  */
 static svn_error_t *
 read_log_rev_or_packfile(query_t *query,
                          svn_revnum_t base,
                          int count,
-                         apr_pool_t *pool)
+                         apr_pool_t *result_pool,
+                         apr_pool_t *scratch_pool)
 {
   fs_fs_data_t *ffd = query->fs->fsap_data;
-  apr_pool_t *iterpool = svn_pool_create(pool);
-  apr_pool_t *localpool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   apr_off_t max_offset;
   apr_off_t offset = 0;
   int i;
@@ -919,8 +914,9 @@ read_log_rev_or_packfile(query_t *query,
   for (i = 0; i < count; ++i)
     {
       /* create the revision info for the current rev */
-      revision_info_t *info = apr_pcalloc(pool, sizeof(*info));
-      info->representations = apr_array_make(pool, 4, sizeof(rep_stats_t*));
+      revision_info_t *info = apr_pcalloc(result_pool, sizeof(*info));
+      info->representations = apr_array_make(result_pool, 4,
+                                             sizeof(rep_stats_t*));
       info->revision = base + i;
 
       APR_ARRAY_PUSH(query->revisions, revision_info_t*) = info;
@@ -928,9 +924,9 @@ read_log_rev_or_packfile(query_t *query,
 
   /* open the pack / rev file that is covered by the p2l index */
   SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, query->fs, base,
-                                           localpool, iterpool));
+                                           scratch_pool, iterpool));
   SVN_ERR(svn_fs_fs__p2l_get_max_offset(&max_offset, query->fs, rev_file,
-                                        base, localpool));
+                                        base, scratch_pool));
 
   /* record the whole pack size in the first rev so the total sum will
      still be correct */
@@ -974,8 +970,8 @@ read_log_rev_or_packfile(query_t *query,
               revision_info_t *info = APR_ARRAY_IDX(query->revisions,
                                                     entry->item.revision,
                                                     revision_info_t*);
-              SVN_ERR(read_item(&item, rev_file, entry, iterpool));
-              SVN_ERR(read_noderev(query, item, 0, info, pool, iterpool));
+              SVN_ERR(read_item(&item, rev_file, entry, iterpool, iterpool));
+              SVN_ERR(read_noderev(query, item, info, result_pool, iterpool));
             }
           else if (entry->type == SVN_FS_FS__ITEM_TYPE_CHANGES)
             {
@@ -983,9 +979,9 @@ read_log_rev_or_packfile(query_t *query,
               revision_info_t *info = APR_ARRAY_IDX(query->revisions,
                                                     entry->item.revision,
                                                     revision_info_t*);
-              SVN_ERR(read_item(&item, rev_file, entry, iterpool));
+              SVN_ERR(read_item(&item, rev_file, entry, iterpool, iterpool));
               info->change_count
-                = get_change_count(item->data + 0, item->len);
+                = get_log_change_count(item->data + 0, item->len);
               info->changes_len += entry->size;
             }
 
@@ -996,74 +992,99 @@ read_log_rev_or_packfile(query_t *query,
 
   /* clean up and close file handles */
   svn_pool_destroy(iterpool);
-  svn_pool_destroy(localpool);
 
   return SVN_NO_ERROR;
 }
 
 /* Read the content of the pack file staring at revision BASE logical
- * addressing mode and store it in QUERY.  Use POOL for allocations.
+ * addressing mode and store it in QUERY.
+ *
+ * Use RESULT_POOL for persistent allocations and SCRATCH_POOL for
+ * temporaries.
  */
 static svn_error_t *
 read_log_pack_file(query_t *query,
                    svn_revnum_t base,
-                   apr_pool_t *pool)
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
 {
-  SVN_ERR(read_log_rev_or_packfile(query, base, query->shard_size, pool));
+  SVN_ERR(read_log_rev_or_packfile(query, base, query->shard_size,
+                                   result_pool, scratch_pool));
 
   /* one more pack file processed */
   if (query->progress_func)
-    query->progress_func(base, query->progress_baton, pool);
+    query->progress_func(base, query->progress_baton, scratch_pool);
 
   return SVN_NO_ERROR;
 }
 
 /* Read the content of the file for REVISION in logical addressing mode
- * and store its contents in QUERY.  Use POOL for allocations.
+ * and store its contents in QUERY.
+ *
+ * Use RESULT_POOL for persistent allocations and SCRATCH_POOL for
+ * temporaries.
  */
 static svn_error_t *
 read_log_revision_file(query_t *query,
                        svn_revnum_t revision,
-                       apr_pool_t *pool)
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
 {
-  SVN_ERR(read_log_rev_or_packfile(query, revision, 1, pool));
+  SVN_ERR(read_log_rev_or_packfile(query, revision, 1,
+                                   result_pool, scratch_pool));
 
   /* show progress every 1000 revs or so */
   if (query->progress_func)
     {
       if (query->shard_size && (revision % query->shard_size == 0))
-        query->progress_func(revision, query->progress_baton, pool);
+        query->progress_func(revision, query->progress_baton, scratch_pool);
       if (!query->shard_size && (revision % 1000 == 0))
-        query->progress_func(revision, query->progress_baton, pool);
+        query->progress_func(revision, query->progress_baton, scratch_pool);
     }
 
   return SVN_NO_ERROR;
 }
 
 /* Read the repository and collect the stats info in QUERY.
- * Use POOL for allocations.
+ *
+ * Use RESULT_POOL for persistent allocations and SCRATCH_POOL for
+ * temporaries.
  */
 static svn_error_t *
 read_revisions(query_t *query,
-               apr_pool_t *pool)
+               apr_pool_t *result_pool,
+               apr_pool_t *scratch_pool)
 {
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   svn_revnum_t revision;
 
   /* read all packed revs */
   for ( revision = 0
       ; revision < query->min_unpacked_rev
       ; revision += query->shard_size)
-    if (svn_fs_fs__use_log_addressing(query->fs, revision))
-      SVN_ERR(read_log_pack_file(query, revision, pool));
-    else
-      SVN_ERR(read_phys_pack_file(query, revision, pool));
+    {
+      svn_pool_clear(iterpool);
+
+      if (svn_fs_fs__use_log_addressing(query->fs))
+        SVN_ERR(read_log_pack_file(query, revision, result_pool, iterpool));
+      else
+        SVN_ERR(read_phys_pack_file(query, revision, result_pool, iterpool));
+    }
 
   /* read non-packed revs */
   for ( ; revision <= query->head; ++revision)
-    if (svn_fs_fs__use_log_addressing(query->fs, revision))
-      SVN_ERR(read_log_revision_file(query, revision, pool));
-    else
-      SVN_ERR(read_phys_revision_file(query, revision, pool));
+    {
+      svn_pool_clear(iterpool);
+
+      if (svn_fs_fs__use_log_addressing(query->fs))
+        SVN_ERR(read_log_revision_file(query, revision, result_pool,
+                                       iterpool));
+      else
+        SVN_ERR(read_phys_revision_file(query, revision, result_pool,
+                                        iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
@@ -1232,7 +1253,7 @@ svn_fs_fs__get_stats(svn_fs_fs__stats_t 
   SVN_ERR(create_query(&query, fs, *stats, progress_func, progress_func,
                        cancel_func, cancel_baton, scratch_pool,
                        scratch_pool));
-  SVN_ERR(read_revisions(query, scratch_pool));
+  SVN_ERR(read_revisions(query, scratch_pool, scratch_pool));
   aggregate_stats(query->revisions, *stats);
 
   return SVN_NO_ERROR;

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/structure
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/structure?rev=1641647&r1=1641646&r2=1641647&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/structure 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/structure Tue 
Nov 25 16:26:48 2014
@@ -44,9 +44,7 @@ repository) is:
       <rev>.<count>   Pack file, if the repository has been packed (see below)
       manifest        Pack manifest file, if a pack file exists (see below)
     revprops.db       SQLite database of the packed revprops (format 5 only)
-  transactions/       Subdirectory containing transactions (format 1 to 6)
-    <txnid>.txn/      Directory containing transaction <txnid>
-  transactions-la/    Subdirectory containing transactions (format 7+)
+  transactions/       Subdirectory containing transactions
     <txnid>.txn/      Directory containing transaction <txnid>
   txn-protorevs/      Subdirectory containing transaction proto-revision files
     <txnid>.rev       Proto-revision file for transaction <txnid>
@@ -216,8 +214,8 @@ Filesystem format options
 
 Currently, the only recognised format options are "layout" and "addressing".
 The first specifies the paths that will be used to store the revision
-files and revision property files.  The second specifies for which
-revisions address translation is required.
+files and revision property files.  The second specifies that logical to
+physical address translation is required.
 
 The "layout" option is followed by the name of the filesystem layout
 and any required parameters.  The default layout, if no "layout"
@@ -257,11 +255,10 @@ The supported modes, and the parameters 
   pairs with "offset" being the byte offset relative to the beginning of
   the revision in the respective rev or pack file.
 
-"logical <first-revision-to-use-it>"
-  'first-revision-to-use-it' specifies the first revision to use logical
-  addressing, must coincide with the beginning of a shard and may be a
-  future revision.  All earlier revisions use physical addressing.  It is
-  illegal to use logical addressing on non-sharded repositories.
+"logical"
+  All existing and future revision files will use logical
+  addressing. It is illegal to use logical addressing on non-sharded
+  repositories.
 
 
 Addressing modes

Modified: 
subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c?rev=1641647&r1=1641646&r2=1641647&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c 
Tue Nov 25 16:26:48 2014
@@ -391,7 +391,7 @@ auto_truncate_proto_rev(svn_fs_t *fs,
                         apr_pool_t *pool)
 {
   /* Only relevant for newer FSFS formats. */
-  if (svn_fs_fs__use_log_addressing(fs, txn_id->revision))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       /* Determine file range covered by the proto-index so far.  Note that
          we always append to both file, i.e. the last index entry also
@@ -1612,21 +1612,16 @@ svn_fs_fs__add_change(svn_fs_t *fs,
 
 /* If the transaction TXN_ID in FS uses logical addressing, store the
  * (ITEM_INDEX, OFFSET) pair in the txn's log-to-phys proto index file.
- * If FINAL_REVISION is not SVN_INVALID_REVNUM, use it to determine whether
- * to actually write to the proto-index.  Use POOL for allocations.
+ * Use POOL for allocations.
  */
 static svn_error_t *
 store_l2p_index_entry(svn_fs_t *fs,
                       const svn_fs_fs__id_part_t *txn_id,
-                      svn_revnum_t final_revision,
                       apr_off_t offset,
                       apr_uint64_t item_index,
                       apr_pool_t *pool)
 {
-  if (final_revision == SVN_INVALID_REVNUM)
-    final_revision = txn_id->revision + 1;
-
-  if (svn_fs_fs__use_log_addressing(fs, final_revision))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       const char *path = svn_fs_fs__path_l2p_proto_index(fs, txn_id, pool);
       apr_file_t *file;
@@ -1641,20 +1636,15 @@ store_l2p_index_entry(svn_fs_t *fs,
 
 /* If the transaction TXN_ID in FS uses logical addressing, store ENTRY
  * in the phys-to-log proto index file of transaction TXN_ID.
- * If FINAL_REVISION is not SVN_INVALID_REVNUM, use it to determine whether
- * to actually write to the proto-index.  Use POOL for allocations.
+ * Use POOL for allocations.
  */
 static svn_error_t *
 store_p2l_index_entry(svn_fs_t *fs,
                       const svn_fs_fs__id_part_t *txn_id,
-                      svn_revnum_t final_revision,
                       svn_fs_fs__p2l_entry_t *entry,
                       apr_pool_t *pool)
 {
-  if (final_revision == SVN_INVALID_REVNUM)
-    final_revision = txn_id->revision + 1;
-
-  if (svn_fs_fs__use_log_addressing(fs, final_revision))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       const char *path = svn_fs_fs__path_p2l_proto_index(fs, txn_id, pool);
       apr_file_t *file;
@@ -1670,22 +1660,16 @@ store_p2l_index_entry(svn_fs_t *fs,
  * of file system FS and return it in *ITEM_INDEX.  For old formats, it
  * will simply return the offset as item index; in new formats, it will
  * increment the txn's item index counter file and store the mapping in
- * the proto index file.  If FINAL_REVISION is not SVN_INVALID_REVNUM, use
- * it to determine whether to actually write to the proto-index.
- * Use POOL for allocations.
+ * the proto index file.  Use POOL for allocations.
  */
 static svn_error_t *
 allocate_item_index(apr_uint64_t *item_index,
                     svn_fs_t *fs,
                     const svn_fs_fs__id_part_t *txn_id,
-                    svn_revnum_t final_revision,
                     apr_off_t my_offset,
                     apr_pool_t *pool)
 {
-  if (final_revision == SVN_INVALID_REVNUM)
-    final_revision = txn_id->revision + 1;
-
-  if (svn_fs_fs__use_log_addressing(fs, final_revision))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       apr_file_t *file;
       char buffer[SVN_INT64_BUFFER_SIZE] = { 0 };
@@ -1712,8 +1696,7 @@ allocate_item_index(apr_uint64_t *item_i
       SVN_ERR(svn_io_file_close(file, pool));
 
       /* write log-to-phys index */
-      SVN_ERR(store_l2p_index_entry(fs, txn_id, final_revision,
-                                    my_offset, *item_index, pool));
+      SVN_ERR(store_l2p_index_entry(fs, txn_id, my_offset, *item_index, pool));
     }
   else
     {
@@ -2309,8 +2292,7 @@ rep_write_contents_close(void *baton)
       /* Write out our cosmetic end marker. */
       SVN_ERR(svn_stream_puts(b->rep_stream, "ENDREP\n"));
       SVN_ERR(allocate_item_index(&rep->item_index, b->fs, &rep->txn_id,
-                                  SVN_INVALID_REVNUM, b->rep_offset,
-                                  b->scratch_pool));
+                                  b->rep_offset, b->scratch_pool));
 
       b->noderev->data_rep = rep;
     }
@@ -2336,8 +2318,8 @@ rep_write_contents_close(void *baton)
                                       b->scratch_pool));
 
       SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->scratch_pool));
-      SVN_ERR(store_p2l_index_entry(b->fs, &rep->txn_id, SVN_INVALID_REVNUM,
-                                    &entry, b->scratch_pool));
+      SVN_ERR(store_p2l_index_entry(b->fs, &rep->txn_id, &entry,
+                                    b->scratch_pool));
     }
 
   SVN_ERR(svn_io_file_close(b->file, b->scratch_pool));
@@ -2519,9 +2501,7 @@ write_directory_to_stream(svn_stream_t *
    is not NULL, it will be used in addition to the on-disk cache to find
    earlier reps with the same content.  When such existing reps can be
    found, we will truncate the one just written from the file and return
-   the existing rep.  If FINAL_REVISION is not SVN_INVALID_REVNUM, use it
-   to determine whether to write to the proto-index files.
-   Perform temporary allocations in SCRATCH_POOL. */
+   the existing rep.  Perform temporary allocations in SCRATCH_POOL. */
 static svn_error_t *
 write_container_rep(representation_t *rep,
                     apr_file_t *file,
@@ -2530,7 +2510,6 @@ write_container_rep(representation_t *re
                     svn_fs_t *fs,
                     apr_hash_t *reps_hash,
                     apr_uint32_t item_type,
-                    svn_revnum_t final_revision,
                     apr_pool_t *scratch_pool)
 {
   svn_stream_t *stream;
@@ -2582,7 +2561,7 @@ write_container_rep(representation_t *re
       SVN_ERR(svn_stream_puts(whb->stream, "ENDREP\n"));
 
       SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id,
-                                  final_revision, offset, scratch_pool));
+                                  offset, scratch_pool));
 
       entry.offset = offset;
       SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool));
@@ -2594,8 +2573,7 @@ write_container_rep(representation_t *re
                                       fnv1a_checksum_ctx,
                                       scratch_pool));
 
-      SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, final_revision,
-                                    &entry, scratch_pool));
+      SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, &entry, scratch_pool));
 
       /* update the representation */
       rep->size = whb->size;
@@ -2616,8 +2594,6 @@ write_container_rep(representation_t *re
 
    If ITEM_TYPE is IS_PROPS equals SVN_FS_FS__ITEM_TYPE_*_PROPS, assume
    that we want to a props representation as the base for our delta.
-   If FINAL_REVISION is not SVN_INVALID_REVNUM, use it to determine whether
-   to write to the proto-index files.
    Perform temporary allocations in SCRATCH_POOL.
  */
 static svn_error_t *
@@ -2629,7 +2605,6 @@ write_container_delta_rep(representation
                           node_revision_t *noderev,
                           apr_hash_t *reps_hash,
                           apr_uint32_t item_type,
-                          svn_revnum_t final_revision,
                           apr_pool_t *scratch_pool)
 {
   svn_txdelta_window_handler_t diff_wh;
@@ -2726,7 +2701,7 @@ write_container_delta_rep(representation
       SVN_ERR(svn_stream_puts(file_stream, "ENDREP\n"));
 
       SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id,
-                                  final_revision, offset, scratch_pool));
+                                  offset, scratch_pool));
 
       entry.offset = offset;
       SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool));
@@ -2738,8 +2713,7 @@ write_container_delta_rep(representation
                                       fnv1a_checksum_ctx,
                                       scratch_pool));
 
-      SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, final_revision,
-                                    &entry, scratch_pool));
+      SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, &entry, scratch_pool));
 
       /* update the representation */
       rep->expanded_size = whb->size;
@@ -2926,12 +2900,11 @@ write_final_rev(const svn_fs_id_t **new_
                                               write_directory_to_stream,
                                               fs, noderev, NULL,
                                               SVN_FS_FS__ITEM_TYPE_DIR_REP,
-                                              rev, pool));
+                                              pool));
           else
             SVN_ERR(write_container_rep(noderev->data_rep, file, entries,
                                         write_directory_to_stream, fs, NULL,
-                                        SVN_FS_FS__ITEM_TYPE_DIR_REP, rev,
-                                        pool));
+                                        SVN_FS_FS__ITEM_TYPE_DIR_REP, pool));
 
           reset_txn_in_rep(noderev->data_rep);
         }
@@ -2947,7 +2920,7 @@ write_final_rev(const svn_fs_id_t **new_
           reset_txn_in_rep(noderev->data_rep);
           noderev->data_rep->revision = rev;
 
-          if (!svn_fs_fs__use_log_addressing(fs, rev))
+          if (!svn_fs_fs__use_log_addressing(fs))
             {
               /* See issue 3845.  Some unknown mechanism caused the
                  protorev file to get truncated, so check for that
@@ -2976,11 +2949,11 @@ write_final_rev(const svn_fs_id_t **new_
       if (ffd->deltify_properties)
         SVN_ERR(write_container_delta_rep(noderev->prop_rep, file, proplist,
                                           write_hash_to_stream, fs, noderev,
-                                          reps_hash, item_type, rev, pool));
+                                          reps_hash, item_type, pool));
       else
         SVN_ERR(write_container_rep(noderev->prop_rep, file, proplist,
                                     write_hash_to_stream, fs, reps_hash,
-                                    item_type, rev, pool));
+                                    item_type, pool));
 
       reset_txn_in_rep(noderev->prop_rep);
     }
@@ -2996,15 +2969,15 @@ write_final_rev(const svn_fs_id_t **new_
 
   /* root nodes have a fixed ID in log addressing mode */
   SVN_ERR(svn_fs_fs__get_file_offset(&my_offset, file, pool));
-  if (svn_fs_fs__use_log_addressing(fs, rev) && at_root)
+  if (svn_fs_fs__use_log_addressing(fs) && at_root)
     {
       /* reference the root noderev from the log-to-phys index */
       rev_item.number = SVN_FS_FS__ITEM_INDEX_ROOT_NODE;
-      SVN_ERR(store_l2p_index_entry(fs, txn_id, rev, my_offset,
+      SVN_ERR(store_l2p_index_entry(fs, txn_id, my_offset,
                                     rev_item.number, pool));
     }
   else
-    SVN_ERR(allocate_item_index(&rev_item.number, fs, txn_id, rev,
+    SVN_ERR(allocate_item_index(&rev_item.number, fs, txn_id,
                                 my_offset, pool));
 
   rev_item.revision = rev;
@@ -3062,7 +3035,7 @@ write_final_rev(const svn_fs_id_t **new_
                                    pool));
 
   /* reference the root noderev from the log-to-phys index */
-  if (svn_fs_fs__use_log_addressing(fs, rev))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       svn_fs_fs__p2l_entry_t entry;
       rev_item.revision = SVN_INVALID_REVNUM;
@@ -3076,7 +3049,7 @@ write_final_rev(const svn_fs_id_t **new_
                                       fnv1a_checksum_ctx,
                                       pool));
 
-      SVN_ERR(store_p2l_index_entry(fs, txn_id, rev, &entry, pool));
+      SVN_ERR(store_p2l_index_entry(fs, txn_id, &entry, pool));
     }
 
   /* Return our ID that references the revision file. */
@@ -3086,17 +3059,15 @@ write_final_rev(const svn_fs_id_t **new_
 }
 
 /* Write the changed path info CHANGED_PATHS from transaction TXN_ID to the
-   permanent rev-file FILE representing NEW_REV in filesystem FS.  *OFFSET_P
-   is set the to offset in the file of the beginning of this information.
-   NEW_REV is the revision currently being committed.
-   Perform temporary allocations in POOL. */
+   permanent rev-file FILE in filesystem FS.  *OFFSET_P is set the to offset
+   in the file of the beginning of this information.  Perform temporary
+   allocations in POOL. */
 static svn_error_t *
 write_final_changed_path_info(apr_off_t *offset_p,
                               apr_file_t *file,
                               svn_fs_t *fs,
                               const svn_fs_fs__id_part_t *txn_id,
                               apr_hash_t *changed_paths,
-                              svn_revnum_t new_rev,
                               apr_pool_t *pool)
 {
   apr_off_t offset;
@@ -3114,7 +3085,7 @@ write_final_changed_path_info(apr_off_t 
   *offset_p = offset;
 
   /* reference changes from the indexes */
-  if (svn_fs_fs__use_log_addressing(fs, new_rev))
+  if (svn_fs_fs__use_log_addressing(fs))
     {
       svn_fs_fs__p2l_entry_t entry;
 
@@ -3128,8 +3099,8 @@ write_final_changed_path_info(apr_off_t 
                                       fnv1a_checksum_ctx,
                                       pool));
 
-      SVN_ERR(store_p2l_index_entry(fs, txn_id, new_rev, &entry, pool));
-      SVN_ERR(store_l2p_index_entry(fs, txn_id, new_rev, entry.offset,
+      SVN_ERR(store_p2l_index_entry(fs, txn_id, &entry, pool));
+      SVN_ERR(store_l2p_index_entry(fs, txn_id, entry.offset,
                                     SVN_FS_FS__ITEM_INDEX_CHANGES, pool));
     }
 
@@ -3286,242 +3257,6 @@ verify_locks(svn_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
-/* Return TRUE, if transaction TXN_ID in FS definitively uses logical
- * addressing mode.  Use POOL for temporary allocations.
- */
-static svn_boolean_t
-using_log_addressing(svn_fs_t *fs,
-                     const svn_fs_fs__id_part_t *txn_id,
-                     apr_pool_t *pool)
-{
-  /* As long as we don't write new data representations, we won't allocate
-     IDs and there is no difference between log & phys mode.
-
-     After the first ID got allocated, it is logical mode and the proto-
-     index file does exist.
-   */
-  svn_node_kind_t kind;
-  const char *path = svn_fs_fs__path_l2p_proto_index(fs, txn_id, pool);
-
-  svn_error_t *err = svn_io_check_path(path, &kind, pool);
-  if (err)
-    {
-      /* We couldn't check for the presence of the index file.
-
-         So, we probably won't be able to access it during later stages
-         of the commit.
-       */
-      svn_error_clear(err);
-      return FALSE;
-    }
-
-  return kind == svn_node_file;
-}
-
-/* Return TRUE, if the file with FILENAME contains a node revision.
- */
-static svn_boolean_t
-is_noderev_file(const char *filename)
-{
-  apr_size_t dot_count = 0;
-
-  /* all interesting files start with "node." */
-  if (strncmp(filename, PATH_PREFIX_NODE, strlen(PATH_PREFIX_NODE)))
-    return FALSE;
-
-  for (; *filename; ++filename)
-    if (*filename == '.')
-      ++dot_count;
-
-  return dot_count == 2;
-}
-
-/* Determine the checksum for the SIZE bytes of data starting at START
- * in FILE and return the result in *FNV1_CHECKSUM.
- * Use POOL for tempoary allocations.
- */
-static svn_error_t *
-fnv1a_checksum_on_file_range(apr_uint32_t *fnv1_checksum,
-                             apr_file_t *file,
-                             apr_off_t start,
-                             apr_off_t size,
-                             apr_pool_t *pool)
-{
-  char *buffer = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE);
-
-  svn_checksum_ctx_t *checksum_ctx
-    = svn_checksum_ctx_create(svn_checksum_fnv1a_32x4, pool);
-
-  SVN_ERR(svn_io_file_seek(file, APR_SET, &start, pool));
-  while (size > 0)
-    {
-      apr_size_t to_read = MIN(size, sizeof(buffer));
-
-      SVN_ERR(svn_io_file_read_full2(file, buffer, to_read, &to_read,
-                                     NULL, pool));
-      SVN_ERR(svn_checksum_update(checksum_ctx, buffer, to_read));
-      size -= to_read;
-    }
-  SVN_ERR(fnv1a_checksum_finalize(fnv1_checksum, checksum_ctx, pool));
-
-  return SVN_NO_ERROR;
-}
-
-/* qsort()-compatible comparison function sorting svn_fs_fs__p2l_entry_t
- * by offset.
- */
-static int
-compare_sort_p2l_entry(const void *a,
-                       const void *b)
-{
-  apr_off_t lhs = ((const svn_fs_fs__p2l_entry_t *)a)->offset;
-  apr_off_t rhs = ((const svn_fs_fs__p2l_entry_t *)b)->offset;
-
-  return lhs < rhs ? -1 : rhs == lhs ? 0 : 1;
-}
-
-
-/* Upgrade the transaction TXN_ID in FS from physical addressing mode
- * to logical addressing mode.  FINAL_REVISION is the revision that this
- * txn is being committed to.  Use POOL for temporary allocations.
- */
-static svn_error_t *
-upgrade_transaction(svn_fs_t *fs,
-                    const svn_fs_fs__id_part_t *txn_id,
-                    svn_revnum_t final_revision,
-                    apr_file_t *proto_file,
-                    apr_pool_t *pool)
-{
-  fs_fs_data_t *ffd = fs->fsap_data;
-  apr_hash_t *dirents;
-  int i;
-  apr_hash_index_t* hi;
-
-  /* we allocate large temporary data and want to release it asap */
-
-  apr_pool_t *subpool = svn_pool_create(pool);
-  apr_pool_t *iterpool = svn_pool_create(pool);
-
-  apr_hash_t *id_map = apr_hash_make(subpool);
-  const char *txn_dir = svn_fs_fs__path_txn_dir(fs, txn_id, subpool);
-  apr_array_header_t *p2l_entries
-    = apr_array_make(subpool, 16, sizeof(svn_fs_fs__p2l_entry_t));
-
-  /* scan the txn directory for noderev files and patch them up */
-
-  SVN_ERR(svn_io_get_dirents3(&dirents, txn_dir, TRUE, subpool, iterpool));
-  for (hi = apr_hash_first(subpool, dirents); hi; hi = apr_hash_next(hi))
-    {
-      apr_file_t *file;
-      const char *filename;
-      node_revision_t *noderev;
-      svn_stream_t *stream;
-      const char *name;
-      apr_uint64_t *old_index, *item_index, *new_index;
-
-      svn_pool_clear(iterpool);
-
-      /* We are only interested in file data reps of this txns.
-         Older IDs remain valid because they are already committed.
-         Other IDs (noderevs and their usage in directories) will only be
-         assigned later anyways. */
-
-      name = apr_hash_this_key(hi);
-      if (!is_noderev_file(name))
-        continue;
-
-      filename = svn_dirent_join(txn_dir, name, iterpool);
-      SVN_ERR(svn_io_file_open(&file, filename,
-                               APR_READ | APR_WRITE | APR_BUFFERED,
-                               APR_OS_DEFAULT,
-                               iterpool));
-      stream = svn_stream_from_aprfile2(file, TRUE, iterpool);
-      SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, iterpool, iterpool));
-      if (   noderev->data_rep == NULL
-          || noderev->data_rep->revision != SVN_INVALID_REVNUM
-          || noderev->kind != svn_node_file)
-        continue;
-
-      /* We need to assign an id.
-         We might already have one because of rep sharing. */
-
-      item_index = &noderev->data_rep->item_index;
-      new_index = apr_hash_get(id_map, item_index, sizeof(*item_index));
-
-      if (new_index)
-        {
-          *item_index = *new_index;
-        }
-      else
-        {
-          svn_fs_fs__rep_header_t *header;
-          svn_fs_fs__p2l_entry_t *entry;
-
-          /* assign a logical ID and write the L2P proto-index */
-
-          old_index = apr_pmemdup(subpool, item_index, sizeof(*item_index));
-          SVN_ERR(allocate_item_index(item_index, fs, txn_id, final_revision,
-                                      *old_index, iterpool));
-
-          new_index = apr_pmemdup(subpool, item_index, sizeof(*item_index));
-          apr_hash_set(id_map, old_index, sizeof(*old_index), new_index);
-
-          /* we need to know the length of the representation header
-             because it is not accounted for by the representation length */
-
-          entry = apr_array_push(p2l_entries);
-          entry->offset = *old_index;
-          SVN_ERR(svn_io_file_seek(proto_file, APR_SET, &entry->offset,
-                                   iterpool));
-          SVN_ERR(svn_fs_fs__read_rep_header(&header,
-                    svn_stream_from_aprfile2(proto_file, TRUE, iterpool),
-                    iterpool, iterpool));
-
-          /* Create the corresponding entry for the P2L proto-index.
-
-             We need to write that proto-index in strict offset order but
-             we have no control over the order in which we traverse the
-             data reps.   Thus, we collect the entries in an array. */
-
-          entry->size = noderev->data_rep->size + header->header_size + 7;
-                        /* 7 for the "ENDREP\n" */
-          entry->type = SVN_FS_FS__ITEM_TYPE_FILE_REP;
-          entry->item.revision = SVN_INVALID_REVNUM;
-          entry->item.number = *new_index;
-          SVN_ERR(fnv1a_checksum_on_file_range(&entry->fnv1_checksum,
-                                               proto_file,
-                                               entry->offset, entry->size,
-                                               iterpool));
-        }
-
-      /* write the updated noderev to disk */
-
-      SVN_ERR(svn_io_file_trunc(file, 0, iterpool));
-      SVN_ERR(svn_fs_fs__write_noderev(stream, noderev, ffd->format,
-                                       TRUE, iterpool));
-    }
-
-  /* Finally, write all P2L proto-index entries ordered by item offset. */
-
-  qsort(p2l_entries->elts, p2l_entries->nelts, p2l_entries->elt_size,
-        compare_sort_p2l_entry);
-  for (i = 0; i < p2l_entries->nelts; ++i)
-    {
-      svn_fs_fs__p2l_entry_t *entry;
-
-      svn_pool_clear(iterpool);
-
-      entry = &APR_ARRAY_IDX(p2l_entries, i, svn_fs_fs__p2l_entry_t);
-      SVN_ERR(store_p2l_index_entry(fs, txn_id, final_revision,
-                                    entry, iterpool));
-    }
-
-  svn_pool_clear(iterpool);
-  svn_pool_clear(subpool);
-
-  return SVN_NO_ERROR;
-}
-
 /* Return in *PATH the path to a file containing the properties that
    make up the final revision properties file.  This involves setting
    svn:date and removing any temporary properties associated with the
@@ -3701,18 +3436,6 @@ commit_body(void *baton, apr_pool_t *poo
                                  cb->fs, txn_id, pool));
   SVN_ERR(svn_fs_fs__get_file_offset(&initial_offset, proto_file, pool));
 
-  /* Make sure that we don't try to commit an old txn that used physical
-     addressing but will be committed into the revision range that requires
-     logical addressing.
-     */
-  if (svn_fs_fs__use_log_addressing(cb->fs, new_rev)
-      && !svn_fs_fs__use_log_addressing(cb->fs, txn_id->revision)
-      && !using_log_addressing(cb->fs, txn_id, pool))
-    {
-      SVN_ERR(upgrade_transaction(cb->fs, txn_id, new_rev, proto_file, pool));
-      SVN_ERR(svn_io_file_seek(proto_file, APR_SET, &initial_offset, pool));
-    }
-
   /* Write out all the node-revisions and directory contents. */
   root_id = svn_fs_fs__id_txn_create_root(txn_id, pool);
   SVN_ERR(write_final_rev(&new_root_id, proto_file, new_rev, cb->fs, root_id,
@@ -3723,9 +3446,17 @@ commit_body(void *baton, apr_pool_t *poo
   /* Write the changed-path information. */
   SVN_ERR(write_final_changed_path_info(&changed_path_offset, proto_file,
                                         cb->fs, txn_id, changed_paths,
-                                        new_rev, pool));
+                                        pool));
 
-  if (!svn_fs_fs__use_log_addressing(cb->fs, new_rev))
+  if (svn_fs_fs__use_log_addressing(cb->fs))
+    {
+      /* Append the index data to the rev file. */
+      SVN_ERR(svn_fs_fs__add_index_data(cb->fs, proto_file,
+                      svn_fs_fs__path_l2p_proto_index(cb->fs, txn_id, pool),
+                      svn_fs_fs__path_p2l_proto_index(cb->fs, txn_id, pool),
+                      new_rev, pool));
+    }
+  else
     {
       /* Write the final line. */
 
@@ -3737,15 +3468,6 @@ commit_body(void *baton, apr_pool_t *poo
       SVN_ERR(svn_io_file_write_full(proto_file, trailer->data, trailer->len,
                                      NULL, pool));
     }
-  else
-    {
-      /* Append the index data to the rev file. */
-      SVN_ERR(svn_fs_fs__add_index_data(cb->fs, proto_file,
-                      svn_fs_fs__path_l2p_proto_index(cb->fs, txn_id, pool),
-                      svn_fs_fs__path_p2l_proto_index(cb->fs, txn_id, pool),
-                      new_rev, pool));
-    }
-
 
   SVN_ERR(svn_io_file_flush_to_disk(proto_file, pool));
   SVN_ERR(svn_io_file_close(proto_file, pool));

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/tree.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/tree.c?rev=1641647&r1=1641646&r2=1641647&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/tree.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/tree.c Tue Nov 
25 16:26:48 2014
@@ -2387,10 +2387,7 @@ fs_dir_optimal_order(apr_array_header_t 
                      apr_hash_t *entries,
                      apr_pool_t *pool)
 {
-  *ordered_p
-    = svn_fs_fs__order_dir_entries(root->fs, entries,
-                                   root->rev,
-                                   pool);
+  *ordered_p = svn_fs_fs__order_dir_entries(root->fs, entries, pool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/util.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/util.c?rev=1641647&r1=1641646&r2=1641647&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/util.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/util.c Tue Nov 
25 16:26:48 2014
@@ -237,11 +237,7 @@ const char *
 svn_fs_fs__path_txns_dir(svn_fs_t *fs,
                          apr_pool_t *pool)
 {
-  fs_fs_data_t *ffd = fs->fsap_data;
-
-  return ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT
-       ? svn_dirent_join(fs->path, PATH_TXNS_LA_DIR, pool)
-       : svn_dirent_join(fs->path, PATH_TXNS_DIR, pool);
+  return svn_dirent_join(fs->path, PATH_TXNS_DIR, pool);
 }
 
 const char *
@@ -691,10 +687,8 @@ svn_fs_fs__move_into_place(const char *o
 }
 
 svn_boolean_t
-svn_fs_fs__use_log_addressing(svn_fs_t *fs,
-                              svn_revnum_t rev)
+svn_fs_fs__use_log_addressing(svn_fs_t *fs)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-  return ffd->min_log_addressing_rev != SVN_INVALID_REVNUM
-      && ffd->min_log_addressing_rev <= rev;
+  return ffd->use_log_addressing;
 }

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/util.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/util.h?rev=1641647&r1=1641646&r2=1641647&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/util.h 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/util.h Tue Nov 
25 16:26:48 2014
@@ -401,9 +401,8 @@ svn_fs_fs__move_into_place(const char *o
                            const char *perms_reference,
                            apr_pool_t *pool);
 
-/* Return TRUE, iff revision REV in FS requires logical addressing. */
+/* Return TRUE, iff FS uses logical addressing. */
 svn_boolean_t
-svn_fs_fs__use_log_addressing(svn_fs_t *fs,
-                              svn_revnum_t rev);
+svn_fs_fs__use_log_addressing(svn_fs_t *fs);
 
 #endif

Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/verify.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/verify.c?rev=1641647&r1=1641646&r2=1641647&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/verify.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/verify.c Tue 
Nov 25 16:26:48 2014
@@ -22,6 +22,7 @@
 
 #include "svn_sorts.h"
 #include "svn_checksum.h"
+#include "svn_time.h"
 #include "private/svn_subr_private.h"
 
 #include "verify.h"
@@ -404,7 +405,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
                                            "refers to revision %ld outside "
                                            "the rev / pack file (%ld-%ld)"),
                                          apr_off_t_toa(pool, entry->offset),
-                                         entry->item.number,
+                                         (long)entry->item.number,
                                          start, start + count - 1);
             }
           else
@@ -702,6 +703,49 @@ compare_p2l_to_rev(svn_fs_t *fs,
   return SVN_NO_ERROR;
 }
 
+/* Verify that the revprops of the revisions START to END in FS can be
+ * accessed.  Invoke CANCEL_FUNC with CANCEL_BATON at regular intervals.
+ *
+ * The values of START and END have already been auto-selected and
+ * verified.
+ */
+static svn_error_t *
+verify_revprops(svn_fs_t *fs,
+                svn_revnum_t start,
+                svn_revnum_t end,
+                svn_cancel_func_t cancel_func,
+                void *cancel_baton,
+                apr_pool_t *pool)
+{
+  svn_revnum_t revision;
+  apr_pool_t *iterpool = svn_pool_create(pool);
+
+  for (revision = start; revision < end; ++revision)
+    {
+      svn_string_t *date;
+      apr_time_t timetemp;
+
+      svn_pool_clear(iterpool);
+
+      /* Access the svn:date revprop.
+       * This implies parsing all revprops for that revision. */
+      SVN_ERR(svn_fs_fs__revision_prop(&date, fs, revision,
+                                       SVN_PROP_REVISION_DATE, iterpool));
+
+      /* The time stamp is the only revprop that, if given, needs to
+       * have a valid content. */
+      if (date)
+        SVN_ERR(svn_time_from_cstring(&timetemp, date->data, iterpool));
+
+      if (cancel_func)
+        SVN_ERR(cancel_func(cancel_baton));
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
 static svn_revnum_t
 pack_size(svn_fs_t *fs, svn_revnum_t rev)
 {
@@ -710,22 +754,24 @@ pack_size(svn_fs_t *fs, svn_revnum_t rev
   return rev < ffd->min_unpacked_rev ? ffd->max_files_per_dir : 1;
 }
 
-/* Verify that the log-to-phys indexes and phys-to-log indexes are
- * consistent with each other.  The function signature is similar to
- * svn_fs_fs__verify.
+/* Verify that on-disk representation has not been tempered with (in a way
+ * that leaves the repository in a corrupted state).  This compares log-to-
+ * phys with phys-to-log indexes, verifies the low-level checksums and
+ * checks that all revprops are available.  The function signature is
+ * similar to svn_fs_fs__verify.
  *
  * The values of START and END have already been auto-selected and
  * verified.  You may call this for format7 or higher repos.
  */
 static svn_error_t *
-verify_index_consistency(svn_fs_t *fs,
-                         svn_revnum_t start,
-                         svn_revnum_t end,
-                         svn_fs_progress_notify_func_t notify_func,
-                         void *notify_baton,
-                         svn_cancel_func_t cancel_func,
-                         void *cancel_baton,
-                         apr_pool_t *pool)
+verify_f7_metadata_consistency(svn_fs_t *fs,
+                               svn_revnum_t start,
+                               svn_revnum_t end,
+                               svn_fs_progress_notify_func_t notify_func,
+                               void *notify_baton,
+                               svn_cancel_func_t cancel_func,
+                               void *cancel_baton,
+                               apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   svn_revnum_t revision, next_revision;
@@ -761,6 +807,11 @@ verify_index_consistency(svn_fs_t *fs,
         err = compare_p2l_to_rev(fs, pack_start, pack_end - pack_start,
                                  cancel_func, cancel_baton, iterpool);
 
+      /* ensure that revprops are available and accessible */
+      if (!err)
+        err = verify_revprops(fs, pack_start, pack_end,
+                              cancel_func, cancel_baton, iterpool);
+
       /* concurrent packing is one of the reasons why verification may fail.
          Make sure, we operate on up-to-date information. */
       if (err)
@@ -811,11 +862,10 @@ svn_fs_fs__verify(svn_fs_t *fs,
 
   /* log/phys index consistency.  We need to check them first to make
      sure we can access the rev / pack files in format7. */
-  if (svn_fs_fs__use_log_addressing(fs, end))
-    SVN_ERR(verify_index_consistency(fs,
-                                     MAX(start, ffd->min_log_addressing_rev),
-                                     end, notify_func, notify_baton,
-                                     cancel_func, cancel_baton, pool));
+  if (svn_fs_fs__use_log_addressing(fs))
+    SVN_ERR(verify_f7_metadata_consistency(fs, start, end,
+                                           notify_func, notify_baton,
+                                           cancel_func, cancel_baton, pool));
 
   /* rep cache consistency */
   if (ffd->format >= SVN_FS_FS__MIN_REP_SHARING_FORMAT)

Modified: 
subversion/branches/move-tracking-2/subversion/libsvn_fs_util/fs-util.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_util/fs-util.c?rev=1641647&r1=1641646&r2=1641647&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_util/fs-util.c 
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_util/fs-util.c Tue 
Nov 25 16:26:48 2014
@@ -199,6 +199,7 @@ svn_fs__path_change_create_internal(cons
   change->node_rev_id = node_rev_id;
   change->change_kind = change_kind;
   change->mergeinfo_mod = svn_tristate_unknown;
+  change->copyfrom_rev = SVN_INVALID_REVNUM;
 
   return change;
 }

Propchange: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
  Merged 
/subversion/trunk/subversion/libsvn_fs_fs:r1603487,1603499,1603605,1604128,1604414,1604416-1604417,1604421,1604717,1604802,1604824,1604836,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607572,1612810,1613872,1614611,1615348,1615351-1615352,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618641,1618653,1618662,1619358,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,1624011,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947,1627949,1627966,1628093,1628159,1628161,1628392-1628393,1628415,1628427,1628738,1628762,1629854-1629855,1629857,1629865,1629873,16
 
29875,1629879,1630067,1630070,1631049-1631051,1631075,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1633232,1633617-1633618,1634872,1634920,1636478,1636483,1636629
  Merged /subversion/trunk/subversion/libsvn_fs_x:r1635153-1641646
  Merged /subversion/branches/log-addressing/subversion/libsvn_fs_fs:r1531982


Reply via email to