You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2014/06/24 23:30:01 UTC

svn commit: r1605201 [3/5] - in /subversion/branches/svn-auth-x509: ./ build/generator/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subve...

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/index.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/index.h?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/index.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/index.h Tue Jun 24 21:29:59 2014
@@ -70,10 +70,6 @@ typedef struct svn_fs_fs__p2l_entry_t
   svn_fs_fs__id_part_t item;
 } svn_fs_fs__p2l_entry_t;
 
-/* Close the index file STREAM and underlying file handle. */
-svn_error_t *
-svn_fs_fs__packed_stream_close(svn_fs_fs__packed_number_stream_t *stream);
-
 /* Open / create a log-to-phys index file with the full file path name
  * FILE_NAME.  Return the open file in *PROTO_INDEX and use POOL for
  * allocations.
@@ -105,14 +101,14 @@ svn_fs_fs__l2p_proto_index_add_entry(apr
                                      apr_uint64_t item_index,
                                      apr_pool_t *pool);
 
-/* Use the proto index file stored at PROTO_FILE_NAME and construct the
- * final log-to-phys index file at FILE_NAME.  The first revision will
+/* Use the proto index file stored at PROTO_FILE_NAME, construct the final
+ * log-to-phys index and append it to INDEX_FILE.  The first revision will
  * be REVISION, entries to the next revision will be assigned to REVISION+1
  * and so forth.  Use POOL for allocations.
  */
 svn_error_t *
-svn_fs_fs__l2p_index_create(svn_fs_t *fs,
-                            const char *file_name,
+svn_fs_fs__l2p_index_append(svn_fs_t *fs,
+                            apr_file_t *index_file,
                             const char *proto_file_name,
                             svn_revnum_t revision,
                             apr_pool_t *pool);
@@ -145,14 +141,14 @@ svn_fs_fs__p2l_proto_index_next_offset(a
                                        apr_file_t *proto_index,
                                        apr_pool_t *pool);
 
-/* Use the proto index file stored at PROTO_FILE_NAME and construct the
- * final phys-to-log index file at FILE_NAME.  Entries without a valid
+/* Use the proto index file stored at PROTO_FILE_NAME, construct the final
+ * phys-to-log index and append it to INDEX_FILE.  Entries without a valid
  * revision will be assigned to the REVISION given here.
  * Use POOL for allocations.
  */
 svn_error_t *
-svn_fs_fs__p2l_index_create(svn_fs_t *fs,
-                            const char *file_name,
+svn_fs_fs__p2l_index_append(svn_fs_t *fs,
+                            apr_file_t *index_file,
                             const char *proto_file_name,
                             svn_revnum_t revision,
                             apr_pool_t *pool);

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/low_level.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/low_level.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/low_level.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/low_level.c Tue Jun 24 21:29:59 2014
@@ -150,14 +150,49 @@ svn_fs_fs__parse_revision_trailer(apr_of
 svn_stringbuf_t *
 svn_fs_fs__unparse_revision_trailer(apr_off_t root_offset,
                                     apr_off_t changes_offset,
-                                    apr_pool_t *pool)
+                                    apr_pool_t *result_pool)
 {
-  return svn_stringbuf_createf(pool,
+  return svn_stringbuf_createf(result_pool,
                                "%" APR_OFF_T_FMT " %" APR_OFF_T_FMT "\n",
                                root_offset,
                                changes_offset);
 }
 
+svn_error_t *
+svn_fs_fs__parse_footer(apr_off_t *l2p_offset,
+                        apr_off_t *p2l_offset,
+                        svn_stringbuf_t *footer,
+                        svn_revnum_t rev)
+{
+  apr_int64_t val;
+
+  /* Split the footer into the 2 number strings. */
+  char *seperator = strchr(footer->data, ' ');
+  if (!seperator)
+    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+                             _("Revision file (r%ld) has corrupt footer"),
+                             rev);
+  *seperator = '\0';
+
+  /* Convert offset values. */
+  SVN_ERR(svn_cstring_atoi64(&val, footer->data));
+  *l2p_offset = (apr_off_t)val;
+  SVN_ERR(svn_cstring_atoi64(&val, seperator + 1));
+  *p2l_offset = (apr_off_t)val;
+
+  return SVN_NO_ERROR;
+}
+
+svn_stringbuf_t *
+svn_fs_fs__unparse_footer(apr_off_t l2p_offset,
+                          apr_off_t p2l_offset,
+                          apr_pool_t *result_pool)
+{
+  return svn_stringbuf_createf(result_pool,
+                               "%" APR_OFF_T_FMT " %" APR_OFF_T_FMT,
+                               l2p_offset,
+                               p2l_offset);
+}
 
 /* Read the next entry in the changes record from file FILE and store
    the resulting change in *CHANGE_P.  If there is no next record,
@@ -165,7 +200,8 @@ svn_fs_fs__unparse_revision_trailer(apr_
 static svn_error_t *
 read_change(change_t **change_p,
             svn_stream_t *stream,
-            apr_pool_t *pool)
+            apr_pool_t *result_pool,
+            apr_pool_t *scratch_pool)
 {
   svn_stringbuf_t *line;
   svn_boolean_t eof = TRUE;
@@ -176,13 +212,13 @@ read_change(change_t **change_p,
   /* Default return value. */
   *change_p = NULL;
 
-  SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, pool));
+  SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool));
 
   /* Check for a blank line. */
   if (eof || (line->len == 0))
     return SVN_NO_ERROR;
 
-  change = apr_pcalloc(pool, sizeof(*change));
+  change = apr_pcalloc(result_pool, sizeof(*change));
   info = &change->info;
   last_str = line->data;
 
@@ -192,7 +228,7 @@ read_change(change_t **change_p,
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Invalid changes line in rev-file"));
 
-  info->node_rev_id = svn_fs_fs__id_parse(str, strlen(str), pool);
+  info->node_rev_id = svn_fs_fs__id_parse(str, result_pool);
   if (info->node_rev_id == NULL)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Invalid changes line in rev-file"));
@@ -313,10 +349,10 @@ read_change(change_t **change_p,
   
   /* Get the changed path. */
   change->path.len = strlen(last_str);
-  change->path.data = apr_pstrmemdup(pool, last_str, change->path.len);
+  change->path.data = apr_pstrdup(result_pool, last_str);
 
   /* Read the next line, the copyfrom line. */
-  SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, pool));
+  SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool));
   info->copyfrom_known = TRUE;
   if (eof || line->len == 0)
     {
@@ -336,7 +372,7 @@ read_change(change_t **change_p,
         return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                 _("Invalid changes line in rev-file"));
 
-      info->copyfrom_path = apr_pstrdup(pool, last_str);
+      info->copyfrom_path = apr_pstrdup(result_pool, last_str);
     }
 
   *change_p = change;
@@ -347,36 +383,72 @@ read_change(change_t **change_p,
 svn_error_t *
 svn_fs_fs__read_changes(apr_array_header_t **changes,
                         svn_stream_t *stream,
-                        apr_pool_t *pool)
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
 {
   change_t *change;
+  apr_pool_t *iterpool;
 
-  /* pre-allocate enough room for most change lists
-     (will be auto-expanded as necessary) */
-  *changes = apr_array_make(pool, 30, sizeof(change_t *));
+  /* Pre-allocate enough room for most change lists.
+     (will be auto-expanded as necessary).
 
-  SVN_ERR(read_change(&change, stream, pool));
+     Chose the default to just below 2^N such that the doubling reallocs
+     will request roughly 2^M bytes from the OS without exceeding the
+     respective two-power by just a few bytes (leaves room array and APR
+     node overhead for large enough M).
+   */
+  *changes = apr_array_make(result_pool, 63, sizeof(change_t *));
+
+  SVN_ERR(read_change(&change, stream, result_pool, scratch_pool));
+  iterpool = svn_pool_create(scratch_pool);
   while (change)
     {
       APR_ARRAY_PUSH(*changes, change_t*) = change;
-      SVN_ERR(read_change(&change, stream, pool));
+      SVN_ERR(read_change(&change, stream, result_pool, iterpool));
+      svn_pool_clear(iterpool);
     }
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_fs_fs__read_changes_incrementally(svn_stream_t *stream,
+                                      svn_fs_fs__change_receiver_t
+                                        change_receiver,
+                                      void *change_receiver_baton,
+                                      apr_pool_t *scratch_pool)
+{
+  change_t *change;
+  apr_pool_t *iterpool;
+
+  iterpool = svn_pool_create(scratch_pool);
+  do
+    {
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(read_change(&change, stream, iterpool, iterpool));
+      if (change)
+        SVN_ERR(change_receiver(change_receiver_baton, change, iterpool));
+    }
+  while (change);
+  svn_pool_destroy(iterpool);
+  
+  return SVN_NO_ERROR;
+}
+
 /* Write a single change entry, path PATH, change CHANGE, and copyfrom
    string COPYFROM, into the file specified by FILE.  Only include the
    node kind field if INCLUDE_NODE_KIND is true.  Only include the
    mergeinfo-mod field if INCLUDE_MERGEINFO_MODS is true.  All temporary
-   allocations are in POOL. */
+   allocations are in SCRATCH_POOL. */
 static svn_error_t *
 write_change_entry(svn_stream_t *stream,
                    const char *path,
                    svn_fs_path_change2_t *change,
                    svn_boolean_t include_node_kind,
                    svn_boolean_t include_mergeinfo_mods,
-                   apr_pool_t *pool)
+                   apr_pool_t *scratch_pool)
 {
   const char *idstr;
   const char *change_string = NULL;
@@ -409,7 +481,7 @@ write_change_entry(svn_stream_t *stream,
     }
 
   if (change->node_rev_id)
-    idstr = svn_fs_fs__id_unparse(change->node_rev_id, pool)->data;
+    idstr = svn_fs_fs__id_unparse(change->node_rev_id, scratch_pool)->data;
   else
     idstr = ACTION_RESET;
 
@@ -417,19 +489,19 @@ write_change_entry(svn_stream_t *stream,
     {
       SVN_ERR_ASSERT(change->node_kind == svn_node_dir
                      || change->node_kind == svn_node_file);
-      kind_string = apr_psprintf(pool, "-%s",
+      kind_string = apr_psprintf(scratch_pool, "-%s",
                                  change->node_kind == svn_node_dir
                                  ? SVN_FS_FS__KIND_DIR
                                   : SVN_FS_FS__KIND_FILE);
     }
 
   if (include_mergeinfo_mods && change->mergeinfo_mod != svn_tristate_unknown)
-    mergeinfo_string = apr_psprintf(pool, " %s",
+    mergeinfo_string = apr_psprintf(scratch_pool, " %s",
                                     change->mergeinfo_mod == svn_tristate_true
                                       ? FLAG_TRUE
                                       : FLAG_FALSE);
 
-  buf = svn_stringbuf_createf(pool, "%s %s%s %s %s%s %s\n",
+  buf = svn_stringbuf_createf(scratch_pool, "%s %s%s %s %s%s %s\n",
                               idstr, change_string, kind_string,
                               change->text_mod ? FLAG_TRUE : FLAG_FALSE,
                               change->prop_mod ? FLAG_TRUE : FLAG_FALSE,
@@ -438,7 +510,7 @@ write_change_entry(svn_stream_t *stream,
 
   if (SVN_IS_VALID_REVNUM(change->copyfrom_rev))
     {
-      svn_stringbuf_appendcstr(buf, apr_psprintf(pool, "%ld %s",
+      svn_stringbuf_appendcstr(buf, apr_psprintf(scratch_pool, "%ld %s",
                                                  change->copyfrom_rev,
                                                  change->copyfrom_path));
     }
@@ -455,9 +527,9 @@ svn_fs_fs__write_changes(svn_stream_t *s
                          svn_fs_t *fs,
                          apr_hash_t *changes,
                          svn_boolean_t terminate_list,
-                         apr_pool_t *pool)
+                         apr_pool_t *scratch_pool)
 {
-  apr_pool_t *iterpool = svn_pool_create(pool);
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   fs_fs_data_t *ffd = fs->fsap_data;
   svn_boolean_t include_node_kinds =
       ffd->format >= SVN_FS_FS__MIN_KIND_IN_CHANGED_FORMAT;
@@ -470,7 +542,8 @@ svn_fs_fs__write_changes(svn_stream_t *s
      that the final file is deterministic and repeatable, however the
      rest of the FSFS code doesn't require any particular order here. */
   sorted_changed_paths = svn_sort__hash(changes,
-                                        svn_sort_compare_items_lexically, pool);
+                                        svn_sort_compare_items_lexically,
+                                        scratch_pool);
 
   /* Write all items to disk in the new order. */
   for (i = 0; i < sorted_changed_paths->nelts; ++i)
@@ -499,13 +572,13 @@ svn_fs_fs__write_changes(svn_stream_t *s
 /* Given a revision file FILE that has been pre-positioned at the
    beginning of a Node-Rev header block, read in that header block and
    store it in the apr_hash_t HEADERS.  All allocations will be from
-   POOL. */
+   RESULT_POOL. */
 static svn_error_t *
 read_header_block(apr_hash_t **headers,
                   svn_stream_t *stream,
-                  apr_pool_t *pool)
+                  apr_pool_t *result_pool)
 {
-  *headers = svn_hash__make(pool);
+  *headers = svn_hash__make(result_pool);
 
   while (1)
     {
@@ -515,7 +588,8 @@ read_header_block(apr_hash_t **headers,
       apr_ssize_t name_len;
       svn_boolean_t eof;
 
-      SVN_ERR(svn_stream_readline(stream, &header_str, "\n", &eof, pool));
+      SVN_ERR(svn_stream_readline(stream, &header_str, "\n", &eof,
+                                  result_pool));
 
       if (eof || header_str->len == 0)
         break; /* end of header block */
@@ -562,7 +636,8 @@ read_header_block(apr_hash_t **headers,
 svn_error_t *
 svn_fs_fs__parse_representation(representation_t **rep_p,
                                 svn_stringbuf_t *text,
-                                apr_pool_t *pool)
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool)
 {
   representation_t *rep;
   char *str;
@@ -571,7 +646,7 @@ svn_fs_fs__parse_representation(represen
   svn_checksum_t *checksum;
   const char *end;
 
-  rep = apr_pcalloc(pool, sizeof(*rep));
+  rep = apr_pcalloc(result_pool, sizeof(*rep));
   *rep_p = rep;
 
   str = svn_cstring_tokenize(" ", &string);
@@ -620,7 +695,8 @@ svn_fs_fs__parse_representation(represen
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Malformed text representation offset line in node-rev"));
 
-  SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_md5, str, pool));
+  SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_md5, str,
+                                 scratch_pool));
   memcpy(rep->md5_digest, checksum->digest, sizeof(rep->md5_digest));
 
   /* The remaining fields are only used for formats >= 4, so check that. */
@@ -633,7 +709,8 @@ svn_fs_fs__parse_representation(represen
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Malformed text representation offset line in node-rev"));
 
-  SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str, pool));
+  SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str,
+                                 scratch_pool));
   rep->has_sha1 = checksum != NULL;
   memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest));
 
@@ -666,17 +743,22 @@ static svn_error_t *
 read_rep_offsets(representation_t **rep_p,
                  char *string,
                  const svn_fs_id_t *noderev_id,
-                 apr_pool_t *pool)
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
   svn_error_t *err
     = svn_fs_fs__parse_representation(rep_p,
-                                      svn_stringbuf_create_wrap(string, pool),
-                                      pool);
+                                      svn_stringbuf_create_wrap(string,
+                                                                scratch_pool),
+                                      result_pool,
+                                      scratch_pool);
   if (err)
     {
-      const svn_string_t *id_unparsed = svn_fs_fs__id_unparse(noderev_id, pool);
+      const svn_string_t *id_unparsed;
       const char *where;
-      where = apr_psprintf(pool,
+
+      id_unparsed = svn_fs_fs__id_unparse(noderev_id, scratch_pool);
+      where = apr_psprintf(scratch_pool,
                            _("While reading representation offsets "
                              "for node-revision '%s':"),
                            noderev_id ? id_unparsed->data : "(null)");
@@ -694,16 +776,17 @@ read_rep_offsets(representation_t **rep_
 svn_error_t *
 svn_fs_fs__read_noderev(node_revision_t **noderev_p,
                         svn_stream_t *stream,
-                        apr_pool_t *pool)
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
 {
   apr_hash_t *headers;
   node_revision_t *noderev;
   char *value;
   const char *noderev_id;
 
-  SVN_ERR(read_header_block(&headers, stream, pool));
+  SVN_ERR(read_header_block(&headers, stream, scratch_pool));
 
-  noderev = apr_pcalloc(pool, sizeof(*noderev));
+  noderev = apr_pcalloc(result_pool, sizeof(*noderev));
 
   /* Read the node-rev id. */
   value = svn_hash_gets(headers, HEADER_ID);
@@ -714,7 +797,7 @@ svn_fs_fs__read_noderev(node_revision_t 
 
   SVN_ERR(svn_stream_close(stream));
 
-  noderev->id = svn_fs_fs__id_parse(value, strlen(value), pool);
+  noderev->id = svn_fs_fs__id_parse(value, result_pool);
   noderev_id = value; /* for error messages later */
 
   /* Read the type. */
@@ -744,7 +827,7 @@ svn_fs_fs__read_noderev(node_revision_t 
   if (value)
     {
       SVN_ERR(read_rep_offsets(&noderev->prop_rep, value,
-                               noderev->id, pool));
+                               noderev->id, result_pool, scratch_pool));
     }
 
   /* Get the data location. */
@@ -752,7 +835,7 @@ svn_fs_fs__read_noderev(node_revision_t 
   if (value)
     {
       SVN_ERR(read_rep_offsets(&noderev->data_rep, value,
-                               noderev->id, pool));
+                               noderev->id, result_pool, scratch_pool));
     }
 
   /* Get the created path. */
@@ -765,20 +848,19 @@ svn_fs_fs__read_noderev(node_revision_t 
     }
   else
     {
-      noderev->created_path = apr_pstrdup(pool, value);
+      noderev->created_path = apr_pstrdup(result_pool, value);
     }
 
   /* Get the predecessor ID. */
   value = svn_hash_gets(headers, HEADER_PRED);
   if (value)
-    noderev->predecessor_id = svn_fs_fs__id_parse(value, strlen(value),
-                                                  pool);
+    noderev->predecessor_id = svn_fs_fs__id_parse(value, result_pool);
 
   /* Get the copyroot. */
   value = svn_hash_gets(headers, HEADER_COPYROOT);
   if (value == NULL)
     {
-      noderev->copyroot_path = apr_pstrdup(pool, noderev->created_path);
+      noderev->copyroot_path = apr_pstrdup(result_pool, noderev->created_path);
       noderev->copyroot_rev = svn_fs_fs__id_rev(noderev->id);
     }
   else
@@ -797,7 +879,7 @@ svn_fs_fs__read_noderev(node_revision_t 
         return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                                  _("Malformed copyroot line in node-rev '%s'"),
                                  noderev_id);
-      noderev->copyroot_path = apr_pstrdup(pool, value);
+      noderev->copyroot_path = apr_pstrdup(result_pool, value);
     }
 
   /* Get the copyfrom. */
@@ -821,7 +903,7 @@ svn_fs_fs__read_noderev(node_revision_t 
         return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                                  _("Malformed copyfrom line in node-rev '%s'"),
                                  noderev_id);
-      noderev->copyfrom_path = apr_pstrdup(pool, value);
+      noderev->copyfrom_path = apr_pstrdup(result_pool, value);
     }
 
   /* Get whether this is a fresh txn root. */
@@ -846,13 +928,13 @@ svn_fs_fs__read_noderev(node_revision_t 
 
 /* Return a textual representation of the DIGEST of given KIND.
  * If IS_NULL is TRUE, no digest is available.
- * Use POOL for allocations.
+ * Allocate the result in RESULT_POOL.
  */
 static const char *
 format_digest(const unsigned char *digest,
               svn_checksum_kind_t kind,
               svn_boolean_t is_null,
-              apr_pool_t *pool)
+              apr_pool_t *result_pool)
 {
   svn_checksum_t checksum;
   checksum.digest = digest;
@@ -861,37 +943,41 @@ format_digest(const unsigned char *diges
   if (is_null)
     return "(null)";
 
-  return svn_checksum_to_cstring_display(&checksum, pool);
+  return svn_checksum_to_cstring_display(&checksum, result_pool);
 }
 
 svn_stringbuf_t *
 svn_fs_fs__unparse_representation(representation_t *rep,
                                   int format,
                                   svn_boolean_t mutable_rep_truncated,
-                                  apr_pool_t *pool)
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool)
 {
   char buffer[SVN_INT64_BUFFER_SIZE];
   if (svn_fs_fs__id_txn_used(&rep->txn_id) && mutable_rep_truncated)
-    return svn_stringbuf_ncreate("-1", 2, pool);
+    return svn_stringbuf_ncreate("-1", 2, result_pool);
 
   if (format < SVN_FS_FS__MIN_REP_SHARING_FORMAT || !rep->has_sha1)
     return svn_stringbuf_createf
-            (pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT
+            (result_pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT
              " %" SVN_FILESIZE_T_FMT " %s",
              rep->revision, rep->item_index, rep->size,
              rep->expanded_size,
-             format_digest(rep->md5_digest, svn_checksum_md5, FALSE, pool));
+             format_digest(rep->md5_digest, svn_checksum_md5, FALSE,
+                           scratch_pool));
 
   svn__ui64tobase36(buffer, rep->uniquifier.number);
   return svn_stringbuf_createf
-          (pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT
+          (result_pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT
            " %" SVN_FILESIZE_T_FMT " %s %s %s/_%s",
            rep->revision, rep->item_index, rep->size,
            rep->expanded_size,
-           format_digest(rep->md5_digest, svn_checksum_md5, FALSE, pool),
+           format_digest(rep->md5_digest, svn_checksum_md5,
+                         FALSE, scratch_pool),
            format_digest(rep->sha1_digest, svn_checksum_sha1,
-                         !rep->has_sha1, pool),
-           svn_fs_fs__id_txn_unparse(&rep->uniquifier.noderev_txn_id, pool),
+                         !rep->has_sha1, scratch_pool),
+           svn_fs_fs__id_txn_unparse(&rep->uniquifier.noderev_txn_id,
+                                     scratch_pool),
            buffer);
 }
 
@@ -901,50 +987,50 @@ svn_fs_fs__write_noderev(svn_stream_t *o
                          node_revision_t *noderev,
                          int format,
                          svn_boolean_t include_mergeinfo,
-                         apr_pool_t *pool)
+                         apr_pool_t *scratch_pool)
 {
-  SVN_ERR(svn_stream_printf(outfile, pool, HEADER_ID ": %s\n",
+  SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_ID ": %s\n",
                             svn_fs_fs__id_unparse(noderev->id,
-                                                  pool)->data));
+                                                  scratch_pool)->data));
 
-  SVN_ERR(svn_stream_printf(outfile, pool, HEADER_TYPE ": %s\n",
+  SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_TYPE ": %s\n",
                             (noderev->kind == svn_node_file) ?
                             SVN_FS_FS__KIND_FILE : SVN_FS_FS__KIND_DIR));
 
   if (noderev->predecessor_id)
-    SVN_ERR(svn_stream_printf(outfile, pool, HEADER_PRED ": %s\n",
+    SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_PRED ": %s\n",
                               svn_fs_fs__id_unparse(noderev->predecessor_id,
-                                                    pool)->data));
+                                                    scratch_pool)->data));
 
-  SVN_ERR(svn_stream_printf(outfile, pool, HEADER_COUNT ": %d\n",
+  SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_COUNT ": %d\n",
                             noderev->predecessor_count));
 
   if (noderev->data_rep)
-    SVN_ERR(svn_stream_printf(outfile, pool, HEADER_TEXT ": %s\n",
+    SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_TEXT ": %s\n",
                               svn_fs_fs__unparse_representation
                                 (noderev->data_rep,
                                  format,
                                  noderev->kind == svn_node_dir,
-                                 pool)->data));
+                                 scratch_pool, scratch_pool)->data));
 
   if (noderev->prop_rep)
-    SVN_ERR(svn_stream_printf(outfile, pool, HEADER_PROPS ": %s\n",
+    SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_PROPS ": %s\n",
                               svn_fs_fs__unparse_representation
                                 (noderev->prop_rep, format,
-                                 TRUE, pool)->data));
+                                 TRUE, scratch_pool, scratch_pool)->data));
 
-  SVN_ERR(svn_stream_printf(outfile, pool, HEADER_CPATH ": %s\n",
+  SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_CPATH ": %s\n",
                             noderev->created_path));
 
   if (noderev->copyfrom_path)
-    SVN_ERR(svn_stream_printf(outfile, pool, HEADER_COPYFROM ": %ld"
+    SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_COPYFROM ": %ld"
                               " %s\n",
                               noderev->copyfrom_rev,
                               noderev->copyfrom_path));
 
   if ((noderev->copyroot_rev != svn_fs_fs__id_rev(noderev->id)) ||
       (strcmp(noderev->copyroot_path, noderev->created_path) != 0))
-    SVN_ERR(svn_stream_printf(outfile, pool, HEADER_COPYROOT ": %ld"
+    SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_COPYROOT ": %ld"
                               " %s\n",
                               noderev->copyroot_rev,
                               noderev->copyroot_path));
@@ -955,8 +1041,8 @@ svn_fs_fs__write_noderev(svn_stream_t *o
   if (include_mergeinfo)
     {
       if (noderev->mergeinfo_count > 0)
-        SVN_ERR(svn_stream_printf(outfile, pool, HEADER_MINFO_CNT ": %"
-                                  APR_INT64_T_FMT "\n",
+        SVN_ERR(svn_stream_printf(outfile, scratch_pool, HEADER_MINFO_CNT
+                                  ": %" APR_INT64_T_FMT "\n",
                                   noderev->mergeinfo_count));
 
       if (noderev->has_mergeinfo)
@@ -969,16 +1055,17 @@ svn_fs_fs__write_noderev(svn_stream_t *o
 svn_error_t *
 svn_fs_fs__read_rep_header(svn_fs_fs__rep_header_t **header,
                            svn_stream_t *stream,
-                           apr_pool_t *pool)
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
 {
   svn_stringbuf_t *buffer;
   char *str, *last_str;
   apr_int64_t val;
   svn_boolean_t eol = FALSE;
 
-  SVN_ERR(svn_stream_readline(stream, &buffer, "\n", &eol, pool));
+  SVN_ERR(svn_stream_readline(stream, &buffer, "\n", &eol, scratch_pool));
 
-  *header = apr_pcalloc(pool, sizeof(**header));
+  *header = apr_pcalloc(result_pool, sizeof(**header));
   (*header)->header_size = buffer->len + 1;
   if (strcmp(buffer->data, REP_PLAIN) == 0)
     {
@@ -1028,7 +1115,7 @@ svn_fs_fs__read_rep_header(svn_fs_fs__re
 svn_error_t *
 svn_fs_fs__write_rep_header(svn_fs_fs__rep_header_t *header,
                             svn_stream_t *stream,
-                            apr_pool_t *pool)
+                            apr_pool_t *scratch_pool)
 {
   const char *text;
   
@@ -1043,8 +1130,8 @@ svn_fs_fs__write_rep_header(svn_fs_fs__r
         break;
 
       default:
-        text = apr_psprintf(pool, REP_DELTA " %ld %" APR_OFF_T_FMT " %"
-                            SVN_FILESIZE_T_FMT "\n",
+        text = apr_psprintf(scratch_pool, REP_DELTA " %ld %" APR_OFF_T_FMT
+                                          " %" SVN_FILESIZE_T_FMT "\n",
                             header->base_revision, header->base_item_index,
                             header->base_length);
     }

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/low_level.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/low_level.h?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/low_level.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/low_level.h Tue Jun 24 21:29:59 2014
@@ -31,7 +31,8 @@
 
 /* The functions are grouped as follows:
  *
- * - revision trailer
+ * - revision trailer (up to format 6)
+ * - revision footer (since format 7)
  * - changed path list
  * - node revision
  * - representation (as in "text:" and "props:" lines)
@@ -54,68 +55,113 @@ svn_fs_fs__parse_revision_trailer(apr_of
 
 /* Given the offset of the root noderev in ROOT_OFFSET and the offset of
  * the changed paths list in CHANGES_OFFSET,  return the corresponding
- * revision's trailer.  Allocate it in POOL.
+ * revision's trailer.  Allocate it in RESULT_POOL.
  */
 svn_stringbuf_t *
 svn_fs_fs__unparse_revision_trailer(apr_off_t root_offset,
                                     apr_off_t changes_offset,
-                                    apr_pool_t *pool);
+                                    apr_pool_t *result_pool);
 
-/* Read all the changes from STREAM and store them in *CHANGES.  Do all
-   allocations in POOL. */
+/* Given the format 7+ revision / pack FOOTER, parse it destructively
+ * and return the start offsets of the index data in *L2P_OFFSET and
+ * *P2L_OFFSET, respectively.
+ * 
+ * Note that REV is only used to construct nicer error objects that
+ * mention this revision.
+ */
+svn_error_t *
+svn_fs_fs__parse_footer(apr_off_t *l2p_offset,
+                        apr_off_t *p2l_offset,
+                        svn_stringbuf_t *footer,
+                        svn_revnum_t rev);
+
+/* Given the offset of the L2P index data in L2P_OFFSET and the offset of
+ * the P2L index data in P2L_OFFSET,  return the corresponding format 7+
+ * revision / pack file footer.  Allocate it in RESULT_POOL.
+ */
+svn_stringbuf_t *
+svn_fs_fs__unparse_footer(apr_off_t l2p_offset,
+                          apr_off_t p2l_offset,
+                          apr_pool_t *result_pool);
+
+/* Read all the changes from STREAM and store them in *CHANGES,
+   allocated in RESULT_POOL. Do temporary allocations in SCRATCH_POOL. */
 svn_error_t *
 svn_fs_fs__read_changes(apr_array_header_t **changes,
                         svn_stream_t *stream,
-                        apr_pool_t *pool);
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool);
+
+/* Callback function used by svn_fs_fs__read_changes_incrementally(),
+ * asking the receiver to process to process CHANGE using BATON.  CHANGE
+ * and SCRATCH_POOL will not be valid beyond the current callback invocation.
+ */
+typedef svn_error_t *(*svn_fs_fs__change_receiver_t)(
+  void *baton,
+  change_t *change,
+  apr_pool_t *scratch_pool);
+
+/* Read all the changes from STREAM and invoke CHANGE_RECEIVER on each change.
+   Do all allocations in SCRATCH_POOL. */
+svn_error_t *
+svn_fs_fs__read_changes_incrementally(svn_stream_t *stream,
+                                      svn_fs_fs__change_receiver_t
+                                        change_receiver,
+                                      void *change_receiver_baton,
+                                      apr_pool_t *scratch_pool);
 
 /* Write the changed path info from CHANGES in filesystem FS to the
    output stream STREAM.  You may call this function multiple time on
    the same stream but the last call should set TERMINATE_LIST to write
    an extra empty line that marks the end of the changed paths list.
-   Perform temporary allocations in POOL.
+   Perform temporary allocations in SCRATCH_POOL.
  */
 svn_error_t *
 svn_fs_fs__write_changes(svn_stream_t *stream,
                          svn_fs_t *fs,
                          apr_hash_t *changes,
                          svn_boolean_t terminate_list,
-                         apr_pool_t *pool);
+                         apr_pool_t *scratch_pool);
 
 /* Read a node-revision from STREAM. Set *NODEREV to the new structure,
-   allocated in POOL. */
+   allocated in RESULT_POOL. */
 svn_error_t *
 svn_fs_fs__read_noderev(node_revision_t **noderev,
                         svn_stream_t *stream,
-                        apr_pool_t *pool);
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool);
 
 /* Write the node-revision NODEREV into the stream OUTFILE, compatible with
    filesystem format FORMAT.  Only write mergeinfo-related metadata if
-   INCLUDE_MERGEINFO is true.  Temporary allocations are from POOL. */
+   INCLUDE_MERGEINFO is true.  Temporary allocations are from SCRATCH_POOL. */
 svn_error_t *
 svn_fs_fs__write_noderev(svn_stream_t *outfile,
                          node_revision_t *noderev,
                          int format,
                          svn_boolean_t include_mergeinfo,
-                         apr_pool_t *pool);
+                         apr_pool_t *scratch_pool);
 
 /* Parse the description of a representation from TEXT and store it
-   into *REP_P.  Allocate *REP_P in POOL. */
+   into *REP_P.  TEXT will be invalidated by this call.  Allocate *REP_P in
+   RESULT_POOL and use SCRATCH_POOL for temporaries. */
 svn_error_t *
 svn_fs_fs__parse_representation(representation_t **rep_p,
                                 svn_stringbuf_t *text,
-                                apr_pool_t *pool);
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool);
 
 /* Return a formatted string, compatible with filesystem format FORMAT,
    that represents the location of representation REP.  If
    MUTABLE_REP_TRUNCATED is given, the rep is for props or dir contents,
    and only a "-1" revision number will be given for a mutable rep.
    If MAY_BE_CORRUPT is true, guard for NULL when constructing the string.
-   Perform the allocation from POOL.  */
+   Allocate the result in RESULT_POOL and temporaries in SCRATCH_POOL. */
 svn_stringbuf_t *
 svn_fs_fs__unparse_representation(representation_t *rep,
                                   int format,
                                   svn_boolean_t mutable_rep_truncated,
-                                  apr_pool_t *pool);
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool);
 
 /* This type enumerates all forms of representations that we support. */
 typedef enum svn_fs_fs__rep_type_t
@@ -156,16 +202,18 @@ typedef struct svn_fs_fs__rep_header_t
   apr_size_t header_size;
 } svn_fs_fs__rep_header_t;
 
-/* Read the next line from file FILE and parse it as a text
-   representation entry.  Return the parsed entry in *REP_ARGS_P.
-   Perform all allocations in POOL. */
+/* Read the next line from STREAM and parse it as a text
+   representation header.  Return the parsed entry in *HEADER, allocated
+   in RESULT_POOL. Perform temporary allocations in SCRATCH_POOL. */
 svn_error_t *
 svn_fs_fs__read_rep_header(svn_fs_fs__rep_header_t **header,
                            svn_stream_t *stream,
-                           apr_pool_t *pool);
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool);
 
-/* Write the representation HEADER to STREAM.  Use POOL for allocations. */
+/* Write the representation HEADER to STREAM.
+ * Use SCRATCH_POOL for temporary allocations. */
 svn_error_t *
 svn_fs_fs__write_rep_header(svn_fs_fs__rep_header_t *header,
                             svn_stream_t *stream,
-                            apr_pool_t *pool);
+                            apr_pool_t *scratch_pool);

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/pack.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/pack.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/pack.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/pack.c Tue Jun 24 21:29:59 2014
@@ -360,12 +360,6 @@ static svn_error_t *
 close_pack_context(pack_context_t *context,
                    apr_pool_t *pool)
 {
-  const char *l2p_index_path
-    = apr_pstrcat(pool, context->pack_file_path, PATH_EXT_L2P_INDEX,
-                  SVN_VA_NULL);
-  const char *p2l_index_path
-    = apr_pstrcat(pool, context->pack_file_path, PATH_EXT_P2L_INDEX,
-                  SVN_VA_NULL);
   const char *proto_l2p_index_path;
   const char *proto_p2l_index_path;
 
@@ -374,18 +368,17 @@ close_pack_context(pack_context_t *conte
                                context->proto_l2p_index, pool));
   SVN_ERR(svn_io_file_name_get(&proto_p2l_index_path,
                                context->proto_p2l_index, pool));
-  
+
   /* finalize proto index files */
   SVN_ERR(svn_io_file_close(context->proto_l2p_index, pool));
   SVN_ERR(svn_io_file_close(context->proto_p2l_index, pool));
 
-  /* Create the actual index files*/
-  SVN_ERR(svn_fs_fs__l2p_index_create(context->fs, l2p_index_path,
-                                      proto_l2p_index_path,
-                                      context->shard_rev, pool));
-  SVN_ERR(svn_fs_fs__p2l_index_create(context->fs, p2l_index_path,
-                                      proto_p2l_index_path,
-                                      context->shard_rev, pool));
+  /* Append the actual index data to the pack file. */
+  SVN_ERR(svn_fs_fs__add_index_data(context->fs, context->pack_file,
+                                    proto_l2p_index_path,
+                                    proto_p2l_index_path,
+                                    context->shard_rev, 
+                                    pool));
 
   /* remove proto index files */
   SVN_ERR(svn_io_remove_file2(proto_l2p_index_path, FALSE, pool));
@@ -580,7 +573,7 @@ copy_rep_to_temp(pack_context_t *context
 
   /* read & parse the representation header */
   stream = svn_stream_from_aprfile2(rev_file, TRUE, pool);
-  SVN_ERR(svn_fs_fs__read_rep_header(&rep_header, stream, pool));
+  SVN_ERR(svn_fs_fs__read_rep_header(&rep_header, stream, pool, pool));
   svn_stream_close(stream);
 
   /* if the representation is a delta against some other rep, link the two */
@@ -723,7 +716,7 @@ copy_node_to_temp(pack_context_t *contex
 
   /* read & parse noderev */
   stream = svn_stream_from_aprfile2(rev_file, TRUE, pool);
-  SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, pool));
+  SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, pool, pool));
   svn_stream_close(stream);
 
   /* create a copy of ENTRY, make it point to the copy destination and
@@ -1294,26 +1287,21 @@ pack_range(pack_context_t *context,
   for (revision = context->start_rev; revision < context->end_rev; ++revision)
     {
       apr_off_t offset = 0;
-      apr_finfo_t finfo;
       svn_fs_fs__revision_file_t *rev_file;
-      const char *path;
 
       svn_pool_clear(revpool);
 
-      /* Get the size of the file. */
-      path = svn_dirent_join(context->shard_dir,
-                             apr_psprintf(revpool, "%ld", revision),
-                             revpool);
-      SVN_ERR(svn_io_stat(&finfo, path, APR_FINFO_SIZE, revpool));
+      /* Get the rev file dimensions (mainly index locations). */
       SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, context->fs,
                                                revision, revpool));
+      SVN_ERR(svn_fs_fs__auto_read_footer(rev_file));
 
       /* store the indirect array index */
       APR_ARRAY_PUSH(context->rev_offsets, int) = context->reps->nelts;
   
       /* read the phys-to-log index file until we covered the whole rev file.
        * That index contains enough info to build both target indexes from it. */
-      while (offset < finfo.size)
+      while (offset < rev_file->l2p_offset)
         {
           /* read one cluster */
           int i;
@@ -1339,7 +1327,7 @@ pack_range(pack_context_t *context,
 
               /* process entry while inside the rev file */
               offset = entry->offset;
-              if (offset < finfo.size)
+              if (offset < rev_file->l2p_offset)
                 {
                   SVN_ERR(svn_io_file_seek(rev_file->file, SEEK_SET, &offset,
                                            iterpool2));

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/recovery.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/recovery.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/recovery.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/recovery.c Tue Jun 24 21:29:59 2014
@@ -161,7 +161,7 @@ recover_find_max_ids(svn_fs_t *fs,
 
   baton.stream = rev_file->stream;
   SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &offset, pool));
-  SVN_ERR(svn_fs_fs__read_noderev(&noderev, baton.stream, pool));
+  SVN_ERR(svn_fs_fs__read_noderev(&noderev, baton.stream, pool, pool));
 
   /* Check that this is a directory.  It should be. */
   if (noderev->kind != svn_node_dir)
@@ -184,7 +184,7 @@ recover_find_max_ids(svn_fs_t *fs,
   SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rev_file, rev, NULL,
                                  noderev->data_rep->item_index, pool));
   SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &offset, pool));
-  SVN_ERR(svn_fs_fs__read_rep_header(&header, baton.stream, pool));
+  SVN_ERR(svn_fs_fs__read_rep_header(&header, baton.stream, pool, pool));
   if (header->type != svn_fs_fs__rep_plain)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Recovery encountered a deltified directory "
@@ -244,7 +244,7 @@ recover_find_max_ids(svn_fs_t *fs,
         return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                 _("Directory entry corrupt"));
 
-      id = svn_fs_fs__id_parse(str, strlen(str), iterpool);
+      id = svn_fs_fs__id_parse(str, iterpool);
 
       rev_item = svn_fs_fs__id_rev_item(id);
       if (rev_item->revision != rev)

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/rev_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/rev_file.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/rev_file.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/rev_file.c Tue Jun 24 21:29:59 2014
@@ -23,17 +23,18 @@
 #include "rev_file.h"
 #include "fs_fs.h"
 #include "index.h"
+#include "low_level.h"
 #include "util.h"
 
 #include "../libsvn_fs/fs-loader.h"
 
 #include "svn_private_config.h"
 
-void
-svn_fs_fs__init_revision_file(svn_fs_fs__revision_file_t *file,
-                              svn_fs_t *fs,
-                              svn_revnum_t revision,
-                              apr_pool_t *pool)
+static void
+init_revision_file(svn_fs_fs__revision_file_t *file,
+                   svn_fs_t *fs,
+                   svn_revnum_t revision,
+                   apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
 
@@ -46,6 +47,10 @@ svn_fs_fs__init_revision_file(svn_fs_fs_
   file->stream = NULL;
   file->p2l_stream = NULL;
   file->l2p_stream = NULL;
+  file->block_size = ffd->block_size;
+  file->l2p_offset = -1;
+  file->p2l_offset = -1;
+  file->footer_offset = -1;
   file->pool = pool;
 }
 
@@ -121,20 +126,46 @@ svn_fs_fs__open_pack_or_rev_file(svn_fs_
                                  apr_pool_t *pool)
 {
   *file = apr_palloc(pool, sizeof(**file));
-  svn_fs_fs__init_revision_file(*file, fs, rev, pool);
+  init_revision_file(*file, fs, rev, pool);
 
   return svn_error_trace(open_pack_or_rev_file(*file, fs, rev, pool));
 }
 
 svn_error_t *
-svn_fs_fs__reopen_revision_file(svn_fs_fs__revision_file_t *file,
-                                svn_fs_t *fs,
-                                svn_revnum_t rev)
+svn_fs_fs__auto_read_footer(svn_fs_fs__revision_file_t *file)
 {
-  if (file->file)
-    svn_fs_fs__close_revision_file(file);
+  if (file->l2p_offset == -1)
+    {
+      apr_off_t filesize = 0;
+      unsigned char footer_length;
+      svn_stringbuf_t *footer;
+
+      /* Determine file size. */
+      SVN_ERR(svn_io_file_seek(file->file, APR_END, &filesize, file->pool));
+
+      /* Read last byte (containing the length of the footer). */
+      SVN_ERR(svn_io_file_aligned_seek(file->file, file->block_size, NULL,
+                                       filesize - 1, file->pool));
+      SVN_ERR(svn_io_file_read_full2(file->file, &footer_length,
+                                     sizeof(footer_length), NULL, NULL,
+                                     file->pool));
+
+      /* Read footer. */
+      footer = svn_stringbuf_create_ensure(footer_length, file->pool);
+      SVN_ERR(svn_io_file_aligned_seek(file->file, file->block_size, NULL,
+                                       filesize - 1 - footer_length,
+                                       file->pool));
+      SVN_ERR(svn_io_file_read_full2(file->file, footer->data, footer_length,
+                                     &footer->len, NULL, file->pool));
+      footer->data[footer->len] = '\0';
+
+      /* Extract index locations. */
+      SVN_ERR(svn_fs_fs__parse_footer(&file->l2p_offset, &file->p2l_offset,
+                                      footer, file->start_revision));
+      file->footer_offset = filesize - footer_length - 1;
+    }
 
-  return svn_error_trace(open_pack_or_rev_file(file, fs, rev, file->pool));
+  return SVN_NO_ERROR;
 }
 
 svn_error_t *
@@ -165,9 +196,6 @@ svn_fs_fs__close_revision_file(svn_fs_fs
   if (file->file)
     SVN_ERR(svn_io_file_close(file->file, file->pool));
 
-  SVN_ERR(svn_fs_fs__packed_stream_close(file->l2p_stream));
-  SVN_ERR(svn_fs_fs__packed_stream_close(file->p2l_stream));
-
   file->file = NULL;
   file->stream = NULL;
   file->l2p_stream = NULL;

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/rev_file.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/rev_file.h?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/rev_file.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/rev_file.h Tue Jun 24 21:29:59 2014
@@ -38,7 +38,9 @@
 typedef struct svn_fs_fs__packed_number_stream_t
   svn_fs_fs__packed_number_stream_t;
 
-/* All files and associated properties for START_REVISION.
+/* Data file, including indexes data, and associated properties for
+ * START_REVISION.  As the FILE is kept open, background pack operations
+ * will not cause access to this file to fail.
  */
 typedef struct svn_fs_fs__revision_file_t
 {
@@ -49,31 +51,41 @@ typedef struct svn_fs_fs__revision_file_
   /* the revision was packed when the first file / stream got opened */
   svn_boolean_t is_packed;
 
-  /* rev / pack file or NULL if not opened, yet */
+  /* rev / pack file */
   apr_file_t *file;
 
   /* stream based on FILE and not NULL exactly when FILE is not NULL */
   svn_stream_t *stream;
 
-  /* the opened P2L index or NULL.  Always NULL for txns. */
+  /* the opened P2L index stream or NULL.  Always NULL for txns. */
   svn_fs_fs__packed_number_stream_t *p2l_stream;
 
-  /* the opened L2P index or NULL.  Always NULL for txns. */
+  /* the opened L2P index stream or NULL.  Always NULL for txns. */
   svn_fs_fs__packed_number_stream_t *l2p_stream;
 
+  /* Copied from FS->FFD->BLOCK_SIZE upon creation.  It allows us to
+   * use aligned seek() without having the FS handy. */
+  apr_off_t block_size;
+
+  /* Offset within FILE at which the rev data ends and the L2P index
+   * data starts. Less than P2L_OFFSET. -1 if svn_fs_fs__auto_read_footer
+   * has not been called, yet. */
+  apr_off_t l2p_offset;
+
+  /* Offset within FILE at which the L2P index ends and the P2L index
+   * data starts. Greater than L2P_OFFSET. -1 if svn_fs_fs__auto_read_footer
+   * has not been called, yet. */
+  apr_off_t p2l_offset;
+
+  /* Offset within FILE at which the P2L index ends and the footer starts.
+   * Greater than P2L_OFFSET. -1 if svn_fs_fs__auto_read_footer has not
+   * been called, yet. */
+  apr_off_t footer_offset;
+
   /* pool containing this object */
   apr_pool_t *pool;
 } svn_fs_fs__revision_file_t;
 
-/* Initialize the FILE data structure for REVISION in FS without actually
- * opening any files.  Use POOL for all future allocations in FILE.
- */
-void
-svn_fs_fs__init_revision_file(svn_fs_fs__revision_file_t *file,
-                              svn_fs_t *fs,
-                              svn_revnum_t revision,
-                              apr_pool_t *pool);
-
 /* Open the correct revision file for REV.  If the filesystem FS has
  * been packed, *FILE will be set to the packed file; otherwise, set *FILE
  * to the revision file for REV.  Return SVN_ERR_FS_NO_SUCH_REVISION if the
@@ -84,15 +96,13 @@ svn_fs_fs__open_pack_or_rev_file(svn_fs_
                                  svn_revnum_t rev,
                                  apr_pool_t *pool);
 
-/* Close previous files as well as streams in FILE (if open) and open the
- * rev / pack file for REVISION in FS.  This is useful when a pack operation
- * made the current files outdated or no longer available and the caller
- * wants to keep the same revision file data structure.
+/* If the footer data in FILE has not been read, yet, do so now.
+ * Index locations will only be read upon request as we assume they get
+ * cached and the FILE is usually used for REP data access only.
+ * Hence, the separate step.
  */
 svn_error_t *
-svn_fs_fs__reopen_revision_file(svn_fs_fs__revision_file_t *file,
-                                svn_fs_t *fs,
-                                svn_revnum_t revision);
+svn_fs_fs__auto_read_footer(svn_fs_fs__revision_file_t *file);
 
 /* Open the proto-rev file of transaction TXN_ID in FS and return it in *FILE.
  * Use POOL for allocations. */

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/temp_serializer.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/temp_serializer.c Tue Jun 24 21:29:59 2014
@@ -1148,18 +1148,15 @@ svn_fs_fs__serialize_changes(void **data
   svn_stringbuf_t *serialized;
   int i;
 
-  /* initialize our auxiliary data structure */
+  /* initialize our auxiliary data structure and link it to the
+   * array elements */
   changes.count = array->nelts;
-  changes.changes = apr_palloc(pool, sizeof(change_t*) * changes.count);
-
-  /* populate it with the array elements */
-  for (i = 0; i < changes.count; ++i)
-    changes.changes[i] = APR_ARRAY_IDX(array, i, change_t*);
+  changes.changes = (change_t **)array->elts;
 
   /* serialize it and all its elements */
   context = svn_temp_serializer__init(&changes,
                                       sizeof(changes),
-                                      changes.count * 100,
+                                      changes.count * 250,
                                       pool);
 
   svn_temp_serializer__push(context,
@@ -1188,19 +1185,21 @@ svn_fs_fs__deserialize_changes(void **ou
 {
   int i;
   changes_data_t *changes = (changes_data_t *)data;
-  apr_array_header_t *array = apr_array_make(pool, changes->count,
-                                             sizeof(change_t *));
+  apr_array_header_t *array = apr_array_make(pool, 0, sizeof(change_t *));
 
   /* de-serialize our auxiliary data structure */
   svn_temp_deserializer__resolve(changes, (void**)&changes->changes);
 
   /* de-serialize each entry and add it to the array */
   for (i = 0; i < changes->count; ++i)
-    {
-      deserialize_change(changes->changes,
-                         (change_t **)&changes->changes[i]);
-      APR_ARRAY_PUSH(array, change_t *) = changes->changes[i];
-    }
+    deserialize_change(changes->changes,
+                       (change_t **)&changes->changes[i]);
+
+  /* Use the changes buffer as the array's data buffer
+   * (DATA remains valid for at least as long as POOL). */
+  array->elts = (char *)changes->changes;
+  array->nelts = changes->count;
+  array->nalloc = changes->count;
 
   /* done */
   *out = array;