You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by iv...@apache.org on 2014/06/20 02:41:21 UTC
svn commit: r1604059 [3/4] - in /subversion/branches/remove-log-addressing:
subversion/libsvn_fs_fs/ subversion/tests/libsvn_fs_fs/
tools/server-side/svnfsfs/
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/index.h
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/index.h?rev=1604059&r1=1604058&r2=1604059&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/index.h (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/index.h Fri Jun 20 00:41:20 2014
@@ -70,128 +70,6 @@ typedef struct svn_fs_fs__p2l_entry_t
svn_fs_fs__id_part_t item;
} svn_fs_fs__p2l_entry_t;
-/* Close the index file STREAM and underlying file handle. */
-svn_error_t *
-svn_fs_fs__packed_stream_close(svn_fs_fs__packed_number_stream_t *stream);
-
-/* Open / create a log-to-phys index file with the full file path name
- * FILE_NAME. Return the open file in *PROTO_INDEX and use POOL for
- * allocations.
- */
-svn_error_t *
-svn_fs_fs__l2p_proto_index_open(apr_file_t **proto_index,
- const char *file_name,
- apr_pool_t *pool);
-
-/* Call this function before adding entries for the next revision to the
- * log-to-phys index file in PROTO_INDEX. Use POOL for allocations.
- */
-svn_error_t *
-svn_fs_fs__l2p_proto_index_add_revision(apr_file_t *proto_index,
- apr_pool_t *pool);
-
-/* Add a new mapping, ITEM_INDEX to the OFFSET, to log-to-phys index file
- * in PROTO_INDEX. Please note that mappings may be added in any order
- * but duplicate entries for the same ITEM_INDEX are not supported.
- * Not all possible index values need to be used. OFFSET may be -1 to
- * mark 'invalid' item indexes but that is already implied for all item
- * indexes not explicitly given a mapping.
- *
- * Use POOL for allocations.
- */
-svn_error_t *
-svn_fs_fs__l2p_proto_index_add_entry(apr_file_t *proto_index,
- apr_off_t offset,
- apr_uint64_t item_index,
- apr_pool_t *pool);
-
-/* Use the proto index file stored at PROTO_FILE_NAME and construct the
- * final log-to-phys index file at FILE_NAME. The first revision will
- * be REVISION, entries to the next revision will be assigned to REVISION+1
- * and so forth. Use POOL for allocations.
- */
-svn_error_t *
-svn_fs_fs__l2p_index_create(svn_fs_t *fs,
- const char *file_name,
- const char *proto_file_name,
- svn_revnum_t revision,
- apr_pool_t *pool);
-
-/* Open / create a phys-to-log index file with the full file path name
- * FILE_NAME. Return the open file in *PROTO_INDEX and use POOL for
- * allocations.
- */
-svn_error_t *
-svn_fs_fs__p2l_proto_index_open(apr_file_t **proto_index,
- const char *file_name,
- apr_pool_t *pool);
-
-/* Add a new mapping ENTRY to the phys-to-log index file in PROTO_INDEX.
- * The entries must be added in ascending offset order and must not leave
- * intermittent ranges uncovered. The revision value in ENTRY may be
- * SVN_INVALID_REVISION. Use POOL for allocations.
- */
-svn_error_t *
-svn_fs_fs__p2l_proto_index_add_entry(apr_file_t *proto_index,
- svn_fs_fs__p2l_entry_t *entry,
- apr_pool_t *pool);
-
-/* Set *NEXT_OFFSET to the first offset behind the last entry in the
- * phys-to-log proto index file PROTO_INDEX. This will be 0 for empty
- * index files. Use POOL for temporary allocations.
- */
-svn_error_t *
-svn_fs_fs__p2l_proto_index_next_offset(apr_off_t *next_offset,
- apr_file_t *proto_index,
- apr_pool_t *pool);
-
-/* Use the proto index file stored at PROTO_FILE_NAME and construct the
- * final phys-to-log index file at FILE_NAME. Entries without a valid
- * revision will be assigned to the REVISION given here.
- * Use POOL for allocations.
- */
-svn_error_t *
-svn_fs_fs__p2l_index_create(svn_fs_t *fs,
- const char *file_name,
- const char *proto_file_name,
- svn_revnum_t revision,
- apr_pool_t *pool);
-
-/* Use the phys-to-log mapping files in FS to build a list of entries
- * that (at least partly) overlap with the range given by BLOCK_START
- * offset and BLOCK_SIZE in the rep / pack file containing REVISION.
- * Return the array in *ENTRIES with svn_fs_fs__p2l_entry_t as elements.
- * REV_FILE determines whether to access single rev or pack file data.
- * If that is not available anymore (neither in cache nor on disk),
- * return an error. Use POOL for allocations.
- *
- * Note that (only) the first and the last mapping may cross a cluster
- * boundary.
- */
-svn_error_t *
-svn_fs_fs__p2l_index_lookup(apr_array_header_t **entries,
- svn_fs_t *fs,
- svn_fs_fs__revision_file_t *rev_file,
- svn_revnum_t revision,
- apr_off_t block_start,
- apr_off_t block_size,
- apr_pool_t *pool);
-
-/* Use the phys-to-log mapping files in FS to return the entry for the
- * item starting at global OFFSET in the rep file containing REVISION in
- * *ENTRY. Sets *ENTRY to NULL if no item starts at exactly that offset.
- * REV_FILE determines whether to access single rev or pack file data.
- * If that is not available anymore (neither in cache nor on disk),
- * return an error. Use POOL for allocations.
- */
-svn_error_t *
-svn_fs_fs__p2l_entry_lookup(svn_fs_fs__p2l_entry_t **entry,
- svn_fs_t *fs,
- svn_fs_fs__revision_file_t *rev_file,
- svn_revnum_t revision,
- apr_off_t offset,
- apr_pool_t *pool);
-
/* For ITEM_INDEX within REV in FS, return the position in the respective
* rev or pack file in *ABSOLUTE_POSITION. If TXN_ID is not NULL, return
* the file offset within that transaction and REV should be given as
@@ -212,124 +90,4 @@ svn_fs_fs__item_offset(apr_off_t *absolu
apr_uint64_t item_index,
apr_pool_t *pool);
-/* Use the log-to-phys indexes in FS to determine the maximum item indexes
- * assigned to revision START_REV to START_REV + COUNT - 1. That is a
- * close upper limit to the actual number of items in the respective revs.
- * Return the results in *MAX_IDS, allocated in POOL.
- */
-svn_error_t *
-svn_fs_fs__l2p_get_max_ids(apr_array_header_t **max_ids,
- svn_fs_t *fs,
- svn_revnum_t start_rev,
- apr_size_t count,
- apr_pool_t *pool);
-
-/* In *OFFSET, return the last OFFSET in the pack / rev file containing.
- * REV_FILE determines whether to access single rev or pack file data.
- * If that is not available anymore (neither in cache nor on disk), re-open
- * the rev / pack file and retry to open the index file.
- * Use POOL for allocations.
- */
-svn_error_t *
-svn_fs_fs__p2l_get_max_offset(apr_off_t *offset,
- svn_fs_t *fs,
- svn_fs_fs__revision_file_t *rev_file,
- svn_revnum_t revision,
- apr_pool_t *pool);
-
-/* Serialization and caching interface
- */
-
-/* We use this key type to address individual pages from both index types.
- */
-typedef struct svn_fs_fs__page_cache_key_t
-{
- /* in l2p: this is the revision of the items being mapped
- in p2l: this is the start revision identifying the pack / rev file */
- apr_uint32_t revision;
-
- /* if TRUE, this is the index to a pack file
- */
- svn_boolean_t is_packed;
-
- /* in l2p: page number within the revision
- * in p2l: page number with the rev / pack file
- */
- apr_uint64_t page;
-} svn_fs_fs__page_cache_key_t;
-
-/*
- * Implements svn_cache__serialize_func_t for l2p_header_t objects.
- */
-svn_error_t *
-svn_fs_fs__serialize_l2p_header(void **data,
- apr_size_t *data_len,
- void *in,
- apr_pool_t *pool);
-
-/*
- * Implements svn_cache__deserialize_func_t for l2p_header_t objects.
- */
-svn_error_t *
-svn_fs_fs__deserialize_l2p_header(void **out,
- void *data,
- apr_size_t data_len,
- apr_pool_t *pool);
-
-/*
- * Implements svn_cache__serialize_func_t for l2p_page_t objects.
- */
-svn_error_t *
-svn_fs_fs__serialize_l2p_page(void **data,
- apr_size_t *data_len,
- void *in,
- apr_pool_t *pool);
-
-/*
- * Implements svn_cache__deserialize_func_t for l2p_page_t objects.
- */
-svn_error_t *
-svn_fs_fs__deserialize_l2p_page(void **out,
- void *data,
- apr_size_t data_len,
- apr_pool_t *pool);
-
-/*
- * Implements svn_cache__serialize_func_t for p2l_header_t objects.
- */
-svn_error_t *
-svn_fs_fs__serialize_p2l_header(void **data,
- apr_size_t *data_len,
- void *in,
- apr_pool_t *pool);
-
-/*
- * Implements svn_cache__deserialize_func_t for p2l_header_t objects.
- */
-svn_error_t *
-svn_fs_fs__deserialize_p2l_header(void **out,
- void *data,
- apr_size_t data_len,
- apr_pool_t *pool);
-
-/*
- * Implements svn_cache__serialize_func_t for apr_array_header_t objects
- * with elements of type svn_fs_fs__p2l_entry_t.
- */
-svn_error_t *
-svn_fs_fs__serialize_p2l_page(void **data,
- apr_size_t *data_len,
- void *in,
- apr_pool_t *pool);
-
-/*
- * Implements svn_cache__deserialize_func_t for apr_array_header_t objects
- * with elements of type svn_fs_fs__p2l_entry_t.
- */
-svn_error_t *
-svn_fs_fs__deserialize_p2l_page(void **out,
- void *data,
- apr_size_t data_len,
- apr_pool_t *pool);
-
#endif
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/pack.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/pack.c?rev=1604059&r1=1604058&r2=1604059&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/pack.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/pack.c Fri Jun 20 00:41:20 2014
@@ -35,7 +35,6 @@
#include "pack.h"
#include "util.h"
#include "id.h"
-#include "index.h"
#include "low_level.h"
#include "revprops.h"
#include "transaction.h"
@@ -131,498 +130,6 @@ typedef struct reference_t
svn_fs_fs__id_part_t from;
} reference_t;
-/* This structure keeps track of all the temporary data and status that
- * needs to be kept around during the creation of one pack file. After
- * each revision range (in case we can't process all revs at once due to
- * memory restrictions), parts of the data will get re-initialized.
- */
-typedef struct pack_context_t
-{
- /* file system that we operate on */
- svn_fs_t *fs;
-
- /* cancel function to invoke at regular intervals. May be NULL */
- svn_cancel_func_t cancel_func;
-
- /* baton to pass to CANCEL_FUNC */
- void *cancel_baton;
-
- /* first revision in the shard (and future pack file) */
- svn_revnum_t shard_rev;
-
- /* first revision in the range to process (>= SHARD_REV) */
- svn_revnum_t start_rev;
-
- /* first revision after the range to process (<= SHARD_END_REV) */
- svn_revnum_t end_rev;
-
- /* first revision after the current shard */
- svn_revnum_t shard_end_rev;
-
- /* log-to-phys proto index for the whole pack file */
- apr_file_t *proto_l2p_index;
-
- /* phys-to-log proto index for the whole pack file */
- apr_file_t *proto_p2l_index;
-
- /* full shard directory path (containing the unpacked revisions) */
- const char *shard_dir;
-
- /* full packed shard directory path (containing the pack file + indexes) */
- const char *pack_file_dir;
-
- /* full pack file path (including PACK_FILE_DIR) */
- const char *pack_file_path;
-
- /* current write position (i.e. file length) in the pack file */
- apr_off_t pack_offset;
-
- /* the pack file to ultimately write all data to */
- apr_file_t *pack_file;
-
- /* array of svn_fs_fs__p2l_entry_t *, all referring to change lists.
- * Will be filled in phase 2 and be cleared after each revision range. */
- apr_array_header_t *changes;
-
- /* temp file receiving all change list items (referenced by CHANGES).
- * Will be filled in phase 2 and be cleared after each revision range. */
- apr_file_t *changes_file;
-
- /* array of svn_fs_fs__p2l_entry_t *, all referring to file properties.
- * Will be filled in phase 2 and be cleared after each revision range. */
- apr_array_header_t *file_props;
-
- /* temp file receiving all file prop items (referenced by FILE_PROPS).
- * Will be filled in phase 2 and be cleared after each revision range.*/
- apr_file_t *file_props_file;
-
- /* array of svn_fs_fs__p2l_entry_t *, all referring to directory properties.
- * Will be filled in phase 2 and be cleared after each revision range. */
- apr_array_header_t *dir_props;
-
- /* temp file receiving all directory prop items (referenced by DIR_PROPS).
- * Will be filled in phase 2 and be cleared after each revision range.*/
- apr_file_t *dir_props_file;
-
- /* container for all PATH members in PATH_ORDER. */
- svn_prefix_tree__t *paths;
-
- /* array of path_order_t *. Will be filled in phase 2 and be cleared
- * after each revision range. Sorted by PATH, NODE_ID. */
- apr_array_header_t *path_order;
-
- /* array of reference_t* linking representations to their delta bases.
- * Will be filled in phase 2 and be cleared after each revision range.
- * It will be sorted by the FROM members (for rep->base rep lookup). */
- apr_array_header_t *references;
-
- /* array of svn_fs_fs__p2l_entry_t*. Will be filled in phase 2 and be
- * cleared after each revision range. During phase 3, we will set items
- * to NULL that we already processed. */
- apr_array_header_t *reps;
-
- /* array of int, marking for each revision, the which offset their items
- * begin in REPS. Will be filled in phase 2 and be cleared after
- * each revision range. */
- apr_array_header_t *rev_offsets;
-
- /* temp file receiving all items referenced by REPS.
- * Will be filled in phase 2 and be cleared after each revision range.*/
- apr_file_t *reps_file;
-
- /* pool used for temporary data structures that will be cleaned up when
- * the next range of revisions is being processed */
- apr_pool_t *info_pool;
-} pack_context_t;
-
-/* Create and initialize a new pack context for packing shard SHARD_REV in
- * SHARD_DIR into PACK_FILE_DIR within filesystem FS. Allocate it in POOL
- * and return the structure in *CONTEXT.
- *
- * Limit the number of items being copied per iteration to MAX_ITEMS.
- * Set CANCEL_FUNC and CANCEL_BATON as well.
- */
-static svn_error_t *
-initialize_pack_context(pack_context_t *context,
- svn_fs_t *fs,
- const char *pack_file_dir,
- const char *shard_dir,
- svn_revnum_t shard_rev,
- int max_items,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *pool)
-{
- fs_fs_data_t *ffd = fs->fsap_data;
- const char *temp_dir;
- int max_revs = MIN(ffd->max_files_per_dir, max_items);
-
- SVN_ERR_ASSERT(ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT);
- SVN_ERR_ASSERT(shard_rev % ffd->max_files_per_dir == 0);
-
- /* where we will place our various temp files */
- SVN_ERR(svn_io_temp_dir(&temp_dir, pool));
-
- /* store parameters */
- context->fs = fs;
- context->cancel_func = cancel_func;
- context->cancel_baton = cancel_baton;
-
- context->shard_rev = shard_rev;
- context->start_rev = shard_rev;
- context->end_rev = shard_rev;
- context->shard_end_rev = shard_rev + ffd->max_files_per_dir;
-
- /* Create the new directory and pack file. */
- context->shard_dir = shard_dir;
- context->pack_file_dir = pack_file_dir;
- context->pack_file_path
- = svn_dirent_join(pack_file_dir, PATH_PACKED, pool);
- SVN_ERR(svn_io_file_open(&context->pack_file, context->pack_file_path,
- APR_WRITE | APR_BUFFERED | APR_BINARY | APR_EXCL
- | APR_CREATE, APR_OS_DEFAULT, pool));
-
- /* Proto index files */
- SVN_ERR(svn_fs_fs__l2p_proto_index_open(
- &context->proto_l2p_index,
- svn_dirent_join(pack_file_dir,
- PATH_INDEX PATH_EXT_L2P_INDEX,
- pool),
- pool));
- SVN_ERR(svn_fs_fs__p2l_proto_index_open(
- &context->proto_p2l_index,
- svn_dirent_join(pack_file_dir,
- PATH_INDEX PATH_EXT_P2L_INDEX,
- pool),
- pool));
-
- /* item buckets: one item info array and one temp file per bucket */
- context->changes = apr_array_make(pool, max_items,
- sizeof(svn_fs_fs__p2l_entry_t *));
- SVN_ERR(svn_io_open_unique_file3(&context->changes_file, NULL, temp_dir,
- svn_io_file_del_on_close, pool, pool));
- context->file_props = apr_array_make(pool, max_items,
- sizeof(svn_fs_fs__p2l_entry_t *));
- SVN_ERR(svn_io_open_unique_file3(&context->file_props_file, NULL, temp_dir,
- svn_io_file_del_on_close, pool, pool));
- context->dir_props = apr_array_make(pool, max_items,
- sizeof(svn_fs_fs__p2l_entry_t *));
- SVN_ERR(svn_io_open_unique_file3(&context->dir_props_file, NULL, temp_dir,
- svn_io_file_del_on_close, pool, pool));
-
- /* noderev and representation item bucket */
- context->rev_offsets = apr_array_make(pool, max_revs, sizeof(int));
- context->path_order = apr_array_make(pool, max_items,
- sizeof(path_order_t *));
- context->references = apr_array_make(pool, max_items,
- sizeof(reference_t *));
- context->reps = apr_array_make(pool, max_items,
- sizeof(svn_fs_fs__p2l_entry_t *));
- SVN_ERR(svn_io_open_unique_file3(&context->reps_file, NULL, temp_dir,
- svn_io_file_del_on_close, pool, pool));
-
- /* the pool used for temp structures */
- context->info_pool = svn_pool_create(pool);
- context->paths = svn_prefix_tree__create(context->info_pool);
-
- return SVN_NO_ERROR;
-}
-
-/* Clean up / free all revision range specific data and files in CONTEXT.
- * Use POOL for temporary allocations.
- */
-static svn_error_t *
-reset_pack_context(pack_context_t *context,
- apr_pool_t *pool)
-{
- apr_array_clear(context->changes);
- SVN_ERR(svn_io_file_trunc(context->changes_file, 0, pool));
- apr_array_clear(context->file_props);
- SVN_ERR(svn_io_file_trunc(context->file_props_file, 0, pool));
- apr_array_clear(context->dir_props);
- SVN_ERR(svn_io_file_trunc(context->dir_props_file, 0, pool));
-
- apr_array_clear(context->rev_offsets);
- apr_array_clear(context->path_order);
- apr_array_clear(context->references);
- apr_array_clear(context->reps);
- SVN_ERR(svn_io_file_trunc(context->reps_file, 0, pool));
-
- svn_pool_clear(context->info_pool);
-
- return SVN_NO_ERROR;
-}
-
-/* Call this after the last revision range. It will finalize all index files
- * for CONTEXT and close any open files. Use POOL for temporary allocations.
- */
-static svn_error_t *
-close_pack_context(pack_context_t *context,
- apr_pool_t *pool)
-{
- const char *l2p_index_path
- = apr_pstrcat(pool, context->pack_file_path, PATH_EXT_L2P_INDEX,
- SVN_VA_NULL);
- const char *p2l_index_path
- = apr_pstrcat(pool, context->pack_file_path, PATH_EXT_P2L_INDEX,
- SVN_VA_NULL);
- const char *proto_l2p_index_path;
- const char *proto_p2l_index_path;
-
- /* need the file names for the actual index creation call further down */
- SVN_ERR(svn_io_file_name_get(&proto_l2p_index_path,
- context->proto_l2p_index, pool));
- SVN_ERR(svn_io_file_name_get(&proto_p2l_index_path,
- context->proto_p2l_index, pool));
-
- /* finalize proto index files */
- SVN_ERR(svn_io_file_close(context->proto_l2p_index, pool));
- SVN_ERR(svn_io_file_close(context->proto_p2l_index, pool));
-
- /* Create the actual index files*/
- SVN_ERR(svn_fs_fs__l2p_index_create(context->fs, l2p_index_path,
- proto_l2p_index_path,
- context->shard_rev, pool));
- SVN_ERR(svn_fs_fs__p2l_index_create(context->fs, p2l_index_path,
- proto_p2l_index_path,
- context->shard_rev, pool));
-
- /* remove proto index files */
- SVN_ERR(svn_io_remove_file2(proto_l2p_index_path, FALSE, pool));
- SVN_ERR(svn_io_remove_file2(proto_p2l_index_path, FALSE, pool));
-
- SVN_ERR(svn_io_file_close(context->pack_file, pool));
-
- return SVN_NO_ERROR;
-}
-
-/* Efficiently copy SIZE bytes from SOURCE to DEST. Invoke the CANCEL_FUNC
- * from CONTEXT at regular intervals. Use POOL for allocations.
- */
-static svn_error_t *
-copy_file_data(pack_context_t *context,
- apr_file_t *dest,
- apr_file_t *source,
- apr_off_t size,
- apr_pool_t *pool)
-{
- /* most non-representation items will be small. Minimize the buffer
- * and infrastructure overhead in that case. */
- enum { STACK_BUFFER_SIZE = 1024 };
-
- if (size < STACK_BUFFER_SIZE)
- {
- /* copy small data using a fixed-size buffer on stack */
- char buffer[STACK_BUFFER_SIZE];
- SVN_ERR(svn_io_file_read_full2(source, buffer, (apr_size_t)size,
- NULL, NULL, pool));
- SVN_ERR(svn_io_file_write_full(dest, buffer, (apr_size_t)size,
- NULL, pool));
- }
- else
- {
- /* use streaming copies for larger data blocks. That may require
- * the allocation of larger buffers and we should make sure that
- * this extra memory is released asap. */
- fs_fs_data_t *ffd = context->fs->fsap_data;
- apr_pool_t *copypool = svn_pool_create(pool);
- char *buffer = apr_palloc(copypool, ffd->block_size);
-
- while (size)
- {
- apr_size_t to_copy = (apr_size_t)(MIN(size, ffd->block_size));
- if (context->cancel_func)
- SVN_ERR(context->cancel_func(context->cancel_baton));
-
- SVN_ERR(svn_io_file_read_full2(source, buffer, to_copy,
- NULL, NULL, pool));
- SVN_ERR(svn_io_file_write_full(dest, buffer, to_copy,
- NULL, pool));
-
- size -= to_copy;
- }
-
- svn_pool_destroy(copypool);
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Writes SIZE bytes, all 0, to DEST. Uses POOL for allocations.
- */
-static svn_error_t *
-write_null_bytes(apr_file_t *dest,
- apr_off_t size,
- apr_pool_t *pool)
-{
- /* Have a collection of high-quality, easy to access NUL bytes handy. */
- enum { BUFFER_SIZE = 1024 };
- static const char buffer[BUFFER_SIZE] = { 0 };
-
- /* copy SIZE of them into the file's buffer */
- while (size)
- {
- apr_size_t to_write = MIN(size, BUFFER_SIZE);
- SVN_ERR(svn_io_file_write_full(dest, buffer, to_write, NULL, pool));
- size -= to_write;
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Copy the "simple" item (changed paths list or property representation)
- * from the current position in REV_FILE to TEMP_FILE using CONTEXT. Add
- * a copy of ENTRY to ENTRIES but with an updated offset value that points
- * to the copy destination in TEMP_FILE. Use POOL for allocations.
- */
-static svn_error_t *
-copy_item_to_temp(pack_context_t *context,
- apr_array_header_t *entries,
- apr_file_t *temp_file,
- apr_file_t *rev_file,
- svn_fs_fs__p2l_entry_t *entry,
- apr_pool_t *pool)
-{
- svn_fs_fs__p2l_entry_t *new_entry
- = apr_pmemdup(context->info_pool, entry, sizeof(*entry));
- new_entry->offset = 0;
- SVN_ERR(svn_io_file_seek(temp_file, SEEK_CUR, &new_entry->offset, pool));
- APR_ARRAY_PUSH(entries, svn_fs_fs__p2l_entry_t *) = new_entry;
-
- SVN_ERR(copy_file_data(context, temp_file, rev_file, entry->size, pool));
-
- return SVN_NO_ERROR;
-}
-
-/* Return the offset within CONTEXT->REPS that corresponds to item
- * ITEM_INDEX in REVISION.
- */
-static int
-get_item_array_index(pack_context_t *context,
- svn_revnum_t revision,
- apr_int64_t item_index)
-{
- assert(revision >= context->start_rev);
- return (int)item_index + APR_ARRAY_IDX(context->rev_offsets,
- revision - context->start_rev,
- int);
-}
-
-/* Write INFO to the correct position in CONTEXT->REP_INFOS. The latter
- * may need auto-expanding. Overwriting an array element is not allowed.
- */
-static void
-add_item_rep_mapping(pack_context_t *context,
- svn_fs_fs__p2l_entry_t *entry)
-{
- int idx;
-
- /* index of INFO */
- idx = get_item_array_index(context,
- entry->item.revision,
- entry->item.number);
-
- /* make sure the index exists in the array */
- while (context->reps->nelts <= idx)
- APR_ARRAY_PUSH(context->reps, void *) = NULL;
-
- /* set the element. If there is already an entry, there are probably
- * two items claiming to be the same -> bail out */
- assert(!APR_ARRAY_IDX(context->reps, idx, void *));
- APR_ARRAY_IDX(context->reps, idx, void *) = entry;
-}
-
-/* Return the P2L entry from CONTEXT->REPS for the given ID. If there is
- * none (or not anymore), return NULL. If RESET has been specified, set
- * the array entry to NULL after returning the entry.
- */
-static svn_fs_fs__p2l_entry_t *
-get_item(pack_context_t *context,
- const svn_fs_fs__id_part_t *id,
- svn_boolean_t reset)
-{
- svn_fs_fs__p2l_entry_t *result = NULL;
- if (id->number && id->revision >= context->start_rev)
- {
- int idx = get_item_array_index(context, id->revision, id->number);
- if (context->reps->nelts > idx)
- {
- result = APR_ARRAY_IDX(context->reps, idx, void *);
- if (result && reset)
- APR_ARRAY_IDX(context->reps, idx, void *) = NULL;
- }
- }
-
- return result;
-}
-
-/* Copy representation item identified by ENTRY from the current position
- * in REV_FILE into CONTEXT->REPS_FILE. Add all tracking into needed by
- * our placement algorithm to CONTEXT. Use POOL for temporary allocations.
- */
-static svn_error_t *
-copy_rep_to_temp(pack_context_t *context,
- apr_file_t *rev_file,
- svn_fs_fs__p2l_entry_t *entry,
- apr_pool_t *pool)
-{
- svn_fs_fs__rep_header_t *rep_header;
- svn_stream_t *stream;
- apr_off_t source_offset = entry->offset;
-
- /* create a copy of ENTRY, make it point to the copy destination and
- * store it in CONTEXT */
- entry = apr_pmemdup(context->info_pool, entry, sizeof(*entry));
- entry->offset = 0;
- SVN_ERR(svn_io_file_seek(context->reps_file, SEEK_CUR, &entry->offset,
- pool));
- add_item_rep_mapping(context, entry);
-
- /* read & parse the representation header */
- stream = svn_stream_from_aprfile2(rev_file, TRUE, pool);
- SVN_ERR(svn_fs_fs__read_rep_header(&rep_header, stream, pool));
- svn_stream_close(stream);
-
- /* if the representation is a delta against some other rep, link the two */
- if ( rep_header->type == svn_fs_fs__rep_delta
- && rep_header->base_revision >= context->start_rev)
- {
- reference_t *reference = apr_pcalloc(context->info_pool,
- sizeof(*reference));
- reference->from = entry->item;
- reference->to.revision = rep_header->base_revision;
- reference->to.number = rep_header->base_item_index;
- APR_ARRAY_PUSH(context->references, reference_t *) = reference;
- }
-
- /* copy the whole rep (including header!) to our temp file */
- SVN_ERR(svn_io_file_seek(rev_file, SEEK_SET, &source_offset, pool));
- SVN_ERR(copy_file_data(context, context->reps_file, rev_file, entry->size,
- pool));
-
- return SVN_NO_ERROR;
-}
-
-/* Directories first, dirs / files sorted by name in reverse lexical order.
- * This maximizes the chance of two items being located close to one another
- * in *all* pack files independent of their change order. It also groups
- * multi-project repos nicely according to their sub-projects. The reverse
- * order aspect gives "trunk" preference over "tags" and "branches", so
- * trunk-related items are more likely to be contiguous.
- */
-static int
-compare_dir_entries_format7(const svn_sort__item_t *a,
- const svn_sort__item_t *b)
-{
- const svn_fs_dirent_t *lhs = (const svn_fs_dirent_t *) a->value;
- const svn_fs_dirent_t *rhs = (const svn_fs_dirent_t *) b->value;
-
- if (lhs->kind != rhs->kind)
- return lhs->kind == svn_node_dir ? -1 : 1;
-
- return strcmp(lhs->name, rhs->name);
-}
-
/* Directories entries sorted by revision (decreasing - to max cache hits)
* and offset (increasing - to max benefit from APR file buffering).
*/
@@ -657,9 +164,7 @@ svn_fs_fs__order_dir_entries(svn_fs_t *f
{
apr_array_header_t *ordered
= svn_sort__hash(directory,
- svn_fs_fs__use_log_addressing(fs, revision)
- ? compare_dir_entries_format7
- : compare_dir_entries_format6,
+ compare_dir_entries_format6,
pool);
apr_array_header_t *result
@@ -673,922 +178,6 @@ svn_fs_fs__order_dir_entries(svn_fs_t *f
return result;
}
-/* Return a duplicate of the the ORIGINAL path and with special sub-strins
- * (e.g. "trunk") modified in such a way that have a lower lexicographic
- * value than any other "normal" file name.
- */
-static const char *
-tweak_path_for_ordering(const char *original,
- apr_pool_t *pool)
-{
- /* We may add further special cases as needed. */
- enum {SPECIAL_COUNT = 2};
- static const char *special[SPECIAL_COUNT] = {"trunk", "branch"};
- char *pos;
- char *path = apr_pstrdup(pool, original);
- int i;
-
- /* Replace the first char of any "special" sub-string we find by
- * a control char, i.e. '\1' .. '\31'. In the rare event that this
- * would clash with existing paths, no data will be lost but merely
- * the node ordering will be sub-optimal.
- */
- for (i = 0; i < SPECIAL_COUNT; ++i)
- for (pos = strstr(path, special[i]);
- pos;
- pos = strstr(pos + 1, special[i]))
- {
- *pos = (char)(i + '\1');
- }
-
- return path;
-}
-
-/* Copy node revision item identified by ENTRY from the current position
- * in REV_FILE into CONTEXT->REPS_FILE. Add all tracking into needed by
- * our placement algorithm to CONTEXT. Use POOL for temporary allocations.
- */
-static svn_error_t *
-copy_node_to_temp(pack_context_t *context,
- apr_file_t *rev_file,
- svn_fs_fs__p2l_entry_t *entry,
- apr_pool_t *pool)
-{
- path_order_t *path_order = apr_pcalloc(context->info_pool,
- sizeof(*path_order));
- node_revision_t *noderev;
- const char *sort_path;
- svn_stream_t *stream;
- apr_off_t source_offset = entry->offset;
-
- /* read & parse noderev */
- stream = svn_stream_from_aprfile2(rev_file, TRUE, pool);
- SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, pool));
- svn_stream_close(stream);
-
- /* create a copy of ENTRY, make it point to the copy destination and
- * store it in CONTEXT */
- entry = apr_pmemdup(context->info_pool, entry, sizeof(*entry));
- entry->offset = 0;
- SVN_ERR(svn_io_file_seek(context->reps_file, SEEK_CUR,
- &entry->offset, pool));
- add_item_rep_mapping(context, entry);
-
- /* copy the noderev to our temp file */
- SVN_ERR(svn_io_file_seek(rev_file, SEEK_SET, &source_offset, pool));
- SVN_ERR(copy_file_data(context, context->reps_file, rev_file, entry->size,
- pool));
-
- /* if the node has a data representation, make that the node's "base".
- * This will (often) cause the noderev to be placed right in front of
- * its data representation. */
-
- if (noderev->data_rep && noderev->data_rep->revision >= context->start_rev)
- {
- path_order->rep_id.revision = noderev->data_rep->revision;
- path_order->rep_id.number = noderev->data_rep->item_index;
- path_order->expanded_size = noderev->data_rep->expanded_size
- ? noderev->data_rep->expanded_size
- : noderev->data_rep->size;
- }
-
- /* Sort path is the key used for ordering noderevs and associated reps.
- * It will not be stored in the final pack file. */
- sort_path = tweak_path_for_ordering(noderev->created_path, pool);
- path_order->path = svn_prefix_string__create(context->paths, sort_path);
- path_order->node_id = *svn_fs_fs__id_node_id(noderev->id);
- path_order->revision = svn_fs_fs__id_rev(noderev->id);
- path_order->predecessor_count = noderev->predecessor_count;
- path_order->is_dir = noderev->kind == svn_node_dir;
- path_order->noderev_id = *svn_fs_fs__id_rev_item(noderev->id);
- APR_ARRAY_PUSH(context->path_order, path_order_t *) = path_order;
-
- return SVN_NO_ERROR;
-}
-
-/* implements compare_fn_t. Bring all directories in front of the files
- and sort descendingly by PATH, NODE_ID and REVISION.
- */
-static int
-compare_path_order(const path_order_t * const * lhs_p,
- const path_order_t * const * rhs_p)
-{
- const path_order_t * lhs = *lhs_p;
- const path_order_t * rhs = *rhs_p;
-
- /* cluster all directories */
- int diff = rhs->is_dir - lhs->is_dir;
- if (diff)
- return diff;
-
- /* lexicographic order on path and node (i.e. latest first) */
- diff = svn_prefix_string__compare(lhs->path, rhs->path);
- if (diff)
- return diff;
-
- /* reverse order on node (i.e. latest first) */
- diff = svn_fs_fs__id_part_compare(&rhs->node_id, &lhs->node_id);
- if (diff)
- return diff;
-
- /* reverse order on revision (i.e. latest first) */
- if (lhs->revision != rhs->revision)
- return lhs->revision < rhs->revision ? 1 : -1;
-
- return 0;
-}
-
-/* implements compare_fn_t. Sort ascendingly by FROM, TO.
- */
-static int
-compare_references(const reference_t * const * lhs_p,
- const reference_t * const * rhs_p)
-{
- const reference_t * lhs = *lhs_p;
- const reference_t * rhs = *rhs_p;
-
- int diff = svn_fs_fs__id_part_compare(&lhs->from, &rhs->from);
- return diff ? diff : svn_fs_fs__id_part_compare(&lhs->to, &rhs->to);
-}
-
-/* implements compare_fn_t. Assume ascending order by FROM.
- */
-static int
-compare_ref_to_item(const reference_t * const * lhs_p,
- const svn_fs_fs__id_part_t * rhs_p)
-{
- return svn_fs_fs__id_part_compare(&(*lhs_p)->from, rhs_p);
-}
-
-/* implements compare_fn_t. Finds the DIR / FILE boundary.
- */
-static int
-compare_is_dir(const path_order_t * const * lhs_p,
- const void *unused)
-{
- return (*lhs_p)->is_dir ? -1 : 0;
-}
-
-/* Look for the least significant bit set in VALUE and return the smallest
- * number with the same property, i.e. the largest power of 2 that is a
- * factor in VALUE. */
-static int
-roundness(int value)
-{
- return value ? value - (value & (value - 1)) : INT_MAX;
-}
-
-/* Order a range of data collected in CONTEXT such that we can place them
- * in the desired order. The input is taken from *PATH_ORDER, offsets FIRST
- * to LAST and then written in the final order to the same range in *TEMP.
- */
-static void
-sort_reps_range(pack_context_t *context,
- const path_order_t **path_order,
- const path_order_t **temp,
- int first,
- int last)
-{
- const svn_prefix_string__t *path;
- int i, dest, best;
- svn_fs_fs__id_part_t rep_id;
- fs_fs_data_t *ffd = context->fs->fsap_data;
-
- /* The logic below would fail for empty ranges. */
- if (first == last)
- return;
-
- /* Re-order noderevs like this:
- *
- * (1) Most likely to be referenced by future pack files, in path order.
- * (2) highest revision rep per path + dependency chain
- * (3) Remaining reps in path, rev order
- *
- * We simply pick & chose from the existing path, rev order.
- */
- dest = first;
- path = path_order[first]->path;
- best = first;
-
- /* (1) For each path, pick the "roundest" representation and put it in
- * front of all other nodes in the pack file. The "roundest" rep is
- * the one most likely to be referenced from future pack files, i.e. we
- * concentrate those potential "foreign link targets" in one section of
- * the pack file.
- *
- * And we only apply this to reps outside the linear deltification
- * sections because references *into* linear deltification ranges are
- * much less likely.
- */
- for (i = first; i < last; ++i)
- {
- /* Investigated all nodes for the current path? */
- if (svn_prefix_string__compare(path, path_order[i]->path))
- {
- /* next path */
- path = path_order[i]->path;
-
- /* Pick roundest non-linear deltified node. */
- if (roundness(path_order[best]->predecessor_count)
- >= ffd->max_linear_deltification)
- {
- temp[dest++] = path_order[best];
- path_order[best] = NULL;
- best = i;
- }
- }
-
- /* next entry */
- if ( roundness(path_order[best]->predecessor_count)
- < roundness(path_order[i]->predecessor_count))
- best = i;
- }
-
- /* Treat the last path the same as all others. */
- if (roundness(path_order[best]->predecessor_count)
- >= ffd->max_linear_deltification)
- {
- temp[dest++] = path_order[best];
- path_order[best] = NULL;
- }
-
- /* (2) For each (remaining) path, pick the nodes along the delta chain
- * for the highest revision. Due to our ordering, this is the first
- * node we encounter for any path.
- *
- * Most references that don't hit a delta base picked in (1), will
- * access HEAD of the respective path. Keeping all its dependency chain
- * in one place turns reconstruction into a linear scan of minimal length.
- */
- for (i = first; i < last; ++i)
- if (path_order[i])
- {
- /* This is the first path we still have to handle. */
- path = path_order[i]->path;
- rep_id = path_order[i]->rep_id;
- break;
- }
-
- for (i = first; i < last; ++i)
- if (path_order[i])
- {
- /* New path? */
- if (svn_prefix_string__compare(path, path_order[i]->path))
- {
- path = path_order[i]->path;
- rep_id = path_order[i]->rep_id;
- }
-
- /* Pick nodes along the deltification chain. Skip side-branches. */
- if (svn_fs_fs__id_part_eq(&path_order[i]->rep_id, &rep_id))
- {
- reference_t **reference;
-
- temp[dest++] = path_order[i];
- path_order[i] = NULL;
-
- reference = svn_sort__array_lookup(context->references,
- &rep_id, NULL,
- (int (*)(const void *, const void *))compare_ref_to_item);
- if (reference)
- rep_id = (*reference)->to;
- }
- }
-
- /* (3) All remaining nodes in path, rev order. Linear deltification
- * makes HEAD delta chains from (2) cover all or most of their deltas
- * in a given pack file. So, this is just a few remnants that we put
- * at the end of the pack file.
- */
- for (i = first; i < last; ++i)
- if (path_order[i])
- temp[dest++] = path_order[i];
-
- /* We now know the final ordering. */
- assert(dest == last);
-}
-
-/* Order the data collected in CONTEXT such that we can place them in the
- * desired order.
- */
-static void
-sort_reps(pack_context_t *context)
-{
- apr_pool_t *temp_pool;
- const path_order_t **temp, **path_order;
- int i, count, dir_count;
-
- /* We will later assume that there is at least one node / path.
- */
- if (context->path_order->nelts == 0)
- {
- assert(context->references->nelts == 0);
- return;
- }
-
- /* Sort containers by path and IDs, respectively.
- */
- svn_sort__array(context->path_order,
- (int (*)(const void *, const void *))compare_path_order);
- svn_sort__array(context->references,
- (int (*)(const void *, const void *))compare_references);
-
- /* Directories are already in front; sort directories section and files
- * section separately but use the same heuristics (see sub-function).
- */
- temp_pool = svn_pool_create(context->info_pool);
- count = context->path_order->nelts;
- temp = apr_pcalloc(temp_pool, count * sizeof(*temp));
- path_order = (void *)context->path_order->elts;
-
- /* Find the boundary between DIR and FILE section. */
- dir_count = svn_sort__bsearch_lower_bound(context->path_order, NULL,
- (int (*)(const void *, const void *))compare_is_dir);
-
- /* Sort those sub-sections separately. */
- sort_reps_range(context, path_order, temp, 0, dir_count);
- sort_reps_range(context, path_order, temp, dir_count, count);
-
- /* We now know the final ordering. */
- for (i = 0; i < count; ++i)
- path_order[i] = temp[i];
-
- svn_pool_destroy(temp_pool);
-}
-
-/* implements compare_fn_t. Place LHS before RHS, if the latter is older.
- */
-static int
-compare_p2l_info(const svn_fs_fs__p2l_entry_t * const * lhs,
- const svn_fs_fs__p2l_entry_t * const * rhs)
-{
- assert(*lhs != *rhs);
-
- if ((*lhs)->item.revision == (*rhs)->item.revision)
- return (*lhs)->item.number > (*rhs)->item.number ? -1 : 1;
-
- return (*lhs)->item.revision > (*rhs)->item.revision ? -1 : 1;
-}
-
-/* Sort svn_fs_fs__p2l_entry_t * array ENTRIES by age. Place the latest
- * items first.
- */
-static void
-sort_items(apr_array_header_t *entries)
-{
- svn_sort__array(entries,
- (int (*)(const void *, const void *))compare_p2l_info);
-}
-
-/* Return the remaining unused bytes in the current block in CONTEXT's
- * pack file.
- */
-static apr_ssize_t
-get_block_left(pack_context_t *context)
-{
- fs_fs_data_t *ffd = context->fs->fsap_data;
- return ffd->block_size - (context->pack_offset % ffd->block_size);
-}
-
-/* To prevent items from overlapping a block boundary, we will usually
- * put them into the next block and top up the old one with NUL bytes.
- * Pad CONTEXT's pack file to the end of the current block, if TO_ADD does
- * not fit into the current block and the padding is short enough.
- * Use POOL for allocations.
- */
-static svn_error_t *
-auto_pad_block(pack_context_t *context,
- apr_off_t to_add,
- apr_pool_t *pool)
-{
- fs_fs_data_t *ffd = context->fs->fsap_data;
-
- /* This is the maximum number of bytes "wasted" that way per block.
- * Larger items will cross the block boundaries. */
- const apr_off_t max_padding = MAX(ffd->block_size / 50, 512);
-
- /* Is wasted space small enough to align the current item to the next
- * block? */
- apr_off_t padding = get_block_left(context);
-
- if (padding < to_add && padding < max_padding)
- {
- /* Yes. To up with NUL bytes and don't forget to create
- * an P2L index entry marking this section as unused. */
- svn_fs_fs__p2l_entry_t null_entry;
-
- null_entry.offset = context->pack_offset;
- null_entry.size = padding;
- null_entry.type = SVN_FS_FS__ITEM_TYPE_UNUSED;
- null_entry.item.revision = SVN_INVALID_REVNUM;
- null_entry.item.number = SVN_FS_FS__ITEM_INDEX_UNUSED;
- null_entry.fnv1_checksum = 0;
-
- SVN_ERR(write_null_bytes(context->pack_file, padding, pool));
- SVN_ERR(svn_fs_fs__p2l_proto_index_add_entry(
- context->proto_p2l_index, &null_entry, pool));
- context->pack_offset += padding;
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Read the contents of ITEM, if not empty, from TEMP_FILE and write it
- * to CONTEXT->PACK_FILE. Use POOL for allocations.
- */
-static svn_error_t *
-store_item(pack_context_t *context,
- apr_file_t *temp_file,
- svn_fs_fs__p2l_entry_t *item,
- apr_pool_t *pool)
-{
- apr_off_t safety_margin;
-
- /* skip empty entries */
- if (item->type == SVN_FS_FS__ITEM_TYPE_UNUSED)
- return SVN_NO_ERROR;
-
- /* If the next item does not fit into the current block, auto-pad it.
- Take special care of textual noderevs since their parsers may
- prefetch up to 80 bytes and we don't want them to cross block
- boundaries. */
- safety_margin = item->type == SVN_FS_FS__ITEM_TYPE_NODEREV
- ? SVN__LINE_CHUNK_SIZE
- : 0;
- SVN_ERR(auto_pad_block(context, item->size + safety_margin, pool));
-
- /* select the item in the source file and copy it into the target
- * pack file */
- SVN_ERR(svn_io_file_seek(temp_file, SEEK_SET, &item->offset, pool));
- SVN_ERR(copy_file_data(context, context->pack_file, temp_file,
- item->size, pool));
-
- /* write index entry and update current position */
- item->offset = context->pack_offset;
- context->pack_offset += item->size;
-
- SVN_ERR(svn_fs_fs__p2l_proto_index_add_entry(context->proto_p2l_index,
- item, pool));
-
- APR_ARRAY_PUSH(context->reps, svn_fs_fs__p2l_entry_t *) = item;
-
- return SVN_NO_ERROR;
-}
-
-/* Read the contents of the non-empty items in ITEMS from TEMP_FILE and
- * write them to CONTEXT->PACK_FILE. Use POOL for allocations.
- */
-static svn_error_t *
-store_items(pack_context_t *context,
- apr_file_t *temp_file,
- apr_array_header_t *items,
- apr_pool_t *pool)
-{
- int i;
- apr_pool_t *iterpool = svn_pool_create(pool);
-
- /* copy all items in strict order */
- for (i = 0; i < items->nelts; ++i)
- {
- svn_pool_clear(iterpool);
- SVN_ERR(store_item(context, temp_file,
- APR_ARRAY_IDX(items, i, svn_fs_fs__p2l_entry_t *),
- iterpool));
- }
-
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-/* Copy (append) the items identified by svn_fs_fs__p2l_entry_t * elements
- * in ENTRIES strictly in order from TEMP_FILE into CONTEXT->PACK_FILE.
- * Use POOL for temporary allocations.
- */
-static svn_error_t *
-copy_reps_from_temp(pack_context_t *context,
- apr_file_t *temp_file,
- apr_pool_t *pool)
-{
- apr_pool_t *iterpool = svn_pool_create(pool);
- apr_array_header_t *path_order = context->path_order;
- apr_array_header_t *parts = apr_array_make(pool, 16, sizeof(void*));
- int i;
-
- /* copy items in path order. */
- for (i = 0; i < path_order->nelts; ++i)
- {
- path_order_t *current_path;
- svn_fs_fs__p2l_entry_t *node_part;
- svn_fs_fs__p2l_entry_t *rep_part;
-
- svn_pool_clear(iterpool);
-
- current_path = APR_ARRAY_IDX(path_order, i, path_order_t *);
- node_part = get_item(context, ¤t_path->noderev_id, TRUE);
- rep_part = get_item(context, ¤t_path->rep_id, TRUE);
-
- if (node_part)
- SVN_ERR(store_item(context, temp_file, node_part, iterpool));
- if (rep_part)
- SVN_ERR(store_item(context, temp_file, rep_part, iterpool));
-
- /* processed all items */
- apr_array_clear(parts);
- }
-
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-/* implements compare_fn_t. Place LHS before RHS, if the latter belongs to
- * a newer revision.
- */
-static int
-compare_p2l_info_rev(const svn_fs_fs__p2l_entry_t * const * lhs_p,
- const svn_fs_fs__p2l_entry_t * const * rhs_p)
-{
- const svn_fs_fs__p2l_entry_t * lhs = *lhs_p;
- const svn_fs_fs__p2l_entry_t * rhs = *rhs_p;
-
- if (lhs->item.revision == rhs->item.revision)
- return 0;
-
- return lhs->item.revision < rhs->item.revision ? -1 : 1;
-}
-
-/* Write the log-to-phys proto index file for CONTEXT and use POOL for
- * temporary allocations. All items in all buckets must have been placed
- * by now.
- */
-static svn_error_t *
-write_l2p_index(pack_context_t *context,
- apr_pool_t *pool)
-{
- apr_pool_t *iterpool = svn_pool_create(pool);
- svn_revnum_t prev_rev = SVN_INVALID_REVNUM;
- int i, dest;
-
- /* eliminate empty entries from CONTEXT->REPS */
- for (i = 0, dest = 0; i < context->reps->nelts; ++i)
- {
- svn_fs_fs__p2l_entry_t *entry
- = APR_ARRAY_IDX(context->reps, i, svn_fs_fs__p2l_entry_t *);
- if (entry)
- APR_ARRAY_IDX(context->reps, dest++, svn_fs_fs__p2l_entry_t *)
- = entry;
- }
- context->reps->nelts = dest;
-
- /* we need to write the l2p index revision by revision */
- svn_sort__array(context->reps,
- (int (*)(const void *, const void *))compare_p2l_info_rev);
-
- /* write index entries */
- for (i = 0; i < context->reps->nelts; ++i)
- {
- svn_fs_fs__p2l_entry_t *p2l_entry
- = APR_ARRAY_IDX(context->reps, i, svn_fs_fs__p2l_entry_t *);
- if (p2l_entry == NULL)
- continue;
-
- /* next revision? */
- if (prev_rev != p2l_entry->item.revision)
- {
- prev_rev = p2l_entry->item.revision;
- SVN_ERR(svn_fs_fs__l2p_proto_index_add_revision(
- context->proto_l2p_index, iterpool));
- }
-
- /* add entry */
- SVN_ERR(svn_fs_fs__l2p_proto_index_add_entry(context->proto_l2p_index,
- p2l_entry->offset,
- p2l_entry->item.number,
- iterpool));
-
- /* keep memory usage in check */
- if (i % 256 == 0)
- svn_pool_clear(iterpool);
- }
-
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
-/* Pack the current revision range of CONTEXT, i.e. this covers phases 2
- * to 4. Use POOL for allocations.
- */
-static svn_error_t *
-pack_range(pack_context_t *context,
- apr_pool_t *pool)
-{
- fs_fs_data_t *ffd = context->fs->fsap_data;
- apr_pool_t *revpool = svn_pool_create(pool);
- apr_pool_t *iterpool = svn_pool_create(pool);
- apr_pool_t *iterpool2 = svn_pool_create(pool);
-
- /* Phase 2: Copy items into various buckets and build tracking info */
- svn_revnum_t revision;
- for (revision = context->start_rev; revision < context->end_rev; ++revision)
- {
- apr_off_t offset = 0;
- apr_finfo_t finfo;
- svn_fs_fs__revision_file_t *rev_file;
- const char *path;
-
- svn_pool_clear(revpool);
-
- /* Get the size of the file. */
- path = svn_dirent_join(context->shard_dir,
- apr_psprintf(revpool, "%ld", revision),
- revpool);
- SVN_ERR(svn_io_stat(&finfo, path, APR_FINFO_SIZE, revpool));
- SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, context->fs,
- revision, revpool));
-
- /* store the indirect array index */
- APR_ARRAY_PUSH(context->rev_offsets, int) = context->reps->nelts;
-
- /* read the phys-to-log index file until we covered the whole rev file.
- * That index contains enough info to build both target indexes from it. */
- while (offset < finfo.size)
- {
- /* read one cluster */
- int i;
- apr_array_header_t *entries;
-
- svn_pool_clear(iterpool);
-
- SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, context->fs,
- rev_file, revision, offset,
- ffd->p2l_page_size, iterpool));
-
- for (i = 0; i < entries->nelts; ++i)
- {
- svn_fs_fs__p2l_entry_t *entry
- = &APR_ARRAY_IDX(entries, i, svn_fs_fs__p2l_entry_t);
-
- /* skip first entry if that was duplicated due crossing a
- cluster boundary */
- if (offset > entry->offset)
- continue;
-
- svn_pool_clear(iterpool2);
-
- /* process entry while inside the rev file */
- offset = entry->offset;
- if (offset < finfo.size)
- {
- SVN_ERR(svn_io_file_seek(rev_file->file, SEEK_SET, &offset,
- iterpool2));
-
- if (entry->type == SVN_FS_FS__ITEM_TYPE_CHANGES)
- SVN_ERR(copy_item_to_temp(context,
- context->changes,
- context->changes_file,
- rev_file->file, entry,
- iterpool2));
- else if (entry->type == SVN_FS_FS__ITEM_TYPE_FILE_PROPS)
- SVN_ERR(copy_item_to_temp(context,
- context->file_props,
- context->file_props_file,
- rev_file->file, entry,
- iterpool2));
- else if (entry->type == SVN_FS_FS__ITEM_TYPE_DIR_PROPS)
- SVN_ERR(copy_item_to_temp(context,
- context->dir_props,
- context->dir_props_file,
- rev_file->file, entry,
- iterpool2));
- else if ( entry->type == SVN_FS_FS__ITEM_TYPE_FILE_REP
- || entry->type == SVN_FS_FS__ITEM_TYPE_DIR_REP)
- SVN_ERR(copy_rep_to_temp(context, rev_file->file, entry,
- iterpool2));
- else if (entry->type == SVN_FS_FS__ITEM_TYPE_NODEREV)
- SVN_ERR(copy_node_to_temp(context, rev_file->file, entry,
- iterpool2));
- else
- SVN_ERR_ASSERT(entry->type == SVN_FS_FS__ITEM_TYPE_UNUSED);
-
- offset += entry->size;
- }
- }
-
- if (context->cancel_func)
- SVN_ERR(context->cancel_func(context->cancel_baton));
- }
- }
-
- svn_pool_destroy(iterpool2);
- svn_pool_destroy(iterpool);
-
- /* phase 3: placement.
- * Use "newest first" placement for simple items. */
- sort_items(context->changes);
- sort_items(context->file_props);
- sort_items(context->dir_props);
-
- /* follow dependencies recursively for noderevs and data representations */
- sort_reps(context);
-
- /* phase 4: copy bucket data to pack file. Write P2L index. */
- SVN_ERR(store_items(context, context->changes_file, context->changes,
- revpool));
- svn_pool_clear(revpool);
- SVN_ERR(store_items(context, context->file_props_file, context->file_props,
- revpool));
- svn_pool_clear(revpool);
- SVN_ERR(store_items(context, context->dir_props_file, context->dir_props,
- revpool));
- svn_pool_clear(revpool);
- SVN_ERR(copy_reps_from_temp(context, context->reps_file, revpool));
- svn_pool_clear(revpool);
-
- /* write L2P index as well (now that we know all target offsets) */
- SVN_ERR(write_l2p_index(context, revpool));
-
- svn_pool_destroy(revpool);
-
- return SVN_NO_ERROR;
-}
-
-/* Append CONTEXT->START_REV to the context's pack file with no re-ordering.
- * This function will only be used for very large revisions (>>100k changes).
- * Use POOL for temporary allocations.
- */
-static svn_error_t *
-append_revision(pack_context_t *context,
- apr_pool_t *pool)
-{
- fs_fs_data_t *ffd = context->fs->fsap_data;
- apr_off_t offset = 0;
- apr_pool_t *iterpool = svn_pool_create(pool);
- svn_fs_fs__revision_file_t *rev_file;
- apr_finfo_t finfo;
-
- /* Get the size of the file. */
- const char *path = svn_dirent_join(context->shard_dir,
- apr_psprintf(iterpool, "%ld",
- context->start_rev),
- pool);
- SVN_ERR(svn_io_stat(&finfo, path, APR_FINFO_SIZE, pool));
-
- /* Copy all the bits from the rev file to the end of the pack file. */
- SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, context->fs,
- context->start_rev, pool));
- SVN_ERR(copy_file_data(context, context->pack_file, rev_file->file,
- finfo.size, iterpool));
-
- /* mark the start of a new revision */
- SVN_ERR(svn_fs_fs__l2p_proto_index_add_revision(context->proto_l2p_index,
- pool));
-
- /* read the phys-to-log index file until we covered the whole rev file.
- * That index contains enough info to build both target indexes from it. */
- while (offset < finfo.size)
- {
- /* read one cluster */
- int i;
- apr_array_header_t *entries;
-
- svn_pool_clear(iterpool);
- SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, context->fs, rev_file,
- context->start_rev, offset,
- ffd->p2l_page_size, iterpool));
-
- for (i = 0; i < entries->nelts; ++i)
- {
- svn_fs_fs__p2l_entry_t *entry
- = &APR_ARRAY_IDX(entries, i, svn_fs_fs__p2l_entry_t);
-
- /* skip first entry if that was duplicated due crossing a
- cluster boundary */
- if (offset > entry->offset)
- continue;
-
- /* process entry while inside the rev file */
- offset = entry->offset;
- if (offset < finfo.size)
- {
- entry->offset += context->pack_offset;
- offset += entry->size;
- SVN_ERR(svn_fs_fs__l2p_proto_index_add_entry(
- context->proto_l2p_index, entry->offset,
- entry->item.number, iterpool));
- SVN_ERR(svn_fs_fs__p2l_proto_index_add_entry(
- context->proto_p2l_index, entry, iterpool));
- }
- }
- }
-
- svn_pool_destroy(iterpool);
- context->pack_offset += finfo.size;
-
- SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
-
- return SVN_NO_ERROR;
-}
-
-/* Logical addressing mode packing logic.
- *
- * Pack the revision shard starting at SHARD_REV in filesystem FS from
- * SHARD_DIR into the PACK_FILE_DIR, using POOL for allocations. Limit
- * the extra memory consumption to MAX_MEM bytes. CANCEL_FUNC and
- * CANCEL_BATON are what you think they are.
- */
-static svn_error_t *
-pack_log_addressed(svn_fs_t *fs,
- const char *pack_file_dir,
- const char *shard_dir,
- svn_revnum_t shard_rev,
- apr_size_t max_mem,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *pool)
-{
- enum
- {
- /* estimated amount of memory used to represent one item in memory
- * during rev file packing */
- PER_ITEM_MEM = APR_ALIGN_DEFAULT(sizeof(path_order_t))
- + APR_ALIGN_DEFAULT(2 *sizeof(void*))
- + APR_ALIGN_DEFAULT(sizeof(reference_t))
- + APR_ALIGN_DEFAULT(sizeof(svn_fs_fs__p2l_entry_t))
- + 6 * sizeof(void*)
- };
-
- int max_items;
- apr_array_header_t *max_ids;
- pack_context_t context = { 0 };
- int i;
- apr_size_t item_count = 0;
- apr_pool_t *iterpool = svn_pool_create(pool);
-
- /* Prevent integer overflow. We use apr arrays to process the items so
- * the maximum number of items is INT_MAX. */
- {
- apr_size_t temp = max_mem / PER_ITEM_MEM;
- SVN_ERR_ASSERT(temp <= INT_MAX);
- max_items = (int)temp;
- }
-
- /* set up a pack context */
- SVN_ERR(initialize_pack_context(&context, fs, pack_file_dir, shard_dir,
- shard_rev, max_items, cancel_func,
- cancel_baton, pool));
-
- /* phase 1: determine the size of the revisions to pack */
- SVN_ERR(svn_fs_fs__l2p_get_max_ids(&max_ids, fs, shard_rev,
- context.shard_end_rev - shard_rev,
- pool));
-
- /* pack revisions in ranges that don't exceed MAX_MEM */
- for (i = 0; i < max_ids->nelts; ++i)
- if (APR_ARRAY_IDX(max_ids, i, apr_uint64_t) + item_count <= max_items)
- {
- context.end_rev++;
- }
- else
- {
- svn_pool_clear(iterpool);
-
- /* some unpacked revisions before this one? */
- if (context.start_rev < context.end_rev)
- {
- /* pack them intelligently (might be just 1 rev but still ...) */
- SVN_ERR(pack_range(&context, iterpool));
- SVN_ERR(reset_pack_context(&context, iterpool));
- item_count = 0;
- }
-
- /* next revision range is to start with the current revision */
- context.start_rev = i + context.shard_rev;
- context.end_rev = context.start_rev + 1;
-
- /* if this is a very large revision, we must place it as is */
- if (APR_ARRAY_IDX(max_ids, i, apr_uint64_t) > max_items)
- {
- SVN_ERR(append_revision(&context, iterpool));
- context.start_rev++;
- }
- else
- item_count += (apr_size_t)APR_ARRAY_IDX(max_ids, i, apr_uint64_t);
- }
-
- /* non-empty revision range at the end? */
- if (context.start_rev < context.end_rev)
- SVN_ERR(pack_range(&context, iterpool));
-
- /* last phase: finalize indexes and clean up */
- SVN_ERR(reset_pack_context(&context, iterpool));
- SVN_ERR(close_pack_context(&context, iterpool));
- svn_pool_destroy(iterpool);
-
- return SVN_NO_ERROR;
-}
-
/* Given REV in FS, set *REV_OFFSET to REV's offset in the packed file.
Use POOL for temporary allocations. */
svn_error_t *
@@ -1765,14 +354,9 @@ pack_rev_shard(svn_fs_t *fs,
/* Create the new directory and pack file. */
SVN_ERR(svn_io_dir_make(pack_file_dir, APR_OS_DEFAULT, pool));
- /* Index information files */
- if (svn_fs_fs__use_log_addressing(fs, shard_rev))
- SVN_ERR(pack_log_addressed(fs, pack_file_dir, shard_path, shard_rev,
- max_mem, cancel_func, cancel_baton, pool));
- else
- SVN_ERR(pack_phys_addressed(pack_file_dir, shard_path, shard_rev,
- max_files_per_dir, cancel_func,
- cancel_baton, pool));
+ SVN_ERR(pack_phys_addressed(pack_file_dir, shard_path, shard_rev,
+ max_files_per_dir, cancel_func,
+ cancel_baton, pool));
SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, pool));
SVN_ERR(svn_io_set_file_read_only(pack_file_path, FALSE, pool));
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/rev_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/rev_file.c?rev=1604059&r1=1604058&r2=1604059&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/rev_file.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/rev_file.c Fri Jun 20 00:41:20 2014
@@ -22,7 +22,6 @@
#include "rev_file.h"
#include "fs_fs.h"
-#include "index.h"
#include "util.h"
#include "../libsvn_fs/fs-loader.h"
@@ -44,8 +43,6 @@ svn_fs_fs__init_revision_file(svn_fs_fs_
file->file = NULL;
file->stream = NULL;
- file->p2l_stream = NULL;
- file->l2p_stream = NULL;
file->pool = pool;
}
@@ -165,13 +162,8 @@ svn_fs_fs__close_revision_file(svn_fs_fs
if (file->file)
SVN_ERR(svn_io_file_close(file->file, file->pool));
- SVN_ERR(svn_fs_fs__packed_stream_close(file->l2p_stream));
- SVN_ERR(svn_fs_fs__packed_stream_close(file->p2l_stream));
-
file->file = NULL;
file->stream = NULL;
- file->l2p_stream = NULL;
- file->p2l_stream = NULL;
return SVN_NO_ERROR;
}
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/rev_file.h
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/rev_file.h?rev=1604059&r1=1604058&r2=1604059&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/rev_file.h (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/rev_file.h Fri Jun 20 00:41:20 2014
@@ -55,12 +55,6 @@ typedef struct svn_fs_fs__revision_file_
/* stream based on FILE and not NULL exactly when FILE is not NULL */
svn_stream_t *stream;
- /* the opened P2L index or NULL. Always NULL for txns. */
- svn_fs_fs__packed_number_stream_t *p2l_stream;
-
- /* the opened L2P index or NULL. Always NULL for txns. */
- svn_fs_fs__packed_number_stream_t *l2p_stream;
-
/* pool containing this object */
apr_pool_t *pool;
} svn_fs_fs__revision_file_t;
Modified: subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/transaction.c?rev=1604059&r1=1604058&r2=1604059&view=diff
==============================================================================
--- subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/remove-log-addressing/subversion/libsvn_fs_fs/transaction.c Fri Jun 20 00:41:20 2014
@@ -390,32 +390,6 @@ auto_truncate_proto_rev(svn_fs_t *fs,
apr_pool_t *pool)
{
/* Only relevant for newer FSFS formats. */
- if (svn_fs_fs__use_log_addressing(fs, txn_id->revision))
- {
- /* Determine file range covered by the proto-index so far. Note that
- we always append to both file, i.e. the last index entry also
- corresponds to the last addition in the rev file. */
- const char *path = svn_fs_fs__path_p2l_proto_index(fs, txn_id, pool);
- apr_file_t *file;
- apr_off_t indexed_length;
-
- SVN_ERR(svn_fs_fs__p2l_proto_index_open(&file, path, pool));
- SVN_ERR(svn_fs_fs__p2l_proto_index_next_offset(&indexed_length, file,
- pool));
- SVN_ERR(svn_io_file_close(file, pool));
-
- /* Handle mismatches. */
- if (indexed_length < actual_length)
- SVN_ERR(svn_io_file_trunc(proto_rev, indexed_length, pool));
- else if (indexed_length > actual_length)
- return svn_error_createf(SVN_ERR_FS_ITEM_INDEX_INCONSISTENT,
- NULL,
- _("p2l proto index offset %s beyond proto"
- "rev file size %s for TXN %s"),
- apr_off_t_toa(pool, indexed_length),
- apr_off_t_toa(pool, actual_length),
- svn_fs_fs__id_txn_unparse(txn_id, pool));
- }
return SVN_NO_ERROR;
}
@@ -1612,62 +1586,6 @@ svn_fs_fs__add_change(svn_fs_t *fs,
return svn_io_file_close(file, pool);
}
-/* If the transaction TXN_ID in FS uses logical addressing, store the
- * (ITEM_INDEX, OFFSET) pair in the txn's log-to-phys proto index file.
- * If FINAL_REVISION is not SVN_INVALID_REVNUM, use it to determine whether
- * to actually write to the proto-index. Use POOL for allocations.
- */
-static svn_error_t *
-store_l2p_index_entry(svn_fs_t *fs,
- const svn_fs_fs__id_part_t *txn_id,
- svn_revnum_t final_revision,
- apr_off_t offset,
- apr_uint64_t item_index,
- apr_pool_t *pool)
-{
- if (final_revision == SVN_INVALID_REVNUM)
- final_revision = txn_id->revision + 1;
-
- if (svn_fs_fs__use_log_addressing(fs, final_revision))
- {
- const char *path = svn_fs_fs__path_l2p_proto_index(fs, txn_id, pool);
- apr_file_t *file;
- SVN_ERR(svn_fs_fs__l2p_proto_index_open(&file, path, pool));
- SVN_ERR(svn_fs_fs__l2p_proto_index_add_entry(file, offset,
- item_index, pool));
- SVN_ERR(svn_io_file_close(file, pool));
- }
-
- return SVN_NO_ERROR;
-}
-
-/* If the transaction TXN_ID in FS uses logical addressing, store ENTRY
- * in the phys-to-log proto index file of transaction TXN_ID.
- * If FINAL_REVISION is not SVN_INVALID_REVNUM, use it to determine whether
- * to actually write to the proto-index. Use POOL for allocations.
- */
-static svn_error_t *
-store_p2l_index_entry(svn_fs_t *fs,
- const svn_fs_fs__id_part_t *txn_id,
- svn_revnum_t final_revision,
- svn_fs_fs__p2l_entry_t *entry,
- apr_pool_t *pool)
-{
- if (final_revision == SVN_INVALID_REVNUM)
- final_revision = txn_id->revision + 1;
-
- if (svn_fs_fs__use_log_addressing(fs, final_revision))
- {
- const char *path = svn_fs_fs__path_p2l_proto_index(fs, txn_id, pool);
- apr_file_t *file;
- SVN_ERR(svn_fs_fs__p2l_proto_index_open(&file, path, pool));
- SVN_ERR(svn_fs_fs__p2l_proto_index_add_entry(file, entry, pool));
- SVN_ERR(svn_io_file_close(file, pool));
- }
-
- return SVN_NO_ERROR;
-}
-
/* Allocate an item index for the given MY_OFFSET in the transaction TXN_ID
* of file system FS and return it in *ITEM_INDEX. For old formats, it
* will simply return the offset as item index; in new formats, it will
@@ -1687,40 +1605,7 @@ allocate_item_index(apr_uint64_t *item_i
if (final_revision == SVN_INVALID_REVNUM)
final_revision = txn_id->revision + 1;
- if (svn_fs_fs__use_log_addressing(fs, final_revision))
- {
- apr_file_t *file;
- char buffer[SVN_INT64_BUFFER_SIZE] = { 0 };
- svn_boolean_t eof = FALSE;
- apr_size_t to_write;
- apr_size_t read;
- apr_off_t offset = 0;
-
- /* read number, increment it and write it back to disk */
- SVN_ERR(svn_io_file_open(&file,
- svn_fs_fs__path_txn_item_index(fs, txn_id, pool),
- APR_READ | APR_WRITE | APR_CREATE | APR_BUFFERED,
- APR_OS_DEFAULT, pool));
- SVN_ERR(svn_io_file_read_full2(file, buffer, sizeof(buffer)-1,
- &read, &eof, pool));
- if (read)
- SVN_ERR(svn_cstring_atoui64(item_index, buffer));
- else
- *item_index = SVN_FS_FS__ITEM_INDEX_FIRST_USER;
-
- to_write = svn__ui64toa(buffer, *item_index + 1);
- SVN_ERR(svn_io_file_seek(file, SEEK_SET, &offset, pool));
- SVN_ERR(svn_io_file_write_full(file, buffer, to_write, NULL, pool));
- SVN_ERR(svn_io_file_close(file, pool));
-
- /* write log-to-phys index */
- SVN_ERR(store_l2p_index_entry(fs, txn_id, final_revision,
- my_offset, *item_index, pool));
- }
- else
- {
- *item_index = (apr_uint64_t)my_offset;
- }
+ *item_index = (apr_uint64_t)my_offset;
return SVN_NO_ERROR;
}
@@ -2315,8 +2200,6 @@ rep_write_contents_close(void *baton)
b->pool));
SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->pool));
- SVN_ERR(store_p2l_index_entry(b->fs, &rep->txn_id, SVN_INVALID_REVNUM,
- &entry, b->pool));
}
SVN_ERR(svn_io_file_close(b->file, b->pool));
@@ -2570,9 +2453,6 @@ write_container_rep(representation_t *re
fnv1a_checksum_ctx,
pool));
- SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, final_revision,
- &entry, pool));
-
/* update the representation */
rep->size = whb->size;
rep->expanded_size = whb->size;
@@ -2710,9 +2590,6 @@ write_container_delta_rep(representation
fnv1a_checksum_ctx,
pool));
- SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, final_revision,
- &entry, pool));
-
/* update the representation */
rep->expanded_size = whb->size;
rep->size = rep_end - delta_start;
@@ -2921,16 +2798,13 @@ write_final_rev(const svn_fs_id_t **new_
reset_txn_in_rep(noderev->data_rep);
noderev->data_rep->revision = rev;
- if (!svn_fs_fs__use_log_addressing(fs, rev))
- {
- /* See issue 3845. Some unknown mechanism caused the
- protorev file to get truncated, so check for that
- here. */
- if (noderev->data_rep->item_index + noderev->data_rep->size
- > initial_offset)
- return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
- _("Truncated protorev file detected"));
- }
+ /* See issue 3845. Some unknown mechanism caused the
+ protorev file to get truncated, so check for that
+ here. */
+ if (noderev->data_rep->item_index + noderev->data_rep->size
+ > initial_offset)
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ _("Truncated protorev file detected"));
}
}
@@ -2968,16 +2842,8 @@ write_final_rev(const svn_fs_id_t **new_
/* root nodes have a fixed ID in log addressing mode */
SVN_ERR(svn_fs_fs__get_file_offset(&my_offset, file, pool));
- if (svn_fs_fs__use_log_addressing(fs, rev) && at_root)
- {
- /* reference the root noderev from the log-to-phys index */
- rev_item.number = SVN_FS_FS__ITEM_INDEX_ROOT_NODE;
- SVN_ERR(store_l2p_index_entry(fs, txn_id, rev, my_offset,
- rev_item.number, pool));
- }
- else
- SVN_ERR(allocate_item_index(&rev_item.number, fs, txn_id, rev,
- my_offset, pool));
+ SVN_ERR(allocate_item_index(&rev_item.number, fs, txn_id, rev,
+ my_offset, pool));
rev_item.revision = rev;
new_id = svn_fs_fs__id_rev_create(&node_id, ©_id, &rev_item, pool);
@@ -3033,24 +2899,6 @@ write_final_rev(const svn_fs_id_t **new_
svn_fs_fs__fs_supports_mergeinfo(fs),
pool));
- /* reference the root noderev from the log-to-phys index */
- if (svn_fs_fs__use_log_addressing(fs, rev))
- {
- svn_fs_fs__p2l_entry_t entry;
- rev_item.revision = SVN_INVALID_REVNUM;
-
- entry.offset = my_offset;
- SVN_ERR(svn_fs_fs__get_file_offset(&my_offset, file, pool));
- entry.size = my_offset - entry.offset;
- entry.type = SVN_FS_FS__ITEM_TYPE_NODEREV;
- entry.item = rev_item;
- SVN_ERR(fnv1a_checksum_finalize(&entry.fnv1_checksum,
- fnv1a_checksum_ctx,
- pool));
-
- SVN_ERR(store_p2l_index_entry(fs, txn_id, rev, &entry, pool));
- }
-
/* Return our ID that references the revision file. */
*new_id_p = noderev->id;
@@ -3085,26 +2933,6 @@ write_final_changed_path_info(apr_off_t
*offset_p = offset;
- /* reference changes from the indexes */
- if (svn_fs_fs__use_log_addressing(fs, new_rev))
- {
- svn_fs_fs__p2l_entry_t entry;
-
- entry.offset = offset;
- SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool));
- entry.size = offset - entry.offset;
- entry.type = SVN_FS_FS__ITEM_TYPE_CHANGES;
- entry.item.revision = SVN_INVALID_REVNUM;
- entry.item.number = SVN_FS_FS__ITEM_INDEX_CHANGES;
- SVN_ERR(fnv1a_checksum_finalize(&entry.fnv1_checksum,
- fnv1a_checksum_ctx,
- pool));
-
- SVN_ERR(store_p2l_index_entry(fs, txn_id, new_rev, &entry, pool));
- SVN_ERR(store_l2p_index_entry(fs, txn_id, new_rev, entry.offset,
- SVN_FS_FS__ITEM_INDEX_CHANGES, pool));
- }
-
return SVN_NO_ERROR;
}
@@ -3257,38 +3085,6 @@ verify_locks(svn_fs_t *fs,
return SVN_NO_ERROR;
}
-/* Return TRUE, if transaction TXN_ID in FS definitively uses logical
- * addressing mode. Use POOL for temporary allocations.
- */
-static svn_boolean_t
-using_log_addressing(svn_fs_t *fs,
- const svn_fs_fs__id_part_t *txn_id,
- apr_pool_t *pool)
-{
- /* As long as we don't write new data representations, we won't allocate
- IDs and there is no difference between log & phys mode.
-
- After the first ID got allocated, it is logical mode and the proto-
- index file does exist.
- */
- svn_node_kind_t kind;
- const char *path = svn_fs_fs__path_l2p_proto_index(fs, txn_id, pool);
-
- svn_error_t *err = svn_io_check_path(path, &kind, pool);
- if (err)
- {
- /* We couldn't check for the presence of the index file.
-
- So, we probably won't be able to access it during later stages
- of the commit.
- */
- svn_error_clear(err);
- return FALSE;
- }
-
- return kind == svn_node_file;
-}
-
/* Return TRUE, if the file with FILENAME contains a node revision.
*/
static svn_boolean_t
@@ -3307,192 +3103,6 @@ is_noderev_file(const char *filename)
return dot_count == 2;
}
-/* Determine the checksum for the SIZE bytes of data starting at START
- * in FILE and return the result in *FNV1_CHECKSUM.
- * Use POOL for tempoary allocations.
- */
-static svn_error_t *
-fnv1a_checksum_on_file_range(apr_uint32_t *fnv1_checksum,
- apr_file_t *file,
- apr_off_t start,
- apr_off_t size,
- apr_pool_t *pool)
-{
- char *buffer = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE);
-
- svn_checksum_ctx_t *checksum_ctx
- = svn_checksum_ctx_create(svn_checksum_fnv1a_32x4, pool);
-
- SVN_ERR(svn_io_file_seek(file, APR_SET, &start, pool));
- while (size > 0)
- {
- apr_size_t to_read = MIN(size, sizeof(buffer));
-
- SVN_ERR(svn_io_file_read_full2(file, buffer, to_read, &to_read,
- NULL, pool));
- SVN_ERR(svn_checksum_update(checksum_ctx, buffer, to_read));
- size -= to_read;
- }
- SVN_ERR(fnv1a_checksum_finalize(fnv1_checksum, checksum_ctx, pool));
-
- return SVN_NO_ERROR;
-}
-
-/* qsort()-compatible comparison function sorting svn_fs_fs__p2l_entry_t
- * by offset.
- */
-static int
-compare_sort_p2l_entry(const void *a,
- const void *b)
-{
- apr_off_t lhs = ((const svn_fs_fs__p2l_entry_t *)a)->offset;
- apr_off_t rhs = ((const svn_fs_fs__p2l_entry_t *)b)->offset;
-
- return lhs < rhs ? -1 : rhs == lhs ? 0 : 1;
-}
-
-
-/* Upgrade the transaction TXN_ID in FS from physical addressing mode
- * to logical addressing mode. FINAL_REVISION is the revision that this
- * txn is being committed to. Use POOL for temporary allocations.
- */
-static svn_error_t *
-upgrade_transaction(svn_fs_t *fs,
- const svn_fs_fs__id_part_t *txn_id,
- svn_revnum_t final_revision,
- apr_file_t *proto_file,
- apr_pool_t *pool)
-{
- fs_fs_data_t *ffd = fs->fsap_data;
- apr_hash_t *dirents;
- int i;
- apr_hash_index_t* hi;
-
- /* we allocate large temporary data and want to release it asap */
-
- apr_pool_t *subpool = svn_pool_create(pool);
- apr_pool_t *iterpool = svn_pool_create(pool);
-
- apr_hash_t *id_map = apr_hash_make(subpool);
- const char *txn_dir = svn_fs_fs__path_txn_dir(fs, txn_id, subpool);
- apr_array_header_t *p2l_entries
- = apr_array_make(subpool, 16, sizeof(svn_fs_fs__p2l_entry_t));
-
- /* scan the txn directory for noderev files and patch them up */
-
- SVN_ERR(svn_io_get_dirents3(&dirents, txn_dir, TRUE, subpool, iterpool));
- for (hi = apr_hash_first(subpool, dirents); hi; hi = apr_hash_next(hi))
- {
- apr_file_t *file;
- const char *filename;
- node_revision_t *noderev;
- svn_stream_t *stream;
- const char *name;
- apr_uint64_t *old_index, *item_index, *new_index;
-
- svn_pool_clear(iterpool);
-
- /* We are only interested in file data reps of this txns.
- Older IDs remain valid because they are already committed.
- Other IDs (noderevs and their usage in directories) will only be
- assigned later anyways. */
-
- name = svn__apr_hash_index_key(hi);
- if (!is_noderev_file(name))
- continue;
-
- filename = svn_dirent_join(txn_dir, name, iterpool);
- SVN_ERR(svn_io_file_open(&file, filename,
- APR_READ | APR_WRITE | APR_BUFFERED,
- APR_OS_DEFAULT,
- iterpool));
- stream = svn_stream_from_aprfile2(file, TRUE, iterpool);
- SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, iterpool));
- if ( noderev->data_rep == NULL
- || noderev->data_rep->revision != SVN_INVALID_REVNUM
- || noderev->kind != svn_node_file)
- continue;
-
- /* We need to assign an id.
- We might already have one because of rep sharing. */
-
- item_index = &noderev->data_rep->item_index;
- new_index = apr_hash_get(id_map, item_index, sizeof(*item_index));
-
- if (new_index)
- {
- *item_index = *new_index;
- }
- else
- {
- svn_fs_fs__rep_header_t *header;
- svn_fs_fs__p2l_entry_t *entry;
-
- /* assign a logical ID and write the L2P proto-index */
-
- old_index = apr_pmemdup(subpool, item_index, sizeof(*item_index));
- SVN_ERR(allocate_item_index(item_index, fs, txn_id, final_revision,
- *old_index, iterpool));
-
- new_index = apr_pmemdup(subpool, item_index, sizeof(*item_index));
- apr_hash_set(id_map, old_index, sizeof(*old_index), new_index);
-
- /* we need to know the length of the representation header
- because it is not accounted for by the representation length */
-
- entry = apr_array_push(p2l_entries);
- entry->offset = *old_index;
- SVN_ERR(svn_io_file_seek(proto_file, APR_SET, &entry->offset,
- iterpool));
- SVN_ERR(svn_fs_fs__read_rep_header(&header,
- svn_stream_from_aprfile2(proto_file, TRUE, iterpool),
- iterpool));
-
- /* Create the corresponding entry for the P2L proto-index.
-
- We need to write that proto-index in strict offset order but
- we have no control over the order in which we traverse the
- data reps. Thus, we collect the entries in an array. */
-
- entry->size = noderev->data_rep->size + header->header_size + 7;
- /* 7 for the "ENDREP\n" */
- entry->type = SVN_FS_FS__ITEM_TYPE_FILE_REP;
- entry->item.revision = SVN_INVALID_REVNUM;
- entry->item.number = *new_index;
- SVN_ERR(fnv1a_checksum_on_file_range(&entry->fnv1_checksum,
- proto_file,
- entry->offset, entry->size,
- iterpool));
- }
-
- /* write the updated noderev to disk */
-
- SVN_ERR(svn_io_file_trunc(file, 0, iterpool));
- SVN_ERR(svn_fs_fs__write_noderev(stream, noderev, ffd->format,
- TRUE, iterpool));
- }
-
- /* Finally, write all P2L proto-index entries ordered by item offset. */
-
- qsort(p2l_entries->elts, p2l_entries->nelts, p2l_entries->elt_size,
- compare_sort_p2l_entry);
- for (i = 0; i < p2l_entries->nelts; ++i)
- {
- svn_fs_fs__p2l_entry_t *entry;
-
- svn_pool_clear(iterpool);
-
- entry = &APR_ARRAY_IDX(p2l_entries, i, svn_fs_fs__p2l_entry_t);
- SVN_ERR(store_p2l_index_entry(fs, txn_id, final_revision,
- entry, iterpool));
- }
-
- svn_pool_clear(iterpool);
- svn_pool_clear(subpool);
-
- return SVN_NO_ERROR;
-}
-
/* Return in *PATH the path to a file containing the properties that
make up the final revision properties file. This involves setting
svn:date and removing any temporary properties associated with the
@@ -3582,6 +3192,7 @@ commit_body(void *baton, apr_pool_t *poo
apr_off_t initial_offset, changed_path_offset;
const svn_fs_fs__id_part_t *txn_id = svn_fs_fs__txn_get_id(cb->txn);
apr_hash_t *changed_paths;
+ svn_stringbuf_t *trailer;
/* Read the current youngest revision and, possibly, the next available
node id and copy id (for old format filesystems). Update the cached
@@ -3615,18 +3226,6 @@ commit_body(void *baton, apr_pool_t *poo
cb->fs, txn_id, pool));
SVN_ERR(svn_fs_fs__get_file_offset(&initial_offset, proto_file, pool));
- /* Make sure that we don't try to commit an old txn that used physical
- addressing but will be committed into the revision range that requires
- logical addressing.
- */
- if (svn_fs_fs__use_log_addressing(cb->fs, new_rev)
- && !svn_fs_fs__use_log_addressing(cb->fs, txn_id->revision)
- && !using_log_addressing(cb->fs, txn_id, pool))
- {
- SVN_ERR(upgrade_transaction(cb->fs, txn_id, new_rev, proto_file, pool));
- SVN_ERR(svn_io_file_seek(proto_file, APR_SET, &initial_offset, pool));
- }
-
/* Write out all the node-revisions and directory contents. */
root_id = svn_fs_fs__id_txn_create_root(txn_id, pool);
SVN_ERR(write_final_rev(&new_root_id, proto_file, new_rev, cb->fs, root_id,
@@ -3639,18 +3238,15 @@ commit_body(void *baton, apr_pool_t *poo
cb->fs, txn_id, changed_paths,
new_rev, pool));
- if (!svn_fs_fs__use_log_addressing(cb->fs, new_rev))
- {
- /* Write the final line. */
+ /* Write the final line. */
- svn_stringbuf_t *trailer
- = svn_fs_fs__unparse_revision_trailer
- ((apr_off_t)svn_fs_fs__id_item(new_root_id),
- changed_path_offset,
- pool);
- SVN_ERR(svn_io_file_write_full(proto_file, trailer->data, trailer->len,
- NULL, pool));
- }
+ trailer
+ = svn_fs_fs__unparse_revision_trailer
+ ((apr_off_t)svn_fs_fs__id_item(new_root_id),
+ changed_path_offset,
+ pool);
+ SVN_ERR(svn_io_file_write_full(proto_file, trailer->data, trailer->len,
+ NULL, pool));
SVN_ERR(svn_io_file_flush_to_disk(proto_file, pool));
SVN_ERR(svn_io_file_close(proto_file, pool));
@@ -3696,20 +3292,6 @@ commit_body(void *baton, apr_pool_t *poo
}
}
- if (svn_fs_fs__use_log_addressing(cb->fs, new_rev))
- {
- /* Convert the index files from the proto format into their form
- in their final location */
- SVN_ERR(svn_fs_fs__l2p_index_create(cb->fs,
- svn_fs_fs__path_l2p_index(cb->fs, new_rev, FALSE, pool),
- svn_fs_fs__path_l2p_proto_index(cb->fs, txn_id, pool),
- new_rev, pool));
- SVN_ERR(svn_fs_fs__p2l_index_create(cb->fs,
- svn_fs_fs__path_p2l_index(cb->fs, new_rev, FALSE, pool),
- svn_fs_fs__path_p2l_proto_index(cb->fs, txn_id, pool),
- new_rev, pool));
- }
-
/* Move the finished rev file into place.
### This "breaks" the transaction by removing the protorev file