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/06/24 23:30:01 UTC
svn commit: r1605201 [2/5] - in /subversion/branches/svn-auth-x509: ./
build/generator/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subve...
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.c Tue Jun 24 21:29:59 2014
@@ -88,12 +88,13 @@ dbg_log_access(svn_fs_t *fs,
const char *type = types[item_type];
const char *pack = "";
apr_off_t offset;
- svn_fs_fs__revision_file_t rev_file;
+ svn_fs_fs__revision_file_t *rev_file;
- svn_fs_fs__init_revision_file(&rev_file, fs, revision, scratch_pool);
+ SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, revision,
+ scratch_pool));
/* determine rev / pack file offset */
- SVN_ERR(svn_fs_fs__item_offset(&offset, fs, &rev_file, revision, NULL,
+ SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rev_file, revision, NULL,
item_index, scratch_pool));
/* constructing the pack file description */
@@ -156,7 +157,7 @@ dbg_log_access(svn_fs_t *fs,
if (svn_fs_fs__use_log_addressing(fs, revision))
{
/* reverse index lookup: get item description in ENTRY */
- SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, &rev_file, revision,
+ SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file, revision,
offset, scratch_pool));
if (entry)
{
@@ -284,7 +285,8 @@ static svn_error_t *
get_node_revision_body(node_revision_t **noderev_p,
svn_fs_t *fs,
const svn_fs_id_t *id,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_error_t *err;
svn_boolean_t is_cached = FALSE;
@@ -297,8 +299,10 @@ get_node_revision_body(node_revision_t *
/* This is a transaction node-rev. Its storage logic is very
different from that of rev / pack files. */
err = svn_io_file_open(&file,
- svn_fs_fs__path_txn_node_rev(fs, id, pool),
- APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool);
+ svn_fs_fs__path_txn_node_rev(fs, id,
+ scratch_pool),
+ APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
+ scratch_pool);
if (err)
{
if (APR_STATUS_IS_ENOENT(err->apr_err))
@@ -313,8 +317,8 @@ get_node_revision_body(node_revision_t *
SVN_ERR(svn_fs_fs__read_noderev(noderev_p,
svn_stream_from_aprfile2(file,
FALSE,
- pool),
- pool));
+ scratch_pool),
+ result_pool, scratch_pool));
}
else
{
@@ -334,7 +338,7 @@ get_node_revision_body(node_revision_t *
&is_cached,
ffd->node_revision_cache,
&key,
- pool));
+ result_pool));
if (is_cached)
return SVN_NO_ERROR;
}
@@ -343,7 +347,7 @@ get_node_revision_body(node_revision_t *
SVN_ERR(open_and_seek_revision(&revision_file, fs,
rev_item->revision,
rev_item->number,
- pool));
+ scratch_pool));
if (svn_fs_fs__use_log_addressing(fs, rev_item->revision))
{
@@ -353,15 +357,16 @@ get_node_revision_body(node_revision_t *
rev_item->revision,
rev_item->number,
revision_file,
- pool,
- pool));
+ result_pool,
+ scratch_pool));
}
else
{
/* physical addressing mode reading, parsing and caching */
SVN_ERR(svn_fs_fs__read_noderev(noderev_p,
revision_file->stream,
- pool));
+ result_pool,
+ scratch_pool));
/* Workaround issue #4031: is-fresh-txn-root in revision files. */
(*noderev_p)->is_fresh_txn_root = FALSE;
@@ -371,7 +376,7 @@ get_node_revision_body(node_revision_t *
SVN_ERR(svn_cache__set(ffd->node_revision_cache,
&key,
*noderev_p,
- pool));
+ scratch_pool));
}
SVN_ERR(svn_fs_fs__close_revision_file(revision_file));
@@ -384,14 +389,16 @@ svn_error_t *
svn_fs_fs__get_node_revision(node_revision_t **noderev_p,
svn_fs_t *fs,
const svn_fs_id_t *id,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
const svn_fs_fs__id_part_t *rev_item = svn_fs_fs__id_rev_item(id);
- svn_error_t *err = get_node_revision_body(noderev_p, fs, id, pool);
+ svn_error_t *err = get_node_revision_body(noderev_p, fs, id,
+ result_pool, scratch_pool);
if (err && err->apr_err == SVN_ERR_FS_CORRUPT)
{
- svn_string_t *id_string = svn_fs_fs__id_unparse(id, pool);
+ svn_string_t *id_string = svn_fs_fs__id_unparse(id, scratch_pool);
return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
"Corrupt node-revision '%s'",
id_string->data);
@@ -402,7 +409,7 @@ svn_fs_fs__get_node_revision(node_revisi
rev_item->number,
*noderev_p,
SVN_FS_FS__ITEM_TYPE_NODEREV,
- pool));
+ scratch_pool));
return svn_error_trace(err);
}
@@ -424,7 +431,7 @@ get_fs_id_at_offset(svn_fs_id_t **id_p,
SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, pool));
SVN_ERR(svn_fs_fs__read_noderev(&noderev,
rev_file->stream,
- pool));
+ pool, pool));
/* noderev->id is const, get rid of that */
*id_p = svn_fs_fs__id_copy(noderev->id, pool);
@@ -537,14 +544,15 @@ svn_error_t *
svn_fs_fs__rev_get_root(svn_fs_id_t **root_id_p,
svn_fs_t *fs,
svn_revnum_t rev,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
- SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, pool));
+ SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, scratch_pool));
if (svn_fs_fs__use_log_addressing(fs, rev))
{
- *root_id_p = svn_fs_fs__id_create_root(rev, pool);
+ *root_id_p = svn_fs_fs__id_create_root(rev, result_pool);
}
else
{
@@ -554,20 +562,23 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
svn_boolean_t is_cached;
SVN_ERR(svn_cache__get((void **) root_id_p, &is_cached,
- ffd->rev_root_id_cache, &rev, pool));
+ ffd->rev_root_id_cache, &rev, result_pool));
if (is_cached)
return SVN_NO_ERROR;
- SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev, pool));
+ SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev,
+ scratch_pool));
SVN_ERR(get_root_changes_offset(&root_offset, NULL,
- revision_file->file, fs, rev, pool));
+ revision_file->file, fs, rev,
+ scratch_pool));
SVN_ERR(get_fs_id_at_offset(&root_id, revision_file, fs, rev,
- root_offset, pool));
+ root_offset, result_pool));
SVN_ERR(svn_fs_fs__close_revision_file(revision_file));
- SVN_ERR(svn_cache__set(ffd->rev_root_id_cache, &rev, root_id, pool));
+ SVN_ERR(svn_cache__set(ffd->rev_root_id_cache, &rev, root_id,
+ scratch_pool));
*root_id_p = root_id;
}
@@ -711,10 +722,11 @@ create_rep_state_body(rep_state_t **rep_
shared_file_t **shared_file,
representation_t *rep,
svn_fs_t *fs,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
- rep_state_t *rs = apr_pcalloc(pool, sizeof(*rs));
+ rep_state_t *rs = apr_pcalloc(result_pool, sizeof(*rs));
svn_fs_fs__rep_header_t *rh;
svn_boolean_t is_cached = FALSE;
apr_uint64_t estimated_window_storage;
@@ -771,7 +783,7 @@ create_rep_state_body(rep_state_t **rep_
/* cache lookup, i.e. skip reading the rep header if possible */
if (ffd->rep_header_cache && !svn_fs_fs__id_txn_used(&rep->txn_id))
SVN_ERR(svn_cache__get((void **) &rh, &is_cached,
- ffd->rep_header_cache, &key, pool));
+ ffd->rep_header_cache, &key, result_pool));
/* initialize the (shared) FILE member in RS */
if (reuse_shared_file)
@@ -780,9 +792,9 @@ create_rep_state_body(rep_state_t **rep_
}
else
{
- shared_file_t *file = apr_pcalloc(pool, sizeof(*file));
+ shared_file_t *file = apr_pcalloc(result_pool, sizeof(*file));
file->revision = rep->revision;
- file->pool = pool;
+ file->pool = result_pool;
file->fs = fs;
rs->sfile = file;
@@ -806,8 +818,8 @@ create_rep_state_body(rep_state_t **rep_
SVN_ERR(auto_open_shared_file(rs->sfile));
SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rs->sfile->rfile,
rep->revision, NULL, rep->item_index,
- pool));
- SVN_ERR(rs_aligned_seek(rs, NULL, offset, pool));
+ scratch_pool));
+ SVN_ERR(rs_aligned_seek(rs, NULL, offset, scratch_pool));
}
else
{
@@ -815,27 +827,29 @@ create_rep_state_body(rep_state_t **rep_
* an in-txn file.
*/
SVN_ERR(open_and_seek_representation(&rs->sfile->rfile, fs, rep,
- pool));
+ result_pool));
}
- SVN_ERR(svn_fs_fs__read_rep_header(&rh, rs->sfile->rfile->stream, pool));
- SVN_ERR(get_file_offset(&rs->start, rs, pool));
+ SVN_ERR(svn_fs_fs__read_rep_header(&rh, rs->sfile->rfile->stream,
+ result_pool, scratch_pool));
+ SVN_ERR(get_file_offset(&rs->start, rs, result_pool));
/* populate the cache if appropriate */
if (! svn_fs_fs__id_txn_used(&rep->txn_id))
{
if (svn_fs_fs__use_log_addressing(fs, rep->revision))
SVN_ERR(block_read(NULL, fs, rep->revision, rep->item_index,
- rs->sfile->rfile, pool, pool));
+ rs->sfile->rfile, result_pool, scratch_pool));
else
if (ffd->rep_header_cache)
- SVN_ERR(svn_cache__set(ffd->rep_header_cache, &key, rh, pool));
+ SVN_ERR(svn_cache__set(ffd->rep_header_cache, &key, rh,
+ scratch_pool));
}
}
/* finalize */
SVN_ERR(dbg_log_access(fs, rep->revision, rep->item_index, rh,
- SVN_FS_FS__ITEM_TYPE_ANY_REP, pool));
+ SVN_FS_FS__ITEM_TYPE_ANY_REP, scratch_pool));
rs->header_size = rh->header_size;
*rep_state = rs;
@@ -868,13 +882,16 @@ create_rep_state(rep_state_t **rep_state
shared_file_t **shared_file,
representation_t *rep,
svn_fs_t *fs,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_error_t *err = create_rep_state_body(rep_state, rep_header,
- shared_file, rep, fs, pool);
+ shared_file, rep, fs,
+ result_pool, scratch_pool);
if (err && err->apr_err == SVN_ERR_FS_CORRUPT)
{
fs_fs_data_t *ffd = fs->fsap_data;
+ const char *rep_str;
/* ### This always returns "-1" for transaction reps, because
### this particular bit of code doesn't know if the rep is
@@ -883,12 +900,14 @@ create_rep_state(rep_state_t **rep_state
### from the protorev file, though, so this is probably OK.
### And anyone going to debug corruption errors is probably
### going to jump straight to this comment anyway! */
+ rep_str = rep
+ ? svn_fs_fs__unparse_representation
+ (rep, ffd->format, TRUE, scratch_pool, scratch_pool)->data
+ : "(null)";
+
return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
"Corrupt representation '%s'",
- rep
- ? svn_fs_fs__unparse_representation
- (rep, ffd->format, TRUE, pool)->data
- : "(null)");
+ rep_str);
}
/* ### Call representation_string() ? */
return svn_error_trace(err);
@@ -898,7 +917,7 @@ svn_error_t *
svn_fs_fs__check_rep(representation_t *rep,
svn_fs_t *fs,
void **hint,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
if (svn_fs_fs__use_log_addressing(fs, rep->revision))
{
@@ -906,32 +925,33 @@ svn_fs_fs__check_rep(representation_t *r
apr_off_t offset;
svn_fs_fs__p2l_entry_t *entry;
- svn_fs_fs__revision_file_t rev_file;
- svn_fs_fs__init_revision_file(&rev_file, fs, rep->revision, pool);
+ svn_fs_fs__revision_file_t *rev_file;
+ SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, rep->revision,
+ scratch_pool));
/* This will auto-retry if there was a background pack. */
- SVN_ERR(svn_fs_fs__item_offset(&offset, fs, &rev_file, rep->revision,
- NULL, rep->item_index, pool));
+ SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rev_file, rep->revision,
+ NULL, rep->item_index, scratch_pool));
/* This may fail if there is a background pack operation (can't auto-
retry because the item offset lookup has to be redone as well). */
- err = svn_fs_fs__p2l_entry_lookup(&entry, fs, &rev_file, rep->revision,
- offset, pool);
+ err = svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file, rep->revision,
+ offset, scratch_pool);
/* Retry if the packing state may have changed, i.e. if we got an
error while opening the index for a non-packed rev file. */
- if (err && !rev_file.is_packed)
+ if (err && !rev_file->is_packed)
{
- SVN_ERR(svn_fs_fs__close_revision_file(&rev_file));
+ SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
/* Be sure to know the latest pack status of REP. */
- SVN_ERR(svn_fs_fs__update_min_unpacked_rev(fs, pool));
+ SVN_ERR(svn_fs_fs__update_min_unpacked_rev(fs, scratch_pool));
if (svn_fs_fs__is_packed_rev(fs, rep->revision))
{
/* REP got actually packed. Retry (can happen at most once). */
svn_error_clear(err);
return svn_error_trace(svn_fs_fs__check_rep(rep, fs, hint,
- pool));
+ scratch_pool));
}
}
@@ -943,12 +963,13 @@ svn_fs_fs__check_rep(representation_t *r
return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, NULL,
_("No representation found at offset %s "
"for item %s in revision %ld"),
- apr_off_t_toa(pool, offset),
- apr_psprintf(pool, "%" APR_UINT64_T_FMT,
+ apr_off_t_toa(scratch_pool, offset),
+ apr_psprintf(scratch_pool,
+ "%" APR_UINT64_T_FMT,
rep->item_index),
rep->revision);
- SVN_ERR(svn_fs_fs__close_revision_file(&rev_file));
+ SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
}
else
{
@@ -957,7 +978,7 @@ svn_fs_fs__check_rep(representation_t *r
/* ### Should this be using read_rep_line() directly? */
SVN_ERR(create_rep_state(&rs, &rep_header, (shared_file_t**)hint,
- rep, fs, pool));
+ rep, fs, scratch_pool, scratch_pool));
}
return SVN_NO_ERROR;
@@ -968,13 +989,14 @@ svn_fs_fs__rep_chain_length(int *chain_l
int *shard_count,
representation_t *rep,
svn_fs_t *fs,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
svn_revnum_t shard_size = ffd->max_files_per_dir
? ffd->max_files_per_dir
: 1;
- apr_pool_t *sub_pool = svn_pool_create(pool);
+ apr_pool_t *sub_pool = svn_pool_create(scratch_pool);
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
svn_boolean_t is_delta = FALSE;
int count = 0;
int shards = 1;
@@ -995,6 +1017,9 @@ svn_fs_fs__rep_chain_length(int *chain_l
do
{
rep_state_t *rep_state;
+
+ svn_pool_clear(iterpool);
+
if (base_rep.revision / shard_size != last_shard)
{
last_shard = base_rep.revision / shard_size;
@@ -1006,7 +1031,8 @@ svn_fs_fs__rep_chain_length(int *chain_l
&file_hint,
&base_rep,
fs,
- sub_pool));
+ sub_pool,
+ iterpool));
base_rep.revision = header->base_revision;
base_rep.item_index = header->base_item_index;
@@ -1026,6 +1052,7 @@ svn_fs_fs__rep_chain_length(int *chain_l
*chain_length = count;
*shard_count = shards;
svn_pool_destroy(sub_pool);
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -1148,8 +1175,8 @@ parse_raw_window(void **out,
* rep state RS from the current FSFS session's cache. This will be a
* no-op and IS_CACHED will be set to FALSE if no cache has been given.
* If a cache is available IS_CACHED will inform the caller about the
- * success of the lookup. Allocations (of the window in particualar) will
- * be made from POOL.
+ * success of the lookup. Allocations of the window in will be made
+ * from RESULT_POOL. Use SCRATCH_POOL for temporary allocations.
*
* If the information could be found, put RS to CHUNK_INDEX.
*/
@@ -1158,7 +1185,8 @@ get_cached_window(svn_txdelta_window_t *
rep_state_t *rs,
int chunk_index,
svn_boolean_t *is_cached,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
if (! rs->window_cache)
{
@@ -1176,7 +1204,7 @@ get_cached_window(svn_txdelta_window_t *
is_cached,
rs->window_cache,
&key,
- pool));
+ result_pool));
/* If we did not find a parsed txdelta window, we might have a raw
version of it in our cache. If so, read, parse and re-cache it. */
@@ -1184,10 +1212,10 @@ get_cached_window(svn_txdelta_window_t *
{
SVN_ERR(svn_cache__get_partial((void **) &cached_window, is_cached,
rs->raw_window_cache, &key,
- parse_raw_window, NULL, pool));
+ parse_raw_window, NULL, result_pool));
if (*is_cached)
SVN_ERR(svn_cache__set(rs->window_cache, &key, cached_window,
- pool));
+ scratch_pool));
}
/* Return cached information. */
@@ -1312,6 +1340,7 @@ build_rep_list(apr_array_header_t **list
svn_fs_fs__rep_header_t *rep_header;
svn_boolean_t is_cached = FALSE;
shared_file_t *shared_file = NULL;
+ apr_pool_t *iterpool = svn_pool_create(pool);
*list = apr_array_make(pool, 1, sizeof(rep_state_t *));
rep = *first_rep;
@@ -1321,7 +1350,8 @@ build_rep_list(apr_array_header_t **list
*expanded_size = first_rep->expanded_size;
/* for the top-level rep, we need the rep_args */
- SVN_ERR(create_rep_state(&rs, &rep_header, &shared_file, &rep, fs, pool));
+ SVN_ERR(create_rep_state(&rs, &rep_header, &shared_file, &rep, fs, pool,
+ iterpool));
/* Unknown size or empty representation?
That implies the this being the first iteration.
@@ -1335,10 +1365,12 @@ build_rep_list(apr_array_header_t **list
while (1)
{
+ svn_pool_clear(iterpool);
+
/* fetch state, if that has not been done already */
if (!rs)
SVN_ERR(create_rep_state(&rs, &rep_header, &shared_file,
- &rep, fs, pool));
+ &rep, fs, pool, iterpool));
/* for txn reps, there won't be a cached combined window */
if (!svn_fs_fs__id_txn_used(&rep.txn_id))
@@ -1352,14 +1384,14 @@ build_rep_list(apr_array_header_t **list
rs->current = 0;
rs->size = (*window_p)->len;
*src_state = rs;
- return SVN_NO_ERROR;
+ break;
}
if (rep_header->type == svn_fs_fs__rep_plain)
{
/* This is a plaintext, so just return the current rep_state. */
*src_state = rs;
- return SVN_NO_ERROR;
+ break;
}
/* Push this rep onto the list. If it's self-compressed, we're done. */
@@ -1367,7 +1399,7 @@ build_rep_list(apr_array_header_t **list
if (rep_header->type == svn_fs_fs__rep_self_delta)
{
*src_state = NULL;
- return SVN_NO_ERROR;
+ break;
}
rep.revision = rep_header->base_revision;
@@ -1377,6 +1409,9 @@ build_rep_list(apr_array_header_t **list
rs = NULL;
}
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
}
@@ -1421,18 +1456,22 @@ rep_read_get_baton(struct rep_read_baton
than THIS_CHUNK + 1 when this function returns. */
static svn_error_t *
read_delta_window(svn_txdelta_window_t **nwin, int this_chunk,
- rep_state_t *rs, apr_pool_t *pool)
+ rep_state_t *rs, apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_boolean_t is_cached;
apr_off_t start_offset;
apr_off_t end_offset;
+ apr_pool_t *iterpool;
+
SVN_ERR_ASSERT(rs->chunk_index <= this_chunk);
SVN_ERR(dbg_log_access(rs->sfile->fs, rs->revision, rs->item_index,
- NULL, SVN_FS_FS__ITEM_TYPE_ANY_REP, pool));
+ NULL, SVN_FS_FS__ITEM_TYPE_ANY_REP, scratch_pool));
/* Read the next window. But first, try to find it in the cache. */
- SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached, pool));
+ SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached,
+ result_pool, scratch_pool));
if (is_cached)
return SVN_NO_ERROR;
@@ -1448,32 +1487,35 @@ read_delta_window(svn_txdelta_window_t *
&& rs->raw_window_cache)
{
SVN_ERR(block_read(NULL, rs->sfile->fs, rs->revision, rs->item_index,
- rs->sfile->rfile, pool, pool));
+ rs->sfile->rfile, result_pool, scratch_pool));
/* reading the whole block probably also provided us with the
desired txdelta window */
- SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached, pool));
+ SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached,
+ result_pool, scratch_pool));
if (is_cached)
return SVN_NO_ERROR;
}
/* data is still not cached -> we need to read it.
Make sure we have all the necessary info. */
- SVN_ERR(auto_set_start_offset(rs, pool));
- SVN_ERR(auto_read_diff_version(rs, pool));
+ SVN_ERR(auto_set_start_offset(rs, scratch_pool));
+ SVN_ERR(auto_read_diff_version(rs, scratch_pool));
/* RS->FILE may be shared between RS instances -> make sure we point
* to the right data. */
start_offset = rs->start + rs->current;
- SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, pool));
+ SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, scratch_pool));
/* Skip windows to reach the current chunk if we aren't there yet. */
+ iterpool = svn_pool_create(scratch_pool);
while (rs->chunk_index < this_chunk)
{
+ svn_pool_clear(iterpool);
SVN_ERR(svn_txdelta_skip_svndiff_window(rs->sfile->rfile->file,
- rs->ver, pool));
+ rs->ver, iterpool));
rs->chunk_index++;
- SVN_ERR(get_file_offset(&start_offset, rs, pool));
+ SVN_ERR(get_file_offset(&start_offset, rs, iterpool));
rs->current = start_offset - rs->start;
if (rs->current >= rs->size)
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -1481,11 +1523,12 @@ read_delta_window(svn_txdelta_window_t *
"beyond the end of the "
"representation"));
}
+ svn_pool_destroy(iterpool);
/* Actually read the next window. */
SVN_ERR(svn_txdelta_read_svndiff_window(nwin, rs->sfile->rfile->stream,
- rs->ver, pool));
- SVN_ERR(get_file_offset(&end_offset, rs, pool));
+ rs->ver, result_pool));
+ SVN_ERR(get_file_offset(&end_offset, rs, scratch_pool));
rs->current = end_offset - rs->start;
if (rs->current > rs->size)
return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -1495,7 +1538,7 @@ read_delta_window(svn_txdelta_window_t *
/* the window has not been cached before, thus cache it now
* (if caching is used for them at all) */
if (SVN_IS_VALID_REVNUM(rs->revision))
- SVN_ERR(set_cached_window(*nwin, rs, pool));
+ SVN_ERR(set_cached_window(*nwin, rs, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1503,22 +1546,23 @@ read_delta_window(svn_txdelta_window_t *
/* Read SIZE bytes from the representation RS and return it in *NWIN. */
static svn_error_t *
read_plain_window(svn_stringbuf_t **nwin, rep_state_t *rs,
- apr_size_t size, apr_pool_t *pool)
+ apr_size_t size, apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
apr_off_t offset;
/* RS->FILE may be shared between RS instances -> make sure we point
* to the right data. */
SVN_ERR(auto_open_shared_file(rs->sfile));
- SVN_ERR(auto_set_start_offset(rs, pool));
+ SVN_ERR(auto_set_start_offset(rs, scratch_pool));
offset = rs->start + rs->current;
- SVN_ERR(rs_aligned_seek(rs, NULL, offset, pool));
+ SVN_ERR(rs_aligned_seek(rs, NULL, offset, scratch_pool));
/* Read the plain data. */
- *nwin = svn_stringbuf_create_ensure(size, pool);
+ *nwin = svn_stringbuf_create_ensure(size, result_pool);
SVN_ERR(svn_io_file_read_full2(rs->sfile->rfile->file, (*nwin)->data, size,
- NULL, NULL, pool));
+ NULL, NULL, result_pool));
(*nwin)->data[size] = 0;
/* Update RS. */
@@ -1539,6 +1583,7 @@ get_combined_window(svn_stringbuf_t **re
apr_array_header_t *windows;
svn_stringbuf_t *source, *buf = rb->base_window;
rep_state_t *rs;
+ apr_pool_t *iterpool;
/* Read all windows that we need to combine. This is fine because
the size of each window is relatively small (100kB) and skip-
@@ -1546,12 +1591,16 @@ get_combined_window(svn_stringbuf_t **re
Stop early if one of them does not depend on its predecessors. */
window_pool = svn_pool_create(rb->pool);
windows = apr_array_make(window_pool, 0, sizeof(svn_txdelta_window_t *));
+ iterpool = svn_pool_create(rb->pool);
for (i = 0; i < rb->rs_list->nelts; ++i)
{
svn_txdelta_window_t *window;
+ svn_pool_clear(iterpool);
+
rs = APR_ARRAY_IDX(rb->rs_list, i, rep_state_t *);
- SVN_ERR(read_delta_window(&window, rb->chunk_index, rs, window_pool));
+ SVN_ERR(read_delta_window(&window, rb->chunk_index, rs, window_pool,
+ iterpool));
APR_ARRAY_PUSH(windows, svn_txdelta_window_t *) = window;
if (window->src_ops == 0)
@@ -1567,6 +1616,8 @@ get_combined_window(svn_stringbuf_t **re
{
svn_txdelta_window_t *window;
+ svn_pool_clear(iterpool);
+
rs = APR_ARRAY_IDX(rb->rs_list, i, rep_state_t *);
window = APR_ARRAY_IDX(windows, i, svn_txdelta_window_t *);
@@ -1577,7 +1628,7 @@ get_combined_window(svn_stringbuf_t **re
source = buf;
if (source == NULL && rb->src_state != NULL)
SVN_ERR(read_plain_window(&source, rb->src_state, window->sview_len,
- pool));
+ pool, iterpool));
/* Combine this window with the current one. */
new_pool = svn_pool_create(rb->pool);
@@ -1604,6 +1655,7 @@ get_combined_window(svn_stringbuf_t **re
svn_pool_destroy(pool);
pool = new_pool;
}
+ svn_pool_destroy(iterpool);
svn_pool_destroy(window_pool);
@@ -2132,14 +2184,18 @@ delta_read_next_window(svn_txdelta_windo
apr_pool_t *pool)
{
struct delta_read_baton *drb = baton;
+ apr_pool_t *scratch_pool = svn_pool_create(pool);
*window = NULL;
if (drb->rs->current < drb->rs->size)
{
- SVN_ERR(read_delta_window(window, drb->rs->chunk_index, drb->rs, pool));
+ SVN_ERR(read_delta_window(window, drb->rs->chunk_index, drb->rs, pool,
+ scratch_pool));
drb->rs->chunk_index++;
}
+ svn_pool_destroy(scratch_pool);
+
return SVN_NO_ERROR;
}
@@ -2187,7 +2243,7 @@ svn_fs_fs__get_file_delta_stream(svn_txd
{
/* Read target's base rep if any. */
SVN_ERR(create_rep_state(&rep_state, &rep_header, NULL,
- target->data_rep, fs, pool));
+ target->data_rep, fs, pool, pool));
if (source && source->data_rep && target->data_rep)
{
@@ -2354,7 +2410,7 @@ read_dir_entries(apr_array_header_t *ent
_("Directory entry corrupt in '%s'"),
svn_fs_fs__id_unparse(id, scratch_pool)->data);
- dirent->id = svn_fs_fs__id_parse(str, strlen(str), result_pool);
+ dirent->id = svn_fs_fs__id_parse(str, result_pool);
/* In incremental mode, update the hash; otherwise, write to the
* final array. Be sure to use hash keys that survive this iteration.
@@ -2411,11 +2467,9 @@ get_dir_contents(apr_array_header_t **en
}
else if (noderev->data_rep)
{
- /* use a temporary pool for temp objects.
- * Also undeltify content before parsing it. Otherwise, we could only
+ /* Undeltify content before parsing it. Otherwise, we could only
* parse it byte-by-byte.
*/
- apr_pool_t *text_pool = svn_pool_create(scratch_pool);
apr_size_t len = noderev->data_rep->expanded_size
? (apr_size_t)noderev->data_rep->expanded_size
: (apr_size_t)noderev->data_rep->size;
@@ -2423,16 +2477,14 @@ get_dir_contents(apr_array_header_t **en
/* The representation is immutable. Read it normally. */
SVN_ERR(svn_fs_fs__get_contents(&contents, fs, noderev->data_rep,
- FALSE, text_pool));
- SVN_ERR(svn_stringbuf_from_stream(&text, contents, len, text_pool));
+ FALSE, scratch_pool));
+ SVN_ERR(svn_stringbuf_from_stream(&text, contents, len, scratch_pool));
SVN_ERR(svn_stream_close(contents));
/* de-serialize hash */
- contents = svn_stream_from_stringbuf(text, text_pool);
+ contents = svn_stream_from_stringbuf(text, scratch_pool);
SVN_ERR(read_dir_entries(*entries, contents, FALSE, noderev->id,
result_pool, scratch_pool));
-
- svn_pool_destroy(text_pool);
}
return SVN_NO_ERROR;
@@ -2637,19 +2689,20 @@ svn_error_t *
svn_fs_fs__get_changes(apr_array_header_t **changes,
svn_fs_t *fs,
svn_revnum_t rev,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
apr_off_t changes_offset = SVN_FS_FS__ITEM_INDEX_CHANGES;
svn_fs_fs__revision_file_t *revision_file;
svn_boolean_t found;
fs_fs_data_t *ffd = fs->fsap_data;
+ apr_pool_t *scratch_pool = svn_pool_create(result_pool);
/* try cache lookup first */
if (ffd->changes_cache)
{
SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache,
- &rev, pool));
+ &rev, result_pool));
}
else
{
@@ -2660,47 +2713,59 @@ svn_fs_fs__get_changes(apr_array_header_
{
/* read changes from revision file */
- SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, pool));
+ SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, scratch_pool));
SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev,
- pool));
+ scratch_pool));
if (svn_fs_fs__use_log_addressing(fs, rev))
{
/* 'block-read' will also provide us with the desired data */
SVN_ERR(block_read((void **)changes, fs,
rev, SVN_FS_FS__ITEM_INDEX_CHANGES,
- revision_file, pool, pool));
+ revision_file, result_pool, scratch_pool));
}
else
{
/* physical addressing mode code path */
SVN_ERR(get_root_changes_offset(NULL, &changes_offset,
revision_file->file, fs, rev,
- pool));
+ scratch_pool));
SVN_ERR(aligned_seek(fs, revision_file->file, NULL, changes_offset,
- pool));
+ scratch_pool));
SVN_ERR(svn_fs_fs__read_changes(changes, revision_file->stream,
- pool));
+ result_pool, scratch_pool));
/* cache for future reference */
if (ffd->changes_cache)
- SVN_ERR(svn_cache__set(ffd->changes_cache, &rev, *changes, pool));
+ {
+ /* Guesstimate for the size of the in-cache representation. */
+ apr_size_t estimated_size = (apr_size_t)250 * (*changes)->nelts;
+
+ /* Don't even serialize data that probably won't fit into the
+ * cache. This often implies that either CHANGES is very
+ * large, memory is scarce or both. Having a huge temporary
+ * copy would not be a good thing in either case. */
+ if (svn_cache__is_cachable(ffd->changes_cache, estimated_size))
+ SVN_ERR(svn_cache__set(ffd->changes_cache, &rev, *changes,
+ scratch_pool));
+ }
}
SVN_ERR(svn_fs_fs__close_revision_file(revision_file));
}
SVN_ERR(dbg_log_access(fs, rev, changes_offset, *changes,
- SVN_FS_FS__ITEM_TYPE_CHANGES, pool));
+ SVN_FS_FS__ITEM_TYPE_CHANGES, scratch_pool));
+ svn_pool_destroy(scratch_pool);
return SVN_NO_ERROR;
}
/* Inialize the representation read state RS for the given REP_HEADER and
* p2l index ENTRY. If not NULL, assign FILE and STREAM to RS.
- * Use POOL for allocations.
+ * Use RESULT_POOL for allocations.
*/
static svn_error_t *
init_rep_state(rep_state_t *rs,
@@ -2708,10 +2773,10 @@ init_rep_state(rep_state_t *rs,
svn_fs_t *fs,
svn_fs_fs__revision_file_t *file,
svn_fs_fs__p2l_entry_t* entry,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
- shared_file_t *shared_file = apr_pcalloc(pool, sizeof(*shared_file));
+ shared_file_t *shared_file = apr_pcalloc(result_pool, sizeof(*shared_file));
/* this function does not apply to representation containers */
SVN_ERR_ASSERT(entry->type >= SVN_FS_FS__ITEM_TYPE_FILE_REP
@@ -2720,7 +2785,7 @@ init_rep_state(rep_state_t *rs,
shared_file->rfile = file;
shared_file->fs = fs;
shared_file->revision = entry->item.revision;
- shared_file->pool = pool;
+ shared_file->pool = result_pool;
rs->sfile = shared_file;
rs->revision = entry->item.revision;
@@ -2868,7 +2933,7 @@ cache_windows(svn_fs_t *fs,
/* Read all txdelta / plain windows following REP_HEADER in FS as described
* by ENTRY. Read the data from the already open FILE and the wrapping
* STREAM object. If MAX_OFFSET is not -1, don't read windows that start
- * at or beyond that offset. Use POOL for allocations.
+ * at or beyond that offset. Use SCRATCH_POOL for temporary allocations.
* If caching is not enabled, this is a no-op.
*/
static svn_error_t *
@@ -2877,7 +2942,8 @@ block_read_windows(svn_fs_fs__rep_header
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t* entry,
apr_off_t max_offset,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
rep_state_t rs = { 0 };
@@ -2890,7 +2956,8 @@ block_read_windows(svn_fs_fs__rep_header
&& !ffd->combined_window_cache))
return SVN_NO_ERROR;
- SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry, pool));
+ SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry,
+ result_pool));
/* RS->FILE may be shared between RS instances -> make sure we point
* to the right data. */
@@ -2902,26 +2969,28 @@ block_read_windows(svn_fs_fs__rep_header
/* already in cache? */
SVN_ERR(svn_cache__has_key(&is_cached, rs.combined_cache,
- get_window_key(&key, &rs), pool));
+ get_window_key(&key, &rs),
+ scratch_pool));
if (is_cached)
return SVN_NO_ERROR;
/* for larger reps, the header may have crossed a block boundary.
* make sure we still read blocks properly aligned, i.e. don't use
* plain seek here. */
- SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, pool));
+ SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, scratch_pool));
- plaintext = svn_stringbuf_create_ensure(rs.size, pool);
+ plaintext = svn_stringbuf_create_ensure(rs.size, result_pool);
SVN_ERR(svn_io_file_read_full2(rev_file->file, plaintext->data,
- rs.size, &plaintext->len, NULL, pool));
+ rs.size, &plaintext->len, NULL,
+ result_pool));
plaintext->data[plaintext->len] = 0;
rs.current += rs.size;
- SVN_ERR(set_cached_combined_window(plaintext, &rs, pool));
+ SVN_ERR(set_cached_combined_window(plaintext, &rs, scratch_pool));
}
else
{
- SVN_ERR(cache_windows(fs, &rs, max_offset, pool));
+ SVN_ERR(cache_windows(fs, &rs, max_offset, scratch_pool));
}
return SVN_NO_ERROR;
@@ -2937,7 +3006,8 @@ read_rep_header(svn_fs_fs__rep_header_t
svn_fs_t *fs,
svn_stream_t *stream,
pair_cache_key_t *key,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
svn_boolean_t is_cached = FALSE;
@@ -2945,15 +3015,18 @@ read_rep_header(svn_fs_fs__rep_header_t
if (ffd->rep_header_cache)
{
SVN_ERR(svn_cache__get((void**)rep_header, &is_cached,
- ffd->rep_header_cache, key, pool));
+ ffd->rep_header_cache, key,
+ result_pool));
if (is_cached)
return SVN_NO_ERROR;
}
- SVN_ERR(svn_fs_fs__read_rep_header(rep_header, stream, pool));
+ SVN_ERR(svn_fs_fs__read_rep_header(rep_header, stream, result_pool,
+ scratch_pool));
if (ffd->rep_header_cache)
- SVN_ERR(svn_cache__set(ffd->rep_header_cache, key, *rep_header, pool));
+ SVN_ERR(svn_cache__set(ffd->rep_header_cache, key, *rep_header,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -2962,14 +3035,16 @@ read_rep_header(svn_fs_fs__rep_header_t
* addressed by ENTRY->ITEM in FS and cache it if caches are enabled.
* Read the data from the already open FILE and the wrapping
* STREAM object. If MAX_OFFSET is not -1, don't read windows that start
- * at or beyond that offset. Use POOL for allocations.
+ * at or beyond that offset.
+ * Use SCRATCH_POOL for temporary allocations.
*/
static svn_error_t *
block_read_contents(svn_fs_t *fs,
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t* entry,
apr_off_t max_offset,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
pair_cache_key_t header_key = { 0 };
svn_fs_fs__rep_header_t *rep_header;
@@ -2978,9 +3053,9 @@ block_read_contents(svn_fs_t *fs,
header_key.second = entry->item.number;
SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key,
- pool));
+ result_pool, scratch_pool));
SVN_ERR(block_read_windows(rep_header, fs, rev_file, entry, max_offset,
- pool));
+ result_pool, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3033,7 +3108,8 @@ block_read_changes(apr_array_header_t **
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t *entry,
svn_boolean_t must_read,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
svn_stream_t *stream;
@@ -3045,22 +3121,25 @@ block_read_changes(apr_array_header_t **
{
svn_boolean_t is_cached;
SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache,
- &entry->item.revision, pool));
+ &entry->item.revision,
+ scratch_pool));
if (is_cached)
return SVN_NO_ERROR;
}
- SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, pool));
+ SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry,
+ scratch_pool));
/* read changes from revision file */
- SVN_ERR(svn_fs_fs__read_changes(changes, stream, pool));
+ SVN_ERR(svn_fs_fs__read_changes(changes, stream, result_pool,
+ scratch_pool));
/* cache for future reference */
if (ffd->changes_cache)
SVN_ERR(svn_cache__set(ffd->changes_cache, &entry->item.revision,
- *changes, pool));
+ *changes, scratch_pool));
return SVN_NO_ERROR;
}
@@ -3068,7 +3147,7 @@ block_read_changes(apr_array_header_t **
/* If not already cached or if MUST_READ is set, read the nod revision
* addressed by ENTRY in FS and retúrn it in *NODEREV_P. Cache the
* result if caching is enabled. Read the data from the already open
- * FILE and wrapping FILE_STREAM. Use POOL for allocations.
+ * FILE and wrapping FILE_STREAM. Use SCRATCH_POOL for temporary allocations.
*/
static svn_error_t *
block_read_noderev(node_revision_t **noderev_p,
@@ -3076,7 +3155,8 @@ block_read_noderev(node_revision_t **nod
svn_fs_fs__revision_file_t *rev_file,
svn_fs_fs__p2l_entry_t *entry,
svn_boolean_t must_read,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
svn_stream_t *stream;
@@ -3093,23 +3173,25 @@ block_read_noderev(node_revision_t **nod
{
svn_boolean_t is_cached;
SVN_ERR(svn_cache__has_key(&is_cached, ffd->node_revision_cache,
- &key, pool));
+ &key, scratch_pool));
if (is_cached)
return SVN_NO_ERROR;
}
- SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry, pool));
+ SVN_ERR(auto_select_stream(&stream, fs, rev_file, entry,
+ scratch_pool));
/* read node rev from revision file */
- SVN_ERR(svn_fs_fs__read_noderev(noderev_p, stream, pool));
+ SVN_ERR(svn_fs_fs__read_noderev(noderev_p, stream,
+ result_pool, scratch_pool));
/* Workaround issue #4031: is-fresh-txn-root in revision files. */
(*noderev_p)->is_fresh_txn_root = FALSE;
if (ffd->node_revision_cache)
SVN_ERR(svn_cache__set(ffd->node_revision_cache, &key, *noderev_p,
- pool));
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -3138,7 +3220,14 @@ block_read(void **result,
apr_array_header_t *entries;
int run_count = 0;
int i;
- apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_pool_t *iterpool;
+
+ /* Block read is an optional feature. If the caller does not want anything
+ * specific we may not have to read anything. */
+ if (!result && !ffd->use_block_read)
+ return SVN_NO_ERROR;
+
+ iterpool = svn_pool_create(scratch_pool);
/* don't try this on transaction protorev files */
SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
@@ -3160,37 +3249,12 @@ block_read(void **result,
*/
do
{
- svn_error_t *err;
-
/* fetch list of items in the block surrounding OFFSET */
block_start = offset - (offset % ffd->block_size);
- err = svn_fs_fs__p2l_index_lookup(&entries, fs, revision_file,
- revision, block_start,
- ffd->block_size, scratch_pool);
-
- /* if the revision got packed in the meantime and we still need
- * to actually read some item, we retry the whole process */
- if (err)
- {
- /* We failed for the first time. Refresh cache & retry. */
- SVN_ERR(svn_fs_fs__update_min_unpacked_rev(fs, scratch_pool));
- if ( revision_file->is_packed
- != svn_fs_fs__is_packed_rev(fs, revision))
- {
- if (result && !*result)
- {
- SVN_ERR(svn_fs_fs__reopen_revision_file(revision_file, fs,
- revision));
- SVN_ERR(block_read(result, fs, revision, item_index,
- revision_file, result_pool,
- scratch_pool));
- }
+ SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, revision_file,
+ revision, block_start,
+ ffd->block_size, scratch_pool));
- return SVN_NO_ERROR;
- }
- }
-
- SVN_ERR(err);
SVN_ERR(aligned_seek(fs, revision_file->file, &block_start, offset,
iterpool));
@@ -3220,7 +3284,8 @@ block_read(void **result,
/* handle all items that start within this block and are relatively
* small (i.e. < block size). Always read the item we need to return.
*/
- if (is_result || ( entry->offset >= block_start
+ if (is_result || ( ffd->use_block_read
+ && entry->offset >= block_start
&& entry->size < ffd->block_size))
{
void *item = NULL;
@@ -3236,20 +3301,22 @@ block_read(void **result,
is_wanted
? -1
: block_start + ffd->block_size,
- pool));
+ pool, iterpool));
break;
case SVN_FS_FS__ITEM_TYPE_NODEREV:
if (ffd->node_revision_cache || is_result)
SVN_ERR(block_read_noderev((node_revision_t **)&item,
fs, revision_file,
- entry, is_result, pool));
+ entry, is_result, pool,
+ iterpool));
break;
case SVN_FS_FS__ITEM_TYPE_CHANGES:
SVN_ERR(block_read_changes((apr_array_header_t **)&item,
fs, revision_file,
- entry, is_result, pool));
+ entry, is_result,
+ pool, iterpool));
break;
default:
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.h?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/cached_data.h Tue Jun 24 21:29:59 2014
@@ -36,7 +36,8 @@ svn_error_t *
svn_fs_fs__get_node_revision(node_revision_t **noderev_p,
svn_fs_t *fs,
const svn_fs_id_t *id,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Set *ROOT_ID to the node-id for the root of revision REV in
filesystem FS. Do any allocations in POOL. */
@@ -44,28 +45,29 @@ svn_error_t *
svn_fs_fs__rev_get_root(svn_fs_id_t **root_id,
svn_fs_t *fs,
svn_revnum_t rev,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Verify that representation REP in FS can be accessed. Successive calls
to this function should pass a non-NULL value to HINT. In that case,
many file open / close operations can be eliminated.
- Do any allocations in POOL. */
+ Do any allocations in SCRATCH_POOL. */
svn_error_t *
svn_fs_fs__check_rep(representation_t *rep,
svn_fs_t *fs,
void **hint,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
/* Follow the representation delta chain in FS starting with REP. The
number of reps (including REP) in the chain will be returned in
*CHAIN_LENGTH. *SHARD_COUNT will be set to the number of shards
- accessed. Do any allocations in POOL. */
+ accessed. Do any allocations in SCRATCH_POOL. */
svn_error_t *
svn_fs_fs__rep_chain_length(int *chain_length,
int *shard_count,
representation_t *rep,
svn_fs_t *fs,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
/* Set *CONTENTS to be a readable svn_stream_t that receives the text
representation REP as seen in filesystem FS. If CACHE_FULLTEXT is
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/dag.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/dag.c Tue Jun 24 21:29:59 2014
@@ -160,10 +160,13 @@ get_node_revision(node_revision_t **node
if (! node->node_revision)
{
node_revision_t *noderev;
+ apr_pool_t *scratch_pool = svn_pool_create(node->node_pool);
SVN_ERR(svn_fs_fs__get_node_revision(&noderev, node->fs,
- node->id, node->node_pool));
+ node->id, node->node_pool,
+ scratch_pool));
node->node_revision = noderev;
+ svn_pool_destroy(scratch_pool);
}
/* Now NODE->node_revision is set. */
@@ -614,7 +617,7 @@ svn_fs_fs__dag_revision_root(dag_node_t
/* Construct the node. */
new_node = apr_pcalloc(pool, sizeof(*new_node));
new_node->fs = fs;
- SVN_ERR(svn_fs_fs__rev_get_root(&new_node->id, fs, rev, pool));
+ SVN_ERR(svn_fs_fs__rev_get_root(&new_node->id, fs, rev, pool, pool));
/* Grab the contents so we can inspect the node's kind and created path. */
new_node->node_pool = pool;
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.h?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.h Tue Jun 24 21:29:59 2014
@@ -303,7 +303,11 @@ typedef struct fs_fs_data_t
/* Rev / pack file granularity covered by phys-to-log index pages */
apr_int64_t p2l_page_size;
-
+
+ /* If set, parse and cache *all* data of each block that we read
+ * (not just the one bit that we need, atm). */
+ svn_boolean_t use_block_read;
+
/* The revision that was youngest, last time we checked. */
svn_revnum_t youngest_rev_cache;
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.c Tue Jun 24 21:29:59 2014
@@ -43,6 +43,7 @@
#include "private/svn_fs_util.h"
#include "private/svn_string_private.h"
+#include "private/svn_subr_private.h"
#include "../libsvn_fs/fs-loader.h"
/* The default maximum number of files per directory to store in the
@@ -722,7 +723,7 @@ read_config(fs_fs_data_t *ffd,
SVN_ERR(svn_config_get_bool(config, &ffd->compress_packed_revprops,
CONFIG_SECTION_PACKED_REVPROPS,
CONFIG_OPTION_COMPRESS_PACKED_REVPROPS,
- TRUE));
+ FALSE));
SVN_ERR(svn_config_get_int64(config, &ffd->revprop_pack_size,
CONFIG_SECTION_PACKED_REVPROPS,
CONFIG_OPTION_REVPROP_PACK_SIZE,
@@ -927,15 +928,15 @@ write_config(svn_fs_t *fs,
"### ineffective." NL
"### revprop-pack-size is 64 kBytes by default for non-compressed revprop" NL
"### pack files and 256 kBytes when compression has been enabled." NL
-"# " CONFIG_OPTION_REVPROP_PACK_SIZE " = 256" NL
+"# " CONFIG_OPTION_REVPROP_PACK_SIZE " = 64" NL
"###" NL
"### To save disk space, packed revprop files may be compressed. Standard" NL
"### revprops tend to allow for very effective compression. Reading and" NL
"### even more so writing, become significantly more CPU intensive. With" NL
"### revprop caching enabled, the overhead can be offset by reduced I/O" NL
"### unless you often modify revprops after packing." NL
-"### Compressing packed revprops is enabled by default." NL
-"# " CONFIG_OPTION_COMPRESS_PACKED_REVPROPS " = true" NL
+"### Compressing packed revprops is disabled by default." NL
+"# " CONFIG_OPTION_COMPRESS_PACKED_REVPROPS " = false" NL
"" NL
"[" CONFIG_SECTION_IO "]" NL
"### Parameters in this section control the data access granularity in" NL
@@ -993,6 +994,18 @@ write_config(svn_fs_t *fs,
fsfs_conf_contents, pool);
}
+/* Read / Evaluate the global configuration in FS->CONFIG to set up
+ * parameters in FS. */
+static svn_error_t *
+read_global_config(svn_fs_t *fs)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+ ffd->use_block_read
+ = svn_hash__get_bool(fs->config, SVN_FS_CONFIG_FSFS_BLOCK_READ, TRUE);
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_fs_fs__open(svn_fs_t *fs, const char *path, apr_pool_t *pool)
{
@@ -1031,6 +1044,9 @@ svn_fs_fs__open(svn_fs_t *fs, const char
/* Read the configuration file. */
SVN_ERR(read_config(ffd, fs->path, fs->pool, pool));
+ /* Global configuration options. */
+ SVN_ERR(read_global_config(fs));
+
return get_youngest(&(ffd->youngest_rev_cache), path, pool);
}
@@ -1449,15 +1465,35 @@ write_revision_zero(svn_fs_t *fs)
/* Write out a rev file for revision 0. */
if (svn_fs_fs__use_log_addressing(fs, 0))
- SVN_ERR(svn_io_file_create(path_revision_zero,
- "PLAIN\nEND\nENDREP\n"
- "id: 0.0.r0/2\n"
- "type: dir\n"
- "count: 0\n"
- "text: 0 3 4 4 "
- "2d2977d1c96f487abe4a1e202dd03b4e\n"
- "cpath: /\n"
- "\n\n", fs->pool));
+ SVN_ERR(svn_io_file_create_binary(path_revision_zero,
+ "PLAIN\nEND\nENDREP\n"
+ "id: 0.0.r0/2\n"
+ "type: dir\n"
+ "count: 0\n"
+ "text: 0 3 4 4 "
+ "2d2977d1c96f487abe4a1e202dd03b4e\n"
+ "cpath: /\n"
+ "\n\n"
+
+ /* L2P index */
+ "\0\x80\x40" /* rev 0, 8k entries per page */
+ "\1\1\1" /* 1 rev, 1 page, 1 page in 1st rev */
+ "\6\4" /* page size: bytes, count */
+ "\0\xd6\1\xb1\1\x21" /* phys offsets + 1 */
+
+ /* P2L index */
+ "\0\x6b" /* start rev, rev file size */
+ "\x80\x80\4\1\x1D" /* 64k pages, 1 page using 29 bytes */
+ "\0" /* offset entry 0 page 1 */
+ /* len, item & type, rev, checksum */
+ "\x11\x34\0\xf5\xd6\x8c\x81\x06"
+ "\x59\x09\0\xc8\xfc\xf6\x81\x04"
+ "\1\x0d\0\x9d\x9e\xa9\x94\x0f"
+ "\x95\xff\3\x1b\0\0" /* last entry fills up 64k page */
+
+ /* Footer */
+ "107 121\7",
+ 107 + 14 + 38 + 7 + 1, fs->pool));
else
SVN_ERR(svn_io_file_create(path_revision_zero,
"PLAIN\nEND\nENDREP\n"
@@ -1471,35 +1507,6 @@ write_revision_zero(svn_fs_t *fs)
SVN_ERR(svn_io_set_file_read_only(path_revision_zero, FALSE, fs->pool));
- if (svn_fs_fs__use_log_addressing(fs, 0))
- {
- const char *path = svn_fs_fs__path_l2p_index(fs, 0, FALSE, fs->pool);
- SVN_ERR(svn_io_file_create_binary
- (path,
- "\0\x80\x40" /* rev 0, 8k entries per page */
- "\1\1\1" /* 1 rev, 1 page, 1 page in 1st rev */
- "\6\4" /* page size: bytes, count */
- "\0\xd6\1\xb1\1\x21", /* phys offsets + 1 */
- 14,
- fs->pool));
- SVN_ERR(svn_io_set_file_read_only(path, FALSE, fs->pool));
-
- path = svn_fs_fs__path_p2l_index(fs, 0, FALSE, fs->pool);
- SVN_ERR(svn_io_file_create_binary
- (path,
- "\0\x6b" /* start rev, rev file size */
- "\x80\x80\4\1\x1D" /* 64k pages, 1 page using 29 bytes */
- "\0" /* offset entry 0 page 1 */
- /* len, item & type, rev, checksum */
- "\x11\x34\0\xf5\xd6\x8c\x81\x06"
- "\x59\x09\0\xc8\xfc\xf6\x81\x04"
- "\1\x0d\0\x9d\x9e\xa9\x94\x0f"
- "\x95\xff\3\x1b\0\0", /* last entry fills up 64k page */
- 38,
- fs->pool));
- SVN_ERR(svn_io_set_file_read_only(path, FALSE, fs->pool));
- }
-
/* Set a date on revision 0. */
date.data = svn_time_to_cstring(apr_time_now(), fs->pool);
date.len = strlen(date.data);
@@ -1614,6 +1621,9 @@ svn_fs_fs__create(svn_fs_t *fs,
SVN_ERR(read_config(ffd, fs->path, fs->pool, pool));
+ /* Global configuration options. */
+ SVN_ERR(read_global_config(fs));
+
/* Create the min unpacked rev file. */
if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
SVN_ERR(svn_io_file_create(svn_fs_fs__path_min_unpacked_rev(fs, pool),
@@ -1737,8 +1747,9 @@ svn_fs_fs__get_node_origin(const svn_fs_
= apr_hash_get(node_origins, node_id_ptr, len);
if (origin_id_str)
- *origin_id = svn_fs_fs__id_parse(origin_id_str->data,
- origin_id_str->len, pool);
+ *origin_id = svn_fs_fs__id_parse(apr_pstrdup(pool,
+ origin_id_str->data),
+ pool);
}
return SVN_NO_ERROR;
}
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/hotcopy.c Tue Jun 24 21:29:59 2014
@@ -228,14 +228,12 @@ hotcopy_io_copy_dir_recursively(const ch
/* Copy an un-packed revision or revprop file for revision REV from SRC_SUBDIR
* to DST_SUBDIR. Assume a sharding layout based on MAX_FILES_PER_DIR.
- * If INCLUDE_INDEXES is set, copy rev index files as well.
* Use SCRATCH_POOL for temporary allocations. */
static svn_error_t *
hotcopy_copy_shard_file(const char *src_subdir,
const char *dst_subdir,
svn_revnum_t rev,
int max_files_per_dir,
- svn_boolean_t include_indexes,
apr_pool_t *scratch_pool)
{
const char *src_subdir_shard = src_subdir,
@@ -260,18 +258,6 @@ hotcopy_copy_shard_file(const char *src_
apr_psprintf(scratch_pool, "%ld", rev),
scratch_pool));
- if (include_indexes)
- {
- SVN_ERR(hotcopy_io_dir_file_copy(src_subdir_shard, dst_subdir_shard,
- apr_psprintf(scratch_pool, "%ld.l2p",
- rev),
- scratch_pool));
- SVN_ERR(hotcopy_io_dir_file_copy(src_subdir_shard, dst_subdir_shard,
- apr_psprintf(scratch_pool, "%ld.p2l",
- rev),
- scratch_pool));
- }
-
return SVN_NO_ERROR;
}
@@ -327,7 +313,7 @@ hotcopy_copy_packed_shard(svn_revnum_t *
SVN_ERR(hotcopy_copy_shard_file(src_subdir, dst_subdir,
revprop_rev, max_files_per_dir,
- FALSE, iterpool));
+ iterpool));
}
svn_pool_destroy(iterpool);
}
@@ -336,7 +322,7 @@ hotcopy_copy_packed_shard(svn_revnum_t *
/* revprop for revision 0 will never be packed */
if (rev == 0)
SVN_ERR(hotcopy_copy_shard_file(src_subdir, dst_subdir,
- 0, max_files_per_dir, FALSE,
+ 0, max_files_per_dir,
scratch_pool));
/* packed revprops folder */
@@ -717,7 +703,6 @@ hotcopy_revisions(svn_revnum_t *dst_youn
/* Copy the rev file. */
err = hotcopy_copy_shard_file(src_revs_dir, dst_revs_dir,
rev, max_files_per_dir,
- svn_fs_fs__use_log_addressing(src_fs, rev),
iterpool);
if (err)
{
@@ -768,7 +753,7 @@ hotcopy_revisions(svn_revnum_t *dst_youn
/* Copy the revprop file. */
SVN_ERR(hotcopy_copy_shard_file(src_revprops_dir,
dst_revprops_dir,
- rev, max_files_per_dir, FALSE,
+ rev, max_files_per_dir,
iterpool));
/* After completing a full shard, update 'current'. */
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/id.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/id.c Tue Jun 24 21:29:59 2014
@@ -78,7 +78,10 @@ part_parse(svn_fs_fs__id_part_t *part,
return *data == '\0';
}
- part->revision = SVN_STR_TO_REV(++data);
+ {
+ const char *end;
+ part->revision = svn__strtol(data+1, &end);
+ }
return TRUE;
}
@@ -90,8 +93,9 @@ static svn_boolean_t
txn_id_parse(svn_fs_fs__id_part_t *txn_id,
const char *data)
{
- txn_id->revision = SVN_STR_TO_REV(data);
- data = strchr(data, '-');
+ const char *end;
+ txn_id->revision = svn__strtol(data, &end);
+ data = strchr(end, '-');
if (data == NULL)
return FALSE;
@@ -435,16 +439,11 @@ svn_fs_fs__id_copy(const svn_fs_id_t *so
svn_fs_id_t *
-svn_fs_fs__id_parse(const char *data,
- apr_size_t len,
+svn_fs_fs__id_parse(char *data,
apr_pool_t *pool)
{
fs_fs__id_t *id;
- char *data_copy, *str;
-
- /* Dup the ID data into POOL. Our returned ID will have references
- into this memory. */
- data_copy = apr_pstrmemdup(pool, data, len);
+ char *str;
/* Alloc a new svn_fs_id_t structure. */
id = apr_pcalloc(pool, sizeof(*id));
@@ -458,40 +457,41 @@ svn_fs_fs__id_parse(const char *data,
string.*/
/* Node Id */
- str = svn_cstring_tokenize(".", &data_copy);
+ str = svn_cstring_tokenize(".", &data);
if (str == NULL)
return NULL;
if (! part_parse(&id->private_id.node_id, str))
return NULL;
/* Copy Id */
- str = svn_cstring_tokenize(".", &data_copy);
+ str = svn_cstring_tokenize(".", &data);
if (str == NULL)
return NULL;
if (! part_parse(&id->private_id.copy_id, str))
return NULL;
/* Txn/Rev Id */
- str = svn_cstring_tokenize(".", &data_copy);
+ str = svn_cstring_tokenize(".", &data);
if (str == NULL)
return NULL;
if (str[0] == 'r')
{
apr_int64_t val;
+ const char *tmp;
svn_error_t *err;
/* This is a revision type ID */
id->private_id.txn_id.revision = SVN_INVALID_REVNUM;
id->private_id.txn_id.number = 0;
- data_copy = str + 1;
- str = svn_cstring_tokenize("/", &data_copy);
+ data = str + 1;
+ str = svn_cstring_tokenize("/", &data);
if (str == NULL)
return NULL;
- id->private_id.rev_item.revision = SVN_STR_TO_REV(str);
+ id->private_id.rev_item.revision = svn__strtol(str, &tmp);
- err = svn_cstring_atoi64(&val, data_copy);
+ err = svn_cstring_atoi64(&val, data);
if (err)
{
svn_error_clear(err);
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/id.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/id.h?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/id.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/id.h Tue Jun 24 21:29:59 2014
@@ -149,10 +149,9 @@ svn_fs_id_t *svn_fs_fs__id_rev_create(co
svn_fs_id_t *svn_fs_fs__id_copy(const svn_fs_id_t *id,
apr_pool_t *pool);
-/* Return an ID resulting from parsing the string DATA (with length
- LEN), or NULL if DATA is an invalid ID string. */
-svn_fs_id_t *svn_fs_fs__id_parse(const char *data,
- apr_size_t len,
+/* Return an ID resulting from parsing the string DATA, or NULL if DATA is
+ an invalid ID string. *DATA will be modified / invalidated by this call. */
+svn_fs_id_t *svn_fs_fs__id_parse(char *data,
apr_pool_t *pool);
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/index.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/index.c?rev=1605201&r1=1605200&r2=1605201&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/index.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/index.c Tue Jun 24 21:29:59 2014
@@ -159,6 +159,15 @@ struct svn_fs_fs__packed_number_stream_t
/* underlying data file containing the packed values */
apr_file_t *file;
+ /* Offset within FILE at which the stream data starts
+ * (i.e. which offset will reported as offset 0 by packed_stream_offset). */
+ apr_off_t stream_start;
+
+ /* First offset within FILE after the stream data.
+ * Attempts to read beyond this will cause an "Unexpected End Of Stream"
+ * error. */
+ apr_off_t stream_end;
+
/* number of used entries in BUFFER (starting at index 0) */
apr_size_t used;
@@ -240,6 +249,10 @@ packed_stream_read(svn_fs_fs__packed_num
if (block_left >= 10 && block_left < read)
read = block_left;
+ /* Don't read beyond the end of the file section that belongs to this
+ * index / stream. */
+ read = MIN(read, stream->stream_end - stream->next_offset);
+
err = apr_file_read(stream->file, buffer, &read);
if (err && !APR_STATUS_IS_EOF(err))
return stream_error_create(stream, err,
@@ -300,45 +313,33 @@ packed_stream_read(svn_fs_fs__packed_num
return SVN_NO_ERROR;
}
-/* Create and open a packed number stream reading from FILE_NAME and
- * return it in *STREAM. Access the file in chunks of BLOCK_SIZE bytes.
- * Use POOL for allocations.
+/* Create and open a packed number stream reading from offsets START to
+ * END in FILE and return it in *STREAM. Access the file in chunks of
+ * BLOCK_SIZE bytes. Use POOL for allocations.
*/
static svn_error_t *
packed_stream_open(svn_fs_fs__packed_number_stream_t **stream,
- const char *file_name,
+ apr_file_t *file,
+ apr_off_t start,
+ apr_off_t end,
apr_size_t block_size,
apr_pool_t *pool)
{
svn_fs_fs__packed_number_stream_t *result
= apr_palloc(pool, sizeof(*result));
- result->pool = svn_pool_create(pool);
- SVN_ERR(svn_io_file_open(&result->file, file_name,
- APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
- result->pool));
+ result->pool = pool;
+ result->file = file;
+ result->stream_start = start;
+ result->stream_end = end;
result->used = 0;
result->current = 0;
- result->start_offset = 0;
- result->next_offset = 0;
+ result->start_offset = result->stream_start;
+ result->next_offset = result->stream_start;
result->block_size = block_size;
*stream = result;
-
- return SVN_NO_ERROR;
-}
-
-/* Close STREAM which may be NULL.
- */
-svn_error_t *
-svn_fs_fs__packed_stream_close(svn_fs_fs__packed_number_stream_t *stream)
-{
- if (stream)
- {
- SVN_ERR(svn_io_file_close(stream->file, stream->pool));
- svn_pool_destroy(stream->pool);
- }
return SVN_NO_ERROR;
}
@@ -363,20 +364,22 @@ packed_stream_get(apr_uint64_t *value,
return SVN_NO_ERROR;
}
-/* Navigate STREAM to packed file offset OFFSET. There will be no checks
+/* Navigate STREAM to packed stream offset OFFSET. There will be no checks
* whether the given OFFSET is valid.
*/
static void
packed_stream_seek(svn_fs_fs__packed_number_stream_t *stream,
apr_off_t offset)
{
+ apr_off_t file_offset = offset + stream->stream_start;
+
if ( stream->used == 0
|| offset < stream->start_offset
|| offset >= stream->next_offset)
{
/* outside buffered data. Next get() will read() from OFFSET. */
- stream->start_offset = offset;
- stream->next_offset = offset;
+ stream->start_offset = file_offset;
+ stream->next_offset = file_offset;
stream->current = 0;
stream->used = 0;
}
@@ -387,22 +390,25 @@ packed_stream_seek(svn_fs_fs__packed_num
* it for the desired position. */
apr_size_t i;
for (i = 0; i < stream->used; ++i)
- if (stream->buffer[i].total_len > offset - stream->start_offset)
+ if (stream->buffer[i].total_len > file_offset - stream->start_offset)
break;
stream->current = i;
}
}
-/* Return the packed file offset of at which the next number in the stream
+/* Return the packed stream offset of at which the next number in the stream
* can be found.
*/
static apr_off_t
packed_stream_offset(svn_fs_fs__packed_number_stream_t *stream)
{
- return stream->current == 0
+ apr_off_t file_offset
+ = stream->current == 0
? stream->start_offset
: stream->buffer[stream->current-1].total_len + stream->start_offset;
+
+ return file_offset - stream->stream_start;
}
/* Encode VALUE as 7/8b into P and return the number of bytes written.
@@ -537,25 +543,9 @@ svn_fs_fs__l2p_proto_index_add_entry(apr
pool));
}
-static svn_error_t *
-index_create(apr_file_t **index_file, const char *file_name, apr_pool_t *pool)
-{
- /* remove any old index file
- * (it would probably be r/o and simply re-writing it would fail) */
- SVN_ERR(svn_io_remove_file2(file_name, TRUE, pool));
-
- /* We most likely own the write lock to the repo, so this should
- * either just work or fail indicating a serious problem. */
- SVN_ERR(svn_io_file_open(index_file, file_name,
- APR_WRITE | APR_CREATE | APR_BUFFERED,
- APR_OS_DEFAULT, pool));
-
- return SVN_NO_ERROR;
-}
-
svn_error_t *
-svn_fs_fs__l2p_index_create(svn_fs_t *fs,
- const char *file_name,
+svn_fs_fs__l2p_index_append(svn_fs_t *fs,
+ apr_file_t *index_file,
const char *proto_file_name,
svn_revnum_t revision,
apr_pool_t *pool)
@@ -565,7 +555,6 @@ svn_fs_fs__l2p_index_create(svn_fs_t *fs
int i;
apr_uint64_t entry;
svn_boolean_t eof = FALSE;
- apr_file_t *index_file;
unsigned char encoded[ENCODED_INT_LENGTH];
int last_page_count = 0; /* total page count at the start of
@@ -672,9 +661,6 @@ svn_fs_fs__l2p_index_create(svn_fs_t *fs
/* close the source file */
SVN_ERR(svn_io_file_close(proto_index, local_pool));
- /* create the target file */
- SVN_ERR(index_create(&index_file, file_name, local_pool));
-
/* Paranoia check that makes later casting to int32 safe.
* The current implementation is limited to 2G pages per index. */
if (page_counts->nelts > APR_INT32_MAX)
@@ -725,45 +711,13 @@ svn_fs_fs__l2p_index_create(svn_fs_t *fs
local_pool),
NULL, NULL, local_pool));
- /* finalize the index file */
- SVN_ERR(svn_io_file_close(index_file, local_pool));
- SVN_ERR(svn_io_set_file_read_only(file_name, FALSE, local_pool));
-
svn_pool_destroy(local_pool);
return SVN_NO_ERROR;
}
-/* Reopen the rev / pack file in REV_FILE and attempt to open the L2P
- * index for REVISION in FS.
- */
-static svn_error_t *
-retry_open_l2p_index(svn_fs_fs__revision_file_t *rev_file,
- svn_fs_t *fs,
- svn_revnum_t revision)
-{
- fs_fs_data_t *ffd = fs->fsap_data;
-
- /* reopen rep file if necessary */
- if (rev_file->file)
- SVN_ERR(svn_fs_fs__reopen_revision_file(rev_file, fs, revision));
- else
- rev_file->is_packed = svn_fs_fs__is_packed_rev(fs, revision);
-
- /* re-try opening this index (keep the p2l closed) */
- SVN_ERR(packed_stream_open(&rev_file->l2p_stream,
- svn_fs_fs__path_l2p_index(fs, revision,
- rev_file->is_packed,
- rev_file->pool),
- ffd->block_size,
- rev_file->pool));
-
- 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. May fail if pack
- * status changed.
+ * index for REVISION in FS and return it in REV_FILE.
*/
static svn_error_t *
auto_open_l2p_index(svn_fs_fs__revision_file_t *rev_file,
@@ -773,10 +727,12 @@ auto_open_l2p_index(svn_fs_fs__revision_
if (rev_file->l2p_stream == NULL)
{
fs_fs_data_t *ffd = fs->fsap_data;
+
+ SVN_ERR(svn_fs_fs__auto_read_footer(rev_file));
SVN_ERR(packed_stream_open(&rev_file->l2p_stream,
- svn_fs_fs__path_l2p_index(fs, revision,
- rev_file->is_packed,
- rev_file->pool),
+ rev_file->file,
+ rev_file->l2p_offset,
+ rev_file->p2l_offset,
ffd->block_size,
rev_file->pool));
}
@@ -1471,13 +1427,14 @@ svn_fs_fs__l2p_get_max_ids(apr_array_hea
l2p_header_t *header = NULL;
svn_revnum_t revision;
svn_revnum_t last_rev = (svn_revnum_t)(start_rev + count);
- svn_fs_fs__revision_file_t rev_file;
+ svn_fs_fs__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_fs_fs__init_revision_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_fs__close_revision_file(&rev_file));
+ SVN_ERR(svn_fs_fs__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_fs__close_revision_file(rev_file));
/* Determine the length of the item index list for each rev.
* Read new index headers as required. */
@@ -1495,10 +1452,11 @@ svn_fs_fs__l2p_get_max_ids(apr_array_hea
* the number of items in a revision, i.e. there is no consistency
* issue here. */
svn_pool_clear(header_pool);
- rev_file.start_revision = revision;
- SVN_ERR(get_l2p_header(&header, &rev_file, fs, revision,
+ SVN_ERR(svn_fs_fs__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(svn_fs_fs__close_revision_file(&rev_file));
+ SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
}
/* in a revision with N index pages, the first N-1 index pages are
@@ -1546,26 +1504,8 @@ svn_fs_fs__item_offset(apr_off_t *absolu
else if (svn_fs_fs__use_log_addressing(fs, revision))
{
/* ordinary index lookup */
- err = l2p_index_lookup(absolute_position, fs, rev_file, revision,
- item_index, pool);
-
- if (err && !rev_file->is_packed)
- {
- /* REVISION might have been packed in the meantime.
- Refresh cache & retry. */
- err = svn_error_compose_create(err,
- svn_fs_fs__update_min_unpacked_rev
- (fs, pool));
-
- /* retry upon intermittent pack */
- if (svn_fs_fs__is_packed_rev(fs, revision) != rev_file->is_packed)
- {
- svn_error_clear(err);
- SVN_ERR(retry_open_l2p_index(rev_file, fs, revision));
- err = l2p_index_lookup(absolute_position, fs, rev_file,
- revision, item_index, pool);
- }
- }
+ SVN_ERR(l2p_index_lookup(absolute_position, fs, rev_file, revision,
+ item_index, pool));
}
else if (rev_file->is_packed)
{
@@ -1645,8 +1585,8 @@ svn_fs_fs__p2l_proto_index_next_offset(a
}
svn_error_t *
-svn_fs_fs__p2l_index_create(svn_fs_t *fs,
- const char *file_name,
+svn_fs_fs__p2l_index_append(svn_fs_t *fs,
+ apr_file_t *index_file,
const char *proto_file_name,
svn_revnum_t revision,
apr_pool_t *pool)
@@ -1656,7 +1596,6 @@ svn_fs_fs__p2l_index_create(svn_fs_t *fs
apr_file_t *proto_index = NULL;
int i;
svn_boolean_t eof = FALSE;
- apr_file_t *index_file;
unsigned char encoded[ENCODED_INT_LENGTH];
svn_revnum_t last_revision = revision;
apr_uint64_t last_compound = 0;
@@ -1777,9 +1716,6 @@ svn_fs_fs__p2l_index_create(svn_fs_t *fs
APR_ARRAY_PUSH(table_sizes, apr_uint64_t)
= svn_spillbuf__get_size(buffer) - last_buffer_size;
- /* create the target file */
- SVN_ERR(index_create(&index_file, file_name, local_pool));
-
/* write the start revision, file size and page size */
SVN_ERR(svn_io_file_write_full(index_file, encoded,
encode_uint(encoded, revision),
@@ -1809,44 +1745,14 @@ svn_fs_fs__p2l_index_create(svn_fs_t *fs
local_pool),
NULL, NULL, local_pool));
- /* finalize the index file */
- SVN_ERR(svn_io_file_close(index_file, local_pool));
- SVN_ERR(svn_io_set_file_read_only(file_name, FALSE, local_pool));
-
svn_pool_destroy(iter_pool);
svn_pool_destroy(local_pool);
return SVN_NO_ERROR;
}
-/* Reopen the rev / pack file in REV_FILE (if previously opened) using
- * the current pack status of REVISION in FS and open the suitable
- * P2L index. Close the L2P index.
- */
-static svn_error_t *
-retry_open_p2l_index(svn_fs_fs__revision_file_t *rev_file,
- svn_fs_t *fs,
- svn_revnum_t revision)
-{
- fs_fs_data_t *ffd = fs->fsap_data;
-
- /* reopen rep file if necessary */
- if (rev_file->file)
- SVN_ERR(svn_fs_fs__reopen_revision_file(rev_file, fs, revision));
-
- /* re-try opening this index (keep the l2p closed) */
- SVN_ERR(packed_stream_open(&rev_file->p2l_stream,
- svn_fs_fs__path_p2l_index(fs, revision,
- rev_file->is_packed,
- rev_file->pool),
- ffd->block_size,
- rev_file->pool));
-
- return SVN_NO_ERROR;
-}
-
/* If REV_FILE->P2L_STREAM is NULL, create a new stream for the phys-to-log
- * index for REVISION in FS using the rev / pack status provided by REV_FILE.
+ * index for REVISION in FS using the rev / pack file provided by REV_FILE.
*/
static svn_error_t *
auto_open_p2l_index(svn_fs_fs__revision_file_t *rev_file,
@@ -1856,10 +1762,12 @@ auto_open_p2l_index(svn_fs_fs__revision_
if (rev_file->p2l_stream == NULL)
{
fs_fs_data_t *ffd = fs->fsap_data;
+
+ SVN_ERR(svn_fs_fs__auto_read_footer(rev_file));
SVN_ERR(packed_stream_open(&rev_file->p2l_stream,
- svn_fs_fs__path_p2l_index(fs, revision,
- rev_file->is_packed,
- rev_file->pool),
+ rev_file->file,
+ rev_file->p2l_offset,
+ rev_file->footer_offset,
ffd->block_size, rev_file->pool));
}
@@ -2699,17 +2607,8 @@ svn_fs_fs__p2l_get_max_offset(apr_off_t
svn_revnum_t revision,
apr_pool_t *pool)
{
- svn_error_t *err = p2l_get_max_offset(offset, fs, rev_file, revision, pool);
-
- /* retry upon intermittent pack */
- if (err && svn_fs_fs__is_packed_rev(fs, revision) != rev_file->is_packed)
- {
- svn_error_clear(err);
- SVN_ERR(retry_open_p2l_index(rev_file, fs, revision));
- err = p2l_get_max_offset(offset, fs, rev_file, revision, pool);
- }
-
- return svn_error_trace(err);
+ return svn_error_trace(p2l_get_max_offset(offset, fs, rev_file, revision,
+ pool));
}
/*