Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/cached_data.h URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/cached_data.h?rev=1649205&r1=1649204&r2=1649205&view=diff ============================================================================== --- subversion/branches/authzperf/subversion/libsvn_fs_x/cached_data.h (original) +++ subversion/branches/authzperf/subversion/libsvn_fs_x/cached_data.h Sat Jan 3 14:00:41 2015 @@ -34,44 +34,45 @@ /* Set *NODEREV_P to the node-revision for the node ID in FS. Do any allocations in POOL. */ svn_error_t * -svn_fs_x__get_node_revision(node_revision_t **noderev_p, +svn_fs_x__get_node_revision(svn_fs_x__noderev_t **noderev_p, svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool); + const svn_fs_x__id_t *id, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Set *COUNT to the value of the mergeinfo_count member of the node- revision for the node ID in FS. Do any allocations in POOL. */ svn_error_t * svn_fs_x__get_mergeinfo_count(apr_int64_t *count, svn_fs_t *fs, - const svn_fs_id_t *id, + const svn_fs_x__id_t *id, apr_pool_t *pool); -/* Set *ROOT_ID to the node-id for the root of revision REV in - filesystem FS. Do any allocations in POOL. */ +/* Set *ROOT_ID to the noderev ID for the root of revision REV in + filesystem FS. Do temporary allocations in SCRATCH_POOL. */ svn_error_t * -svn_fs_x__rev_get_root(svn_fs_id_t **root_id, +svn_fs_x__rev_get_root(svn_fs_x__id_t *root_id, svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Verify that representation REP in FS can be accessed. - Do any allocations in POOL. */ + Do any allocations in SCRATCH_POOL. */ svn_error_t * -svn_fs_x__check_rep(representation_t *rep, +svn_fs_x__check_rep(svn_fs_x__representation_t *rep, svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Follow the representation delta chain in FS starting with REP. The number of reps (including REP) in the chain will be returned in *CHAIN_LENGTH. *SHARD_COUNT will be set to the number of shards - accessed. Do any allocations in POOL. */ + accessed. Do any allocations in SCRATCH_POOL. */ svn_error_t * svn_fs_x__rep_chain_length(int *chain_length, int *shard_count, - representation_t *rep, + svn_fs_x__representation_t *rep, svn_fs_t *fs, - apr_pool_t *pool); + apr_pool_t *scratch_pool); /* Set *CONTENTS to be a readable svn_stream_t that receives the text representation REP as seen in filesystem FS. If CACHE_FULLTEXT is @@ -81,7 +82,7 @@ svn_fs_x__rep_chain_length(int *chain_le svn_error_t * svn_fs_x__get_contents(svn_stream_t **contents_p, svn_fs_t *fs, - representation_t *rep, + svn_fs_x__representation_t *rep, svn_boolean_t cache_fulltext, apr_pool_t *pool); @@ -95,8 +96,7 @@ svn_error_t * svn_fs_x__get_representation_length(svn_filesize_t *packed_len, svn_filesize_t *expanded_len, svn_fs_t *fs, - apr_file_t *file, - svn_stream_t *stream, + svn_fs_x__revision_file_t *rev_file, svn_fs_x__p2l_entry_t* entry, apr_pool_t *pool); @@ -109,7 +109,7 @@ svn_fs_x__get_representation_length(svn_ svn_error_t * svn_fs_x__try_process_file_contents(svn_boolean_t *success, svn_fs_t *fs, - node_revision_t *noderev, + svn_fs_x__noderev_t *noderev, svn_fs_process_contents_func_t processor, void* baton, apr_pool_t *pool); @@ -120,8 +120,8 @@ svn_fs_x__try_process_file_contents(svn_ svn_error_t * svn_fs_x__get_file_delta_stream(svn_txdelta_stream_t **stream_p, svn_fs_t *fs, - node_revision_t *source, - node_revision_t *target, + svn_fs_x__noderev_t *source, + svn_fs_x__noderev_t *target, apr_pool_t *pool); /* Set *ENTRIES to an apr_array_header_t of dirent structs that contain @@ -131,7 +131,7 @@ svn_fs_x__get_file_delta_stream(svn_txde svn_error_t * svn_fs_x__rep_contents_dir(apr_array_header_t **entries_p, svn_fs_t *fs, - node_revision_t *noderev, + svn_fs_x__noderev_t *noderev, apr_pool_t *result_pool, apr_pool_t *scratch_pool); @@ -139,7 +139,7 @@ svn_fs_x__rep_contents_dir(apr_array_hea entry exists, return NULL. If HINT is not NULL, set *HINT to the array index of the entry returned. Successive calls in a linear scan scenario will be faster called with the same HINT variable. */ -svn_fs_dirent_t * +svn_fs_x__dirent_t * svn_fs_x__find_dir_entry(apr_array_header_t *entries, const char *name, int *hint); @@ -149,9 +149,9 @@ svn_fs_x__find_dir_entry(apr_array_heade be NULL. The returned object is allocated in RESULT_POOL; SCRATCH_POOL used for temporary allocations. */ svn_error_t * -svn_fs_x__rep_contents_dir_entry(svn_fs_dirent_t **dirent, +svn_fs_x__rep_contents_dir_entry(svn_fs_x__dirent_t **dirent, svn_fs_t *fs, - node_revision_t *noderev, + svn_fs_x__noderev_t *noderev, const char *name, apr_pool_t *result_pool, apr_pool_t *scratch_pool); @@ -162,7 +162,7 @@ svn_fs_x__rep_contents_dir_entry(svn_fs_ svn_error_t * svn_fs_x__get_proplist(apr_hash_t **proplist, svn_fs_t *fs, - node_revision_t *noderev, + svn_fs_x__noderev_t *noderev, apr_pool_t *pool); /* Fetch the list of change in revision REV in FS and return it in *CHANGES.
Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/caching.c URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/caching.c?rev=1649205&r1=1649204&r2=1649205&view=diff ============================================================================== --- subversion/branches/authzperf/subversion/libsvn_fs_x/caching.c (original) +++ subversion/branches/authzperf/subversion/libsvn_fs_x/caching.c Sat Jan 3 14:00:41 2015 @@ -126,19 +126,17 @@ read_config(const char **cache_namespace * 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. + * Option "2" is equivalent to "1". */ 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); + SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, + FALSE); else - *cache_revprops = svn_named_atomic__is_efficient(); + *cache_revprops = TRUE; return SVN_NO_ERROR; } @@ -361,7 +359,7 @@ svn_error_t * svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pool_t *pool) { - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; const char *prefix = apr_pstrcat(pool, "fsx:", fs->uuid, "/", normalize_key_part(fs->path, pool), @@ -407,27 +405,6 @@ svn_fs_x__initialize_caches(svn_fs_t *fs apr_pool_cleanup_null); #endif - /* Make the cache for revision roots. For the vast majority of - * commands, this is only going to contain a few entries (svnadmin - * dump/verify is an exception here), so to reduce overhead let's - * try to keep it to just one page. I estimate each entry has about - * 72 bytes of overhead (svn_revnum_t key, svn_fs_id_t + - * id_private_t + 3 strings for value, and the cache_entry); the - * default pool size is 8192, so about a hundred should fit - * comfortably. */ - SVN_ERR(create_cache(&(ffd->rev_root_id_cache), - NULL, - membuffer, - 1, 100, - svn_fs_x__serialize_id, - svn_fs_x__deserialize_id, - sizeof(svn_revnum_t), - apr_pstrcat(pool, prefix, "RRI", SVN_VA_NULL), - 0, - fs, - no_handler, - fs->pool, pool)); - /* Rough estimate: revision DAG nodes have size around 320 bytes, so * let's put 16 on a page. */ SVN_ERR(create_cache(&(ffd->rev_node_cache), @@ -453,7 +430,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 1024, 8, svn_fs_x__serialize_dir_entries, svn_fs_x__deserialize_dir_entries, - sizeof(svn_fs_x__id_part_t), + sizeof(svn_fs_x__id_t), apr_pstrcat(pool, prefix, "DIR", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, fs, @@ -483,7 +460,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 32, 32, /* ~200 byte / entry; 1k entries total */ svn_fs_x__serialize_node_revision, svn_fs_x__deserialize_node_revision, - sizeof(pair_cache_key_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(pool, prefix, "NODEREVS", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, fs, @@ -497,7 +474,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 1, 1000, /* ~8 bytes / entry; 1k entries total */ svn_fs_x__serialize_rep_header, svn_fs_x__deserialize_rep_header, - sizeof(representation_cache_key_t), + sizeof(svn_fs_x__representation_cache_key_t), apr_pstrcat(pool, prefix, "REPHEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, fs, @@ -527,7 +504,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 0, 0, /* Do not use inprocess cache */ /* Values are svn_stringbuf_t */ NULL, NULL, - sizeof(pair_cache_key_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(pool, prefix, "TEXT", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, fs, @@ -540,7 +517,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 0, 0, /* Do not use inprocess cache */ svn_fs_x__serialize_properties, svn_fs_x__deserialize_properties, - sizeof(pair_cache_key_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(pool, prefix, "PROP", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, @@ -593,7 +570,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 0, 0, /* Do not use inprocess cache */ svn_fs_x__serialize_properties, svn_fs_x__deserialize_properties, - sizeof(pair_cache_key_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(pool, prefix, "REVPROP", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, @@ -615,7 +592,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 0, 0, /* Do not use inprocess cache */ svn_fs_x__serialize_txdelta_window, svn_fs_x__deserialize_txdelta_window, - sizeof(window_cache_key_t), + sizeof(svn_fs_x__window_cache_key_t), apr_pstrcat(pool, prefix, "TXDELTA_WINDOW", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_LOW_PRIORITY, @@ -629,7 +606,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 0, 0, /* Do not use inprocess cache */ /* Values are svn_stringbuf_t */ NULL, NULL, - sizeof(window_cache_key_t), + sizeof(svn_fs_x__window_cache_key_t), apr_pstrcat(pool, prefix, "COMBINED_WINDOW", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_LOW_PRIORITY, @@ -649,7 +626,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 16, 4, /* Important, largish objects */ svn_fs_x__serialize_noderevs_container, svn_fs_x__deserialize_noderevs_container, - sizeof(pair_cache_key_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(pool, prefix, "NODEREVSCNT", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, @@ -662,7 +639,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 0, 0, /* Do not use inprocess cache */ svn_fs_x__serialize_changes_container, svn_fs_x__deserialize_changes_container, - sizeof(pair_cache_key_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(pool, prefix, "CHANGESCNT", SVN_VA_NULL), 0, @@ -675,7 +652,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 0, 0, /* Do not use inprocess cache */ svn_fs_x__serialize_reps_container, svn_fs_x__deserialize_reps_container, - sizeof(pair_cache_key_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(pool, prefix, "REPSCNT", SVN_VA_NULL), 0, @@ -690,7 +667,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs a reasonable number of revisions (1k) */ svn_fs_x__serialize_l2p_header, svn_fs_x__deserialize_l2p_header, - sizeof(pair_cache_key_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(pool, prefix, "L2P_HEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, @@ -717,7 +694,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs 4, 1, /* Large entries. Rarely used. */ svn_fs_x__serialize_p2l_header, svn_fs_x__deserialize_p2l_header, - sizeof(pair_cache_key_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(pool, prefix, "P2L_HEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/changes.c URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/changes.c?rev=1649205&r1=1649204&r2=1649205&view=diff ============================================================================== --- subversion/branches/authzperf/subversion/libsvn_fs_x/changes.c (original) +++ subversion/branches/authzperf/subversion/libsvn_fs_x/changes.c Sat Jan 3 14:00:41 2015 @@ -79,9 +79,7 @@ typedef struct binary_change_t /* Relevant parts of the node revision ID of the change. * Empty, if REV_ID is not "used". */ - svn_fs_x__id_part_t node_id; - svn_fs_x__id_part_t copy_id; - svn_fs_x__id_part_t noderev_id; + svn_fs_x__id_t noderev_id; } binary_change_t; @@ -136,24 +134,25 @@ svn_fs_x__changes_create(apr_size_t init */ static svn_error_t * append_change(svn_fs_x__changes_t *changes, - change_t *change) + svn_fs_x__change_t *change) { binary_change_t binary_change = { 0 }; svn_boolean_t is_txn_id; - svn_fs_path_change2_t *info; /* CHANGE must be sufficiently complete */ SVN_ERR_ASSERT(change); SVN_ERR_ASSERT(change->path.data); + /* Relevant parts of the revision ID of the change. */ + binary_change.noderev_id = change->noderev_id; + /* define the kind of change and what specific information is present */ - info = &change->info; - is_txn_id = info->node_rev_id && svn_fs_x__id_is_txn(info->node_rev_id); - binary_change.flags = (info->text_mod ? CHANGE_TEXT_MOD : 0) - | (info->prop_mod ? CHANGE_PROP_MOD : 0) + is_txn_id = svn_fs_x__is_txn(binary_change.noderev_id.change_set); + binary_change.flags = (change->text_mod ? CHANGE_TEXT_MOD : 0) + | (change->prop_mod ? CHANGE_PROP_MOD : 0) | (is_txn_id ? CHANGE_TXN_NODE : 0) - | ((int)info->change_kind << CHANGE_KIND_SHIFT) - | ((int)info->node_kind << CHANGE_NODE_SHIFT); + | ((int)change->change_kind << CHANGE_KIND_SHIFT) + | ((int)change->node_kind << CHANGE_NODE_SHIFT); /* Path of the change. */ binary_change.path @@ -162,12 +161,12 @@ append_change(svn_fs_x__changes_t *chang change->path.len); /* copy-from information, if presence is indicated by FLAGS */ - if (SVN_IS_VALID_REVNUM(info->copyfrom_rev)) + if (SVN_IS_VALID_REVNUM(change->copyfrom_rev)) { - binary_change.copyfrom_rev = info->copyfrom_rev; + binary_change.copyfrom_rev = change->copyfrom_rev; binary_change.copyfrom_path = svn_fs_x__string_table_builder_add(changes->builder, - info->copyfrom_path, + change->copyfrom_path, 0); } else @@ -176,19 +175,6 @@ append_change(svn_fs_x__changes_t *chang binary_change.copyfrom_path = 0; } - /* Relevant parts of the revision ID of the change. */ - if (info->node_rev_id) - { - binary_change.node_id = *svn_fs_x__id_node_id(info->node_rev_id); - binary_change.copy_id = *svn_fs_x__id_copy_id(info->node_rev_id); - binary_change.noderev_id = *svn_fs_x__id_noderev_id(info->node_rev_id); - } - else - { - binary_change.noderev_id.number = 0; - binary_change.noderev_id.change_set = SVN_FS_X__INVALID_CHANGE_SET; - } - APR_ARRAY_PUSH(changes->changes, binary_change_t) = binary_change; return SVN_NO_ERROR; @@ -207,7 +193,7 @@ svn_fs_x__changes_append_list(apr_size_t /* simply append the list and all changes */ for (i = 0; i < list->nelts; ++i) - append_change(changes, APR_ARRAY_IDX(list, i, change_t *)); + append_change(changes, APR_ARRAY_IDX(list, i, svn_fs_x__change_t *)); /* terminate the list by storing the next changes offset */ APR_ARRAY_PUSH(changes->offsets, int) = changes->changes->nelts; @@ -259,44 +245,40 @@ svn_fs_x__changes_get_list(apr_array_hea last = APR_ARRAY_IDX(changes->offsets, (int)idx + 1, int); /* construct result */ - *list = apr_array_make(pool, last - first, sizeof(change_t*)); + *list = apr_array_make(pool, last - first, sizeof(svn_fs_x__change_t*)); for (i = first; i < last; ++i) { const binary_change_t *binary_change = &APR_ARRAY_IDX(changes->changes, i, binary_change_t); - /* convert BINARY_CHANGE into a standard FSX change_t */ - change_t *change = apr_pcalloc(pool, sizeof(*change)); - svn_fs_path_change2_t *info = &change->info; + /* convert BINARY_CHANGE into a standard FSX svn_fs_x__change_t */ + svn_fs_x__change_t *change = apr_pcalloc(pool, sizeof(*change)); change->path.data = svn_fs_x__string_table_get(changes->paths, binary_change->path, &change->path.len, pool); if (binary_change->noderev_id.change_set != SVN_FS_X__INVALID_CHANGE_SET) - info->node_rev_id = svn_fs_x__id_create(&binary_change->node_id, - &binary_change->copy_id, - &binary_change->noderev_id, - pool); + change->noderev_id = binary_change->noderev_id; - info->change_kind = (svn_fs_path_change_kind_t) + change->change_kind = (svn_fs_path_change_kind_t) ((binary_change->flags & CHANGE_KIND_MASK) >> CHANGE_KIND_SHIFT); - info->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0; - info->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0; - info->node_kind = (svn_node_kind_t) + change->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0; + change->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0; + change->node_kind = (svn_node_kind_t) ((binary_change->flags & CHANGE_NODE_MASK) >> CHANGE_NODE_SHIFT); - info->copyfrom_rev = binary_change->copyfrom_rev; - info->copyfrom_known = TRUE; + change->copyfrom_rev = binary_change->copyfrom_rev; + change->copyfrom_known = TRUE; if (SVN_IS_VALID_REVNUM(binary_change->copyfrom_rev)) - info->copyfrom_path + change->copyfrom_path = svn_fs_x__string_table_get(changes->paths, binary_change->copyfrom_path, NULL, pool); /* add it to the result */ - APR_ARRAY_PUSH(*list, change_t*) = change; + APR_ARRAY_PUSH(*list, svn_fs_x__change_t*) = change; } return SVN_NO_ERROR; @@ -330,11 +312,7 @@ svn_fs_x__write_changes_container(svn_st svn_packed__create_int_substream(changes_stream, TRUE, FALSE); svn_packed__create_int_substream(changes_stream, TRUE, TRUE); svn_packed__create_int_substream(changes_stream, TRUE, FALSE); - svn_packed__create_int_substream(changes_stream, TRUE, TRUE); - svn_packed__create_int_substream(changes_stream, TRUE, FALSE); - svn_packed__create_int_substream(changes_stream, TRUE, TRUE); - svn_packed__create_int_substream(changes_stream, TRUE, FALSE); - + /* serialize offsets array */ for (i = 0; i < changes->offsets->nelts; ++i) svn_packed__add_uint(offsets_stream, @@ -352,10 +330,6 @@ svn_fs_x__write_changes_container(svn_st svn_packed__add_int(changes_stream, change->copyfrom_rev); svn_packed__add_uint(changes_stream, change->copyfrom_path); - svn_packed__add_int(changes_stream, change->node_id.change_set); - svn_packed__add_uint(changes_stream, change->node_id.number); - svn_packed__add_int(changes_stream, change->copy_id.change_set); - svn_packed__add_uint(changes_stream, change->copy_id.number); svn_packed__add_int(changes_stream, change->noderev_id.change_set); svn_packed__add_uint(changes_stream, change->noderev_id.number); } @@ -412,10 +386,6 @@ svn_fs_x__read_changes_container(svn_fs_ change.copyfrom_rev = (svn_revnum_t)svn_packed__get_int(changes_stream); change.copyfrom_path = (apr_size_t)svn_packed__get_uint(changes_stream); - change.node_id.change_set = svn_packed__get_int(changes_stream); - change.node_id.number = svn_packed__get_uint(changes_stream); - change.copy_id.change_set = svn_packed__get_int(changes_stream); - change.copy_id.number = svn_packed__get_uint(changes_stream); change.noderev_id.change_set = svn_packed__get_int(changes_stream); change.noderev_id.number = svn_packed__get_uint(changes_stream); @@ -525,43 +495,38 @@ svn_fs_x__changes_get_list_func(void **o last = offsets[idx+1]; /* construct result */ - list = apr_array_make(pool, last - first, sizeof(change_t*)); + list = apr_array_make(pool, last - first, sizeof(svn_fs_x__change_t*)); for (i = first; i < last; ++i) { const binary_change_t *binary_change = &changes[i]; - /* convert BINARY_CHANGE into a standard FSX change_t */ - change_t *change = apr_pcalloc(pool, sizeof(*change)); - svn_fs_path_change2_t *info = &change->info; + /* convert BINARY_CHANGE into a standard FSX svn_fs_x__change_t */ + svn_fs_x__change_t *change = apr_pcalloc(pool, sizeof(*change)); change->path.data = svn_fs_x__string_table_get_func(paths, binary_change->path, &change->path.len, pool); - if (binary_change->noderev_id.change_set != SVN_FS_X__INVALID_CHANGE_SET) - info->node_rev_id = svn_fs_x__id_create(&binary_change->node_id, - &binary_change->copy_id, - &binary_change->noderev_id, - pool); + change->noderev_id = binary_change->noderev_id; - info->change_kind = (svn_fs_path_change_kind_t) + change->change_kind = (svn_fs_path_change_kind_t) ((binary_change->flags & CHANGE_KIND_MASK) >> CHANGE_KIND_SHIFT); - info->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0; - info->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0; - info->node_kind = (svn_node_kind_t) + change->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0; + change->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0; + change->node_kind = (svn_node_kind_t) ((binary_change->flags & CHANGE_NODE_MASK) >> CHANGE_NODE_SHIFT); - info->copyfrom_rev = binary_change->copyfrom_rev; - info->copyfrom_known = TRUE; + change->copyfrom_rev = binary_change->copyfrom_rev; + change->copyfrom_known = TRUE; if (SVN_IS_VALID_REVNUM(binary_change->copyfrom_rev)) - info->copyfrom_path + change->copyfrom_path = svn_fs_x__string_table_get_func(paths, binary_change->copyfrom_path, NULL, pool); /* add it to the result */ - APR_ARRAY_PUSH(list, change_t*) = change; + APR_ARRAY_PUSH(list, svn_fs_x__change_t*) = change; } *out = list; Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/changes.h URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/changes.h?rev=1649205&r1=1649204&r2=1649205&view=diff ============================================================================== --- subversion/branches/authzperf/subversion/libsvn_fs_x/changes.h (original) +++ subversion/branches/authzperf/subversion/libsvn_fs_x/changes.h Sat Jan 3 14:00:41 2015 @@ -32,21 +32,22 @@ * * In its serialized form, the svn_fs_x__changes_t container extracts most * of that redundancy and the run-time representation is also much smaller - * than sum of the respective change_t* arrays. + * than sum of the respective svn_fs_x__change_t* arrays. * * As with other containers, this one has two modes: 'construction', in * which you may add data to it, and 'getter' in which there is only r/o * access to the data. */ -/* An opaque collection of change lists (apr_array_header_t * of change_t*). +/* An opaque collection of change lists (apr_array_header_t * of + * svn_fs_x__change_t *). */ typedef struct svn_fs_x__changes_t svn_fs_x__changes_t; /* Create and populate changes containers. */ /* Create and return a new changes container with an initial capacity of - * INITIAL_COUNT change_t objects. Allocate the result in POOL. + * INITIAL_COUNT svn_fs_x__change_t objects. Allocate the result in POOL. */ svn_fs_x__changes_t * svn_fs_x__changes_create(apr_size_t initial_count, Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/dag.c URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/dag.c?rev=1649205&r1=1649204&r2=1649205&view=diff ============================================================================== --- subversion/branches/authzperf/subversion/libsvn_fs_x/dag.c (original) +++ subversion/branches/authzperf/subversion/libsvn_fs_x/dag.c Sat Jan 3 14:00:41 2015 @@ -31,7 +31,7 @@ #include "dag.h" #include "fs.h" #include "fs_x.h" -#include "id.h" +#include "fs_id.h" #include "cached_data.h" #include "transaction.h" @@ -50,14 +50,14 @@ struct dag_node_t /* The filesystem this dag node came from. */ svn_fs_t *fs; - /* The node revision ID for this dag node, allocated in POOL. */ - svn_fs_id_t *id; + /* The node revision ID for this dag node. */ + svn_fs_x__id_t id; /* In the special case that this node is the root of a transaction that has not yet been modified, the node revision ID for this dag node's predecessor; otherwise NULL. (Used in svn_fs_node_created_rev.) */ - const svn_fs_id_t *fresh_root_predecessor_id; + svn_fs_x__id_t fresh_root_predecessor_id; /* The node's type (file, dir, etc.) */ svn_node_kind_t kind; @@ -69,7 +69,7 @@ struct dag_node_t this yourself, but you're probably better off just calling `get_node_revision' and `set_node_revision', which take care of things for you. */ - node_revision_t *node_revision; + svn_fs_x__noderev_t *node_revision; /* The pool to allocate NODE_REVISION in. */ apr_pool_t *node_pool; @@ -86,11 +86,10 @@ svn_node_kind_t svn_fs_x__dag_node_kind( return node->kind; } - -const svn_fs_id_t * +const svn_fs_x__id_t * svn_fs_x__dag_get_id(const dag_node_t *node) { - return node->id; + return &node->id; } @@ -116,27 +115,22 @@ svn_fs_x__dag_set_fs(dag_node_t *node, s /* Dup NODEREV and all associated data into POOL. Leaves the id and is_fresh_txn_root fields as zero bytes. */ -static node_revision_t * -copy_node_revision(node_revision_t *noderev, +static svn_fs_x__noderev_t * +copy_node_revision(svn_fs_x__noderev_t *noderev, apr_pool_t *pool) { - node_revision_t *nr = apr_pcalloc(pool, sizeof(*nr)); - nr->kind = noderev->kind; - if (noderev->predecessor_id) - nr->predecessor_id = svn_fs_x__id_copy(noderev->predecessor_id, pool); - nr->predecessor_count = noderev->predecessor_count; + svn_fs_x__noderev_t *nr = apr_pmemdup(pool, noderev, sizeof(*noderev)); + if (noderev->copyfrom_path) nr->copyfrom_path = apr_pstrdup(pool, noderev->copyfrom_path); - nr->copyfrom_rev = noderev->copyfrom_rev; + nr->copyroot_path = apr_pstrdup(pool, noderev->copyroot_path); - nr->copyroot_rev = noderev->copyroot_rev; nr->data_rep = svn_fs_x__rep_copy(noderev->data_rep, pool); nr->prop_rep = svn_fs_x__rep_copy(noderev->prop_rep, pool); - nr->mergeinfo_count = noderev->mergeinfo_count; - nr->has_mergeinfo = noderev->has_mergeinfo; if (noderev->created_path) nr->created_path = apr_pstrdup(pool, noderev->created_path); + return nr; } @@ -153,17 +147,19 @@ copy_node_revision(node_revision_t *node changes that never got committed. It's probably best not to change the structure at all. */ static svn_error_t * -get_node_revision(node_revision_t **noderev_p, +get_node_revision(svn_fs_x__noderev_t **noderev_p, dag_node_t *node) { /* If we've already got a copy, there's no need to read it in. */ if (! node->node_revision) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; + apr_pool_t *scratch_pool = svn_pool_create(node->node_pool); - SVN_ERR(svn_fs_x__get_node_revision(&noderev, node->fs, - node->id, node->node_pool)); + SVN_ERR(svn_fs_x__get_node_revision(&noderev, node->fs, &node->id, + node->node_pool, scratch_pool)); node->node_revision = noderev; + svn_pool_destroy(scratch_pool); } /* Now NODE->node_revision is set. */ @@ -171,26 +167,83 @@ get_node_revision(node_revision_t **node return SVN_NO_ERROR; } +/* Return the node revision ID of NODE. The value returned is shared + with NODE, and will be deallocated when NODE is. */ +svn_error_t * +svn_fs_x__dag_get_node_id(svn_fs_x__id_t *node_id, + dag_node_t *node) +{ + svn_fs_x__noderev_t *noderev; + SVN_ERR(get_node_revision(&noderev, node)); + + *node_id = noderev->node_id; + return SVN_NO_ERROR; +} + +/* Return the node revision ID of NODE. The value returned is shared + with NODE, and will be deallocated when NODE is. */ +svn_error_t * +svn_fs_x__dag_get_copy_id(svn_fs_x__id_t *copy_id, + dag_node_t *node) +{ + svn_fs_x__noderev_t *noderev; + SVN_ERR(get_node_revision(&noderev, node)); + + *copy_id = noderev->copy_id; + return SVN_NO_ERROR; +} + +/* Return the node ID of NODE. The value returned is shared with NODE, + and will be deallocated when NODE is. */ +svn_error_t * +svn_fs_x__dag_related_node(svn_boolean_t *same, + dag_node_t *lhs, + dag_node_t *rhs) +{ + svn_fs_x__id_t lhs_node, rhs_node; + + SVN_ERR(svn_fs_x__dag_get_node_id(&lhs_node, lhs)); + SVN_ERR(svn_fs_x__dag_get_node_id(&rhs_node, rhs)); + *same = svn_fs_x__id_eq(&lhs_node, &rhs_node); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__dag_same_line_of_history(svn_boolean_t *same, + dag_node_t *lhs, + dag_node_t *rhs) +{ + svn_fs_x__noderev_t *lhs_noderev, *rhs_noderev; + + SVN_ERR(get_node_revision(&lhs_noderev, lhs)); + SVN_ERR(get_node_revision(&rhs_noderev, rhs)); + + *same = svn_fs_x__id_eq(&lhs_noderev->node_id, &rhs_noderev->node_id) + && svn_fs_x__id_eq(&lhs_noderev->copy_id, &rhs_noderev->copy_id); + + return SVN_NO_ERROR; +} svn_boolean_t svn_fs_x__dag_check_mutable(const dag_node_t *node) { - return svn_fs_x__id_is_txn(svn_fs_x__dag_get_id(node)); + return svn_fs_x__is_txn(svn_fs_x__dag_get_id(node)->change_set); } svn_error_t * svn_fs_x__dag_get_node(dag_node_t **node, svn_fs_t *fs, - const svn_fs_id_t *id, + const svn_fs_x__id_t *id, apr_pool_t *pool) { dag_node_t *new_node; - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; /* Construct the node. */ new_node = apr_pcalloc(pool, sizeof(*new_node)); new_node->fs = fs; - new_node->id = svn_fs_x__id_copy(id, pool); + new_node->id = *id; /* Grab the contents so we can inspect the node's kind and created path. */ new_node->node_pool = pool; @@ -203,7 +256,7 @@ svn_fs_x__dag_get_node(dag_node_t **node if (noderev->is_fresh_txn_root) new_node->fresh_root_predecessor_id = noderev->predecessor_id; else - new_node->fresh_root_predecessor_id = NULL; + svn_fs_x__id_reset(&new_node->fresh_root_predecessor_id); /* Return a fresh new node */ *node = new_node; @@ -211,32 +264,31 @@ svn_fs_x__dag_get_node(dag_node_t **node } -svn_error_t * -svn_fs_x__dag_get_revision(svn_revnum_t *rev, - dag_node_t *node, - apr_pool_t *pool) +svn_revnum_t +svn_fs_x__dag_get_revision(const dag_node_t *node) { /* In the special case that this is an unmodified transaction root, we need to actually get the revision of the noderev's predecessor (the revision root); see Issue #2608. */ - const svn_fs_id_t *correct_id = node->fresh_root_predecessor_id - ? node->fresh_root_predecessor_id : node->id; + const svn_fs_x__id_t *correct_id + = svn_fs_x__id_used(&node->fresh_root_predecessor_id) + ? &node->fresh_root_predecessor_id + : &node->id; /* Look up the committed revision from the Node-ID. */ - *rev = svn_fs_x__id_rev(correct_id); - - return SVN_NO_ERROR; + return svn_fs_x__get_revnum(correct_id->change_set); } svn_error_t * -svn_fs_x__dag_get_predecessor_id(const svn_fs_id_t **id_p, +svn_fs_x__dag_get_predecessor_id(svn_fs_x__id_t *id_p, dag_node_t *node) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; SVN_ERR(get_node_revision(&noderev, node)); *id_p = noderev->predecessor_id; + return SVN_NO_ERROR; } @@ -245,7 +297,7 @@ svn_error_t * svn_fs_x__dag_get_predecessor_count(int *count, dag_node_t *node) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; SVN_ERR(get_node_revision(&noderev, node)); *count = noderev->predecessor_count; @@ -256,7 +308,7 @@ svn_error_t * svn_fs_x__dag_get_mergeinfo_count(apr_int64_t *count, dag_node_t *node) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; SVN_ERR(get_node_revision(&noderev, node)); *count = noderev->mergeinfo_count; @@ -267,7 +319,7 @@ svn_error_t * svn_fs_x__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo, dag_node_t *node) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; SVN_ERR(get_node_revision(&noderev, node)); *has_mergeinfo = noderev->has_mergeinfo; @@ -278,7 +330,7 @@ svn_error_t * svn_fs_x__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they, dag_node_t *node) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; if (node->kind != svn_node_dir) { @@ -301,21 +353,22 @@ svn_fs_x__dag_has_descendants_with_merge /* Some of these are helpers for functions outside this section. */ -/* Set *ID_P to the node-id for entry NAME in PARENT. If no such - entry, set *ID_P to NULL but do not error. The node-id is - allocated in POOL. */ +/* Set *ID_P to the noderev-id for entry NAME in PARENT. If no such + entry, set *ID_P to NULL but do not error. */ static svn_error_t * -dir_entry_id_from_node(const svn_fs_id_t **id_p, +dir_entry_id_from_node(svn_fs_x__id_t *id_p, dag_node_t *parent, const char *name, - apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_fs_dirent_t *dirent; + svn_fs_x__dirent_t *dirent; - SVN_ERR(svn_fs_x__dag_dir_entry(&dirent, parent, name, result_pool, + SVN_ERR(svn_fs_x__dag_dir_entry(&dirent, parent, name, scratch_pool, scratch_pool)); - *id_p = dirent ? dirent->id : NULL; + if (dirent) + *id_p = dirent->id; + else + svn_fs_x__id_reset(id_p); return SVN_NO_ERROR; } @@ -332,12 +385,12 @@ dir_entry_id_from_node(const svn_fs_id_t static svn_error_t * set_entry(dag_node_t *parent, const char *name, - const svn_fs_id_t *id, + const svn_fs_x__id_t *id, svn_node_kind_t kind, svn_fs_x__txn_id_t txn_id, apr_pool_t *pool) { - node_revision_t *parent_noderev; + svn_fs_x__noderev_t *parent_noderev; /* Get the parent's node-revision. */ SVN_ERR(get_node_revision(&parent_noderev, parent)); @@ -364,8 +417,7 @@ make_entry(dag_node_t **child_p, svn_fs_x__txn_id_t txn_id, apr_pool_t *pool) { - const svn_fs_id_t *new_node_id; - node_revision_t new_noderev, *parent_noderev; + svn_fs_x__noderev_t new_noderev, *parent_noderev; /* Make sure that NAME is a single path component. */ if (! svn_path_is_single_path_component(name)) @@ -396,20 +448,20 @@ make_entry(dag_node_t **child_p, new_noderev.copyroot_rev = parent_noderev->copyroot_rev; new_noderev.copyfrom_rev = SVN_INVALID_REVNUM; new_noderev.copyfrom_path = NULL; + svn_fs_x__id_reset(&new_noderev.predecessor_id); SVN_ERR(svn_fs_x__create_node - (&new_node_id, svn_fs_x__dag_get_fs(parent), &new_noderev, - svn_fs_x__id_copy_id(svn_fs_x__dag_get_id(parent)), - txn_id, pool)); + (svn_fs_x__dag_get_fs(parent), &new_noderev, + &parent_noderev->copy_id, txn_id, pool)); /* Create a new dag_node_t for our new node */ SVN_ERR(svn_fs_x__dag_get_node(child_p, svn_fs_x__dag_get_fs(parent), - new_node_id, pool)); + &new_noderev.noderev_id, pool)); /* We can safely call set_entry because we already know that PARENT is mutable, and we just created CHILD, so we know it has no ancestors (therefore, PARENT cannot be an ancestor of CHILD) */ - return set_entry(parent, name, svn_fs_x__dag_get_id(*child_p), + return set_entry(parent, name, &new_noderev.noderev_id, new_noderev.kind, txn_id, pool); } @@ -419,7 +471,7 @@ svn_fs_x__dag_dir_entries(apr_array_head dag_node_t *node, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; SVN_ERR(get_node_revision(&noderev, node)); @@ -431,13 +483,13 @@ svn_fs_x__dag_dir_entries(apr_array_head } svn_error_t * -svn_fs_x__dag_dir_entry(svn_fs_dirent_t **dirent, - dag_node_t *node, - const char* name, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_fs_x__dag_dir_entry(svn_fs_x__dirent_t **dirent, + dag_node_t *node, + const char* name, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; SVN_ERR(get_node_revision(&noderev, node)); if (noderev->kind != svn_node_dir) @@ -453,7 +505,7 @@ svn_fs_x__dag_dir_entry(svn_fs_dirent_t svn_error_t * svn_fs_x__dag_set_entry(dag_node_t *node, const char *entry_name, - const svn_fs_id_t *id, + const svn_fs_x__id_t *id, svn_node_kind_t kind, svn_fs_x__txn_id_t txn_id, apr_pool_t *pool) @@ -482,7 +534,7 @@ svn_fs_x__dag_get_proplist(apr_hash_t ** dag_node_t *node, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; apr_hash_t *proplist = NULL; SVN_ERR(get_node_revision(&noderev, node)); @@ -500,12 +552,12 @@ svn_fs_x__dag_set_proplist(dag_node_t *n apr_hash_t *proplist, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; /* Sanity check: this node better be mutable! */ if (! svn_fs_x__dag_check_mutable(node)) { - svn_string_t *idstr = svn_fs_x__id_unparse(node->id, pool); + svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, pool); return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, "Can't set proplist on *immutable* node-revision %s", @@ -525,12 +577,12 @@ svn_fs_x__dag_increment_mergeinfo_count( apr_int64_t increment, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; /* Sanity check: this node better be mutable! */ if (! svn_fs_x__dag_check_mutable(node)) { - svn_string_t *idstr = svn_fs_x__id_unparse(node->id, pool); + svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, pool); return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, "Can't increment mergeinfo count on *immutable* node-revision %s", @@ -546,7 +598,7 @@ svn_fs_x__dag_increment_mergeinfo_count( noderev->mergeinfo_count += increment; if (noderev->mergeinfo_count < 0) { - svn_string_t *idstr = svn_fs_x__id_unparse(node->id, pool); + svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, pool); return svn_error_createf (SVN_ERR_FS_CORRUPT, NULL, apr_psprintf(pool, @@ -557,7 +609,7 @@ svn_fs_x__dag_increment_mergeinfo_count( } if (noderev->mergeinfo_count > 1 && noderev->kind == svn_node_file) { - svn_string_t *idstr = svn_fs_x__id_unparse(node->id, pool); + svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, pool); return svn_error_createf (SVN_ERR_FS_CORRUPT, NULL, apr_psprintf(pool, @@ -568,8 +620,7 @@ svn_fs_x__dag_increment_mergeinfo_count( } /* Flush it out. */ - return svn_fs_x__put_node_revision(node->fs, noderev->id, - noderev, FALSE, pool); + return svn_fs_x__put_node_revision(node->fs, noderev, FALSE, pool); } svn_error_t * @@ -577,12 +628,12 @@ svn_fs_x__dag_set_has_mergeinfo(dag_node svn_boolean_t has_mergeinfo, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; /* Sanity check: this node better be mutable! */ if (! svn_fs_x__dag_check_mutable(node)) { - svn_string_t *idstr = svn_fs_x__id_unparse(node->id, pool); + svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, pool); return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, "Can't set mergeinfo flag on *immutable* node-revision %s", @@ -595,8 +646,7 @@ svn_fs_x__dag_set_has_mergeinfo(dag_node noderev->has_mergeinfo = has_mergeinfo; /* Flush it out. */ - return svn_fs_x__put_node_revision(node->fs, noderev->id, - noderev, FALSE, pool); + return svn_fs_x__put_node_revision(node->fs, noderev, FALSE, pool); } @@ -614,6 +664,7 @@ svn_fs_x__dag_revision_root(dag_node_t * new_node = apr_pcalloc(pool, sizeof(*new_node)); new_node->fs = fs; SVN_ERR(svn_fs_x__rev_get_root(&new_node->id, fs, rev, pool)); + svn_fs_x__id_reset(&new_node->fresh_root_predecessor_id); /* Grab the contents so we can inspect the node's kind and created path. */ new_node->node_pool = pool; @@ -621,7 +672,6 @@ svn_fs_x__dag_revision_root(dag_node_t * /* Initialize the KIND and CREATED_PATH attributes */ new_node->kind = svn_node_dir; new_node->created_path = "/"; - new_node->fresh_root_predecessor_id = NULL; /* Return a fresh new node */ *node_p = new_node; @@ -635,10 +685,10 @@ svn_fs_x__dag_txn_root(dag_node_t **node svn_fs_x__txn_id_t txn_id, apr_pool_t *pool) { - const svn_fs_id_t *root_id, *ignored; + svn_fs_x__id_t root_id; - SVN_ERR(svn_fs_x__get_txn_ids(&root_id, &ignored, fs, txn_id, pool)); - return svn_fs_x__dag_get_node(node_p, fs, root_id, pool); + svn_fs_x__init_txn_root(&root_id, txn_id); + return svn_fs_x__dag_get_node(node_p, fs, &root_id, pool); } @@ -648,10 +698,13 @@ svn_fs_x__dag_txn_base_root(dag_node_t * svn_fs_x__txn_id_t txn_id, apr_pool_t *pool) { - const svn_fs_id_t *base_root_id, *ignored; + svn_fs_x__id_t base_root_id; + svn_revnum_t base_rev; + + SVN_ERR(svn_fs_x__get_base_rev(&base_rev, fs, txn_id, pool)); - SVN_ERR(svn_fs_x__get_txn_ids(&ignored, &base_root_id, fs, txn_id, pool)); - return svn_fs_x__dag_get_node(node_p, fs, base_root_id, pool); + svn_fs_x__init_rev_root(&base_root_id, base_rev); + return svn_fs_x__dag_get_node(node_p, fs, &base_root_id, pool); } @@ -660,13 +713,13 @@ svn_fs_x__dag_clone_child(dag_node_t **c dag_node_t *parent, const char *parent_path, const char *name, - const svn_fs_x__id_part_t *copy_id, + const svn_fs_x__id_t *copy_id, svn_fs_x__txn_id_t txn_id, svn_boolean_t is_parent_copyroot, apr_pool_t *pool) { dag_node_t *cur_entry; /* parent's current entry named NAME */ - const svn_fs_id_t *new_node_id; /* node id we'll put into NEW_NODE */ + const svn_fs_x__id_t *new_node_id; /* node id we'll put into NEW_NODE */ svn_fs_t *fs = svn_fs_x__dag_get_fs(parent); apr_pool_t *subpool = svn_pool_create(pool); @@ -694,11 +747,11 @@ svn_fs_x__dag_clone_child(dag_node_t **c if (svn_fs_x__dag_check_mutable(cur_entry)) { /* This has already been cloned */ - new_node_id = cur_entry->id; + new_node_id = svn_fs_x__dag_get_id(cur_entry); } else { - node_revision_t *noderev, *parent_noderev; + svn_fs_x__noderev_t *noderev, *parent_noderev; /* Go get a fresh NODE-REVISION for current child node. */ SVN_ERR(get_node_revision(&noderev, cur_entry)); @@ -714,13 +767,16 @@ svn_fs_x__dag_clone_child(dag_node_t **c noderev->copyfrom_path = NULL; noderev->copyfrom_rev = SVN_INVALID_REVNUM; - noderev->predecessor_id = svn_fs_x__id_copy(cur_entry->id, pool); + noderev->predecessor_id = noderev->noderev_id; if (noderev->predecessor_count != -1) noderev->predecessor_count++; noderev->created_path = svn_fspath__join(parent_path, name, pool); - SVN_ERR(svn_fs_x__create_successor(&new_node_id, fs, cur_entry->id, - noderev, copy_id, txn_id, pool)); + if (copy_id == NULL) + copy_id = &noderev->copy_id; + + SVN_ERR(svn_fs_x__create_successor(fs, noderev, copy_id, txn_id, pool)); + new_node_id = &noderev->noderev_id; /* Replace the ID in the parent's ENTRY list with the ID which refers to the mutable clone of this child. */ @@ -741,24 +797,11 @@ svn_fs_x__dag_clone_root(dag_node_t **ro svn_fs_x__txn_id_t txn_id, apr_pool_t *pool) { - const svn_fs_id_t *base_root_id, *root_id; - - /* Get the node ID's of the root directories of the transaction and - its base revision. */ - SVN_ERR(svn_fs_x__get_txn_ids(&root_id, &base_root_id, fs, txn_id, pool)); - - /* Oh, give me a clone... - (If they're the same, we haven't cloned the transaction's root - directory yet.) */ - SVN_ERR_ASSERT(!svn_fs_x__id_eq(root_id, base_root_id)); - - /* - * (Sung to the tune of "Home, Home on the Range", with thanks to - * Randall Garrett and Isaac Asimov.) - */ + svn_fs_x__id_t root_id; + svn_fs_x__init_txn_root(&root_id, txn_id); /* One way or another, root_id now identifies a cloned root node. */ - return svn_fs_x__dag_get_node(root_p, fs, root_id, pool); + return svn_fs_x__dag_get_node(root_p, fs, &root_id, pool); } @@ -768,10 +811,9 @@ svn_fs_x__dag_delete(dag_node_t *parent, svn_fs_x__txn_id_t txn_id, apr_pool_t *pool) { - node_revision_t *parent_noderev; + svn_fs_x__noderev_t *parent_noderev; svn_fs_t *fs = parent->fs; - svn_fs_dirent_t *dirent; - svn_fs_id_t *id; + svn_fs_x__dirent_t *dirent; apr_pool_t *subpool; /* Make sure parent is a directory. */ @@ -809,13 +851,9 @@ svn_fs_x__dag_delete(dag_node_t *parent, (SVN_ERR_FS_NO_SUCH_ENTRY, NULL, "Delete failed--directory has no entry '%s'", name); - /* Copy the ID out of the subpool and release the rest of the - directory listing. */ - id = svn_fs_x__id_copy(dirent->id, pool); - svn_pool_destroy(subpool); - /* If mutable, remove it and any mutable children from db. */ - SVN_ERR(svn_fs_x__dag_delete_if_mutable(parent->fs, id, pool)); + SVN_ERR(svn_fs_x__dag_delete_if_mutable(parent->fs, &dirent->id, pool)); + svn_pool_destroy(subpool); /* Remove this entry from its parent's entries list. */ return svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name, @@ -824,28 +862,8 @@ svn_fs_x__dag_delete(dag_node_t *parent, svn_error_t * -svn_fs_x__dag_remove_node(svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool) -{ - dag_node_t *node; - - /* Fetch the node. */ - SVN_ERR(svn_fs_x__dag_get_node(&node, fs, id, pool)); - - /* If immutable, do nothing and return immediately. */ - if (! svn_fs_x__dag_check_mutable(node)) - return svn_error_createf(SVN_ERR_FS_NOT_MUTABLE, NULL, - "Attempted removal of immutable node"); - - /* Delete the node revision. */ - return svn_fs_x__delete_node_revision(fs, id, pool); -} - - -svn_error_t * svn_fs_x__dag_delete_if_mutable(svn_fs_t *fs, - const svn_fs_id_t *id, + const svn_fs_x__id_t *id, apr_pool_t *pool) { dag_node_t *node; @@ -862,19 +880,26 @@ svn_fs_x__dag_delete_if_mutable(svn_fs_t { apr_array_header_t *entries; int i; + apr_pool_t *iterpool = svn_pool_create(pool); /* Loop over directory entries */ SVN_ERR(svn_fs_x__dag_dir_entries(&entries, node, pool)); if (entries) for (i = 0; i < entries->nelts; ++i) - SVN_ERR(svn_fs_x__dag_delete_if_mutable(fs, - APR_ARRAY_IDX(entries, i, svn_fs_dirent_t *)->id, - pool)); + { + const svn_fs_x__id_t *noderev_id + = &APR_ARRAY_IDX(entries, i, svn_fs_x__dirent_t *)->id; + + svn_pool_clear(iterpool); + SVN_ERR(svn_fs_x__dag_delete_if_mutable(fs, noderev_id, pool)); + } + + svn_pool_destroy(iterpool); } /* ... then delete the node itself, after deleting any mutable representations and strings it points to. */ - return svn_fs_x__dag_remove_node(fs, id, pool); + return svn_fs_x__delete_node_revision(fs, id, pool); } svn_error_t * @@ -908,7 +933,7 @@ svn_fs_x__dag_get_contents(svn_stream_t dag_node_t *file, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; svn_stream_t *contents; /* Make sure our node is a file. */ @@ -936,8 +961,8 @@ svn_fs_x__dag_get_file_delta_stream(svn_ dag_node_t *target, apr_pool_t *pool) { - node_revision_t *src_noderev; - node_revision_t *tgt_noderev; + svn_fs_x__noderev_t *src_noderev; + svn_fs_x__noderev_t *tgt_noderev; /* Make sure our nodes are files. */ if ((source && source->kind != svn_node_file) @@ -966,7 +991,7 @@ svn_fs_x__dag_try_process_file_contents( void* baton, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; /* Go get fresh node-revisions for the nodes. */ SVN_ERR(get_node_revision(&noderev, node)); @@ -982,7 +1007,7 @@ svn_fs_x__dag_file_length(svn_filesize_t dag_node_t *file, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; /* Make sure our node is a file. */ if (file->kind != svn_node_file) @@ -1003,7 +1028,7 @@ svn_fs_x__dag_file_checksum(svn_checksum svn_checksum_kind_t kind, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; if (file->kind != svn_node_file) return svn_error_createf @@ -1021,7 +1046,7 @@ svn_fs_x__dag_get_edit_stream(svn_stream dag_node_t *file, apr_pool_t *pool) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; svn_stream_t *ws; /* Make sure our node is a file. */ @@ -1074,27 +1099,29 @@ svn_fs_x__dag_dup(const dag_node_t *node apr_pool_t *pool) { /* Allocate our new node. */ - dag_node_t *new_node = apr_pcalloc(pool, sizeof(*new_node)); - - new_node->fs = node->fs; - new_node->id = svn_fs_x__id_copy(node->id, pool); - new_node->kind = node->kind; + dag_node_t *new_node = apr_pmemdup(pool, node, sizeof(*new_node)); new_node->created_path = apr_pstrdup(pool, node->created_path); - /* Only copy cached node_revision_t for immutable nodes. */ + /* Only copy cached svn_fs_x__noderev_t for immutable nodes. */ if (node->node_revision && !svn_fs_x__dag_check_mutable(node)) - { - new_node->node_revision = copy_node_revision(node->node_revision, pool); - new_node->node_revision->id = - svn_fs_x__id_copy(node->node_revision->id, pool); - new_node->node_revision->is_fresh_txn_root = - node->node_revision->is_fresh_txn_root; - } + new_node->node_revision = copy_node_revision(node->node_revision, pool); + else + new_node->node_revision = NULL; + new_node->node_pool = pool; return new_node; } +dag_node_t * +svn_fs_x__dag_copy_into_pool(dag_node_t *node, + apr_pool_t *pool) +{ + return (node->node_pool == pool + ? node + : svn_fs_x__dag_dup(node, pool)); +} + svn_error_t * svn_fs_x__dag_serialize(void **data, apr_size_t *data_len, @@ -1123,8 +1150,6 @@ svn_fs_x__dag_serialize(void **data, (const void * const *)&node->node_pool); /* serialize other sub-structures */ - svn_fs_x__id_serialize(context, (const svn_fs_id_t **)&node->id); - svn_fs_x__id_serialize(context, &node->fresh_root_predecessor_id); svn_temp_serializer__add_string(context, &node->created_path); /* return serialized data */ @@ -1150,10 +1175,6 @@ svn_fs_x__dag_deserialize(void **out, node->fs = NULL; /* fixup all references to sub-structures */ - svn_fs_x__id_deserialize(node, &node->id, pool); - svn_fs_x__id_deserialize(node, - (svn_fs_id_t **)&node->fresh_root_predecessor_id, - pool); svn_fs_x__noderev_deserialize(node, &node->node_revision, pool); node->node_pool = pool; @@ -1172,12 +1193,11 @@ svn_fs_x__dag_open(dag_node_t **child_p, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - const svn_fs_id_t *node_id; + svn_fs_x__id_t node_id; /* Ensure that NAME exists in PARENT's entry list. */ - SVN_ERR(dir_entry_id_from_node(&node_id, parent, name, - scratch_pool, scratch_pool)); - if (! node_id) + SVN_ERR(dir_entry_id_from_node(&node_id, parent, name, scratch_pool)); + if (! svn_fs_x__id_used(&node_id)) { *child_p = NULL; return SVN_NO_ERROR; @@ -1191,7 +1211,7 @@ svn_fs_x__dag_open(dag_node_t **child_p, /* Now get the node that was requested. */ return svn_fs_x__dag_get_node(child_p, svn_fs_x__dag_get_fs(parent), - node_id, result_pool); + &node_id, result_pool); } @@ -1205,13 +1225,12 @@ svn_fs_x__dag_copy(dag_node_t *to_node, svn_fs_x__txn_id_t txn_id, apr_pool_t *pool) { - const svn_fs_id_t *id; + const svn_fs_x__id_t *id; if (preserve_history) { - node_revision_t *from_noderev, *to_noderev; - svn_fs_x__id_part_t copy_id; - const svn_fs_id_t *src_id = svn_fs_x__dag_get_id(from_node); + svn_fs_x__noderev_t *from_noderev, *to_noderev; + svn_fs_x__id_t copy_id; svn_fs_t *fs = svn_fs_x__dag_get_fs(from_node); /* Make a copy of the original node revision. */ @@ -1223,7 +1242,7 @@ svn_fs_x__dag_copy(dag_node_t *to_node, /* Create a successor with its predecessor pointing at the copy source. */ - to_noderev->predecessor_id = svn_fs_x__id_copy(src_id, pool); + to_noderev->predecessor_id = to_noderev->noderev_id; if (to_noderev->predecessor_count != -1) to_noderev->predecessor_count++; to_noderev->created_path = @@ -1235,9 +1254,9 @@ svn_fs_x__dag_copy(dag_node_t *to_node, /* Set the copyroot equal to our own id. */ to_noderev->copyroot_path = NULL; - SVN_ERR(svn_fs_x__create_successor(&id, fs, src_id, to_noderev, + SVN_ERR(svn_fs_x__create_successor(fs, to_noderev, ©_id, txn_id, pool)); - + id = &to_noderev->noderev_id; } else /* don't preserve history */ { @@ -1261,7 +1280,7 @@ svn_fs_x__dag_things_different(svn_boole svn_boolean_t strict, apr_pool_t *pool) { - node_revision_t *noderev1, *noderev2; + svn_fs_x__noderev_t *noderev1, *noderev2; svn_fs_t *fs; svn_boolean_t same; @@ -1297,7 +1316,7 @@ svn_fs_x__dag_get_copyroot(svn_revnum_t const char **path, dag_node_t *node) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; /* Go get a fresh node-revision for NODE. */ SVN_ERR(get_node_revision(&noderev, node)); @@ -1312,7 +1331,7 @@ svn_error_t * svn_fs_x__dag_get_copyfrom_rev(svn_revnum_t *rev, dag_node_t *node) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; /* Go get a fresh node-revision for NODE. */ SVN_ERR(get_node_revision(&noderev, node)); @@ -1326,7 +1345,7 @@ svn_error_t * svn_fs_x__dag_get_copyfrom_path(const char **path, dag_node_t *node) { - node_revision_t *noderev; + svn_fs_x__noderev_t *noderev; /* Go get a fresh node-revision for NODE. */ SVN_ERR(get_node_revision(&noderev, node)); @@ -1341,7 +1360,7 @@ svn_fs_x__dag_update_ancestry(dag_node_t dag_node_t *source, apr_pool_t *pool) { - node_revision_t *source_noderev, *target_noderev; + svn_fs_x__noderev_t *source_noderev, *target_noderev; if (! svn_fs_x__dag_check_mutable(target)) return svn_error_createf @@ -1351,11 +1370,11 @@ svn_fs_x__dag_update_ancestry(dag_node_t SVN_ERR(get_node_revision(&source_noderev, source)); SVN_ERR(get_node_revision(&target_noderev, target)); - target_noderev->predecessor_id = source->id; + target_noderev->predecessor_id = source_noderev->noderev_id; target_noderev->predecessor_count = source_noderev->predecessor_count; if (target_noderev->predecessor_count != -1) target_noderev->predecessor_count++; - return svn_fs_x__put_node_revision(target->fs, target->id, target_noderev, - FALSE, pool); + return svn_fs_x__put_node_revision(target->fs, target_noderev, FALSE, + pool); } Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/dag.h URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/dag.h?rev=1649205&r1=1649204&r2=1649205&view=diff ============================================================================== --- subversion/branches/authzperf/subversion/libsvn_fs_x/dag.h (original) +++ subversion/branches/authzperf/subversion/libsvn_fs_x/dag.h Sat Jan 3 14:00:41 2015 @@ -27,6 +27,7 @@ #include "svn_delta.h" #include "private/svn_cache.h" +#include "fs.h" #include "id.h" #ifdef __cplusplus @@ -68,7 +69,7 @@ typedef struct dag_node_t dag_node_t; svn_error_t * svn_fs_x__dag_get_node(dag_node_t **node, svn_fs_t *fs, - const svn_fs_id_t *id, + const svn_fs_x__id_t *id, apr_pool_t *pool); @@ -80,6 +81,12 @@ dag_node_t * svn_fs_x__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_x__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 * @@ -104,28 +111,49 @@ svn_fs_t *svn_fs_x__dag_get_fs(dag_node_ void svn_fs_x__dag_set_fs(dag_node_t *node, svn_fs_t *fs); -/* Set *REV to NODE's revision number, allocating in POOL. If NODE - has never been committed as part of a revision, set *REV to - SVN_INVALID_REVNUM. */ -svn_error_t *svn_fs_x__dag_get_revision(svn_revnum_t *rev, - dag_node_t *node, - apr_pool_t *pool); +/* Return NODE's revision number. If NODE has never been committed as + part of a revision, set *REV to SVN_INVALID_REVNUM. */ +svn_revnum_t svn_fs_x__dag_get_revision(const dag_node_t *node); /* Return the node revision ID of NODE. The value returned is shared with NODE, and will be deallocated when NODE is. */ -const svn_fs_id_t *svn_fs_x__dag_get_id(const dag_node_t *node); +const svn_fs_x__id_t * +svn_fs_x__dag_get_id(const dag_node_t *node); +/* Return the node ID of NODE. The value returned is shared with NODE, + and will be deallocated when NODE is. */ +svn_error_t * +svn_fs_x__dag_get_node_id(svn_fs_x__id_t *node_id, + dag_node_t *node); + +/* Return the copy ID of NODE. The value returned is shared with NODE, + and will be deallocated when NODE is. */ +svn_error_t * +svn_fs_x__dag_get_copy_id(svn_fs_x__id_t *copy_id, + dag_node_t *node); + +/* Set *SAME to TRUE, if nodes LHS and RHS have the same node ID. */ +svn_error_t * +svn_fs_x__dag_related_node(svn_boolean_t *same, + dag_node_t *lhs, + dag_node_t *rhs); + +/* Set *SAME to TRUE, if nodes LHS and RHS have the same node and copy IDs. + */ +svn_error_t * +svn_fs_x__dag_same_line_of_history(svn_boolean_t *same, + dag_node_t *lhs, + dag_node_t *rhs); /* Return the created path of NODE. The value returned is shared with NODE, and will be deallocated when NODE is. */ const char *svn_fs_x__dag_get_created_path(dag_node_t *node); -/* Set *ID_P to the node revision ID of NODE's immediate predecessor, - or NULL if NODE has no predecessor. +/* Set *ID_P to the node revision ID of NODE's immediate predecessor. */ -svn_error_t *svn_fs_x__dag_get_predecessor_id(const svn_fs_id_t **id_p, +svn_error_t *svn_fs_x__dag_get_predecessor_id(svn_fs_x__id_t *id_p, dag_node_t *node); @@ -266,7 +294,7 @@ svn_fs_x__dag_open(dag_node_t **child_p, /* Set *ENTRIES_P to an array of NODE's entries, sorted by entry names, - and the values are svn_fs_dirent_t's. The returned table (and elements) + and the values are svn_fs_x__dirent_t. The returned table (and elements) is allocated in POOL, which is also used for temporary allocations. */ svn_error_t *svn_fs_x__dag_dir_entries(apr_array_header_t **entries_p, dag_node_t *node, @@ -279,7 +307,7 @@ svn_error_t *svn_fs_x__dag_dir_entries(a Otherwise, the *DIRENT will be set to NULL. */ /* ### This function is currently only called from dag.c. */ -svn_error_t * svn_fs_x__dag_dir_entry(svn_fs_dirent_t **dirent, +svn_error_t * svn_fs_x__dag_dir_entry(svn_fs_x__dirent_t **dirent, dag_node_t *node, const char* name, apr_pool_t *result_pool, @@ -296,7 +324,7 @@ svn_error_t * svn_fs_x__dag_dir_entry(sv */ svn_error_t *svn_fs_x__dag_set_entry(dag_node_t *node, const char *entry_name, - const svn_fs_id_t *id, + const svn_fs_x__id_t *id, svn_node_kind_t kind, svn_fs_x__txn_id_t txn_id, apr_pool_t *pool); @@ -325,7 +353,7 @@ svn_error_t *svn_fs_x__dag_clone_child(d dag_node_t *parent, const char *parent_path, const char *name, - const svn_fs_x__id_part_t *copy_id, + const svn_fs_x__id_t *copy_id, svn_fs_x__txn_id_t txn_id, svn_boolean_t is_parent_copyroot, apr_pool_t *pool); @@ -349,27 +377,13 @@ svn_error_t *svn_fs_x__dag_delete(dag_no apr_pool_t *pool); -/* Delete the node revision assigned to node ID from FS's `nodes' - table, allocating from POOL. Also delete any mutable - representations and strings associated with that node revision. ID - may refer to a file or directory, which must be mutable. - - NOTE: If ID represents a directory, and that directory has mutable - children, you risk orphaning those children by leaving them - dangling, disconnected from all DAG trees. It is assumed that - callers of this interface know what in the world they are doing. */ -svn_error_t *svn_fs_x__dag_remove_node(svn_fs_t *fs, - const svn_fs_id_t *id, - apr_pool_t *pool); - - /* Delete all mutable node revisions reachable from node ID, including ID itself, from FS's `nodes' table, allocating from POOL. Also delete any mutable representations and strings associated with that node revision. ID may refer to a file or directory, which may be mutable or immutable. */ svn_error_t *svn_fs_x__dag_delete_if_mutable(svn_fs_t *fs, - const svn_fs_id_t *id, + const svn_fs_x__id_t *id, apr_pool_t *pool); Modified: subversion/branches/authzperf/subversion/libsvn_fs_x/fs.c URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_fs_x/fs.c?rev=1649205&r1=1649204&r2=1649205&view=diff ============================================================================== --- subversion/branches/authzperf/subversion/libsvn_fs_x/fs.c (original) +++ subversion/branches/authzperf/subversion/libsvn_fs_x/fs.c Sat Jan 3 14:00:41 2015 @@ -45,6 +45,7 @@ #include "revprops.h" #include "rep-cache.h" #include "transaction.h" +#include "util.h" #include "svn_private_config.h" #include "private/svn_fs_util.h" @@ -62,30 +63,38 @@ static svn_error_t * x_serialized_init(svn_fs_t *fs, apr_pool_t *common_pool, apr_pool_t *pool) { - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; const char *key; void *val; - fs_x_shared_data_t *ffsd; + svn_fs_x__shared_data_t *ffsd; apr_status_t status; /* Note that we are allocating a small amount of long-lived data for each separate repository opened during the lifetime of the 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 deconstructor + in a subpool, add a reference-count, and add a serialized destructor to the FS vtable. That's more machinery than it's worth. - Using the uuid to obtain the lock creates a corner case if a - caller uses svn_fs_set_uuid on the repository in a process where - other threads might be using the same repository through another - FS object. The only real-world consumer of svn_fs_set_uuid is - "svnadmin load", so this is a low-priority problem, and we don't - know of a better way of associating such data with the - repository. */ + 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). + + 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_FSX_SHARED_USERDATA_PREFIX, fs->uuid, - SVN_VA_NULL); + SVN_ERR_ASSERT(ffd->instance_id); + + key = apr_pstrcat(pool, SVN_FSX_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 FSX shared data")); @@ -99,13 +108,16 @@ x_serialized_init(svn_fs_t *fs, apr_pool /* POSIX fcntl locks are per-process, so we need a mutex for intra-process synchronization when grabbing the repository write lock. */ - SVN_ERR(svn_mutex__init(&ffsd->fs_write_lock, TRUE, common_pool)); + SVN_ERR(svn_mutex__init(&ffsd->fs_write_lock, + SVN_FS_X__USE_LOCK_MUTEX, common_pool)); /* ... the pack lock ... */ - SVN_ERR(svn_mutex__init(&ffsd->fs_pack_lock, TRUE, common_pool)); + SVN_ERR(svn_mutex__init(&ffsd->fs_pack_lock, + SVN_FS_X__USE_LOCK_MUTEX, common_pool)); /* ... not to mention locking the txn-current file. */ - SVN_ERR(svn_mutex__init(&ffsd->txn_current_lock, TRUE, common_pool)); + SVN_ERR(svn_mutex__init(&ffsd->txn_current_lock, + SVN_FS_X__USE_LOCK_MUTEX, common_pool)); /* We also need a mutex for synchronizing access to the active transaction list and free transaction pointer. */ @@ -158,6 +170,16 @@ x_freeze_body(void *baton, } static svn_error_t * +x_freeze_body2(void *baton, + apr_pool_t *pool) +{ + struct x_freeze_baton_t *b = baton; + SVN_ERR(svn_fs_x__with_write_lock(b->fs, x_freeze_body, baton, pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * x_freeze(svn_fs_t *fs, svn_fs_freeze_func_t freeze_func, void *freeze_baton, @@ -170,7 +192,7 @@ x_freeze(svn_fs_t *fs, b.freeze_baton = freeze_baton; SVN_ERR(svn_fs__check_fs(fs, TRUE)); - SVN_ERR(svn_fs_x__with_write_lock(fs, x_freeze_body, &b, pool)); + SVN_ERR(svn_fs_x__with_pack_lock(fs, x_freeze_body2, &b, pool)); return SVN_NO_ERROR; } @@ -181,7 +203,7 @@ x_info(const void **fsx_info, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; svn_fs_fsx_info_t *info = apr_palloc(result_pool, sizeof(*info)); info->fs_type = SVN_FS_TYPE_FSX; info->shard_size = ffd->max_files_per_dir; @@ -190,15 +212,40 @@ x_info(const void **fsx_info, return SVN_NO_ERROR; } +/* Wrapper around svn_fs_x__get_revision_proplist() adapting between function + signatures. */ +static svn_error_t * +x_revision_proplist(apr_hash_t **proplist_p, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *pool) +{ + /* No need to bypass the caches for r/o access to revprops. */ + return svn_error_trace(svn_fs_x__get_revision_proplist(proplist_p, fs, + rev, FALSE, pool)); +} + +/* Wrapper around svn_fs_x__set_uuid() adapting between function + signatures. */ +static svn_error_t * +x_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_x__set_uuid(fs, uuid, NULL, pool)); +} + /* The vtable associated with a specific open filesystem. */ static fs_vtable_t fs_vtable = { svn_fs_x__youngest_rev, svn_fs_x__revision_prop, - svn_fs_x__revision_proplist, + x_revision_proplist, svn_fs_x__change_rev_prop, - svn_fs_x__set_uuid, + x_set_uuid, svn_fs_x__revision_root, svn_fs_x__begin_txn, svn_fs_x__open_txn, @@ -225,12 +272,21 @@ static fs_vtable_t fs_vtable = { static svn_error_t * initialize_fs_struct(svn_fs_t *fs) { - fs_x_data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd)); + svn_fs_x__data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd)); 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 fsx-backed Subversion filesystem at path PATH and link it into *FS. Perform temporary allocations in POOL, and fs-global allocations @@ -298,20 +354,53 @@ x_open_for_recovery(svn_fs_t *fs, apr_pool_t *pool, apr_pool_t *common_pool) { - /* Recovery for FSX is currently limited to recreating the 'current' + 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_x__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_x__read_format_file(fs, subpool)); + + /* Now, read 'current' and try to patch it if necessary. */ + err = svn_fs_x__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_x__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_x__write_current(fs, 0, subpool)); + } + + uninitialize_fs_struct(fs); + svn_pool_destroy(subpool); /* Now open the filesystem properly by calling the vtable method directly. */ return x_open(fs, path, common_pool_lock, pool, common_pool); @@ -399,11 +488,13 @@ x_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_x__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(x_open(dst_fs, dst_path, common_pool_lock, pool, common_pool)); @@ -411,8 +502,9 @@ x_hotcopy(svn_fs_t *src_fs, SVN_ERR(cancel_func(cancel_baton)); /* Now, we may copy data as needed ... */ - return svn_fs_x__hotcopy(src_fs, dst_fs, - incremental, cancel_func, cancel_baton, pool); + return svn_fs_x__hotcopy(src_fs, dst_fs, incremental, + notify_func, notify_baton, + cancel_func, cancel_baton, pool); } @@ -443,7 +535,7 @@ x_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 * @@ -466,7 +558,7 @@ x_set_svn_fs_open(svn_fs_t *fs, apr_pool_t *, apr_pool_t *)) { - fs_x_data_t *ffd = fs->fsap_data; + svn_fs_x__data_t *ffd = fs->fsap_data; ffd->svn_fs_open_ = svn_fs_open_; return SVN_NO_ERROR; }
