You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2014/10/29 23:27:03 UTC
svn commit: r1635317 [1/2] - in /subversion/trunk/subversion/libsvn_fs_x: ./
cached_data.c cached_data.h fs_x.c fs_x.h index.c index.h pack.c recovery.c
rev_file.c rev_file.h verify.c
Author: stefan2
Date: Wed Oct 29 22:27:02 2014
New Revision: 1635317
URL: http://svn.apache.org/r1635317
Log:
Sync FSX with FSFS:
Merge and adapt revisions r1531982 and r1604717 from libsvn_fs_fs.
Various conflicts were caused by reordered code and renamed functions
in FSX. Lots of additonal code / callers to be adapted.
This ports the revision_file_t abstraction to FSX.
Added:
subversion/trunk/subversion/libsvn_fs_x/rev_file.c
- copied, changed from r1531982, subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.c
subversion/trunk/subversion/libsvn_fs_x/rev_file.h
- copied, changed from r1531982, subversion/branches/log-addressing/subversion/libsvn_fs_fs/rev_file.h
Modified:
subversion/trunk/subversion/libsvn_fs_x/ (props changed)
subversion/trunk/subversion/libsvn_fs_x/cached_data.c
subversion/trunk/subversion/libsvn_fs_x/cached_data.h
subversion/trunk/subversion/libsvn_fs_x/fs_x.c
subversion/trunk/subversion/libsvn_fs_x/fs_x.h
subversion/trunk/subversion/libsvn_fs_x/index.c
subversion/trunk/subversion/libsvn_fs_x/index.h
subversion/trunk/subversion/libsvn_fs_x/pack.c
subversion/trunk/subversion/libsvn_fs_x/recovery.c
subversion/trunk/subversion/libsvn_fs_x/verify.c
Propchange: subversion/trunk/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
Merged /subversion/trunk/subversion/libsvn_fs_fs:r1604717
Merged /subversion/branches/log-addressing/subversion/libsvn_fs_fs:r1531982
Modified: subversion/trunk/subversion/libsvn_fs_x/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/cached_data.c?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/cached_data.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/cached_data.c Wed Oct 29 22:27:02 2014
@@ -48,12 +48,12 @@
#include "svn_private_config.h"
-/* forward-declare */
+/* forward-declare. See implementation for the docstring */
static svn_error_t *
block_read(void **result,
svn_fs_t *fs,
const svn_fs_x__id_part_t *id,
- apr_file_t *revision_file,
+ svn_fs_x__revision_file_t *revision_file,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
@@ -192,12 +192,12 @@ aligned_seek(svn_fs_t *fs,
store the newly opened file in FILE. Seek to the item's location before
returning. Perform temporary allocations in POOL. */
static svn_error_t *
-open_and_seek_revision(apr_file_t **file,
+open_and_seek_revision(svn_fs_x__revision_file_t **file,
svn_fs_t *fs,
const svn_fs_x__id_part_t *id,
apr_pool_t *pool)
{
- apr_file_t *rev_file;
+ svn_fs_x__revision_file_t *rev_file;
apr_off_t offset = -1;
apr_uint32_t sub_item = 0;
svn_revnum_t rev = svn_fs_x__get_revnum(id->change_set);
@@ -205,8 +205,8 @@ open_and_seek_revision(apr_file_t **file
SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, pool));
SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, rev, pool));
- SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, id, pool));
- SVN_ERR(aligned_seek(fs, rev_file, NULL, offset, pool));
+ SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, rev_file, id, pool));
+ SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, pool));
*file = rev_file;
@@ -217,24 +217,20 @@ open_and_seek_revision(apr_file_t **file
to its position and store the newly opened file in FILE. Perform
temporary allocations in POOL. */
static svn_error_t *
-open_and_seek_transaction(apr_file_t **file,
+open_and_seek_transaction(svn_fs_x__revision_file_t **file,
svn_fs_t *fs,
representation_t *rep,
apr_pool_t *pool)
{
- apr_file_t *rev_file;
apr_off_t offset;
apr_uint32_t sub_item = 0;
apr_int64_t txn_id = svn_fs_x__get_txn_id(rep->id.change_set);
- SVN_ERR(svn_io_file_open(&rev_file,
- svn_fs_x__path_txn_proto_rev(fs, txn_id, pool),
- APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
+ SVN_ERR(svn_fs_x__open_proto_rev_file(file, fs, txn_id, pool));
- SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, &rep->id, pool));
- SVN_ERR(aligned_seek(fs, rev_file, NULL, offset, pool));
-
- *file = rev_file;
+ SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, *file, &rep->id,
+ pool));
+ SVN_ERR(aligned_seek(fs, (*file)->file, NULL, offset, pool));
return SVN_NO_ERROR;
}
@@ -243,7 +239,7 @@ open_and_seek_transaction(apr_file_t **f
the correct file and seek to the correction location. Store this
file in *FILE_P. Perform any allocations in POOL. */
static svn_error_t *
-open_and_seek_representation(apr_file_t **file_p,
+open_and_seek_representation(svn_fs_x__revision_file_t **file_p,
svn_fs_t *fs,
representation_t *rep,
apr_pool_t *pool)
@@ -276,16 +272,17 @@ get_node_revision_body(node_revision_t *
const svn_fs_id_t *id,
apr_pool_t *pool)
{
- apr_file_t *revision_file;
svn_error_t *err;
svn_boolean_t is_cached = FALSE;
fs_x_data_t *ffd = fs->fsap_data;
if (svn_fs_x__id_is_txn(id))
{
+ apr_file_t *file;
+
/* This is a transaction node-rev. Its storage logic is very
different from that of rev / pack files. */
- err = svn_io_file_open(&revision_file,
+ err = svn_io_file_open(&file,
svn_fs_x__path_txn_node_rev(fs, id, pool),
APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
if (err)
@@ -300,26 +297,31 @@ get_node_revision_body(node_revision_t *
}
SVN_ERR(svn_fs_x__read_noderev(noderev_p,
- svn_stream_from_aprfile2(revision_file,
+ svn_stream_from_aprfile2(file,
FALSE,
pool),
pool));
}
else
{
+ svn_fs_x__revision_file_t *revision_file;
+
/* noderevs in rev / pack files can be cached */
const svn_fs_x__id_part_t *noderev_id = svn_fs_x__id_noderev_id(id);
svn_revnum_t revision = svn_fs_x__get_revnum(noderev_id->change_set);
pair_cache_key_t key;
+ SVN_ERR(svn_fs_x__open_pack_or_rev_file(&revision_file, fs, revision,
+ pool));
+
/* First, try a noderevs container cache lookup. */
if ( svn_fs_x__is_packed_rev(fs, revision)
&& ffd->noderevs_container_cache)
{
apr_off_t offset;
apr_uint32_t sub_item;
- SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, noderev_id,
- pool));
+ SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, revision_file,
+ noderev_id, pool));
key.revision = svn_fs_x__packed_base_rev(fs, revision);
key.second = offset;
@@ -357,7 +359,7 @@ get_node_revision_body(node_revision_t *
revision_file,
pool,
pool));
- SVN_ERR(svn_io_file_close(revision_file, pool));
+ SVN_ERR(svn_fs_x__close_revision_file(revision_file));
}
return SVN_NO_ERROR;
@@ -407,6 +409,9 @@ svn_fs_x__get_mergeinfo_count(apr_int64_
fs_x_data_t *ffd = fs->fsap_data;
svn_revnum_t revision = svn_fs_x__get_revnum(noderev_id->change_set);
+ svn_fs_x__revision_file_t *rev_file;
+ SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, revision, pool));
+
if ( svn_fs_x__is_packed_rev(fs, revision)
&& ffd->noderevs_container_cache)
{
@@ -415,7 +420,7 @@ svn_fs_x__get_mergeinfo_count(apr_int64_
apr_uint32_t sub_item;
svn_boolean_t is_cached;
- SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs,
+ SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, rev_file,
noderev_id, pool));
key.revision = svn_fs_x__packed_base_rev(fs, revision);
key.second = offset;
@@ -455,15 +460,13 @@ svn_fs_x__rev_get_root(svn_fs_id_t **roo
typedef struct shared_file_t
{
/* The opened file. NULL while file is not open, yet. */
- apr_file_t *file;
-
- /* Stream wrapper around FILE. NULL while file is not open, yet. */
- svn_stream_t *stream;
+ svn_fs_x__revision_file_t *rfile;
/* file system to open the file in */
svn_fs_t *fs;
- /* revision contained in the file */
+ /* a revision contained in the FILE. Since this file may be shared,
+ that value may be different from REP_STATE_T->REVISION. */
svn_revnum_t revision;
/* pool to use when creating the FILE. This guarantees that the file
@@ -477,7 +480,7 @@ typedef struct shared_file_t
typedef struct rep_state_t
{
/* shared lazy-open rev/pack file structure */
- shared_file_t *file;
+ shared_file_t *sfile;
/* The txdelta window cache to use or NULL. */
svn_cache__t *window_cache;
/* Caches un-deltified windows. May be NULL. */
@@ -490,16 +493,95 @@ typedef struct rep_state_t
apr_size_t header_size;
apr_off_t start; /* The starting offset for the raw
svndiff data minus header.
- -1 if the offset is yet unknwon. */
+ -1 if the offset is yet unknown. */
/* sub-item index in case the rep is containered */
apr_uint32_t sub_item;
- apr_off_t current;/* The current offset relative to start. */
- apr_off_t size; /* Final value of CURRENT. */
+ apr_off_t current;/* The current offset relative to START. */
+ apr_off_t size; /* The on-disk size of the representation. */
int ver; /* If a delta, what svndiff version?
-1 for unknown delta version. */
int chunk_index; /* number of the window to read */
} rep_state_t;
+/* Simple wrapper around svn_fs_x__get_file_offset to simplify callers. */
+static svn_error_t *
+get_file_offset(apr_off_t *offset,
+ rep_state_t *rs,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_fs_x__get_file_offset(offset,
+ rs->sfile->rfile->file,
+ pool));
+}
+
+/* Simple wrapper around svn_io_file_aligned_seek to simplify callers. */
+static svn_error_t *
+rs_aligned_seek(rep_state_t *rs,
+ apr_off_t *buffer_start,
+ apr_off_t offset,
+ apr_pool_t *pool)
+{
+ fs_x_data_t *ffd = rs->sfile->fs->fsap_data;
+ return svn_error_trace(svn_io_file_aligned_seek(rs->sfile->rfile->file,
+ ffd->block_size,
+ buffer_start, offset,
+ pool));
+}
+
+/* Open FILE->FILE and FILE->STREAM if they haven't been opened, yet. */
+static svn_error_t*
+auto_open_shared_file(shared_file_t *file)
+{
+ if (file->rfile == NULL)
+ SVN_ERR(svn_fs_x__open_pack_or_rev_file(&file->rfile, file->fs,
+ file->revision, file->pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Set RS->START to the begin of the representation raw in RS->SFILE->RFILE,
+ if that hasn't been done yet. Use POOL for temporary allocations. */
+static svn_error_t*
+auto_set_start_offset(rep_state_t *rs, apr_pool_t *pool)
+{
+ if (rs->start == -1)
+ {
+ SVN_ERR(svn_fs_x__item_offset(&rs->start, &rs->sub_item,
+ rs->sfile->fs, rs->sfile->rfile,
+ &rs->rep_id, pool));
+ rs->start += rs->header_size;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Set RS->VER depending on what is found in the already open RS->FILE->FILE
+ if the diff version is still unknown. Use POOL for temporary allocations.
+ */
+static svn_error_t*
+auto_read_diff_version(rep_state_t *rs, apr_pool_t *pool)
+{
+ if (rs->ver == -1)
+ {
+ char buf[4];
+ SVN_ERR(rs_aligned_seek(rs, NULL, rs->start, pool));
+ SVN_ERR(svn_io_file_read_full2(rs->sfile->rfile->file, buf,
+ sizeof(buf), NULL, NULL, pool));
+
+ /* ### Layering violation */
+ if (! ((buf[0] == 'S') && (buf[1] == 'V') && (buf[2] == 'N')))
+ return svn_error_create
+ (SVN_ERR_FS_CORRUPT, NULL,
+ _("Malformed svndiff data in representation"));
+ rs->ver = buf[3];
+
+ rs->chunk_index = 0;
+ rs->current = 4;
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* See create_rep_state, which wraps this and adds another error. */
static svn_error_t *
create_rep_state_body(rep_state_t **rep_state,
@@ -525,7 +607,7 @@ create_rep_state_body(rep_state_t **rep_
* we can re-use the same, already open file object
*/
svn_boolean_t reuse_shared_file
- = shared_file && *shared_file && (*shared_file)->file
+ = shared_file && *shared_file && (*shared_file)->rfile
&& SVN_IS_VALID_REVNUM((*shared_file)->revision)
&& (*shared_file)->revision < ffd->min_unpacked_rev
&& revision < ffd->min_unpacked_rev
@@ -569,45 +651,63 @@ create_rep_state_body(rep_state_t **rep_
SVN_ERR(svn_cache__get((void **) &rh, &is_cached,
ffd->rep_header_cache, &key, pool));
- if (is_cached)
+ /* initialize the (shared) FILE member in RS */
+ if (reuse_shared_file)
{
- if (reuse_shared_file)
- {
- rs->file = *shared_file;
- }
- else
- {
- shared_file_t *file = apr_pcalloc(pool, sizeof(*file));
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
-
- file->revision = revision;
- file->pool = pool;
- file->fs = fs;
- rs->file = file;
-
- /* remember the current file, if suggested by the caller */
- if (shared_file)
- *shared_file = file;
- }
+ rs->sfile = *shared_file;
}
else
{
+ shared_file_t *file = apr_pcalloc(pool, sizeof(*file));
+ file->revision = revision;
+ file->pool = pool;
+ file->fs = fs;
+ rs->sfile = file;
+
+ /* remember the current file, if suggested by the caller */
+ if (shared_file)
+ *shared_file = file;
+ }
+
+ /* read rep header, if necessary */
+ if (!is_cached)
+ {
/* we will need the on-disk location for non-txn reps */
apr_off_t offset;
apr_uint32_t sub_item;
+ svn_boolean_t in_container = TRUE;
- if (SVN_IS_VALID_REVNUM(revision))
- SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, &rep->id, pool));
+ /* ensure file is open and navigate to the start of rep header */
+ if (reuse_shared_file)
+ {
+ /* ... we can re-use the same, already open file object.
+ * This implies that we don't read from a txn.
+ */
+ SVN_ERR_ASSERT(sub_item == 0);
+ rs->sfile = *shared_file;
+ SVN_ERR(auto_open_shared_file(rs->sfile));
+ SVN_ERR(rs_aligned_seek(rs, NULL, offset, pool));
+ }
+ else
+ {
+ /* otherwise, create a new file object. May or may not be
+ * an in-txn file.
+ */
+ SVN_ERR(open_and_seek_representation(&rs->sfile->rfile, fs, rep,
+ pool));
+ }
- /* is rep stored in some star-deltified container? */
if (SVN_IS_VALID_REVNUM(revision))
{
- svn_boolean_t in_container = TRUE;
+ SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs,
+ rs->sfile->rfile, &rep->id, pool));
+
+ /* is rep stored in some star-deltified container? */
if (sub_item == 0)
{
svn_fs_x__p2l_entry_t *entry;
- SVN_ERR(svn_fs_x__p2l_entry_lookup(&entry, fs, revision,
- offset, pool));
+ SVN_ERR(svn_fs_x__p2l_entry_lookup(&entry, fs, rs->sfile->rfile,
+ revision, offset, pool));
in_container = entry->type == SVN_FS_X__ITEM_TYPE_REPS_CONT;
}
@@ -617,57 +717,26 @@ create_rep_state_body(rep_state_t **rep_
*rep_header = apr_pcalloc(pool, sizeof(**rep_header));
(*rep_header)->type = svn_fs_x__rep_container;
- /* provide an empty shared file struct */
- rs->file = apr_pcalloc(pool, sizeof(*rs->file));
- rs->file->revision = revision;
- rs->file->pool = pool;
- rs->file->fs = fs;
-
/* exit to caller */
*rep_state = rs;
return SVN_NO_ERROR;
}
}
- if (reuse_shared_file)
- {
- /* ... we can re-use the same, already open file object
- */
- SVN_ERR_ASSERT(sub_item == 0);
- SVN_ERR(aligned_seek(fs, (*shared_file)->file, NULL, offset, pool));
-
- rs->file = *shared_file;
- }
- else
- {
- shared_file_t *file = apr_pcalloc(pool, sizeof(*file));
- file->revision = revision;
- file->pool = pool;
- file->fs = fs;
-
- /* otherwise, create a new file object
- */
- SVN_ERR(open_and_seek_representation(&file->file, fs, rep, pool));
- file->stream = svn_stream_from_aprfile2(file->file, TRUE,
- file->pool);
- rs->file = file;
-
- /* remember the current file, if suggested by the caller */
- if (shared_file)
- *shared_file = file;
- }
-
- SVN_ERR(svn_fs_x__read_rep_header(&rh, rs->file->stream, pool));
- SVN_ERR(svn_fs_x__get_file_offset(&rs->start, rs->file->file, pool));
+ SVN_ERR(svn_fs_x__read_rep_header(&rh, rs->sfile->rfile->stream, pool));
+ SVN_ERR(get_file_offset(&rs->start, rs, pool));
+ /* populate the cache if appropriate */
if (SVN_IS_VALID_REVNUM(revision))
{
- SVN_ERR(block_read(NULL, fs, &rs->rep_id, rs->file->file, pool, pool));
+ SVN_ERR(block_read(NULL, fs, &rs->rep_id, rs->sfile->rfile, pool,
+ pool));
if (ffd->rep_header_cache)
SVN_ERR(svn_cache__set(ffd->rep_header_cache, &key, rh, pool));
}
}
+ /* finalize */
SVN_ERR(dgb__log_access(fs, &rs->rep_id, rh, SVN_FS_X__ITEM_TYPE_ANY_REP,
pool));
@@ -675,8 +744,9 @@ create_rep_state_body(rep_state_t **rep_
*rep_state = rs;
*rep_header = rh;
- /* We are dealing with a delta, find out what version. */
rs->chunk_index = 0;
+
+ /* skip "SVNx" diff marker */
rs->current = 4;
return SVN_NO_ERROR;
@@ -735,11 +805,16 @@ svn_fs_x__check_rep(representation_t *re
svn_fs_x__p2l_entry_t *entry;
svn_revnum_t revision = svn_fs_x__get_revnum(rep->id.change_set);
+ svn_fs_x__revision_file_t *rev_file;
+ SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, revision, pool));
+
/* Does REP->ID refer to an actual item? Which one is it? */
- SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, &rep->id, pool));
+ SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, rev_file, &rep->id,
+ pool));
/* What is the type of that item? */
- SVN_ERR(svn_fs_x__p2l_entry_lookup(&entry, fs, revision, offset, pool));
+ SVN_ERR(svn_fs_x__p2l_entry_lookup(&entry, fs, rev_file, revision, offset,
+ pool));
/* Verify that we've got an item that is actually a representation. */
if ( entry == NULL
@@ -1240,63 +1315,6 @@ rep_read_get_baton(struct rep_read_baton
return SVN_NO_ERROR;
}
-/* Open FILE->FILE and FILE->STREAM if they haven't been opened, yet. */
-static svn_error_t*
-auto_open_shared_file(shared_file_t *file)
-{
- if (file->file == NULL)
- {
- SVN_ERR(svn_fs_x__open_pack_or_rev_file(&file->file, file->fs,
- file->revision, file->pool));
- file->stream = svn_stream_from_aprfile2(file->file, TRUE, file->pool);
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Set RS->START to the begin of the representation raw in RS->FILE->FILE,
- if that hasn't been done yet. Use POOL for temporary allocations. */
-static svn_error_t*
-auto_set_start_offset(rep_state_t *rs, apr_pool_t *pool)
-{
- if (rs->start == -1)
- {
- SVN_ERR(svn_fs_x__item_offset(&rs->start, &rs->sub_item,
- rs->file->fs, &rs->rep_id, pool));
- rs->start += rs->header_size;
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Set RS->VER depending on what is found in the already open RS->FILE->FILE
- if the diff version is still unknown. Use POOL for temporary allocations.
- */
-static svn_error_t*
-auto_read_diff_version(rep_state_t *rs, apr_pool_t *pool)
-{
- if (rs->ver == -1)
- {
- char buf[4];
- SVN_ERR(aligned_seek(rs->file->fs, rs->file->file, NULL, rs->start,
- pool));
- SVN_ERR(svn_io_file_read_full2(rs->file->file, buf, sizeof(buf),
- NULL, NULL, pool));
-
- /* ### Layering violation */
- if (! ((buf[0] == 'S') && (buf[1] == 'V') && (buf[2] == 'N')))
- return svn_error_create
- (SVN_ERR_FS_CORRUPT, NULL,
- _("Malformed svndiff data in representation"));
- rs->ver = buf[3];
-
- rs->chunk_index = 0;
- rs->current = 4;
- }
-
- return SVN_NO_ERROR;
-}
-
/* Skip forwards to THIS_CHUNK in REP_STATE and then read the next delta
window into *NWIN. */
static svn_error_t *
@@ -1310,7 +1328,7 @@ read_delta_window(svn_txdelta_window_t *
SVN_ERR_ASSERT(rs->chunk_index <= this_chunk);
- SVN_ERR(dgb__log_access(rs->file->fs, &rs->rep_id, NULL,
+ SVN_ERR(dgb__log_access(rs->sfile->fs, &rs->rep_id, NULL,
SVN_FS_X__ITEM_TYPE_ANY_REP, pool));
/* Read the next window. But first, try to find it in the cache. */
@@ -1319,7 +1337,7 @@ read_delta_window(svn_txdelta_window_t *
return SVN_NO_ERROR;
/* someone has to actually read the data from file. Open it */
- SVN_ERR(auto_open_shared_file(rs->file));
+ SVN_ERR(auto_open_shared_file(rs->sfile));
/* invoke the 'block-read' feature for non-txn data.
However, don't do that if we are in the middle of some representation,
@@ -1328,8 +1346,8 @@ read_delta_window(svn_txdelta_window_t *
&& svn_fs_x__is_revision(rs->rep_id.change_set)
&& rs->window_cache)
{
- SVN_ERR(block_read(NULL, rs->file->fs, &rs->rep_id, rs->file->file,
- pool, pool));
+ SVN_ERR(block_read(NULL, rs->sfile->fs, &rs->rep_id,
+ rs->sfile->rfile, pool, pool));
/* reading the whole block probably also provided us with the
desired txdelta window */
@@ -1346,19 +1364,19 @@ read_delta_window(svn_txdelta_window_t *
/* RS->FILE may be shared between RS instances -> make sure we point
* to the right data. */
start_offset = rs->start + rs->current;
- SVN_ERR(aligned_seek(rs->file->fs, rs->file->file, NULL, start_offset,
- pool));
+ SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, pool));
/* Skip windows to reach the current chunk if we aren't there yet. */
iterpool = svn_pool_create(pool);
while (rs->chunk_index < this_chunk)
{
+ apr_file_t *file = rs->sfile->rfile->file;
svn_pool_clear(iterpool);
- SVN_ERR(svn_txdelta_skip_svndiff_window(rs->file->file, rs->ver,
- iterpool));
+
+ SVN_ERR(svn_txdelta_skip_svndiff_window(file, rs->ver, pool));
rs->chunk_index++;
- SVN_ERR(svn_fs_x__get_file_offset(&start_offset, rs->file->file,
- iterpool));
+ SVN_ERR(svn_fs_x__get_file_offset(&start_offset, file, iterpool));
+
rs->current = start_offset - rs->start;
if (rs->current >= rs->size)
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -1369,9 +1387,9 @@ read_delta_window(svn_txdelta_window_t *
svn_pool_destroy(iterpool);
/* Actually read the next window. */
- SVN_ERR(svn_txdelta_read_svndiff_window(nwin, rs->file->stream, rs->ver,
- pool));
- SVN_ERR(svn_fs_x__get_file_offset(&end_offset, rs->file->file, pool));
+ SVN_ERR(svn_txdelta_read_svndiff_window(nwin, rs->sfile->rfile->stream,
+ rs->ver, pool));
+ SVN_ERR(get_file_offset(&end_offset, rs, pool));
rs->current = end_offset - rs->start;
if (rs->current > rs->size)
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -1394,7 +1412,7 @@ read_container_window(svn_stringbuf_t **
apr_pool_t *pool)
{
svn_fs_x__rep_extractor_t *extractor = NULL;
- svn_fs_t *fs = rs->file->fs;
+ svn_fs_t *fs = rs->sfile->fs;
fs_x_data_t *ffd = fs->fsap_data;
pair_cache_key_t key;
svn_revnum_t revision = svn_fs_x__get_revnum(rs->rep_id.change_set);
@@ -1420,9 +1438,9 @@ read_container_window(svn_stringbuf_t **
/* read from disk, if necessary */
if (extractor == NULL)
{
- SVN_ERR(auto_open_shared_file(rs->file));
+ SVN_ERR(auto_open_shared_file(rs->sfile));
SVN_ERR(block_read((void **)&extractor, fs, &rs->rep_id,
- rs->file->file, pool, pool));
+ rs->sfile->rfile, pool, pool));
}
SVN_ERR(svn_fs_x__extractor_drive(nwin, extractor, rs->current, size,
@@ -1549,8 +1567,7 @@ static svn_error_t *
init_rep_state(rep_state_t *rs,
svn_fs_x__rep_header_t *rep_header,
svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
apr_pool_t *pool)
{
@@ -1562,13 +1579,12 @@ init_rep_state(rep_state_t *rs,
&& entry->type <= SVN_FS_X__ITEM_TYPE_DIR_PROPS);
SVN_ERR_ASSERT(entry->item_count == 1);
- shared_file->file = file;
- shared_file->stream = stream;
+ shared_file->rfile = rev_file;
shared_file->fs = fs;
shared_file->revision = svn_fs_x__get_revnum(entry->items[0].change_set);
shared_file->pool = pool;
- rs->file = shared_file;
+ rs->sfile = shared_file;
rs->rep_id = entry->items[0];
rs->header_size = rep_header->header_size;
rs->start = entry->offset + rs->header_size;
@@ -1627,16 +1643,17 @@ cache_windows(svn_filesize_t *fulltext_l
apr_off_t block_start;
/* navigate to & read the current window */
- SVN_ERR(aligned_seek(fs, rs->file->file, &block_start,
- start_offset, pool));
- SVN_ERR(svn_txdelta_read_svndiff_window(&window, rs->file->stream,
+ SVN_ERR(rs_aligned_seek(rs, &block_start, start_offset, pool));
+ SVN_ERR(svn_txdelta_read_svndiff_window(&window,
+ rs->sfile->rfile->stream,
rs->ver, pool));
/* aggregate expanded window size */
*fulltext_len += window->tview_len;
/* determine on-disk window size */
- SVN_ERR(svn_fs_x__get_file_offset(&end_offset, rs->file->file,
+ SVN_ERR(svn_fs_x__get_file_offset(&end_offset,
+ rs->sfile->rfile->file,
pool));
rs->current = end_offset - rs->start;
if (rs->current > rs->size)
@@ -1693,8 +1710,7 @@ svn_error_t *
svn_fs_x__get_representation_length(svn_filesize_t *packed_len,
svn_filesize_t *expanded_len,
svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
apr_pool_t *pool)
{
@@ -1711,12 +1727,12 @@ svn_fs_x__get_representation_length(svn_
key.revision = svn_fs_x__get_revnum(entry->items[0].change_set);
key.is_packed = svn_fs_x__is_packed_rev(fs, key.revision);
key.item_index = entry->items[0].number;
- SVN_ERR(read_rep_header(&rep_header, fs, stream, &key, pool));
+ SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &key, pool));
/* prepare representation reader state (rs) structure */
- SVN_ERR(init_rep_state(&rs, rep_header, fs, file, stream, entry, pool));
+ SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry, pool));
- /* RS->FILE may be shared between RS instances -> make sure we point
+ /* RS->SFILE may be shared between RS instances -> make sure we point
* to the right data. */
*packed_len = rs.size;
SVN_ERR(cache_windows(expanded_len, fs, &rs, -1, pool));
@@ -2307,10 +2323,10 @@ svn_fs_x__get_file_delta_stream(svn_txde
}
/* Don't keep file handles open for longer than necessary. */
- if (rep_state->file->file)
+ if (rep_state->sfile->rfile)
{
- SVN_ERR(svn_io_file_close(rep_state->file->file, pool));
- rep_state->file->file = NULL;
+ SVN_ERR(svn_fs_x__close_revision_file(rep_state->sfile->rfile));
+ rep_state->sfile->rfile = NULL;
}
}
@@ -2723,7 +2739,7 @@ svn_fs_x__get_changes(apr_array_header_t
svn_revnum_t rev,
apr_pool_t *result_pool)
{
- apr_file_t *revision_file;
+ svn_fs_x__revision_file_t *revision_file;
svn_boolean_t found;
fs_x_data_t *ffd = fs->fsap_data;
apr_pool_t *scratch_pool = svn_pool_create(result_pool);
@@ -2732,6 +2748,12 @@ svn_fs_x__get_changes(apr_array_header_t
id.change_set = svn_fs_x__change_set_by_rev(rev);
id.number = SVN_FS_X__ITEM_INDEX_CHANGES;
+ /* Provide revision file. */
+
+ SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool));
+ SVN_ERR(svn_fs_x__open_pack_or_rev_file(&revision_file, fs, rev,
+ scratch_pool));
+
/* try cache lookup first */
if (ffd->changes_container_cache && svn_fs_x__is_packed_rev(fs, rev))
@@ -2740,8 +2762,8 @@ svn_fs_x__get_changes(apr_array_header_t
apr_uint32_t sub_item;
pair_cache_key_t key;
- SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, &id,
- scratch_pool));
+ SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, revision_file,
+ &id, scratch_pool));
key.revision = svn_fs_x__packed_base_rev(fs, rev);
key.second = offset;
@@ -2762,17 +2784,11 @@ svn_fs_x__get_changes(apr_array_header_t
if (!found)
{
- /* read changes from revision file */
-
- SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool));
- SVN_ERR(svn_fs_x__open_pack_or_rev_file(&revision_file, fs, rev,
- scratch_pool));
-
/* 'block-read' will also provide us with the desired data */
SVN_ERR(block_read((void **)changes, fs, &id, revision_file,
result_pool, scratch_pool));
- SVN_ERR(svn_io_file_close(revision_file, scratch_pool));
+ SVN_ERR(svn_fs_x__close_revision_file(revision_file));
}
SVN_ERR(dgb__log_access(fs, &id, *changes, SVN_FS_X__ITEM_TYPE_CHANGES,
@@ -2790,8 +2806,7 @@ svn_fs_x__get_changes(apr_array_header_t
*/
static svn_error_t *
block_read_contents(svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
pair_cache_key_t *key,
apr_off_t max_offset,
@@ -2810,10 +2825,9 @@ block_read_contents(svn_fs_t *fs,
header_key.is_packed = svn_fs_x__is_packed_rev(fs, header_key.revision);
header_key.item_index = key->second;
- SVN_ERR(read_rep_header(&rep_header, fs, stream, &header_key,
+ SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key,
scratch_pool));
- SVN_ERR(init_rep_state(&rs, rep_header, fs, file, stream, entry,
- scratch_pool));
+ SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry, scratch_pool));
SVN_ERR(cache_windows(&fulltext_len, fs, &rs, max_offset, scratch_pool));
return SVN_NO_ERROR;
@@ -2822,8 +2836,7 @@ block_read_contents(svn_fs_t *fs,
static svn_error_t *
auto_select_stream(svn_stream_t **stream,
svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *file_stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
apr_pool_t *pool)
{
@@ -2834,13 +2847,13 @@ auto_select_stream(svn_stream_t **stream
svn_stringbuf_t *text = svn_stringbuf_create_ensure(entry->size, pool);
text->len = entry->size;
text->data[text->len] = 0;
- SVN_ERR(svn_io_file_read_full2(file, text->data, text->len, NULL,
- NULL, pool));
+ SVN_ERR(svn_io_file_read_full2(rev_file->file, text->data, text->len,
+ NULL, NULL, pool));
*stream = svn_stream_from_stringbuf(text, pool);
}
else
{
- *stream = file_stream;
+ *stream = rev_file->stream;
}
return SVN_NO_ERROR;
@@ -2855,8 +2868,7 @@ auto_select_stream(svn_stream_t **stream
static svn_error_t *
block_read_changes(apr_array_header_t **changes,
svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *file_stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
svn_boolean_t must_read,
apr_pool_t *result_pool,
@@ -2881,8 +2893,7 @@ block_read_changes(apr_array_header_t **
return SVN_NO_ERROR;
}
- SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
- scratch_pool));
+ SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
/* read changes from revision file */
@@ -2900,8 +2911,7 @@ block_read_changes(apr_array_header_t **
static svn_error_t *
block_read_changes_container(apr_array_header_t **changes,
svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *file_stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
apr_uint32_t sub_item,
svn_boolean_t must_read,
@@ -2927,8 +2937,7 @@ block_read_changes_container(apr_array_h
return SVN_NO_ERROR;
}
- SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
- scratch_pool));
+ SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
/* read changes from revision file */
@@ -2951,8 +2960,7 @@ block_read_changes_container(apr_array_h
static svn_error_t *
block_read_noderev(node_revision_t **noderev_p,
svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *file_stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
pair_cache_key_t *key,
svn_boolean_t must_read,
@@ -2977,8 +2985,7 @@ block_read_noderev(node_revision_t **nod
return SVN_NO_ERROR;
}
- SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
- scratch_pool));
+ SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
/* read node rev from revision file */
@@ -2997,8 +3004,7 @@ block_read_noderev(node_revision_t **nod
static svn_error_t *
block_read_noderevs_container(node_revision_t **noderev_p,
svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *file_stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
apr_uint32_t sub_item,
svn_boolean_t must_read,
@@ -3024,8 +3030,7 @@ block_read_noderevs_container(node_revis
return SVN_NO_ERROR;
}
- SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
- scratch_pool));
+ SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
/* read noderevs from revision file */
@@ -3048,8 +3053,7 @@ block_read_noderevs_container(node_revis
static svn_error_t *
block_read_reps_container(svn_fs_x__rep_extractor_t **extractor,
svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *file_stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
apr_uint32_t sub_item,
svn_boolean_t must_read,
@@ -3075,8 +3079,7 @@ block_read_reps_container(svn_fs_x__rep_
return SVN_NO_ERROR;
}
- SVN_ERR(auto_select_stream(&stream, fs, file, file_stream, entry,
- scratch_pool));
+ SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, scratch_pool));
/* read noderevs from revision file */
@@ -3100,7 +3103,7 @@ static svn_error_t *
block_read(void **result,
svn_fs_t *fs,
const svn_fs_x__id_part_t *id,
- apr_file_t *revision_file,
+ svn_fs_x__revision_file_t *revision_file,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -3113,23 +3116,23 @@ block_read(void **result,
int run_count = 0;
int i;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- svn_stream_t *stream = svn_stream_from_aprfile2(revision_file, TRUE,
- scratch_pool);
/* don't try this on transaction protorev files */
SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
/* index lookup: find the OFFSET of the item we *must* read plus (in the
* "do-while" block) the list of items in the same block. */
- SVN_ERR(svn_fs_x__item_offset(&wanted_offset, &wanted_sub_item, fs, id,
- iterpool));
+ SVN_ERR(svn_fs_x__item_offset(&wanted_offset, &wanted_sub_item, fs,
+ revision_file, id, iterpool));
offset = wanted_offset;
do
{
/* fetch list of items in the block surrounding OFFSET */
- SVN_ERR(aligned_seek(fs, revision_file, &block_start, offset, iterpool));
- SVN_ERR(svn_fs_x__p2l_index_lookup(&entries, fs, revision, block_start,
+ SVN_ERR(aligned_seek(fs, revision_file->file, &block_start, offset,
+ iterpool));
+ SVN_ERR(svn_fs_x__p2l_index_lookup(&entries, fs, revision_file,
+ revision, block_start,
ffd->block_size, scratch_pool));
/* read all items from the block */
@@ -3166,7 +3169,7 @@ block_read(void **result,
key.revision = svn_fs_x__get_revnum(entry->items[0].change_set);
key.second = entry->items[0].number;
- SVN_ERR(svn_io_file_seek(revision_file, APR_SET,
+ SVN_ERR(svn_io_file_seek(revision_file->file, SEEK_SET,
&entry->offset, iterpool));
switch (entry->type)
{
@@ -3174,7 +3177,7 @@ block_read(void **result,
case SVN_FS_X__ITEM_TYPE_DIR_REP:
case SVN_FS_X__ITEM_TYPE_FILE_PROPS:
case SVN_FS_X__ITEM_TYPE_DIR_PROPS:
- SVN_ERR(block_read_contents(fs, revision_file, stream,
+ SVN_ERR(block_read_contents(fs, revision_file,
entry, &key,
is_wanted
? -1
@@ -3185,14 +3188,14 @@ block_read(void **result,
case SVN_FS_X__ITEM_TYPE_NODEREV:
if (ffd->node_revision_cache || is_result)
SVN_ERR(block_read_noderev((node_revision_t **)&item,
- fs, revision_file, stream,
+ fs, revision_file,
entry, &key, is_result,
pool, iterpool));
break;
case SVN_FS_X__ITEM_TYPE_CHANGES:
SVN_ERR(block_read_changes((apr_array_header_t **)&item,
- fs, revision_file, stream,
+ fs, revision_file,
entry, is_result,
pool, iterpool));
break;
@@ -3200,7 +3203,7 @@ block_read(void **result,
case SVN_FS_X__ITEM_TYPE_CHANGES_CONT:
SVN_ERR(block_read_changes_container
((apr_array_header_t **)&item,
- fs, revision_file, stream,
+ fs, revision_file,
entry, wanted_sub_item,
is_result, pool, iterpool));
break;
@@ -3208,7 +3211,7 @@ block_read(void **result,
case SVN_FS_X__ITEM_TYPE_NODEREVS_CONT:
SVN_ERR(block_read_noderevs_container
((node_revision_t **)&item,
- fs, revision_file, stream,
+ fs, revision_file,
entry, wanted_sub_item,
is_result, pool, iterpool));
break;
@@ -3216,7 +3219,7 @@ block_read(void **result,
case SVN_FS_X__ITEM_TYPE_REPS_CONT:
SVN_ERR(block_read_reps_container
((svn_fs_x__rep_extractor_t **)&item,
- fs, revision_file, stream,
+ fs, revision_file,
entry, wanted_sub_item,
is_result, pool, iterpool));
break;
@@ -3243,7 +3246,6 @@ block_read(void **result,
/* if the caller requested a result, we must have provided one by now */
assert(!result || *result);
- SVN_ERR(svn_stream_close(stream));
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
Modified: subversion/trunk/subversion/libsvn_fs_x/cached_data.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/cached_data.h?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/cached_data.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/cached_data.h Wed Oct 29 22:27:02 2014
@@ -95,8 +95,7 @@ svn_error_t *
svn_fs_x__get_representation_length(svn_filesize_t *packed_len,
svn_filesize_t *expanded_len,
svn_fs_t *fs,
- apr_file_t *file,
- svn_stream_t *stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_x__p2l_entry_t* entry,
apr_pool_t *pool);
Modified: subversion/trunk/subversion/libsvn_fs_x/fs_x.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs_x.c?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs_x.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs_x.c Wed Oct 29 22:27:02 2014
@@ -604,60 +604,6 @@ svn_fs_x__ensure_revision_exists(svn_rev
_("No such revision %ld"), rev);
}
-/* Open the correct revision file for REV. If the filesystem FS has
- been packed, *FILE will be set to the packed file; otherwise, set *FILE
- to the revision file for REV. Return SVN_ERR_FS_NO_SUCH_REVISION if the
- file doesn't exist.
-
- TODO: Consider returning an indication of whether this is a packed rev
- file, so the caller need not rely on is_packed_rev() which in turn
- relies on the cached FFD->min_unpacked_rev value not having changed
- since the rev file was opened.
-
- Use POOL for allocations. */
-svn_error_t *
-svn_fs_x__open_pack_or_rev_file(apr_file_t **file,
- svn_fs_t *fs,
- svn_revnum_t rev,
- apr_pool_t *pool)
-{
- svn_error_t *err;
- svn_boolean_t retry = FALSE;
-
- do
- {
- const char *path = svn_fs_x__path_rev_absolute(fs, rev, pool);
-
- /* open the revision file in buffered r/o mode */
- err = svn_io_file_open(file, path,
- APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
- if (err && APR_STATUS_IS_ENOENT(err->apr_err))
- {
- /* Could not open the file. This may happen if the
- * file once existed but got packed later. */
- svn_error_clear(err);
-
- /* if that was our 2nd attempt, leave it at that. */
- if (retry)
- return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
- _("No such revision %ld"), rev);
-
- /* We failed for the first time. Refresh cache & retry. */
- SVN_ERR(svn_fs_x__update_min_unpacked_rev(fs, pool));
-
- retry = TRUE;
- }
- else
- {
- retry = FALSE;
- }
- }
- while (retry);
-
- return svn_error_trace(err);
-}
-
-
svn_error_t *
svn_fs_x__revision_proplist(apr_hash_t **proplist_p,
svn_fs_t *fs,
Modified: subversion/trunk/subversion/libsvn_fs_x/fs_x.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs_x.h?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs_x.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs_x.h Wed Oct 29 22:27:02 2014
@@ -51,15 +51,6 @@ svn_error_t *svn_fs_x__youngest_rev(svn_
svn_fs_t *fs,
apr_pool_t *pool);
-/* For revision REV in fileysystem FS, open the revision (or packed rev)
- file and seek to the start of the revision. Return it in *FILE, and
- use POOL for allocations. */
-svn_error_t *
-svn_fs_x__open_pack_or_rev_file(apr_file_t **file,
- svn_fs_t *fs,
- svn_revnum_t rev,
- apr_pool_t *pool);
-
/* Return SVN_ERR_FS_NO_SUCH_REVISION if the given revision REV is newer
than the current youngest revision in FS or is simply not a valid
revision number, else return success. */
Modified: subversion/trunk/subversion/libsvn_fs_x/index.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/index.c?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/index.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/index.c Wed Oct 29 22:27:02 2014
@@ -37,6 +37,7 @@
#include "svn_private_config.h"
#include "temp_serializer.h"
+#include "fs_x.h"
#include "../libsvn_fs/fs-loader.h"
@@ -159,7 +160,7 @@ typedef struct value_position_pair_t
/* State of a prefetching packed number stream. It will read compressed
* index data efficiently and present it as a series of non-packed uint64.
*/
-typedef struct packed_number_stream_t
+struct svn_fs_x__packed_number_stream_t
{
/* underlying data file containing the packed values */
apr_file_t *file;
@@ -185,14 +186,14 @@ typedef struct packed_number_stream_t
/* buffer for prefetched values */
value_position_pair_t buffer[MAX_NUMBER_PREFETCH];
-} packed_number_stream_t;
+};
/* Return an svn_error_t * object for error ERR on STREAM with the given
* MESSAGE string. The latter must have a placeholder for the index file
* name ("%s") and the current read offset (e.g. "0x%lx").
*/
static svn_error_t *
-stream_error_create(packed_number_stream_t *stream,
+stream_error_create(svn_fs_x__packed_number_stream_t *stream,
apr_status_t err,
const char *message)
{
@@ -215,7 +216,7 @@ stream_error_create(packed_number_stream
*/
SVN__PREVENT_INLINE
static svn_error_t *
-packed_stream_read(packed_number_stream_t *stream)
+packed_stream_read(svn_fs_x__packed_number_stream_t *stream)
{
unsigned char buffer[MAX_NUMBER_PREFETCH];
apr_size_t read = 0;
@@ -310,18 +311,19 @@ packed_stream_read(packed_number_stream_
* Use POOL for allocations.
*/
static svn_error_t *
-packed_stream_open(packed_number_stream_t **stream,
+packed_stream_open(svn_fs_x__packed_number_stream_t **stream,
const char *file_name,
apr_size_t block_size,
apr_pool_t *pool)
{
- packed_number_stream_t *result = apr_palloc(pool, sizeof(*result));
+ svn_fs_x__packed_number_stream_t *result
+ = apr_palloc(pool, sizeof(*result));
result->pool = svn_pool_create(pool);
SVN_ERR(svn_io_file_open(&result->file, file_name,
APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
result->pool));
-
+
result->used = 0;
result->current = 0;
result->start_offset = 0;
@@ -335,9 +337,8 @@ packed_stream_open(packed_number_stream_
/* Close STREAM which may be NULL.
*/
-SVN__FORCE_INLINE
-static svn_error_t *
-packed_stream_close(packed_number_stream_t *stream)
+svn_error_t *
+svn_fs_x__packed_stream_close(svn_fs_x__packed_number_stream_t *stream)
{
if (stream)
{
@@ -357,7 +358,7 @@ packed_stream_close(packed_number_stream
SVN__FORCE_INLINE
static svn_error_t*
packed_stream_get(apr_uint64_t *value,
- packed_number_stream_t *stream)
+ svn_fs_x__packed_number_stream_t *stream)
{
if (stream->current == stream->used)
SVN_ERR(packed_stream_read(stream));
@@ -372,7 +373,7 @@ packed_stream_get(apr_uint64_t *value,
* whether the given OFFSET is valid.
*/
static void
-packed_stream_seek(packed_number_stream_t *stream,
+packed_stream_seek(svn_fs_x__packed_number_stream_t *stream,
apr_off_t offset)
{
if ( stream->used == 0
@@ -403,7 +404,7 @@ packed_stream_seek(packed_number_stream_
* can be found.
*/
static apr_off_t
-packed_stream_offset(packed_number_stream_t *stream)
+packed_stream_offset(svn_fs_x__packed_number_stream_t *stream)
{
return stream->current == 0
? stream->start_offset
@@ -993,7 +994,7 @@ l2p_header_access_func(void **out,
*/
static svn_error_t *
expand_rle(apr_array_header_t *values,
- packed_number_stream_t *stream,
+ svn_fs_x__packed_number_stream_t *stream,
apr_size_t count)
{
apr_array_clear(values);
@@ -1026,13 +1027,34 @@ expand_rle(apr_array_header_t *values,
return SVN_NO_ERROR;
}
+/* If REV_FILE->L2P_STREAM is NULL, create a new stream for the log-to-phys
+ * index for REVISION in FS and return it in REV_FILE.
+ */
+static svn_error_t *
+auto_open_l2p_index(svn_fs_x__revision_file_t *rev_file,
+ svn_fs_t *fs,
+ svn_revnum_t revision)
+{
+ if (rev_file->l2p_stream == NULL)
+ {
+ fs_x_data_t *ffd = fs->fsap_data;
+ SVN_ERR(packed_stream_open(&rev_file->l2p_stream,
+ svn_fs_x__path_l2p_index(fs, revision,
+ rev_file->pool),
+ ffd->block_size,
+ rev_file->pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Read the header data structure of the log-to-phys index for REVISION
- * in FS and return it in *HEADER. To maximize efficiency, use or return
- * the data stream in *STREAM. Use POOL for allocations.
+ * in FS and return it in *HEADER. Read data from REV_FILE.
+ * Use POOL for allocations.
*/
static svn_error_t *
get_l2p_header_body(l2p_header_t **header,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
svn_revnum_t revision,
apr_pool_t *pool)
@@ -1051,21 +1073,17 @@ get_l2p_header_body(l2p_header_t **heade
key.revision = base_revision(fs, revision);
key.second = svn_fs_x__is_packed_rev(fs, revision);
- if (*stream == NULL)
- SVN_ERR(packed_stream_open(stream,
- svn_fs_x__path_l2p_index(fs, revision, pool),
- ffd->block_size, pool));
- else
- packed_stream_seek(*stream, 0);
+ SVN_ERR(auto_open_l2p_index(rev_file, fs, revision));
+ packed_stream_seek(rev_file->l2p_stream, 0);
/* read the table sizes */
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
result->first_revision = (svn_revnum_t)value;
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
result->revision_count = (int)value;
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
result->page_size = (apr_uint32_t)value;
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
page_count = (apr_size_t)value;
if (result->first_revision > revision
@@ -1085,7 +1103,8 @@ get_l2p_header_body(l2p_header_t **heade
/* read per-revision page table sizes (i.e. number of pages per rev) */
page_table_index = 0;
result->page_table_index[0] = page_table_index;
- SVN_ERR(expand_rle(expanded_values, *stream, result->revision_count));
+ SVN_ERR(expand_rle(expanded_values, rev_file->l2p_stream,
+ result->revision_count));
for (i = 0; i < result->revision_count; ++i)
{
page_table_index
@@ -1096,14 +1115,14 @@ get_l2p_header_body(l2p_header_t **heade
/* read actual page tables */
for (page = 0; page < page_count; ++page)
{
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
result->page_table[page].size = (apr_uint32_t)value;
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
result->page_table[page].entry_count = (apr_uint32_t)value;
}
/* correct the page description offsets */
- offset = packed_stream_offset(*stream);
+ offset = packed_stream_offset(rev_file->l2p_stream);
for (page = 0; page < page_count; ++page)
{
result->page_table[page].offset = offset;
@@ -1124,7 +1143,7 @@ get_l2p_header_body(l2p_header_t **heade
*/
static svn_error_t *
get_l2p_page_info(l2p_page_info_baton_t *baton,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
apr_pool_t *pool)
{
@@ -1145,7 +1164,7 @@ get_l2p_page_info(l2p_page_info_baton_t
return SVN_NO_ERROR;
/* read from disk, cache and copy the result */
- SVN_ERR(get_l2p_header_body(&result, stream, fs, baton->revision, pool));
+ SVN_ERR(get_l2p_header_body(&result, rev_file, fs, baton->revision, pool));
SVN_ERR(l2p_header_copy(baton, result, result->page_table,
result->page_table_index, pool));
@@ -1158,7 +1177,7 @@ get_l2p_page_info(l2p_page_info_baton_t
*/
static svn_error_t *
get_l2p_header(l2p_header_t **header,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
svn_revnum_t revision,
apr_pool_t *pool)
@@ -1176,7 +1195,7 @@ get_l2p_header(l2p_header_t **header,
return SVN_NO_ERROR;
/* read from disk and cache the result */
- SVN_ERR(get_l2p_header_body(header, stream, fs, revision, pool));
+ SVN_ERR(get_l2p_header_body(header, rev_file, fs, revision, pool));
return SVN_NO_ERROR;
}
@@ -1188,13 +1207,12 @@ get_l2p_header(l2p_header_t **header,
*/
static svn_error_t *
get_l2p_page(l2p_page_t **page,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
svn_revnum_t start_revision,
l2p_page_table_entry_t *table_entry,
apr_pool_t *pool)
{
- fs_x_data_t *ffd = fs->fsap_data;
apr_uint64_t value, last_value = 0;
apr_uint32_t i;
l2p_page_t *result = apr_pcalloc(pool, sizeof(*result));
@@ -1202,14 +1220,8 @@ get_l2p_page(l2p_page_t **page,
apr_off_t *container_offsets;
/* open index file and select page */
- if (*stream == NULL)
- SVN_ERR(packed_stream_open(stream,
- svn_fs_x__path_l2p_index(fs, start_revision,
- pool),
- ffd->block_size,
- pool));
-
- packed_stream_seek(*stream, table_entry->offset);
+ SVN_ERR(auto_open_l2p_index(rev_file, fs, start_revision));
+ packed_stream_seek(rev_file->l2p_stream, table_entry->offset);
/* initialize the page content */
result->entry_count = table_entry->entry_count;
@@ -1220,11 +1232,11 @@ get_l2p_page(l2p_page_t **page,
/* container offsets array */
- SVN_ERR(packed_stream_get(&container_count, *stream));
+ SVN_ERR(packed_stream_get(&container_count, rev_file->l2p_stream));
container_offsets = apr_pcalloc(pool, container_count * sizeof(*result));
for (i = 0; i < container_count; ++i)
{
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
last_value += value;
container_offsets[i] = (apr_off_t)last_value - 1;
/* '-1' is represented as '0' in the index file */
@@ -1233,7 +1245,7 @@ get_l2p_page(l2p_page_t **page,
/* read all page entries (offsets in rev file and container sub-items) */
for (i = 0; i < result->entry_count; ++i)
{
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
if (value == 0)
{
result->offsets[i] = -1;
@@ -1242,7 +1254,7 @@ get_l2p_page(l2p_page_t **page,
else if (value <= container_count)
{
result->offsets[i] = container_offsets[value - 1];
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream));
result->sub_items[i] = (apr_uint32_t)value;
}
else
@@ -1423,7 +1435,7 @@ get_l2p_page_table(apr_array_header_t *p
static svn_error_t *
prefetch_l2p_pages(svn_boolean_t *end,
svn_fs_t *fs,
- packed_number_stream_t *stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t first_revision,
svn_revnum_t revision,
apr_array_header_t *pages,
@@ -1482,7 +1494,7 @@ prefetch_l2p_pages(svn_boolean_t *end,
/* no in cache -> read from stream (data already buffered in APR)
* and cache the result */
l2p_page_t *page = NULL;
- SVN_ERR(get_l2p_page(&page, &stream, fs, first_revision,
+ SVN_ERR(get_l2p_page(&page, rev_file, fs, first_revision,
entry, iterpool));
SVN_ERR(svn_cache__set(ffd->l2p_page_cache, &key, page,
@@ -1503,6 +1515,7 @@ static svn_error_t *
l2p_index_lookup(apr_off_t *offset,
apr_uint32_t *sub_item,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_uint64_t item_index,
apr_pool_t *pool)
@@ -1511,7 +1524,6 @@ l2p_index_lookup(apr_off_t *offset,
l2p_page_info_baton_t info_baton;
l2p_page_baton_t page_baton;
l2p_page_t *page = NULL;
- packed_number_stream_t *stream = NULL;
svn_fs_x__page_cache_key_t key = { 0 };
svn_boolean_t is_cached = FALSE;
void *dummy = NULL;
@@ -1520,7 +1532,7 @@ l2p_index_lookup(apr_off_t *offset,
* access the l2p index page for (REVISION,ITEM_INDEX)*/
info_baton.revision = revision;
info_baton.item_index = item_index;
- SVN_ERR(get_l2p_page_info(&info_baton, &stream, fs, pool));
+ SVN_ERR(get_l2p_page_info(&info_baton, rev_file, fs, pool));
/* try to find the page in the cache and get the OFFSET from it */
page_baton.revision = revision;
@@ -1553,7 +1565,7 @@ l2p_index_lookup(apr_off_t *offset,
apr_off_t min_offset = max_offset - ffd->block_size;
/* read the relevant page */
- SVN_ERR(get_l2p_page(&page, &stream, fs, info_baton.first_revision,
+ SVN_ERR(get_l2p_page(&page, rev_file, fs, info_baton.first_revision,
&info_baton.entry, pool));
/* cache the page and extract the result we need */
@@ -1573,7 +1585,7 @@ l2p_index_lookup(apr_off_t *offset,
: -1;
svn_pool_clear(iterpool);
- SVN_ERR(prefetch_l2p_pages(&end, fs, stream,
+ SVN_ERR(prefetch_l2p_pages(&end, fs, rev_file,
info_baton.first_revision,
prefetch_revision, pages,
excluded_page_no, min_offset,
@@ -1587,7 +1599,7 @@ l2p_index_lookup(apr_off_t *offset,
{
svn_pool_clear(iterpool);
- SVN_ERR(prefetch_l2p_pages(&end, fs, stream,
+ SVN_ERR(prefetch_l2p_pages(&end, fs, rev_file,
info_baton.first_revision,
prefetch_revision, pages, -1,
min_offset, max_offset, iterpool));
@@ -1596,8 +1608,6 @@ l2p_index_lookup(apr_off_t *offset,
svn_pool_destroy(iterpool);
}
- SVN_ERR(packed_stream_close(stream));
-
*offset = page_baton.offset;
*sub_item = page_baton.sub_item;
@@ -1658,13 +1668,14 @@ svn_fs_x__l2p_get_max_ids(apr_array_head
l2p_header_t *header = NULL;
svn_revnum_t revision;
svn_revnum_t last_rev = (svn_revnum_t)(start_rev + count);
- packed_number_stream_t *stream = NULL;
+ svn_fs_x__revision_file_t *rev_file;
apr_pool_t *header_pool = svn_pool_create(pool);
/* read index master data structure for the index covering START_REV */
- SVN_ERR(get_l2p_header(&header, &stream, fs, start_rev, header_pool));
- SVN_ERR(packed_stream_close(stream));
- stream = NULL;
+ SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start_rev,
+ header_pool));
+ SVN_ERR(get_l2p_header(&header, rev_file, fs, start_rev, header_pool));
+ SVN_ERR(svn_fs_x__close_revision_file(rev_file));
/* Determine the length of the item index list for each rev.
* Read new index headers as required. */
@@ -1682,10 +1693,11 @@ svn_fs_x__l2p_get_max_ids(apr_array_head
* the number of items in a revision, i.e. there is no consistency
* issue here. */
svn_pool_clear(header_pool);
- SVN_ERR(get_l2p_header(&header, &stream, fs, revision,
+ SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, revision,
+ header_pool));
+ SVN_ERR(get_l2p_header(&header, rev_file, fs, revision,
header_pool));
- SVN_ERR(packed_stream_close(stream));
- stream = NULL;
+ SVN_ERR(svn_fs_x__close_revision_file(rev_file));
}
/* in a revision with N index pages, the first N-1 index pages are
@@ -2100,19 +2112,36 @@ p2l_page_info_func(void **out,
return SVN_NO_ERROR;
}
+/* If REV_FILE->L2P_STREAM is NULL, create a new stream for the log-to-phys
+ * index for REVISION in FS and return it in REV_FILE.
+ */
+static svn_error_t *
+auto_open_p2l_index(svn_fs_x__revision_file_t *rev_file,
+ svn_fs_t *fs,
+ svn_revnum_t revision)
+{
+ if (rev_file->p2l_stream == NULL)
+ {
+ fs_x_data_t *ffd = fs->fsap_data;
+ SVN_ERR(packed_stream_open(&rev_file->p2l_stream,
+ svn_fs_x__path_p2l_index(fs, revision,
+ rev_file->pool),
+ ffd->block_size,
+ rev_file->pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Read the header data structure of the phys-to-log index for REVISION in
- * FS and return it in *HEADER.
- *
- * To maximize efficiency, use or return the data stream in *STREAM.
- * If *STREAM is yet to be constructed, do so in STREAM_POOL.
- * Use POOL for allocations.
+ * FS and return it in *HEADER, allocated in POOL. Use REV_FILE to access
+ * on-disk data.
*/
static svn_error_t *
get_p2l_header(p2l_header_t **header,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
svn_revnum_t revision,
- apr_pool_t *stream_pool,
apr_pool_t *pool)
{
fs_x_data_t *ffd = fs->fsap_data;
@@ -2134,25 +2163,20 @@ get_p2l_header(p2l_header_t **header,
/* not found -> must read it from disk.
* Open index file or position read pointer to the begin of the file */
- if (*stream == NULL)
- SVN_ERR(packed_stream_open(stream,
- svn_fs_x__path_p2l_index(fs, key.revision,
- pool),
- ffd->block_size, stream_pool));
- else
- packed_stream_seek(*stream, 0);
+ SVN_ERR(auto_open_p2l_index(rev_file, fs, key.revision));
+ packed_stream_seek(rev_file->p2l_stream, 0);
/* allocate result data structure */
result = apr_pcalloc(pool, sizeof(*result));
/* read table sizes and allocate page array */
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
result->first_revision = (svn_revnum_t)value;
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
result->file_size = value;
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
result->page_size = value;
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
result->page_count = (apr_size_t)value;
result->offsets
= apr_pcalloc(pool, (result->page_count + 1) * sizeof(*result->offsets));
@@ -2161,12 +2185,12 @@ get_p2l_header(p2l_header_t **header,
result->offsets[0] = 0;
for (i = 0; i < result->page_count; ++i)
{
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
result->offsets[i+1] = result->offsets[i] + (apr_off_t)value;
}
/* correct the offset values */
- offset = packed_stream_offset(*stream);
+ offset = packed_stream_offset(rev_file->p2l_stream);
for (i = 0; i <= result->page_count; ++i)
result->offsets[i] += offset;
@@ -2181,17 +2205,14 @@ get_p2l_header(p2l_header_t **header,
/* Read the header data structure of the phys-to-log index for revision
* BATON->REVISION in FS. Return in *BATON all info relevant to read the
- * index page for the rev / pack file offset BATON->OFFSET.
- *
- * To maximize efficiency, use or return the data stream in *STREAM.
- * If *STREAM is yet to be constructed, do so in STREAM_POOL.
+ * index page for the rev / pack file offset BATON->OFFSET. Use REV_FILE
+ * to access on-disk data.
* Use POOL for allocations.
*/
static svn_error_t *
get_p2l_page_info(p2l_page_info_baton_t *baton,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
- apr_pool_t *stream_pool,
apr_pool_t *pool)
{
fs_x_data_t *ffd = fs->fsap_data;
@@ -2209,8 +2230,7 @@ get_p2l_page_info(p2l_page_info_baton_t
if (is_cached)
return SVN_NO_ERROR;
- SVN_ERR(get_p2l_header(&header, stream, fs, baton->revision,
- stream_pool, pool));
+ SVN_ERR(get_p2l_header(&header, rev_file, fs, baton->revision, pool));
/* copy the requested info into *BATON */
p2l_page_info_copy(baton, header, header->offsets);
@@ -2223,7 +2243,7 @@ get_p2l_page_info(p2l_page_info_baton_t
* be moved forward by the size of entry. Use POOL for allocations.
*/
static svn_error_t *
-read_entry(packed_number_stream_t *stream,
+read_entry(svn_fs_x__packed_number_stream_t *stream,
apr_off_t *item_offset,
svn_revnum_t revision,
apr_array_header_t *result,
@@ -2285,17 +2305,15 @@ read_entry(packed_number_stream_t *strea
*/
static svn_error_t *
get_p2l_page(apr_array_header_t **entries,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
svn_revnum_t start_revision,
apr_off_t start_offset,
apr_off_t next_offset,
apr_off_t page_start,
apr_uint64_t page_size,
- apr_pool_t *stream_pool,
apr_pool_t *pool)
{
- fs_x_data_t *ffd = fs->fsap_data;
apr_uint64_t value;
apr_array_header_t *result
= apr_array_make(pool, 16, sizeof(svn_fs_x__p2l_entry_t));
@@ -2303,23 +2321,20 @@ get_p2l_page(apr_array_header_t **entrie
apr_off_t offset;
/* open index and navigate to page start */
- if (*stream == NULL)
- SVN_ERR(packed_stream_open(stream,
- svn_fs_x__path_p2l_index(fs, start_revision, pool),
- ffd->block_size, stream_pool));
- packed_stream_seek(*stream, start_offset);
+ SVN_ERR(auto_open_p2l_index(rev_file, fs, start_revision));
+ packed_stream_seek(rev_file->p2l_stream, start_offset);
/* read rev file offset of the first page entry (all page entries will
* only store their sizes). */
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
item_offset = (apr_off_t)value;
/* read all entries of this page */
do
{
- SVN_ERR(read_entry(*stream, &item_offset, start_revision, result,
- pool));
- offset = packed_stream_offset(*stream);
+ SVN_ERR(read_entry(rev_file->p2l_stream, &item_offset, start_revision,
+ result, pool));
+ offset = packed_stream_offset(rev_file->p2l_stream);
}
while (offset < next_offset);
@@ -2327,10 +2342,10 @@ get_p2l_page(apr_array_header_t **entrie
* entry of the next page */
if (item_offset < page_start + page_size)
{
- SVN_ERR(packed_stream_get(&value, *stream));
+ SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream));
item_offset = (apr_off_t)value;
- SVN_ERR(read_entry(*stream, &item_offset, start_revision, result,
- pool));
+ SVN_ERR(read_entry(rev_file->p2l_stream, &item_offset, start_revision,
+ result, pool));
}
*entries = result;
@@ -2353,10 +2368,9 @@ static svn_error_t *
prefetch_p2l_page(svn_boolean_t *end,
int *leaking_bucket,
svn_fs_t *fs,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
p2l_page_info_baton_t *baton,
apr_off_t min_offset,
- apr_pool_t *stream_pool,
apr_pool_t *scratch_pool)
{
fs_x_data_t *ffd = fs->fsap_data;
@@ -2367,7 +2381,7 @@ prefetch_p2l_page(svn_boolean_t *end,
/* fetch the page info */
*end = FALSE;
baton->revision = baton->first_revision;
- SVN_ERR(get_p2l_page_info(baton, stream, fs, stream_pool, scratch_pool));
+ SVN_ERR(get_p2l_page_info(baton, rev_file, fs, scratch_pool));
if (baton->start_offset < min_offset)
{
/* page outside limits -> stop prefetching */
@@ -2396,13 +2410,12 @@ prefetch_p2l_page(svn_boolean_t *end,
++*leaking_bucket;
/* read from disk */
- SVN_ERR(get_p2l_page(&page, stream, fs,
+ SVN_ERR(get_p2l_page(&page, rev_file, fs,
baton->first_revision,
baton->start_offset,
baton->next_offset,
baton->page_start,
baton->page_size,
- stream_pool,
scratch_pool));
/* and put it into our cache */
@@ -2420,7 +2433,7 @@ prefetch_p2l_page(svn_boolean_t *end,
static svn_error_t *
get_p2l_keys(p2l_page_info_baton_t *page_info_p,
svn_fs_x__page_cache_key_t *key_p,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
svn_revnum_t revision,
apr_off_t offset,
@@ -2432,21 +2445,18 @@ get_p2l_keys(p2l_page_info_baton_t *page
* contents at pack / rev file position OFFSET. */
page_info.offset = offset;
page_info.revision = revision;
- SVN_ERR(get_p2l_page_info(&page_info, stream, fs, pool, pool));
+ SVN_ERR(get_p2l_page_info(&page_info, rev_file, fs, pool));
/* if the offset refers to a non-existent page, bail out */
if (page_info.page_count <= page_info.page_no)
- {
- SVN_ERR(packed_stream_close(*stream));
- return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
- _("Offset %s too large in revision %ld"),
- apr_off_t_toa(pool, offset), revision);
- }
+ return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL,
+ _("Offset %s too large in revision %ld"),
+ apr_off_t_toa(pool, offset), revision);
/* return results */
if (page_info_p)
*page_info_p = page_info;
-
+
/* construct cache key */
if (key_p)
{
@@ -2567,7 +2577,7 @@ p2l_entries_func(void **out,
*/
static svn_error_t *
p2l_index_lookup(apr_array_header_t *entries,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
svn_revnum_t revision,
apr_off_t block_start,
@@ -2589,7 +2599,7 @@ p2l_index_lookup(apr_array_header_t *ent
SVN_ERR_ASSERT(block_start < block_end);
/* look for the fist page of the range in our cache */
- SVN_ERR(get_p2l_keys(&page_info, &key, stream, fs, revision, block_start,
+ SVN_ERR(get_p2l_keys(&page_info, &key, rev_file, fs, revision, block_start,
pool));
SVN_ERR(svn_cache__get_partial((void**)&local_result, &is_cached,
ffd->p2l_page_cache, &key, p2l_entries_func,
@@ -2620,19 +2630,18 @@ p2l_index_lookup(apr_array_header_t *ent
while (prefetch_info.offset >= prefetch_info.page_size && !end)
{
prefetch_info.offset -= prefetch_info.page_size;
- SVN_ERR(prefetch_p2l_page(&end, &leaking_bucket, fs, stream,
- &prefetch_info, min_offset,
- pool, iterpool));
+ SVN_ERR(prefetch_p2l_page(&end, &leaking_bucket, fs, rev_file,
+ &prefetch_info, min_offset, iterpool));
svn_pool_clear(iterpool);
}
/* fetch page from disk and put it into the cache */
- SVN_ERR(get_p2l_page(&page_entries, stream, fs,
+ SVN_ERR(get_p2l_page(&page_entries, rev_file, fs,
page_info.first_revision,
page_info.start_offset,
page_info.next_offset,
page_info.page_start,
- page_info.page_size, pool, iterpool));
+ page_info.page_size, iterpool));
SVN_ERR(svn_cache__set(ffd->p2l_page_cache, &key, page_entries,
iterpool));
@@ -2650,9 +2659,8 @@ p2l_index_lookup(apr_array_header_t *ent
&& !end)
{
prefetch_info.offset += prefetch_info.page_size;
- SVN_ERR(prefetch_p2l_page(&end, &leaking_bucket, fs, stream,
- &prefetch_info, min_offset,
- pool, iterpool));
+ SVN_ERR(prefetch_p2l_page(&end, &leaking_bucket, fs, rev_file,
+ &prefetch_info, min_offset, iterpool));
svn_pool_clear(iterpool);
}
@@ -2700,13 +2708,12 @@ p2l_index_lookup(apr_array_header_t *ent
svn_error_t *
svn_fs_x__p2l_index_lookup(apr_array_header_t **entries,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_off_t block_start,
apr_off_t block_size,
apr_pool_t *pool)
{
- packed_number_stream_t *stream = NULL;
-
apr_off_t block_end = block_start + block_size;
/* the receiving container */
@@ -2720,7 +2727,7 @@ svn_fs_x__p2l_index_lookup(apr_array_hea
while (block_start < block_end)
{
svn_fs_x__p2l_entry_t *entry;
- SVN_ERR(p2l_index_lookup(result, &stream, fs, revision, block_start,
+ SVN_ERR(p2l_index_lookup(result, rev_file, fs, revision, block_start,
block_end, pool));
SVN_ERR_ASSERT(result->nelts > 0);
@@ -2742,9 +2749,6 @@ svn_fs_x__p2l_index_lookup(apr_array_hea
last_count = result->nelts;
}
- /* make sure we close files after usage */
- SVN_ERR(packed_stream_close(stream));
-
*entries = result;
return SVN_NO_ERROR;
}
@@ -2819,7 +2823,7 @@ p2l_entry_lookup_func(void **out,
static svn_error_t *
p2l_entry_lookup(svn_fs_x__p2l_entry_t **entry_p,
- packed_number_stream_t **stream,
+ svn_fs_x__revision_file_t *rev_file,
svn_fs_t *fs,
svn_revnum_t revision,
apr_off_t offset,
@@ -2831,7 +2835,8 @@ p2l_entry_lookup(svn_fs_x__p2l_entry_t *
p2l_page_info_baton_t page_info;
/* look for this info in our cache */
- SVN_ERR(get_p2l_keys(&page_info, &key, stream, fs, revision, offset, pool));
+ SVN_ERR(get_p2l_keys(&page_info, &key, rev_file, fs, revision, offset,
+ pool));
SVN_ERR(svn_cache__get_partial((void**)entry_p, &is_cached,
ffd->p2l_page_cache, &key,
p2l_entry_lookup_func, &offset, pool));
@@ -2840,7 +2845,7 @@ p2l_entry_lookup(svn_fs_x__p2l_entry_t *
/* do a standard index lookup. This is will automatically prefetch
* data to speed up future lookups. */
apr_array_header_t *entries = apr_array_make(pool, 1, sizeof(**entry_p));
- SVN_ERR(p2l_index_lookup(entries, stream, fs, revision, offset,
+ SVN_ERR(p2l_index_lookup(entries, rev_file, fs, revision, offset,
offset + 1, pool));
/* Find the entry that we want. */
@@ -2854,17 +2859,18 @@ p2l_entry_lookup(svn_fs_x__p2l_entry_t *
svn_error_t *
svn_fs_x__p2l_entry_lookup(svn_fs_x__p2l_entry_t **entry_p,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_off_t offset,
apr_pool_t *pool)
{
- packed_number_stream_t *stream = NULL;
+ svn_fs_x__packed_number_stream_t *stream = NULL;
/* look for this info in our cache */
- SVN_ERR(p2l_entry_lookup(entry_p, &stream, fs, revision, offset, pool));
+ SVN_ERR(p2l_entry_lookup(entry_p, rev_file, fs, revision, offset, pool));
/* make sure we close files after usage */
- SVN_ERR(packed_stream_close(stream));
+ SVN_ERR(svn_fs_x__packed_stream_close(stream));
return SVN_NO_ERROR;
}
@@ -2911,13 +2917,13 @@ p2l_item_lookup_func(void **out,
svn_error_t *
svn_fs_x__p2l_item_lookup(svn_fs_x__id_part_t **item,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_off_t offset,
apr_uint32_t sub_item,
apr_pool_t *pool)
{
fs_x_data_t *ffd = fs->fsap_data;
- packed_number_stream_t *stream = NULL;
svn_fs_x__page_cache_key_t key = { 0 };
svn_boolean_t is_cached = FALSE;
p2l_page_info_baton_t page_info;
@@ -2926,7 +2932,7 @@ svn_fs_x__p2l_item_lookup(svn_fs_x__id_p
*item = NULL;
/* look for this info in our cache */
- SVN_ERR(get_p2l_keys(&page_info, &key, &stream, fs, revision, offset,
+ SVN_ERR(get_p2l_keys(&page_info, &key, rev_file, fs, revision, offset,
pool));
baton.offset = offset;
baton.sub_item = sub_item;
@@ -2938,16 +2944,13 @@ svn_fs_x__p2l_item_lookup(svn_fs_x__id_p
/* do a standard index lookup. This is will automatically prefetch
* data to speed up future lookups. */
svn_fs_x__p2l_entry_t *entry;
- SVN_ERR(p2l_entry_lookup(&entry, &stream, fs, revision, offset, pool));
+ SVN_ERR(p2l_entry_lookup(&entry, rev_file, fs, revision, offset, pool));
/* return result */
if (entry && entry->item_count > sub_item)
*item = apr_pmemdup(pool, entry->items + sub_item, sizeof(**item));
}
- /* make sure we close files after usage */
- SVN_ERR(packed_stream_close(stream));
-
return SVN_NO_ERROR;
}
@@ -2971,11 +2974,11 @@ p2l_get_max_offset_func(void **out,
svn_error_t *
svn_fs_x__p2l_get_max_offset(apr_off_t *offset,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_pool_t *pool)
{
fs_x_data_t *ffd = fs->fsap_data;
- packed_number_stream_t *stream = NULL;
p2l_header_t *header;
svn_boolean_t is_cached = FALSE;
apr_off_t *offset_p;
@@ -2994,12 +2997,9 @@ svn_fs_x__p2l_get_max_offset(apr_off_t *
return SVN_NO_ERROR;
}
- SVN_ERR(get_p2l_header(&header, &stream, fs, revision, pool, pool));
+ SVN_ERR(get_p2l_header(&header, rev_file, fs, revision, pool));
*offset = header->file_size;
- /* make sure we close files after usage */
- SVN_ERR(packed_stream_close(stream));
-
return SVN_NO_ERROR;
}
@@ -3007,6 +3007,7 @@ svn_error_t *
svn_fs_x__item_offset(apr_off_t *offset,
apr_uint32_t *sub_item,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
const svn_fs_x__id_part_t *item_id,
apr_pool_t *pool)
{
@@ -3015,7 +3016,7 @@ svn_fs_x__item_offset(apr_off_t *offset,
svn_fs_x__get_txn_id(item_id->change_set),
item_id->number, pool));
else
- SVN_ERR(l2p_index_lookup(offset, sub_item, fs,
+ SVN_ERR(l2p_index_lookup(offset, sub_item, fs, rev_file,
svn_fs_x__get_revnum(item_id->change_set),
item_id->number, pool));
Modified: subversion/trunk/subversion/libsvn_fs_x/index.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/index.h?rev=1635317&r1=1635316&r2=1635317&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/index.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/index.h Wed Oct 29 22:27:02 2014
@@ -24,6 +24,7 @@
#define SVN_LIBSVN_FS__INDEX_H
#include "fs.h"
+#include "rev_file.h"
/* Per-defined item index values. They are used to identify empty or
* mandatory items.
@@ -85,6 +86,10 @@ svn_fs_x__p2l_entry_t *
svn_fs_x__p2l_entry_dup(const svn_fs_x__p2l_entry_t *entry,
apr_pool_t *pool);
+/* Close the index file STREAM and underlying file handle. */
+svn_error_t *
+svn_fs_x__packed_stream_close(svn_fs_x__packed_number_stream_t *stream);
+
/* Open / create a log-to-phys index file with the full file path name
* FILE_NAME. Return the open file in *PROTO_INDEX and use POOL for
* allocations.
@@ -182,6 +187,7 @@ svn_fs_x__p2l_index_create(svn_fs_t *fs,
svn_error_t *
svn_fs_x__p2l_index_lookup(apr_array_header_t **entries,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_off_t block_start,
apr_off_t block_size,
@@ -195,6 +201,7 @@ svn_fs_x__p2l_index_lookup(apr_array_hea
svn_error_t *
svn_fs_x__p2l_entry_lookup(svn_fs_x__p2l_entry_t **entry,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_off_t offset,
apr_pool_t *pool);
@@ -208,6 +215,7 @@ svn_fs_x__p2l_entry_lookup(svn_fs_x__p2l
svn_error_t *
svn_fs_x__p2l_item_lookup(svn_fs_x__id_part_t **item,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_off_t offset,
apr_uint32_t sub_item,
@@ -221,6 +229,7 @@ svn_error_t *
svn_fs_x__item_offset(apr_off_t *offset,
apr_uint32_t *sub_item,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
const svn_fs_x__id_part_t *item_id,
apr_pool_t *pool);
@@ -243,6 +252,7 @@ svn_fs_x__l2p_get_max_ids(apr_array_head
svn_error_t *
svn_fs_x__p2l_get_max_offset(apr_off_t *offset,
svn_fs_t *fs,
+ svn_fs_x__revision_file_t *rev_file,
svn_revnum_t revision,
apr_pool_t *pool);