Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/revprops.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/revprops.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/revprops.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/revprops.c Sun Jun 14 20:58:10 2015 @@ -36,11 +36,6 @@ #include "svn_private_config.h" -/* Give writing processes 10 seconds to replace an existing revprop - file with a new one. After that time, we assume that the writing - process got aborted and that we have re-read revprops. */ -#define REVPROP_CHANGE_TIMEOUT (10 * 1000000) - svn_error_t * svn_fs_fs__upgrade_pack_revprops(svn_fs_t *fs, svn_fs_upgrade_notify_t notify_func, @@ -111,7 +106,7 @@ svn_fs_fs__upgrade_cleanup_pack_revprops apr_pool_t *iterpool = svn_pool_create(scratch_pool); const char *revsprops_dir = svn_dirent_join(fs->path, PATH_REVPROPS_DIR, scratch_pool); - + /* delete the non-packed revprops shards afterwards */ for (shard = 0; shard < first_unpacked_shard; ++shard) { @@ -415,7 +410,8 @@ parse_packed_revprops(svn_fs_t *fs, * length header to remove) */ svn_stringbuf_t *compressed = revprops->packed_revprops; svn_stringbuf_t *uncompressed = svn_stringbuf_create_empty(pool); - SVN_ERR(svn__decompress(compressed, uncompressed, APR_SIZE_MAX)); + SVN_ERR(svn__decompress(compressed->data, compressed->len, + uncompressed, APR_SIZE_MAX)); /* read first revision number and number of revisions in the pack */ stream = svn_stream_from_stringbuf(uncompressed, scratch_pool); @@ -657,17 +653,23 @@ write_non_packed_revprop(const char **fi apr_hash_t *proplist, apr_pool_t *pool) { + apr_file_t *file; svn_stream_t *stream; *final_path = svn_fs_fs__path_revprops(fs, rev, pool); /* ### do we have a directory sitting around already? we really shouldn't ### have to get the dirname here. */ - SVN_ERR(svn_stream_open_unique(&stream, tmp_path, - svn_dirent_dirname(*final_path, pool), - svn_io_file_del_none, pool, pool)); + SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, + svn_dirent_dirname(*final_path, pool), + svn_io_file_del_none, pool, pool)); + stream = svn_stream_from_aprfile2(file, TRUE, pool); SVN_ERR(svn_hash_write2(proplist, stream, SVN_HASH_TERMINATOR, pool)); SVN_ERR(svn_stream_close(stream)); + /* Flush temporary file to disk and close it. */ + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); + return SVN_NO_ERROR; } @@ -750,7 +752,7 @@ serialize_revprops_header(svn_stream_t * return SVN_NO_ERROR; } -/* Writes the a pack file to FILE_STREAM. It copies the serialized data +/* Writes the a pack file to FILE. It copies the serialized data * from REVPROPS for the indexes [START,END) except for index CHANGED_INDEX. * * The data for the latter is taken from NEW_SERIALIZED. Note, that @@ -768,7 +770,7 @@ repack_revprops(svn_fs_t *fs, int changed_index, svn_stringbuf_t *new_serialized, apr_off_t new_total_size, - svn_stream_t *file_stream, + apr_file_t *file, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; @@ -810,15 +812,17 @@ repack_revprops(svn_fs_t *fs, SVN_ERR(svn_stream_close(stream)); /* compress / store the data */ - SVN_ERR(svn__compress(uncompressed, + SVN_ERR(svn__compress(uncompressed->data, uncompressed->len, compressed, ffd->compress_packed_revprops ? SVN_DELTA_COMPRESSION_LEVEL_DEFAULT : SVN_DELTA_COMPRESSION_LEVEL_NONE)); - /* finally, write the content to the target stream and close it */ - SVN_ERR(svn_stream_write(file_stream, compressed->data, &compressed->len)); - SVN_ERR(svn_stream_close(file_stream)); + /* finally, write the content to the target file, flush and close it */ + SVN_ERR(svn_io_file_write_full(file, compressed->data, compressed->len, + NULL, pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR; } @@ -826,23 +830,22 @@ repack_revprops(svn_fs_t *fs, /* Allocate a new pack file name for revisions * [REVPROPS->START_REVISION + START, REVPROPS->START_REVISION + END - 1] * of REVPROPS->MANIFEST. Add the name of old file to FILES_TO_DELETE, - * auto-create that array if necessary. Return an open file stream to - * the new file in *STREAM allocated in POOL. + * auto-create that array if necessary. Return an open file *FILE that is + * allocated in POOL. */ static svn_error_t * -repack_stream_open(svn_stream_t **stream, - svn_fs_t *fs, - packed_revprops_t *revprops, - int start, - int end, - apr_array_header_t **files_to_delete, - apr_pool_t *pool) +repack_file_open(apr_file_t **file, + svn_fs_t *fs, + packed_revprops_t *revprops, + int start, + int end, + apr_array_header_t **files_to_delete, + apr_pool_t *pool) { apr_int64_t tag; const char *tag_string; svn_string_t *new_filename; int i; - apr_file_t *file; int manifest_offset = (int)(revprops->start_revision - revprops->manifest_start); @@ -874,12 +877,11 @@ repack_stream_open(svn_stream_t **stream APR_ARRAY_IDX(revprops->manifest, i + manifest_offset, const char*) = new_filename->data; - /* create a file stream for the new file */ - SVN_ERR(svn_io_file_open(&file, svn_dirent_join(revprops->folder, - new_filename->data, - pool), + /* open the file */ + SVN_ERR(svn_io_file_open(file, svn_dirent_join(revprops->folder, + new_filename->data, + pool), APR_WRITE | APR_CREATE, APR_OS_DEFAULT, pool)); - *stream = svn_stream_from_aprfile2(file, FALSE, pool); return SVN_NO_ERROR; } @@ -903,6 +905,7 @@ write_packed_revprop(const char **final_ packed_revprops_t *revprops; apr_int64_t generation = 0; svn_stream_t *stream; + apr_file_t *file; svn_stringbuf_t *serialized; apr_off_t new_total_size; int changed_index; @@ -933,11 +936,11 @@ write_packed_revprop(const char **final_ *final_path = svn_dirent_join(revprops->folder, revprops->filename, pool); - SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder, - svn_io_file_del_none, pool, pool)); + SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder, + svn_io_file_del_none, pool, pool)); SVN_ERR(repack_revprops(fs, revprops, 0, revprops->sizes->nelts, changed_index, serialized, new_total_size, - stream, pool)); + file, pool)); } else { @@ -983,50 +986,51 @@ write_packed_revprop(const char **final_ /* write the new, split files */ if (left_count) { - SVN_ERR(repack_stream_open(&stream, fs, revprops, 0, - left_count, files_to_delete, pool)); + SVN_ERR(repack_file_open(&file, fs, revprops, 0, + left_count, files_to_delete, pool)); SVN_ERR(repack_revprops(fs, revprops, 0, left_count, changed_index, serialized, new_total_size, - stream, pool)); + file, pool)); } if (left_count + right_count < revprops->sizes->nelts) { - SVN_ERR(repack_stream_open(&stream, fs, revprops, changed_index, - changed_index + 1, files_to_delete, - pool)); + SVN_ERR(repack_file_open(&file, fs, revprops, changed_index, + changed_index + 1, files_to_delete, + pool)); SVN_ERR(repack_revprops(fs, revprops, changed_index, changed_index + 1, changed_index, serialized, new_total_size, - stream, pool)); + file, pool)); } if (right_count) { - SVN_ERR(repack_stream_open(&stream, fs, revprops, - revprops->sizes->nelts - right_count, - revprops->sizes->nelts, - files_to_delete, pool)); + SVN_ERR(repack_file_open(&file, fs, revprops, + revprops->sizes->nelts - right_count, + revprops->sizes->nelts, + files_to_delete, pool)); SVN_ERR(repack_revprops(fs, revprops, revprops->sizes->nelts - right_count, revprops->sizes->nelts, changed_index, - serialized, new_total_size, stream, + serialized, new_total_size, file, pool)); } /* write the new manifest */ *final_path = svn_dirent_join(revprops->folder, PATH_MANIFEST, pool); - SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder, - svn_io_file_del_none, pool, pool)); - + SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder, + svn_io_file_del_none, pool, pool)); + stream = svn_stream_from_aprfile2(file, TRUE, pool); for (i = 0; i < revprops->manifest->nelts; ++i) { const char *filename = APR_ARRAY_IDX(revprops->manifest, i, const char*); SVN_ERR(svn_stream_printf(stream, pool, "%s\n", filename)); } - SVN_ERR(svn_stream_close(stream)); + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); } return SVN_NO_ERROR; @@ -1165,7 +1169,6 @@ svn_fs_fs__copy_revprops(const char *pac apr_file_t *pack_file; svn_revnum_t rev; apr_pool_t *iterpool = svn_pool_create(scratch_pool); - svn_stream_t *stream; /* create empty data buffer and a write stream on top of it */ svn_stringbuf_t *uncompressed @@ -1189,6 +1192,7 @@ svn_fs_fs__copy_revprops(const char *pac for (rev = start_rev; rev <= end_rev; rev++) { const char *path; + svn_stream_t *stream; svn_pool_clear(iterpool); @@ -1207,12 +1211,14 @@ svn_fs_fs__copy_revprops(const char *pac SVN_ERR(svn_stream_close(pack_stream)); /* compress the content (or just store it for COMPRESSION_LEVEL 0) */ - SVN_ERR(svn__compress(uncompressed, compressed, compression_level)); + SVN_ERR(svn__compress(uncompressed->data, uncompressed->len, + compressed, compression_level)); /* write the pack file content to disk */ - stream = svn_stream_from_aprfile2(pack_file, FALSE, scratch_pool); - SVN_ERR(svn_stream_write(stream, compressed->data, &compressed->len)); - SVN_ERR(svn_stream_close(stream)); + SVN_ERR(svn_io_file_write_full(pack_file, compressed->data, compressed->len, + NULL, scratch_pool)); + SVN_ERR(svn_io_file_flush_to_disk(pack_file, scratch_pool)); + SVN_ERR(svn_io_file_close(pack_file, scratch_pool)); svn_pool_destroy(iterpool); @@ -1231,6 +1237,7 @@ svn_fs_fs__pack_revprops_shard(const cha apr_pool_t *scratch_pool) { const char *manifest_file_path, *pack_filename = NULL; + apr_file_t *manifest_file; svn_stream_t *manifest_stream; svn_revnum_t start_rev, end_rev, rev; apr_off_t total_size; @@ -1247,8 +1254,12 @@ svn_fs_fs__pack_revprops_shard(const cha /* Create the new directory and manifest file stream. */ SVN_ERR(svn_io_dir_make(pack_file_dir, APR_OS_DEFAULT, scratch_pool)); - SVN_ERR(svn_stream_open_writable(&manifest_stream, manifest_file_path, - scratch_pool, scratch_pool)); + + SVN_ERR(svn_io_file_open(&manifest_file, manifest_file_path, + APR_WRITE | APR_BUFFERED | APR_CREATE | APR_EXCL, + APR_OS_DEFAULT, scratch_pool)); + manifest_stream = svn_stream_from_aprfile2(manifest_file, TRUE, + scratch_pool); /* revisions to handle. Special case: revision 0 */ start_rev = (svn_revnum_t) (shard * max_files_per_dir); @@ -1315,8 +1326,10 @@ svn_fs_fs__pack_revprops_shard(const cha compression_level, cancel_func, cancel_baton, iterpool)); - /* flush the manifest file and update permissions */ + /* flush the manifest file to disk and update permissions */ SVN_ERR(svn_stream_close(manifest_stream)); + SVN_ERR(svn_io_file_flush_to_disk(manifest_file, iterpool)); + SVN_ERR(svn_io_file_close(manifest_file, iterpool)); SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, iterpool)); svn_pool_destroy(iterpool); @@ -1347,7 +1360,7 @@ svn_fs_fs__delete_revprops_shard(const c apr_psprintf(iterpool, "%d", i), iterpool); if (cancel_func) - SVN_ERR((*cancel_func)(cancel_baton)); + SVN_ERR(cancel_func(cancel_baton)); SVN_ERR(svn_io_remove_file2(path, TRUE, iterpool)); }
Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/revprops.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/revprops.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/revprops.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/revprops.h Sun Jun 14 20:58:10 2015 @@ -23,12 +23,12 @@ #include "svn_fs.h" /* In the filesystem FS, pack all revprop shards up to min_unpacked_rev. - * + * * NOTE: Keep the old non-packed shards around until after the format bump. * Otherwise, re-running upgrade will drop the packed revprop shard but * have no unpacked data anymore. Call upgrade_cleanup_pack_revprops after * the bump. - * + * * NOTIFY_FUNC and NOTIFY_BATON as well as CANCEL_FUNC and CANCEL_BATON are * used in the usual way. Temporary allocations are done in SCRATCH_POOL. */ @@ -42,7 +42,7 @@ svn_fs_fs__upgrade_pack_revprops(svn_fs_ /* In the filesystem FS, remove all non-packed revprop shards up to * min_unpacked_rev. Temporary allocations are done in SCRATCH_POOL. - * + * * NOTIFY_FUNC and NOTIFY_BATON as well as CANCEL_FUNC and CANCEL_BATON are * used in the usual way. Cancellation is supported in the sense that we * will cleanly abort the operation. However, there will be remnant shards @@ -79,7 +79,7 @@ svn_fs_fs__set_revision_proplist(svn_fs_ /* Return TRUE, if for REVISION in FS, we can find the revprop pack file. * Use POOL for temporary allocations. - * Set *MISSING, if the reason is a missing manifest or pack file. + * Set *MISSING, if the reason is a missing manifest or pack file. */ svn_boolean_t svn_fs_fs__packed_revprop_available(svn_boolean_t *missing, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/stats.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/stats.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/stats.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/stats.c Sun Jun 14 20:58:10 2015 @@ -176,23 +176,6 @@ typedef struct query_t void *cancel_baton; } query_t; -/* Return the length of REV_FILE in *FILE_SIZE. - * Use SCRATCH_POOL for temporary allocations. - */ -static svn_error_t * -get_file_size(apr_off_t *file_size, - svn_fs_fs__revision_file_t *rev_file, - apr_pool_t *scratch_pool) -{ - apr_finfo_t finfo; - - SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, rev_file->file, - scratch_pool)); - - *file_size = finfo.size; - return SVN_NO_ERROR; -} - /* Initialize the LARGEST_CHANGES member in STATS with a capacity of COUNT * entries. Allocate the result in RESULT_POOL. */ @@ -300,7 +283,7 @@ add_change(svn_fs_fs__stats_t *stats, add_to_histogram(&stats->dir_prop_rep_histogram, rep_size); add_to_histogram(&stats->dir_prop_histogram, expanded_size); break; - case file_property_rep: + case file_property_rep: add_to_histogram(&stats->file_prop_rep_histogram, rep_size); add_to_histogram(&stats->file_prop_histogram, expanded_size); break; @@ -436,8 +419,7 @@ parse_representation(rep_stats_t **repre */ result = apr_pcalloc(result_pool, sizeof(*result)); result->revision = rep->revision; - result->expanded_size = (rep->expanded_size ? rep->expanded_size - : rep->size); + result->expanded_size = rep->expanded_size; result->offset = (apr_off_t)rep->item_index; result->size = rep->size; @@ -695,7 +677,7 @@ read_phys_revision(query_t *query, trailer = svn_stringbuf_ncreate(buf, len, scratch_pool); /* Parse that trailer. */ - SVN_ERR(svn_fs_fs__parse_revision_trailer(&root_node_offset, + SVN_ERR(svn_fs_fs__parse_revision_trailer(&root_node_offset, &changes_offset, trailer, info->revision)); SVN_ERR(get_phys_change_count(query, info, scratch_pool)); @@ -729,12 +711,12 @@ read_phys_pack_file(query_t *query, { apr_pool_t *iterpool = svn_pool_create(scratch_pool); int i; - apr_off_t file_size = 0; + svn_filesize_t file_size = 0; svn_fs_fs__revision_file_t *rev_file; SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, query->fs, base, scratch_pool, scratch_pool)); - SVN_ERR(get_file_size(&file_size, rev_file, scratch_pool)); + SVN_ERR(svn_io_file_size_get(&file_size, rev_file->file, scratch_pool)); /* process each revision in the pack file */ for (i = 0; i < query->shard_size; ++i) @@ -798,7 +780,7 @@ read_phys_revision_file(query_t *query, apr_pool_t *scratch_pool) { revision_info_t *info = apr_pcalloc(result_pool, sizeof(*info)); - apr_off_t file_size = 0; + svn_filesize_t file_size = 0; svn_fs_fs__revision_file_t *rev_file; /* cancellation support */ @@ -808,7 +790,7 @@ read_phys_revision_file(query_t *query, /* read the whole pack file into memory */ SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, query->fs, revision, scratch_pool, scratch_pool)); - SVN_ERR(get_file_size(&file_size, rev_file, scratch_pool)); + SVN_ERR(svn_io_file_size_get(&file_size, rev_file->file, scratch_pool)); /* create the revision info for the current rev */ info->representations = apr_array_make(result_pool, 4, sizeof(rep_stats_t*)); Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/structure URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/structure?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/structure (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/structure Sun Jun 14 20:58:10 2015 @@ -198,9 +198,9 @@ Shard packing: (i.e. same min packed revision) Addressing: - Format 1-6: Physical addressing; uses fixed positions within a rev file + Format 1+: Physical addressing; uses fixed positions within a rev file Format 7+: Logical addressing; uses item index that will be translated - on-the-fly to the actual rev / pack file location + on-the-fly to the actual rev / pack file location (default for 7+ created) Repository IDs: Format 1+: The first line of db/uuid contains the repository UUID @@ -525,6 +525,7 @@ A revision file contains a concatenation * Text and property representations * Node-revisions * The changed-path data + * Two offsets at the very end (physical addressing only) * Index data (logical addressing only) * Revision / pack file footer (logical addressing only) @@ -578,8 +579,9 @@ defined: representations may not be handled correctly by SVN before 1.7.20, 1.8.12 and 1.9.0, if they have 0 <size> fields for non-empty contents. Releases 1.8.0 through 1.8.11 may have falsely created instances of - that (see issue #4554). Finally, 0 <size> fields are NEVER legal for - DELTA representations. + that (see issue #4554). Finally, 0 <size> fields are only ever legal + for DELTA representations if the reconstructed full-text is actually + empty. The predecessor of a node-rev crosses both soft and true copies; together with the count field, it allows efficient determination of @@ -756,6 +758,9 @@ Format 7 introduces logical addressing t to be translated / mapped to physical rev / pack file offsets. These indexes are appended to the respective rev / pack file. +The indexes map (revision number, item-index) pairs to absolute file offsets +and absolute file offsets to (revision number, item-index, item metadata). + Details of the binary format used by these index files can be found in structure-indexes. Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/structure-indexes URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/structure-indexes?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/structure-indexes (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/structure-indexes Sun Jun 14 20:58:10 2015 @@ -13,10 +13,10 @@ to read and cache any data without trave Rev and pack files are immutable, so the same is true for index data. During a transaction or while packing a file, a proto index file gets -written (actually, one log-to-phys and one phys-to-log). Its format is -a simple concatenation of runtime structs and as such, an implementation -detail subject to change. A proto index basically aggregates all the -information that must later be transformed into the final index. +written (actually, one log-to-phys and one phys-to-log). They use a +simpler, less compact format with fixed record lengths. A proto index +basically aggregates all the information that must later be transformed +into the final index. General design concerns @@ -192,11 +192,11 @@ at the beginning of the file is optional <bof> /* begin of proto index file for revision r and following */ (0, 0) /* mark start of revision r, optional for first rev */ - (off, item)* /* zero to many mappings in random order */ + (off, item)* /* zero or more mappings in random order */ (0, 0) /* mark start of revision r + 1 */ - (off, item)* /* zero to many mappings in random order */ + (off, item)* /* zero or more mappings in random order */ (0, 0) /* mark start of revision r + 2 */ - (off, item)* /* zero to many mappings in random order */ + (off, item)* /* zero or more mappings in random order */ ... <eof> /* end of file. */ @@ -343,10 +343,12 @@ For performance reasons we use a modifie h0 = fnv_1a([b0 b4 b8 ..]), ..., h3 = fnv_1a([b3 b7 b11 ..]) -* combine the big endian representation of these checksums plus the - remnant of the original stream into a 12 to 15 byte long intermediate +* concatenate the big endian representation of these checksums (4 bytes + each) plus the remnant of the original stream into a 16 to 19 byte long + intermediate: - [i0 .. iK], 12 <= K+1 <= 15 + [i0 .. iK] = [big-endian(h0) ... big-endian(h3) remnant ], 16 <= K+1 <= 19 -* FNV checksum = fnv_1a([i0 .. iK]) in big endian representation +* fold the variable-length intermediate into a compact 32 bit checksum: + FNV checksum = fnv_1a([i0 .. iK]) Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/temp_serializer.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/temp_serializer.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/temp_serializer.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/temp_serializer.c Sun Jun 14 20:58:10 2015 @@ -153,6 +153,10 @@ typedef struct dir_data_t * (it's int because the directory is an APR array) */ int count; + /** Current length of the in-txn in-disk representation of the directory. + * SVN_INVALID_FILESIZE if unknown (i.e. committed data). */ + svn_filesize_t txn_filesize; + /* number of unused dir entry buckets in the index */ apr_size_t over_provision; @@ -198,15 +202,16 @@ serialize_dir_entry(svn_temp_serializer_ svn_temp_serializer__pop(context); } -/* Utility function to serialize the ENTRIES into a new serialization +/* Utility function to serialize the DIR into a new serialization * context to be returned. Allocation will be made form POOL. */ static svn_temp_serializer__context_t * -serialize_dir(apr_array_header_t *entries, apr_pool_t *pool) +serialize_dir(svn_fs_fs__dir_data_t *dir, apr_pool_t *pool) { dir_data_t dir_data; int i = 0; svn_temp_serializer__context_t *context; + apr_array_header_t *entries = dir->entries; /* calculate sizes */ int count = entries->nelts; @@ -216,6 +221,7 @@ serialize_dir(apr_array_header_t *entrie /* copy the hash entries to an auxiliary struct of known layout */ dir_data.count = count; + dir_data.txn_filesize = dir->txn_filesize; dir_data.over_provision = over_provision; dir_data.operations = 0; dir_data.entries = apr_palloc(pool, entries_len); @@ -252,24 +258,29 @@ serialize_dir(apr_array_header_t *entrie return context; } -/* Utility function to reconstruct a dir entries array from serialized data +/* Utility function to reconstruct a dir entries struct from serialized data * in BUFFER and DIR_DATA. Allocation will be made form POOL. */ -static apr_array_header_t * +static svn_fs_fs__dir_data_t * deserialize_dir(void *buffer, dir_data_t *dir_data, apr_pool_t *pool) { - apr_array_header_t *result - = apr_array_make(pool, dir_data->count, sizeof(svn_fs_dirent_t *)); + svn_fs_fs__dir_data_t *result; apr_size_t i; apr_size_t count; svn_fs_dirent_t *entry; svn_fs_dirent_t **entries; + /* Construct empty directory object. */ + result = apr_pcalloc(pool, sizeof(*result)); + result->entries + = apr_array_make(pool, dir_data->count, sizeof(svn_fs_dirent_t *)); + result->txn_filesize = dir_data->txn_filesize; + /* resolve the reference to the entries array */ svn_temp_deserializer__resolve(buffer, (void **)&dir_data->entries); entries = dir_data->entries; - /* fixup the references within each entry and add it to the hash */ + /* fixup the references within each entry and add it to the RESULT */ for (i = 0, count = dir_data->count; i < count; ++i) { svn_temp_deserializer__resolve(entries, (void **)&entries[i]); @@ -280,7 +291,7 @@ deserialize_dir(void *buffer, dir_data_t svn_fs_fs__id_deserialize(entry, (svn_fs_id_t **)&entry->id); /* add the entry to the hash */ - APR_ARRAY_PUSH(result, svn_fs_dirent_t *) = entry; + APR_ARRAY_PUSH(result->entries, svn_fs_dirent_t *) = entry; } /* return the now complete hash */ @@ -496,8 +507,7 @@ svn_fs_fs__serialize_manifest(void **dat apr_array_header_t *manifest = in; *data_len = sizeof(apr_off_t) *manifest->nelts; - *data = apr_palloc(pool, *data_len); - memcpy(*data, manifest->elts, *data_len); + *data = apr_pmemdup(pool, manifest->elts, *data_len); return SVN_NO_ERROR; } @@ -764,7 +774,7 @@ svn_fs_fs__serialize_dir_entries(void ** void *in, apr_pool_t *pool) { - apr_array_header_t *dir = in; + svn_fs_fs__dir_data_t *dir = in; /* serialize the dir content into a new serialization context * and return the serialized data */ @@ -803,6 +813,20 @@ svn_fs_fs__get_sharded_offset(void **out return SVN_NO_ERROR; } +svn_error_t * +svn_fs_fs__extract_dir_filesize(void **out, + const void *data, + apr_size_t data_len, + void *baton, + apr_pool_t *pool) +{ + const dir_data_t *dir_data = data; + + *(svn_filesize_t *)out = dir_data->txn_filesize; + + return SVN_NO_ERROR; +} + /* Utility function that returns the lowest index of the first entry in * *ENTRIES that points to a dir entry with a name equal or larger than NAME. * If an exact match has been found, *FOUND will be set to TRUE. COUNT is @@ -857,7 +881,7 @@ svn_fs_fs__extract_dir_entry(void **out, apr_pool_t *pool) { const dir_data_t *dir_data = data; - const char* name = baton; + const extract_dir_entry_baton_t *entry_baton = baton; svn_boolean_t found; /* resolve the reference to the entries array */ @@ -870,13 +894,14 @@ svn_fs_fs__extract_dir_entry(void **out, /* binary search for the desired entry by name */ apr_size_t pos = find_entry((svn_fs_dirent_t **)entries, - name, + entry_baton->name, dir_data->count, &found); - /* de-serialize that entry or return NULL, if no match has been found */ + /* de-serialize that entry or return NULL, if no match has been found. + * Be sure to check that the directory contents is still up-to-date. */ *out = NULL; - if (found) + if (found && dir_data->txn_filesize == entry_baton->txn_filesize) { const svn_fs_dirent_t *source = svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]); @@ -889,8 +914,7 @@ svn_fs_fs__extract_dir_entry(void **out, apr_size_t size = lengths[pos]; /* copy & deserialize the entry */ - svn_fs_dirent_t *new_entry = apr_palloc(pool, size); - memcpy(new_entry, source, size); + svn_fs_dirent_t *new_entry = apr_pmemdup(pool, source, size); svn_temp_deserializer__resolve(new_entry, (void **)&new_entry->name); svn_fs_fs__id_deserialize(new_entry, (svn_fs_id_t **)&new_entry->id); @@ -911,31 +935,34 @@ slowly_replace_dir_entry(void **data, { replace_baton_t *replace_baton = (replace_baton_t *)baton; dir_data_t *dir_data = (dir_data_t *)*data; - apr_array_header_t *dir; + svn_fs_fs__dir_data_t *dir; int idx = -1; svn_fs_dirent_t *entry; + apr_array_header_t *entries; SVN_ERR(svn_fs_fs__deserialize_dir_entries((void **)&dir, *data, dir_data->len, pool)); - entry = svn_fs_fs__find_dir_entry(dir, replace_baton->name, &idx); + entries = dir->entries; + entry = svn_fs_fs__find_dir_entry(entries, replace_baton->name, &idx); /* Replacement or removal? */ if (replace_baton->new_entry) { /* Replace ENTRY with / insert the NEW_ENTRY */ if (entry) - APR_ARRAY_IDX(dir, idx, svn_fs_dirent_t *) = replace_baton->new_entry; + APR_ARRAY_IDX(entries, idx, svn_fs_dirent_t *) + = replace_baton->new_entry; else - svn_sort__array_insert(dir, &replace_baton->new_entry, idx); + svn_sort__array_insert(entries, &replace_baton->new_entry, idx); } else { /* Remove the old ENTRY. */ if (entry) - svn_sort__array_delete(dir, idx, 1); + svn_sort__array_delete(entries, idx, 1); } return svn_fs_fs__serialize_dir_entries(data, data_len, dir, pool); @@ -957,6 +984,12 @@ svn_fs_fs__replace_dir_entry(void **data svn_temp_serializer__context_t *context; + /* update the cached file length info. + * Because we are writing to the cache, it is fair to assume that the + * caller made sure that the current contents is consistent with the + * previous state of the directory file. */ + dir_data->txn_filesize = replace_baton->txn_filesize; + /* after quite a number of operations, let's re-pack everything. * This is to limit the number of wasted space as we cannot overwrite * existing data but must always append. */ Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/temp_serializer.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/temp_serializer.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/temp_serializer.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/temp_serializer.h Sun Jun 14 20:58:10 2015 @@ -192,7 +192,7 @@ svn_fs_fs__deserialize_node_revision(voi apr_pool_t *pool); /** - * Implements #svn_cache__serialize_func_t for a directory contents array + * Implements #svn_cache__serialize_func_t for a #svn_fs_fs__dir_data_t */ svn_error_t * svn_fs_fs__serialize_dir_entries(void **data, @@ -201,7 +201,7 @@ svn_fs_fs__serialize_dir_entries(void ** apr_pool_t *pool); /** - * Implements #svn_cache__deserialize_func_t for a directory contents array + * Implements #svn_cache__deserialize_func_t for a #svn_fs_fs__dir_data_t */ svn_error_t * svn_fs_fs__deserialize_dir_entries(void **out, @@ -221,9 +221,38 @@ svn_fs_fs__get_sharded_offset(void **out apr_pool_t *pool); /** + * Implements #svn_cache__partial_getter_func_t. + * Set (svn_filesize_t) @a *out to the filesize info stored with the + * serialized directory in @a data of @a data_len. @a baton is unused. + */ +svn_error_t * +svn_fs_fs__extract_dir_filesize(void **out, + const void *data, + apr_size_t data_len, + void *baton, + apr_pool_t *pool); + +/** + * Describes the entry to be found in a directory: Identifies the entry + * by @a name and requires the directory file size to be @a filesize. + */ +typedef struct extract_dir_entry_baton_t +{ + /** name of the directory entry to return */ + const char *name; + + /** Current length of the in-txn in-disk representation of the directory. + * SVN_INVALID_FILESIZE if unknown. */ + svn_filesize_t txn_filesize; +} extract_dir_entry_baton_t; + + +/** * Implements #svn_cache__partial_getter_func_t for a single * #svn_fs_dirent_t within a serialized directory contents hash, - * identified by its name (const char @a *baton). + * identified by its name (in (extract_dir_entry_baton_t *) @a *baton). + * If the filesize specified in the baton does not match the cached + * value for this directory, @a *out will be NULL as well. */ svn_error_t * svn_fs_fs__extract_dir_entry(void **out, @@ -236,7 +265,10 @@ svn_fs_fs__extract_dir_entry(void **out, * Describes the change to be done to a directory: Set the entry * identify by @a name to the value @a new_entry. If the latter is * @c NULL, the entry shall be removed if it exists. Otherwise it - * will be replaced or automatically added, respectively. + * will be replaced or automatically added, respectively. The + * @a filesize allows readers to identify stale cache data (e.g. + * due to concurrent access to txns); writers use it to update the + * cached file size info. */ typedef struct replace_baton_t { @@ -245,6 +277,10 @@ typedef struct replace_baton_t /** directory entry to insert instead */ svn_fs_dirent_t *new_entry; + + /** Current length of the in-txn in-disk representation of the directory. + * SVN_INVALID_FILESIZE if unknown. */ + svn_filesize_t txn_filesize; } replace_baton_t; /** Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/transaction.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/transaction.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/transaction.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/transaction.c Sun Jun 14 20:58:10 2015 @@ -25,6 +25,7 @@ #include <assert.h> #include <apr_sha1.h> +#include "svn_error_codes.h" #include "svn_hash.h" #include "svn_props.h" #include "svn_sorts.h" @@ -63,7 +64,7 @@ path_txn_sha1(svn_fs_t *fs, svn_checksum_t checksum; checksum.digest = sha1; checksum.kind = svn_checksum_sha1; - + return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool), svn_checksum_to_cstring(&checksum, pool), pool); @@ -465,7 +466,7 @@ get_writable_proto_rev(apr_file_t **file /* We don't want unused sections (such as leftovers from failed delta stream) in our file. If we use log addressing, we would need an - index entry for the unused section and that section would need to + index entry for the unused section and that section would need to be all NUL by convention. So, detect and fix those cases by truncating the protorev file. */ if (!err) @@ -973,7 +974,7 @@ get_and_increment_txn_key_body(void *bat /* remove trailing newlines */ line_length = svn__ui64tobase36(new_id_str, cb->txn_number+1); new_id_str[line_length] = '\n'; - + /* Increment the key and add a trailing \n to the string so the txn-current file has a newline in it. */ SVN_ERR(svn_io_write_atomic(txn_current_filename, new_id_str, @@ -1127,6 +1128,7 @@ get_txn_proplist(apr_hash_t *proplist, apr_pool_t *pool) { svn_stream_t *stream; + svn_error_t *err; /* Check for issue #3696. (When we find and fix the cause, we can change * this to an assertion.) */ @@ -1140,7 +1142,14 @@ get_txn_proplist(apr_hash_t *proplist, pool, pool)); /* Read in the property list. */ - SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, pool)); + err = svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, pool); + if (err) + { + err = svn_error_compose_create(err, svn_stream_close(stream)); + return svn_error_quick_wrapf(err, + _("malformed property list in transaction '%s'"), + path_txn_props(fs, txn_id, pool)); + } return svn_stream_close(stream); } @@ -1164,7 +1173,7 @@ set_txn_proplist(svn_fs_t *fs, SVN_ERR(svn_stream_close(stream)); /* Open the transaction properties file and write new contents to it. */ - SVN_ERR(svn_io_write_atomic((final + SVN_ERR(svn_io_write_atomic((final ? path_txn_props_final(fs, txn_id, pool) : path_txn_props(fs, txn_id, pool)), buf->data, buf->len, @@ -1270,7 +1279,7 @@ write_next_ids(svn_fs_t *fs, apr_file_t *file; char buffer[2 * SVN_INT64_BUFFER_SIZE + 2]; char *p = buffer; - + p += svn__ui64tobase36(p, node_id); *(p++) = ' '; p += svn__ui64tobase36(p, copy_id); @@ -1515,22 +1524,80 @@ svn_fs_fs__set_entry(svn_fs_t *fs, } else { + const svn_io_dirent2_t *dirent; + /* The directory rep is already mutable, so just open it for append. */ SVN_ERR(svn_io_file_open(&file, filename, APR_WRITE | APR_APPEND, - APR_OS_DEFAULT, pool)); - out = svn_stream_from_aprfile2(file, TRUE, pool); + APR_OS_DEFAULT, subpool)); + out = svn_stream_from_aprfile2(file, TRUE, subpool); + + /* If the cache contents is stale, drop it. + * + * Note that the directory file is append-only, i.e. if the size + * did not change, the contents didn't either. */ + if (ffd->txn_dir_cache) + { + const char *key + = svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data; + svn_boolean_t found; + svn_filesize_t filesize; + + /* Get the file size that corresponds to the cached contents + * (if any). */ + SVN_ERR(svn_cache__get_partial((void **)&filesize, &found, + ffd->txn_dir_cache, key, + svn_fs_fs__extract_dir_filesize, + NULL, subpool)); + + /* File size info still matches? + * If not, we need to drop the cache entry. */ + if (found) + { + SVN_ERR(svn_io_stat_dirent2(&dirent, filename, FALSE, FALSE, + subpool, subpool)); + + if (filesize != dirent->filesize) + SVN_ERR(svn_cache__set(ffd->txn_dir_cache, key, NULL, + subpool)); + } + } + } + + /* Append an incremental hash entry for the entry change. */ + if (id) + { + svn_fs_dirent_t entry; + entry.name = name; + entry.id = id; + entry.kind = kind; + + SVN_ERR(unparse_dir_entry(&entry, out, subpool)); + } + else + { + SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n", + strlen(name), name)); } + /* Flush APR buffers. */ + SVN_ERR(svn_io_file_close(file, subpool)); + svn_pool_clear(subpool); + /* if we have a directory cache for this transaction, update it */ if (ffd->txn_dir_cache) { - /* build parameters: (name, new entry) pair */ + /* build parameters: name, new entry, new file size */ const char *key = svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data; replace_baton_t baton; + const svn_io_dirent2_t *dirent; + SVN_ERR(svn_io_stat_dirent2(&dirent, filename, FALSE, FALSE, + subpool, subpool)); + baton.name = name; baton.new_entry = NULL; + baton.txn_filesize = dirent->filesize; if (id) { @@ -1545,25 +1612,7 @@ svn_fs_fs__set_entry(svn_fs_t *fs, svn_fs_fs__replace_dir_entry, &baton, subpool)); } - svn_pool_clear(subpool); - - /* Append an incremental hash entry for the entry change. */ - if (id) - { - svn_fs_dirent_t entry; - entry.name = name; - entry.id = id; - entry.kind = kind; - - SVN_ERR(unparse_dir_entry(&entry, out, subpool)); - } - else - { - SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n", - strlen(name), name)); - } - SVN_ERR(svn_io_file_close(file, subpool)); svn_pool_destroy(subpool); return SVN_NO_ERROR; } @@ -1963,9 +2012,7 @@ choose_delta_base(representation_t **rep /* Very short rep bases are simply not worth it as we are unlikely * to re-coup the deltification space overhead of 20+ bytes. */ - svn_filesize_t rep_size = (*rep)->expanded_size - ? (*rep)->expanded_size - : (*rep)->size; + svn_filesize_t rep_size = (*rep)->expanded_size; if (rep_size < 64) { *rep = NULL; @@ -2118,7 +2165,7 @@ rep_write_get_baton(struct rep_write_bat } /* For REP->SHA1_CHECKSUM, try to find an already existing representation - in FS and return it in *OUT_REP. If no such representation exists or + in FS and return it in *OLD_REP. If no such representation exists or if rep sharing has been disabled for FS, NULL will be returned. Since there may be new duplicate representations within the same uncommitted revision, those can be passed in REPS_HASH (maps a sha1 digest onto @@ -2144,7 +2191,7 @@ get_shared_rep(representation_t **old_re /* Check and see if we already have a representation somewhere that's identical to the one we just wrote out. Start with the hash lookup - because it is cheepest. */ + because it is cheapest. */ if (reps_hash) *old_rep = apr_hash_get(reps_hash, rep->sha1_digest, @@ -2213,12 +2260,37 @@ get_shared_rep(representation_t **old_re if (!*old_rep) return SVN_NO_ERROR; - /* We don't want 0-length PLAIN representations to replace non-0-length - ones (see issue #4554). Also, this doubles as a simple guard against - general rep-cache induced corruption. */ - if ( ((*old_rep)->expanded_size != rep->expanded_size) - || ((*old_rep)->size != rep->size)) + /* A simple guard against general rep-cache induced corruption. */ + if ((*old_rep)->expanded_size != rep->expanded_size) { + /* Make the problem show up in the server log. + + Because not sharing reps is always a safe option, + terminating the request would be inappropriate. + */ + svn_checksum_t checksum; + checksum.digest = rep->sha1_digest; + checksum.kind = svn_checksum_sha1; + + err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Rep size %s mismatches rep-cache.db value %s " + "for SHA1 %s.\n" + "You should delete the rep-cache.db and " + "verify the repository. The cached rep will " + "not be shared.", + apr_psprintf(scratch_pool, + "%" SVN_FILESIZE_T_FMT, + rep->expanded_size), + apr_psprintf(scratch_pool, + "%" SVN_FILESIZE_T_FMT, + (*old_rep)->expanded_size), + svn_checksum_to_cstring_display(&checksum, + scratch_pool)); + + (fs->warning)(fs->warning_baton, err); + svn_error_clear(err); + + /* Ignore the shared rep. */ *old_rep = NULL; } else @@ -2553,6 +2625,7 @@ write_container_rep(representation_t *re /* Check and see if we already have a representation somewhere that's identical to the one we just wrote out. */ + rep->expanded_size = whb->size; SVN_ERR(get_shared_rep(&old_rep, fs, rep, reps_hash, scratch_pool, scratch_pool)); @@ -2588,7 +2661,6 @@ write_container_rep(representation_t *re /* update the representation */ rep->size = whb->size; - rep->expanded_size = whb->size; } return SVN_NO_ERROR; @@ -2692,6 +2764,7 @@ write_container_delta_rep(representation /* Check and see if we already have a representation somewhere that's identical to the one we just wrote out. */ + rep->expanded_size = whb->size; SVN_ERR(get_shared_rep(&old_rep, fs, rep, reps_hash, scratch_pool, scratch_pool)); @@ -2727,7 +2800,6 @@ write_container_delta_rep(representation SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, &entry, scratch_pool)); /* update the representation */ - rep->expanded_size = whb->size; rep->size = rep_end - delta_start; } @@ -3354,7 +3426,7 @@ svn_fs_fs__add_index_data(svn_fs_t *fs, pool, pool)); /* Append footer. */ - footer = svn_fs_fs__unparse_footer(l2p_offset, l2p_checksum, + footer = svn_fs_fs__unparse_footer(l2p_offset, l2p_checksum, p2l_offset, p2l_checksum, pool, pool); SVN_ERR(svn_io_file_write_full(file, footer->data, footer->len, NULL, pool)); Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/tree.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/tree.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/tree.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/tree.c Sun Jun 14 20:58:10 2015 @@ -90,7 +90,7 @@ typedef struct fs_txn_root_data_t { /* TXN_ID value from the main struct but as a struct instead of a string */ svn_fs_fs__id_part_t txn_id; - + /* Cache of txn DAG nodes (without their nested noderevs, because * it's mutable). Same keys/values as ffd->rev_node_cache. */ svn_cache__t *txn_node_cache; @@ -574,7 +574,7 @@ root_txn_id(svn_fs_root_t *root) { fs_txn_root_data_t *frd = root->fsap_data; assert(root->is_txn_root); - + return &frd->txn_id; } @@ -1328,8 +1328,8 @@ fs_node_relation(svn_fs_node_relation_t apr_pool_t *pool) { dag_node_t *node; - const svn_fs_id_t *id; - svn_fs_fs__id_part_t rev_item_a, rev_item_b, node_id_a, node_id_b; + const svn_fs_id_t *id_a, *id_b; + svn_fs_fs__id_part_t node_id_a, node_id_b; /* Root paths are a common special case. */ svn_boolean_t a_is_root_dir @@ -1337,6 +1337,11 @@ fs_node_relation(svn_fs_node_relation_t svn_boolean_t b_is_root_dir = (path_b[0] == '\0') || ((path_b[0] == '/') && (path_b[1] == '\0')); + /* Another useful thing to know: Both are txns but not the same txn. */ + svn_boolean_t different_txn + = root_a->is_txn_root && root_b->is_txn_root + && strcmp(root_a->txn, root_b->txn); + /* Path from different repository are always unrelated. */ if (root_a->fs != root_b->fs) { @@ -1344,20 +1349,15 @@ fs_node_relation(svn_fs_node_relation_t return SVN_NO_ERROR; } - /* Nodes from different transactions are never related. */ - if (root_a->is_txn_root && root_b->is_txn_root - && strcmp(root_a->txn, root_b->txn)) - { - *relation = svn_fs_node_unrelated; - return SVN_NO_ERROR; - } - /* Are both (!) root paths? Then, they are related and we only test how * direct the relation is. */ if (a_is_root_dir && b_is_root_dir) { - *relation = root_a->rev == root_b->rev - ? svn_fs_node_same + /* For txn roots, root->REV is the base revision of that TXN. */ + *relation = ( (root_a->rev == root_b->rev) + && (root_a->is_txn_root == root_b->is_txn_root) + && !different_txn) + ? svn_fs_node_unchanged : svn_fs_node_common_ancestor; return SVN_NO_ERROR; } @@ -1365,21 +1365,35 @@ fs_node_relation(svn_fs_node_relation_t /* We checked for all separations between ID spaces (repos, txn). * Now, we can simply test for the ID values themselves. */ SVN_ERR(get_dag(&node, root_a, path_a, pool)); - id = svn_fs_fs__dag_get_id(node); - rev_item_a = *svn_fs_fs__id_rev_item(id); - node_id_a = *svn_fs_fs__id_node_id(id); + id_a = svn_fs_fs__dag_get_id(node); + node_id_a = *svn_fs_fs__id_node_id(id_a); SVN_ERR(get_dag(&node, root_b, path_b, pool)); - id = svn_fs_fs__dag_get_id(node); - rev_item_b = *svn_fs_fs__id_rev_item(id); - node_id_b = *svn_fs_fs__id_node_id(id); - - if (svn_fs_fs__id_part_eq(&rev_item_a, &rev_item_b)) - *relation = svn_fs_node_same; - else if (svn_fs_fs__id_part_eq(&node_id_a, &node_id_b)) - *relation = svn_fs_node_common_ancestor; + id_b = svn_fs_fs__dag_get_id(node); + node_id_b = *svn_fs_fs__id_node_id(id_b); + + /* Noderevs from different nodes are unrelated. */ + if (!svn_fs_fs__id_part_eq(&node_id_a, &node_id_b)) + { + *relation = svn_fs_node_unrelated; + return SVN_NO_ERROR; + } + + /* Noderevs have the same node-ID now. So, they *seem* to be related. + * + * Special case: Different txns may create the same (txn-local) node ID. + * These are not related to each other, nor to any other node ID so far. */ + if (different_txn && node_id_a.revision == SVN_INVALID_REVNUM) + { + *relation = svn_fs_node_unrelated; + return SVN_NO_ERROR; + } + + /* The noderevs are actually related. Are they the same? */ + if (svn_fs_fs__id_eq(id_a, id_b)) + *relation = svn_fs_node_unchanged; else - *relation = svn_fs_node_unrelated; + *relation = svn_fs_node_common_ancestor; return SVN_NO_ERROR; } @@ -1501,6 +1515,19 @@ fs_node_proplist(apr_hash_t **table_p, return SVN_NO_ERROR; } +static svn_error_t * +fs_node_has_props(svn_boolean_t *has_props, + svn_fs_root_t *root, + const char *path, + apr_pool_t *scratch_pool) +{ + dag_node_t *node; + + SVN_ERR(get_dag(&node, root, path, scratch_pool)); + + return svn_error_trace(svn_fs_fs__dag_has_props(has_props, node, + scratch_pool)); +} static svn_error_t * increment_mergeinfo_up_tree(parent_path_t *pp, @@ -2095,7 +2122,7 @@ merge_changes(dag_node_t *ancestor_node, dag_node_t *txn_root_node; svn_fs_t *fs = txn->fs; const svn_fs_fs__id_part_t *txn_id = svn_fs_fs__txn_get_id(txn); - + SVN_ERR(svn_fs_fs__dag_txn_root(&txn_root_node, fs, txn_id, pool)); if (ancestor_node == NULL) @@ -2378,9 +2405,11 @@ static svn_error_t * fs_dir_optimal_order(apr_array_header_t **ordered_p, svn_fs_root_t *root, apr_hash_t *entries, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - *ordered_p = svn_fs_fs__order_dir_entries(root->fs, entries, pool); + *ordered_p = svn_fs_fs__order_dir_entries(root->fs, entries, result_pool, + scratch_pool); return SVN_NO_ERROR; } @@ -2905,7 +2934,7 @@ window_consumer(svn_txdelta_window_t *wi cb->target_string. */ SVN_ERR(tb->interpreter(window, tb->interpreter_baton)); - /* Is the window NULL? If so, we're done. The stream has already been + /* Is the window NULL? If so, we're done. The stream has already been closed by the interpreter. */ if (! window) SVN_ERR(svn_fs_fs__dag_finalize_edits(tb->node, tb->result_checksum, @@ -4222,6 +4251,7 @@ static root_vtable_t root_vtable = { fs_closest_copy, fs_node_prop, fs_node_proplist, + fs_node_has_props, fs_change_node_prop, fs_props_changed, fs_dir_entries, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/util.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/util.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/util.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/util.c Sun Jun 14 20:58:10 2015 @@ -637,6 +637,22 @@ svn_fs_fs__move_into_place(const char *o apr_pool_t *pool) { svn_error_t *err; + apr_file_t *file; + +#if defined(WIN32) || defined(__OS2__) + + /* APR will *not* error out on Win32 if this requires a copy instead of + of a move. */ + SVN_ERR(svn_io_file_rename(old_filename, new_filename, pool)); + + /* Flush the target of the copy to disk. */ + SVN_ERR(svn_io_file_open(&file, new_filename, APR_WRITE, + APR_OS_DEFAULT, pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); + + /* Copying permissions is a no-op on WIN32. */ +#else SVN_ERR(svn_io_copy_perms(perms_reference, old_filename, pool)); @@ -644,8 +660,6 @@ svn_fs_fs__move_into_place(const char *o err = svn_io_file_rename(old_filename, new_filename, pool); if (err && APR_STATUS_IS_EXDEV(err->apr_err)) { - apr_file_t *file; - /* Can't rename across devices; fall back to copying. */ svn_error_clear(err); err = SVN_NO_ERROR; @@ -654,26 +668,19 @@ svn_fs_fs__move_into_place(const char *o /* Flush the target of the copy to disk. */ SVN_ERR(svn_io_file_open(&file, new_filename, APR_READ, APR_OS_DEFAULT, pool)); - /* ### BH: Does this really guarantee a flush of the data written - ### via a completely different handle on all operating systems? - ### - ### Maybe we should perform the copy ourselves instead of making - ### apr do that and flush the real handle? */ SVN_ERR(svn_io_file_flush_to_disk(file, pool)); SVN_ERR(svn_io_file_close(file, pool)); } if (err) return svn_error_trace(err); -#ifdef __linux__ +#if SVN_ON_POSIX { - /* Linux has the unusual feature that fsync() on a file is not - enough to ensure that a file's directory entries have been - flushed to disk; you have to fsync the directory as well. + /* On POSIX, the file name is stored in the file's directory entry. + Hence, we need to fsync() that directory as well. On other operating systems, we'd only be asking for trouble by trying to open and fsync a directory. */ const char *dirname; - apr_file_t *file; dirname = svn_dirent_dirname(new_filename, pool); SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, @@ -683,6 +690,8 @@ svn_fs_fs__move_into_place(const char *o } #endif +#endif /* defined(WIN32) || defined(__OS2__) */ + return SVN_NO_ERROR; } Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/verify.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/verify.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/verify.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_fs/verify.c Sun Jun 14 20:58:10 2015 @@ -204,7 +204,7 @@ verify_index_checksum(apr_file_t *file, const char *file_name; SVN_ERR(svn_io_file_name_get(&file_name, file, scratch_pool)); - SVN_ERR(svn_checksum_mismatch_err(expected, actual, scratch_pool, + SVN_ERR(svn_checksum_mismatch_err(expected, actual, scratch_pool, _("%s checksum mismatch in file %s"), name, file_name)); } @@ -463,7 +463,8 @@ expect_buffer_nul(apr_file_t *file, /* read the whole data block; error out on failure */ data.chunks[(size - 1)/ sizeof(apr_uint64_t)] = 0; - SVN_ERR(svn_io_file_read_full2(file, data.buffer, size, NULL, NULL, pool)); + SVN_ERR(svn_io_file_read_full2(file, data.buffer, (apr_size_t)size, NULL, + NULL, pool)); /* chunky check */ for (i = 0; i < size / sizeof(apr_uint64_t); ++i) @@ -476,7 +477,7 @@ expect_buffer_nul(apr_file_t *file, { const char *file_name; apr_off_t offset; - + SVN_ERR(svn_io_file_name_get(&file_name, file, pool)); SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool)); offset -= size - i; @@ -793,7 +794,7 @@ verify_f7_metadata_consistency(svn_fs_t /* Check for external corruption to the indexes. */ err = verify_index_checksums(fs, pack_start, cancel_func, cancel_baton, iterpool); - + /* two-way index check */ if (!err) err = compare_l2p_to_p2l_index(fs, pack_start, pack_end - pack_start, @@ -850,13 +851,15 @@ svn_fs_fs__verify(svn_fs_t *fs, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; - svn_revnum_t youngest = ffd->youngest_rev_cache; /* cache is current */ /* Input validation. */ if (! SVN_IS_VALID_REVNUM(start)) start = 0; if (! SVN_IS_VALID_REVNUM(end)) - end = youngest; + { + SVN_ERR(svn_fs_fs__youngest_rev(&end, fs, pool)); + } + SVN_ERR(svn_fs_fs__ensure_revision_exists(start, fs, pool)); SVN_ERR(svn_fs_fs__ensure_revision_exists(end, fs, pool)); Propchange: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Sun Jun 14 20:58:10 2015 @@ -60,6 +60,7 @@ /subversion/branches/nfc-nfd-aware-client/subversion/libsvn_fs_x:870276,870376 /subversion/branches/node_pool/subversion/libsvn_fs_x:1304828-1305388 /subversion/branches/performance/subversion/libsvn_fs_x:979193,980118,981087,981090,981189,981194,981287,981684,981827,982043,982355,983398,983406,983430,983474,983488,983490,983760,983764,983766,983770,984927,984973,984984,985014,985037,985046,985472,985477,985482,985487-985488,985493,985497,985500,985514,985601,985603,985606,985669,985673,985695,985697,986453,986465,986485,986491-986492,986517,986521,986605,986608,986817,986832,987865,987868-987869,987872,987886-987888,987893,988319,988898,990330,990533,990535-990537,990541,990568,990572,990574-990575,990600,990759,992899,992904,992911,993127,993141,994956,995478,995507,995603,998012,998858,999098,1001413,1001417,1004291,1022668,1022670,1022676,1022715,1022719,1025660,1025672,1027193,1027203,1027206,1027214,1027227,1028077,1028092,1028094,1028104,1028107,1028111,1028354,1029038,1029042-1029043,1029054-1029055,1029062-1029063,1029078,1029080,1029090,1029092-1029093,1029111,1029151,1029158,1029229-1029230,1029232,1029335-1029336,102 9339-1029340,1029342,1029344,1030763,1030827,1031203,1031235,1032285,1032333,1033040,1033057,1033294,1035869,1035882,1039511,1043705,1053735,1056015,1066452,1067683,1067697-1078365 +/subversion/branches/pin-externals/subversion/libsvn_fs_x:1643757-1659392 /subversion/branches/py-tests-as-modules/subversion/libsvn_fs_x:956579-1033052 /subversion/branches/ra_serf-digest-authn/subversion/libsvn_fs_x:875693-876404 /subversion/branches/reintegrate-improvements/subversion/libsvn_fs_x:873853-874164 @@ -89,4 +90,4 @@ /subversion/branches/verify-keep-going/subversion/libsvn_fs_x:1439280-1492639,1546002-1546110 /subversion/branches/wc-collate-path/subversion/libsvn_fs_x:1402685-1480384 /subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1653608, 1658482 -/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1658218-1659236 +/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1658218-1685462 Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/cached_data.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/cached_data.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/cached_data.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/cached_data.c Sun Jun 14 20:58:10 2015 @@ -327,7 +327,7 @@ get_node_revision_body(svn_fs_x__noderev key.second = offset; SVN_ERR(svn_cache__get_partial((void **)noderev_p, &is_cached, - ffd->noderevs_container_cache, &key, + ffd->noderevs_container_cache, &key, svn_fs_x__noderevs_get_func, &sub_item, result_pool)); if (is_cached) @@ -481,7 +481,7 @@ typedef struct rep_state_t apr_uint32_t sub_item; apr_off_t current;/* The current offset relative to START. */ apr_off_t size; /* The on-disk size of the representation. */ - int ver; /* If a delta, what svndiff version? + int ver; /* If a delta, what svndiff version? -1 for unknown delta version. */ int chunk_index; /* number of the window to read */ } rep_state_t; @@ -793,7 +793,7 @@ svn_fs_x__check_rep(svn_fs_x__representa && entry->type != SVN_FS_X__ITEM_TYPE_FILE_PROPS && entry->type != SVN_FS_X__ITEM_TYPE_DIR_PROPS && entry->type != SVN_FS_X__ITEM_TYPE_REPS_CONT)) - return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, NULL, + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("No representation found at offset %s " "for item %s in revision %ld"), apr_off_t_toa(scratch_pool, offset), @@ -937,7 +937,7 @@ typedef struct rep_read_baton_t /* The text we've been reading, if we're going to cache it. */ svn_stringbuf_t *current_fulltext; - /* If not NULL, attempt to read the data from this cache. + /* If not NULL, attempt to read the data from this cache. Once that lookup fails, reset it to NULL. */ svn_cache__t *fulltext_cache; @@ -1009,7 +1009,7 @@ get_cached_window_sizes_func(void **out, window_sizes_t *result = apr_palloc(pool, sizeof(*result)); result->packed_len = window->end_offset - window->start_offset; result->target_len = txdelta_window->tview_len; - + *out = result; return SVN_NO_ERROR; @@ -1724,13 +1724,13 @@ svn_fs_x__get_representation_length(svn_ svn_fs_x__representation_cache_key_t key = { 0 }; rep_state_t rs = { 0 }; svn_fs_x__rep_header_t *rep_header; - + /* this function does not apply to representation containers */ SVN_ERR_ASSERT(entry->type >= SVN_FS_X__ITEM_TYPE_FILE_REP && entry->type <= SVN_FS_X__ITEM_TYPE_DIR_PROPS); SVN_ERR_ASSERT(entry->item_count == 1); - /* get / read the representation header */ + /* get / read the representation header */ key.revision = svn_fs_x__get_revnum(entry->items[0].change_set); key.is_packed = svn_fs_x__is_packed_rev(fs, key.revision); key.item_index = entry->items[0].number; @@ -1759,7 +1759,7 @@ get_contents_from_windows(rep_read_baton char *cur = buf; rep_state_t *rs; - /* Special case for when there are no delta reps, only a + /* Special case for when there are no delta reps, only a containered text. */ if (rb->rs_list->nelts == 0 && rb->buf == NULL) { @@ -2060,7 +2060,7 @@ rep_read_contents(void *baton, &rb->src_state, rb->fs, &rb->rep, rb->filehandle_pool, rb->scratch_pool)); - /* In case we did read from the fulltext cache before, make the + /* In case we did read from the fulltext cache before, make the * window stream catch up. Also, initialize the fulltext buffer * if we want to cache the fulltext at the end. */ SVN_ERR(skip_contents(rb, rb->fulltext_delivered)); @@ -2488,7 +2488,7 @@ read_dir_entries(apr_array_header_t *ent /* In incremental mode, update the hash; otherwise, write to the * final array. */ if (incremental) - apr_hash_set(hash, entry.key, entry.keylen, dirent); + apr_hash_set(hash, dirent->name, entry.keylen, dirent); else APR_ARRAY_PUSH(entries, svn_fs_x__dirent_t *) = dirent; } Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/changes.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/changes.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/changes.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/changes.c Sun Jun 14 20:58:10 2015 @@ -187,7 +187,7 @@ svn_fs_x__changes_append_list(apr_size_t apr_array_header_t *list) { int i; - + /* CHANGES must be in 'builder' mode */ SVN_ERR_ASSERT(changes->builder); SVN_ERR_ASSERT(changes->paths == NULL); @@ -273,7 +273,7 @@ svn_fs_x__changes_get_list(apr_array_hea change->copyfrom_rev = binary_change->copyfrom_rev; change->copyfrom_known = TRUE; if (SVN_IS_VALID_REVNUM(binary_change->copyfrom_rev)) - change->copyfrom_path + change->copyfrom_path = svn_fs_x__string_table_get(changes->paths, binary_change->copyfrom_path, NULL, @@ -339,7 +339,7 @@ svn_fs_x__write_changes_container(svn_st /* write to disk */ SVN_ERR(svn_fs_x__write_string_table(stream, paths, scratch_pool)); SVN_ERR(svn_packed__data_write(stream, root, scratch_pool)); - + return SVN_NO_ERROR; } @@ -395,7 +395,7 @@ svn_fs_x__read_changes_container(svn_fs_ } *changes_p = changes; - + return SVN_NO_ERROR; } @@ -521,7 +521,7 @@ svn_fs_x__changes_get_list_func(void **o change->copyfrom_rev = binary_change->copyfrom_rev; change->copyfrom_known = TRUE; if (SVN_IS_VALID_REVNUM(binary_change->copyfrom_rev)) - change->copyfrom_path + change->copyfrom_path = svn_fs_x__string_table_get_func(paths, binary_change->copyfrom_path, NULL, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/dag.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/dag.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/dag.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/dag.h Sun Jun 14 20:58:10 2015 @@ -173,7 +173,7 @@ svn_fs_x__dag_node_kind(dag_node_t *node If properties do not exist on NODE, *PROPLIST_P will be set to NULL. - Allocate the result in RESULT_POOL and use SCRATCH_POOL for temporaries. + Allocate the result in RESULT_POOL and use SCRATCH_POOL for temporaries. */ svn_error_t * svn_fs_x__dag_get_proplist(apr_hash_t **proplist_p, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs.c Sun Jun 14 20:58:10 2015 @@ -27,7 +27,6 @@ #include <apr_general.h> #include <apr_pools.h> #include <apr_file_io.h> -#include <apr_thread_mutex.h> #include "svn_fs.h" #include "svn_delta.h" @@ -165,9 +164,11 @@ x_freeze_body(void *baton, SVN_ERR(svn_fs_x__exists_rep_cache(&exists, b->fs, scratch_pool)); if (exists) - SVN_ERR(svn_fs_x__lock_rep_cache(b->fs, scratch_pool)); - - SVN_ERR(b->freeze_func(b->freeze_baton, scratch_pool)); + SVN_ERR(svn_fs_x__with_rep_cache_lock(b->fs, + b->freeze_func, b->freeze_baton, + scratch_pool)); + else + SVN_ERR(b->freeze_func(b->freeze_baton, scratch_pool)); return SVN_NO_ERROR; } Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs.h Sun Jun 14 20:58:10 2015 @@ -269,7 +269,7 @@ typedef struct svn_fs_x__data_t /* Rev / pack file granularity covered by phys-to-log index pages */ apr_int64_t p2l_page_size; - + /* The revision that was youngest, last time we checked. */ svn_revnum_t youngest_rev_cache; Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_id.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_id.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_id.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_id.c Sun Jun 14 20:58:10 2015 @@ -48,7 +48,7 @@ typedef struct fs_x__id_t /* The state machine behind this is as follows: - + (A) FS passed in during context construction still open and uses a different pool as the context (Usually the initial state). In that case, FS_PATH is NULL and we watch for either pool's cleanup. @@ -217,13 +217,7 @@ id_compare(const svn_fs_id_t *a, /* Quick check: same IDs? */ if (svn_fs_x__id_eq(&id_a->noderev_id, &id_b->noderev_id)) - return svn_fs_node_same; - - /* Items from different txns are unrelated. */ - if ( svn_fs_x__is_txn(id_a->noderev_id.change_set) - && svn_fs_x__is_txn(id_b->noderev_id.change_set) - && id_a->noderev_id.change_set != id_b->noderev_id.change_set) - return svn_fs_node_unrelated; + return svn_fs_node_unchanged; /* Fetch the nodesrevs, compare the IDs of the nodes they belong to and clean up any temporaries. If we can't find one of the noderevs, don't Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_x.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_x.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_x.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_x.c Sun Jun 14 20:58:10 2015 @@ -606,7 +606,7 @@ svn_fs_x__open(svn_fs_t *fs, fs, scratch_pool)); } -/* Baton type bridging svn_fs_x__upgrade and upgrade_body carrying +/* Baton type bridging svn_fs_x__upgrade and upgrade_body carrying * parameters over between them. */ typedef struct upgrade_baton_t { @@ -660,7 +660,7 @@ svn_fs_x__upgrade(svn_fs_t *fs, baton.notify_baton = notify_baton; baton.cancel_func = cancel_func; baton.cancel_baton = cancel_baton; - + return svn_fs_x__with_all_locks(fs, upgrade_body, (void *)&baton, scratch_pool); } @@ -814,7 +814,7 @@ svn_fs_x__file_checksum(svn_checksum_t * { svn_checksum_t temp; temp.kind = kind; - + switch(kind) { case svn_checksum_md5: Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/hotcopy.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/hotcopy.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/hotcopy.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/hotcopy.h Sun Jun 14 20:58:10 2015 @@ -40,7 +40,7 @@ svn_fs_x__hotcopy_prepare_target(svn_fs_ * not re-copy data which already exists in DST_FS. Indicate progress via * the optional NOTIFY_FUNC callback using NOTIFY_BATON. * Use SCRATCH_POOL for temporary allocations. */ -svn_error_t * +svn_error_t * svn_fs_x__hotcopy(svn_fs_t *src_fs, svn_fs_t *dst_fs, svn_boolean_t incremental, Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/index.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/index.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/index.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/index.c Sun Jun 14 20:58:10 2015 @@ -82,7 +82,7 @@ typedef struct l2p_page_table_entry_t /* Master run-time data structure of an log-to-phys index. It contains * the page tables of every revision covered by that index - but not the - * pages themselves. + * pages themselves. */ typedef struct l2p_header_t { @@ -723,7 +723,7 @@ stream_write_encoded(svn_stream_t *strea apr_uint64_t value) { unsigned char encoded[ENCODED_INT_LENGTH]; - + apr_size_t len = encode_uint(encoded, value); return svn_error_trace(svn_stream_write(stream, (char *)encoded, &len)); } @@ -806,7 +806,7 @@ encode_l2p_page(apr_array_header_t *entr int container_count = 0; apr_uint64_t last_offset = 0; int i; - + apr_size_t data_size = count * sizeof(l2p_page_entry_t); svn_stringbuf_t *container_offsets = svn_stringbuf_create_ensure(count * 2, scratch_pool); @@ -932,7 +932,7 @@ svn_fs_x__l2p_index_append(svn_checksum_ * The current implementation is limited to 2G entries per page. */ if (ffd->l2p_page_size > APR_INT32_MAX) return svn_error_createf(SVN_ERR_FS_INDEX_OVERFLOW , NULL, - _("L2P index page size %s" + _("L2P index page size %s" " exceeds current limit of 2G entries"), apr_psprintf(local_pool, "%" APR_UINT64_T_FMT, ffd->l2p_page_size)); @@ -1469,7 +1469,7 @@ get_l2p_page(l2p_page_t **page, container_offsets[i] = (apr_off_t)last_value - 1; /* '-1' is represented as '0' in the index file */ } - + /* read all page entries (offsets in rev file and container sub-items) */ for (i = 0; i < result->entry_count; ++i) { @@ -1517,14 +1517,14 @@ typedef struct l2p_page_baton_t /* offset within the cached page */ apr_uint32_t page_offset; - + /* out data */ /* absolute item or container offset in rev / pack file */ apr_off_t offset; /* 0 -> container / item itself; sub-item in container otherwise */ apr_uint32_t sub_item; - + } l2p_page_baton_t; /* Return the rev / pack file offset of the item at BATON->PAGE_OFFSET in @@ -1623,7 +1623,7 @@ l2p_page_table_access_func(void **out, /* set output as a courtesy to the caller */ *out = table_baton->pages; - + return SVN_NO_ERROR; } @@ -1898,7 +1898,7 @@ l2p_proto_index_lookup(apr_off_t *offset } SVN_ERR(svn_io_file_close(file, scratch_pool)); - + return SVN_NO_ERROR; } @@ -2392,7 +2392,7 @@ p2l_page_info_copy(p2l_page_info_baton_t const p2l_header_t *header, const apr_off_t *offsets) { - /* if the requested offset is out of bounds, return info for + /* if the requested offset is out of bounds, return info for * a zero-sized empty page right behind the last page. */ if (baton->offset / header->page_size < header->page_count) @@ -2479,7 +2479,7 @@ get_p2l_header(p2l_header_t **header, /* allocate result data structure */ result = apr_pcalloc(result_pool, sizeof(*result)); - + /* Read table sizes, check them for plausibility and allocate page array. */ SVN_ERR(packed_stream_get(&value, stream)); result->first_revision = (svn_revnum_t)value; @@ -2815,7 +2815,7 @@ get_p2l_keys(p2l_page_info_baton_t *page apr_pool_t *scratch_pool) { p2l_page_info_baton_t page_info; - + /* request info for the index pages that describes the pack / rev file * contents at pack / rev file position OFFSET. */ page_info.offset = offset; @@ -2841,7 +2841,7 @@ get_p2l_keys(p2l_page_info_baton_t *page key.is_packed = svn_fs_x__is_packed_rev(fs, revision); key.page = page_info.page_no; - *key_p = key; + *key_p = key; } return SVN_NO_ERROR; @@ -3551,7 +3551,7 @@ compare_p2l_info_rev(const sub_item_orde { svn_fs_x__id_t *lhs_part; svn_fs_x__id_t *rhs_part; - + assert(lhs != rhs); if (lhs->entry->item_count == 0) return rhs->entry->item_count == 0 ? 0 : -1; @@ -3880,7 +3880,7 @@ svn_fs_x__serialize_p2l_page(void **data table_size); for (i = 0; i < page->nelts; ++i) - svn_temp_serializer__add_leaf(context, + svn_temp_serializer__add_leaf(context, (const void * const *)&entries[i].items, entries[i].item_count * sizeof(*entries[i].items)); Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/index.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/index.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/index.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/index.h Sun Jun 14 20:58:10 2015 @@ -83,7 +83,7 @@ typedef struct svn_fs_x__p2l_entry_t { /* offset of the first byte that belongs to the item */ apr_off_t offset; - + /* length of the item in bytes */ apr_off_t size; @@ -132,7 +132,7 @@ svn_fs_x__l2p_proto_index_add_revision(a * (OFFSET, SUB_ITEM) may be (-1, 0) to mark 'invalid' item indexes but * that is already implied for all item indexes not explicitly given a * mapping. - * + * * Use SCRATCH_POOL for temporary allocations. */ svn_error_t * @@ -145,7 +145,7 @@ svn_fs_x__l2p_proto_index_add_entry(apr_ /* Use the proto index file stored at PROTO_FILE_NAME, construct the final * log-to-phys index and append it to INDEX_FILE. The first revision will * be REVISION, entries to the next revision will be assigned to REVISION+1 - * and so forth. + * and so forth. * * Return the MD5 checksum of the on-disk index data in *CHECKSUM, allocated * in RESULT_POOL. Use SCRATCH_POOL for temporary allocations.
