You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by iv...@apache.org on 2014/11/14 14:18:03 UTC
svn commit: r1639628 [4/23] - in /subversion/branches/svn-auth-x509: ./
build/ build/generator/ notes/ notes/api-errata/1.8/ notes/api-errata/1.9/
notes/wc-ng/ subversion/ subversion/bindings/ctypes-python/
subversion/bindings/cxxhl/ subversion/binding...
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_diff/diff_memory.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_diff/diff_memory.c Fri Nov 14 13:17:55 2014
@@ -610,7 +610,7 @@ static const svn_diff_output_fns_t mem_o
svn_error_t *
-svn_diff_mem_string_output_unified2(svn_stream_t *output_stream,
+svn_diff_mem_string_output_unified3(svn_stream_t *output_stream,
svn_diff_t *diff,
svn_boolean_t with_diff_header,
const char *hunk_delimiter,
@@ -619,6 +619,9 @@ svn_diff_mem_string_output_unified2(svn_
const char *header_encoding,
const svn_string_t *original,
const svn_string_t *modified,
+ int context_size,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool)
{
@@ -636,7 +639,8 @@ svn_diff_mem_string_output_unified2(svn_
= (hunk_delimiter == NULL || strcmp(hunk_delimiter, "##") != 0)
? APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_FILE APR_EOL_STR
: APR_EOL_STR SVN_DIFF__NO_NEWLINE_AT_END_OF_PROPERTY APR_EOL_STR;
- baton.context_size = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+ baton.context_size = context_size >= 0 ? context_size
+ : SVN_DIFF__UNIFIED_CONTEXT_SIZE;
SVN_ERR(svn_utf_cstring_from_utf8_ex2
(&(baton.prefix_str[unified_output_context]), " ",
@@ -658,8 +662,9 @@ svn_diff_mem_string_output_unified2(svn_
original_header, modified_header, pool));
}
- SVN_ERR(svn_diff_output(diff, &baton,
- &mem_output_unified_vtable));
+ SVN_ERR(svn_diff_output2(diff, &baton,
+ &mem_output_unified_vtable,
+ cancel_func, cancel_baton));
SVN_ERR(output_unified_flush_hunk(&baton, hunk_delimiter));
@@ -669,28 +674,6 @@ svn_diff_mem_string_output_unified2(svn_
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_diff_mem_string_output_unified(svn_stream_t *output_stream,
- svn_diff_t *diff,
- const char *original_header,
- const char *modified_header,
- const char *header_encoding,
- const svn_string_t *original,
- const svn_string_t *modified,
- apr_pool_t *pool)
-{
- SVN_ERR(svn_diff_mem_string_output_unified2(output_stream,
- diff,
- TRUE,
- NULL,
- original_header,
- modified_header,
- header_encoding,
- original,
- modified,
- pool));
- return SVN_NO_ERROR;
-}
@@ -739,6 +722,10 @@ typedef struct merge_output_baton_t
svn_diff_conflict_display_style_t conflict_style;
int context_size;
+ /* cancel support */
+ svn_cancel_func_t cancel_func;
+ void *cancel_baton;
+
/* The rest of the fields are for
svn_diff_conflict_display_only_conflicts only. Note that for
these batons, OUTPUT_STREAM is either CONTEXT_SAVER->STREAM or
@@ -923,7 +910,8 @@ output_conflict(void *baton,
if (style == svn_diff_conflict_display_resolved_modified_latest)
{
if (diff)
- return svn_diff_output(diff, baton, &merge_output_vtable);
+ return svn_diff_output2(diff, baton, &merge_output_vtable,
+ btn->cancel_func, btn->cancel_baton);
else
style = svn_diff_conflict_display_modified_latest;
}
@@ -1066,7 +1054,7 @@ detect_eol(svn_string_t *token)
}
svn_error_t *
-svn_diff_mem_string_output_merge2(svn_stream_t *output_stream,
+svn_diff_mem_string_output_merge3(svn_stream_t *output_stream,
svn_diff_t *diff,
const svn_string_t *original,
const svn_string_t *modified,
@@ -1076,6 +1064,8 @@ svn_diff_mem_string_output_merge2(svn_st
const char *conflict_latest,
const char *conflict_separator,
svn_diff_conflict_display_style_t style,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool)
{
merge_output_baton_t btn;
@@ -1113,6 +1103,8 @@ svn_diff_mem_string_output_merge2(svn_st
eol = APR_EOL_STR; /* use the platform default */
btn.marker_eol = eol;
+ btn.cancel_func = cancel_func;
+ btn.cancel_baton = cancel_baton;
SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[1],
conflict_modified
@@ -1135,45 +1127,9 @@ svn_diff_mem_string_output_merge2(svn_st
: ">>>>>>> (latest)",
pool));
- SVN_ERR(svn_diff_output(diff, &btn, vtable));
+ SVN_ERR(svn_diff_output2(diff, &btn, vtable, cancel_func, cancel_baton));
if (conflicts_only)
svn_pool_destroy(btn.pool);
return SVN_NO_ERROR;
}
-
-svn_error_t *
-svn_diff_mem_string_output_merge(svn_stream_t *output_stream,
- svn_diff_t *diff,
- const svn_string_t *original,
- const svn_string_t *modified,
- const svn_string_t *latest,
- const char *conflict_original,
- const char *conflict_modified,
- const char *conflict_latest,
- const char *conflict_separator,
- svn_boolean_t display_original_in_conflict,
- svn_boolean_t display_resolved_conflicts,
- apr_pool_t *pool)
-{
- svn_diff_conflict_display_style_t style =
- svn_diff_conflict_display_modified_latest;
-
- if (display_resolved_conflicts)
- style = svn_diff_conflict_display_resolved_modified_latest;
-
- if (display_original_in_conflict)
- style = svn_diff_conflict_display_modified_original_latest;
-
- return svn_diff_mem_string_output_merge2(output_stream,
- diff,
- original,
- modified,
- latest,
- conflict_original,
- conflict_modified,
- conflict_latest,
- conflict_separator,
- style,
- pool);
-}
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_diff/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_diff/util.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_diff/util.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_diff/util.c Fri Nov 14 13:17:55 2014
@@ -516,6 +516,9 @@ svn_diff__display_prop_diffs(svn_stream_
const apr_array_header_t *propchanges,
apr_hash_t *original_props,
svn_boolean_t pretty_print_mergeinfo,
+ int context_size,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *scratch_pool)
{
apr_pool_t *pool = scratch_pool;
@@ -600,9 +603,10 @@ svn_diff__display_prop_diffs(svn_stream_
* UNIX patch could apply the property diff to, so we use "##"
* instead of "@@" as the default hunk delimiter for property diffs.
* We also suppress the diff header. */
- SVN_ERR(svn_diff_mem_string_output_unified2(
+ SVN_ERR(svn_diff_mem_string_output_unified3(
outstream, diff, FALSE /* no header */, "##", NULL, NULL,
- encoding, orig, val, iterpool));
+ encoding, orig, val, context_size,
+ cancel_func, cancel_baton, iterpool));
}
}
svn_pool_destroy(iterpool);
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs/editor.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs/editor.c Fri Nov 14 13:17:55 2014
@@ -63,8 +63,6 @@ struct edit_baton {
};
#define FSPATH(relpath, pool) apr_pstrcat(pool, "/", relpath, SVN_VA_NULL)
-#define UNUSED(x) ((void)(x))
-
static svn_error_t *
get_root(svn_fs_root_t **root,
@@ -522,7 +520,8 @@ alter_symlink_cb(void *baton,
{
struct edit_baton *eb = baton;
- UNUSED(eb); SVN__NOT_IMPLEMENTED();
+ SVN_UNUSED(eb);
+ SVN__NOT_IMPLEMENTED();
}
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs/fs-loader.c Fri Nov 14 13:17:55 2014
@@ -393,7 +393,7 @@ synchronized_initialize(void *baton, apr
{
common_pool = svn_pool_create(pool);
base_defn.next = NULL;
- SVN_ERR(svn_mutex__init(&common_pool_lock, TRUE, TRUE, common_pool));
+ SVN_ERR(svn_mutex__init(&common_pool_lock, TRUE, common_pool));
/* ### This won't work if POOL is NULL and libsvn_fs is loaded as a DSO
### (via libsvn_ra_local say) since the global common_pool will live
@@ -558,6 +558,13 @@ svn_fs_upgrade2(const char *path,
return SVN_NO_ERROR;
}
+/* A warning handling function that does not abort on errors,
+ but just lets them be returned normally. */
+static void
+verify_fs_warning_func(void *baton, svn_error_t *err)
+{
+}
+
svn_error_t *
svn_fs_verify(const char *path,
apr_hash_t *fs_config,
@@ -574,6 +581,7 @@ svn_fs_verify(const char *path,
SVN_ERR(fs_library_vtable(&vtable, path, pool));
fs = fs_new(fs_config, pool);
+ svn_fs_set_warning_func(fs, verify_fs_warning_func, NULL);
SVN_ERR(vtable->verify_fs(fs, path, start, end,
notify_func, notify_baton,
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/changes-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/changes-table.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/changes-table.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/changes-table.c Fri Nov 14 13:17:55 2014
@@ -121,12 +121,32 @@ svn_fs_bdb__changes_delete(svn_fs_t *fs,
return SVN_NO_ERROR;
}
+/* Return a deep FS API type copy of SOURCE in internal format and allocate
+ * the result in RESULT_POOL.
+ */
+static svn_fs_path_change2_t *
+change_to_fs_change(const change_t *change,
+ apr_pool_t *result_pool)
+{
+ svn_fs_path_change2_t *result = svn_fs__path_change_create_internal(
+ svn_fs_base__id_copy(change->noderev_id,
+ result_pool),
+ change->kind,
+ result_pool);
+ result->text_mod = change->text_mod;
+ result->prop_mod = change->prop_mod;
+ result->node_kind = svn_node_unknown;
+ result->copyfrom_known = FALSE;
+
+ return result;
+}
/* Merge the internal-use-only CHANGE into a hash of public-FS
svn_fs_path_change2_t CHANGES, collapsing multiple changes into a
single succinct change per path. */
static svn_error_t *
fold_change(apr_hash_t *changes,
+ apr_hash_t *deletions,
const change_t *change)
{
apr_pool_t *pool = apr_hash_pool_get(changes);
@@ -185,7 +205,7 @@ fold_change(apr_hash_t *changes,
case svn_fs_path_change_reset:
/* A reset here will simply remove the path change from the
hash. */
- old_change = NULL;
+ new_change = NULL;
break;
case svn_fs_path_change_delete:
@@ -194,14 +214,21 @@ fold_change(apr_hash_t *changes,
/* If the path was introduced in this transaction via an
add, and we are deleting it, just remove the path
altogether. */
- old_change = NULL;
+ new_change = NULL;
+ }
+ else if (old_change->change_kind == svn_fs_path_change_replace)
+ {
+ /* A deleting a 'replace' restore the original deletion. */
+ new_change = svn_hash_gets(deletions, path);
+ SVN_ERR_ASSERT(new_change);
}
else
{
/* A deletion overrules all previous changes. */
- old_change->change_kind = svn_fs_path_change_delete;
- old_change->text_mod = change->text_mod;
- old_change->prop_mod = change->prop_mod;
+ new_change = old_change;
+ new_change->change_kind = svn_fs_path_change_delete;
+ new_change->text_mod = change->text_mod;
+ new_change->prop_mod = change->prop_mod;
}
break;
@@ -209,38 +236,33 @@ fold_change(apr_hash_t *changes,
case svn_fs_path_change_replace:
/* An add at this point must be following a previous delete,
so treat it just like a replace. */
- old_change->change_kind = svn_fs_path_change_replace;
- old_change->node_rev_id = svn_fs_base__id_copy(change->noderev_id,
- pool);
- old_change->text_mod = change->text_mod;
- old_change->prop_mod = change->prop_mod;
+
+ new_change = change_to_fs_change(change, pool);
+ new_change->change_kind = svn_fs_path_change_replace;
+
+ /* Remember the original deletion.
+ * Make sure to allocate the hash key in a durable pool. */
+ svn_hash_sets(deletions,
+ apr_pstrdup(apr_hash_pool_get(deletions), path),
+ old_change);
break;
case svn_fs_path_change_modify:
default:
+ new_change = old_change;
if (change->text_mod)
- old_change->text_mod = TRUE;
+ new_change->text_mod = TRUE;
if (change->prop_mod)
- old_change->prop_mod = TRUE;
+ new_change->prop_mod = TRUE;
break;
}
-
- /* Point our new_change to our (possibly modified) old_change. */
- new_change = old_change;
}
else
{
/* This change is new to the hash, so make a new public change
structure from the internal one (in the hash's pool), and dup
the path into the hash's pool, too. */
- new_change = svn_fs__path_change_create_internal(
- svn_fs_base__id_copy(change->noderev_id, pool),
- change->kind,
- pool);
- new_change->text_mod = change->text_mod;
- new_change->prop_mod = change->prop_mod;
- new_change->node_kind = svn_node_unknown;
- new_change->copyfrom_known = FALSE;
+ new_change = change_to_fs_change(change, pool);
path = apr_pstrdup(pool, change->path);
}
@@ -265,6 +287,8 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
svn_error_t *err = SVN_NO_ERROR;
apr_hash_t *changes = apr_hash_make(pool);
apr_pool_t *subpool = svn_pool_create(pool);
+ apr_pool_t *iterpool = svn_pool_create(pool);
+ apr_hash_t *deletions = apr_hash_make(subpool);
/* Get a cursor on the first record matching KEY, and then loop over
the records, adding them to the return array. */
@@ -286,11 +310,11 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
svn_skel_t *result_skel;
/* Clear the per-iteration subpool. */
- svn_pool_clear(subpool);
+ svn_pool_clear(iterpool);
/* RESULT now contains a change record associated with KEY. We
need to parse that skel into an change_t structure ... */
- result_skel = svn_skel__parse(result.data, result.size, subpool);
+ result_skel = svn_skel__parse(result.data, result.size, iterpool);
if (! result_skel)
{
err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
@@ -298,12 +322,12 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
key);
goto cleanup;
}
- err = svn_fs_base__parse_change_skel(&change, result_skel, subpool);
+ err = svn_fs_base__parse_change_skel(&change, result_skel, iterpool);
if (err)
goto cleanup;
/* ... and merge it with our return hash. */
- err = fold_change(changes, change);
+ err = fold_change(changes, deletions, change);
if (err)
goto cleanup;
@@ -319,7 +343,7 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
{
apr_hash_index_t *hi;
- for (hi = apr_hash_first(subpool, changes);
+ for (hi = apr_hash_first(iterpool, changes);
hi;
hi = apr_hash_next(hi))
{
@@ -347,6 +371,7 @@ svn_fs_bdb__changes_fetch(apr_hash_t **c
}
/* Destroy the per-iteration subpool. */
+ svn_pool_destroy(iterpool);
svn_pool_destroy(subpool);
/* If there are no (more) change records for this KEY, we're
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/env.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/env.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/env.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/bdb/env.c Fri Nov 14 13:17:55 2014
@@ -380,7 +380,7 @@ bdb_init_cb(void *baton, apr_pool_t *poo
bdb_cache_pool = svn_pool_create(pool);
bdb_cache = apr_hash_make(bdb_cache_pool);
- SVN_ERR(svn_mutex__init(&bdb_cache_lock, TRUE, TRUE, bdb_cache_pool));
+ SVN_ERR(svn_mutex__init(&bdb_cache_lock, TRUE, bdb_cache_pool));
apr_pool_cleanup_register(bdb_cache_pool, NULL, clear_cache,
apr_pool_cleanup_null);
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_base/fs.c Fri Nov 14 13:17:55 2014
@@ -1084,7 +1084,7 @@ svn_fs_base__clean_logs(const char *live
{ /* Process unused logs from live area */
int idx;
- apr_pool_t *sub_pool = svn_pool_create(pool);
+ apr_pool_t *subpool = svn_pool_create(pool);
/* Process log files. */
for (idx = 0; idx < logfiles->nelts; idx++)
@@ -1093,9 +1093,9 @@ svn_fs_base__clean_logs(const char *live
const char *live_log_path;
const char *backup_log_path;
- svn_pool_clear(sub_pool);
- live_log_path = svn_dirent_join(live_path, log_file, sub_pool);
- backup_log_path = svn_dirent_join(backup_path, log_file, sub_pool);
+ svn_pool_clear(subpool);
+ live_log_path = svn_dirent_join(live_path, log_file, subpool);
+ backup_log_path = svn_dirent_join(backup_path, log_file, subpool);
{ /* Compare files. No point in using MD5 and wasting CPU cycles as we
got full copies of both logs */
@@ -1112,17 +1112,17 @@ svn_fs_base__clean_logs(const char *live
SVN_ERR(svn_io_files_contents_same_p(&files_match,
live_log_path,
backup_log_path,
- sub_pool));
+ subpool));
/* If log files do not match, go to the next log file. */
if (!files_match)
continue;
}
- SVN_ERR(svn_io_remove_file2(live_log_path, FALSE, sub_pool));
+ SVN_ERR(svn_io_remove_file2(live_log_path, FALSE, subpool));
}
- svn_pool_destroy(sub_pool);
+ svn_pool_destroy(subpool);
}
return SVN_NO_ERROR;
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=1639628&r1=1639627&r2=1639628&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 Fri Nov 14 13:17:55 2014
@@ -74,7 +74,7 @@ dbg_log_access(svn_fs_t *fs,
svn_revnum_t revision,
apr_uint64_t item_index,
void *item,
- int item_type,
+ apr_uint32_t item_type,
apr_pool_t *scratch_pool)
{
/* no-op if this macro is not defined */
@@ -154,7 +154,7 @@ dbg_log_access(svn_fs_t *fs,
}
/* some info is only available in format7 repos */
- if (svn_fs_fs__use_log_addressing(fs, revision))
+ if (svn_fs_fs__use_log_addressing(fs))
{
/* reverse index lookup: get item description in ENTRY */
SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file, revision,
@@ -284,8 +284,7 @@ use_block_read(svn_fs_t *fs,
svn_revnum_t revision)
{
fs_fs_data_t *ffd = fs->fsap_data;
- return svn_fs_fs__use_log_addressing(fs, revision)
- && ffd->use_block_read;
+ return svn_fs_fs__use_log_addressing(fs) && ffd->use_block_read;
}
/* Get the node-revision for the node ID in FS.
@@ -552,7 +551,7 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
fs_fs_data_t *ffd = fs->fsap_data;
SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, scratch_pool));
- if (svn_fs_fs__use_log_addressing(fs, rev))
+ if (svn_fs_fs__use_log_addressing(fs))
{
*root_id_p = svn_fs_fs__id_create_root(rev, result_pool);
}
@@ -922,7 +921,7 @@ svn_fs_fs__check_rep(representation_t *r
void **hint,
apr_pool_t *scratch_pool)
{
- if (svn_fs_fs__use_log_addressing(fs, rep->revision))
+ if (svn_fs_fs__use_log_addressing(fs))
{
apr_off_t offset;
svn_fs_fs__p2l_entry_t *entry;
@@ -937,8 +936,9 @@ svn_fs_fs__check_rep(representation_t *r
/* 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). */
- SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file, rep->revision,
- offset, scratch_pool));
+ SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file,
+ rep->revision, offset,
+ scratch_pool, scratch_pool));
if ( entry == NULL
|| entry->type < SVN_FS_FS__ITEM_TYPE_FILE_REP
@@ -978,7 +978,7 @@ svn_fs_fs__rep_chain_length(int *chain_l
svn_revnum_t shard_size = ffd->max_files_per_dir
? ffd->max_files_per_dir
: 1;
- apr_pool_t *sub_pool = svn_pool_create(scratch_pool);
+ apr_pool_t *subpool = svn_pool_create(scratch_pool);
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
svn_boolean_t is_delta = FALSE;
int count = 0;
@@ -1014,7 +1014,7 @@ svn_fs_fs__rep_chain_length(int *chain_l
&file_hint,
&base_rep,
fs,
- sub_pool,
+ subpool,
iterpool));
base_rep.revision = header->base_revision;
@@ -1023,18 +1023,28 @@ svn_fs_fs__rep_chain_length(int *chain_l
svn_fs_fs__id_txn_reset(&base_rep.txn_id);
is_delta = header->type == svn_fs_fs__rep_delta;
+ /* Clear it the SUBPOOL once in a while. Doing it too frequently
+ * renders the FILE_HINT ineffective. Doing too infrequently, may
+ * leave us with too many open file handles.
+ *
+ * Note that this is mostly about efficiency, with larger values
+ * being more efficient, and any non-zero value is legal here. When
+ * reading deltified contents, we may keep 10s of rev files open at
+ * the same time and the system has to cope with that. Thus, the
+ * limit of 16 chosen below is in the same ballpark.
+ */
++count;
if (count % 16 == 0)
{
file_hint = NULL;
- svn_pool_clear(sub_pool);
+ svn_pool_clear(subpool);
}
}
while (is_delta && base_rep.revision);
*chain_length = count;
*shard_count = shards;
- svn_pool_destroy(sub_pool);
+ svn_pool_destroy(subpool);
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
@@ -2393,7 +2403,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, result_pool);
+ SVN_ERR(svn_fs_fs__id_parse(&dirent->id, 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.
@@ -2710,7 +2720,7 @@ svn_fs_fs__get_changes(apr_array_header_
{
/* Addressing is very different for old formats
* (needs to read the revision trailer). */
- if (svn_fs_fs__use_log_addressing(fs, rev))
+ if (svn_fs_fs__use_log_addressing(fs))
SVN_ERR(svn_fs_fs__item_offset(&changes_offset, fs,
revision_file, rev, NULL,
SVN_FS_FS__ITEM_INDEX_CHANGES,
@@ -3251,7 +3261,8 @@ block_read(void **result,
block_start = offset - (offset % ffd->block_size);
SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, revision_file,
revision, block_start,
- ffd->block_size, scratch_pool));
+ ffd->block_size, scratch_pool,
+ scratch_pool));
SVN_ERR(aligned_seek(fs, revision_file->file, &block_start, offset,
iterpool));
@@ -3286,7 +3297,7 @@ block_read(void **result,
&& entry->size < ffd->block_size))
{
void *item = NULL;
- SVN_ERR(svn_io_file_seek(revision_file->file, SEEK_SET,
+ SVN_ERR(svn_io_file_seek(revision_file->file, APR_SET,
&entry->offset, iterpool));
switch (entry->type)
{
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/caching.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/caching.c Fri Nov 14 13:17:55 2014
@@ -66,9 +66,8 @@ normalize_key_part(const char *original,
return normalized->data;
}
-/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS and *CACHE_REVPROPS flags will be set
- according to FS->CONFIG. *CACHE_NAMESPACE receives the cache prefix
- to use.
+/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS flags will be set according to
+ FS->CONFIG. *CACHE_NAMESPACE receives the cache prefix to use.
Use FS->pool for allocating the memcache and CACHE_NAMESPACE, and POOL
for temporary allocations. */
@@ -76,7 +75,6 @@ static svn_error_t *
read_config(const char **cache_namespace,
svn_boolean_t *cache_txdeltas,
svn_boolean_t *cache_fulltexts,
- svn_boolean_t *cache_revprops,
svn_fs_t *fs,
apr_pool_t *pool)
{
@@ -119,24 +117,6 @@ read_config(const char **cache_namespace
SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
TRUE);
- /* don't cache revprops by default.
- * Revprop caching significantly speeds up operations like
- * svn ls -v. However, it requires synchronization that may
- * not be available or efficient in the current server setup.
- *
- * If the caller chose option "2", enable revprop caching if
- * the required API support is there to make it efficient.
- */
- if (strcmp(svn_hash__get_cstring(fs->config,
- SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
- ""), "2"))
- *cache_revprops
- = svn_hash__get_bool(fs->config,
- SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
- FALSE);
- else
- *cache_revprops = svn_named_atomic__is_efficient();
-
return SVN_NO_ERROR;
}
@@ -368,14 +348,12 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
svn_boolean_t no_handler = ffd->fail_stop;
svn_boolean_t cache_txdeltas;
svn_boolean_t cache_fulltexts;
- svn_boolean_t cache_revprops;
const char *cache_namespace;
/* Evaluating the cache configuration. */
SVN_ERR(read_config(&cache_namespace,
&cache_txdeltas,
&cache_fulltexts,
- &cache_revprops,
fs,
pool));
@@ -581,28 +559,6 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
ffd->mergeinfo_existence_cache = NULL;
}
- /* if enabled, cache revprops */
- if (cache_revprops)
- {
- SVN_ERR(create_cache(&(ffd->revprop_cache),
- NULL,
- membuffer,
- 0, 0, /* Do not use inprocess cache */
- svn_fs_fs__serialize_properties,
- svn_fs_fs__deserialize_properties,
- sizeof(pair_cache_key_t),
- apr_pstrcat(pool, prefix, "REVPROP",
- SVN_VA_NULL),
- SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
- fs,
- no_handler,
- fs->pool, pool));
- }
- else
- {
- ffd->revprop_cache = NULL;
- }
-
/* if enabled, cache text deltas and their combinations */
if (cache_txdeltas)
{
@@ -654,70 +610,60 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
ffd->combined_window_cache = NULL;
}
- if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
- {
- SVN_ERR(create_cache(&(ffd->l2p_header_cache),
- NULL,
- membuffer,
- 64, 16, /* entry size varies but we must cover
- a reasonable number of revisions (1k) */
- svn_fs_fs__serialize_l2p_header,
- svn_fs_fs__deserialize_l2p_header,
- sizeof(pair_cache_key_t),
- apr_pstrcat(pool, prefix, "L2P_HEADER",
- (char *)NULL),
- SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
- fs,
- no_handler,
- fs->pool, pool));
- SVN_ERR(create_cache(&(ffd->l2p_page_cache),
- NULL,
- membuffer,
- 64, 16, /* entry size varies but we must cover
- a reasonable number of revisions (1k) */
- svn_fs_fs__serialize_l2p_page,
- svn_fs_fs__deserialize_l2p_page,
- sizeof(svn_fs_fs__page_cache_key_t),
- apr_pstrcat(pool, prefix, "L2P_PAGE",
- (char *)NULL),
- SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
- fs,
- no_handler,
- fs->pool, pool));
- SVN_ERR(create_cache(&(ffd->p2l_header_cache),
- NULL,
- membuffer,
- 4, 1, /* Large entries. Rarely used. */
- svn_fs_fs__serialize_p2l_header,
- svn_fs_fs__deserialize_p2l_header,
- sizeof(pair_cache_key_t),
- apr_pstrcat(pool, prefix, "P2L_HEADER",
- (char *)NULL),
- SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
- fs,
- no_handler,
- fs->pool, pool));
- SVN_ERR(create_cache(&(ffd->p2l_page_cache),
- NULL,
- membuffer,
- 4, 16, /* Variably sized entries. Rarely used. */
- svn_fs_fs__serialize_p2l_page,
- svn_fs_fs__deserialize_p2l_page,
- sizeof(svn_fs_fs__page_cache_key_t),
- apr_pstrcat(pool, prefix, "P2L_PAGE",
- (char *)NULL),
- SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
- fs,
- no_handler,
- fs->pool, pool));
- }
- else
- {
- ffd->l2p_header_cache = NULL;
- ffd->l2p_page_cache = NULL;
- ffd->p2l_header_cache = NULL;
- ffd->p2l_page_cache = NULL;
- }
+ SVN_ERR(create_cache(&(ffd->l2p_header_cache),
+ NULL,
+ membuffer,
+ 64, 16, /* entry size varies but we must cover
+ a reasonable number of revisions (1k) */
+ svn_fs_fs__serialize_l2p_header,
+ svn_fs_fs__deserialize_l2p_header,
+ sizeof(pair_cache_key_t),
+ apr_pstrcat(pool, prefix, "L2P_HEADER",
+ (char *)NULL),
+ SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ fs,
+ no_handler,
+ fs->pool, pool));
+ SVN_ERR(create_cache(&(ffd->l2p_page_cache),
+ NULL,
+ membuffer,
+ 64, 16, /* entry size varies but we must cover
+ a reasonable number of revisions (1k) */
+ svn_fs_fs__serialize_l2p_page,
+ svn_fs_fs__deserialize_l2p_page,
+ sizeof(svn_fs_fs__page_cache_key_t),
+ apr_pstrcat(pool, prefix, "L2P_PAGE",
+ (char *)NULL),
+ SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ fs,
+ no_handler,
+ fs->pool, pool));
+ SVN_ERR(create_cache(&(ffd->p2l_header_cache),
+ NULL,
+ membuffer,
+ 4, 1, /* Large entries. Rarely used. */
+ svn_fs_fs__serialize_p2l_header,
+ svn_fs_fs__deserialize_p2l_header,
+ sizeof(pair_cache_key_t),
+ apr_pstrcat(pool, prefix, "P2L_HEADER",
+ (char *)NULL),
+ SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ fs,
+ no_handler,
+ fs->pool, pool));
+ SVN_ERR(create_cache(&(ffd->p2l_page_cache),
+ NULL,
+ membuffer,
+ 4, 16, /* Variably sized entries. Rarely used. */
+ svn_fs_fs__serialize_p2l_page,
+ svn_fs_fs__deserialize_p2l_page,
+ sizeof(svn_fs_fs__page_cache_key_t),
+ apr_pstrcat(pool, prefix, "P2L_PAGE",
+ (char *)NULL),
+ SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ fs,
+ no_handler,
+ fs->pool, pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs.c Fri Nov 14 13:17:55 2014
@@ -44,6 +44,7 @@
#include "rep-cache.h"
#include "revprops.h"
#include "transaction.h"
+#include "util.h"
#include "verify.h"
#include "svn_private_config.h"
#include "private/svn_fs_util.h"
@@ -73,11 +74,28 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
svn_fs_initialize pool. It's unlikely that anyone will notice
the modest expenditure; the alternative is to allocate each structure
in a subpool, add a reference-count, and add a serialized destructor
- to the FS vtable. That's more machinery than it's worth. */
+ to the FS vtable. That's more machinery than it's worth.
+
+ Picking an appropriate key for the shared data is tricky, because,
+ unfortunately, a filesystem UUID is not really unique. It is implicitly
+ shared between hotcopied (1), dump / loaded (2) or naively copied (3)
+ filesystems. We tackle this problem by using a combination of the UUID
+ and an instance ID as the key. This allows us to avoid key clashing
+ in (1) and (2) for formats >= SVN_FS_FS__MIN_INSTANCE_ID_FORMAT, which
+ do support instance IDs. For old formats the shared data (locks, shared
+ transaction data, ...) will still clash.
+
+ Speaking of (3), there is not so much we can do about it, except maybe
+ provide a convenient way of fixing things. Naively copied filesystems
+ have identical filesystem UUIDs *and* instance IDs. With the key being
+ a combination of these two, clashes can be fixed by changing either of
+ them (or both), e.g. with svn_fs_set_uuid(). */
SVN_ERR_ASSERT(fs->uuid);
- key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX, fs->uuid,
- SVN_VA_NULL);
+ SVN_ERR_ASSERT(ffd->instance_id);
+
+ key = apr_pstrcat(pool, SVN_FSFS_SHARED_USERDATA_PREFIX,
+ fs->uuid, ":", ffd->instance_id, SVN_VA_NULL);
status = apr_pool_userdata_get(&val, key, common_pool);
if (status)
return svn_error_wrap_apr(status, _("Can't fetch FSFS shared data"));
@@ -92,21 +110,19 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
intra-process synchronization when grabbing the repository write
lock. */
SVN_ERR(svn_mutex__init(&ffsd->fs_write_lock,
- TRUE, TRUE, common_pool));
+ SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
/* ... the pack lock ... */
SVN_ERR(svn_mutex__init(&ffsd->fs_pack_lock,
- TRUE, TRUE, common_pool));
+ SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
/* ... not to mention locking the txn-current file. */
SVN_ERR(svn_mutex__init(&ffsd->txn_current_lock,
- TRUE, TRUE, common_pool));
+ SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
/* We also need a mutex for synchronizing access to the active
- transaction list and free transaction pointer. This one is
- enabled unconditionally. */
- SVN_ERR(svn_mutex__init(&ffsd->txn_list_lock,
- TRUE, TRUE, common_pool));
+ transaction list and free transaction pointer. */
+ SVN_ERR(svn_mutex__init(&ffsd->txn_list_lock, TRUE, common_pool));
key = apr_pstrdup(common_pool, key);
status = apr_pool_userdata_set(ffsd, key, NULL, common_pool);
@@ -202,6 +218,18 @@ fs_info(const void **fsfs_info,
return SVN_NO_ERROR;
}
+/* Wrapper around svn_fs_fs__set_uuid() adapting between function
+ signatures. */
+static svn_error_t *
+fs_set_uuid(svn_fs_t *fs,
+ const char *uuid,
+ apr_pool_t *pool)
+{
+ /* Whenever we set a new UUID, imply that FS will also be a different
+ * instance (on formats that support this). */
+ return svn_error_trace(svn_fs_fs__set_uuid(fs, uuid, NULL, pool));
+}
+
/* The vtable associated with a specific open filesystem. */
@@ -210,7 +238,7 @@ static fs_vtable_t fs_vtable = {
svn_fs_fs__revision_prop,
svn_fs_fs__get_revision_proplist,
svn_fs_fs__change_rev_prop,
- svn_fs_fs__set_uuid,
+ fs_set_uuid,
svn_fs_fs__revision_root,
svn_fs_fs__begin_txn,
svn_fs_fs__open_txn,
@@ -238,13 +266,22 @@ static svn_error_t *
initialize_fs_struct(svn_fs_t *fs)
{
fs_fs_data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd));
- ffd->min_log_addressing_rev = SVN_INVALID_REVNUM;
+ ffd->use_log_addressing = FALSE;
fs->vtable = &fs_vtable;
fs->fsap_data = ffd;
return SVN_NO_ERROR;
}
+/* Reset vtable and fsap_data fields in FS such that the FS is basically
+ * closed now. Note that FS must not hold locks when you call this. */
+static void
+uninitialize_fs_struct(svn_fs_t *fs)
+{
+ fs->vtable = NULL;
+ fs->fsap_data = NULL;
+}
+
/* This implements the fs_library_vtable_t.create() API. Create a new
fsfs-backed Subversion filesystem at path PATH and link it into
*FS. Perform temporary allocations in POOL, and fs-global allocations
@@ -312,20 +349,53 @@ fs_open_for_recovery(svn_fs_t *fs,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
+ svn_error_t * err;
+ svn_revnum_t youngest_rev;
+ apr_pool_t * subpool = svn_pool_create(pool);
+
/* Recovery for FSFS is currently limited to recreating the 'current'
file from the latest revision. */
/* The only thing we have to watch out for is that the 'current' file
- might not exist. So we'll try to create it here unconditionally,
- and just ignore any errors that might indicate that it's already
- present. (We'll need it to exist later anyway as a source for the
- new file's permissions). */
+ might not exist or contain garbage. So we'll try to read it here
+ and provide or replace the existing file if we couldn't read it.
+ (We'll also need it to exist later anyway as a source for the new
+ file's permissions). */
- /* Use a partly-filled fs pointer first to create 'current'. This will fail
- if 'current' already exists, but we don't care about that. */
+ /* Use a partly-filled fs pointer first to create 'current'. */
fs->path = apr_pstrdup(fs->pool, path);
- svn_error_clear(svn_io_file_create(svn_fs_fs__path_current(fs, pool),
- "0 1 1\n", pool));
+
+ SVN_ERR(initialize_fs_struct(fs));
+
+ /* Figure out the repo format and check that we can even handle it. */
+ SVN_ERR(svn_fs_fs__read_format_file(fs, subpool));
+
+ /* Now, read 'current' and try to patch it if necessary. */
+ err = svn_fs_fs__youngest_rev(&youngest_rev, fs, subpool);
+ if (err)
+ {
+ const char *file_path;
+
+ /* 'current' file is missing or contains garbage. Since we are trying
+ * to recover from whatever problem there is, being picky about the
+ * error code here won't do us much good. If there is a persistent
+ * problem that we can't fix, it will show up when we try rewrite the
+ * file a few lines further below and we will report the failure back
+ * to the caller.
+ *
+ * Start recovery with HEAD = 0. */
+ svn_error_clear(err);
+ file_path = svn_fs_fs__path_current(fs, subpool);
+
+ /* Best effort to ensure the file exists and is valid.
+ * This may fail for r/o filesystems etc. */
+ SVN_ERR(svn_io_remove_file2(file_path, TRUE, subpool));
+ SVN_ERR(svn_io_file_create_empty(file_path, subpool));
+ SVN_ERR(svn_fs_fs__write_current(fs, 0, 1, 1, subpool));
+ }
+
+ uninitialize_fs_struct(fs);
+ svn_pool_destroy(subpool);
/* Now open the filesystem properly by calling the vtable method directly. */
return fs_open(fs, path, common_pool_lock, pool, common_pool);
@@ -413,11 +483,13 @@ fs_hotcopy(svn_fs_t *src_fs,
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
- /* Provide FFD for DST_FS, test / initialize target repo, remove FFD. */
+ /* Test target repo when in INCREMENTAL mode, initialize it when not.
+ * For this, we need our FS internal data structures to be temporarily
+ * available. */
SVN_ERR(initialize_fs_struct(dst_fs));
SVN_ERR(svn_fs_fs__hotcopy_prepare_target(src_fs, dst_fs, dst_path,
incremental, pool));
- dst_fs->fsap_data = NULL;
+ uninitialize_fs_struct(dst_fs);
/* Now, the destination repo should open just fine. */
SVN_ERR(fs_open(dst_fs, dst_path, common_pool_lock, pool, common_pool));
@@ -458,7 +530,7 @@ fs_delete_fs(const char *path,
apr_pool_t *pool)
{
/* Remove everything. */
- return svn_io_remove_dir2(path, FALSE, NULL, NULL, pool);
+ return svn_error_trace(svn_io_remove_dir2(path, FALSE, NULL, NULL, pool));
}
static const svn_version_t *
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=1639628&r1=1639627&r2=1639628&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 Fri Nov 14 13:17:55 2014
@@ -36,7 +36,6 @@
#include "private/svn_fs_private.h"
#include "private/svn_sqlite.h"
#include "private/svn_mutex.h"
-#include "private/svn_named_atomic.h"
#include "id.h"
@@ -58,7 +57,8 @@ extern "C" {
#define PATH_PACK_LOCK_FILE "pack-lock" /* Pack lock file */
#define PATH_REVS_DIR "revs" /* Directory of revisions */
#define PATH_REVPROPS_DIR "revprops" /* Directory of revprops */
-#define PATH_TXNS_DIR "transactions" /* Directory of transactions */
+#define PATH_TXNS_DIR "transactions" /* Directory of transactions in
+ repos w/o log addressing */
#define PATH_NODE_ORIGINS_DIR "node-origins" /* Lazy node-origin cache */
#define PATH_TXN_PROTOS_DIR "txn-protorevs" /* Directory of proto-revs */
#define PATH_TXN_CURRENT "txn-current" /* File with next txn key */
@@ -177,11 +177,24 @@ extern "C" {
#define SVN_FS_FS__MIN_PACK_LOCK_FORMAT 7
/* Minimum format number that stores mergeinfo-mode flag in changed paths */
-#define SVN_FS_FS__MIN_MERGEINFO_IN_CHANGES_FORMAT 7
+#define SVN_FS_FS__MIN_MERGEINFO_IN_CHANGED_FORMAT 7
+
+/* Minimum format number that supports per-instance filesystem IDs. */
+#define SVN_FS_FS__MIN_INSTANCE_ID_FORMAT 7
/* The minimum format number that supports a configuration file (fsfs.conf) */
#define SVN_FS_FS__MIN_CONFIG_FILE 4
+/* On most operating systems apr implements file locks per process, not
+ per file. On Windows apr implements the locking as per file handle
+ locks, so we don't have to add our own mutex for just in-process
+ synchronization. */
+#if APR_HAS_THREADS && !defined(WIN32)
+#define SVN_FS_FS__USE_LOCK_MUTEX 1
+#else
+#define SVN_FS_FS__USE_LOCK_MUTEX 0
+#endif
+
/* Private FSFS-specific data shared between all svn_txn_t objects that
relate to a particular transaction in a filesystem (as identified
by transaction id and filesystem UUID). Objects of this type are
@@ -289,19 +302,18 @@ typedef struct fs_fs_data_t
layouts) or zero (for linear layouts). */
int max_files_per_dir;
- /* The first revision that uses logical addressing. SVN_INVALID_REVNUM
- if there is no such revision (pre-f7 or non-sharded). May be a
- future revision if the current shard started with physical addressing
- and is not complete, yet. */
- svn_revnum_t min_log_addressing_rev;
+ /* If set, this FS is using logical addressing. Otherwise, it is using
+ physical addressing. */
+ svn_boolean_t use_log_addressing;
- /* Rev / pack file read granularity. */
+ /* Rev / pack file read granularity in bytes. */
apr_int64_t block_size;
/* Capacity in entries of log-to-phys index pages */
apr_int64_t l2p_page_size;
- /* Rev / pack file granularity covered by phys-to-log index pages */
+ /* Rev / pack file granularity (in bytes) covered by a single phys-to-log
+ * index page. */
apr_int64_t p2l_page_size;
/* If set, parse and cache *all* data of each block that we read
@@ -341,21 +353,6 @@ typedef struct fs_fs_data_t
rep key (revision/offset) to svn_stringbuf_t. */
svn_cache__t *fulltext_cache;
- /* Access object to the atomics namespace used by revprop caching.
- Will be NULL until the first access. */
- svn_atomic_namespace__t *revprop_namespace;
-
- /* Access object to the revprop "generation". Will be NULL until
- the first access. */
- svn_named_atomic__t *revprop_generation;
-
- /* Access object to the revprop update timeout. Will be NULL until
- the first access. */
- svn_named_atomic__t *revprop_timeout;
-
- /* Revision property cache. Maps from (rev,generation) to apr_hash_t. */
- svn_cache__t *revprop_cache;
-
/* Node properties cache. Maps from rep key to apr_hash_t. */
svn_cache__t *properties_cache;
@@ -466,6 +463,12 @@ typedef struct fs_fs_data_t
/* Pack after every commit. */
svn_boolean_t pack_after_commit;
+ /* Per-instance filesystem ID, which provides an additional level of
+ uniqueness for filesystems that share the same UUID, but should
+ still be distinguishable (e.g. backups produced by svn_fs_hotcopy()
+ or dump / load cycles). */
+ const char *instance_id;
+
/* Pointer to svn_fs_open. */
svn_error_t *(*svn_fs_open_)(svn_fs_t **, const char *, apr_hash_t *,
apr_pool_t *, apr_pool_t *);
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=1639628&r1=1639627&r2=1639628&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 Fri Nov 14 13:17:55 2014
@@ -86,7 +86,7 @@ are likely some errors because of that.
/* Declarations. */
static svn_error_t *
-get_youngest(svn_revnum_t *youngest_p, const char *fs_path, apr_pool_t *pool);
+get_youngest(svn_revnum_t *youngest_p, svn_fs_t *fs, apr_pool_t *pool);
/* Pathname helper functions */
@@ -213,7 +213,7 @@ with_some_lock_file(with_lock_baton_t *b
if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
err = svn_fs_fs__update_min_unpacked_rev(fs, pool);
if (!err)
- err = get_youngest(&ffd->youngest_rev_cache, fs->path, pool);
+ err = get_youngest(&ffd->youngest_rev_cache, fs, pool);
}
if (!err)
@@ -457,18 +457,18 @@ check_format(int format)
/* Read the format number and maximum number of files per directory
from PATH and return them in *PFORMAT, *MAX_FILES_PER_DIR and
- MIN_LOG_ADDRESSING_REV respectively.
+ USE_LOG_ADDRESSIONG respectively.
*MAX_FILES_PER_DIR is obtained from the 'layout' format option, and
will be set to zero if a linear scheme should be used.
- *MIN_LOG_ADDRESSING_REV is obtained from the 'addressing' format option,
- and will be set to SVN_INVALID_REVNUM for physical addressing.
+ *USE_LOG_ADDRESSIONG is obtained from the 'addressing' format option,
+ and will be set to FALSE for physical addressing.
Use POOL for temporary allocation. */
static svn_error_t *
read_format(int *pformat,
int *max_files_per_dir,
- svn_revnum_t *min_log_addressing_rev,
+ svn_boolean_t *use_log_addressing,
const char *path,
apr_pool_t *pool)
{
@@ -515,7 +515,7 @@ read_format(int *pformat,
/* Set the default values for anything that can be set via an option. */
*max_files_per_dir = 0;
- *min_log_addressing_rev = SVN_INVALID_REVNUM;
+ *use_log_addressing = FALSE;
/* Read any options. */
while (!eos)
@@ -547,18 +547,13 @@ read_format(int *pformat,
{
if (strcmp(buf->data + 11, "physical") == 0)
{
- *min_log_addressing_rev = SVN_INVALID_REVNUM;
+ *use_log_addressing = FALSE;
continue;
}
- if (strncmp(buf->data + 11, "logical ", 8) == 0)
+ if (strcmp(buf->data + 11, "logical") == 0)
{
- int value;
-
- /* Check that the argument is numeric. */
- SVN_ERR(check_format_file_buffer_numeric(buf->data, 19, path, pool));
- SVN_ERR(svn_cstring_atoi(&value, buf->data + 19));
- *min_log_addressing_rev = value;
+ *use_log_addressing = TRUE;
continue;
}
}
@@ -572,7 +567,7 @@ read_format(int *pformat,
* If the format file is inconsistent in that respect, something
* probably went wrong.
*/
- if (*min_log_addressing_rev != SVN_INVALID_REVNUM && !*max_files_per_dir)
+ if (*use_log_addressing && !*max_files_per_dir)
return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
_("'%s' specifies logical addressing for a non-sharded repository"),
svn_dirent_local_style(path, pool));
@@ -610,13 +605,10 @@ svn_fs_fs__write_format(svn_fs_t *fs,
if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
{
- if (ffd->min_log_addressing_rev == SVN_INVALID_REVNUM)
- svn_stringbuf_appendcstr(sb, "addressing physical\n");
+ if (ffd->use_log_addressing)
+ svn_stringbuf_appendcstr(sb, "addressing logical\n");
else
- svn_stringbuf_appendcstr(sb,
- apr_psprintf(pool,
- "addressing logical %ld\n",
- ffd->min_log_addressing_rev));
+ svn_stringbuf_appendcstr(sb, "addressing physical\n");
}
/* svn_io_write_version_file() does a load of magic to allow it to
@@ -644,6 +636,50 @@ svn_fs_fs__fs_supports_mergeinfo(svn_fs_
return ffd->format >= SVN_FS_FS__MIN_MERGEINFO_FORMAT;
}
+/* Check that BLOCK_SIZE is a valid block / page size, i.e. it is within
+ * the range of what the current system may address in RAM and it is a
+ * power of 2. Assume that the element size within the block is ITEM_SIZE.
+ * Use SCRATCH_POOL for temporary allocations.
+ */
+static svn_error_t *
+verify_block_size(apr_int64_t block_size,
+ apr_size_t item_size,
+ const char *name,
+ apr_pool_t *scratch_pool
+ )
+{
+ /* Limit range. */
+ if (block_size <= 0)
+ return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
+ _("%s is too small for fsfs.conf setting '%s'."),
+ apr_psprintf(scratch_pool,
+ "%" APR_INT64_T_FMT,
+ block_size),
+ name);
+
+ if (block_size > SVN_MAX_OBJECT_SIZE / item_size)
+ return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
+ _("%s is too large for fsfs.conf setting '%s'."),
+ apr_psprintf(scratch_pool,
+ "%" APR_INT64_T_FMT,
+ block_size),
+ name);
+
+ /* Ensure it is a power of two.
+ * For positive X, X & (X-1) will reset the lowest bit set.
+ * If the result is 0, at most one bit has been set. */
+ if (0 != (block_size & (block_size - 1)))
+ return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
+ _("%s is invalid for fsfs.conf setting '%s' "
+ "because it is not a power of 2."),
+ apr_psprintf(scratch_pool,
+ "%" APR_INT64_T_FMT,
+ block_size),
+ name);
+
+ return SVN_NO_ERROR;
+}
+
/* Read the configuration information of the file system at FS_PATH
* and set the respective values in FFD. Use pools as usual.
*/
@@ -717,8 +753,8 @@ read_config(fs_fs_data_t *ffd,
CONFIG_SECTION_PACKED_REVPROPS,
CONFIG_OPTION_REVPROP_PACK_SIZE,
ffd->compress_packed_revprops
- ? 0x100
- : 0x40));
+ ? 0x10
+ : 0x4));
ffd->revprop_pack_size *= 1024;
}
@@ -743,15 +779,27 @@ read_config(fs_fs_data_t *ffd,
CONFIG_OPTION_P2L_PAGE_SIZE,
0x400));
+ /* Don't accept unreasonable or illegal values.
+ * Block size and P2L page size are in kbytes;
+ * L2P blocks are arrays of apr_off_t. */
+ SVN_ERR(verify_block_size(ffd->block_size, 0x400,
+ CONFIG_OPTION_BLOCK_SIZE, scratch_pool));
+ SVN_ERR(verify_block_size(ffd->p2l_page_size, 0x400,
+ CONFIG_OPTION_P2L_PAGE_SIZE, scratch_pool));
+ SVN_ERR(verify_block_size(ffd->l2p_page_size, sizeof(apr_off_t),
+ CONFIG_OPTION_L2P_PAGE_SIZE, scratch_pool));
+
+ /* convert kBytes to bytes */
ffd->block_size *= 0x400;
ffd->p2l_page_size *= 0x400;
+ /* L2P pages are in entries - not in (k)Bytes */
}
else
{
/* should be irrelevant but we initialize them anyway */
- ffd->block_size = 0x1000;
- ffd->l2p_page_size = 0x2000;
- ffd->p2l_page_size = 0x100000;
+ ffd->block_size = 0x1000; /* Matches default APR file buffer size. */
+ ffd->l2p_page_size = 0x2000; /* Matches above default. */
+ ffd->p2l_page_size = 0x100000; /* Matches above default in bytes. */
}
if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
@@ -910,20 +958,16 @@ write_config(svn_fs_t *fs,
"### much larger than the limit set here. The threshold will be applied" NL
"### before optional compression takes place." NL
"### Large values will reduce disk space usage at the expense of increased" NL
-"### latency and CPU usage reading and changing individual revprops. They" NL
-"### become an advantage when revprop caching has been enabled because a" NL
-"### lot of data can be read in one go. Values smaller than 4 kByte will" NL
-"### not improve latency any further and quickly render revprop packing" NL
-"### 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 " = 64" NL
+"### latency and CPU usage reading and changing individual revprops." NL
+"### Values smaller than 4 kByte will not improve latency any further and " NL
+"### quickly render revprop packing ineffective." NL
+"### revprop-pack-size is 4 kBytes by default for non-compressed revprop" NL
+"### pack files and 16 kBytes when compression has been enabled." NL
+"# " CONFIG_OPTION_REVPROP_PACK_SIZE " = 4" 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
+"### even more so writing, become significantly more CPU intensive." NL
"### Compressing packed revprops is disabled by default." NL
"# " CONFIG_OPTION_COMPRESS_PACKED_REVPROPS " = false" NL
"" NL
@@ -943,23 +987,18 @@ write_config(svn_fs_t *fs,
"### may improve latency while still maximizing throughput. If block-read" NL
"### has not been enabled, this will be capped to 4 kBytes." NL
"### Can be changed at any time but must be a power of 2." NL
-"### block-size is 64 kBytes by default." NL
+"### block-size is given in kBytes and with a default of 64 kBytes." NL
"# " CONFIG_OPTION_BLOCK_SIZE " = 64" NL
"###" NL
"### The log-to-phys index maps data item numbers to offsets within the" NL
-"### rev or pack file. A revision typically contains 2 .. 5 such items" NL
-"### per changed path. For each revision, at least one page is being" NL
-"### allocated in the l2p index with unused parts resulting in no wasted" NL
-"### space." NL
-"### Changing this parameter only affects larger revisions with thousands" NL
-"### of changed paths. A smaller value means that more pages need to be" NL
-"### allocated for such revisions, increasing the size of the page table" NL
-"### meaning it takes longer to read that table (once). Access to each" NL
-"### page is then faster because less data has to read. So, if you have" NL
-"### several extremely large revisions (approaching 1 mio changes), think" NL
+"### rev or pack file. This index is organized in pages of a fixed maximum" NL
+"### capacity. To access an item, the page table and the respective page" NL
+"### must be read." NL
+"### This parameter only affects revisions with thousands of changed paths." NL
+"### If you have several extremely large revisions (~1 mio changes), think" NL
"### about increasing this setting. Reducing the value will rarely result" NL
"### in a net speedup." NL
-"### This is an expert setting. Any non-zero value is possible." NL
+"### This is an expert setting. Must be a power of 2." NL
"### l2p-page-size is 8192 entries by default." NL
"# " CONFIG_OPTION_L2P_PAGE_SIZE " = 8192" NL
"###" NL
@@ -976,7 +1015,7 @@ write_config(svn_fs_t *fs,
"### smaller changes." NL
"### For source code repositories, this should be about 16x the block-size." NL
"### Must be a power of 2." NL
-"### p2l-page-size is 1024 kBytes by default." NL
+"### p2l-page-size is given in kBytes and with a default of 1024 kBytes." NL
"# " CONFIG_OPTION_P2L_PAGE_SIZE " = 1024" NL
;
#undef NL
@@ -990,8 +1029,14 @@ 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, FALSE);
+
+ /* Providing a config hash is optional. */
+ if (fs->config)
+ ffd->use_block_read = svn_hash__get_bool(fs->config,
+ SVN_FS_CONFIG_FSFS_BLOCK_READ,
+ FALSE);
+ else
+ ffd->use_block_read = FALSE;
/* Ignore the user-specified larger block size if we don't use block-read.
Defaulting to 4k gives us the same access granularity in format 7 as in
@@ -1002,36 +1047,73 @@ read_global_config(svn_fs_t *fs)
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_fs_fs__open(svn_fs_t *fs, const char *path, apr_pool_t *pool)
+/* Read FS's UUID file and store the data in the FS struct. */
+static svn_error_t *
+read_uuid(svn_fs_t *fs,
+ apr_pool_t *scratch_pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
apr_file_t *uuid_file;
- int format, max_files_per_dir;
- svn_revnum_t min_log_addressing_rev;
char buf[APR_UUID_FORMATTED_LENGTH + 2];
apr_size_t limit;
- fs->path = apr_pstrdup(fs->pool, path);
+ /* Read the repository uuid. */
+ SVN_ERR(svn_io_file_open(&uuid_file, path_uuid(fs, scratch_pool),
+ APR_READ | APR_BUFFERED, APR_OS_DEFAULT,
+ scratch_pool));
+
+ limit = sizeof(buf);
+ SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit, scratch_pool));
+ fs->uuid = apr_pstrdup(fs->pool, buf);
- /* Read the FS format number. */
- SVN_ERR(read_format(&format, &max_files_per_dir, &min_log_addressing_rev,
- path_format(fs, pool), pool));
+ /* Read the instance ID. */
+ if (ffd->format >= SVN_FS_FS__MIN_INSTANCE_ID_FORMAT)
+ {
+ limit = sizeof(buf);
+ SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit,
+ scratch_pool));
+ ffd->instance_id = apr_pstrdup(fs->pool, buf);
+ }
+ else
+ {
+ ffd->instance_id = fs->uuid;
+ }
+
+ SVN_ERR(svn_io_file_close(uuid_file, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__read_format_file(svn_fs_t *fs, apr_pool_t *scratch_pool)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+ int format, max_files_per_dir;
+ svn_boolean_t use_log_addressing;
- /* Now we've got a format number no matter what. */
+ /* Read info from format file. */
+ SVN_ERR(read_format(&format, &max_files_per_dir, &use_log_addressing,
+ path_format(fs, scratch_pool), scratch_pool));
+
+ /* Now that we've got *all* info, store / update values in FFD. */
ffd->format = format;
ffd->max_files_per_dir = max_files_per_dir;
- ffd->min_log_addressing_rev = min_log_addressing_rev;
+ ffd->use_log_addressing = use_log_addressing;
- /* Read in and cache the repository uuid. */
- SVN_ERR(svn_io_file_open(&uuid_file, path_uuid(fs, pool),
- APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));
+ return SVN_NO_ERROR;
+}
- limit = sizeof(buf);
- SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit, pool));
- fs->uuid = apr_pstrdup(fs->pool, buf);
+svn_error_t *
+svn_fs_fs__open(svn_fs_t *fs, const char *path, apr_pool_t *pool)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+ fs->path = apr_pstrdup(fs->pool, path);
- SVN_ERR(svn_io_file_close(uuid_file, pool));
+ /* Read the FS format file. */
+ SVN_ERR(svn_fs_fs__read_format_file(fs, pool));
+
+ /* Read in and cache the repository uuid. */
+ SVN_ERR(read_uuid(fs, pool));
/* Read the min unpacked revision. */
if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
@@ -1043,7 +1125,7 @@ svn_fs_fs__open(svn_fs_t *fs, const char
/* Global configuration options. */
SVN_ERR(read_global_config(fs));
- return get_youngest(&(ffd->youngest_rev_cache), path, pool);
+ return get_youngest(&(ffd->youngest_rev_cache), fs, pool);
}
/* Wrapper around svn_io_file_create which ignores EEXIST. */
@@ -1079,13 +1161,13 @@ upgrade_body(void *baton, apr_pool_t *po
svn_fs_t *fs = upgrade_baton->fs;
fs_fs_data_t *ffd = fs->fsap_data;
int format, max_files_per_dir;
- svn_revnum_t min_log_addressing_rev;
+ svn_boolean_t use_log_addressing;
const char *format_path = path_format(fs, pool);
svn_node_kind_t kind;
svn_boolean_t needs_revprop_shard_cleanup = FALSE;
/* Read the FS format number and max-files-per-dir setting. */
- SVN_ERR(read_format(&format, &max_files_per_dir, &min_log_addressing_rev,
+ SVN_ERR(read_format(&format, &max_files_per_dir, &use_log_addressing,
format_path, pool));
/* If the config file does not exist, create one. */
@@ -1126,10 +1208,8 @@ upgrade_body(void *baton, apr_pool_t *po
dir, make that directory. */
if (format < SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
{
- /* We don't use path_txn_proto_rev() here because it expects
- we've already bumped our format. */
SVN_ERR(svn_io_make_dir_recursively(
- svn_dirent_join(fs->path, PATH_TXN_PROTOS_DIR, pool), pool));
+ svn_fs_fs__path_txn_proto_revs(fs, pool), pool));
}
/* If our filesystem is new enough, write the min unpacked rev file. */
@@ -1154,20 +1234,24 @@ upgrade_body(void *baton, apr_pool_t *po
pool));
}
- if ( format < SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT
- && max_files_per_dir > 0)
- {
- min_log_addressing_rev
- = (ffd->youngest_rev_cache / max_files_per_dir + 1)
- * max_files_per_dir;
- }
+ /* We will need the UUID info shortly ...
+ Read it before the format bump as the UUID file still uses the old
+ format. */
+ SVN_ERR(read_uuid(fs, pool));
- /* Bump the format file. */
+ /* Update the format info in the FS struct. Upgrade steps further
+ down will use the format from FS to create missing info. */
ffd->format = SVN_FS_FS__FORMAT_NUMBER;
ffd->max_files_per_dir = max_files_per_dir;
- ffd->min_log_addressing_rev = min_log_addressing_rev;
+ ffd->use_log_addressing = use_log_addressing;
+ /* Always add / bump the instance ID such that no form of caching
+ accidentally uses outdated information. Keep the UUID. */
+ SVN_ERR(svn_fs_fs__set_uuid(fs, fs->uuid, NULL, pool));
+
+ /* Bump the format file. */
SVN_ERR(svn_fs_fs__write_format(fs, TRUE, pool));
+
if (upgrade_baton->notify_func)
SVN_ERR(upgrade_baton->notify_func(upgrade_baton->notify_baton,
SVN_FS_FS__FORMAT_NUMBER,
@@ -1211,17 +1295,11 @@ svn_fs_fs__upgrade(svn_fs_t *fs,
POOL. */
static svn_error_t *
get_youngest(svn_revnum_t *youngest_p,
- const char *fs_path,
+ svn_fs_t *fs,
apr_pool_t *pool)
{
- svn_stringbuf_t *buf;
- SVN_ERR(svn_fs_fs__read_content(&buf,
- svn_dirent_join(fs_path, PATH_CURRENT,
- pool),
- pool));
-
- *youngest_p = SVN_STR_TO_REV(buf->data);
-
+ apr_uint64_t dummy;
+ SVN_ERR(svn_fs_fs__read_current(youngest_p, &dummy, &dummy, fs, pool));
return SVN_NO_ERROR;
}
@@ -1233,12 +1311,33 @@ svn_fs_fs__youngest_rev(svn_revnum_t *yo
{
fs_fs_data_t *ffd = fs->fsap_data;
- SVN_ERR(get_youngest(youngest_p, fs->path, pool));
+ SVN_ERR(get_youngest(youngest_p, fs, pool));
ffd->youngest_rev_cache = *youngest_p;
return SVN_NO_ERROR;
}
+int
+svn_fs_fs__shard_size(svn_fs_t *fs)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+
+ return ffd->max_files_per_dir;
+}
+
+svn_error_t *
+svn_fs_fs__min_unpacked_rev(svn_revnum_t *min_unpacked,
+ svn_fs_t *fs,
+ apr_pool_t *pool)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+
+ SVN_ERR(svn_fs_fs__update_min_unpacked_rev(fs, pool));
+ *min_unpacked = ffd->min_unpacked_rev;
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_fs_fs__ensure_revision_exists(svn_revnum_t rev,
svn_fs_t *fs,
@@ -1256,7 +1355,7 @@ svn_fs_fs__ensure_revision_exists(svn_re
if (rev <= ffd->youngest_rev_cache)
return SVN_NO_ERROR;
- SVN_ERR(get_youngest(&(ffd->youngest_rev_cache), fs->path, pool));
+ SVN_ERR(get_youngest(&(ffd->youngest_rev_cache), fs, pool));
/* Check again. */
if (rev <= ffd->youngest_rev_cache)
@@ -1330,10 +1429,15 @@ svn_fs_fs__file_text_rep_equal(svn_boole
}
/* Old repositories may not have the SHA1 checksum handy.
- This check becomes expensive. Skip it unless explicitly required. */
+ This check becomes expensive. Skip it unless explicitly required.
+
+ We already have seen that the ID is different, so produce a likely
+ false negative as allowed by the API description - even though the
+ MD5 matched, there is an extremely slim chance that the SHA1 wouldn't.
+ */
if (!strict)
{
- *equal = TRUE;
+ *equal = FALSE;
return SVN_NO_ERROR;
}
@@ -1465,7 +1569,7 @@ write_revision_zero(svn_fs_t *fs,
svn_string_t date;
/* Write out a rev file for revision 0. */
- if (svn_fs_fs__use_log_addressing(fs, 0))
+ if (svn_fs_fs__use_log_addressing(fs))
{
apr_array_header_t *index_entries;
svn_fs_fs__p2l_entry_t *entry;
@@ -1550,59 +1654,29 @@ write_revision_zero(svn_fs_t *fs,
}
svn_error_t *
-svn_fs_fs__create(svn_fs_t *fs,
- const char *path,
- apr_pool_t *pool)
+svn_fs_fs__create_file_tree(svn_fs_t *fs,
+ const char *path,
+ int format,
+ int shard_size,
+ svn_boolean_t use_log_addressing,
+ apr_pool_t *pool)
{
- int format = SVN_FS_FS__FORMAT_NUMBER;
fs_fs_data_t *ffd = fs->fsap_data;
fs->path = apr_pstrdup(fs->pool, path);
- /* See if compatibility with older versions was explicitly requested. */
- if (fs->config)
- {
- svn_version_t *compatible_version;
- SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
- pool));
-
- /* select format number */
- switch(compatible_version->minor)
- {
- case 0: return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
- _("FSFS is not compatible with Subversion prior to 1.1"));
-
- case 1:
- case 2:
- case 3: format = 1;
- break;
-
- case 4: format = 2;
- break;
-
- case 5: format = 3;
- break;
-
- case 6:
- case 7: format = 4;
- break;
-
- case 8: format = 6;
- break;
-
- default:format = SVN_FS_FS__FORMAT_NUMBER;
- }
- }
ffd->format = format;
- /* Override the default linear layout if this is a new-enough format. */
+ /* Use an appropriate sharding mode if supported by the format. */
if (format >= SVN_FS_FS__MIN_LAYOUT_FORMAT_OPTION_FORMAT)
- ffd->max_files_per_dir = SVN_FS_FS_DEFAULT_MAX_FILES_PER_DIR;
+ ffd->max_files_per_dir = shard_size;
+ else
+ ffd->max_files_per_dir = 0;
/* Select the addressing mode depending on the format. */
if (format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT)
- ffd->min_log_addressing_rev = 0;
+ ffd->use_log_addressing = use_log_addressing;
else
- ffd->min_log_addressing_rev = SVN_INVALID_REVNUM;
+ ffd->use_log_addressing = FALSE;
/* Create the revision data directories. */
if (ffd->max_files_per_dir)
@@ -1626,23 +1700,22 @@ svn_fs_fs__create(svn_fs_t *fs,
pool));
/* Create the transaction directory. */
- SVN_ERR(svn_io_make_dir_recursively(svn_dirent_join(path, PATH_TXNS_DIR,
- pool),
+ SVN_ERR(svn_io_make_dir_recursively(svn_fs_fs__path_txns_dir(fs, pool),
pool));
/* Create the protorevs directory. */
if (format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
- SVN_ERR(svn_io_make_dir_recursively(svn_dirent_join(path, PATH_TXN_PROTOS_DIR,
- pool),
+ SVN_ERR(svn_io_make_dir_recursively(svn_fs_fs__path_txn_proto_revs(fs,
+ pool),
pool));
/* Create the 'current' file. */
- SVN_ERR(svn_io_file_create(svn_fs_fs__path_current(fs, pool),
- (format >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT
- ? "0\n" : "0 1 1\n"),
- pool));
+ SVN_ERR(svn_io_file_create_empty(svn_fs_fs__path_current(fs, pool), pool));
+ SVN_ERR(svn_fs_fs__write_current(fs, 0, 1, 1, pool));
+
+ /* Create the 'uuid' file. */
SVN_ERR(svn_io_file_create_empty(svn_fs_fs__path_lock(fs, pool), pool));
- SVN_ERR(svn_fs_fs__set_uuid(fs, NULL, pool));
+ SVN_ERR(svn_fs_fs__set_uuid(fs, NULL, NULL, pool));
/* Create the fsfs.conf file if supported. Older server versions would
simply ignore the file but that might result in a different behavior
@@ -1675,38 +1748,110 @@ svn_fs_fs__create(svn_fs_t *fs,
pool));
}
+ ffd->youngest_rev_cache = 0;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__create(svn_fs_t *fs,
+ const char *path,
+ apr_pool_t *pool)
+{
+ int format = SVN_FS_FS__FORMAT_NUMBER;
+ int shard_size = SVN_FS_FS_DEFAULT_MAX_FILES_PER_DIR;
+
+ /* Process the given filesystem config. */
+ if (fs->config)
+ {
+ svn_version_t *compatible_version;
+ const char *shard_size_str;
+ SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
+ pool));
+
+ /* select format number */
+ switch(compatible_version->minor)
+ {
+ case 0: return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,
+ _("FSFS is not compatible with Subversion prior to 1.1"));
+
+ case 1:
+ case 2:
+ case 3: format = 1;
+ break;
+
+ case 4: format = 2;
+ break;
+
+ case 5: format = 3;
+ break;
+
+ case 6:
+ case 7: format = 4;
+ break;
+
+ case 8: format = 6;
+ break;
+
+ default:format = SVN_FS_FS__FORMAT_NUMBER;
+ }
+
+ shard_size_str = svn_hash_gets(fs->config, SVN_FS_CONFIG_FSFS_SHARD_SIZE);
+ if (shard_size_str)
+ {
+ apr_int64_t val;
+ SVN_ERR(svn_cstring_strtoi64(&val, shard_size_str, 0,
+ APR_INT32_MAX, 10));
+
+ shard_size = (int) val;
+ }
+ }
+
+ /* Actual FS creation. */
+ SVN_ERR(svn_fs_fs__create_file_tree(fs, path, format, shard_size, TRUE, pool));
+
/* This filesystem is ready. Stamp it with a format number. */
SVN_ERR(svn_fs_fs__write_format(fs, FALSE, pool));
- ffd->youngest_rev_cache = 0;
return SVN_NO_ERROR;
}
svn_error_t *
svn_fs_fs__set_uuid(svn_fs_t *fs,
const char *uuid,
+ const char *instance_id,
apr_pool_t *pool)
{
- char *my_uuid;
- apr_size_t my_uuid_len;
+ fs_fs_data_t *ffd = fs->fsap_data;
const char *uuid_path = path_uuid(fs, pool);
+ svn_stringbuf_t *contents = svn_stringbuf_create_empty(pool);
if (! uuid)
uuid = svn_uuid_generate(pool);
- /* Make sure we have a copy in FS->POOL, and append a newline. */
- my_uuid = apr_pstrcat(fs->pool, uuid, "\n", SVN_VA_NULL);
- my_uuid_len = strlen(my_uuid);
+ if (! instance_id)
+ instance_id = svn_uuid_generate(pool);
+
+ svn_stringbuf_appendcstr(contents, uuid);
+ svn_stringbuf_appendcstr(contents, "\n");
+
+ if (ffd->format >= SVN_FS_FS__MIN_INSTANCE_ID_FORMAT)
+ {
+ svn_stringbuf_appendcstr(contents, instance_id);
+ svn_stringbuf_appendcstr(contents, "\n");
+ }
/* We use the permissions of the 'current' file, because the 'uuid'
file does not exist during repository creation. */
- SVN_ERR(svn_io_write_atomic(uuid_path, my_uuid, my_uuid_len,
+ SVN_ERR(svn_io_write_atomic(uuid_path, contents->data, contents->len,
svn_fs_fs__path_current(fs, pool) /* perms */,
pool));
- /* Remove the newline we added, and stash the UUID. */
- my_uuid[my_uuid_len - 1] = '\0';
- fs->uuid = my_uuid;
+ fs->uuid = apr_pstrdup(fs->pool, uuid);
+
+ if (ffd->format >= SVN_FS_FS__MIN_INSTANCE_ID_FORMAT)
+ ffd->instance_id = apr_pstrdup(fs->pool, instance_id);
+ else
+ ffd->instance_id = fs->uuid;
return SVN_NO_ERROR;
}
@@ -1782,9 +1927,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(apr_pstrdup(pool,
- origin_id_str->data),
- pool);
+ SVN_ERR(svn_fs_fs__id_parse(origin_id,
+ apr_pstrdup(pool, origin_id_str->data),
+ pool));
}
return SVN_NO_ERROR;
}
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.h?rev=1639628&r1=1639627&r2=1639628&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_fs_fs/fs_fs.h Fri Nov 14 13:17:55 2014
@@ -25,6 +25,11 @@
#include "fs.h"
+/* Read the 'format' file of fsfs filesystem FS and store its info in FS.
+ * Use SCRATCH_POOL for temporary allocations. */
+svn_error_t *
+svn_fs_fs__read_format_file(svn_fs_t *fs, apr_pool_t *scratch_pool);
+
/* Open the fsfs filesystem pointed to by PATH and associate it with
filesystem object FS. Use POOL for temporary allocations.
@@ -51,6 +56,17 @@ svn_error_t *svn_fs_fs__youngest_rev(svn
svn_fs_t *fs,
apr_pool_t *pool);
+/* Return the shard size of filesystem FS. Return 0 for non-shared ones. */
+int
+svn_fs_fs__shard_size(svn_fs_t *fs);
+
+/* Set *MIN_UNPACKED to the oldest non-packed revision in filesystem FS.
+ Do any temporary allocation in POOL. */
+svn_error_t *
+svn_fs_fs__min_unpacked_rev(svn_revnum_t *min_unpacked,
+ svn_fs_t *fs,
+ 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. */
@@ -106,6 +122,25 @@ svn_error_t *svn_fs_fs__file_checksum(sv
/* Return whether or not the given FS supports mergeinfo metadata. */
svn_boolean_t svn_fs_fs__fs_supports_mergeinfo(svn_fs_t *fs);
+/* Under the repository db PATH, create a FSFS repository with FORMAT,
+ * the given SHARD_SIZE. If USE_LOG_ADDRESSING is non-zero, repository
+ * will use logical addressing. If not supported by the respective format,
+ * the latter two parameters will be ignored. FS will be updated.
+ *
+ * The only file not being written is the 'format' file. This allows
+ * callers such as hotcopy to modify the contents before turning the
+ * tree into an accessible repository.
+ *
+ * Use POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_fs__create_file_tree(svn_fs_t *fs,
+ const char *path,
+ int format,
+ int shard_size,
+ svn_boolean_t use_log_addressing,
+ apr_pool_t *pool);
+
/* Create a fs_fs fileysystem referenced by FS at path PATH. Get any
temporary allocations from POOL.
@@ -115,11 +150,13 @@ svn_error_t *svn_fs_fs__create(svn_fs_t
const char *path,
apr_pool_t *pool);
-/* Set the uuid of repository FS to UUID, if UUID is not NULL;
- otherwise, set the uuid of FS to a newly generated UUID. Perform
- temporary allocations in POOL. */
+/* Set the uuid of repository FS to UUID and the instance ID to INSTANCE_ID.
+ If any of them is NULL, use a newly generated UUID / ID instead. Ignore
+ INSTANCE_ID whenever instance IDs are not supported by the FS format.
+ Perform temporary allocations in POOL. */
svn_error_t *svn_fs_fs__set_uuid(svn_fs_t *fs,
const char *uuid,
+ const char *instance_id,
apr_pool_t *pool);
/* Return the path to the 'current' file in FS.