Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_fs_fs/fs_fs.c view on Meta::CPAN
content->data = next;
}
return FALSE;
}
/* Baton used for recover_body below. */
struct recover_baton {
svn_fs_t *fs;
svn_cancel_func_t cancel_func;
void *cancel_baton;
};
/* The work-horse for svn_fs_fs__recover, called with the FS
write lock. This implements the svn_fs_fs__with_write_lock()
'body' callback type. BATON is a 'struct recover_baton *'. */
static svn_error_t *
recover_body(void *baton, apr_pool_t *pool)
{
struct recover_baton *b = baton;
svn_fs_t *fs = b->fs;
fs_fs_data_t *ffd = fs->fsap_data;
svn_revnum_t max_rev;
char next_node_id_buf[MAX_KEY_SIZE], next_copy_id_buf[MAX_KEY_SIZE];
char *next_node_id = NULL, *next_copy_id = NULL;
svn_revnum_t youngest_rev;
svn_node_kind_t youngest_revprops_kind;
/* Lose potentially corrupted data in temp files */
SVN_ERR(cleanup_revprop_namespace(fs));
/* We need to know the largest revision in the filesystem. */
SVN_ERR(recover_get_largest_revision(fs, &max_rev, pool));
/* Get the expected youngest revision */
SVN_ERR(get_youngest(&youngest_rev, fs->path, pool));
/* Policy note:
Since the revprops file is written after the revs file, the true
maximum available revision is the youngest one for which both are
present. That's probably the same as the max_rev we just found,
but if it's not, we could, in theory, repeatedly decrement
max_rev until we find a revision that has both a revs and
revprops file, then write db/current with that.
But we choose not to. If a repository is so corrupt that it's
missing at least one revprops file, we shouldn't assume that the
youngest revision for which both the revs and revprops files are
present is healthy. In other words, we're willing to recover
from a missing or out-of-date db/current file, because db/current
is truly redundant -- it's basically a cache so we don't have to
find max_rev each time, albeit a cache with unusual semantics,
since it also officially defines when a revision goes live. But
if we're missing more than the cache, it's time to back out and
let the admin reconstruct things by hand: correctness at that
point may depend on external things like checking a commit email
list, looking in particular working copies, etc.
This policy matches well with a typical naive backup scenario.
Say you're rsyncing your FSFS repository nightly to the same
location. Once revs and revprops are written, you've got the
maximum rev; if the backup should bomb before db/current is
written, then db/current could stay arbitrarily out-of-date, but
we can still recover. It's a small window, but we might as well
do what we can. */
/* Even if db/current were missing, it would be created with 0 by
get_youngest(), so this conditional remains valid. */
if (youngest_rev > max_rev)
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
_("Expected current rev to be <= %ld "
"but found %ld"), max_rev, youngest_rev);
/* We only need to search for maximum IDs for old FS formats which
se global ID counters. */
if (ffd->format < SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT)
{
/* Next we need to find the maximum node id and copy id in use across the
filesystem. Unfortunately, the only way we can get this information
is to scan all the noderevs of all the revisions and keep track as
we go along. */
svn_revnum_t rev;
apr_pool_t *iterpool = svn_pool_create(pool);
char max_node_id[MAX_KEY_SIZE] = "0", max_copy_id[MAX_KEY_SIZE] = "0";
apr_size_t len;
for (rev = 0; rev <= max_rev; rev++)
{
apr_file_t *rev_file;
apr_off_t root_offset;
svn_pool_clear(iterpool);
if (b->cancel_func)
SVN_ERR(b->cancel_func(b->cancel_baton));
SVN_ERR(open_pack_or_rev_file(&rev_file, fs, rev, iterpool));
SVN_ERR(get_root_changes_offset(&root_offset, NULL, rev_file, fs, rev,
iterpool));
SVN_ERR(recover_find_max_ids(fs, rev, rev_file, root_offset,
max_node_id, max_copy_id, iterpool));
SVN_ERR(svn_io_file_close(rev_file, iterpool));
}
svn_pool_destroy(iterpool);
/* Now that we finally have the maximum revision, node-id and copy-id, we
can bump the two ids to get the next of each. */
len = strlen(max_node_id);
svn_fs_fs__next_key(max_node_id, &len, next_node_id_buf);
next_node_id = next_node_id_buf;
len = strlen(max_copy_id);
svn_fs_fs__next_key(max_copy_id, &len, next_copy_id_buf);
next_copy_id = next_copy_id_buf;
}
/* Before setting current, verify that there is a revprops file
for the youngest revision. (Issue #2992) */
SVN_ERR(svn_io_check_path(path_revprops(fs, max_rev, pool),
&youngest_revprops_kind, pool));
if (youngest_revprops_kind == svn_node_none)
{
svn_boolean_t missing = TRUE;
( run in 0.466 second using v1.01-cache-2.11-cpan-97f6503c9c8 )