You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/10/14 19:11:01 UTC

svn commit: r1531982 - in /subversion/branches/log-addressing/subversion/libsvn_fs_fs: cached_data.c index.c index.h recovery.c rev_file.c rev_file.h util.c util.h verify.c

Author: stefan2
Date: Mon Oct 14 17:11:01 2013
New Revision: 1531982

URL: http://svn.apache.org/r1531982
Log:
On the log-addressing branch:
Introduce a new abstraction, the "revsion file" which ensures that all
files pertaining to a revision / pack file are read consistently wrt.
being packed.  This is needed to read file offsets from index that
match the actual rev / pack file.

In this commit, we introduce the new API and use it when reading data
from the rev / pack file.  We don't read index files consistently, yet.

* subversion/libsvn_fs_fs/rev_file.h
  (): new file
  (svn_fs_fs__packed_number_stream_t): publish previously private type
  (svn_fs_fs__revision_file_t): declare new object type
  (svn_fs_fs__init_revision_file,
   svn_fs_fs__open_pack_or_rev_file,
   svn_fs_fs__reopen_revision_file,
   svn_fs_fs__open_proto_rev_file,
   svn_fs_fs__close_revision_file): declare operations on that object

* subversion/libsvn_fs_fs/rev_file.c
  (): new file
  (open_pack_or_rev_file): logic taken from svn_fs_fs__open_pack_or_rev_file
                           in utils.c
  (svn_fs_fs__init_revision_file,
   svn_fs_fs__open_pack_or_rev_file,
   svn_fs_fs__reopen_revision_file,
   svn_fs_fs__open_proto_rev_file,
   svn_fs_fs__close_revision_file): implement new API

* subversion/libsvn_fs_fs/util.h
  (svn_fs_fs__open_pack_or_rev_file): remove here

* subversion/libsvn_fs_fs/util.c
  (svn_fs_fs__open_pack_or_rev_file): remove here

* subversion/libsvn_fs_fs/cached_data.c
  (block_read,
   open_and_seek_revision,
   open_and_seek_representation): replace plain APR file with new struct
  (open_and_seek_transaction): ditto; use new API
  (get_node_revision_body): use new type and API for committed data;
                            keep old code for txn data with file varible
                            being renamed for clarity
  (get_fs_id_at_offset,
   svn_fs_fs__rev_get_root): use new type and API
  (shared_file_t): replace plain file member with new struct;
                   drop stream member because it is already provided by
                   the new revision file struct
  (get_file_offset,
   rs_aligned_seek): adapt to struct change
  (auto_open_shared_file): use new API
  (auto_read_diff_version,
   create_rep_state_body
   read_delta_window,
   read_plain_window,
   get_contents): adapt to struct change
  (svn_fs_fs__get_file_delta_stream,
   svn_fs_fs__get_changes): ditto; use new API
  (init_rep_state,
   cache_windows,
   block_read_windows,
   block_read_contents,
   auto_select_stream,
   block_read_changes,
   block_read_noderev,
   block_read): adapt to struct change; replace file+stream with new struct

* subversion/libsvn_fs_fs/index.h
  (svn_fs_fs__packed_stream_close): publish previously private function

* subversion/libsvn_fs_fs/index.c
  (packed_stream_close): rename to ...
  (svn_fs_fs__packed_stream_close): ... this
  (svn_fs_fs__packed_number_stream_t,
   stream_error_create,
   packed_stream_open,
   packed_stream_get,
   get_l2p_header_body,
   get_l2p_page_info,
   get_l2p_page,
   prefetch_l2p_pages,
   l2p_index_lookup,
   get_l2p_header,
   svn_fs_fs__l2p_get_max_ids,
   get_p2l_header,
   get_p2l_page_info,
   get_p2l_page,
   prefetch_p2l_page,
   get_p2l_keys,
   p2l_index_lookup,
   svn_fs_fs__p2l_index_lookup,
   p2l_entry_lookup,
   svn_fs_fs__p2l_entry_lookup,
   svn_fs_fs__p2l_get_max_offset): adapt to renamed stream type and
                                   close function

* subversion/libsvn_fs_fs/recovery.c
  (recover_get_largest_revision,
   recover_find_max_ids): replace plain APR file with new struct
  (svn_fs_fs__find_max_ids): ditto; use new API

* subversion/libsvn_fs_fs/verify.c
  (compare_p2l_to_rev): replace plain APR file with new struct

Added:
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.c
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.h
Modified:
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/cached_data.c
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/index.c
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/index.h
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/recovery.c
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h
    subversion/branches/log-addressing/subversion/libsvn_fs_fs/verify.c

Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/cached_data.c?rev=1531982&r1=1531981&r2=1531982&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/cached_data.c Mon Oct 14 17:11:01 2013
@@ -46,7 +46,7 @@ block_read(void **result,
            svn_fs_t *fs,
            svn_revnum_t revision,
            apr_uint64_t item_index,
-           apr_file_t *revision_file,
+           svn_fs_fs__revision_file_t *revision_file,
            apr_pool_t *result_pool,
            apr_pool_t *scratch_pool);
 
@@ -197,20 +197,20 @@ aligned_seek(svn_fs_t *fs,
    the newly opened file in FILE.  Seek to location OFFSET 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_fs__revision_file_t **file,
                        svn_fs_t *fs,
                        svn_revnum_t rev,
                        apr_uint64_t item,
                        apr_pool_t *pool)
 {
-  apr_file_t *rev_file;
+  svn_fs_fs__revision_file_t *rev_file;
   apr_off_t offset = -1;
 
   SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, pool));
 
   SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, rev, pool));
   SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rev, NULL, item, pool));
-  SVN_ERR(aligned_seek(fs, rev_file, NULL, offset, pool));
+  SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, pool));
 
   *file = rev_file;
 
@@ -221,24 +221,18 @@ 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_fs__revision_file_t **file,
                           svn_fs_t *fs,
                           representation_t *rep,
                           apr_pool_t *pool)
 {
-  apr_file_t *rev_file;
   apr_off_t offset;
 
-  SVN_ERR(svn_io_file_open(&rev_file,
-                           svn_fs_fs__path_txn_proto_rev(fs, &rep->txn_id,
-                                                         pool),
-                           APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
+  SVN_ERR(svn_fs_fs__open_proto_rev_file(file, fs, &rep->txn_id, pool));
 
   SVN_ERR(svn_fs_fs__item_offset(&offset, fs, SVN_INVALID_REVNUM,
                                  &rep->txn_id, rep->item_index, pool));
-  SVN_ERR(aligned_seek(fs, rev_file, NULL, offset, pool));
-
-  *file = rev_file;
+  SVN_ERR(aligned_seek(fs, (*file)->file, NULL, offset, pool));
 
   return SVN_NO_ERROR;
 }
@@ -247,7 +241,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_fs__revision_file_t **file_p,
                              svn_fs_t *fs,
                              representation_t *rep,
                              apr_pool_t *pool)
@@ -281,16 +275,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_fs_data_t *ffd = fs->fsap_data;
 
   if (svn_fs_fs__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_fs__path_txn_node_rev(fs, id, pool),
                              APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
       if (err)
@@ -305,13 +300,15 @@ get_node_revision_body(node_revision_t *
         }
 
       SVN_ERR(svn_fs_fs__read_noderev(noderev_p,
-                                      svn_stream_from_aprfile2(revision_file,
+                                      svn_stream_from_aprfile2(file,
                                                                FALSE,
                                                                pool),
                                       pool));
     }
   else
     {
+      svn_fs_fs__revision_file_t *revision_file;
+
       /* noderevs in rev / pack files can be cached */
       const svn_fs_fs__id_part_t *rev_item = svn_fs_fs__id_rev_item(id);
       pair_cache_key_t key;
@@ -347,15 +344,13 @@ get_node_revision_body(node_revision_t *
                              revision_file,
                              pool,
                              pool));
-          SVN_ERR(svn_io_file_close(revision_file, pool));
+          SVN_ERR(svn_fs_fs__close_revision_file(revision_file));
         }
       else
         {
           /* physical addressing mode reading, parsing and caching */
           SVN_ERR(svn_fs_fs__read_noderev(noderev_p,
-                                          svn_stream_from_aprfile2(revision_file,
-                                                                   FALSE,
-                                                                   pool),
+                                          revision_file->stream,
                                           pool));
 
           /* Workaround issue #4031: is-fresh-txn-root in revision files. */
@@ -406,7 +401,7 @@ svn_fs_fs__get_node_revision(node_revisi
    temporary variables from POOL. */
 static svn_error_t *
 get_fs_id_at_offset(svn_fs_id_t **id_p,
-                    apr_file_t *rev_file,
+                    svn_fs_fs__revision_file_t *rev_file,
                     svn_fs_t *fs,
                     svn_revnum_t rev,
                     apr_off_t offset,
@@ -414,10 +409,9 @@ get_fs_id_at_offset(svn_fs_id_t **id_p,
 {
   node_revision_t *noderev;
 
-  SVN_ERR(aligned_seek(fs, rev_file, NULL, offset, pool));
+  SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, pool));
   SVN_ERR(svn_fs_fs__read_noderev(&noderev,
-                                  svn_stream_from_aprfile2(rev_file, TRUE,
-                                                           pool),
+                                  rev_file->stream,
                                   pool));
 
   /* noderev->id is const, get rid of that */
@@ -530,7 +524,7 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
     }
   else
     {
-      apr_file_t *revision_file;
+      svn_fs_fs__revision_file_t *revision_file;
       apr_off_t root_offset;
       svn_fs_id_t *root_id = NULL;
       svn_boolean_t is_cached;
@@ -541,13 +535,13 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
         return SVN_NO_ERROR;
 
       SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev, pool));
-      SVN_ERR(get_root_changes_offset(&root_offset, NULL, revision_file,
-                                      fs, rev, pool));
+      SVN_ERR(get_root_changes_offset(&root_offset, NULL,
+                                      revision_file->file, fs, rev, pool));
 
       SVN_ERR(get_fs_id_at_offset(&root_id, revision_file, fs, rev,
                                   root_offset, pool));
 
-      SVN_ERR(svn_io_file_close(revision_file, pool));
+      SVN_ERR(svn_fs_fs__close_revision_file(revision_file));
 
       SVN_ERR(svn_cache__set(ffd->rev_root_id_cache, &rev, root_id, pool));
 
@@ -562,10 +556,7 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
 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_fs__revision_file_t *rfile;
 
   /* file system to open the file in */
   svn_fs_t *fs;
@@ -615,7 +606,7 @@ get_file_offset(apr_off_t *offset,
                 apr_pool_t *pool)
 {
   return svn_error_trace(svn_fs_fs__get_file_offset(offset,
-                                                    rs->sfile->file,
+                                                    rs->sfile->rfile->file,
                                                     pool));
 }
 
@@ -627,7 +618,7 @@ rs_aligned_seek(rep_state_t *rs,
                 apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = rs->sfile->fs->fsap_data;
-  return svn_error_trace(svn_io_file_aligned_seek(rs->sfile->file,
+  return svn_error_trace(svn_io_file_aligned_seek(rs->sfile->rfile->file,
                                                   ffd->block_size,
                                                   buffer_start, offset,
                                                   pool));
@@ -637,12 +628,9 @@ rs_aligned_seek(rep_state_t *rs,
 static svn_error_t*
 auto_open_shared_file(shared_file_t *file)
 {
-  if (file->file == NULL)
-    {
-      SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&file->file, file->fs,
-                                               file->revision, file->pool));
-      file->stream = svn_stream_from_aprfile2(file->file, TRUE, file->pool);
-    }
+  if (file->rfile == NULL)
+    SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&file->rfile, file->fs,
+                                             file->revision, file->pool));
 
   return SVN_NO_ERROR;
 }
@@ -673,7 +661,7 @@ auto_read_diff_version(rep_state_t *rs, 
     {
       char buf[4];
       SVN_ERR(rs_aligned_seek(rs, NULL, rs->start, pool));
-      SVN_ERR(svn_io_file_read_full2(rs->sfile->file, buf,
+      SVN_ERR(svn_io_file_read_full2(rs->sfile->rfile->file, buf,
                                      sizeof(buf), NULL, NULL, pool));
 
       /* ### Layering violation */
@@ -713,7 +701,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
       && rep->revision < ffd->min_unpacked_rev
@@ -780,13 +768,11 @@ create_rep_state_body(rep_state_t **rep_
           /* otherwise, create a new file object.  May or may not be
            * an in-txn file.
            */
-          SVN_ERR(open_and_seek_representation(&rs->sfile->file, fs, rep,
+          SVN_ERR(open_and_seek_representation(&rs->sfile->rfile, fs, rep,
                                                pool));
-          rs->sfile->stream = svn_stream_from_aprfile2(rs->sfile->file, TRUE,
-                                                       rs->sfile->pool);
         }
 
-      SVN_ERR(svn_fs_fs__read_rep_header(&rh, rs->sfile->stream, pool));
+      SVN_ERR(svn_fs_fs__read_rep_header(&rh, rs->sfile->rfile->stream, pool));
       SVN_ERR(get_file_offset(&rs->start, rs, pool));
 
       /* populate the cache if appropriate */
@@ -794,7 +780,7 @@ create_rep_state_body(rep_state_t **rep_
         {
           if (svn_fs_fs__use_log_addressing(fs, rep->revision))
             SVN_ERR(block_read(NULL, fs, rep->revision, rep->item_index,
-                               rs->sfile->file, pool, pool));
+                               rs->sfile->rfile, pool, pool));
           else
             if (ffd->rep_header_cache)
               SVN_ERR(svn_cache__set(ffd->rep_header_cache, &key, rh, pool));
@@ -1318,7 +1304,7 @@ read_delta_window(svn_txdelta_window_t *
       && svn_fs_fs__use_log_addressing(rs->sfile->fs, rs->revision))
     {
       SVN_ERR(block_read(NULL, rs->sfile->fs, rs->revision, rs->item_index,
-                         rs->sfile->file, pool, pool));
+                         rs->sfile->rfile, pool, pool));
 
       /* reading the whole block probably also provided us with the
          desired txdelta window */
@@ -1340,7 +1326,7 @@ read_delta_window(svn_txdelta_window_t *
   /* Skip windows to reach the current chunk if we aren't there yet. */
   while (rs->chunk_index < this_chunk)
     {
-      SVN_ERR(svn_txdelta_skip_svndiff_window(rs->sfile->file,
+      SVN_ERR(svn_txdelta_skip_svndiff_window(rs->sfile->rfile->file,
                                               rs->ver, pool));
       rs->chunk_index++;
       SVN_ERR(get_file_offset(&start_offset, rs, pool));
@@ -1353,7 +1339,7 @@ read_delta_window(svn_txdelta_window_t *
     }
 
   /* Actually read the next window. */
-  SVN_ERR(svn_txdelta_read_svndiff_window(nwin, rs->sfile->stream,
+  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;
@@ -1387,7 +1373,7 @@ read_plain_window(svn_stringbuf_t **nwin
 
   /* Read the plain data. */
   *nwin = svn_stringbuf_create_ensure(size, pool);
-  SVN_ERR(svn_io_file_read_full2(rs->sfile->file, (*nwin)->data, size,
+  SVN_ERR(svn_io_file_read_full2(rs->sfile->rfile->file, (*nwin)->data, size,
                                  NULL, NULL, pool));
   (*nwin)->data[size] = 0;
 
@@ -1545,7 +1531,7 @@ get_contents(struct rep_read_baton *rb,
 
           offset = rs->start + rs->current;
           SVN_ERR(rs_aligned_seek(rs, NULL, offset, rb->pool));
-          SVN_ERR(svn_io_file_read_full2(rs->sfile->file, cur,
+          SVN_ERR(svn_io_file_read_full2(rs->sfile->rfile->file, cur,
                                          copy_len, NULL, NULL, rb->pool));
         }
 
@@ -1837,9 +1823,10 @@ svn_fs_fs__get_file_delta_stream(svn_txd
                                                 delta_read_md5_digest, pool);
           return SVN_NO_ERROR;
         }
-      else if (rep_state->sfile->file)
+      else if (rep_state->sfile->rfile)
         {
-          SVN_ERR(svn_io_file_close(rep_state->sfile->file, pool));
+          SVN_ERR(svn_fs_fs__close_revision_file(rep_state->sfile->rfile));
+          rep_state->sfile->rfile = NULL;
         }
     }
 
@@ -2166,7 +2153,7 @@ svn_fs_fs__get_changes(apr_array_header_
                        apr_pool_t *pool)
 {
   apr_off_t changes_offset;
-  apr_file_t *revision_file;
+  svn_fs_fs__revision_file_t *revision_file;
   svn_boolean_t found;
   fs_fs_data_t *ffd = fs->fsap_data;
 
@@ -2195,13 +2182,13 @@ svn_fs_fs__get_changes(apr_array_header_
         {
           /* physical addressing mode code path */
           SVN_ERR(get_root_changes_offset(NULL, &changes_offset,
-                                          revision_file, fs, rev, pool));
+                                          revision_file->file, fs, rev,
+                                          pool));
 
-          SVN_ERR(aligned_seek(fs, revision_file, NULL, changes_offset,
+          SVN_ERR(aligned_seek(fs, revision_file->file, NULL, changes_offset,
                                pool));
-          SVN_ERR(svn_fs_fs__read_changes(changes,
-                      svn_stream_from_aprfile2(revision_file, TRUE, pool),
-                      pool));
+          SVN_ERR(svn_fs_fs__read_changes(changes, revision_file->stream,
+                                          pool));
 
           /* cache for future reference */
 
@@ -2209,7 +2196,7 @@ svn_fs_fs__get_changes(apr_array_header_
             SVN_ERR(svn_cache__set(ffd->changes_cache, &rev, *changes, pool));
         }
 
-      SVN_ERR(svn_io_file_close(revision_file, pool));
+      SVN_ERR(svn_fs_fs__close_revision_file(revision_file));
     }
 
   SVN_ERR(dbg_log_access(fs, rev, changes_offset, *changes,
@@ -2226,8 +2213,7 @@ static svn_error_t *
 init_rep_state(rep_state_t *rs,
                svn_fs_fs__rep_header_t *rep_header,
                svn_fs_t *fs,
-               apr_file_t *file,
-               svn_stream_t *stream,
+               svn_fs_fs__revision_file_t *file,
                svn_fs_fs__p2l_entry_t* entry,
                apr_pool_t *pool)
 {
@@ -2238,8 +2224,7 @@ init_rep_state(rep_state_t *rs,
   SVN_ERR_ASSERT(entry->type >= SVN_FS_FS__ITEM_TYPE_FILE_REP
                  && entry->type <= SVN_FS_FS__ITEM_TYPE_DIR_PROPS);
   
-  shared_file->file = file;
-  shared_file->stream = stream;
+  shared_file->rfile = file;
   shared_file->fs = fs;
   shared_file->revision = entry->item.revision;
   shared_file->pool = pool;
@@ -2281,7 +2266,7 @@ cache_windows(svn_filesize_t *fulltext_l
       /* navigate to & read the current window */
       SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, pool));
       SVN_ERR(svn_txdelta_read_svndiff_window(&window,
-                                              rs->sfile->stream,
+                                              rs->sfile->rfile->stream,
                                               rs->ver, pool));
 
       /* aggregate expanded window size */
@@ -2312,8 +2297,7 @@ cache_windows(svn_filesize_t *fulltext_l
 static svn_error_t *
 block_read_windows(svn_fs_fs__rep_header_t *rep_header,
                    svn_fs_t *fs,
-                   apr_file_t *file,
-                   svn_stream_t *stream,
+                   svn_fs_fs__revision_file_t *rev_file,
                    svn_fs_fs__p2l_entry_t* entry,
                    apr_pool_t *pool)
 {
@@ -2329,7 +2313,7 @@ block_read_windows(svn_fs_fs__rep_header
           && !ffd->combined_window_cache))
     return SVN_NO_ERROR;
 
-  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
    * to the right data. */
@@ -2347,10 +2331,10 @@ block_read_windows(svn_fs_fs__rep_header
       /* for larger reps, the header may have crossed a block boundary.
        * make sure we still read blocks properly aligned, i.e. don't use
        * plain seek here. */
-      SVN_ERR(aligned_seek(fs, file, NULL, offset, pool));
+      SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, pool));
 
       plaintext = svn_stringbuf_create_ensure(rs.size, pool);
-      SVN_ERR(svn_io_file_read_full2(file, plaintext->data,
+      SVN_ERR(svn_io_file_read_full2(rev_file->file, plaintext->data,
                                      rs.size, &plaintext->len, NULL, pool));
       plaintext->data[plaintext->len] = 0;
       rs.current += rs.size;
@@ -2404,8 +2388,7 @@ read_rep_header(svn_fs_fs__rep_header_t 
  */
 static svn_error_t *
 block_read_contents(svn_fs_t *fs,
-                    apr_file_t *file,
-                    svn_stream_t *stream,
+                    svn_fs_fs__revision_file_t *rev_file,
                     svn_fs_fs__p2l_entry_t* entry,
                     apr_pool_t *pool)
 {
@@ -2416,8 +2399,9 @@ block_read_contents(svn_fs_t *fs,
   header_key.is_packed = svn_fs_fs__is_packed_rev(fs, header_key.revision);
   header_key.item_index = entry->item.number;
 
-  SVN_ERR(read_rep_header(&rep_header, fs, stream, &header_key, pool));
-  SVN_ERR(block_read_windows(rep_header, fs, file, stream, entry, pool));
+  SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key,
+                          pool));
+  SVN_ERR(block_read_windows(rep_header, fs, rev_file, entry, pool));
 
   return SVN_NO_ERROR;
 }
@@ -2429,8 +2413,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_fs__revision_file_t *rev_file,
                    svn_fs_fs__p2l_entry_t* entry,
                    apr_pool_t *pool)
 {
@@ -2447,13 +2430,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,
+      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;
@@ -2467,8 +2450,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_fs__revision_file_t *rev_file,
                    svn_fs_fs__p2l_entry_t* entry,
                    svn_boolean_t must_read,
                    apr_pool_t *pool)
@@ -2488,7 +2470,7 @@ block_read_changes(apr_array_header_t **
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry, pool));
+  SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, pool));
 
   /* read changes from revision file */
 
@@ -2511,8 +2493,7 @@ block_read_changes(apr_array_header_t **
 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_fs__revision_file_t *rev_file,
                    svn_fs_fs__p2l_entry_t* entry,
                    svn_boolean_t must_read,
                    apr_pool_t *pool)
@@ -2537,7 +2518,7 @@ block_read_noderev(node_revision_t **nod
         return SVN_NO_ERROR;
     }
 
-  SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry, pool));
+  SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, pool));
 
   /* read node rev from revision file */
 
@@ -2567,7 +2548,7 @@ block_read(void **result,
            svn_fs_t *fs,
            svn_revnum_t revision,
            apr_uint64_t item_index,
-           apr_file_t *revision_file,
+           svn_fs_fs__revision_file_t *revision_file,
            apr_pool_t *result_pool,
            apr_pool_t *scratch_pool)
 {
@@ -2578,8 +2559,6 @@ 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));
@@ -2603,7 +2582,8 @@ block_read(void **result,
     {
       SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, revision, offset,
                                           scratch_pool));
-      SVN_ERR(aligned_seek(fs, revision_file, &block_start, offset, iterpool));
+      SVN_ERR(aligned_seek(fs, revision_file->file, &block_start, offset,
+                           iterpool));
 
       /* read all items from the block */
       for (i = 0; i < entries->nelts; ++i)
@@ -2634,7 +2614,7 @@ block_read(void **result,
                             && entry->size < ffd->block_size))
             {
               void *item = NULL;
-              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)
                 {
@@ -2642,20 +2622,20 @@ block_read(void **result,
                   case SVN_FS_FS__ITEM_TYPE_DIR_REP:
                   case SVN_FS_FS__ITEM_TYPE_FILE_PROPS:
                   case SVN_FS_FS__ITEM_TYPE_DIR_PROPS:
-                    SVN_ERR(block_read_contents(fs, revision_file, stream,
-                                                entry, pool));
+                    SVN_ERR(block_read_contents(fs, revision_file, entry,
+                                                pool));
                     break;
 
                   case SVN_FS_FS__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, is_result, pool));
                     break;
 
                   case SVN_FS_FS__ITEM_TYPE_CHANGES:
                     SVN_ERR(block_read_changes((apr_array_header_t **)&item,
-                                               fs, revision_file,  stream,
+                                               fs, revision_file,
                                                entry, is_result, pool));
                     break;
 
@@ -2682,7 +2662,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/log-addressing/subversion/libsvn_fs_fs/index.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/index.c?rev=1531982&r1=1531981&r2=1531982&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/index.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/index.c Mon Oct 14 17:11:01 2013
@@ -35,6 +35,7 @@
 #include "pack.h"
 #include "temp_serializer.h"
 #include "util.h"
+#include "fs_fs.h"
 
 #include "../libsvn_fs/fs-loader.h"
 
@@ -152,7 +153,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_fs__packed_number_stream_t
 {
   /* underlying data file containing the packed values */
   apr_file_t *file;
@@ -178,14 +179,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_fs__packed_number_stream_t *stream,
                     apr_status_t err,
                     const char *message)
 {
@@ -207,7 +208,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_fs__packed_number_stream_t *stream)
 {
   unsigned char buffer[MAX_NUMBER_PREFETCH];
   apr_size_t read = 0;
@@ -302,18 +303,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_fs__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_fs__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;
@@ -327,9 +329,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_fs__packed_stream_close(svn_fs_fs__packed_number_stream_t *stream)
 {
   if (stream)
     {
@@ -347,7 +348,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_fs__packed_number_stream_t *stream)
 {
   if (stream->current == stream->used)
     SVN_ERR(packed_stream_read(stream));
@@ -362,7 +363,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_fs__packed_number_stream_t *stream,
                    apr_off_t offset)
 {
   if (   stream->used == 0
@@ -393,7 +394,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_fs__packed_number_stream_t *stream)
 {
   return stream->current == 0
        ? stream->start_offset
@@ -703,7 +704,7 @@ svn_fs_fs__l2p_index_create(svn_fs_t *fs
  * REVISION in FS and return it in *STREAM.  Use POOL for allocations.
  */
 static svn_error_t *
-auto_open_l2p_index(packed_number_stream_t **stream,
+auto_open_l2p_index(svn_fs_fs__packed_number_stream_t **stream,
                     svn_fs_t *fs,
                     svn_revnum_t revision,
                     apr_pool_t *pool)
@@ -727,7 +728,7 @@ auto_open_l2p_index(packed_number_stream
  */
 static svn_error_t *
 get_l2p_header_body(l2p_header_t **header,
-                    packed_number_stream_t **stream,
+                    svn_fs_fs__packed_number_stream_t **stream,
                     svn_fs_t *fs,
                     svn_revnum_t revision,
                     apr_pool_t *pool)
@@ -911,7 +912,7 @@ l2p_page_info_access_func(void **out,
  */
 static svn_error_t *
 get_l2p_page_info(l2p_page_info_baton_t *baton,
-                  packed_number_stream_t **stream,
+                  svn_fs_fs__packed_number_stream_t **stream,
                   svn_fs_t *fs,
                   apr_pool_t *pool)
 {
@@ -1029,7 +1030,7 @@ get_l2p_page_table(apr_array_header_t *p
  */
 static svn_error_t *
 get_l2p_page(l2p_page_t **page,
-             packed_number_stream_t **stream,
+             svn_fs_fs__packed_number_stream_t **stream,
              svn_fs_t *fs,
              svn_revnum_t start_revision,
              l2p_page_table_entry_t *table_entry,
@@ -1074,7 +1075,7 @@ get_l2p_page(l2p_page_t **page,
 static svn_error_t *
 prefetch_l2p_pages(svn_boolean_t *end,
                    svn_fs_t *fs,
-                   packed_number_stream_t *stream,
+                   svn_fs_fs__packed_number_stream_t *stream,
                    svn_revnum_t first_revision,
                    svn_revnum_t revision,
                    apr_array_header_t *pages,
@@ -1219,7 +1220,7 @@ l2p_index_lookup(apr_off_t *offset,
   l2p_page_info_baton_t info_baton;
   l2p_entry_baton_t page_baton;
   l2p_page_t *page = NULL;
-  packed_number_stream_t *stream = NULL;
+  svn_fs_fs__packed_number_stream_t *stream = NULL;
   svn_fs_fs__page_cache_key_t key = { 0 };
   svn_boolean_t is_cached = FALSE;
   void *dummy = NULL;
@@ -1301,7 +1302,7 @@ l2p_index_lookup(apr_off_t *offset,
       svn_pool_destroy(iterpool);
     }
 
-  SVN_ERR(packed_stream_close(stream));
+  SVN_ERR(svn_fs_fs__packed_stream_close(stream));
 
   *offset = page_baton.offset;
 
@@ -1356,7 +1357,7 @@ l2p_proto_index_lookup(apr_off_t *offset
  */
 static svn_error_t *
 get_l2p_header(l2p_header_t **header,
-               packed_number_stream_t **stream,
+               svn_fs_fs__packed_number_stream_t **stream,
                svn_fs_t *fs,
                svn_revnum_t revision,
                apr_pool_t *pool)
@@ -1389,12 +1390,12 @@ svn_fs_fs__l2p_get_max_ids(apr_array_hea
   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_fs__packed_number_stream_t *stream = NULL;
   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));
+  SVN_ERR(svn_fs_fs__packed_stream_close(stream));
   stream = NULL;
 
   /* Determine the length of the item index list for each rev.
@@ -1413,7 +1414,7 @@ svn_fs_fs__l2p_get_max_ids(apr_array_hea
           svn_pool_clear(header_pool);
           SVN_ERR(get_l2p_header(&header, &stream, fs, revision,
                                  header_pool));
-          SVN_ERR(packed_stream_close(stream));
+          SVN_ERR(svn_fs_fs__packed_stream_close(stream));
           stream = NULL;
         }
 
@@ -1693,7 +1694,7 @@ svn_fs_fs__p2l_index_create(svn_fs_t *fs
  */
 static svn_error_t *
 get_p2l_header(p2l_header_t **header,
-               packed_number_stream_t **stream,
+               svn_fs_fs__packed_number_stream_t **stream,
                svn_fs_t *fs,
                svn_revnum_t revision,
                apr_pool_t *stream_pool,
@@ -1860,7 +1861,7 @@ p2l_page_info_func(void **out,
  */
 static svn_error_t *
 get_p2l_page_info(p2l_page_info_baton_t *baton,
-                  packed_number_stream_t **stream,
+                  svn_fs_fs__packed_number_stream_t **stream,
                   svn_fs_t *fs,
                   apr_pool_t *stream_pool,
                   apr_pool_t *pool)
@@ -1894,7 +1895,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_fs__packed_number_stream_t *stream,
            apr_off_t *item_offset,
            svn_revnum_t *last_revision,
            apr_uint64_t *last_compound,
@@ -1938,7 +1939,7 @@ 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_fs__packed_number_stream_t **stream,
              svn_fs_t *fs,
              svn_revnum_t start_revision,
              apr_off_t start_offset,
@@ -2013,7 +2014,7 @@ 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_fs__packed_number_stream_t **stream,
                   p2l_page_info_baton_t *baton,
                   apr_off_t min_offset,
                   apr_pool_t *stream_pool,
@@ -2080,7 +2081,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_fs__page_cache_key_t *key_p,
-             packed_number_stream_t **stream,
+             svn_fs_fs__packed_number_stream_t **stream,
              svn_fs_t *fs,
              svn_revnum_t revision,
              apr_off_t offset,
@@ -2097,7 +2098,7 @@ get_p2l_keys(p2l_page_info_baton_t *page
   /* 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));
+      SVN_ERR(svn_fs_fs__packed_stream_close(*stream));
       return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_OVERFLOW , NULL,
                                _("Offset %s too large in revision %ld"),
                                apr_off_t_toa(pool, offset), revision);
@@ -2127,7 +2128,7 @@ get_p2l_keys(p2l_page_info_baton_t *page
  */
 static svn_error_t *
 p2l_index_lookup(apr_array_header_t **entries,
-                 packed_number_stream_t **stream,
+                 svn_fs_fs__packed_number_stream_t **stream,
                  svn_fs_t *fs,
                  svn_revnum_t revision,
                  apr_off_t offset,
@@ -2212,13 +2213,13 @@ svn_fs_fs__p2l_index_lookup(apr_array_he
                             apr_off_t offset,
                             apr_pool_t *pool)
 {
-  packed_number_stream_t *stream = NULL;
+  svn_fs_fs__packed_number_stream_t *stream = NULL;
 
   /* look for this page in our cache */
   SVN_ERR(p2l_index_lookup(entries, &stream, fs, revision, offset, pool));
 
   /* make sure we close files after usage */
-  SVN_ERR(packed_stream_close(stream));
+  SVN_ERR(svn_fs_fs__packed_stream_close(stream));
 
   return SVN_NO_ERROR;
 }
@@ -2291,7 +2292,7 @@ p2l_entry_lookup_func(void **out,
 
 static svn_error_t *
 p2l_entry_lookup(svn_fs_fs__p2l_entry_t **entry_p,
-                 packed_number_stream_t **stream,
+                 svn_fs_fs__packed_number_stream_t **stream,
                  svn_fs_t *fs,
                  svn_revnum_t revision,
                  apr_off_t offset,
@@ -2342,13 +2343,13 @@ svn_fs_fs__p2l_entry_lookup(svn_fs_fs__p
                             apr_off_t offset,
                             apr_pool_t *pool)
 {
-  packed_number_stream_t *stream = NULL;
+  svn_fs_fs__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));
 
   /* make sure we close files after usage */
-  SVN_ERR(packed_stream_close(stream));
+  SVN_ERR(svn_fs_fs__packed_stream_close(stream));
 
   return SVN_NO_ERROR;
 }
@@ -2377,7 +2378,7 @@ svn_fs_fs__p2l_get_max_offset(apr_off_t 
                               apr_pool_t *pool)
 {
   fs_fs_data_t *ffd = fs->fsap_data;
-  packed_number_stream_t *stream = NULL;
+  svn_fs_fs__packed_number_stream_t *stream = NULL;
   p2l_header_t *header;
   svn_boolean_t is_cached = FALSE;
   apr_off_t *offset_p;
@@ -2400,7 +2401,7 @@ svn_fs_fs__p2l_get_max_offset(apr_off_t 
   *offset = header->file_size;
   
   /* make sure we close files after usage */
-  SVN_ERR(packed_stream_close(stream));
+  SVN_ERR(svn_fs_fs__packed_stream_close(stream));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/index.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/index.h?rev=1531982&r1=1531981&r2=1531982&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/index.h (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/index.h Mon Oct 14 17:11:01 2013
@@ -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.
@@ -69,6 +70,10 @@ typedef struct svn_fs_fs__p2l_entry_t
   svn_fs_fs__id_part_t item;
 } svn_fs_fs__p2l_entry_t;
 
+/* Close the index file STREAM and underlying file handle. */
+svn_error_t *
+svn_fs_fs__packed_stream_close(svn_fs_fs__packed_number_stream_t *stream);
+
 /* Open / create a log-to-phys index file with the full file path name
  * FILE_NAME.  Return the open file in *PROTO_INDEX and use POOL for
  * allocations.

Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/recovery.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/recovery.c?rev=1531982&r1=1531981&r2=1531982&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/recovery.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/recovery.c Mon Oct 14 17:11:01 2013
@@ -54,7 +54,7 @@ recover_get_largest_revision(svn_fs_t *f
   while (1)
     {
       svn_error_t *err;
-      apr_file_t *file;
+      svn_fs_fs__revision_file_t *file;
 
       err = svn_fs_fs__open_pack_or_rev_file(&file, fs, right, iterpool);
       svn_pool_clear(iterpool);
@@ -78,7 +78,7 @@ recover_get_largest_revision(svn_fs_t *f
     {
       svn_revnum_t probe = left + ((right - left) / 2);
       svn_error_t *err;
-      apr_file_t *file;
+      svn_fs_fs__revision_file_t *file;
 
       err = svn_fs_fs__open_pack_or_rev_file(&file, fs, probe, iterpool);
       svn_pool_clear(iterpool);
@@ -147,7 +147,7 @@ read_handler_recover(void *baton, char *
 static svn_error_t *
 recover_find_max_ids(svn_fs_t *fs,
                      svn_revnum_t rev,
-                     apr_file_t *rev_file,
+                     svn_fs_fs__revision_file_t *rev_file,
                      apr_off_t offset,
                      apr_uint64_t *max_node_id,
                      apr_uint64_t *max_copy_id,
@@ -161,8 +161,8 @@ recover_find_max_ids(svn_fs_t *fs,
   apr_pool_t *iterpool;
   node_revision_t *noderev;
 
-  baton.stream = svn_stream_from_aprfile2(rev_file, TRUE, pool);
-  SVN_ERR(svn_io_file_seek(rev_file, APR_SET, &offset, pool));
+  baton.stream = rev_file->stream;
+  SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &offset, pool));
   SVN_ERR(svn_fs_fs__read_noderev(&noderev, baton.stream, pool));
 
   /* Check that this is a directory.  It should be. */
@@ -185,7 +185,7 @@ recover_find_max_ids(svn_fs_t *fs,
      rely on directory entries being stored as PLAIN reps, though. */
   SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rev, NULL,
                                  noderev->data_rep->item_index, pool));
-  SVN_ERR(svn_io_file_seek(rev_file, APR_SET, &offset, pool));
+  SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &offset, pool));
   SVN_ERR(svn_fs_fs__read_rep_header(&header, baton.stream, pool));
   if (header->type != svn_fs_fs__rep_plain)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -286,7 +286,7 @@ svn_fs_fs__find_max_ids(svn_fs_t *fs,
 {
   fs_fs_data_t *ffd = fs->fsap_data;
   apr_off_t root_offset;
-  apr_file_t *rev_file;
+  svn_fs_fs__revision_file_t *rev_file;
   svn_fs_id_t *root_id;
 
   /* call this function for old repo formats only */
@@ -302,7 +302,7 @@ svn_fs_fs__find_max_ids(svn_fs_t *fs,
   SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, youngest, pool));
   SVN_ERR(recover_find_max_ids(fs, youngest, rev_file, root_offset,
                                max_node_id, max_copy_id, pool));
-  SVN_ERR(svn_io_file_close(rev_file, pool));
+  SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
 
   return SVN_NO_ERROR;
 }

Added: subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.c?rev=1531982&view=auto
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.c (added)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.c Mon Oct 14 17:11:01 2013
@@ -0,0 +1,176 @@
+/* rev_file.c --- revision file and index access functions
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#include "rev_file.h"
+#include "fs_fs.h"
+#include "index.h"
+#include "util.h"
+
+#include "../libsvn_fs/fs-loader.h"
+
+#include "svn_private_config.h"
+
+void
+svn_fs_fs__init_revision_file(svn_fs_fs__revision_file_t *file,
+                              svn_fs_t *fs,
+                              svn_revnum_t revision,
+                              apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+
+  file->is_packed = svn_fs_fs__is_packed_rev(fs, revision);
+  file->start_revision = revision < ffd->min_unpacked_rev
+                       ? revision - (revision % ffd->max_files_per_dir)
+                       : revision;
+
+  file->file = NULL;
+  file->stream = NULL;
+  file->p2l_stream = NULL;
+  file->l2p_stream = NULL;
+  file->pool = pool;
+}
+
+/* Core implementation of svn_fs_fs__open_pack_or_rev_file working on an
+ * existing, initialized FILE structure.
+ */
+static svn_error_t *
+open_pack_or_rev_file(svn_fs_fs__revision_file_t *file,
+                      svn_fs_t *fs,
+                      svn_revnum_t rev,
+                      apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  svn_error_t *err;
+  svn_boolean_t retry = FALSE;
+
+  do
+    {
+      const char *path = svn_fs_fs__path_rev_absolute(fs, rev, pool);
+      apr_file_t *apr_file;
+
+      /* open the revision file in buffered r/o mode */
+      err = svn_io_file_open(&apr_file, path,
+                             APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
+      if (!err)
+        {
+          file->file = apr_file;
+          file->stream = svn_stream_from_aprfile2(apr_file, TRUE, pool);
+
+          return SVN_NO_ERROR;
+        }
+
+      if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+        {
+          if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
+            {
+              /* 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_fs__update_min_unpacked_rev(fs, pool));
+
+              retry = TRUE;
+            }
+          else
+            {
+              svn_error_clear(err);
+              return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+                                       _("No such revision %ld"), rev);
+            }
+        }
+      else
+        {
+          retry = FALSE;
+        }
+    }
+  while (retry);
+
+  return svn_error_trace(err);
+}
+
+svn_error_t *
+svn_fs_fs__open_pack_or_rev_file(svn_fs_fs__revision_file_t **file,
+                                 svn_fs_t *fs,
+                                 svn_revnum_t rev,
+                                 apr_pool_t *pool)
+{
+  *file = apr_palloc(pool, sizeof(**file));
+  svn_fs_fs__init_revision_file(*file, fs, rev, pool);
+
+  return svn_error_trace(open_pack_or_rev_file(*file, fs, rev, pool));
+}
+
+svn_error_t *
+svn_fs_fs__reopen_revision_file(svn_fs_fs__revision_file_t *file,
+                                svn_fs_t *fs,
+                                svn_revnum_t rev)
+{
+  if (file->file)
+    svn_fs_fs__close_revision_file(file);
+
+  return svn_error_trace(open_pack_or_rev_file(file, fs, rev, file->pool));
+}
+
+svn_error_t *
+svn_fs_fs__open_proto_rev_file(svn_fs_fs__revision_file_t **file,
+                               svn_fs_t *fs,
+                               const svn_fs_fs__id_part_t *txn_id,
+                               apr_pool_t *pool)
+{
+  apr_file_t *apr_file;
+  SVN_ERR(svn_io_file_open(&apr_file,
+                           svn_fs_fs__path_txn_proto_rev(fs, txn_id, pool),
+                           APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
+
+  *file = apr_pcalloc(pool, sizeof(**file));
+  (*file)->file = apr_file;
+  (*file)->is_packed = FALSE;
+  (*file)->start_revision = SVN_INVALID_REVNUM;
+  (*file)->stream = svn_stream_from_aprfile2(apr_file, TRUE, pool);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__close_revision_file(svn_fs_fs__revision_file_t *file)
+{
+  if (file->stream)
+    SVN_ERR(svn_stream_close(file->stream));
+  if (file->file)
+    SVN_ERR(svn_io_file_close(file->file, file->pool));
+
+  SVN_ERR(svn_fs_fs__packed_stream_close(file->l2p_stream));
+  SVN_ERR(svn_fs_fs__packed_stream_close(file->p2l_stream));
+
+  file->file = NULL;
+  file->stream = NULL;
+  file->l2p_stream = NULL;
+  file->p2l_stream = NULL;
+
+  return SVN_NO_ERROR;
+}

Added: subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.h?rev=1531982&view=auto
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.h (added)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.h Mon Oct 14 17:11:01 2013
@@ -0,0 +1,110 @@
+/* rev_file.h --- revision file and index access data structure
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#ifndef SVN_LIBSVN_FS__REV_FILE_H
+#define SVN_LIBSVN_FS__REV_FILE_H
+
+#include "svn_fs.h"
+#include "id.h"
+
+/* In format 7, index files must be read in sync with the respective
+ * revision / pack file.  I.e. we must use packed index files for packed
+ * rev files and unpacked ones for non-packed rev files.  So, the whole
+ * point is to open them with matching "is packed" setting in case some
+ * background pack process was run.
+ */
+
+/* Opaque index stream type.
+ */
+typedef struct svn_fs_fs__packed_number_stream_t
+  svn_fs_fs__packed_number_stream_t;
+
+/* All files and associated properties for START_REVISION.
+ */
+typedef struct svn_fs_fs__revision_file_t
+{
+  /* first (potentially only) revision in the rev / pack file.
+   * SVN_INVALID_REVNUM for txn proto-rev files. */
+  svn_revnum_t start_revision;
+
+  /* the revision was packed when the first file / stream got opened */
+  svn_boolean_t is_packed;
+
+  /* rev / pack file or NULL if not opened, yet */
+  apr_file_t *file;
+
+  /* stream based on FILE and not NULL exactly when FILE is not NULL */
+  svn_stream_t *stream;
+
+  /* the opened P2L index or NULL.  Always NULL for txns. */
+  svn_fs_fs__packed_number_stream_t *p2l_stream;
+
+  /* the opened L2P index or NULL.  Always NULL for txns. */
+  svn_fs_fs__packed_number_stream_t *l2p_stream;
+
+  /* pool containing this object */
+  apr_pool_t *pool;
+} svn_fs_fs__revision_file_t;
+
+/* Initialize the FILE data structure for REVISION in FS without actually
+ * opening any files.  Use POOL for all future allocations in FILE.
+ */
+void
+svn_fs_fs__init_revision_file(svn_fs_fs__revision_file_t *file,
+                              svn_fs_t *fs,
+                              svn_revnum_t revision,
+                              apr_pool_t *pool);
+
+/* Open the correct revision file for REV.  If the filesystem FS has
+ * been packed, *FILE will be set to the packed file; otherwise, set *FILE
+ * to the revision file for REV.  Return SVN_ERR_FS_NO_SUCH_REVISION if the
+ * file doesn't exist.  Use POOL for allocations. */
+svn_error_t *
+svn_fs_fs__open_pack_or_rev_file(svn_fs_fs__revision_file_t **file,
+                                 svn_fs_t *fs,
+                                 svn_revnum_t rev,
+                                 apr_pool_t *pool);
+
+/* Close previous files as well as streams in FILE (if open) and open the
+ * rev / pack file for REVISION in FS.  This is useful when a pack operation
+ * made the current files outdated or no longer available and the caller
+ * wants to keep the same revision file data structure.
+ */
+svn_error_t *
+svn_fs_fs__reopen_revision_file(svn_fs_fs__revision_file_t *file,
+                                svn_fs_t *fs,
+                                svn_revnum_t revision);
+
+/* Open the proto-rev file of transaction TXN_ID in FS and return it in *FILE.
+ * Use POOL for allocations. */
+svn_error_t *
+svn_fs_fs__open_proto_rev_file(svn_fs_fs__revision_file_t **file,
+                               svn_fs_t *fs,
+                               const svn_fs_fs__id_part_t *txn_id,
+                               apr_pool_t *pool);
+
+/* Close all files and streams in FILE.
+ */
+svn_error_t *
+svn_fs_fs__close_revision_file(svn_fs_fs__revision_file_t *file);
+
+#endif

Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c?rev=1531982&r1=1531981&r2=1531982&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.c Mon Oct 14 17:11:01 2013
@@ -613,58 +613,6 @@ svn_fs_fs__move_into_place(const char *o
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_fs_fs__open_pack_or_rev_file(apr_file_t **file,
-                                 svn_fs_t *fs,
-                                 svn_revnum_t rev,
-                                 apr_pool_t *pool)
-{
-  fs_fs_data_t *ffd = fs->fsap_data;
-  svn_error_t *err;
-  svn_boolean_t retry = FALSE;
-
-  do
-    {
-      const char *path = svn_fs_fs__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))
-        {
-          if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
-            {
-              /* 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_fs__update_min_unpacked_rev(fs, pool));
-
-              retry = TRUE;
-            }
-          else
-            {
-              svn_error_clear(err);
-              return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
-                                       _("No such revision %ld"), rev);
-            }
-        }
-      else
-        {
-          retry = FALSE;
-        }
-    }
-  while (retry);
-
-  return svn_error_trace(err);
-}
-
 svn_boolean_t
 svn_fs_fs__use_log_addressing(svn_fs_t *fs,
                               svn_revnum_t rev)

Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h?rev=1531982&r1=1531981&r2=1531982&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/util.h Mon Oct 14 17:11:01 2013
@@ -378,23 +378,6 @@ svn_fs_fs__move_into_place(const char *o
                            const char *perms_reference,
                            apr_pool_t *pool);
 
-/* Open the correct revision file for REV.  If the filesystem FS has
-   been packed, *FILE will be set to the packed file; otherwise, set *FILE
-   to the revision file for REV.  Return SVN_ERR_FS_NO_SUCH_REVISION if the
-   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_fs__open_pack_or_rev_file(apr_file_t **file,
-                                 svn_fs_t *fs,
-                                 svn_revnum_t rev,
-                                 apr_pool_t *pool);
-
 /* Return TRUE, iff revision REV in FS requires logical addressing. */
 svn_boolean_t
 svn_fs_fs__use_log_addressing(svn_fs_t *fs,

Modified: subversion/branches/log-addressing/subversion/libsvn_fs_fs/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/libsvn_fs_fs/verify.c?rev=1531982&r1=1531981&r2=1531982&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/libsvn_fs_fs/verify.c (original)
+++ subversion/branches/log-addressing/subversion/libsvn_fs_fs/verify.c Mon Oct 14 17:11:01 2013
@@ -483,13 +483,13 @@ compare_p2l_to_rev(svn_fs_t *fs,
   apr_pool_t *iterpool = svn_pool_create(pool);
   apr_off_t max_offset;
   apr_off_t offset = 0;
-  apr_file_t *file;
+  svn_fs_fs__revision_file_t *rev_file;
 
   /* open the pack / rev file that is covered by the p2l index */
-  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&file, fs, start, pool));
+  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, start, pool));
 
   /* check file size vs. range covered by index */
-  SVN_ERR(svn_io_file_seek(file, APR_END, &offset, pool));
+  SVN_ERR(svn_io_file_seek(rev_file->file, APR_END, &offset, pool));
   SVN_ERR(svn_fs_fs__p2l_get_max_offset(&max_offset, fs, start, pool));
 
   if (offset != max_offset)
@@ -499,7 +499,8 @@ compare_p2l_to_rev(svn_fs_t *fs,
                              apr_off_t_toa(pool, offset), start,
                              apr_off_t_toa(pool, max_offset));
 
-  SVN_ERR(svn_io_file_aligned_seek(file, ffd->block_size, NULL, 0, pool));
+  SVN_ERR(svn_io_file_aligned_seek(rev_file->file, ffd->block_size, NULL, 0,
+                                   pool));
 
   /* for all offsets in the file, get the P2L index entries and check
      them against the L2P index */
@@ -542,14 +543,16 @@ compare_p2l_to_rev(svn_fs_t *fs,
             {
               /* skip filler entry at the end of the p2l index */
               if (entry->offset != max_offset)
-                SVN_ERR(read_all_nul(file, entry->size, pool));
+                SVN_ERR(read_all_nul(rev_file->file, entry->size, pool));
             }
           else if (entry->fnv1_checksum)
             {
               if (entry->size < STREAM_THRESHOLD)
-                SVN_ERR(expected_buffered_checksum(file, entry, pool));
+                SVN_ERR(expected_buffered_checksum(rev_file->file, entry,
+                                                   pool));
               else
-                SVN_ERR(expected_streamed_checksum(file, entry, pool));
+                SVN_ERR(expected_streamed_checksum(rev_file->file, entry,
+                                                   pool));
             }
 
           /* advance offset */