subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1635317 [1/2] - in /subversion/trunk/subversion/libsvn_fs_x: ./ cached_data.c cached_data.h fs_x.c fs_x.h index.c index.h pack.c recovery.c rev_file.c rev_file.h verify.c
Date Wed, 29 Oct 2014 22:27:03 GMT
Author: stefan2
Date: Wed Oct 29 22:27:02 2014
New Revision: 1635317

URL: http://svn.apache.org/r1635317
Log:
Sync FSX with FSFS:
Merge and adapt revisions r1531982 and r1604717 from libsvn_fs_fs.
Various conflicts were caused by reordered code and renamed functions
in FSX.  Lots of additonal code / callers to be adapted.

This ports the revision_file_t abstraction to FSX.

Added:
    subversion/trunk/subversion/libsvn_fs_x/rev_file.c
      - copied, changed from r1531982, subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.c
    subversion/trunk/subversion/libsvn_fs_x/rev_file.h
      - copied, changed from r1531982, subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.h
Modified:
    subversion/trunk/subversion/libsvn_fs_x/   (props changed)
    subversion/trunk/subversion/libsvn_fs_x/cached_data.c
    subversion/trunk/subversion/libsvn_fs_x/cached_data.h
    subversion/trunk/subversion/libsvn_fs_x/fs_x.c
    subversion/trunk/subversion/libsvn_fs_x/fs_x.h
    subversion/trunk/subversion/libsvn_fs_x/index.c
    subversion/trunk/subversion/libsvn_fs_x/index.h
    subversion/trunk/subversion/libsvn_fs_x/pack.c
    subversion/trunk/subversion/libsvn_fs_x/recovery.c
    subversion/trunk/subversion/libsvn_fs_x/verify.c

Propchange: subversion/trunk/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
  Merged /subversion/trunk/subversion/libsvn_fs_fs:r1604717
  Merged /subversion/branches/log-addressing/subversion/libsvn_fs_fs:r1531982

Modified: subversion/trunk/subversion/libsvn_fs_x/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/cached_data.c?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/cached_data.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/cached_data.c Wed Oct 29 22:27:02 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);
 
@@ -192,12 +192,12 @@ 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);
@@ -205,8 +205,8 @@ open_and_seek_revision(apr_file_t **file
   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__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));
 
-  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)
@@ -276,16 +272,17 @@ get_node_revision_body(node_revision_t *
                        const svn_fs_id_t *id,
                        apr_pool_t *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,
+      err = svn_io_file_open(&file,
                              svn_fs_x__path_txn_node_rev(fs, id, pool),
                              APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
       if (err)
@@ -300,26 +297,31 @@ 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));
     }
   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,
+                                              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, pool));
           key.revision = svn_fs_x__packed_base_rev(fs, revision);
           key.second = offset;
 
@@ -357,7 +359,7 @@ get_node_revision_body(node_revision_t *
                          revision_file,
                          pool,
                          pool));
-      SVN_ERR(svn_io_file_close(revision_file, pool));
+      SVN_ERR(svn_fs_x__close_revision_file(revision_file));
     }
 
   return SVN_NO_ERROR;
@@ -407,6 +409,9 @@ 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));
+
       if (   svn_fs_x__is_packed_rev(fs, revision)
           && ffd->noderevs_container_cache)
         {
@@ -415,7 +420,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;
@@ -455,15 +460,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 +480,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 +493,95 @@ 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));
+
+  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,
@@ -525,7 +607,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
@@ -569,45 +651,63 @@ create_rep_state_body(rep_state_t **rep_
     SVN_ERR(svn_cache__get((void **) &rh, &is_cached,
                            ffd->rep_header_cache, &key, 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(pool, sizeof(*file));
+      file->revision = revision;
+      file->pool = 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));
+          SVN_ERR(rs_aligned_seek(rs, NULL, offset, pool));
+        }
+      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,
+                                               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, 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, pool));
               in_container = entry->type == SVN_FS_X__ITEM_TYPE_REPS_CONT;
             }
 
@@ -617,57 +717,26 @@ create_rep_state_body(rep_state_t **rep_
               *rep_header = apr_pcalloc(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(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, pool));
+      SVN_ERR(get_file_offset(&rs->start, rs, 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, pool,
+                             pool));
           if (ffd->rep_header_cache)
             SVN_ERR(svn_cache__set(ffd->rep_header_cache, &key, rh, pool));
         }
     }
 
+  /* finalize */
   SVN_ERR(dgb__log_access(fs, &rs->rep_id, rh, SVN_FS_X__ITEM_TYPE_ANY_REP,
                           pool));
 
@@ -675,8 +744,9 @@ create_rep_state_body(rep_state_t **rep_
   *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;
@@ -735,11 +805,16 @@ svn_fs_x__check_rep(representation_t *re
   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, 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,
+                                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,
+                                     pool));
 
   /* Verify that we've got an item that is actually a representation. */
   if (   entry == NULL
@@ -1240,63 +1315,6 @@ 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 *
@@ -1310,7 +1328,7 @@ read_delta_window(svn_txdelta_window_t *
 
   SVN_ERR_ASSERT(rs->chunk_index <= this_chunk);
 
-  SVN_ERR(dgb__log_access(rs->file->fs, &rs->rep_id, NULL,
+  SVN_ERR(dgb__log_access(rs->sfile->fs, &rs->rep_id, NULL,
                           SVN_FS_X__ITEM_TYPE_ANY_REP, pool));
 
   /* Read the next window.  But first, try to find it in the cache. */
@@ -1319,7 +1337,7 @@ read_delta_window(svn_txdelta_window_t *
     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,
@@ -1328,8 +1346,8 @@ 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, pool, pool));
 
       /* reading the whole block probably also provided us with the
          desired txdelta window */
@@ -1346,19 +1364,19 @@ read_delta_window(svn_txdelta_window_t *
   /* 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, pool));
 
   /* Skip windows to reach the current chunk if we aren't there yet. */
   iterpool = svn_pool_create(pool);
   while (rs->chunk_index < this_chunk)
     {
+      apr_file_t *file = rs->sfile->rfile->file;
       svn_pool_clear(iterpool);
-      SVN_ERR(svn_txdelta_skip_svndiff_window(rs->file->file, rs->ver,
-                                              iterpool));
+
+      SVN_ERR(svn_txdelta_skip_svndiff_window(file, rs->ver, pool));
       rs->chunk_index++;
-      SVN_ERR(svn_fs_x__get_file_offset(&start_offset, rs->file->file,
-                                        iterpool));
+      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,
@@ -1369,9 +1387,9 @@ read_delta_window(svn_txdelta_window_t *
   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, pool));
+  SVN_ERR(get_file_offset(&end_offset, rs, pool));
   rs->current = end_offset - rs->start;
   if (rs->current > rs->size)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -1394,7 +1412,7 @@ read_container_window(svn_stringbuf_t **
                       apr_pool_t *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);
@@ -1420,9 +1438,9 @@ read_container_window(svn_stringbuf_t **
   /* 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, pool, pool));
     }
 
   SVN_ERR(svn_fs_x__extractor_drive(nwin, extractor, rs->current, size,
@@ -1549,8 +1567,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)
 {
@@ -1562,13 +1579,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;
@@ -1627,16 +1643,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)
@@ -1693,8 +1710,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)
 {
@@ -1711,12 +1727,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));
@@ -2307,10 +2323,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;
         }
     }
 
@@ -2723,7 +2739,7 @@ svn_fs_x__get_changes(apr_array_header_t
                       svn_revnum_t rev,
                       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);
@@ -2732,6 +2748,12 @@ svn_fs_x__get_changes(apr_array_header_t
   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));
+
   /* try cache lookup first */
 
   if (ffd->changes_container_cache && svn_fs_x__is_packed_rev(fs, rev))
@@ -2740,8 +2762,8 @@ 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,
-                                    scratch_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;
 
@@ -2762,17 +2784,11 @@ 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, scratch_pool));
-      SVN_ERR(svn_fs_x__open_pack_or_rev_file(&revision_file, fs, rev,
-                                              scratch_pool));
-
       /* 'block-read' will also provide us with the desired data */
       SVN_ERR(block_read((void **)changes, fs, &id, revision_file,
                          result_pool, scratch_pool));
 
-      SVN_ERR(svn_io_file_close(revision_file, scratch_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,
@@ -2790,8 +2806,7 @@ svn_fs_x__get_changes(apr_array_header_t
  */
 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,
@@ -2810,10 +2825,9 @@ 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,
+  SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key,
                           scratch_pool));
-  SVN_ERR(init_rep_state(&rs, rep_header, fs, file, stream, entry,
-                         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;
@@ -2822,8 +2836,7 @@ block_read_contents(svn_fs_t *fs,
 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__revision_file_t *rev_file,
                    svn_fs_x__p2l_entry_t* entry,
                    apr_pool_t *pool)
 {
@@ -2834,13 +2847,13 @@ auto_select_stream(svn_stream_t **stream
       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));
+      SVN_ERR(svn_io_file_read_full2(rev_file->file, text->data, text->len,
+                                     NULL, NULL, pool));
       *stream = svn_stream_from_stringbuf(text, pool);
     }
   else
     {
-      *stream = file_stream;
+      *stream = rev_file->stream;
     }
 
   return SVN_NO_ERROR;
@@ -2855,8 +2868,7 @@ auto_select_stream(svn_stream_t **stream
 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 *result_pool,
@@ -2881,8 +2893,7 @@ block_read_changes(apr_array_header_t **
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
-                             scratch_pool));
+  SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read changes from revision file */
 
@@ -2900,8 +2911,7 @@ 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,
@@ -2927,8 +2937,7 @@ block_read_changes_container(apr_array_h
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
-                             scratch_pool));
+  SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read changes from revision file */
 
@@ -2951,8 +2960,7 @@ 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,
@@ -2977,8 +2985,7 @@ block_read_noderev(node_revision_t **nod
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
-                             scratch_pool));
+  SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read node rev from revision file */
 
@@ -2997,8 +3004,7 @@ 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,
@@ -3024,8 +3030,7 @@ block_read_noderevs_container(node_revis
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
-                             scratch_pool));
+  SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read noderevs from revision file */
 
@@ -3048,8 +3053,7 @@ 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,
@@ -3075,8 +3079,7 @@ block_read_reps_container(svn_fs_x__rep_
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
-                             scratch_pool));
+  SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
 
   /* read noderevs from revision file */
 
@@ -3100,7 +3103,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)
 {
@@ -3113,23 +3116,23 @@ 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,
+      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));
 
       /* read all items from the block */
@@ -3166,7 +3169,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, APR_SET,
+              SVN_ERR(svn_io_file_seek(revision_file->file, SEEK_SET,
                                        &entry->offset, iterpool));
               switch (entry->type)
                 {
@@ -3174,7 +3177,7 @@ 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
@@ -3185,14 +3188,14 @@ block_read(void **result,
                   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, iterpool));
                     break;
 
                   case SVN_FS_X__ITEM_TYPE_CHANGES:
                     SVN_ERR(block_read_changes((apr_array_header_t **)&item,
-                                               fs, revision_file,  stream,
+                                               fs, revision_file,
                                                entry, is_result,
                                                pool, iterpool));
                     break;
@@ -3200,7 +3203,7 @@ block_read(void **result,
                   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, iterpool));
                     break;
@@ -3208,7 +3211,7 @@ block_read(void **result,
                   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, iterpool));
                     break;
@@ -3216,7 +3219,7 @@ block_read(void **result,
                   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, iterpool));
                     break;
@@ -3243,7 +3246,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/trunk/subversion/libsvn_fs_x/cached_data.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/cached_data.h?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/cached_data.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/cached_data.h Wed Oct 29 22:27:02 2014
@@ -95,8 +95,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/trunk/subversion/libsvn_fs_x/fs_x.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs_x.c?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs_x.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs_x.c Wed Oct 29 22:27:02 2014
@@ -604,60 +604,6 @@ svn_fs_x__ensure_revision_exists(svn_rev
                            _("No such revision %ld"), rev);
 }
 
-/* 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
-   file doesn't exist.
-
-   TODO: Consider returning an indication of whether this is a packed rev
-         file, so the caller need not rely on is_packed_rev() which in turn
-         relies on the cached FFD->min_unpacked_rev value not having changed
-         since the rev file was opened.
-
-   Use POOL for allocations. */
-svn_error_t *
-svn_fs_x__open_pack_or_rev_file(apr_file_t **file,
-                                svn_fs_t *fs,
-                                svn_revnum_t rev,
-                                apr_pool_t *pool)
-{
-  svn_error_t *err;
-  svn_boolean_t retry = FALSE;
-
-  do
-    {
-      const char *path = svn_fs_x__path_rev_absolute(fs, rev, pool);
-
-      /* open the revision file in buffered r/o mode */
-      err = svn_io_file_open(file, path,
-                            APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
-      if (err && APR_STATUS_IS_ENOENT(err->apr_err))
-        {
-          /* Could not open the file. This may happen if the
-            * file once existed but got packed later. */
-          svn_error_clear(err);
-
-          /* if that was our 2nd attempt, leave it at that. */
-          if (retry)
-            return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
-                                     _("No such revision %ld"), rev);
-
-          /* We failed for the first time. Refresh cache & retry. */
-          SVN_ERR(svn_fs_x__update_min_unpacked_rev(fs, pool));
-
-          retry = TRUE;
-        }
-      else
-        {
-          retry = FALSE;
-        }
-    }
-  while (retry);
-
-  return svn_error_trace(err);
-}
-
-
 svn_error_t *
 svn_fs_x__revision_proplist(apr_hash_t **proplist_p,
                             svn_fs_t *fs,

Modified: subversion/trunk/subversion/libsvn_fs_x/fs_x.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs_x.h?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs_x.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs_x.h Wed Oct 29 22:27:02 2014
@@ -51,15 +51,6 @@ svn_error_t *svn_fs_x__youngest_rev(svn_
                                     svn_fs_t *fs,
                                     apr_pool_t *pool);
 
-/* For revision REV in fileysystem FS, open the revision (or packed rev)
-   file and seek to the start of the revision.  Return it in *FILE, and
-   use POOL for allocations. */
-svn_error_t *
-svn_fs_x__open_pack_or_rev_file(apr_file_t **file,
-                                svn_fs_t *fs,
-                                svn_revnum_t rev,
-                                apr_pool_t *pool);
-
 /* Return SVN_ERR_FS_NO_SUCH_REVISION if the given revision REV is newer
    than the current youngest revision in FS or is simply not a valid
    revision number, else return success. */

Modified: subversion/trunk/subversion/libsvn_fs_x/index.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/index.c?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/index.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/index.c Wed Oct 29 22:27:02 2014
@@ -37,6 +37,7 @@
 
 #include "svn_private_config.h"
 #include "temp_serializer.h"
+#include "fs_x.h"
 
 #include "../libsvn_fs/fs-loader.h"
 
@@ -159,7 +160,7 @@ typedef struct value_position_pair_t
 /* State of a prefetching packed number stream.  It will read compressed
  * index data efficiently and present it as a series of non-packed uint64.
  */
-typedef struct packed_number_stream_t
+struct svn_fs_x__packed_number_stream_t
 {
   /* underlying data file containing the packed values */
   apr_file_t *file;
@@ -185,14 +186,14 @@ typedef struct packed_number_stream_t
 
   /* buffer for prefetched values */
   value_position_pair_t buffer[MAX_NUMBER_PREFETCH];
-} packed_number_stream_t;
+};
 
 /* Return an svn_error_t * object for error ERR on STREAM with the given
  * MESSAGE string.  The latter must have a placeholder for the index file
  * name ("%s") and the current read offset (e.g. "0x%lx").
  */
 static svn_error_t *
-stream_error_create(packed_number_stream_t *stream,
+stream_error_create(svn_fs_x__packed_number_stream_t *stream,
                     apr_status_t err,
                     const char *message)
 {
@@ -215,7 +216,7 @@ stream_error_create(packed_number_stream
  */
 SVN__PREVENT_INLINE
 static svn_error_t *
-packed_stream_read(packed_number_stream_t *stream)
+packed_stream_read(svn_fs_x__packed_number_stream_t *stream)
 {
   unsigned char buffer[MAX_NUMBER_PREFETCH];
   apr_size_t read = 0;
@@ -310,18 +311,19 @@ packed_stream_read(packed_number_stream_
  * Use POOL for allocations.
  */
 static svn_error_t *
-packed_stream_open(packed_number_stream_t **stream,
+packed_stream_open(svn_fs_x__packed_number_stream_t **stream,
                    const char *file_name,
                    apr_size_t block_size,
                    apr_pool_t *pool)
 {
-  packed_number_stream_t *result = apr_palloc(pool, sizeof(*result));
+  svn_fs_x__packed_number_stream_t *result
+    = apr_palloc(pool, sizeof(*result));
   result->pool = svn_pool_create(pool);
 
   SVN_ERR(svn_io_file_open(&result->file, file_name,
                            APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
                            result->pool));
-  
+
   result->used = 0;
   result->current = 0;
   result->start_offset = 0;
@@ -335,9 +337,8 @@ packed_stream_open(packed_number_stream_
 
 /* Close STREAM which may be NULL.
  */
-SVN__FORCE_INLINE
-static svn_error_t *
-packed_stream_close(packed_number_stream_t *stream)
+svn_error_t *
+svn_fs_x__packed_stream_close(svn_fs_x__packed_number_stream_t *stream)
 {
   if (stream)
     {
@@ -357,7 +358,7 @@ packed_stream_close(packed_number_stream
 SVN__FORCE_INLINE
 static svn_error_t*
 packed_stream_get(apr_uint64_t *value,
-                  packed_number_stream_t *stream)
+                  svn_fs_x__packed_number_stream_t *stream)
 {
   if (stream->current == stream->used)
     SVN_ERR(packed_stream_read(stream));
@@ -372,7 +373,7 @@ packed_stream_get(apr_uint64_t *value,
  * whether the given OFFSET is valid.
  */
 static void
-packed_stream_seek(packed_number_stream_t *stream,
+packed_stream_seek(svn_fs_x__packed_number_stream_t *stream,
                    apr_off_t offset)
 {
   if (   stream->used == 0
@@ -403,7 +404,7 @@ packed_stream_seek(packed_number_stream_
  * can be found.
  */
 static apr_off_t
-packed_stream_offset(packed_number_stream_t *stream)
+packed_stream_offset(svn_fs_x__packed_number_stream_t *stream)
 {
   return stream->current == 0
        ? stream->start_offset
@@ -993,7 +994,7 @@ l2p_header_access_func(void **out,
  */
 static svn_error_t *
 expand_rle(apr_array_header_t *values,
-           packed_number_stream_t *stream,
+           svn_fs_x__packed_number_stream_t *stream,
            apr_size_t count)
 {
   apr_array_clear(values);
@@ -1026,13 +1027,34 @@ expand_rle(apr_array_header_t *values,
   return SVN_NO_ERROR;
 }
 
+/* If REV_FILE->L2P_STREAM is NULL, create a new stream for the log-to-phys
+ * index for REVISION in FS and return it in REV_FILE.
+ */
+static svn_error_t *
+auto_open_l2p_index(svn_fs_x__revision_file_t *rev_file,
+                    svn_fs_t *fs,
+                    svn_revnum_t revision)
+{
+  if (rev_file->l2p_stream == NULL)
+    {
+      fs_x_data_t *ffd = fs->fsap_data;
+      SVN_ERR(packed_stream_open(&rev_file->l2p_stream,
+                                 svn_fs_x__path_l2p_index(fs, revision,
+                                                          rev_file->pool),
+                                 ffd->block_size,
+                                 rev_file->pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Read the header data structure of the log-to-phys index for REVISION
- * in FS and return it in *HEADER.  To maximize efficiency, use or return
- * the data stream in *STREAM.  Use POOL for allocations.
+ * in FS and return it in *HEADER.  Read data from REV_FILE.
+ * Use POOL for allocations.
  */
 static svn_error_t *
 get_l2p_header_body(l2p_header_t **header,
-                    packed_number_stream_t **stream,
+                    svn_fs_x__revision_file_t *rev_file,
                     svn_fs_t *fs,
                     svn_revnum_t revision,
                     apr_pool_t *pool)
@@ -1051,21 +1073,17 @@ get_l2p_header_body(l2p_header_t **heade
   key.revision = base_revision(fs, revision);
   key.second = svn_fs_x__is_packed_rev(fs, revision);
 
-  if (*stream == NULL)
-    SVN_ERR(packed_stream_open(stream, 
-                               svn_fs_x__path_l2p_index(fs, revision, pool),
-                               ffd->block_size, pool));
-  else
-    packed_stream_seek(*stream, 0);
+  SVN_ERR(auto_open_l2p_index(rev_file, fs, revision));
+  packed_stream_seek(rev_file->l2p_stream, 0);
 
   /* read the table sizes */
-  SVN_ERR(packed_stream_get(&value, *stream));
+  SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
   result->first_revision = (svn_revnum_t)value;
-  SVN_ERR(packed_stream_get(&value, *stream));
+  SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
   result->revision_count = (int)value;
-  SVN_ERR(packed_stream_get(&value, *stream));
+  SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
   result->page_size = (apr_uint32_t)value;
-  SVN_ERR(packed_stream_get(&value, *stream));
+  SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
   page_count = (apr_size_t)value;
 
   if (result->first_revision > revision
@@ -1085,7 +1103,8 @@ get_l2p_header_body(l2p_header_t **heade
   /* read per-revision page table sizes (i.e. number of pages per rev) */
   page_table_index = 0;
   result->page_table_index[0] = page_table_index;
-  SVN_ERR(expand_rle(expanded_values, *stream, result->revision_count));
+  SVN_ERR(expand_rle(expanded_values, rev_file->l2p_stream,
+                     result->revision_count));
   for (i = 0; i < result->revision_count; ++i)
     {
       page_table_index
@@ -1096,14 +1115,14 @@ get_l2p_header_body(l2p_header_t **heade
   /* read actual page tables */
   for (page = 0; page < page_count; ++page)
     {
-      SVN_ERR(packed_stream_get(&value, *stream));
+      SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
       result->page_table[page].size = (apr_uint32_t)value;
-      SVN_ERR(packed_stream_get(&value, *stream));
+      SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
       result->page_table[page].entry_count = (apr_uint32_t)value;
     }
 
   /* correct the page description offsets */
-  offset = packed_stream_offset(*stream);
+  offset = packed_stream_offset(rev_file->l2p_stream);
   for (page = 0; page < page_count; ++page)
     {
       result->page_table[page].offset = offset;
@@ -1124,7 +1143,7 @@ get_l2p_header_body(l2p_header_t **heade
  */
 static svn_error_t *
 get_l2p_page_info(l2p_page_info_baton_t *baton,
-                  packed_number_stream_t **stream,
+                  svn_fs_x__revision_file_t *rev_file,
                   svn_fs_t *fs,
                   apr_pool_t *pool)
 {
@@ -1145,7 +1164,7 @@ get_l2p_page_info(l2p_page_info_baton_t 
     return SVN_NO_ERROR;
 
   /* read from disk, cache and copy the result */
-  SVN_ERR(get_l2p_header_body(&result, stream, fs, baton->revision, pool));
+  SVN_ERR(get_l2p_header_body(&result, rev_file, fs, baton->revision, pool));
   SVN_ERR(l2p_header_copy(baton, result, result->page_table,
                           result->page_table_index, pool));
 
@@ -1158,7 +1177,7 @@ get_l2p_page_info(l2p_page_info_baton_t 
  */
 static svn_error_t *
 get_l2p_header(l2p_header_t **header,
-               packed_number_stream_t **stream,
+               svn_fs_x__revision_file_t *rev_file,
                svn_fs_t *fs,
                svn_revnum_t revision,
                apr_pool_t *pool)
@@ -1176,7 +1195,7 @@ get_l2p_header(l2p_header_t **header,
     return SVN_NO_ERROR;
 
   /* read from disk and cache the result */
-  SVN_ERR(get_l2p_header_body(header, stream, fs, revision, pool));
+  SVN_ERR(get_l2p_header_body(header, rev_file, fs, revision, pool));
 
   return SVN_NO_ERROR;
 }
@@ -1188,13 +1207,12 @@ get_l2p_header(l2p_header_t **header,
  */
 static svn_error_t *
 get_l2p_page(l2p_page_t **page,
-             packed_number_stream_t **stream,
+             svn_fs_x__revision_file_t *rev_file,
              svn_fs_t *fs,
              svn_revnum_t start_revision,
              l2p_page_table_entry_t *table_entry,
              apr_pool_t *pool)
 {
-  fs_x_data_t *ffd = fs->fsap_data;
   apr_uint64_t value, last_value = 0;
   apr_uint32_t i;
   l2p_page_t *result = apr_pcalloc(pool, sizeof(*result));
@@ -1202,14 +1220,8 @@ get_l2p_page(l2p_page_t **page,
   apr_off_t *container_offsets;
 
   /* open index file and select page */
-  if (*stream == NULL)
-    SVN_ERR(packed_stream_open(stream,
-                               svn_fs_x__path_l2p_index(fs, start_revision,
-                                                        pool),
-                               ffd->block_size,
-                               pool));
-
-  packed_stream_seek(*stream, table_entry->offset);
+  SVN_ERR(auto_open_l2p_index(rev_file, fs, start_revision));
+  packed_stream_seek(rev_file->l2p_stream, table_entry->offset);
 
   /* initialize the page content */
   result->entry_count = table_entry->entry_count;
@@ -1220,11 +1232,11 @@ get_l2p_page(l2p_page_t **page,
 
   /* container offsets array */
 
-  SVN_ERR(packed_stream_get(&container_count, *stream));
+  SVN_ERR(packed_stream_get(&container_count, rev_file->l2p_stream));
   container_offsets = apr_pcalloc(pool, container_count * sizeof(*result));
   for (i = 0; i < container_count; ++i)
     {
-      SVN_ERR(packed_stream_get(&value, *stream));
+      SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
       last_value += value;
       container_offsets[i] = (apr_off_t)last_value - 1;
       /* '-1' is represented as '0' in the index file */
@@ -1233,7 +1245,7 @@ get_l2p_page(l2p_page_t **page,
   /* read all page entries (offsets in rev file and container sub-items) */
   for (i = 0; i < result->entry_count; ++i)
     {
-      SVN_ERR(packed_stream_get(&value, *stream));
+      SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
       if (value == 0)
         {
           result->offsets[i] = -1;
@@ -1242,7 +1254,7 @@ get_l2p_page(l2p_page_t **page,
       else if (value <= container_count)
         {
           result->offsets[i] = container_offsets[value - 1];
-          SVN_ERR(packed_stream_get(&value, *stream));
+          SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
           result->sub_items[i] = (apr_uint32_t)value;
         }
       else
@@ -1423,7 +1435,7 @@ get_l2p_page_table(apr_array_header_t *p
 static svn_error_t *
 prefetch_l2p_pages(svn_boolean_t *end,
                    svn_fs_t *fs,
-                   packed_number_stream_t *stream,
+                   svn_fs_x__revision_file_t *rev_file,
                    svn_revnum_t first_revision,
                    svn_revnum_t revision,
                    apr_array_header_t *pages,
@@ -1482,7 +1494,7 @@ prefetch_l2p_pages(svn_boolean_t *end,
           /* no in cache -> read from stream (data already buffered in APR)
            * and cache the result */
           l2p_page_t *page = NULL;
-          SVN_ERR(get_l2p_page(&page, &stream, fs, first_revision,
+          SVN_ERR(get_l2p_page(&page, rev_file, fs, first_revision,
                                entry, iterpool));
 
           SVN_ERR(svn_cache__set(ffd->l2p_page_cache, &key, page,
@@ -1503,6 +1515,7 @@ static svn_error_t *
 l2p_index_lookup(apr_off_t *offset,
                  apr_uint32_t *sub_item,
                  svn_fs_t *fs,
+                 svn_fs_x__revision_file_t *rev_file,
                  svn_revnum_t revision,
                  apr_uint64_t item_index,
                  apr_pool_t *pool)
@@ -1511,7 +1524,6 @@ l2p_index_lookup(apr_off_t *offset,
   l2p_page_info_baton_t info_baton;
   l2p_page_baton_t page_baton;
   l2p_page_t *page = NULL;
-  packed_number_stream_t *stream = NULL;
   svn_fs_x__page_cache_key_t key = { 0 };
   svn_boolean_t is_cached = FALSE;
   void *dummy = NULL;
@@ -1520,7 +1532,7 @@ l2p_index_lookup(apr_off_t *offset,
    * access the l2p index page for (REVISION,ITEM_INDEX)*/
   info_baton.revision = revision;
   info_baton.item_index = item_index;
-  SVN_ERR(get_l2p_page_info(&info_baton, &stream, fs, pool));
+  SVN_ERR(get_l2p_page_info(&info_baton, rev_file, fs, pool));
 
   /* try to find the page in the cache and get the OFFSET from it */
   page_baton.revision = revision;
@@ -1553,7 +1565,7 @@ l2p_index_lookup(apr_off_t *offset,
       apr_off_t min_offset = max_offset - ffd->block_size;
 
       /* read the relevant page */
-      SVN_ERR(get_l2p_page(&page, &stream, fs, info_baton.first_revision,
+      SVN_ERR(get_l2p_page(&page, rev_file, fs, info_baton.first_revision,
                            &info_baton.entry, pool));
 
       /* cache the page and extract the result we need */
@@ -1573,7 +1585,7 @@ l2p_index_lookup(apr_off_t *offset,
                                : -1;
           svn_pool_clear(iterpool);
 
-          SVN_ERR(prefetch_l2p_pages(&end, fs, stream,
+          SVN_ERR(prefetch_l2p_pages(&end, fs, rev_file,
                                      info_baton.first_revision,
                                      prefetch_revision, pages,
                                      excluded_page_no, min_offset,
@@ -1587,7 +1599,7 @@ l2p_index_lookup(apr_off_t *offset,
         {
           svn_pool_clear(iterpool);
 
-          SVN_ERR(prefetch_l2p_pages(&end, fs, stream,
+          SVN_ERR(prefetch_l2p_pages(&end, fs, rev_file,
                                      info_baton.first_revision,
                                      prefetch_revision, pages, -1,
                                      min_offset, max_offset, iterpool));
@@ -1596,8 +1608,6 @@ l2p_index_lookup(apr_off_t *offset,
       svn_pool_destroy(iterpool);
     }
 
-  SVN_ERR(packed_stream_close(stream));
-
   *offset = page_baton.offset;
   *sub_item = page_baton.sub_item;
 
@@ -1658,13 +1668,14 @@ svn_fs_x__l2p_get_max_ids(apr_array_head
   l2p_header_t *header = NULL;
   svn_revnum_t revision;
   svn_revnum_t last_rev = (svn_revnum_t)(start_rev + count);
-  packed_number_stream_t *stream = NULL;
+  svn_fs_x__revision_file_t *rev_file;
   apr_pool_t *header_pool = svn_pool_create(pool);
 
   /* read index master data structure for the index covering START_REV */
-  SVN_ERR(get_l2p_header(&header, &stream, fs, start_rev, header_pool));
-  SVN_ERR(packed_stream_close(stream));
-  stream = NULL;
+  SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start_rev,
+                                          header_pool));
+  SVN_ERR(get_l2p_header(&header, rev_file, fs, start_rev, header_pool));
+  SVN_ERR(svn_fs_x__close_revision_file(rev_file));
 
   /* Determine the length of the item index list for each rev.
    * Read new index headers as required. */
@@ -1682,10 +1693,11 @@ svn_fs_x__l2p_get_max_ids(apr_array_head
            * the number of items in a revision, i.e. there is no consistency
            * issue here. */
           svn_pool_clear(header_pool);
-          SVN_ERR(get_l2p_header(&header, &stream, fs, revision,
+          SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, revision,
+                                                  header_pool));
+          SVN_ERR(get_l2p_header(&header, rev_file, fs, revision,
                                  header_pool));
-          SVN_ERR(packed_stream_close(stream));
-          stream = NULL;
+          SVN_ERR(svn_fs_x__close_revision_file(rev_file));
         }
 
       /* in a revision with N index pages, the first N-1 index pages are
@@ -2100,19 +2112,36 @@ p2l_page_info_func(void **out,
   return SVN_NO_ERROR;
 }
 
+/* If REV_FILE->L2P_STREAM is NULL, create a new stream for the log-to-phys
+ * index for REVISION in FS and return it in REV_FILE.
+ */
+static svn_error_t *
+auto_open_p2l_index(svn_fs_x__revision_file_t *rev_file,
+                    svn_fs_t *fs,
+                    svn_revnum_t revision)
+{
+  if (rev_file->p2l_stream == NULL)
+    {
+      fs_x_data_t *ffd = fs->fsap_data;
+      SVN_ERR(packed_stream_open(&rev_file->p2l_stream,
+                                 svn_fs_x__path_p2l_index(fs, revision,
+                                                          rev_file->pool),
+                                 ffd->block_size,
+                                 rev_file->pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Read the header data structure of the phys-to-log index for REVISION in
- * FS and return it in *HEADER. 
- * 
- * To maximize efficiency, use or return the data stream in *STREAM.
- * If *STREAM is yet to be constructed, do so in STREAM_POOL.
- * Use POOL for allocations.
+ * FS and return it in *HEADER, allocated in POOL. Use REV_FILE to access
+ * on-disk data.
  */
 static svn_error_t *
 get_p2l_header(p2l_header_t **header,
-               packed_number_stream_t **stream,
+               svn_fs_x__revision_file_t *rev_file,
                svn_fs_t *fs,
                svn_revnum_t revision,
-               apr_pool_t *stream_pool,
                apr_pool_t *pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
@@ -2134,25 +2163,20 @@ get_p2l_header(p2l_header_t **header,
 
   /* not found -> must read it from disk.
    * Open index file or position read pointer to the begin of the file */
-  if (*stream == NULL)
-    SVN_ERR(packed_stream_open(stream,
-                               svn_fs_x__path_p2l_index(fs, key.revision,
-                                                        pool),
-                               ffd->block_size, stream_pool));
-  else
-    packed_stream_seek(*stream, 0);
+  SVN_ERR(auto_open_p2l_index(rev_file, fs, key.revision));
+  packed_stream_seek(rev_file->p2l_stream, 0);
 
   /* allocate result data structure */
   result = apr_pcalloc(pool, sizeof(*result));
   
   /* read table sizes and allocate page array */
-  SVN_ERR(packed_stream_get(&value, *stream));
+  SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
   result->first_revision = (svn_revnum_t)value;
-  SVN_ERR(packed_stream_get(&value, *stream));
+  SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
   result->file_size = value;
-  SVN_ERR(packed_stream_get(&value, *stream));
+  SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
   result->page_size = value;
-  SVN_ERR(packed_stream_get(&value, *stream));
+  SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
   result->page_count = (apr_size_t)value;
   result->offsets
     = apr_pcalloc(pool, (result->page_count + 1) * sizeof(*result->offsets));
@@ -2161,12 +2185,12 @@ get_p2l_header(p2l_header_t **header,
   result->offsets[0] = 0;
   for (i = 0; i < result->page_count; ++i)
     {
-      SVN_ERR(packed_stream_get(&value, *stream));
+      SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
       result->offsets[i+1] = result->offsets[i] + (apr_off_t)value;
     }
 
   /* correct the offset values */
-  offset = packed_stream_offset(*stream);
+  offset = packed_stream_offset(rev_file->p2l_stream);
   for (i = 0; i <= result->page_count; ++i)
     result->offsets[i] += offset;
 
@@ -2181,17 +2205,14 @@ get_p2l_header(p2l_header_t **header,
 
 /* Read the header data structure of the phys-to-log index for revision
  * BATON->REVISION in FS.  Return in *BATON all info relevant to read the
- * index page for the rev / pack file offset BATON->OFFSET.
- * 
- * To maximize efficiency, use or return the data stream in *STREAM.
- * If *STREAM is yet to be constructed, do so in STREAM_POOL.
+ * index page for the rev / pack file offset BATON->OFFSET.  Use REV_FILE
+ * to access on-disk data.
  * Use POOL for allocations.
  */
 static svn_error_t *
 get_p2l_page_info(p2l_page_info_baton_t *baton,
-                  packed_number_stream_t **stream,
+                  svn_fs_x__revision_file_t *rev_file,
                   svn_fs_t *fs,
-                  apr_pool_t *stream_pool,
                   apr_pool_t *pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
@@ -2209,8 +2230,7 @@ get_p2l_page_info(p2l_page_info_baton_t 
   if (is_cached)
     return SVN_NO_ERROR;
 
-  SVN_ERR(get_p2l_header(&header, stream, fs, baton->revision,
-                         stream_pool, pool));
+  SVN_ERR(get_p2l_header(&header, rev_file, fs, baton->revision, pool));
 
   /* copy the requested info into *BATON */
   p2l_page_info_copy(baton, header, header->offsets);
@@ -2223,7 +2243,7 @@ get_p2l_page_info(p2l_page_info_baton_t 
  * be moved forward by the size of entry.  Use POOL for allocations.
  */
 static svn_error_t *
-read_entry(packed_number_stream_t *stream,
+read_entry(svn_fs_x__packed_number_stream_t *stream,
            apr_off_t *item_offset,
            svn_revnum_t revision,
            apr_array_header_t *result,
@@ -2285,17 +2305,15 @@ read_entry(packed_number_stream_t *strea
  */
 static svn_error_t *
 get_p2l_page(apr_array_header_t **entries,
-             packed_number_stream_t **stream,
+             svn_fs_x__revision_file_t *rev_file,
              svn_fs_t *fs,
              svn_revnum_t start_revision,
              apr_off_t start_offset,
              apr_off_t next_offset,
              apr_off_t page_start,
              apr_uint64_t page_size,
-             apr_pool_t *stream_pool,
              apr_pool_t *pool)
 {
-  fs_x_data_t *ffd = fs->fsap_data;
   apr_uint64_t value;
   apr_array_header_t *result
     = apr_array_make(pool, 16, sizeof(svn_fs_x__p2l_entry_t));
@@ -2303,23 +2321,20 @@ get_p2l_page(apr_array_header_t **entrie
   apr_off_t offset;
 
   /* open index and navigate to page start */
-  if (*stream == NULL)
-    SVN_ERR(packed_stream_open(stream,
-                        svn_fs_x__path_p2l_index(fs, start_revision, pool),
-                        ffd->block_size, stream_pool));
-  packed_stream_seek(*stream, start_offset);
+  SVN_ERR(auto_open_p2l_index(rev_file, fs, start_revision));
+  packed_stream_seek(rev_file->p2l_stream, start_offset);
 
   /* read rev file offset of the first page entry (all page entries will
    * only store their sizes). */
-  SVN_ERR(packed_stream_get(&value, *stream));
+  SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
   item_offset = (apr_off_t)value;
 
   /* read all entries of this page */
   do
     {
-      SVN_ERR(read_entry(*stream, &item_offset, start_revision, result,
-                         pool));
-      offset = packed_stream_offset(*stream);
+      SVN_ERR(read_entry(rev_file->p2l_stream, &item_offset, start_revision,
+                         result, pool));
+      offset = packed_stream_offset(rev_file->p2l_stream);
     }
   while (offset < next_offset);
 
@@ -2327,10 +2342,10 @@ get_p2l_page(apr_array_header_t **entrie
    * entry of the next page */
   if (item_offset < page_start + page_size)
     {
-      SVN_ERR(packed_stream_get(&value, *stream));
+      SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
       item_offset = (apr_off_t)value;
-      SVN_ERR(read_entry(*stream, &item_offset, start_revision, result,
-                         pool));
+      SVN_ERR(read_entry(rev_file->p2l_stream, &item_offset, start_revision,
+                         result, pool));
     }
 
   *entries = result;
@@ -2353,10 +2368,9 @@ static svn_error_t *
 prefetch_p2l_page(svn_boolean_t *end,
                   int *leaking_bucket,
                   svn_fs_t *fs,
-                  packed_number_stream_t **stream,
+                  svn_fs_x__revision_file_t *rev_file,
                   p2l_page_info_baton_t *baton,
                   apr_off_t min_offset,
-                  apr_pool_t *stream_pool,
                   apr_pool_t *scratch_pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
@@ -2367,7 +2381,7 @@ prefetch_p2l_page(svn_boolean_t *end,
   /* fetch the page info */
   *end = FALSE;
   baton->revision = baton->first_revision;
-  SVN_ERR(get_p2l_page_info(baton, stream, fs, stream_pool, scratch_pool));
+  SVN_ERR(get_p2l_page_info(baton, rev_file, fs, scratch_pool));
   if (baton->start_offset < min_offset)
     {
       /* page outside limits -> stop prefetching */
@@ -2396,13 +2410,12 @@ prefetch_p2l_page(svn_boolean_t *end,
   ++*leaking_bucket;
 
   /* read from disk */
-  SVN_ERR(get_p2l_page(&page, stream, fs,
+  SVN_ERR(get_p2l_page(&page, rev_file, fs,
                        baton->first_revision,
                        baton->start_offset,
                        baton->next_offset,
                        baton->page_start,
                        baton->page_size,
-                       stream_pool,
                        scratch_pool));
 
   /* and put it into our cache */
@@ -2420,7 +2433,7 @@ prefetch_p2l_page(svn_boolean_t *end,
 static svn_error_t *
 get_p2l_keys(p2l_page_info_baton_t *page_info_p,
              svn_fs_x__page_cache_key_t *key_p,
-             packed_number_stream_t **stream,
+             svn_fs_x__revision_file_t *rev_file,
              svn_fs_t *fs,
              svn_revnum_t revision,
              apr_off_t offset,
@@ -2432,21 +2445,18 @@ get_p2l_keys(p2l_page_info_baton_t *page
    * contents at pack / rev file position OFFSET. */
   page_info.offset = offset;
   page_info.revision = revision;
-  SVN_ERR(get_p2l_page_info(&page_info, stream, fs, pool, pool));
+  SVN_ERR(get_p2l_page_info(&page_info, rev_file, fs, pool));
 
   /* if the offset refers to a non-existent page, bail out */
   if (page_info.page_count <= page_info.page_no)
-    {
-      SVN_ERR(packed_stream_close(*stream));
-      return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
-                               _("Offset %s too large in revision %ld"),
-                               apr_off_t_toa(pool, offset), revision);
-    }
+    return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
+                             _("Offset %s too large in revision %ld"),
+                             apr_off_t_toa(pool, offset), revision);
 
   /* return results */
   if (page_info_p)
     *page_info_p = page_info;
-  
+
   /* construct cache key */
   if (key_p)
     {
@@ -2567,7 +2577,7 @@ p2l_entries_func(void **out,
  */
 static svn_error_t *
 p2l_index_lookup(apr_array_header_t *entries,
-                 packed_number_stream_t **stream,
+                 svn_fs_x__revision_file_t *rev_file,
                  svn_fs_t *fs,
                  svn_revnum_t revision,
                  apr_off_t block_start,
@@ -2589,7 +2599,7 @@ p2l_index_lookup(apr_array_header_t *ent
   SVN_ERR_ASSERT(block_start < block_end);
 
   /* look for the fist page of the range in our cache */
-  SVN_ERR(get_p2l_keys(&page_info, &key, stream, fs, revision, block_start,
+  SVN_ERR(get_p2l_keys(&page_info, &key, rev_file, fs, revision, block_start,
                        pool));
   SVN_ERR(svn_cache__get_partial((void**)&local_result, &is_cached,
                                  ffd->p2l_page_cache, &key, p2l_entries_func,
@@ -2620,19 +2630,18 @@ p2l_index_lookup(apr_array_header_t *ent
       while (prefetch_info.offset >= prefetch_info.page_size && !end)
         {
           prefetch_info.offset -= prefetch_info.page_size;
-          SVN_ERR(prefetch_p2l_page(&end, &leaking_bucket, fs, stream,
-                                    &prefetch_info, min_offset,
-                                    pool, iterpool));
+          SVN_ERR(prefetch_p2l_page(&end, &leaking_bucket, fs, rev_file,
+                                    &prefetch_info, min_offset, iterpool));
           svn_pool_clear(iterpool);
         }
 
       /* fetch page from disk and put it into the cache */
-      SVN_ERR(get_p2l_page(&page_entries, stream, fs,
+      SVN_ERR(get_p2l_page(&page_entries, rev_file, fs,
                            page_info.first_revision,
                            page_info.start_offset,
                            page_info.next_offset,
                            page_info.page_start,
-                           page_info.page_size, pool, iterpool));
+                           page_info.page_size, iterpool));
 
       SVN_ERR(svn_cache__set(ffd->p2l_page_cache, &key, page_entries,
                              iterpool));
@@ -2650,9 +2659,8 @@ p2l_index_lookup(apr_array_header_t *ent
              && !end)
         {
           prefetch_info.offset += prefetch_info.page_size;
-          SVN_ERR(prefetch_p2l_page(&end, &leaking_bucket, fs, stream,
-                                    &prefetch_info, min_offset,
-                                    pool, iterpool));
+          SVN_ERR(prefetch_p2l_page(&end, &leaking_bucket, fs, rev_file,
+                                    &prefetch_info, min_offset, iterpool));
           svn_pool_clear(iterpool);
         }
 
@@ -2700,13 +2708,12 @@ p2l_index_lookup(apr_array_header_t *ent
 svn_error_t *
 svn_fs_x__p2l_index_lookup(apr_array_header_t **entries,
                            svn_fs_t *fs,
+                           svn_fs_x__revision_file_t *rev_file,
                            svn_revnum_t revision,
                            apr_off_t block_start,
                            apr_off_t block_size,
                            apr_pool_t *pool)
 {
-  packed_number_stream_t *stream = NULL;
-
   apr_off_t block_end = block_start + block_size;
 
   /* the receiving container */
@@ -2720,7 +2727,7 @@ svn_fs_x__p2l_index_lookup(apr_array_hea
   while (block_start < block_end)
     {
       svn_fs_x__p2l_entry_t *entry;
-      SVN_ERR(p2l_index_lookup(result, &stream, fs, revision, block_start,
+      SVN_ERR(p2l_index_lookup(result, rev_file, fs, revision, block_start,
                                block_end, pool));
       SVN_ERR_ASSERT(result->nelts > 0);
 
@@ -2742,9 +2749,6 @@ svn_fs_x__p2l_index_lookup(apr_array_hea
       last_count = result->nelts;
     }
 
-  /* make sure we close files after usage */
-  SVN_ERR(packed_stream_close(stream));
-
   *entries = result;
   return SVN_NO_ERROR;
 }
@@ -2819,7 +2823,7 @@ p2l_entry_lookup_func(void **out,
 
 static svn_error_t *
 p2l_entry_lookup(svn_fs_x__p2l_entry_t **entry_p,
-                 packed_number_stream_t **stream,
+                 svn_fs_x__revision_file_t *rev_file,
                  svn_fs_t *fs,
                  svn_revnum_t revision,
                  apr_off_t offset,
@@ -2831,7 +2835,8 @@ p2l_entry_lookup(svn_fs_x__p2l_entry_t *
   p2l_page_info_baton_t page_info;
 
   /* look for this info in our cache */
-  SVN_ERR(get_p2l_keys(&page_info, &key, stream, fs, revision, offset, pool));
+  SVN_ERR(get_p2l_keys(&page_info, &key, rev_file, fs, revision, offset,
+                       pool));
   SVN_ERR(svn_cache__get_partial((void**)entry_p, &is_cached,
                                  ffd->p2l_page_cache, &key,
                                  p2l_entry_lookup_func, &offset, pool));
@@ -2840,7 +2845,7 @@ p2l_entry_lookup(svn_fs_x__p2l_entry_t *
       /* do a standard index lookup.  This is will automatically prefetch
        * data to speed up future lookups. */
       apr_array_header_t *entries = apr_array_make(pool, 1, sizeof(**entry_p));
-      SVN_ERR(p2l_index_lookup(entries, stream, fs, revision, offset,
+      SVN_ERR(p2l_index_lookup(entries, rev_file, fs, revision, offset,
                                offset + 1, pool));
 
       /* Find the entry that we want. */
@@ -2854,17 +2859,18 @@ p2l_entry_lookup(svn_fs_x__p2l_entry_t *
 svn_error_t *
 svn_fs_x__p2l_entry_lookup(svn_fs_x__p2l_entry_t **entry_p,
                            svn_fs_t *fs,
+                           svn_fs_x__revision_file_t *rev_file,
                            svn_revnum_t revision,
                            apr_off_t offset,
                            apr_pool_t *pool)
 {
-  packed_number_stream_t *stream = NULL;
+  svn_fs_x__packed_number_stream_t *stream = NULL;
 
   /* look for this info in our cache */
-  SVN_ERR(p2l_entry_lookup(entry_p, &stream, fs, revision, offset, pool));
+  SVN_ERR(p2l_entry_lookup(entry_p, rev_file, fs, revision, offset, pool));
 
   /* make sure we close files after usage */
-  SVN_ERR(packed_stream_close(stream));
+  SVN_ERR(svn_fs_x__packed_stream_close(stream));
 
   return SVN_NO_ERROR;
 }
@@ -2911,13 +2917,13 @@ p2l_item_lookup_func(void **out,
 svn_error_t *
 svn_fs_x__p2l_item_lookup(svn_fs_x__id_part_t **item,
                           svn_fs_t *fs,
+                          svn_fs_x__revision_file_t *rev_file,
                           svn_revnum_t revision,
                           apr_off_t offset,
                           apr_uint32_t sub_item,
                           apr_pool_t *pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
-  packed_number_stream_t *stream = NULL;
   svn_fs_x__page_cache_key_t key = { 0 };
   svn_boolean_t is_cached = FALSE;
   p2l_page_info_baton_t page_info;
@@ -2926,7 +2932,7 @@ svn_fs_x__p2l_item_lookup(svn_fs_x__id_p
   *item = NULL;
 
   /* look for this info in our cache */
-  SVN_ERR(get_p2l_keys(&page_info, &key, &stream, fs, revision, offset,
+  SVN_ERR(get_p2l_keys(&page_info, &key, rev_file, fs, revision, offset,
                        pool));
   baton.offset = offset;
   baton.sub_item = sub_item;
@@ -2938,16 +2944,13 @@ svn_fs_x__p2l_item_lookup(svn_fs_x__id_p
       /* do a standard index lookup.  This is will automatically prefetch
        * data to speed up future lookups. */
       svn_fs_x__p2l_entry_t *entry;
-      SVN_ERR(p2l_entry_lookup(&entry, &stream, fs, revision, offset, pool));
+      SVN_ERR(p2l_entry_lookup(&entry, rev_file, fs, revision, offset, pool));
 
       /* return result */
       if (entry && entry->item_count > sub_item)
         *item = apr_pmemdup(pool, entry->items + sub_item, sizeof(**item));
     }
 
-  /* make sure we close files after usage */
-  SVN_ERR(packed_stream_close(stream));
-
   return SVN_NO_ERROR;
 }
 
@@ -2971,11 +2974,11 @@ p2l_get_max_offset_func(void **out,
 svn_error_t *
 svn_fs_x__p2l_get_max_offset(apr_off_t *offset,
                              svn_fs_t *fs,
+                             svn_fs_x__revision_file_t *rev_file,
                              svn_revnum_t revision,
                              apr_pool_t *pool)
 {
   fs_x_data_t *ffd = fs->fsap_data;
-  packed_number_stream_t *stream = NULL;
   p2l_header_t *header;
   svn_boolean_t is_cached = FALSE;
   apr_off_t *offset_p;
@@ -2994,12 +2997,9 @@ svn_fs_x__p2l_get_max_offset(apr_off_t *
       return SVN_NO_ERROR;
     }
 
-  SVN_ERR(get_p2l_header(&header, &stream, fs, revision, pool, pool));
+  SVN_ERR(get_p2l_header(&header, rev_file, fs, revision, pool));
   *offset = header->file_size;
 
-  /* make sure we close files after usage */
-  SVN_ERR(packed_stream_close(stream));
-
   return SVN_NO_ERROR;
 }
 
@@ -3007,6 +3007,7 @@ svn_error_t *
 svn_fs_x__item_offset(apr_off_t *offset,
                       apr_uint32_t *sub_item,
                       svn_fs_t *fs,
+                      svn_fs_x__revision_file_t *rev_file,
                       const svn_fs_x__id_part_t *item_id,
                       apr_pool_t *pool)
 {
@@ -3015,7 +3016,7 @@ svn_fs_x__item_offset(apr_off_t *offset,
                                    svn_fs_x__get_txn_id(item_id->change_set),
                                    item_id->number, pool));
   else
-    SVN_ERR(l2p_index_lookup(offset, sub_item, fs,
+    SVN_ERR(l2p_index_lookup(offset, sub_item, fs, rev_file,
                              svn_fs_x__get_revnum(item_id->change_set),
                              item_id->number, pool));
 

Modified: subversion/trunk/subversion/libsvn_fs_x/index.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/index.h?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/index.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/index.h Wed Oct 29 22:27:02 2014
@@ -24,6 +24,7 @@
 #define SVN_LIBSVN_FS__INDEX_H
 
 #include "fs.h"
+#include "rev_file.h"
 
 /* Per-defined item index values.  They are used to identify empty or
  * mandatory items.
@@ -85,6 +86,10 @@ svn_fs_x__p2l_entry_t *
 svn_fs_x__p2l_entry_dup(const svn_fs_x__p2l_entry_t *entry,
                         apr_pool_t *pool);
 
+/* Close the index file STREAM and underlying file handle. */
+svn_error_t *
+svn_fs_x__packed_stream_close(svn_fs_x__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.
@@ -182,6 +187,7 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
 svn_error_t *
 svn_fs_x__p2l_index_lookup(apr_array_header_t **entries,
                            svn_fs_t *fs,
+                           svn_fs_x__revision_file_t *rev_file,
                            svn_revnum_t revision,
                            apr_off_t block_start,
                            apr_off_t block_size,
@@ -195,6 +201,7 @@ svn_fs_x__p2l_index_lookup(apr_array_hea
 svn_error_t *
 svn_fs_x__p2l_entry_lookup(svn_fs_x__p2l_entry_t **entry,
                            svn_fs_t *fs,
+                           svn_fs_x__revision_file_t *rev_file,
                            svn_revnum_t revision,
                            apr_off_t offset,
                            apr_pool_t *pool);
@@ -208,6 +215,7 @@ svn_fs_x__p2l_entry_lookup(svn_fs_x__p2l
 svn_error_t *
 svn_fs_x__p2l_item_lookup(svn_fs_x__id_part_t **item,
                           svn_fs_t *fs,
+                          svn_fs_x__revision_file_t *rev_file,
                           svn_revnum_t revision,
                           apr_off_t offset,
                           apr_uint32_t sub_item,
@@ -221,6 +229,7 @@ svn_error_t *
 svn_fs_x__item_offset(apr_off_t *offset,
                       apr_uint32_t *sub_item,
                       svn_fs_t *fs,
+                      svn_fs_x__revision_file_t *rev_file,
                       const svn_fs_x__id_part_t *item_id,
                       apr_pool_t *pool);
 
@@ -243,6 +252,7 @@ svn_fs_x__l2p_get_max_ids(apr_array_head
 svn_error_t *
 svn_fs_x__p2l_get_max_offset(apr_off_t *offset,
                              svn_fs_t *fs,
+                             svn_fs_x__revision_file_t *rev_file,
                              svn_revnum_t revision,
                              apr_pool_t *pool);
 



Mime
View raw message