diff options
author | Peter Wemm <peter@FreeBSD.org> | 2018-05-08 03:44:38 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 2018-05-08 03:44:38 +0000 |
commit | 3faf8d6bffc5d0fb2525ba37bb504c53366caf9d (patch) | |
tree | 7e47911263e75034b767fe34b2f8d3d17e91f66d /subversion/libsvn_fs_x/util.c | |
parent | a55fb3c0d5eca7d887798125d5b95942b1f01d4b (diff) |
Diffstat (limited to 'subversion/libsvn_fs_x/util.c')
-rw-r--r-- | subversion/libsvn_fs_x/util.c | 182 |
1 files changed, 69 insertions, 113 deletions
diff --git a/subversion/libsvn_fs_x/util.c b/subversion/libsvn_fs_x/util.c index da004ad8febb..bab47fc6d01c 100644 --- a/subversion/libsvn_fs_x/util.c +++ b/subversion/libsvn_fs_x/util.c @@ -110,11 +110,17 @@ svn_fs_x__path_current(svn_fs_t *fs, } const char * +svn_fs_x__path_next(svn_fs_t *fs, + apr_pool_t *result_pool) +{ + return svn_dirent_join(fs->path, PATH_NEXT, result_pool); +} + +const char * svn_fs_x__path_txn_current(svn_fs_t *fs, apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_TXN_CURRENT, - result_pool); + return svn_dirent_join(fs->path, PATH_TXN_CURRENT, result_pool); } const char * @@ -147,14 +153,12 @@ svn_fs_x__path_revprop_generation(svn_fs_t *fs, /* Return the full path of the file FILENAME within revision REV's shard in * FS. If FILENAME is NULL, return the shard directory directory itself. - * REVPROPS indicates the parent of the shard parent folder ("revprops" or - * "revs"). PACKED says whether we want the packed shard's name. + * PACKED says whether we want the packed shard's name. * * Allocate the result in RESULT_POOL. */static const char* construct_shard_sub_path(svn_fs_t *fs, svn_revnum_t rev, - svn_boolean_t revprops, svn_boolean_t packed, const char *filename, apr_pool_t *result_pool) @@ -162,9 +166,6 @@ construct_shard_sub_path(svn_fs_t *fs, svn_fs_x__data_t *ffd = fs->fsap_data; char buffer[SVN_INT64_BUFFER_SIZE + sizeof(PATH_EXT_PACKED_SHARD)] = { 0 }; - /* Select the appropriate parent path constant. */ - const char *parent = revprops ? PATH_REVPROPS_DIR : PATH_REVS_DIR; - /* String containing the shard number. */ apr_size_t len = svn__i64toa(buffer, rev / ffd->max_files_per_dir); @@ -173,7 +174,7 @@ construct_shard_sub_path(svn_fs_t *fs, strncpy(buffer + len, PATH_EXT_PACKED_SHARD, sizeof(buffer) - len - 1); /* This will also work for NULL FILENAME as well. */ - return svn_dirent_join_many(result_pool, fs->path, parent, buffer, + return svn_dirent_join_many(result_pool, fs->path, PATH_REVS_DIR, buffer, filename, SVN_VA_NULL); } @@ -184,15 +185,15 @@ svn_fs_x__path_rev_packed(svn_fs_t *fs, apr_pool_t *result_pool) { assert(svn_fs_x__is_packed_rev(fs, rev)); - return construct_shard_sub_path(fs, rev, FALSE, TRUE, kind, result_pool); + return construct_shard_sub_path(fs, rev, TRUE, kind, result_pool); } const char * -svn_fs_x__path_rev_shard(svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool) +svn_fs_x__path_shard(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool) { - return construct_shard_sub_path(fs, rev, FALSE, FALSE, NULL, result_pool); + return construct_shard_sub_path(fs, rev, FALSE, NULL, result_pool); } const char * @@ -200,11 +201,12 @@ svn_fs_x__path_rev(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *result_pool) { - char buffer[SVN_INT64_BUFFER_SIZE]; - svn__i64toa(buffer, rev); + char buffer[SVN_INT64_BUFFER_SIZE + 1]; + buffer[0] = 'r'; + svn__i64toa(buffer + 1, rev); assert(! svn_fs_x__is_packed_rev(fs, rev)); - return construct_shard_sub_path(fs, rev, FALSE, FALSE, buffer, result_pool); + return construct_shard_sub_path(fs, rev, FALSE, buffer, result_pool); } const char * @@ -218,19 +220,11 @@ svn_fs_x__path_rev_absolute(svn_fs_t *fs, } const char * -svn_fs_x__path_revprops_shard(svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool) -{ - return construct_shard_sub_path(fs, rev, TRUE, FALSE, NULL, result_pool); -} - -const char * -svn_fs_x__path_revprops_pack_shard(svn_fs_t *fs, +svn_fs_x__path_pack_shard(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *result_pool) { - return construct_shard_sub_path(fs, rev, TRUE, TRUE, NULL, result_pool); + return construct_shard_sub_path(fs, rev, TRUE, NULL, result_pool); } const char * @@ -238,11 +232,17 @@ svn_fs_x__path_revprops(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *result_pool) { - char buffer[SVN_INT64_BUFFER_SIZE]; - svn__i64toa(buffer, rev); + char buffer[SVN_INT64_BUFFER_SIZE + 1]; + buffer[0] = 'p'; + svn__i64toa(buffer + 1, rev); assert(! svn_fs_x__is_packed_revprop(fs, rev)); - return construct_shard_sub_path(fs, rev, TRUE, FALSE, buffer, result_pool); + + /* Revprops for packed r0 are not packed, yet stored in the packed shard. + Hence, the second flag must check for packed _rev_ - not revprop. */ + return construct_shard_sub_path(fs, rev, + svn_fs_x__is_packed_rev(fs, rev) /* sic! */, + buffer, result_pool); } const char * @@ -340,14 +340,6 @@ svn_fs_x__path_txn_props(svn_fs_t *fs, return construct_txn_path(fs, txn_id, PATH_TXN_PROPS, result_pool); } -const char * -svn_fs_x__path_txn_props_final(svn_fs_t *fs, - svn_fs_x__txn_id_t txn_id, - apr_pool_t *result_pool) -{ - return construct_txn_path(fs, txn_id, PATH_TXN_PROPS_FINAL, result_pool); -} - const char* svn_fs_x__path_l2p_proto_index(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, @@ -543,6 +535,7 @@ svn_fs_x__write_min_unpacked_rev(svn_fs_t *fs, svn_revnum_t revnum, apr_pool_t *scratch_pool) { + svn_fs_x__data_t *ffd = fs->fsap_data; const char *final_path; char buf[SVN_INT64_BUFFER_SIZE]; apr_size_t len = svn__i64toa(buf, revnum); @@ -550,8 +543,9 @@ svn_fs_x__write_min_unpacked_rev(svn_fs_t *fs, final_path = svn_fs_x__path_min_unpacked_rev(fs, scratch_pool); - SVN_ERR(svn_io_write_atomic(final_path, buf, len + 1, - final_path /* copy_perms */, scratch_pool)); + SVN_ERR(svn_io_write_atomic2(final_path, buf, len + 1, + final_path /* copy_perms */, + ffd->flush_to_disk, scratch_pool)); return SVN_NO_ERROR; } @@ -574,7 +568,7 @@ svn_fs_x__read_current(svn_revnum_t *rev, return SVN_NO_ERROR; } -/* Atomically update the 'current' file to hold the specifed REV. +/* Atomically update the 'current' file to hold the specified REV. Perform temporary allocations in SCRATCH_POOL. */ svn_error_t * svn_fs_x__write_current(svn_fs_t *fs, @@ -583,17 +577,28 @@ svn_fs_x__write_current(svn_fs_t *fs, { char *buf; const char *tmp_name, *name; + apr_file_t *file; /* Now we can just write out this line. */ buf = apr_psprintf(scratch_pool, "%ld\n", rev); name = svn_fs_x__path_current(fs, scratch_pool); - SVN_ERR(svn_io_write_unique(&tmp_name, - svn_dirent_dirname(name, scratch_pool), - buf, strlen(buf), - svn_io_file_del_none, scratch_pool)); + tmp_name = svn_fs_x__path_next(fs, scratch_pool); - return svn_fs_x__move_into_place(tmp_name, name, name, scratch_pool); + SVN_ERR(svn_io_file_open(&file, tmp_name, + APR_WRITE | APR_CREATE | APR_BUFFERED, + APR_OS_DEFAULT, scratch_pool)); + SVN_ERR(svn_io_file_write_full(file, buf, strlen(buf), NULL, + scratch_pool)); + SVN_ERR(svn_io_file_close(file, scratch_pool)); + + /* Copying permissions is a no-op on WIN32. */ + SVN_ERR(svn_io_copy_perms(name, tmp_name, scratch_pool)); + + /* Move the file into place. */ + SVN_ERR(svn_io_file_rename2(tmp_name, name, TRUE, scratch_pool)); + + return SVN_NO_ERROR; } @@ -640,22 +645,6 @@ svn_fs_x__try_stringbuf_from_file(svn_stringbuf_t **content, /* Fetch the current offset of FILE into *OFFSET_P. */ svn_error_t * -svn_fs_x__get_file_offset(apr_off_t *offset_p, - apr_file_t *file, - apr_pool_t *scratch_pool) -{ - apr_off_t offset; - - /* Note that, for buffered files, one (possibly surprising) side-effect - of this call is to flush any unwritten data to disk. */ - offset = 0; - SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, scratch_pool)); - *offset_p = offset; - - return SVN_NO_ERROR; -} - -svn_error_t * svn_fs_x__read_content(svn_stringbuf_t **content, const char *fname, apr_pool_t *result_pool) @@ -711,66 +700,33 @@ svn_fs_x__read_number_from_stream(apr_int64_t *result, return SVN_NO_ERROR; } - -/* Move a file into place from OLD_FILENAME in the transactions - directory to its final location NEW_FILENAME in the repository. On - Unix, match the permissions of the new file to the permissions of - PERMS_REFERENCE. Temporary allocations are from SCRATCH_POOL. - - This function almost duplicates svn_io_file_move(), but it tries to - guarantee a flush. */ svn_error_t * svn_fs_x__move_into_place(const char *old_filename, const char *new_filename, const char *perms_reference, + svn_fs_x__batch_fsync_t *batch, apr_pool_t *scratch_pool) { - svn_error_t *err; - + /* Copying permissions is a no-op on WIN32. */ SVN_ERR(svn_io_copy_perms(perms_reference, old_filename, scratch_pool)); + /* We use specific 'fsyncing move' Win32 API calls on Windows while the + * directory update fsync is POSIX-only. Moreover, there tend to be only + * a few moved files (1 or 2) per batch. + * + * Therefore, we use the platform-optimized "immediate" fsyncs on all + * non-POSIX platforms and the "scheduled" fsyncs on POSIX only. + */ +#if defined(SVN_ON_POSIX) /* Move the file into place. */ - err = svn_io_file_rename(old_filename, new_filename, scratch_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; - SVN_ERR(svn_io_copy_file(old_filename, new_filename, TRUE, - scratch_pool)); - - /* Flush the target of the copy to disk. */ - SVN_ERR(svn_io_file_open(&file, new_filename, APR_READ, - APR_OS_DEFAULT, scratch_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, scratch_pool)); - SVN_ERR(svn_io_file_close(file, scratch_pool)); - } - if (err) - return svn_error_trace(err); - -#ifdef __linux__ - { - /* 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 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, scratch_pool); - SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, - scratch_pool)); - SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool)); - SVN_ERR(svn_io_file_close(file, scratch_pool)); - } + SVN_ERR(svn_io_file_rename2(old_filename, new_filename, FALSE, + scratch_pool)); + + /* Schedule for synchronization. */ + SVN_ERR(svn_fs_x__batch_fsync_new_path(batch, new_filename, scratch_pool)); +#else + SVN_ERR(svn_io_file_rename2(old_filename, new_filename, TRUE, + scratch_pool)); #endif return SVN_NO_ERROR; |