You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2015/01/03 15:00:44 UTC
svn commit: r1649205 [4/30] - in /subversion/branches/authzperf: ./ build/
build/ac-macros/ notes/ subversion/bindings/ctypes-python/
subversion/bindings/cxxhl/
subversion/bindings/javahl/tests/org/apache/subversion/javahl/
subversion/bindings/swig/ su...
Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/cached_data.c Sat Jan 3 14:00:41 2015
@@ -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,
@@ -277,15 +277,13 @@ err_dangling_id(svn_fs_t *fs, const svn_
id_str->data, fs->path);
}
-/* Return TRUE, if REVISION in FS is of a format that supports block-read
- and the feature has been enabled. */
+/* Return TRUE, if FS is of a format that supports block-read and the
+ feature has been enabled. */
static svn_boolean_t
-use_block_read(svn_fs_t *fs,
- svn_revnum_t revision)
+use_block_read(svn_fs_t *fs)
{
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.
@@ -360,7 +358,7 @@ get_node_revision_body(node_revision_t *
rev_item->number,
scratch_pool));
- if (use_block_read(fs, rev_item->revision))
+ if (use_block_read(fs))
{
/* block-read will parse the whole block and will also return
the one noderev that we need right now. */
@@ -552,7 +550,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);
}
@@ -840,7 +838,7 @@ create_rep_state_body(rep_state_t **rep_
/* populate the cache if appropriate */
if (! svn_fs_fs__id_txn_used(&rep->txn_id))
{
- if (use_block_read(fs, rep->revision))
+ if (use_block_read(fs))
SVN_ERR(block_read(NULL, fs, rep->revision, rep->item_index,
rs->sfile->rfile, result_pool, scratch_pool));
else
@@ -922,14 +920,24 @@ 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;
+ svn_fs_fs__revision_file_t *rev_file = NULL;
- 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, scratch_pool));
+ /* Reuse the revision file provided by *HINT, if it is given and
+ * actually the rev / pack file that we want. */
+ svn_revnum_t start_rev = svn_fs_fs__packed_base_rev(fs, rep->revision);
+ if (hint)
+ rev_file = *(svn_fs_fs__revision_file_t **)hint;
+
+ if (rev_file == NULL || rev_file->start_revision != start_rev)
+ SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, rep->revision,
+ scratch_pool, scratch_pool));
+
+ if (hint)
+ *hint = rev_file;
/* This will auto-retry if there was a background pack. */
SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rev_file, rep->revision,
@@ -937,8 +945,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
@@ -951,8 +960,6 @@ svn_fs_fs__check_rep(representation_t *r
"%" APR_UINT64_T_FMT,
rep->item_index),
rep->revision);
-
- SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
}
else
{
@@ -978,7 +985,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 +1021,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 +1030,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;
@@ -1466,7 +1483,7 @@ read_delta_window(svn_txdelta_window_t *
because the block is unlikely to contain other data. */
if ( rs->chunk_index == 0
&& SVN_IS_VALID_REVNUM(rs->revision)
- && use_block_read(rs->sfile->fs, rs->revision)
+ && use_block_read(rs->sfile->fs)
&& rs->raw_window_cache)
{
SVN_ERR(block_read(NULL, rs->sfile->fs, rs->revision, rs->item_index,
@@ -2393,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, 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.
@@ -2699,7 +2716,7 @@ svn_fs_fs__get_changes(apr_array_header_
SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev,
scratch_pool, scratch_pool));
- if (use_block_read(fs, rev))
+ if (use_block_read(fs))
{
/* 'block-read' will also provide us with the desired data */
SVN_ERR(block_read((void **)changes, fs,
@@ -2710,7 +2727,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 +3268,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 +3304,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/authzperf/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/caching.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/caching.c Sat Jan 3 14:00:41 2015
@@ -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,10 +117,6 @@ read_config(const char **cache_namespace
SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
TRUE);
- /* For now, always disable revprop caching.
- */
- *cache_revprops = FALSE;
-
return SVN_NO_ERROR;
}
@@ -347,7 +341,6 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
fs_fs_data_t *ffd = fs->fsap_data;
const char *prefix = apr_pstrcat(pool,
"fsfs:", fs->uuid,
- ":", ffd->instance_id,
"/", normalize_key_part(fs->path, pool),
":",
SVN_VA_NULL);
@@ -355,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));
@@ -568,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)
{
@@ -641,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;
}
@@ -717,12 +676,44 @@ struct txn_cleanup_baton_t
/* the position where to reset it */
svn_cache__t **to_reset;
+
+ /* pool that TXN_CACHE was allocated in */
+ apr_pool_t *txn_pool;
+
+ /* pool that the FS containing the TO_RESET pointer was allocator */
+ apr_pool_t *fs_pool;
};
+/* Forward declaration. */
+static apr_status_t
+remove_txn_cache_fs(void *baton_void);
+
/* APR pool cleanup handler that will reset the cache pointer given in
- BATON_VOID. */
+ BATON_VOID when the TXN_POOL gets cleaned up. */
static apr_status_t
-remove_txn_cache(void *baton_void)
+remove_txn_cache_txn(void *baton_void)
+{
+ struct txn_cleanup_baton_t *baton = baton_void;
+
+ /* be careful not to hurt performance by resetting newer txn's caches. */
+ if (*baton->to_reset == baton->txn_cache)
+ {
+ /* This is equivalent to calling svn_fs_fs__reset_txn_caches(). */
+ *baton->to_reset = NULL;
+ }
+
+ /* It's cleaned up now. Prevent double cleanup. */
+ apr_pool_cleanup_kill(baton->fs_pool,
+ baton,
+ remove_txn_cache_fs);
+
+ return APR_SUCCESS;
+}
+
+/* APR pool cleanup handler that will reset the cache pointer given in
+ BATON_VOID when the FS_POOL gets cleaned up. */
+static apr_status_t
+remove_txn_cache_fs(void *baton_void)
{
struct txn_cleanup_baton_t *baton = baton_void;
@@ -730,19 +721,25 @@ remove_txn_cache(void *baton_void)
if (*baton->to_reset == baton->txn_cache)
{
/* This is equivalent to calling svn_fs_fs__reset_txn_caches(). */
- *baton->to_reset = NULL;
+ *baton->to_reset = NULL;
}
+ /* It's cleaned up now. Prevent double cleanup. */
+ apr_pool_cleanup_kill(baton->txn_pool,
+ baton,
+ remove_txn_cache_txn);
+
return APR_SUCCESS;
}
/* This function sets / registers the required callbacks for a given
- * transaction-specific *CACHE object, if CACHE is not NULL and a no-op
- * otherwise. In particular, it will ensure that *CACHE gets reset to NULL
- * upon POOL destruction latest.
+ * transaction-specific *CACHE object in FS, if CACHE is not NULL and
+ * a no-op otherwise. In particular, it will ensure that *CACHE gets
+ * reset to NULL upon POOL or FS->POOL destruction latest.
*/
static void
-init_txn_callbacks(svn_cache__t **cache,
+init_txn_callbacks(svn_fs_t *fs,
+ svn_cache__t **cache,
apr_pool_t *pool)
{
if (*cache != NULL)
@@ -752,10 +749,20 @@ init_txn_callbacks(svn_cache__t **cache,
baton = apr_palloc(pool, sizeof(*baton));
baton->txn_cache = *cache;
baton->to_reset = cache;
+ baton->txn_pool = pool;
+ baton->fs_pool = fs->pool;
+ /* If any of these pools gets cleaned, we must reset the cache.
+ * We don't know which one will get cleaned up first, so register
+ * cleanup actions for both and during the cleanup action, unregister
+ * the respective other action. */
apr_pool_cleanup_register(pool,
baton,
- remove_txn_cache,
+ remove_txn_cache_txn,
+ apr_pool_cleanup_null);
+ apr_pool_cleanup_register(fs->pool,
+ baton,
+ remove_txn_cache_fs,
apr_pool_cleanup_null);
}
}
@@ -774,7 +781,6 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
Therefore, throw in a uuid as well - just to be sure. */
const char *prefix = apr_pstrcat(pool,
"fsfs:", fs->uuid,
- ":", ffd->instance_id,
"/", fs->path,
":", txn_id,
":", svn_uuid_generate(pool), ":",
@@ -806,7 +812,7 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
pool, pool));
/* reset the transaction-specific cache if the pool gets cleaned up. */
- init_txn_callbacks(&(ffd->txn_dir_cache), pool);
+ init_txn_callbacks(fs, &(ffd->txn_dir_cache), pool);
return SVN_NO_ERROR;
}
Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.c Sat Jan 3 14:00:41 2015
@@ -866,14 +866,20 @@ svn_fs_fs__dag_delete_if_mutable(svn_fs_
{
apr_array_header_t *entries;
int i;
+ apr_pool_t *iterpool = svn_pool_create(pool);
/* Loop over directory entries */
SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, node, pool));
if (entries)
for (i = 0; i < entries->nelts; ++i)
- SVN_ERR(svn_fs_fs__dag_delete_if_mutable(fs,
- APR_ARRAY_IDX(entries, i, svn_fs_dirent_t *)->id,
- pool));
+ {
+ svn_pool_clear(iterpool);
+ SVN_ERR(svn_fs_fs__dag_delete_if_mutable(fs,
+ APR_ARRAY_IDX(entries, i, svn_fs_dirent_t *)->id,
+ iterpool));
+ }
+
+ svn_pool_destroy(iterpool);
}
/* ... then delete the node itself, after deleting any mutable
@@ -1099,6 +1105,15 @@ svn_fs_fs__dag_dup(const dag_node_t *nod
return new_node;
}
+dag_node_t *
+svn_fs_fs__dag_copy_into_pool(dag_node_t *node,
+ apr_pool_t *pool)
+{
+ return (node->node_pool == pool
+ ? node
+ : svn_fs_fs__dag_dup(node, pool));
+}
+
svn_error_t *
svn_fs_fs__dag_serialize(void **data,
apr_size_t *data_len,
Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.h?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/dag.h Sat Jan 3 14:00:41 2015
@@ -80,6 +80,12 @@ dag_node_t *
svn_fs_fs__dag_dup(const dag_node_t *node,
apr_pool_t *pool);
+/* If NODE has been allocated in POOL, return NODE. Otherwise, return
+ a copy created in POOL with svn_fs_fs__dag_dup. */
+dag_node_t *
+svn_fs_fs__dag_copy_into_pool(dag_node_t *node,
+ apr_pool_t *pool);
+
/* Serialize a DAG node, except don't try to preserve the 'fs' member.
Implements svn_cache__serialize_func_t */
svn_error_t *
Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.c Sat Jan 3 14:00:41 2015
@@ -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"
@@ -213,6 +214,7 @@ fs_info(const void **fsfs_info,
info->fs_type = SVN_FS_TYPE_FSFS;
info->shard_size = ffd->max_files_per_dir;
info->min_unpacked_rev = ffd->min_unpacked_rev;
+ info->log_addressing = ffd->use_log_addressing;
*fsfs_info = info;
return SVN_NO_ERROR;
}
@@ -265,7 +267,7 @@ 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;
@@ -348,20 +350,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);
@@ -496,7 +531,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/authzperf/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.h?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/fs.h Sat Jan 3 14:00:41 2015
@@ -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,7 +177,7 @@ 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
@@ -189,7 +189,6 @@ extern "C" {
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. */
-/* Compare ../libsvn_subr/named_atomic.c:USE_THREAD_MUTEX */
#if APR_HAS_THREADS && !defined(WIN32)
#define SVN_FS_FS__USE_LOCK_MUTEX 1
#else
@@ -303,11 +302,9 @@ 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 in bytes. */
apr_int64_t block_size;
@@ -356,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;
Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.c Sat Jan 3 14:00:41 2015
@@ -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,6 +779,16 @@ 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;
@@ -912,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
@@ -949,19 +991,14 @@ write_config(svn_fs_t *fs,
"# " 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
@@ -992,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
@@ -1042,22 +1085,32 @@ read_uuid(svn_fs_t *fs,
}
svn_error_t *
-svn_fs_fs__open(svn_fs_t *fs, const char *path, apr_pool_t *pool)
+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_revnum_t min_log_addressing_rev;
-
- fs->path = apr_pstrdup(fs->pool, path);
+ svn_boolean_t use_log_addressing;
- /* Read the FS format number. */
- SVN_ERR(read_format(&format, &max_files_per_dir, &min_log_addressing_rev,
- path_format(fs, pool), pool));
+ /* 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 we've got a format number no matter what. */
+ /* 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;
+
+ return SVN_NO_ERROR;
+}
+
+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);
+
+ /* 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));
@@ -1072,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. */
@@ -1108,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. */
@@ -1155,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. */
@@ -1183,14 +1234,6 @@ 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. */
@@ -1200,7 +1243,7 @@ upgrade_body(void *baton, apr_pool_t *po
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. */
@@ -1208,6 +1251,7 @@ upgrade_body(void *baton, apr_pool_t *po
/* 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,
@@ -1251,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;
}
@@ -1273,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,
@@ -1296,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)
@@ -1370,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;
}
@@ -1505,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;
@@ -1590,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)
@@ -1666,21 +1700,20 @@ 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, NULL, pool));
@@ -1715,10 +1748,76 @@ 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;
+ svn_boolean_t log_addressing;
+
+ /* 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;
+ }
+ }
+
+ log_addressing = svn_hash__get_bool(fs->config,
+ SVN_FS_CONFIG_FSFS_LOG_ADDRESSING,
+ TRUE);
+
+ /* Actual FS creation. */
+ SVN_ERR(svn_fs_fs__create_file_tree(fs, path, format, shard_size,
+ log_addressing, 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;
}
@@ -1834,9 +1933,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/authzperf/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.h?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/fs_fs.h Sat Jan 3 14:00:41 2015
@@ -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.
Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/hotcopy.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/hotcopy.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/hotcopy.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/hotcopy.c Sat Jan 3 14:00:41 2015
@@ -369,33 +369,30 @@ hotcopy_copy_packed_shard(svn_boolean_t
return SVN_NO_ERROR;
}
-/* Remove FILE in SHARD folder. Use POOL for temporary allocations. */
+/* Remove file PATH, if it exists - even if it is read-only.
+ * Use POOL for temporary allocations. */
static svn_error_t *
-hotcopy_remove_file(const char *shard,
- const char *file,
+hotcopy_remove_file(const char *path,
apr_pool_t *pool)
{
- const char *rev_path = svn_dirent_join(shard, file, pool);
-
/* Make the rev file writable and remove it. */
- SVN_ERR(svn_io_set_file_read_write(rev_path, TRUE, pool));
- SVN_ERR(svn_io_remove_file2(rev_path, TRUE, pool));
+ SVN_ERR(svn_io_set_file_read_write(path, TRUE, pool));
+ SVN_ERR(svn_io_remove_file2(path, TRUE, pool));
return SVN_NO_ERROR;
}
/* Remove revision or revprop files between START_REV (inclusive) and
- * END_REV (non-inclusive) from folder DST_SUBDIR in DST_FS. Also,
- * remove index files if REMOVE_INDEXES is set. Assume sharding as per
- * MAX_FILES_PER_DIR. Use SCRATCH_POOL for temporary allocations. */
+ * END_REV (non-inclusive) from folder DST_SUBDIR in DST_FS. Assume
+ * sharding as per MAX_FILES_PER_DIR.
+ * Use SCRATCH_POOL for temporary allocations. */
static svn_error_t *
hotcopy_remove_files(svn_fs_t *dst_fs,
const char *dst_subdir,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
int max_files_per_dir,
- svn_boolean_t remove_indexes,
apr_pool_t *scratch_pool)
{
const char *shard;
@@ -420,18 +417,11 @@ hotcopy_remove_files(svn_fs_t *dst_fs,
}
/* remove files for REV */
- SVN_ERR(hotcopy_remove_file(dst_subdir_shard,
- apr_psprintf(iterpool, "%ld", rev),
+ SVN_ERR(hotcopy_remove_file(svn_dirent_join(dst_subdir_shard,
+ apr_psprintf(iterpool,
+ "%ld", rev),
+ iterpool),
iterpool));
- if (remove_indexes && svn_fs_fs__use_log_addressing(dst_fs, rev))
- {
- SVN_ERR(hotcopy_remove_file(dst_subdir_shard,
- apr_psprintf(iterpool, "%ld.p2l", rev),
- iterpool));
- SVN_ERR(hotcopy_remove_file(dst_subdir_shard,
- apr_psprintf(iterpool, "%ld.l2p", rev),
- iterpool));
- }
}
svn_pool_destroy(iterpool);
@@ -455,7 +445,7 @@ hotcopy_remove_rev_files(svn_fs_t *dst_f
PATH_REVS_DIR,
scratch_pool),
start_rev, end_rev,
- max_files_per_dir, TRUE, scratch_pool));
+ max_files_per_dir, scratch_pool));
return SVN_NO_ERROR;
}
@@ -479,7 +469,7 @@ hotcopy_remove_revprop_files(svn_fs_t *d
PATH_REVPROPS_DIR,
scratch_pool),
start_rev ? start_rev : 1, end_rev,
- max_files_per_dir, FALSE, scratch_pool));
+ max_files_per_dir, scratch_pool));
return SVN_NO_ERROR;
}
@@ -1003,17 +993,6 @@ hotcopy_body(void *baton, apr_pool_t *po
SVN_ERR(svn_io_dir_file_copy(src_fs->path, dst_fs->path,
PATH_TXN_CURRENT, pool));
- /* If a revprop generation file exists in the source filesystem,
- * reset it to zero (since this is on a different path, it will not
- * overlap with data already in cache). Also, clean up stale files
- * used for the named atomics implementation. */
- SVN_ERR(svn_io_check_path(svn_fs_fs__path_revprop_generation(src_fs, pool),
- &kind, pool));
- if (kind == svn_node_file)
- SVN_ERR(svn_fs_fs__write_revprop_generation_file(dst_fs, 0, pool));
-
- SVN_ERR(svn_fs_fs__cleanup_revprop_namespace(dst_fs));
-
return SVN_NO_ERROR;
}
@@ -1042,76 +1021,26 @@ hotcopy_create_empty_dest(svn_fs_t *src_
apr_pool_t *pool)
{
fs_fs_data_t *src_ffd = src_fs->fsap_data;
- fs_fs_data_t *dst_ffd = dst_fs->fsap_data;
- dst_fs->path = apr_pstrdup(pool, dst_path);
-
- dst_ffd->max_files_per_dir = src_ffd->max_files_per_dir;
- dst_ffd->min_log_addressing_rev = src_ffd->min_log_addressing_rev;
- dst_ffd->format = src_ffd->format;
-
- /* Create the revision data directories. */
- if (dst_ffd->max_files_per_dir)
- SVN_ERR(svn_io_make_dir_recursively(svn_fs_fs__path_rev_shard(dst_fs,
- 0, pool),
- pool));
- else
- SVN_ERR(svn_io_make_dir_recursively(svn_dirent_join(dst_path,
- PATH_REVS_DIR, pool),
- pool));
-
- /* Create the revprops directory. */
- if (src_ffd->max_files_per_dir)
- SVN_ERR(svn_io_make_dir_recursively(
- svn_fs_fs__path_revprops_shard(dst_fs, 0, pool),
- pool));
- else
- SVN_ERR(svn_io_make_dir_recursively(svn_dirent_join(dst_path,
- PATH_REVPROPS_DIR,
- pool),
- pool));
-
- /* Create the transaction directory. */
- SVN_ERR(svn_io_make_dir_recursively(svn_dirent_join(dst_path, PATH_TXNS_DIR,
- pool),
+ /* Create the DST_FS repository with the same layout as SRC_FS. */
+ SVN_ERR(svn_fs_fs__create_file_tree(dst_fs, dst_path, src_ffd->format,
+ src_ffd->max_files_per_dir,
+ src_ffd->use_log_addressing,
pool));
- /* Create the protorevs directory. */
- if (dst_ffd->format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT)
- SVN_ERR(svn_io_make_dir_recursively(svn_dirent_join(dst_path,
- PATH_TXN_PROTOS_DIR,
- pool),
- pool));
-
- /* Create the 'current' file. */
- SVN_ERR(svn_io_file_create(svn_fs_fs__path_current(dst_fs, pool),
- (dst_ffd->format >=
- SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT
- ? "0\n" : "0 1 1\n"),
- pool));
-
- /* Create the lock and 'uuid' files. Hotcopy destination receives a
- new instance ID, but has the same filesystem UUID as the source. */
- SVN_ERR(svn_io_file_create_empty(svn_fs_fs__path_lock(dst_fs, pool), pool));
+ /* Copy the UUID. Hotcopy destination receives a new instance ID, but
+ * has the same filesystem UUID as the source. */
SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_fs->uuid, NULL, pool));
- /* Create the min unpacked rev file. */
- if (dst_ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT)
- SVN_ERR(svn_io_file_create(svn_fs_fs__path_min_unpacked_rev(dst_fs, pool),
- "0\n", pool));
- /* Create the txn-current file if the repository supports
- the transaction sequence file. */
- if (dst_ffd->format >= SVN_FS_FS__MIN_TXN_CURRENT_FORMAT)
- {
- SVN_ERR(svn_io_file_create(svn_fs_fs__path_txn_current(dst_fs, pool),
- "0\n", pool));
- SVN_ERR(svn_io_file_create_empty(
- svn_fs_fs__path_txn_current_lock(dst_fs, pool),
- pool));
- }
-
- /* FS creation is complete. Stamp it with a format file. */
- SVN_ERR(svn_fs_fs__write_format(dst_fs, TRUE, pool));
+ /* Remove revision 0 contents. Otherwise, it may not get overwritten
+ * due to having a newer timestamp. */
+ SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_rev(dst_fs, 0, pool), pool));
+ SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_revprops(dst_fs, 0, pool),
+ pool));
+
+ /* This filesystem is ready. Stamp it with a format number. Fail if
+ * the 'format' file should already exist. */
+ SVN_ERR(svn_fs_fs__write_format(dst_fs, FALSE, pool));
return SVN_NO_ERROR;
}
@@ -1175,8 +1104,8 @@ svn_fs_fs__hotcopy(svn_fs_t *src_fs,
hbb.notify_baton = notify_baton;
hbb.cancel_func = cancel_func;
hbb.cancel_baton = cancel_baton;
- SVN_ERR(svn_fs_fs__with_write_lock(dst_fs, hotcopy_locking_src_body, &hbb,
- pool));
+ SVN_ERR(svn_fs_fs__with_all_locks(dst_fs, hotcopy_locking_src_body, &hbb,
+ pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/id.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/id.c?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/id.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/id.c Sat Jan 3 14:00:41 2015
@@ -494,10 +494,11 @@ svn_fs_fs__id_copy(const svn_fs_id_t *so
return (svn_fs_id_t *)new_id;
}
-
-svn_fs_id_t *
-svn_fs_fs__id_parse(char *data,
- apr_pool_t *pool)
+/* 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. */
+static svn_fs_id_t *
+id_parse(char *data,
+ apr_pool_t *pool)
{
fs_fs__id_t *id;
char *str;
@@ -573,6 +574,21 @@ svn_fs_fs__id_parse(char *data,
return (svn_fs_id_t *)id;
}
+svn_error_t *
+svn_fs_fs__id_parse(const svn_fs_id_t **id_p,
+ char *data,
+ apr_pool_t *pool)
+{
+ svn_fs_id_t *id = id_parse(data, pool);
+ if (id == NULL)
+ return svn_error_createf(SVN_ERR_FS_MALFORMED_NODEREV_ID, NULL,
+ "Malformed node revision ID string");
+
+ *id_p = id;
+
+ return SVN_NO_ERROR;
+}
+
/* (de-)serialization support */
/* Serialize an ID within the serialization CONTEXT.
Modified: subversion/branches/authzperf/subversion/libsvn_fs_fs/id.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_fs/id.h?rev=1649205&r1=1649204&r2=1649205&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_fs_fs/id.h (original)
+++ subversion/branches/authzperf/subversion/libsvn_fs_fs/id.h Sat Jan 3 14:00:41 2015
@@ -24,32 +24,12 @@
#define SVN_LIBSVN_FS_FS_ID_H
#include "svn_fs.h"
+#include "private/svn_fs_fs_private.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-/* Node-revision IDs in FSFS consist of 3 of sub-IDs ("parts") that consist
- * of a creation REVISION number and some revision- / transaction-local
- * counter value (NUMBER). Old-style ID parts use global counter values.
- *
- * The parts are: node_id, copy_id and txn_id for in-txn IDs as well as
- * node_id, copy_id and rev_offset for in-revision IDs. This struct the
- * data structure used for each of those parts.
- */
-typedef struct svn_fs_fs__id_part_t
-{
- /* SVN_INVALID_REVNUM for txns -> not a txn, COUNTER must be 0.
- SVN_INVALID_REVNUM for others -> not assigned to a revision, yet.
- 0 for others -> old-style ID or the root in rev 0. */
- svn_revnum_t revision;
-
- /* sub-id value relative to REVISION. Its interpretation depends on
- the part itself. In rev_item, it is the index_index value, in others
- it represents a unique counter value. */
- apr_uint64_t number;
-} svn_fs_fs__id_part_t;
-
/*** Operations on ID parts. ***/
@@ -149,10 +129,13 @@ 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, 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);
+/* Return an ID in *ID_P resulting from parsing the string DATA, or an error
+ if DATA is an invalid ID string. *DATA will be modified / invalidated by
+ this call. */
+svn_error_t *
+svn_fs_fs__id_parse(const svn_fs_id_t **id_p,
+ char *data,
+ apr_pool_t *pool);
/* (de-)serialization support*/