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/07/16 13:40:19 UTC

svn commit: r1503664 - in /subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs: fs_fs.c util.c util.h

Author: stefan2
Date: Tue Jul 16 11:40:19 2013
New Revision: 1503664

URL: http://svn.apache.org/r1503664
Log:
On the fsfs-improvements branch:  Move some more of the path calculation
and file I/O functions to utils.*.

* subversion/libsvn_fs_fs/util.h
  (svn_fs_fs__path_txn_dir,
   svn_fs_fs__path_txn_proto_rev,
   svn_fs_fs__path_txn_node_rev,
   svn_fs_fs__path_txn_node_props,
   svn_fs_fs__path_txn_node_children,
   svn_fs_fs__get_file_offset,
   svn_fs_fs__open_pack_or_rev_file): declare new private APIs

* subversion/libsvn_fs_fs/util.c
  (svn_fs_fs__path_txn_dir,
   svn_fs_fs__path_txn_proto_rev,
   svn_fs_fs__path_txn_node_rev,
   svn_fs_fs__path_txn_node_props,
   svn_fs_fs__path_txn_node_children,
   svn_fs_fs__get_file_offset,
   svn_fs_fs__open_pack_or_rev_file): code taken from fs_fs.c;
                                      added API prefix

* subversion/libsvn_fs_fs/fs_fs.c
  (path_txn_dir,
   path_txn_proto_rev,
   path_txn_node_rev,
   path_txn_node_props,
   path_txn_node_children,
   get_file_offset,
   open_pack_or_rev_file): moved to utils.c
  (path_txn_sha1,
   path_txn_changes,
   path_txn_props,
   path_txn_next_ids,
   open_and_seek_revision,
   get_writable_proto_rev_body, 
   purge_shared_txn, 
   svn_fs_fs__revision_exists, 
   open_and_seek_revision, 
   open_and_seek_transaction, 
   get_node_revision_body, 
   svn_fs_fs__put_node_revision, 
   svn_fs_fs__rev_get_root, 
   create_rep_state_body, 
   read_delta_window, 
   get_dir_contents, 
   svn_fs_fs__get_proplist, 
   get_changes, 
   svn_fs_fs__create_txn, 
   svn_fs_fs__purge_txn, 
   svn_fs_fs__set_entry, 
   rep_write_get_baton, 
   rep_write_contents_close, 
   svn_fs_fs__set_proplist, 
   write_hash_rep, 
   write_hash_delta_rep, 
   write_final_rev, 
   write_final_changed_path_info, 
   commit_body, 
   recover_get_largest_revision, 
   recover_body, 
   svn_fs_fs__open_txn, 
   svn_fs_fs__delete_node_revision, 
   hotcopy_update_current): update callers

Modified:
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.c
    subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.h

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c?rev=1503664&r1=1503663&r2=1503664&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/fs_fs.c Tue Jul 16 11:40:19 2013
@@ -168,16 +168,6 @@ path_lock(svn_fs_t *fs, apr_pool_t *pool
   return svn_dirent_join(fs->path, PATH_LOCK_FILE, pool);
 }
 
-static APR_INLINE const char *
-path_txn_dir(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool)
-{
-  SVN_ERR_ASSERT_NO_RETURN(txn_id != NULL);
-  return svn_dirent_join_many(pool, fs->path, PATH_TXNS_DIR,
-                              apr_pstrcat(pool, txn_id, PATH_EXT_TXN,
-                                          (char *)NULL),
-                              NULL);
-}
-
 /* Return the name of the sha1->rep mapping file in transaction TXN_ID
  * within FS for the given SHA1 checksum.  Use POOL for allocations.
  */
@@ -185,7 +175,7 @@ static APR_INLINE const char *
 path_txn_sha1(svn_fs_t *fs, const char *txn_id, svn_checksum_t *sha1,
               apr_pool_t *pool)
 {
-  return svn_dirent_join(path_txn_dir(fs, txn_id, pool),
+  return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
                          svn_checksum_to_cstring(sha1, pool),
                          pool);
 }
@@ -193,32 +183,22 @@ path_txn_sha1(svn_fs_t *fs, const char *
 static APR_INLINE const char *
 path_txn_changes(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool)
 {
-  return svn_dirent_join(path_txn_dir(fs, txn_id, pool), PATH_CHANGES, pool);
+  return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
+                         PATH_CHANGES, pool);
 }
 
 static APR_INLINE const char *
 path_txn_props(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool)
 {
-  return svn_dirent_join(path_txn_dir(fs, txn_id, pool), PATH_TXN_PROPS, pool);
+  return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
+                         PATH_TXN_PROPS, pool);
 }
 
 static APR_INLINE const char *
 path_txn_next_ids(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool)
 {
-  return svn_dirent_join(path_txn_dir(fs, txn_id, pool), PATH_NEXT_IDS, pool);
-}
-
-static APR_INLINE const char *
-path_txn_proto_rev(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool)
-{
-  fs_fs_data_t *ffd = fs->fsap_data;
-  if (ffd->format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
-    return svn_dirent_join_many(pool, fs->path, PATH_TXN_PROTOS_DIR,
-                                apr_pstrcat(pool, txn_id, PATH_EXT_REV,
-                                            (char *)NULL),
-                                NULL);
-  else
-    return svn_dirent_join(path_txn_dir(fs, txn_id, pool), PATH_REV, pool);
+  return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
+                         PATH_NEXT_IDS, pool);
 }
 
 static APR_INLINE const char *
@@ -231,34 +211,8 @@ path_txn_proto_rev_lock(svn_fs_t *fs, co
                                             (char *)NULL),
                                 NULL);
   else
-    return svn_dirent_join(path_txn_dir(fs, txn_id, pool), PATH_REV_LOCK,
-                           pool);
-}
-
-static const char *
-path_txn_node_rev(svn_fs_t *fs, const svn_fs_id_t *id, apr_pool_t *pool)
-{
-  const char *txn_id = svn_fs_fs__id_txn_id(id);
-  const char *node_id = svn_fs_fs__id_node_id(id);
-  const char *copy_id = svn_fs_fs__id_copy_id(id);
-  const char *name = apr_psprintf(pool, PATH_PREFIX_NODE "%s.%s",
-                                  node_id, copy_id);
-
-  return svn_dirent_join(path_txn_dir(fs, txn_id, pool), name, pool);
-}
-
-static APR_INLINE const char *
-path_txn_node_props(svn_fs_t *fs, const svn_fs_id_t *id, apr_pool_t *pool)
-{
-  return apr_pstrcat(pool, path_txn_node_rev(fs, id, pool), PATH_EXT_PROPS,
-                     (char *)NULL);
-}
-
-static APR_INLINE const char *
-path_txn_node_children(svn_fs_t *fs, const svn_fs_id_t *id, apr_pool_t *pool)
-{
-  return apr_pstrcat(pool, path_txn_node_rev(fs, id, pool),
-                     PATH_EXT_CHILDREN, (char *)NULL);
+    return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
+                           PATH_REV_LOCK, pool);
 }
 
 static APR_INLINE const char *
@@ -663,7 +617,8 @@ get_writable_proto_rev_body(svn_fs_t *fs
 
 
   /* Now open the prototype revision file and seek to the end. */
-  err = svn_io_file_open(file, path_txn_proto_rev(fs, txn_id, pool),
+  err = svn_io_file_open(file,
+                         svn_fs_fs__path_txn_proto_rev(fs, txn_id, pool),
                          APR_WRITE | APR_BUFFERED, APR_OS_DEFAULT, pool);
 
   /* You might expect that we could dispense with the following seek
@@ -738,22 +693,6 @@ purge_shared_txn(svn_fs_t *fs, const cha
 
 
 
-/* Fetch the current offset of FILE into *OFFSET_P. */
-static svn_error_t *
-get_file_offset(apr_off_t *offset_p, apr_file_t *file, apr_pool_t *pool)
-{
-  apr_off_t offset;
-
-  /* Note that, for buffered files, one (possibly surprising) side-effect
-     of this call is to flush any unwritten data to disk. */
-  offset = 0;
-  SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, pool));
-  *offset_p = offset;
-
-  return SVN_NO_ERROR;
-}
-
-
 /* Check that BUF, a nul-terminated buffer of text from format file PATH,
    contains only digits at OFFSET and beyond, raising an error if not.
 
@@ -1403,71 +1342,6 @@ svn_fs_fs__revision_exists(svn_revnum_t 
   return SVN_NO_ERROR;
 }
 
-/* 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 svn_fs_fs__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. */
-static svn_error_t *
-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 = NULL;
-  const char *path;
-  svn_boolean_t retry = FALSE;
-
-  do
-    {
-      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);
-}
-
 /* Open the revision file for revision REV in filesystem FS and store
    the newly opened file in FILE.  Seek to location OFFSET before
    returning.  Perform temporary allocations in POOL. */
@@ -1480,9 +1354,9 @@ open_and_seek_revision(apr_file_t **file
 {
   apr_file_t *rev_file;
 
-  SVN_ERR(ensure_revision_exists(fs, rev, pool));
+  SVN_ERR(svn_fs_fs__revision_exists(rev, fs, pool));
 
-  SVN_ERR(open_pack_or_rev_file(&rev_file, fs, rev, pool));
+  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, rev, pool));
 
   if (svn_fs_fs__is_packed_rev(fs, rev))
     {
@@ -1514,7 +1388,8 @@ open_and_seek_transaction(apr_file_t **f
   apr_file_t *rev_file;
   apr_off_t offset;
 
-  SVN_ERR(svn_io_file_open(&rev_file, path_txn_proto_rev(fs, txn_id, pool),
+  SVN_ERR(svn_io_file_open(&rev_file,
+                           svn_fs_fs__path_txn_proto_rev(fs, txn_id, pool),
                            APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
 
   offset = rep->offset;
@@ -1635,7 +1510,8 @@ get_node_revision_body(node_revision_t *
   if (svn_fs_fs__id_txn_id(id))
     {
       /* This is a transaction node-rev. */
-      err = svn_io_file_open(&revision_file, path_txn_node_rev(fs, id, pool),
+      err = svn_io_file_open(&revision_file,
+                             svn_fs_fs__path_txn_node_rev(fs, id, pool),
                              APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
     }
   else
@@ -1703,7 +1579,8 @@ svn_fs_fs__put_node_revision(svn_fs_t *f
                              _("Attempted to write to non-transaction '%s'"),
                              svn_fs_fs__id_unparse(id, pool)->data);
 
-  SVN_ERR(svn_io_file_open(&noderev_file, path_txn_node_rev(fs, id, pool),
+  SVN_ERR(svn_io_file_open(&noderev_file,
+                           svn_fs_fs__path_txn_node_rev(fs, id, pool),
                            APR_WRITE | APR_CREATE | APR_TRUNCATE
                            | APR_BUFFERED, APR_OS_DEFAULT, pool));
 
@@ -1887,14 +1764,14 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
   svn_fs_id_t *root_id = NULL;
   svn_boolean_t is_cached;
 
-  SVN_ERR(ensure_revision_exists(fs, rev, pool));
+  SVN_ERR(svn_fs_fs__revision_exists(rev, fs, pool));
 
   SVN_ERR(svn_cache__get((void **) root_id_p, &is_cached,
                          ffd->rev_root_id_cache, &rev, pool));
   if (is_cached)
     return SVN_NO_ERROR;
 
-  SVN_ERR(open_pack_or_rev_file(&revision_file, fs, rev, pool));
+  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));
 
@@ -1987,7 +1864,7 @@ create_rep_state_body(struct rep_state *
   SVN_ERR(svn_fs_fs__read_rep_header(&rh,
                            svn_stream_from_aprfile2(rs->file, FALSE, pool),
                            pool));
-  SVN_ERR(get_file_offset(&rs->start, rs->file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&rs->start, rs->file, pool));
   rs->off = rs->start;
   rs->end = rs->start + rep->size;
   *rep_state = rs;
@@ -2437,7 +2314,7 @@ read_delta_window(svn_txdelta_window_t *
     {
       SVN_ERR(svn_txdelta_skip_svndiff_window(rs->file, rs->ver, pool));
       rs->chunk_index++;
-      SVN_ERR(get_file_offset(&rs->off, rs->file, pool));
+      SVN_ERR(svn_fs_fs__get_file_offset(&rs->off, rs->file, pool));
       if (rs->off >= rs->end)
         return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                 _("Reading one svndiff window read "
@@ -2455,7 +2332,7 @@ read_delta_window(svn_txdelta_window_t *
   stream = svn_stream_from_aprfile2(rs->file, TRUE, pool);
   SVN_ERR(svn_txdelta_read_svndiff_window(nwin, stream, rs->ver, pool));
   rs->chunk_index++;
-  SVN_ERR(get_file_offset(&rs->off, rs->file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&rs->off, rs->file, pool));
 
   if (rs->off > rs->end)
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -2968,7 +2845,8 @@ get_dir_contents(apr_hash_t *entries,
 
   if (noderev->data_rep && noderev->data_rep->txn_id)
     {
-      const char *filename = path_txn_node_children(fs, noderev->id, pool);
+      const char *filename
+        = svn_fs_fs__path_txn_node_children(fs, noderev->id, pool);
 
       /* The representation is mutable.  Read the old directory
          contents from the mutable children file, followed by the
@@ -3227,7 +3105,8 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
 
   if (noderev->prop_rep && noderev->prop_rep->txn_id)
     {
-      const char *filename = path_txn_node_props(fs, noderev->id, pool);
+      const char *filename
+        = svn_fs_fs__path_txn_node_props(fs, noderev->id, pool);
       proplist = apr_hash_make(pool);
 
       SVN_ERR(svn_stream_open_readonly(&stream, filename, pool, pool));
@@ -3680,7 +3559,7 @@ get_changes(apr_array_header_t **changes
 
   SVN_ERR(ensure_revision_exists(fs, rev, pool));
 
-  SVN_ERR(open_pack_or_rev_file(&revision_file, fs, rev, pool));
+  SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev, pool));
 
   SVN_ERR(get_root_changes_offset(NULL, &changes_offset, revision_file, fs,
                                   rev, pool));
@@ -3905,8 +3784,8 @@ svn_fs_fs__create_txn(svn_fs_txn_t **txn
   SVN_ERR(create_new_txn_noderev_from_rev(fs, txn->id, root_id, pool));
 
   /* Create an empty rev file. */
-  SVN_ERR(svn_io_file_create(path_txn_proto_rev(fs, txn->id, pool), "",
-                             pool));
+  SVN_ERR(svn_io_file_create(svn_fs_fs__path_txn_proto_rev(fs, txn->id, pool),
+                             "", pool));
 
   /* Create an empty rev-lock file. */
   SVN_ERR(svn_io_file_create(path_txn_proto_rev_lock(fs, txn->id, pool), "",
@@ -4166,16 +4045,17 @@ svn_fs_fs__purge_txn(svn_fs_t *fs,
   /* Remove the shared transaction object associated with this transaction. */
   SVN_ERR(purge_shared_txn(fs, txn_id, pool));
   /* Remove the directory associated with this transaction. */
-  SVN_ERR(svn_io_remove_dir2(path_txn_dir(fs, txn_id, pool), FALSE,
-                             NULL, NULL, pool));
+  SVN_ERR(svn_io_remove_dir2(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
+                             FALSE, NULL, NULL, pool));
   if (ffd->format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
     {
       /* Delete protorev and its lock, which aren't in the txn
          directory.  It's OK if they don't exist (for example, if this
          is post-commit and the proto-rev has been moved into
          place). */
-      SVN_ERR(svn_io_remove_file2(path_txn_proto_rev(fs, txn_id, pool),
-                                  TRUE, pool));
+      SVN_ERR(svn_io_remove_file2(
+                  svn_fs_fs__path_txn_proto_rev(fs, txn_id, pool),
+                  TRUE, pool));
       SVN_ERR(svn_io_remove_file2(path_txn_proto_rev_lock(fs, txn_id, pool),
                                   TRUE, pool));
     }
@@ -4208,7 +4088,8 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
                      apr_pool_t *pool)
 {
   representation_t *rep = parent_noderev->data_rep;
-  const char *filename = path_txn_node_children(fs, parent_noderev->id, pool);
+  const char *filename
+    = svn_fs_fs__path_txn_node_children(fs, parent_noderev->id, pool);
   apr_file_t *file;
   svn_stream_t *out;
   fs_fs_data_t *ffd = fs->fsap_data;
@@ -4607,7 +4488,7 @@ rep_write_get_baton(struct rep_write_bat
   b->file = file;
   b->rep_stream = svn_stream_from_aprfile2(file, TRUE, b->pool);
 
-  SVN_ERR(get_file_offset(&b->rep_offset, file, b->pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&b->rep_offset, file, b->pool));
 
   /* Get the base for this delta. */
   SVN_ERR(choose_delta_base(&base_rep, fs, noderev, FALSE, b->pool));
@@ -4628,7 +4509,7 @@ rep_write_get_baton(struct rep_write_bat
   SVN_ERR(svn_fs_fs__write_rep_header(&header, b->rep_stream, b->pool));
 
   /* Now determine the offset of the actual svndiff data. */
-  SVN_ERR(get_file_offset(&b->delta_start, file, b->pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&b->delta_start, file, b->pool));
 
   /* Cleanup in case something goes wrong. */
   apr_pool_cleanup_register(b->pool, b, rep_write_cleanup,
@@ -4769,7 +4650,7 @@ rep_write_contents_close(void *baton)
     SVN_ERR(svn_stream_close(b->delta_stream));
 
   /* Determine the length of the svndiff data. */
-  SVN_ERR(get_file_offset(&offset, b->file, b->pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&offset, b->file, b->pool));
   rep->size = offset - b->delta_start;
 
   /* Fill in the rest of the representation field. */
@@ -4901,7 +4782,8 @@ svn_fs_fs__set_proplist(svn_fs_t *fs,
                         apr_hash_t *proplist,
                         apr_pool_t *pool)
 {
-  const char *filename = path_txn_node_props(fs, noderev->id, pool);
+  const char *filename
+    = svn_fs_fs__path_txn_node_props(fs, noderev->id, pool);
   apr_file_t *file;
   svn_stream_t *out;
 
@@ -5013,7 +4895,7 @@ write_hash_rep(representation_t *rep,
   struct write_hash_baton *whb;
   representation_t *old_rep;
 
-  SVN_ERR(get_file_offset(&rep->offset, file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&rep->offset, file, pool));
 
   whb = apr_pcalloc(pool, sizeof(*whb));
 
@@ -5097,7 +4979,7 @@ write_hash_delta_rep(representation_t *r
   SVN_ERR(choose_delta_base(&base_rep, fs, noderev, props, pool));
   SVN_ERR(read_representation(&source, fs, base_rep, pool));
 
-  SVN_ERR(get_file_offset(&rep->offset, file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&rep->offset, file, pool));
 
   /* Write out the rep header. */
   if (base_rep)
@@ -5114,7 +4996,7 @@ write_hash_delta_rep(representation_t *r
 
   file_stream = svn_stream_from_aprfile2(file, TRUE, pool);
   SVN_ERR(svn_fs_fs__write_rep_header(&header, file_stream, pool));
-  SVN_ERR(get_file_offset(&delta_start, file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&delta_start, file, pool));
 
   /* Prepare to write the svndiff data. */
   svn_txdelta_to_svndiff3(&diff_wh,
@@ -5156,7 +5038,7 @@ write_hash_delta_rep(representation_t *r
   else
     {
       /* Write out our cosmetic end marker. */
-      SVN_ERR(get_file_offset(&rep_end, file, pool));
+      SVN_ERR(svn_fs_fs__get_file_offset(&rep_end, file, pool));
       SVN_ERR(svn_stream_puts(file_stream, "ENDREP\n"));
 
       /* update the representation */
@@ -5375,7 +5257,7 @@ write_final_rev(const svn_fs_id_t **new_
 
 
   /* Convert our temporary ID into a permanent revision one. */
-  SVN_ERR(get_file_offset(&my_offset, file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&my_offset, file, pool));
 
   node_id = svn_fs_fs__id_node_id(noderev->id);
   if (*node_id == '_')
@@ -5480,7 +5362,7 @@ write_final_changed_path_info(apr_off_t 
   apr_hash_t *changed_paths;
   apr_off_t offset;
 
-  SVN_ERR(get_file_offset(&offset, file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool));
 
   SVN_ERR(svn_fs_fs__txn_changes_fetch(&changed_paths, fs, txn_id, pool));
 
@@ -5724,7 +5606,7 @@ commit_body(void *baton, apr_pool_t *poo
   /* Get a write handle on the proto revision file. */
   SVN_ERR(get_writable_proto_rev(&proto_file, &proto_file_lockcookie,
                                  cb->fs, cb->txn->id, pool));
-  SVN_ERR(get_file_offset(&initial_offset, proto_file, pool));
+  SVN_ERR(svn_fs_fs__get_file_offset(&initial_offset, proto_file, pool));
 
   /* Write out all the node-revisions and directory contents. */
   root_id = svn_fs_fs__id_txn_create("0", "0", cb->txn->id, pool);
@@ -5812,7 +5694,7 @@ commit_body(void *baton, apr_pool_t *poo
   /* Move the finished rev file into place. */
   old_rev_filename = svn_fs_fs__path_rev_absolute(cb->fs, old_rev, pool);
   rev_filename = svn_fs_fs__path_rev(cb->fs, new_rev, pool);
-  proto_filename = path_txn_proto_rev(cb->fs, cb->txn->id, pool);
+  proto_filename = svn_fs_fs__path_txn_proto_rev(cb->fs, cb->txn->id, pool);
   SVN_ERR(svn_fs_fs__move_into_place(proto_filename, rev_filename,
                                      old_rev_filename, pool));
 
@@ -6097,7 +5979,7 @@ recover_get_largest_revision(svn_fs_t *f
       svn_error_t *err;
       apr_file_t *file;
 
-      err = open_pack_or_rev_file(&file, fs, right, iterpool);
+      err = svn_fs_fs__open_pack_or_rev_file(&file, fs, right, iterpool);
       svn_pool_clear(iterpool);
 
       if (err && err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
@@ -6121,7 +6003,7 @@ recover_get_largest_revision(svn_fs_t *f
       svn_error_t *err;
       apr_file_t *file;
 
-      err = open_pack_or_rev_file(&file, fs, probe, iterpool);
+      err = svn_fs_fs__open_pack_or_rev_file(&file, fs, probe, iterpool);
       svn_pool_clear(iterpool);
 
       if (err && err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
@@ -6406,7 +6288,8 @@ recover_body(void *baton, apr_pool_t *po
           if (b->cancel_func)
             SVN_ERR(b->cancel_func(b->cancel_baton));
 
-          SVN_ERR(open_pack_or_rev_file(&rev_file, fs, rev, iterpool));
+          SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, rev,
+                                                   iterpool));
           SVN_ERR(get_root_changes_offset(&root_offset, NULL, rev_file, fs, rev,
                                           iterpool));
           SVN_ERR(recover_find_max_ids(fs, rev, rev_file, root_offset,
@@ -6727,7 +6610,8 @@ svn_fs_fs__open_txn(svn_fs_txn_t **txn_p
   transaction_t *local_txn;
 
   /* First check to see if the directory exists. */
-  SVN_ERR(svn_io_check_path(path_txn_dir(fs, name, pool), &kind, pool));
+  SVN_ERR(svn_io_check_path(svn_fs_fs__path_txn_dir(fs, name, pool), &kind,
+                            pool));
 
   /* Did we find it? */
   if (kind != svn_node_dir)
@@ -6774,16 +6658,17 @@ svn_fs_fs__delete_node_revision(svn_fs_t
 
   /* Delete any mutable property representation. */
   if (noderev->prop_rep && noderev->prop_rep->txn_id)
-    SVN_ERR(svn_io_remove_file2(path_txn_node_props(fs, id, pool), FALSE,
-                                pool));
+    SVN_ERR(svn_io_remove_file2(svn_fs_fs__path_txn_node_props(fs, id, pool),
+                                FALSE, pool));
 
   /* Delete any mutable data representation. */
   if (noderev->data_rep && noderev->data_rep->txn_id
       && noderev->kind == svn_node_dir)
     {
       fs_fs_data_t *ffd = fs->fsap_data;
-      SVN_ERR(svn_io_remove_file2(path_txn_node_children(fs, id, pool), FALSE,
-                                  pool));
+      SVN_ERR(svn_io_remove_file2(svn_fs_fs__path_txn_node_children(fs, id,
+                                                                    pool),
+                                  FALSE, pool));
 
       /* remove the corresponding entry from the cache, if such exists */
       if (ffd->txn_dir_cache)
@@ -6793,7 +6678,8 @@ svn_fs_fs__delete_node_revision(svn_fs_t
         }
     }
 
-  return svn_io_remove_file2(path_txn_node_rev(fs, id, pool), FALSE, pool);
+  return svn_io_remove_file2(svn_fs_fs__path_txn_node_rev(fs, id, pool),
+                             FALSE, pool);
 }
 
 
@@ -7454,8 +7340,8 @@ hotcopy_update_current(svn_revnum_t *dst
       if (dst_ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
         SVN_ERR(svn_fs_fs__update_min_unpacked_rev(dst_fs, scratch_pool));
 
-      SVN_ERR(open_pack_or_rev_file(&rev_file, dst_fs, new_youngest,
-                                    scratch_pool));
+      SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, dst_fs,
+                                               new_youngest, scratch_pool));
       SVN_ERR(get_root_changes_offset(&root_offset, NULL, rev_file,
                                       dst_fs, new_youngest, scratch_pool));
       SVN_ERR(recover_find_max_ids(dst_fs, new_youngest, rev_file,

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.c?rev=1503664&r1=1503663&r2=1503664&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.c (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.c Tue Jul 16 11:40:19 2013
@@ -169,6 +169,67 @@ svn_fs_fs__path_revprops(svn_fs_t *fs,
 }
 
 const char *
+svn_fs_fs__path_txn_dir(svn_fs_t *fs,
+                        const char *txn_id,
+                        apr_pool_t *pool)
+{
+  SVN_ERR_ASSERT_NO_RETURN(txn_id != NULL);
+  return svn_dirent_join_many(pool, fs->path, PATH_TXNS_DIR,
+                              apr_pstrcat(pool, txn_id, PATH_EXT_TXN,
+                                          (char *)NULL),
+                              NULL);
+}
+
+const char *
+svn_fs_fs__path_txn_proto_rev(svn_fs_t *fs,
+                              const char *txn_id,
+                              apr_pool_t *pool)
+{
+  fs_fs_data_t *ffd = fs->fsap_data;
+  if (ffd->format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
+    return svn_dirent_join_many(pool, fs->path, PATH_TXN_PROTOS_DIR,
+                                apr_pstrcat(pool, txn_id, PATH_EXT_REV,
+                                            (char *)NULL),
+                                NULL);
+  else
+    return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool),
+                           PATH_REV, pool);
+}
+
+const char *
+svn_fs_fs__path_txn_node_rev(svn_fs_t *fs,
+                             const svn_fs_id_t *id,
+                             apr_pool_t *pool)
+{
+  const char *txn_id = svn_fs_fs__id_txn_id(id);
+  const char *node_id = svn_fs_fs__id_node_id(id);
+  const char *copy_id = svn_fs_fs__id_copy_id(id);
+  const char *name = apr_psprintf(pool, PATH_PREFIX_NODE "%s.%s",
+                                  node_id, copy_id);
+
+  return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool), name,
+                         pool);
+}
+
+const char *
+svn_fs_fs__path_txn_node_props(svn_fs_t *fs,
+                               const svn_fs_id_t *id,
+                               apr_pool_t *pool)
+{
+  return apr_pstrcat(pool, svn_fs_fs__path_txn_node_rev(fs, id, pool),
+                     PATH_EXT_PROPS, (char *)NULL);
+}
+
+const char *
+svn_fs_fs__path_txn_node_children(svn_fs_t *fs,
+                                  const svn_fs_id_t *id,
+                                  apr_pool_t *pool)
+{
+  return apr_pstrcat(pool, svn_fs_fs__path_txn_node_rev(fs, id, pool),
+                     PATH_EXT_CHILDREN, (char *)NULL);
+}
+
+const char *
 svn_fs_fs__path_min_unpacked_rev(svn_fs_t *fs,
                                  apr_pool_t *pool)
 {
@@ -286,6 +347,22 @@ svn_fs_fs__try_stringbuf_from_file(svn_s
 }
 
 svn_error_t *
+svn_fs_fs__get_file_offset(apr_off_t *offset_p,
+                           apr_file_t *file,
+                           apr_pool_t *pool)
+{
+  apr_off_t offset;
+
+  /* Note that, for buffered files, one (possibly surprising) side-effect
+     of this call is to flush any unwritten data to disk. */
+  offset = 0;
+  SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, pool));
+  *offset_p = offset;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_fs_fs__read_content(svn_stringbuf_t **content,
                         const char *fname,
                         apr_pool_t *pool)
@@ -391,3 +468,54 @@ 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);
+}

Modified: subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.h?rev=1503664&r1=1503663&r2=1503664&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.h (original)
+++ subversion/branches/fsfs-improvements/subversion/libsvn_fs_fs/util.h Tue Jul 16 11:40:19 2013
@@ -155,6 +155,47 @@ const char *
 svn_fs_fs__path_min_unpacked_rev(svn_fs_t *fs,
                                  apr_pool_t *pool);
 
+/* Return the path of the directory containing the transaction TXN_ID in FS.
+ * The result will be allocated in POOL.
+ */
+const char *
+svn_fs_fs__path_txn_dir(svn_fs_t *fs,
+                        const char *txn_id,
+                        apr_pool_t *pool);
+
+/* Return the path of the proto-revision file for transaction TXN_ID in FS.
+ * The result will be allocated in POOL.
+ */
+const char *
+svn_fs_fs__path_txn_proto_rev(svn_fs_t *fs,
+                              const char *txn_id,
+                              apr_pool_t *pool);
+
+/* Return the path of the file containing the in-transaction node revision
+ * identified by ID in FS.  The result will be allocated in POOL.
+ */
+const char *
+svn_fs_fs__path_txn_node_rev(svn_fs_t *fs,
+                             const svn_fs_id_t *id,
+                             apr_pool_t *pool);
+
+/* Return the path of the file containing the in-transaction properties of
+ * the node identified by ID in FS.  The result will be allocated in POOL.
+ */
+const char *
+svn_fs_fs__path_txn_node_props(svn_fs_t *fs,
+                               const svn_fs_id_t *id,
+                               apr_pool_t *pool);
+
+/* Return the path of the file containing the directory entries of the
+ * in-transaction directory node identified by ID in FS.
+ * The result will be allocated in POOL.
+ */
+const char *
+svn_fs_fs__path_txn_node_children(svn_fs_t *fs,
+                                  const svn_fs_id_t *id,
+                                  apr_pool_t *pool);
+
 /* Set *MIN_UNPACKED_REV to the integer value read from the file returned
  * by #svn_fs_fs__path_min_unpacked_rev() for FS.
  * Use POOL for temporary allocations.
@@ -210,6 +251,12 @@ svn_fs_fs__try_stringbuf_from_file(svn_s
                                    svn_boolean_t last_attempt,
                                    apr_pool_t *pool);
 
+/* Fetch the current offset of FILE into *OFFSET_P. */
+svn_error_t *
+svn_fs_fs__get_file_offset(apr_off_t *offset_p,
+                           apr_file_t *file,
+                           apr_pool_t *pool);
+
 /* Read the file FNAME and store the contents in *BUF.
    Allocations are performed in POOL. */
 svn_error_t *
@@ -242,4 +289,21 @@ 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);
+
 #endif
\ No newline at end of file