subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From i...@apache.org
Subject svn commit: r1639628 [9/23] - in /subversion/branches/svn-auth-x509: ./ build/ build/generator/ notes/ notes/api-errata/1.8/ notes/api-errata/1.9/ notes/wc-ng/ subversion/ subversion/bindings/ctypes-python/ subversion/bindings/cxxhl/ subversion/binding...
Date Fri, 14 Nov 2014 13:18:03 GMT
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/cached_data.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/cached_data.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/cached_data.c Fri Nov 14 13:17:55 2014
@@ -48,12 +48,12 @@
 
 #include "svn_private_config.h"
 
-/* forward-declare */
+/* forward-declare. See implementation for the docstring */
 static svn_error_t *
 block_read(void **result,
            svn_fs_t *fs,
            const svn_fs_x__id_part_t *id,
-           apr_file_t *revision_file,
+           svn_fs_x__revision_file_t *revision_file,
            apr_pool_t *result_pool,
            apr_pool_t *scratch_pool);
 
@@ -70,7 +70,7 @@ static svn_error_t *
 dgb__log_access(svn_fs_t *fs,
                 const svn_fs_x__id_part_t *id,
                 void *item,
-                int item_type,
+                apr_uint32_t item_type,
                 apr_pool_t *scratch_pool)
 {
   /* no-op if this macro is not defined */
@@ -192,21 +192,21 @@ aligned_seek(svn_fs_t *fs,
    store the newly opened file in FILE.  Seek to the item's location before
    returning.  Perform temporary allocations in POOL. */
 static svn_error_t *
-open_and_seek_revision(apr_file_t **file,
+open_and_seek_revision(svn_fs_x__revision_file_t **file,
                        svn_fs_t *fs,
                        const svn_fs_x__id_part_t *id,
                        apr_pool_t *pool)
 {
-  apr_file_t *rev_file;
+  svn_fs_x__revision_file_t *rev_file;
   apr_off_t offset = -1;
   apr_uint32_t sub_item = 0;
   svn_revnum_t rev = svn_fs_x__get_revnum(id->change_set);
 
   SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, pool));
 
-  SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, rev, pool));
-  SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, id, pool));
-  SVN_ERR(aligned_seek(fs, rev_file, NULL, offset, pool));
+  SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, rev, pool, pool));
+  SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, rev_file, id, pool));
+  SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, pool));
 
   *file = rev_file;
 
@@ -217,24 +217,20 @@ open_and_seek_revision(apr_file_t **file
    to its position and store the newly opened file in FILE.  Perform
    temporary allocations in POOL. */
 static svn_error_t *
-open_and_seek_transaction(apr_file_t **file,
+open_and_seek_transaction(svn_fs_x__revision_file_t **file,
                           svn_fs_t *fs,
                           representation_t *rep,
                           apr_pool_t *pool)
 {
-  apr_file_t *rev_file;
   apr_off_t offset;
   apr_uint32_t sub_item = 0;
   apr_int64_t txn_id = svn_fs_x__get_txn_id(rep->id.change_set);
 
-  SVN_ERR(svn_io_file_open(&rev_file,
-                           svn_fs_x__path_txn_proto_rev(fs, txn_id, pool),
-                           APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
+  SVN_ERR(svn_fs_x__open_proto_rev_file(file, fs, txn_id, pool, pool));
 
-  SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, &rep->id, pool));
-  SVN_ERR(aligned_seek(fs, rev_file, NULL, offset, pool));
-
-  *file = rev_file;
+  SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, *file, &rep->id,
+                                pool));
+  SVN_ERR(aligned_seek(fs, (*file)->file, NULL, offset, pool));
 
   return SVN_NO_ERROR;
 }
@@ -243,7 +239,7 @@ open_and_seek_transaction(apr_file_t **f
    the correct file and seek to the correction location.  Store this
    file in *FILE_P.  Perform any allocations in POOL. */
 static svn_error_t *
-open_and_seek_representation(apr_file_t **file_p,
+open_and_seek_representation(svn_fs_x__revision_file_t **file_p,
                              svn_fs_t *fs,
                              representation_t *rep,
                              apr_pool_t *pool)
@@ -274,20 +270,24 @@ static svn_error_t *
 get_node_revision_body(node_revision_t **noderev_p,
                        svn_fs_t *fs,
                        const svn_fs_id_t *id,
-                       apr_pool_t *pool)
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
 {
-  apr_file_t *revision_file;
   svn_error_t *err;
   svn_boolean_t is_cached = FALSE;
   fs_x_data_t *ffd = fs->fsap_data;
 
   if (svn_fs_x__id_is_txn(id))
     {
+      apr_file_t *file;
+
       /* This is a transaction node-rev.  Its storage logic is very
          different from that of rev / pack files. */
-      err = svn_io_file_open(&revision_file,
-                             svn_fs_x__path_txn_node_rev(fs, id, pool),
-                             APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
+      err = svn_io_file_open(&file,
+                             svn_fs_x__path_txn_node_rev(fs, id,
+                                                         scratch_pool),
+                             APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
+                             scratch_pool);
       if (err)
         {
           if (APR_STATUS_IS_ENOENT(err->apr_err))
@@ -300,33 +300,38 @@ get_node_revision_body(node_revision_t *
         }
 
       SVN_ERR(svn_fs_x__read_noderev(noderev_p,
-                                     svn_stream_from_aprfile2(revision_file,
+                                     svn_stream_from_aprfile2(file,
                                                               FALSE,
-                                                              pool),
-                                     pool));
+                                                              scratch_pool),
+                                     result_pool, scratch_pool));
     }
   else
     {
+      svn_fs_x__revision_file_t *revision_file;
+
       /* noderevs in rev / pack files can be cached */
       const svn_fs_x__id_part_t *noderev_id = svn_fs_x__id_noderev_id(id);
       svn_revnum_t revision = svn_fs_x__get_revnum(noderev_id->change_set);
       pair_cache_key_t key;
 
+      SVN_ERR(svn_fs_x__open_pack_or_rev_file(&revision_file, fs, revision,
+                                              scratch_pool, scratch_pool));
+
       /* First, try a noderevs container cache lookup. */
       if (   svn_fs_x__is_packed_rev(fs, revision)
           && ffd->noderevs_container_cache)
         {
           apr_off_t offset;
           apr_uint32_t sub_item;
-          SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, noderev_id,
-                                        pool));
+          SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, revision_file,
+                                        noderev_id, scratch_pool));
           key.revision = svn_fs_x__packed_base_rev(fs, revision);
           key.second = offset;
 
           SVN_ERR(svn_cache__get_partial((void **)noderev_p, &is_cached,
                                          ffd->noderevs_container_cache, &key, 
                                          svn_fs_x__noderevs_get_func,
-                                         &sub_item, pool));
+                                         &sub_item, result_pool));
           if (is_cached)
             return SVN_NO_ERROR;
         }
@@ -342,22 +347,23 @@ get_node_revision_body(node_revision_t *
                                  &is_cached,
                                  ffd->node_revision_cache,
                                  &key,
-                                 pool));
+                                 result_pool));
           if (is_cached)
             return SVN_NO_ERROR;
         }
 
-      /* someone needs to read the data from this file: */
-      err = open_and_seek_revision(&revision_file, fs, noderev_id, pool);
+      /* read the data from disk */
+      SVN_ERR(open_and_seek_revision(&revision_file, fs, noderev_id,
+                                     scratch_pool));
 
       /* block-read will parse the whole block and will also return
-          the one noderev that we need right now. */
+         the one noderev that we need right now. */
       SVN_ERR(block_read((void **)noderev_p, fs,
                          noderev_id,
                          revision_file,
-                         pool,
-                         pool));
-      SVN_ERR(svn_io_file_close(revision_file, pool));
+                         result_pool,
+                         scratch_pool));
+      SVN_ERR(svn_fs_x__close_revision_file(revision_file));
     }
 
   return SVN_NO_ERROR;
@@ -367,21 +373,23 @@ svn_error_t *
 svn_fs_x__get_node_revision(node_revision_t **noderev_p,
                             svn_fs_t *fs,
                             const svn_fs_id_t *id,
-                            apr_pool_t *pool)
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
 {
   const svn_fs_x__id_part_t *noderev_id = svn_fs_x__id_noderev_id(id);
 
-  svn_error_t *err = get_node_revision_body(noderev_p, fs, id, pool);
+  svn_error_t *err = get_node_revision_body(noderev_p, fs, id,
+                                            result_pool, scratch_pool);
   if (err && err->apr_err == SVN_ERR_FS_CORRUPT)
     {
-      svn_string_t *id_string = svn_fs_x__id_unparse(id, pool);
+      svn_string_t *id_string = svn_fs_x__id_unparse(id, scratch_pool);
       return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
                                "Corrupt node-revision '%s'",
                                id_string->data);
     }
 
   SVN_ERR(dgb__log_access(fs, noderev_id, *noderev_p,
-                          SVN_FS_X__ITEM_TYPE_NODEREV, pool));
+                          SVN_FS_X__ITEM_TYPE_NODEREV, scratch_pool));
 
   return svn_error_trace(err);
 }
@@ -407,6 +415,10 @@ svn_fs_x__get_mergeinfo_count(apr_int64_
       fs_x_data_t *ffd = fs->fsap_data;
       svn_revnum_t revision = svn_fs_x__get_revnum(noderev_id->change_set);
 
+      svn_fs_x__revision_file_t *rev_file;
+      SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, revision, pool,
+                                              pool));
+
       if (   svn_fs_x__is_packed_rev(fs, revision)
           && ffd->noderevs_container_cache)
         {
@@ -415,7 +427,7 @@ svn_fs_x__get_mergeinfo_count(apr_int64_
           apr_uint32_t sub_item;
           svn_boolean_t is_cached;
 
-          SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs,
+          SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, rev_file,
                                         noderev_id, pool));
           key.revision = svn_fs_x__packed_base_rev(fs, revision);
           key.second = offset;
@@ -431,7 +443,7 @@ svn_fs_x__get_mergeinfo_count(apr_int64_
 #endif
 
   /* fallback to the naive implementation handling all edge cases */
-  SVN_ERR(svn_fs_x__get_node_revision(&noderev, fs, id, pool));
+  SVN_ERR(svn_fs_x__get_node_revision(&noderev, fs, id, pool, pool));
   *count = noderev->mergeinfo_count;
 
   return SVN_NO_ERROR;
@@ -442,10 +454,11 @@ svn_error_t *
 svn_fs_x__rev_get_root(svn_fs_id_t **root_id_p,
                        svn_fs_t *fs,
                        svn_revnum_t rev,
-                       apr_pool_t *pool)
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
 {
-  SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, pool));
-  *root_id_p = svn_fs_x__id_create_root(rev, pool);
+  SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool));
+  *root_id_p = svn_fs_x__id_create_root(rev, result_pool);
 
   return SVN_NO_ERROR;
 }
@@ -455,15 +468,13 @@ svn_fs_x__rev_get_root(svn_fs_id_t **roo
 typedef struct shared_file_t
 {
   /* The opened file. NULL while file is not open, yet. */
-  apr_file_t *file;
-
-  /* Stream wrapper around FILE. NULL while file is not open, yet. */
-  svn_stream_t *stream;
+  svn_fs_x__revision_file_t *rfile;
 
   /* file system to open the file in */
   svn_fs_t *fs;
 
-  /* revision contained in the file */
+  /* a revision contained in the FILE.  Since this file may be shared,
+     that value may be different from REP_STATE_T->REVISION. */
   svn_revnum_t revision;
 
   /* pool to use when creating the FILE.  This guarantees that the file
@@ -477,7 +488,7 @@ typedef struct shared_file_t
 typedef struct rep_state_t
 {
                     /* shared lazy-open rev/pack file structure */
-  shared_file_t *file;
+  shared_file_t *sfile;
                     /* The txdelta window cache to use or NULL. */
   svn_cache__t *window_cache;
                     /* Caches un-deltified windows. May be NULL. */
@@ -490,16 +501,96 @@ typedef struct rep_state_t
   apr_size_t header_size;
   apr_off_t start;  /* The starting offset for the raw
                        svndiff data minus header.
-                       -1 if the offset is yet unknwon. */
+                       -1 if the offset is yet unknown. */
                     /* sub-item index in case the rep is containered */
   apr_uint32_t sub_item;
-  apr_off_t current;/* The current offset relative to start. */
-  apr_off_t size;   /* Final value of CURRENT. */
+  apr_off_t current;/* The current offset relative to START. */
+  apr_off_t size;   /* The on-disk size of the representation. */
   int ver;          /* If a delta, what svndiff version? 
                        -1 for unknown delta version. */
   int chunk_index;  /* number of the window to read */
 } rep_state_t;
 
+/* Simple wrapper around svn_fs_x__get_file_offset to simplify callers. */
+static svn_error_t *
+get_file_offset(apr_off_t *offset,
+                rep_state_t *rs,
+                apr_pool_t *pool)
+{
+  return svn_error_trace(svn_fs_x__get_file_offset(offset,
+                                                   rs->sfile->rfile->file,
+                                                   pool));
+}
+
+/* Simple wrapper around svn_io_file_aligned_seek to simplify callers. */
+static svn_error_t *
+rs_aligned_seek(rep_state_t *rs,
+                apr_off_t *buffer_start,
+                apr_off_t offset,
+                apr_pool_t *pool)
+{
+  fs_x_data_t *ffd = rs->sfile->fs->fsap_data;
+  return svn_error_trace(svn_io_file_aligned_seek(rs->sfile->rfile->file,
+                                                  ffd->block_size,
+                                                  buffer_start, offset,
+                                                  pool));
+}
+
+/* Open FILE->FILE and FILE->STREAM if they haven't been opened, yet. */
+static svn_error_t*
+auto_open_shared_file(shared_file_t *file)
+{
+  if (file->rfile == NULL)
+    SVN_ERR(svn_fs_x__open_pack_or_rev_file(&file->rfile, file->fs,
+                                            file->revision, file->pool,
+                                            file->pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Set RS->START to the begin of the representation raw in RS->SFILE->RFILE,
+   if that hasn't been done yet.  Use POOL for temporary allocations. */
+static svn_error_t*
+auto_set_start_offset(rep_state_t *rs, apr_pool_t *pool)
+{
+  if (rs->start == -1)
+    {
+      SVN_ERR(svn_fs_x__item_offset(&rs->start, &rs->sub_item,
+                                    rs->sfile->fs, rs->sfile->rfile,
+                                    &rs->rep_id, pool));
+      rs->start += rs->header_size;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Set RS->VER depending on what is found in the already open RS->FILE->FILE
+   if the diff version is still unknown.  Use POOL for temporary allocations.
+ */
+static svn_error_t*
+auto_read_diff_version(rep_state_t *rs, apr_pool_t *pool)
+{
+  if (rs->ver == -1)
+    {
+      char buf[4];
+      SVN_ERR(rs_aligned_seek(rs, NULL, rs->start, pool));
+      SVN_ERR(svn_io_file_read_full2(rs->sfile->rfile->file, buf,
+                                     sizeof(buf), NULL, NULL, pool));
+
+      /* ### Layering violation */
+      if (! ((buf[0] == 'S') && (buf[1] == 'V') && (buf[2] == 'N')))
+        return svn_error_create
+          (SVN_ERR_FS_CORRUPT, NULL,
+           _("Malformed svndiff data in representation"));
+      rs->ver = buf[3];
+
+      rs->chunk_index = 0;
+      rs->current = 4;
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* See create_rep_state, which wraps this and adds another error. */
 static svn_error_t *
 create_rep_state_body(rep_state_t **rep_state,
@@ -507,10 +598,11 @@ create_rep_state_body(rep_state_t **rep_
                       shared_file_t **shared_file,
                       representation_t *rep,
                       svn_fs_t *fs,
-                      apr_pool_t *pool)
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
-  rep_state_t *rs = apr_pcalloc(pool, sizeof(*rs));
+  rep_state_t *rs = apr_pcalloc(result_pool, sizeof(*rs));
   svn_fs_x__rep_header_t *rh;
   svn_boolean_t is_cached = FALSE;
   svn_revnum_t revision = svn_fs_x__get_revnum(rep->id.change_set);
@@ -525,7 +617,7 @@ create_rep_state_body(rep_state_t **rep_
    * we can re-use the same, already open file object
    */
   svn_boolean_t reuse_shared_file
-    =    shared_file && *shared_file && (*shared_file)->file
+    =    shared_file && *shared_file && (*shared_file)->rfile
       && SVN_IS_VALID_REVNUM((*shared_file)->revision)
       && (*shared_file)->revision < ffd->min_unpacked_rev
       && revision < ffd->min_unpacked_rev
@@ -567,116 +659,109 @@ create_rep_state_body(rep_state_t **rep_
   /* cache lookup, i.e. skip reading the rep header if possible */
   if (ffd->rep_header_cache && SVN_IS_VALID_REVNUM(revision))
     SVN_ERR(svn_cache__get((void **) &rh, &is_cached,
-                           ffd->rep_header_cache, &key, pool));
+                           ffd->rep_header_cache, &key, result_pool));
 
-  if (is_cached)
+  /* initialize the (shared) FILE member in RS */
+  if (reuse_shared_file)
     {
-      if (reuse_shared_file)
-        {
-          rs->file = *shared_file;
-        }
-      else
-        {
-          shared_file_t *file = apr_pcalloc(pool, sizeof(*file));
-          SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
-
-          file->revision = revision;
-          file->pool = pool;
-          file->fs = fs;
-          rs->file = file;
-
-          /* remember the current file, if suggested by the caller */
-          if (shared_file)
-            *shared_file = file;
-        }
+      rs->sfile = *shared_file;
     }
   else
     {
+      shared_file_t *file = apr_pcalloc(result_pool, sizeof(*file));
+      file->revision = revision;
+      file->pool = result_pool;
+      file->fs = fs;
+      rs->sfile = file;
+
+      /* remember the current file, if suggested by the caller */
+      if (shared_file)
+        *shared_file = file;
+    }
+
+  /* read rep header, if necessary */
+  if (!is_cached)
+    {
       /* we will need the on-disk location for non-txn reps */
       apr_off_t offset;
       apr_uint32_t sub_item;
+      svn_boolean_t in_container = TRUE;
 
-      if (SVN_IS_VALID_REVNUM(revision))
-        SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, &rep->id, pool));
+      /* ensure file is open and navigate to the start of rep header */
+      if (reuse_shared_file)
+        {
+          /* ... we can re-use the same, already open file object.
+           * This implies that we don't read from a txn.
+           */
+          SVN_ERR_ASSERT(sub_item == 0);
+          rs->sfile = *shared_file;
+          SVN_ERR(auto_open_shared_file(rs->sfile));
+        }
+      else
+        {
+          /* otherwise, create a new file object.  May or may not be
+           * an in-txn file.
+           */
+          SVN_ERR(open_and_seek_representation(&rs->sfile->rfile, fs, rep,
+                                               result_pool));
+        }
 
-      /* is rep stored in some star-deltified container? */
       if (SVN_IS_VALID_REVNUM(revision))
         {
-          svn_boolean_t in_container = TRUE;
+          SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs,
+                                        rs->sfile->rfile, &rep->id,
+                                        scratch_pool));
+
+          /* is rep stored in some star-deltified container? */
           if (sub_item == 0)
             {
               svn_fs_x__p2l_entry_t *entry;
-              SVN_ERR(svn_fs_x__p2l_entry_lookup(&entry, fs, revision,
-                                                 offset, pool));
+              SVN_ERR(svn_fs_x__p2l_entry_lookup(&entry, fs, rs->sfile->rfile,
+                                                 revision, offset,
+                                                 scratch_pool, scratch_pool));
               in_container = entry->type == SVN_FS_X__ITEM_TYPE_REPS_CONT;
             }
 
           if (in_container)
             {
               /* construct a container rep header */
-              *rep_header = apr_pcalloc(pool, sizeof(**rep_header));
+              *rep_header = apr_pcalloc(result_pool, sizeof(**rep_header));
               (*rep_header)->type = svn_fs_x__rep_container;
 
-              /* provide an empty shared file struct */
-              rs->file = apr_pcalloc(pool, sizeof(*rs->file));
-              rs->file->revision = revision;
-              rs->file->pool = pool;
-              rs->file->fs = fs;
-
               /* exit to caller */
               *rep_state = rs;
               return SVN_NO_ERROR;
             }
-        }
 
-      if (reuse_shared_file)
-        {
-          /* ... we can re-use the same, already open file object
-           */
-          SVN_ERR_ASSERT(sub_item == 0);
-          SVN_ERR(aligned_seek(fs, (*shared_file)->file, NULL, offset, pool));
-
-          rs->file = *shared_file;
-        }
-      else
-        {
-          shared_file_t *file = apr_pcalloc(pool, sizeof(*file));
-          file->revision = revision;
-          file->pool = pool;
-          file->fs = fs;
-
-          /* otherwise, create a new file object
-           */
-          SVN_ERR(open_and_seek_representation(&file->file, fs, rep, pool));
-          file->stream = svn_stream_from_aprfile2(file->file, TRUE,
-                                                  file->pool);
-          rs->file = file;
-
-          /* remember the current file, if suggested by the caller */
-          if (shared_file)
-            *shared_file = file;
+          SVN_ERR(rs_aligned_seek(rs, NULL, offset, scratch_pool));
         }
 
-      SVN_ERR(svn_fs_x__read_rep_header(&rh, rs->file->stream, pool));
-      SVN_ERR(svn_fs_x__get_file_offset(&rs->start, rs->file->file, pool));
+      SVN_ERR(svn_fs_x__read_rep_header(&rh, rs->sfile->rfile->stream,
+                                        result_pool, scratch_pool));
+      SVN_ERR(get_file_offset(&rs->start, rs, result_pool));
 
+      /* populate the cache if appropriate */
       if (SVN_IS_VALID_REVNUM(revision))
         {
-          SVN_ERR(block_read(NULL, fs, &rs->rep_id, rs->file->file, pool, pool));
+          SVN_ERR(block_read(NULL, fs, &rs->rep_id, rs->sfile->rfile,
+                             result_pool, scratch_pool));
           if (ffd->rep_header_cache)
-            SVN_ERR(svn_cache__set(ffd->rep_header_cache, &key, rh, pool));
+            SVN_ERR(svn_cache__set(ffd->rep_header_cache, &key, rh,
+                                   scratch_pool));
         }
     }
 
+  /* finalize */
   SVN_ERR(dgb__log_access(fs, &rs->rep_id, rh, SVN_FS_X__ITEM_TYPE_ANY_REP,
-                          pool));
+                          scratch_pool));
 
   rs->header_size = rh->header_size;
   *rep_state = rs;
   *rep_header = rh;
 
-  /* We are dealing with a delta, find out what version. */
   rs->chunk_index = 0;
+
+  /* skip "SVNx" diff marker */
   rs->current = 4;
 
   return SVN_NO_ERROR;
@@ -699,14 +784,14 @@ create_rep_state(rep_state_t **rep_state
                  shared_file_t **shared_file,
                  representation_t *rep,
                  svn_fs_t *fs,
-                 apr_pool_t *pool)
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
   svn_error_t *err = create_rep_state_body(rep_state, rep_header,
-                                           shared_file, rep, fs, pool);
+                                           shared_file, rep, fs,
+                                           result_pool, scratch_pool);
   if (err && err->apr_err == SVN_ERR_FS_CORRUPT)
     {
-      fs_x_data_t *ffd = fs->fsap_data;
-
       /* ### This always returns "-1" for transaction reps, because
          ### this particular bit of code doesn't know if the rep is
          ### stored in the protorev or in the mutable area (for props
@@ -718,7 +803,8 @@ create_rep_state(rep_state_t **rep_state
                                "Corrupt representation '%s'",
                                rep
                                ? svn_fs_x__unparse_representation
-                                   (rep, ffd->format, TRUE, pool)->data
+                                   (rep, TRUE, scratch_pool,
+                                    scratch_pool)->data
                                : "(null)");
     }
   /* ### Call representation_string() ? */
@@ -728,18 +814,24 @@ create_rep_state(rep_state_t **rep_state
 svn_error_t *
 svn_fs_x__check_rep(representation_t *rep,
                     svn_fs_t *fs,
-                    apr_pool_t *pool)
+                    apr_pool_t *scratch_pool)
 {
   apr_off_t offset;
   apr_uint32_t sub_item;
   svn_fs_x__p2l_entry_t *entry;
   svn_revnum_t revision = svn_fs_x__get_revnum(rep->id.change_set);
 
+  svn_fs_x__revision_file_t *rev_file;
+  SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, revision,
+                                          scratch_pool, scratch_pool));
+
   /* Does REP->ID refer to an actual item? Which one is it? */
-  SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, &rep->id, pool));
+  SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, rev_file, &rep->id,
+                                scratch_pool));
 
   /* What is the type of that item? */
-  SVN_ERR(svn_fs_x__p2l_entry_lookup(&entry, fs, revision, offset, pool));
+  SVN_ERR(svn_fs_x__p2l_entry_lookup(&entry, fs, rev_file, revision, offset,
+                                     scratch_pool, scratch_pool));
 
   /* Verify that we've got an item that is actually a representation. */
   if (   entry == NULL
@@ -751,8 +843,8 @@ svn_fs_x__check_rep(representation_t *re
     return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, NULL,
                              _("No representation found at offset %s "
                                "for item %s in revision %ld"),
-                             apr_off_t_toa(pool, offset),
-                             apr_psprintf(pool, "%" APR_UINT64_T_FMT,
+                             apr_off_t_toa(scratch_pool, offset),
+                             apr_psprintf(scratch_pool, "%" APR_UINT64_T_FMT,
                                           rep->id.number),
                              revision);
 
@@ -766,19 +858,22 @@ svn_fs_x__rep_chain_length(int *chain_le
                            int *shard_count,
                            representation_t *rep,
                            svn_fs_t *fs,
-                           apr_pool_t *pool)
+                           apr_pool_t *scratch_pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
-  svn_revnum_t shard_size = ffd->max_files_per_dir
-                          ? ffd->max_files_per_dir
-                          : 1;
-  apr_pool_t *sub_pool = svn_pool_create(pool);
+  svn_revnum_t shard_size = ffd->max_files_per_dir;
   svn_boolean_t is_delta = FALSE;
   int count = 0;
   int shards = 1;
   svn_revnum_t revision = svn_fs_x__get_revnum(rep->id.change_set);
   svn_revnum_t last_shard = revision / shard_size;
-  
+
+  /* Note that this iteration pool will be used in a non-standard way.
+   * To reuse open file handles between iterations (e.g. while within the
+   * same pack file), we only clear this pool once in a while instead of
+   * at the start of each iteration. */
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
   /* Check whether the length of the deltification chain is acceptable.
    * Otherwise, shared reps may form a non-skipping delta chain in
    * extreme cases. */
@@ -806,7 +901,8 @@ svn_fs_x__rep_chain_length(int *chain_le
                                     &file_hint,
                                     &base_rep,
                                     fs,
-                                    sub_pool));
+                                    iterpool,
+                                    iterpool));
 
       base_rep.id.change_set
         = svn_fs_x__change_set_by_rev(header->base_revision);
@@ -814,18 +910,28 @@ svn_fs_x__rep_chain_length(int *chain_le
       base_rep.size = header->base_length;
       is_delta = header->type == svn_fs_x__rep_delta;
 
+      /* Clear it the ITERPOOL once in a while.  Doing it too frequently
+       * renders the FILE_HINT ineffective.  Doing too infrequently, may
+       * leave us with too many open file handles.
+       *
+       * Note that this is mostly about efficiency, with larger values
+       * being more efficient, and any non-zero value is legal here.  When
+       * reading deltified contents, we may keep 10s of rev files open at
+       * the same time and the system has to cope with that.  Thus, the
+       * limit of 16 chosen below is in the same ballpark.
+       */
       ++count;
       if (count % 16 == 0)
         {
           file_hint = NULL;
-          svn_pool_clear(sub_pool);
+          svn_pool_clear(iterpool);
         }
     }
   while (is_delta && base_rep.id.change_set);
 
   *chain_length = count;
   *shard_count = shards;
-  svn_pool_destroy(sub_pool);
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
@@ -955,9 +1061,14 @@ get_cached_window_sizes_func(void **out,
   return SVN_NO_ERROR;
 }
 
-/* Return the packed & expanded sizes of the window addressed by RS.  If the
- * window cannot be found in the window cache, set *IS_CACHED to FALSE.
- * Otherwise, set it to TRUE and return the data in *SIZES, allocated in POOL.
+/* Read the WINDOW_P number CHUNK_INDEX for the representation given in
+ * rep state RS from the current FSFS session's cache.  This will be a
+ * no-op and IS_CACHED will be set to FALSE if no cache has been given.
+ * If a cache is available IS_CACHED will inform the caller about the
+ * success of the lookup. Allocations of the window in will be made
+ * from RESULT_POOL. Use SCRATCH_POOL for temporary allocations.
+ *
+ * If the information could be found, put RS to CHUNK_INDEX.
  */
 static svn_error_t *
 get_cached_window_sizes(window_sizes_t **sizes,
@@ -990,7 +1101,8 @@ get_cached_window(svn_txdelta_window_t *
                   rep_state_t *rs,
                   int chunk_index,
                   svn_boolean_t *is_cached,
-                  apr_pool_t *pool)
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
 {
   if (! rs->window_cache)
     {
@@ -1008,7 +1120,7 @@ get_cached_window(svn_txdelta_window_t *
                              is_cached,
                              rs->window_cache,
                              &key,
-                             pool));
+                             result_pool));
 
       if (*is_cached)
         {
@@ -1131,19 +1243,23 @@ build_rep_list(apr_array_header_t **list
   svn_fs_x__rep_header_t *rep_header;
   svn_boolean_t is_cached = FALSE;
   shared_file_t *shared_file = NULL;
+  apr_pool_t *iterpool = svn_pool_create(pool);
 
   *list = apr_array_make(pool, 1, sizeof(rep_state_t *));
   rep = *first_rep;
 
   /* for the top-level rep, we need the rep_args */
-  SVN_ERR(create_rep_state(&rs, &rep_header, &shared_file, &rep, fs, pool));
+  SVN_ERR(create_rep_state(&rs, &rep_header, &shared_file, &rep, fs, pool,
+                           iterpool));
 
   while (1)
     {
+      svn_pool_clear(iterpool);
+
       /* fetch state, if that has not been done already */
       if (!rs)
         SVN_ERR(create_rep_state(&rs, &rep_header, &shared_file,
-                                 &rep, fs, pool));
+                                 &rep, fs, pool, iterpool));
 
       /* for txn reps and containered reps, there won't be a cached
        * combined window */
@@ -1159,14 +1275,14 @@ build_rep_list(apr_array_header_t **list
           rs->current = 0;
           rs->size = (*window_p)->len;
           *src_state = rs;
-          return SVN_NO_ERROR;
+          break;
         }
 
       if (rep_header->type == svn_fs_x__rep_container)
         {
           /* This is a container item, so just return the current rep_state. */
           *src_state = rs;
-          return SVN_NO_ERROR;
+          break;
         }
 
       /* Push this rep onto the list.  If it's self-compressed, we're done. */
@@ -1174,7 +1290,7 @@ build_rep_list(apr_array_header_t **list
       if (rep_header->type == svn_fs_x__rep_self_delta)
         {
           *src_state = NULL;
-          return SVN_NO_ERROR;
+          break;
         }
 
       rep.id.change_set
@@ -1184,6 +1300,9 @@ build_rep_list(apr_array_header_t **list
 
       rs = NULL;
     }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -1225,84 +1344,31 @@ rep_read_get_baton(struct rep_read_baton
   return SVN_NO_ERROR;
 }
 
-/* Open FILE->FILE and FILE->STREAM if they haven't been opened, yet. */
-static svn_error_t*
-auto_open_shared_file(shared_file_t *file)
-{
-  if (file->file == NULL)
-    {
-      SVN_ERR(svn_fs_x__open_pack_or_rev_file(&file->file, file->fs,
-                                              file->revision, file->pool));
-      file->stream = svn_stream_from_aprfile2(file->file, TRUE, file->pool);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/* Set RS->START to the begin of the representation raw in RS->FILE->FILE,
-   if that hasn't been done yet.  Use POOL for temporary allocations. */
-static svn_error_t*
-auto_set_start_offset(rep_state_t *rs, apr_pool_t *pool)
-{
-  if (rs->start == -1)
-    {
-      SVN_ERR(svn_fs_x__item_offset(&rs->start, &rs->sub_item,
-                                    rs->file->fs, &rs->rep_id, pool));
-      rs->start += rs->header_size;
-    }
-
-  return SVN_NO_ERROR;
-}
-
-/* Set RS->VER depending on what is found in the already open RS->FILE->FILE
-   if the diff version is still unknown.  Use POOL for temporary allocations.
- */
-static svn_error_t*
-auto_read_diff_version(rep_state_t *rs, apr_pool_t *pool)
-{
-  if (rs->ver == -1)
-    {
-      char buf[4];
-      SVN_ERR(aligned_seek(rs->file->fs, rs->file->file, NULL, rs->start,
-                           pool));
-      SVN_ERR(svn_io_file_read_full2(rs->file->file, buf, sizeof(buf),
-                                     NULL, NULL, pool));
-
-      /* ### Layering violation */
-      if (! ((buf[0] == 'S') && (buf[1] == 'V') && (buf[2] == 'N')))
-        return svn_error_create
-          (SVN_ERR_FS_CORRUPT, NULL,
-           _("Malformed svndiff data in representation"));
-      rs->ver = buf[3];
-
-      rs->chunk_index = 0;
-      rs->current = 4;
-    }
-
-  return SVN_NO_ERROR;
-}
-
 /* Skip forwards to THIS_CHUNK in REP_STATE and then read the next delta
    window into *NWIN. */
 static svn_error_t *
 read_delta_window(svn_txdelta_window_t **nwin, int this_chunk,
-                  rep_state_t *rs, apr_pool_t *pool)
+                  rep_state_t *rs, apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
 {
   svn_boolean_t is_cached;
   apr_off_t start_offset;
   apr_off_t end_offset;
+  apr_pool_t *iterpool;
+
   SVN_ERR_ASSERT(rs->chunk_index <= this_chunk);
 
-  SVN_ERR(dgb__log_access(rs->file->fs, &rs->rep_id, NULL,
-                          SVN_FS_X__ITEM_TYPE_ANY_REP, pool));
+  SVN_ERR(dgb__log_access(rs->sfile->fs, &rs->rep_id, NULL,
+                          SVN_FS_X__ITEM_TYPE_ANY_REP, scratch_pool));
 
   /* Read the next window.  But first, try to find it in the cache. */
-  SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached, pool));
+  SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached,
+                            result_pool, scratch_pool));
   if (is_cached)
     return SVN_NO_ERROR;
 
   /* someone has to actually read the data from file.  Open it */
-  SVN_ERR(auto_open_shared_file(rs->file));
+  SVN_ERR(auto_open_shared_file(rs->sfile));
 
   /* invoke the 'block-read' feature for non-txn data.
      However, don't do that if we are in the middle of some representation,
@@ -1311,34 +1377,38 @@ read_delta_window(svn_txdelta_window_t *
       && svn_fs_x__is_revision(rs->rep_id.change_set)
       && rs->window_cache)
     {
-      SVN_ERR(block_read(NULL, rs->file->fs, &rs->rep_id, rs->file->file,
-                         pool, pool));
+      SVN_ERR(block_read(NULL, rs->sfile->fs, &rs->rep_id,
+                         rs->sfile->rfile, result_pool, scratch_pool));
 
       /* reading the whole block probably also provided us with the
          desired txdelta window */
-      SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached, pool));
+      SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached,
+                                result_pool, scratch_pool));
       if (is_cached)
         return SVN_NO_ERROR;
     }
 
   /* data is still not cached -> we need to read it.
      Make sure we have all the necessary info. */
-  SVN_ERR(auto_set_start_offset(rs, pool));
-  SVN_ERR(auto_read_diff_version(rs, pool));
+  SVN_ERR(auto_set_start_offset(rs, scratch_pool));
+  SVN_ERR(auto_read_diff_version(rs, scratch_pool));
 
   /* RS->FILE may be shared between RS instances -> make sure we point
    * to the right data. */
   start_offset = rs->start + rs->current;
-  SVN_ERR(aligned_seek(rs->file->fs, rs->file->file, NULL, start_offset,
-                       pool));
+  SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, scratch_pool));
 
   /* Skip windows to reach the current chunk if we aren't there yet. */
+  iterpool = svn_pool_create(scratch_pool);
   while (rs->chunk_index < this_chunk)
     {
-      SVN_ERR(svn_txdelta_skip_svndiff_window(rs->file->file, rs->ver,
-                                              pool));
+      apr_file_t *file = rs->sfile->rfile->file;
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_txdelta_skip_svndiff_window(file, rs->ver, iterpool));
       rs->chunk_index++;
-      SVN_ERR(svn_fs_x__get_file_offset(&start_offset, rs->file->file, pool));
+      SVN_ERR(svn_fs_x__get_file_offset(&start_offset, file, iterpool));
+
       rs->current = start_offset - rs->start;
       if (rs->current >= rs->size)
         return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -1346,11 +1416,12 @@ read_delta_window(svn_txdelta_window_t *
                                   "beyond the end of the "
                                   "representation"));
     }
+  svn_pool_destroy(iterpool);
 
   /* Actually read the next window. */
-  SVN_ERR(svn_txdelta_read_svndiff_window(nwin, rs->file->stream, rs->ver,
-                                          pool));
-  SVN_ERR(svn_fs_x__get_file_offset(&end_offset, rs->file->file, pool));
+  SVN_ERR(svn_txdelta_read_svndiff_window(nwin, rs->sfile->rfile->stream,
+                                          rs->ver, result_pool));
+  SVN_ERR(get_file_offset(&end_offset, rs, scratch_pool));
   rs->current = end_offset - rs->start;
   if (rs->current > rs->size)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -1360,7 +1431,7 @@ read_delta_window(svn_txdelta_window_t *
   /* the window has not been cached before, thus cache it now
    * (if caching is used for them at all) */
   if (svn_fs_x__is_revision(rs->rep_id.change_set))
-    SVN_ERR(set_cached_window(*nwin, rs, start_offset, pool));
+    SVN_ERR(set_cached_window(*nwin, rs, start_offset, scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1370,15 +1441,16 @@ static svn_error_t *
 read_container_window(svn_stringbuf_t **nwin,
                       rep_state_t *rs,
                       apr_size_t size,
-                      apr_pool_t *pool)
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
 {
   svn_fs_x__rep_extractor_t *extractor = NULL;
-  svn_fs_t *fs = rs->file->fs;
+  svn_fs_t *fs = rs->sfile->fs;
   fs_x_data_t *ffd = fs->fsap_data;
   pair_cache_key_t key;
   svn_revnum_t revision = svn_fs_x__get_revnum(rs->rep_id.change_set);
 
-  SVN_ERR(auto_set_start_offset(rs, pool));
+  SVN_ERR(auto_set_start_offset(rs, scratch_pool));
   key.revision = svn_fs_x__packed_base_rev(fs, revision);
   key.second = rs->start;
 
@@ -1393,19 +1465,19 @@ read_container_window(svn_stringbuf_t **
       SVN_ERR(svn_cache__get_partial((void**)&extractor, &is_cached,
                                      ffd->reps_container_cache, &key,
                                      svn_fs_x__reps_get_func, &baton,
-                                     pool));
+                                     result_pool));
     }
 
   /* read from disk, if necessary */
   if (extractor == NULL)
     {
-      SVN_ERR(auto_open_shared_file(rs->file));
+      SVN_ERR(auto_open_shared_file(rs->sfile));
       SVN_ERR(block_read((void **)&extractor, fs, &rs->rep_id,
-                         rs->file->file, pool, pool));
+                         rs->sfile->rfile, result_pool, scratch_pool));
     }
 
   SVN_ERR(svn_fs_x__extractor_drive(nwin, extractor, rs->current, size,
-                                    pool, pool));
+                                    result_pool, scratch_pool));
 
   /* Update RS. */
   rs->current += (apr_off_t)size;
@@ -1425,6 +1497,7 @@ get_combined_window(svn_stringbuf_t **re
   apr_array_header_t *windows;
   svn_stringbuf_t *source, *buf = rb->base_window;
   rep_state_t *rs;
+  apr_pool_t *iterpool;
 
   /* Read all windows that we need to combine. This is fine because
      the size of each window is relatively small (100kB) and skip-
@@ -1432,12 +1505,16 @@ get_combined_window(svn_stringbuf_t **re
      Stop early if one of them does not depend on its predecessors. */
   window_pool = svn_pool_create(rb->pool);
   windows = apr_array_make(window_pool, 0, sizeof(svn_txdelta_window_t *));
+  iterpool = svn_pool_create(rb->pool);
   for (i = 0; i < rb->rs_list->nelts; ++i)
     {
       svn_txdelta_window_t *window;
 
+      svn_pool_clear(iterpool);
+
       rs = APR_ARRAY_IDX(rb->rs_list, i, rep_state_t *);
-      SVN_ERR(read_delta_window(&window, rb->chunk_index, rs, window_pool));
+      SVN_ERR(read_delta_window(&window, rb->chunk_index, rs, window_pool,
+                                iterpool));
 
       APR_ARRAY_PUSH(windows, svn_txdelta_window_t *) = window;
       if (window->src_ops == 0)
@@ -1453,6 +1530,8 @@ get_combined_window(svn_stringbuf_t **re
     {
       svn_txdelta_window_t *window;
 
+      svn_pool_clear(iterpool);
+
       rs = APR_ARRAY_IDX(rb->rs_list, i, rep_state_t *);
       window = APR_ARRAY_IDX(windows, i, svn_txdelta_window_t *);
 
@@ -1463,7 +1542,7 @@ get_combined_window(svn_stringbuf_t **re
       source = buf;
       if (source == NULL && rb->src_state != NULL)
         SVN_ERR(read_container_window(&source, rb->src_state,
-                                      window->sview_len, pool));
+                                      window->sview_len, pool, iterpool));
 
       /* Combine this window with the current one. */
       new_pool = svn_pool_create(rb->pool);
@@ -1490,6 +1569,7 @@ get_combined_window(svn_stringbuf_t **re
       svn_pool_destroy(pool);
       pool = new_pool;
     }
+  svn_pool_destroy(iterpool);
 
   svn_pool_destroy(window_pool);
 
@@ -1528,8 +1608,7 @@ static svn_error_t *
 init_rep_state(rep_state_t *rs,
                svn_fs_x__rep_header_t *rep_header,
                svn_fs_t *fs,
-               apr_file_t *file,
-               svn_stream_t *stream,
+               svn_fs_x__revision_file_t *rev_file,
                svn_fs_x__p2l_entry_t* entry,
                apr_pool_t *pool)
 {
@@ -1541,13 +1620,12 @@ init_rep_state(rep_state_t *rs,
                  && entry->type <= SVN_FS_X__ITEM_TYPE_DIR_PROPS);
   SVN_ERR_ASSERT(entry->item_count == 1);
 
-  shared_file->file = file;
-  shared_file->stream = stream;
+  shared_file->rfile = rev_file;
   shared_file->fs = fs;
   shared_file->revision = svn_fs_x__get_revnum(entry->items[0].change_set);
   shared_file->pool = pool;
 
-  rs->file = shared_file;
+  rs->sfile = shared_file;
   rs->rep_id = entry->items[0];
   rs->header_size = rep_header->header_size;
   rs->start = entry->offset + rs->header_size;
@@ -1606,16 +1684,17 @@ cache_windows(svn_filesize_t *fulltext_l
           apr_off_t block_start;
 
           /* navigate to & read the current window */
-          SVN_ERR(aligned_seek(fs, rs->file->file, &block_start,
-                               start_offset, pool));
-          SVN_ERR(svn_txdelta_read_svndiff_window(&window, rs->file->stream,
+          SVN_ERR(rs_aligned_seek(rs, &block_start, start_offset, pool));
+          SVN_ERR(svn_txdelta_read_svndiff_window(&window,
+                                                  rs->sfile->rfile->stream,
                                                   rs->ver, pool));
 
           /* aggregate expanded window size */
           *fulltext_len += window->tview_len;
 
           /* determine on-disk window size */
-          SVN_ERR(svn_fs_x__get_file_offset(&end_offset, rs->file->file,
+          SVN_ERR(svn_fs_x__get_file_offset(&end_offset,
+                                            rs->sfile->rfile->file,
                                             pool));
           rs->current = end_offset - rs->start;
           if (rs->current > rs->size)
@@ -1660,7 +1739,7 @@ read_rep_header(svn_fs_x__rep_header_t *
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(svn_fs_x__read_rep_header(rep_header, stream, pool));
+  SVN_ERR(svn_fs_x__read_rep_header(rep_header, stream, pool, pool));
 
   if (ffd->rep_header_cache)
     SVN_ERR(svn_cache__set(ffd->rep_header_cache, key, *rep_header, pool));
@@ -1672,8 +1751,7 @@ svn_error_t *
 svn_fs_x__get_representation_length(svn_filesize_t *packed_len,
                                     svn_filesize_t *expanded_len,
                                     svn_fs_t *fs,
-                                    apr_file_t *file,
-                                    svn_stream_t *stream,
+                                    svn_fs_x__revision_file_t *rev_file,
                                     svn_fs_x__p2l_entry_t* entry,
                                     apr_pool_t *pool)
 {
@@ -1690,12 +1768,12 @@ svn_fs_x__get_representation_length(svn_
   key.revision = svn_fs_x__get_revnum(entry->items[0].change_set);
   key.is_packed = svn_fs_x__is_packed_rev(fs, key.revision);
   key.item_index = entry->items[0].number;
-  SVN_ERR(read_rep_header(&rep_header, fs, stream, &key, pool));
+  SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &key, pool));
 
   /* prepare representation reader state (rs) structure */
-  SVN_ERR(init_rep_state(&rs, rep_header, fs, file, stream, entry, pool));
+  SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry, pool));
   
-  /* RS->FILE may be shared between RS instances -> make sure we point
+  /* RS->SFILE may be shared between RS instances -> make sure we point
    * to the right data. */
   *packed_len = rs.size;
   SVN_ERR(cache_windows(expanded_len, fs, &rs, -1, pool));
@@ -1728,7 +1806,7 @@ get_contents_from_windows(struct rep_rea
            * the delta rep size _before_ putting the data into a
            * a container. */
           SVN_ERR(read_container_window(&rb->base_window, rs,
-                                        rb->len, rb->pool));
+                                        rb->len, rb->pool, rb->pool));
           rs->current -= rb->base_window->len;
         }
 
@@ -2200,14 +2278,18 @@ delta_read_next_window(svn_txdelta_windo
                        apr_pool_t *pool)
 {
   struct delta_read_baton *drb = baton;
+  apr_pool_t *scratch_pool = svn_pool_create(pool);
 
   *window = NULL;
   if (drb->rs->current < drb->rs->size)
     {
-      SVN_ERR(read_delta_window(window, drb->rs->chunk_index, drb->rs, pool));
+      SVN_ERR(read_delta_window(window, drb->rs->chunk_index, drb->rs, pool,
+                                scratch_pool));
       drb->rs->chunk_index++;
     }
 
+  svn_pool_destroy(scratch_pool);
+
   return SVN_NO_ERROR;
 }
 
@@ -2255,7 +2337,7 @@ svn_fs_x__get_file_delta_stream(svn_txde
     {
       /* Read target's base rep if any. */
       SVN_ERR(create_rep_state(&rep_state, &rep_header, NULL,
-                                target->data_rep, fs, pool));
+                                target->data_rep, fs, pool, pool));
 
       /* Try a shortcut: if the target is stored as a delta against the source,
          then just use that delta. */
@@ -2286,10 +2368,10 @@ svn_fs_x__get_file_delta_stream(svn_txde
         }
 
       /* Don't keep file handles open for longer than necessary. */
-      if (rep_state->file->file)
+      if (rep_state->sfile->rfile)
         {
-          SVN_ERR(svn_io_file_close(rep_state->file->file, pool));
-          rep_state->file->file = NULL;
+          SVN_ERR(svn_fs_x__close_revision_file(rep_state->sfile->rfile));
+          rep_state->sfile->rfile = NULL;
         }
     }
 
@@ -2425,7 +2507,7 @@ read_dir_entries(apr_array_header_t *ent
                            _("Directory entry corrupt in '%s'"),
                            svn_fs_x__id_unparse(id, scratch_pool)->data);
 
-      dirent->id = svn_fs_x__id_parse(str, strlen(str), result_pool);
+      SVN_ERR(svn_fs_x__id_parse(&dirent->id, str, result_pool));
 
       /* In incremental mode, update the hash; otherwise, write to the
        * final array. */
@@ -2481,26 +2563,22 @@ get_dir_contents(apr_array_header_t **en
     }
   else if (noderev->data_rep)
     {
-      /* use a temporary pool for temp objects.
-       * Also undeltify content before parsing it. Otherwise, we could only
+      /* Undeltify content before parsing it. Otherwise, we could only
        * parse it byte-by-byte.
        */
-      apr_pool_t *text_pool = svn_pool_create(scratch_pool);
       apr_size_t len = noderev->data_rep->expanded_size;
       svn_stringbuf_t *text;
 
       /* The representation is immutable.  Read it normally. */
       SVN_ERR(svn_fs_x__get_contents(&contents, fs, noderev->data_rep,
-                                     FALSE, text_pool));
-      SVN_ERR(svn_stringbuf_from_stream(&text, contents, len, text_pool));
+                                     FALSE, scratch_pool));
+      SVN_ERR(svn_stringbuf_from_stream(&text, contents, len, scratch_pool));
       SVN_ERR(svn_stream_close(contents));
 
       /* de-serialize hash */
-      contents = svn_stream_from_stringbuf(text, text_pool);
+      contents = svn_stream_from_stringbuf(text, scratch_pool);
       SVN_ERR(read_dir_entries(*entries, contents, FALSE,  noderev->id,
                                result_pool, scratch_pool));
-
-      svn_pool_destroy(text_pool);
     }
 
   return SVN_NO_ERROR;
@@ -2700,16 +2778,23 @@ svn_error_t *
 svn_fs_x__get_changes(apr_array_header_t **changes,
                       svn_fs_t *fs,
                       svn_revnum_t rev,
-                      apr_pool_t *pool)
+                      apr_pool_t *result_pool)
 {
-  apr_file_t *revision_file;
+  svn_fs_x__revision_file_t *revision_file;
   svn_boolean_t found;
   fs_x_data_t *ffd = fs->fsap_data;
+  apr_pool_t *scratch_pool = svn_pool_create(result_pool);
 
   svn_fs_x__id_part_t id;
   id.change_set = svn_fs_x__change_set_by_rev(rev);
   id.number = SVN_FS_X__ITEM_INDEX_CHANGES;
 
+  /* Provide revision file. */
+
+  SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool));
+  SVN_ERR(svn_fs_x__open_pack_or_rev_file(&revision_file, fs, rev,
+                                          scratch_pool, scratch_pool));
+
   /* try cache lookup first */
 
   if (ffd->changes_container_cache && svn_fs_x__is_packed_rev(fs, rev))
@@ -2718,19 +2803,20 @@ svn_fs_x__get_changes(apr_array_header_t
       apr_uint32_t sub_item;
       pair_cache_key_t key;
 
-      SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, &id, pool));
+      SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, revision_file,
+                                    &id, scratch_pool));
       key.revision = svn_fs_x__packed_base_rev(fs, rev);
       key.second = offset;
 
       SVN_ERR(svn_cache__get_partial((void **)changes, &found,
                                      ffd->changes_container_cache, &key,
                                      svn_fs_x__changes_get_list_func,
-                                     &sub_item, pool));
+                                     &sub_item, result_pool));
     }
   else if (ffd->changes_cache)
     {
       SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache,
-                             &rev, pool));
+                             &rev, result_pool));
     }
   else
     {
@@ -2739,22 +2825,17 @@ svn_fs_x__get_changes(apr_array_header_t
 
   if (!found)
     {
-      /* read changes from revision file */
-
-      SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, pool));
-      SVN_ERR(svn_fs_x__open_pack_or_rev_file(&revision_file, fs, rev,
-                                              pool));
-
       /* 'block-read' will also provide us with the desired data */
       SVN_ERR(block_read((void **)changes, fs, &id, revision_file,
-                         pool, pool));
+                         result_pool, scratch_pool));
 
-      SVN_ERR(svn_io_file_close(revision_file, pool));
+      SVN_ERR(svn_fs_x__close_revision_file(revision_file));
     }
 
   SVN_ERR(dgb__log_access(fs, &id, *changes, SVN_FS_X__ITEM_TYPE_CHANGES,
-                          pool));
+                          scratch_pool));
 
+  svn_pool_destroy(scratch_pool);
   return SVN_NO_ERROR;
 }
 
@@ -2762,16 +2843,15 @@ svn_fs_x__get_changes(apr_array_header_t
  * addressed by ENTRY->ITEM in FS and cache it if caches are enabled.
  * Read the data from the already open FILE and the wrapping
  * STREAM object.  If MAX_OFFSET is not -1, don't read windows that start
- * at or beyond that offset.  Use POOL for allocations.
+ * at or beyond that offset.  Use SCRATCH_POOL for temporary allocations.
  */
 static svn_error_t *
 block_read_contents(svn_fs_t *fs,
-                    apr_file_t *file,
-                    svn_stream_t *stream,
+                    svn_fs_x__revision_file_t *rev_file,
                     svn_fs_x__p2l_entry_t* entry,
                     pair_cache_key_t *key,
                     apr_off_t max_offset,
-                    apr_pool_t *pool)
+                    apr_pool_t *scratch_pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
   representation_cache_key_t header_key = { 0 };
@@ -2786,48 +2866,75 @@ block_read_contents(svn_fs_t *fs,
   header_key.is_packed = svn_fs_x__is_packed_rev(fs, header_key.revision);
   header_key.item_index = key->second;
 
-  SVN_ERR(read_rep_header(&rep_header, fs, stream, &header_key, pool));
-  SVN_ERR(init_rep_state(&rs, rep_header, fs, file, stream, entry, pool));
-  SVN_ERR(cache_windows(&fulltext_len, fs, &rs, max_offset, pool));
+  SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key,
+                          scratch_pool));
+  SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry, scratch_pool));
+  SVN_ERR(cache_windows(&fulltext_len, fs, &rs, max_offset, scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
+/* For the given REV_FILE in FS, in *STREAM return a stream covering the
+ * item specified by ENTRY.  Also, verify the item's content by low-level
+ * checksum.  Allocate the result in POOL.
+ */
 static svn_error_t *
-auto_select_stream(svn_stream_t **stream,
-                   svn_fs_t *fs,
-                   apr_file_t *file,
-                   svn_stream_t *file_stream,
-                   svn_fs_x__p2l_entry_t* entry,
-                   apr_pool_t *pool)
+read_item(svn_stream_t **stream,
+          svn_fs_t *fs,
+          svn_fs_x__revision_file_t *rev_file,
+          svn_fs_x__p2l_entry_t* entry,
+          apr_pool_t *pool)
 {
-  fs_x_data_t *ffd = fs->fsap_data;
+  apr_uint32_t digest;
+  svn_checksum_t *expected, *actual;
+  apr_uint32_t plain_digest;
 
-  if (((entry->offset + entry->size) ^ entry->offset) >= ffd->block_size)
-    {
-      svn_stringbuf_t *text = svn_stringbuf_create_ensure(entry->size, pool);
-      text->len = entry->size;
-      text->data[text->len] = 0;
-      SVN_ERR(svn_io_file_read_full2(file, text->data, text->len, NULL,
-                                     NULL, pool));
-      *stream = svn_stream_from_stringbuf(text, pool);
-    }
-  else
-    {
-      *stream = file_stream;
-    }
+  /* Read item into string buffer. */
+  svn_stringbuf_t *text = svn_stringbuf_create_ensure(entry->size, pool);
+  text->len = entry->size;
+  text->data[text->len] = 0;
+  SVN_ERR(svn_io_file_read_full2(rev_file->file, text->data, text->len,
+                                 NULL, NULL, pool));
 
-  return SVN_NO_ERROR;
+  /* Return (construct, calculate) stream and checksum. */
+  *stream = svn_stream_from_stringbuf(text, pool);
+  digest = svn__fnv1a_32x4(text->data, text->len);
+
+  /* Checksums will match most of the time. */
+  if (entry->fnv1_checksum == digest)
+    return SVN_NO_ERROR;
+
+  /* Construct proper checksum objects from their digests to allow for
+   * nice error messages. */
+  plain_digest = htonl(entry->fnv1_checksum);
+  expected = svn_checksum__from_digest_fnv1a_32x4(
+                (const unsigned char *)&plain_digest, pool);
+  plain_digest = htonl(digest);
+  actual = svn_checksum__from_digest_fnv1a_32x4(
+                (const unsigned char *)&plain_digest, pool);
+
+  /* Construct the full error message with all the info we have. */
+  return svn_checksum_mismatch_err(expected, actual, pool,
+                 _("Low-level checksum mismatch while reading\n"
+                   "%s bytes of meta data at offset %s "),
+                 apr_psprintf(pool, "%" APR_OFF_T_FMT, entry->size),
+                 apr_psprintf(pool, "%" APR_OFF_T_FMT, entry->offset));
 }
 
+/* Read all txdelta / plain windows following REP_HEADER in FS as described
+ * by ENTRY.  Read the data from the already open FILE and the wrapping
+ * STREAM object.  If MAX_OFFSET is not -1, don't read windows that start
+ * at or beyond that offset.  Use SCRATCH_POOL for temporary allocations.
+ * If caching is not enabled, this is a no-op.
+ */
 static svn_error_t *
 block_read_changes(apr_array_header_t **changes,
                    svn_fs_t *fs,
-                   apr_file_t *file,
-                   svn_stream_t *file_stream,
+                   svn_fs_x__revision_file_t *rev_file,
                    svn_fs_x__p2l_entry_t* entry,
                    svn_boolean_t must_read,
-                   apr_pool_t *pool)
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
   svn_stream_t *stream;
@@ -2843,21 +2950,32 @@ block_read_changes(apr_array_header_t **
     {
       svn_boolean_t is_cached = FALSE;
       SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache, &revision,
-                                 pool));
+                                 scratch_pool));
       if (is_cached)
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry, pool));
+  SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read changes from revision file */
 
-  SVN_ERR(svn_fs_x__read_changes(changes, stream, pool));
+  SVN_ERR(svn_fs_x__read_changes(changes, stream, result_pool, scratch_pool));
 
   /* cache for future reference */
 
   if (ffd->changes_cache)
-    SVN_ERR(svn_cache__set(ffd->changes_cache, &revision, *changes, pool));
+    {
+      /* Guesstimate for the size of the in-cache representation. */
+      apr_size_t estimated_size = (apr_size_t)250 * (*changes)->nelts;
+
+      /* Don't even serialize data that probably won't fit into the
+        * cache.  This often implies that either CHANGES is very
+        * large, memory is scarce or both.  Having a huge temporary
+        * copy would not be a good thing in either case. */
+      if (svn_cache__is_cachable(ffd->changes_cache, estimated_size))
+        SVN_ERR(svn_cache__set(ffd->changes_cache, &revision, *changes,
+                               scratch_pool));
+    }
 
   return SVN_NO_ERROR;
 }
@@ -2865,12 +2983,12 @@ block_read_changes(apr_array_header_t **
 static svn_error_t *
 block_read_changes_container(apr_array_header_t **changes,
                              svn_fs_t *fs,
-                             apr_file_t *file,
-                             svn_stream_t *file_stream,
+                             svn_fs_x__revision_file_t *rev_file,
                              svn_fs_x__p2l_entry_t* entry,
                              apr_uint32_t sub_item,
                              svn_boolean_t must_read,
-                             apr_pool_t *pool)
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
   svn_fs_x__changes_t *container;
@@ -2886,25 +3004,27 @@ block_read_changes_container(apr_array_h
     {
       svn_boolean_t is_cached = FALSE;
       SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_container_cache,
-                                 &key, pool));
+                                 &key, scratch_pool));
       if (is_cached)
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry, pool));
+  SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read changes from revision file */
 
-  SVN_ERR(svn_fs_x__read_changes_container(&container, stream, pool, pool));
+  SVN_ERR(svn_fs_x__read_changes_container(&container, stream, scratch_pool,
+                                           scratch_pool));
 
   /* extract requested data */
 
   if (must_read)
-    SVN_ERR(svn_fs_x__changes_get_list(changes, container, sub_item, pool));
+    SVN_ERR(svn_fs_x__changes_get_list(changes, container, sub_item,
+                                       result_pool));
 
   if (ffd->changes_container_cache)
     SVN_ERR(svn_cache__set(ffd->changes_container_cache, &key, container,
-                           pool));
+                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -2912,12 +3032,12 @@ block_read_changes_container(apr_array_h
 static svn_error_t *
 block_read_noderev(node_revision_t **noderev_p,
                    svn_fs_t *fs,
-                   apr_file_t *file,
-                   svn_stream_t *file_stream,
+                   svn_fs_x__revision_file_t *rev_file,
                    svn_fs_x__p2l_entry_t* entry,
                    pair_cache_key_t *key,
                    svn_boolean_t must_read,
-                   apr_pool_t *pool)
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
   svn_stream_t *stream;
@@ -2932,22 +3052,24 @@ block_read_noderev(node_revision_t **nod
     {
       svn_boolean_t is_cached = FALSE;
       SVN_ERR(svn_cache__has_key(&is_cached, ffd->node_revision_cache, key,
-                                 pool));
+                                 scratch_pool));
       if (is_cached)
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry, pool));
+  SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read node rev from revision file */
 
-  SVN_ERR(svn_fs_x__read_noderev(noderev_p, stream, pool));
+  SVN_ERR(svn_fs_x__read_noderev(noderev_p, stream, result_pool,
+                                 scratch_pool));
 
   /* Workaround issue #4031: is-fresh-txn-root in revision files. */
   (*noderev_p)->is_fresh_txn_root = FALSE;
 
   if (ffd->node_revision_cache)
-    SVN_ERR(svn_cache__set(ffd->node_revision_cache, key, *noderev_p, pool));
+    SVN_ERR(svn_cache__set(ffd->node_revision_cache, key, *noderev_p,
+                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -2955,12 +3077,12 @@ block_read_noderev(node_revision_t **nod
 static svn_error_t *
 block_read_noderevs_container(node_revision_t **noderev_p,
                               svn_fs_t *fs,
-                              apr_file_t *file,
-                              svn_stream_t *file_stream,
+                              svn_fs_x__revision_file_t *rev_file,
                               svn_fs_x__p2l_entry_t* entry,
                               apr_uint32_t sub_item,
                               svn_boolean_t must_read,
-                              apr_pool_t *pool)
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
   svn_fs_x__noderevs_t *container;
@@ -2976,25 +3098,25 @@ block_read_noderevs_container(node_revis
     {
       svn_boolean_t is_cached = FALSE;
       SVN_ERR(svn_cache__has_key(&is_cached, ffd->noderevs_container_cache,
-                                 &key, pool));
+                                 &key, scratch_pool));
       if (is_cached)
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry, pool));
+  SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read noderevs from revision file */
-
-  SVN_ERR(svn_fs_x__read_noderevs_container(&container, stream, pool, pool));
+  SVN_ERR(svn_fs_x__read_noderevs_container(&container, stream, scratch_pool,
+                                            scratch_pool));
 
   /* extract requested data */
-
   if (must_read)
-    SVN_ERR(svn_fs_x__noderevs_get(noderev_p, container, sub_item, pool));
+    SVN_ERR(svn_fs_x__noderevs_get(noderev_p, container, sub_item,
+                                   result_pool));
 
   if (ffd->noderevs_container_cache)
     SVN_ERR(svn_cache__set(ffd->noderevs_container_cache, &key, container,
-                           pool));
+                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -3002,12 +3124,12 @@ block_read_noderevs_container(node_revis
 static svn_error_t *
 block_read_reps_container(svn_fs_x__rep_extractor_t **extractor,
                           svn_fs_t *fs,
-                          apr_file_t *file,
-                          svn_stream_t *file_stream,
+                          svn_fs_x__revision_file_t *rev_file,
                           svn_fs_x__p2l_entry_t* entry,
                           apr_uint32_t sub_item,
                           svn_boolean_t must_read,
-                          apr_pool_t *pool)
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
   svn_fs_x__reps_t *container;
@@ -3023,25 +3145,26 @@ block_read_reps_container(svn_fs_x__rep_
     {
       svn_boolean_t is_cached = FALSE;
       SVN_ERR(svn_cache__has_key(&is_cached, ffd->reps_container_cache,
-                                 &key, pool));
+                                 &key, scratch_pool));
       if (is_cached)
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry, pool));
+  SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read noderevs from revision file */
-
-  SVN_ERR(svn_fs_x__read_reps_container(&container, stream, pool, pool));
+  SVN_ERR(svn_fs_x__read_reps_container(&container, stream, result_pool,
+                                        scratch_pool));
 
   /* extract requested data */
 
   if (must_read)
-    SVN_ERR(svn_fs_x__reps_get(extractor, fs, container, sub_item, pool));
+    SVN_ERR(svn_fs_x__reps_get(extractor, fs, container, sub_item,
+                               result_pool));
 
   if (ffd->noderevs_container_cache)
     SVN_ERR(svn_cache__set(ffd->reps_container_cache, &key, container,
-                           pool));
+                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -3050,7 +3173,7 @@ static svn_error_t *
 block_read(void **result,
            svn_fs_t *fs,
            const svn_fs_x__id_part_t *id,
-           apr_file_t *revision_file,
+           svn_fs_x__revision_file_t *revision_file,
            apr_pool_t *result_pool,
            apr_pool_t *scratch_pool)
 {
@@ -3063,24 +3186,25 @@ block_read(void **result,
   int run_count = 0;
   int i;
   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-  svn_stream_t *stream = svn_stream_from_aprfile2(revision_file, TRUE,
-                                                  scratch_pool);
 
   /* don't try this on transaction protorev files */
   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
 
   /* index lookup: find the OFFSET of the item we *must* read plus (in the
    * "do-while" block) the list of items in the same block. */
-  SVN_ERR(svn_fs_x__item_offset(&wanted_offset, &wanted_sub_item, fs, id,
-                                iterpool));
+  SVN_ERR(svn_fs_x__item_offset(&wanted_offset, &wanted_sub_item, fs,
+                                revision_file, id, iterpool));
 
   offset = wanted_offset;
   do
     {
       /* fetch list of items in the block surrounding OFFSET */
-      SVN_ERR(aligned_seek(fs, revision_file, &block_start, offset, iterpool));
-      SVN_ERR(svn_fs_x__p2l_index_lookup(&entries, fs, revision, block_start,
-                                         ffd->block_size, scratch_pool));
+      SVN_ERR(aligned_seek(fs, revision_file->file, &block_start, offset,
+                           iterpool));
+      SVN_ERR(svn_fs_x__p2l_index_lookup(&entries, fs, revision_file,
+                                         revision, block_start,
+                                         ffd->block_size, scratch_pool,
+                                         scratch_pool));
 
       /* read all items from the block */
       for (i = 0; i < entries->nelts; ++i)
@@ -3116,7 +3240,7 @@ block_read(void **result,
               key.revision = svn_fs_x__get_revnum(entry->items[0].change_set);
               key.second = entry->items[0].number;
 
-              SVN_ERR(svn_io_file_seek(revision_file, SEEK_SET,
+              SVN_ERR(svn_io_file_seek(revision_file->file, SEEK_SET,
                                        &entry->offset, iterpool));
               switch (entry->type)
                 {
@@ -3124,50 +3248,51 @@ block_read(void **result,
                   case SVN_FS_X__ITEM_TYPE_DIR_REP:
                   case SVN_FS_X__ITEM_TYPE_FILE_PROPS:
                   case SVN_FS_X__ITEM_TYPE_DIR_PROPS:
-                    SVN_ERR(block_read_contents(fs, revision_file, stream,
+                    SVN_ERR(block_read_contents(fs, revision_file,
                                                 entry, &key,
                                                 is_wanted
                                                   ? -1
                                                   : block_start + ffd->block_size,
-                                                pool));
+                                                iterpool));
                     break;
 
                   case SVN_FS_X__ITEM_TYPE_NODEREV:
                     if (ffd->node_revision_cache || is_result)
                       SVN_ERR(block_read_noderev((node_revision_t **)&item,
-                                                 fs, revision_file, stream,
+                                                 fs, revision_file,
                                                  entry, &key, is_result,
-                                                 pool));
+                                                 pool, iterpool));
                     break;
 
                   case SVN_FS_X__ITEM_TYPE_CHANGES:
                     SVN_ERR(block_read_changes((apr_array_header_t **)&item,
-                                               fs, revision_file,  stream,
-                                               entry, is_result, pool));
+                                               fs, revision_file,
+                                               entry, is_result,
+                                               pool, iterpool));
                     break;
 
                   case SVN_FS_X__ITEM_TYPE_CHANGES_CONT:
                     SVN_ERR(block_read_changes_container
                                             ((apr_array_header_t **)&item,
-                                             fs, revision_file,  stream,
+                                             fs, revision_file,
                                              entry, wanted_sub_item,
-                                             is_result, pool));
+                                             is_result, pool, iterpool));
                     break;
 
                   case SVN_FS_X__ITEM_TYPE_NODEREVS_CONT:
                     SVN_ERR(block_read_noderevs_container
                                             ((node_revision_t **)&item,
-                                             fs, revision_file,  stream,
+                                             fs, revision_file,
                                              entry, wanted_sub_item,
-                                             is_result, pool));
+                                             is_result, pool, iterpool));
                     break;
 
                   case SVN_FS_X__ITEM_TYPE_REPS_CONT:
                     SVN_ERR(block_read_reps_container
                                       ((svn_fs_x__rep_extractor_t **)&item,
-                                       fs, revision_file,  stream,
+                                       fs, revision_file,
                                        entry, wanted_sub_item,
-                                       is_result, pool));
+                                       is_result, pool, iterpool));
                     break;
 
                   default:
@@ -3192,7 +3317,6 @@ block_read(void **result,
 
   /* if the caller requested a result, we must have provided one by now */
   assert(!result || *result);
-  SVN_ERR(svn_stream_close(stream));
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/cached_data.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/cached_data.h?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/cached_data.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/cached_data.h Fri Nov 14 13:17:55 2014
@@ -37,7 +37,8 @@ svn_error_t *
 svn_fs_x__get_node_revision(node_revision_t **noderev_p,
                             svn_fs_t *fs,
                             const svn_fs_id_t *id,
-                            apr_pool_t *pool);
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool);
 
 /* Set *COUNT to the value of the mergeinfo_count member of the node-
    revision for the node ID in FS.  Do any allocations in POOL. */
@@ -53,25 +54,26 @@ svn_error_t *
 svn_fs_x__rev_get_root(svn_fs_id_t **root_id,
                        svn_fs_t *fs,
                        svn_revnum_t rev,
-                       apr_pool_t *pool);
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool);
 
 /* Verify that representation REP in FS can be accessed.
-   Do any allocations in POOL. */
+   Do any allocations in SCRATCH_POOL. */
 svn_error_t *
 svn_fs_x__check_rep(representation_t *rep,
                     svn_fs_t *fs,
-                    apr_pool_t *pool);
+                    apr_pool_t *scratch_pool);
 
 /* Follow the representation delta chain in FS starting with REP.  The
    number of reps (including REP) in the chain will be returned in
    *CHAIN_LENGTH.  *SHARD_COUNT will be set to the number of shards
-   accessed.  Do any allocations in POOL. */
+   accessed.  Do any allocations in SCRATCH_POOL. */
 svn_error_t *
 svn_fs_x__rep_chain_length(int *chain_length,
                            int *shard_count,
                            representation_t *rep,
                            svn_fs_t *fs,
-                           apr_pool_t *pool);
+                           apr_pool_t *scratch_pool);
 
 /* Set *CONTENTS to be a readable svn_stream_t that receives the text
    representation REP as seen in filesystem FS.  If CACHE_FULLTEXT is
@@ -95,8 +97,7 @@ svn_error_t *
 svn_fs_x__get_representation_length(svn_filesize_t *packed_len,
                                     svn_filesize_t *expanded_len,
                                     svn_fs_t *fs,
-                                    apr_file_t *file,
-                                    svn_stream_t *stream,
+                                    svn_fs_x__revision_file_t *rev_file,
                                     svn_fs_x__p2l_entry_t* entry,
                                     apr_pool_t *pool);
 

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/caching.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/caching.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/caching.c Fri Nov 14 13:17:55 2014
@@ -126,19 +126,17 @@ read_config(const char **cache_namespace
    * Revprop caching significantly speeds up operations like
    * svn ls -v. However, it requires synchronization that may
    * not be available or efficient in the current server setup.
-   *
-   * If the caller chose option "2", enable revprop caching if
-   * the required API support is there to make it efficient.
+   * Option "2" is equivalent to "1".
    */
   if (strcmp(svn_hash__get_cstring(fs->config,
                                    SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
                                    ""), "2"))
     *cache_revprops
       = svn_hash__get_bool(fs->config,
-                           SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
-                           FALSE);
+                          SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
+                          FALSE);
   else
-    *cache_revprops = svn_named_atomic__is_efficient();
+    *cache_revprops = TRUE;
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_x/dag.c Fri Nov 14 13:17:55 2014
@@ -160,10 +160,13 @@ get_node_revision(node_revision_t **node
   if (! node->node_revision)
     {
       node_revision_t *noderev;
+      apr_pool_t *scratch_pool = svn_pool_create(node->node_pool);
 
       SVN_ERR(svn_fs_x__get_node_revision(&noderev, node->fs,
-                                          node->id, node->node_pool));
+                                          node->id, node->node_pool,
+                                          scratch_pool));
       node->node_revision = noderev;
+      svn_pool_destroy(scratch_pool);
     }
 
   /* Now NODE->node_revision is set.  */
@@ -613,7 +616,7 @@ svn_fs_x__dag_revision_root(dag_node_t *
   /* Construct the node. */
   new_node = apr_pcalloc(pool, sizeof(*new_node));
   new_node->fs = fs;
-  SVN_ERR(svn_fs_x__rev_get_root(&new_node->id, fs, rev, pool));
+  SVN_ERR(svn_fs_x__rev_get_root(&new_node->id, fs, rev, pool, pool));
 
   /* Grab the contents so we can inspect the node's kind and created path. */
   new_node->node_pool = pool;



Mime
View raw message