Julian Foad <julianf...@apache.org> writes: > Similar consideration applies to the API. I think this could be a libsvn_fs > API rather than only in libsvn_fs_fs. Agreed?
Maybe, as an alternative to abstracting and promoting this to a public FS API, we could add a way of performing backend-specific I/O operations through an API like svn_fs_ioctl()? See the attached patch that implements it for existing fsfs stats, dump index and load index operations, and, as I suppose, may also be extended for the "get revision size/stats" operation. This concept and the patch serve two purposes: - They allow us to properly expose FS-specific details and invoke FS-specific operations everywhere without necessarily promoting them into a proper public API (the ioctl code itself may be made either public or private, depending on the requirements). - They solve an potential dependency/linking problem where tools like `svnfsfs` work through the libsvn_fs's loader, but also have to load and call private APIs from libsvn_fs_fs thus ignoring the loader. The latter part may potentially cause issues with the global shared state, etc. With the patch, all such operations always go through the FS loader. Regards, Evgeny Kotkov
Index: build.conf =================================================================== --- build.conf (revision 1857216) +++ build.conf (working copy) @@ -442,7 +442,7 @@ description = Subversion FSFS Repository Manipulat type = exe path = subversion/svnfsfs install = bin -libs = libsvn_repos libsvn_fs libsvn_fs_fs libsvn_delta libsvn_subr apriconv apr +libs = libsvn_repos libsvn_fs libsvn_delta libsvn_subr apriconv apr # ---------------------------------------------------------------------------- # @@ -831,7 +831,7 @@ type = exe path = subversion/tests/libsvn_fs_fs sources = fs-fs-private-test.c install = test -libs = libsvn_test libsvn_fs libsvn_fs_fs libsvn_delta +libs = libsvn_test libsvn_fs libsvn_delta libsvn_repos libsvn_subr apriconv apr msvc-force-static = yes Index: subversion/include/private/svn_fs_fs_private.h =================================================================== --- subversion/include/private/svn_fs_fs_private.h (revision 1857216) +++ subversion/include/private/svn_fs_fs_private.h (working copy) @@ -255,22 +255,6 @@ typedef struct svn_fs_fs__stats_t apr_hash_t *by_extension; } svn_fs_fs__stats_t; - -/* Scan all contents of the repository FS and return statistics in *STATS, - * allocated in RESULT_POOL. Report progress through PROGRESS_FUNC with - * PROGRESS_BATON, if PROGRESS_FUNC is not NULL. - * Use SCRATCH_POOL for temporary allocations. - */ -svn_error_t * -svn_fs_fs__get_stats(svn_fs_fs__stats_t **stats, - svn_fs_t *fs, - svn_fs_progress_notify_func_t progress_func, - void *progress_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); - /* A node-revision ID in FSFS consists of 3 sub-IDs ("parts") that consist * of a creation REVISION number and some revision- / transaction-local * counter value (NUMBER). Old-style ID parts use global counter values. @@ -325,34 +309,37 @@ typedef svn_error_t * void *baton, apr_pool_t *scratch_pool); -/* Read the P2L index for the rev / pack file containing REVISION in FS. - * For each index entry, invoke CALLBACK_FUNC with CALLBACK_BATON. - * If not NULL, call CANCEL_FUNC with CANCEL_BATON from time to time. - * Use SCRATCH_POOL for temporary allocations. - */ -svn_error_t * -svn_fs_fs__dump_index(svn_fs_t *fs, - svn_revnum_t revision, - svn_fs_fs__dump_index_func_t callback_func, - void *callback_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool); +typedef struct svn_fs_fs__ioctl_get_stats_input_t +{ + svn_fs_progress_notify_func_t progress_func; + void *progress_baton; +} svn_fs_fs__ioctl_get_stats_input_t; +typedef struct svn_fs_fs__ioctl_get_stats_output_t +{ + svn_fs_fs__stats_t *stats; +} svn_fs_fs__ioctl_get_stats_output_t; -/* Rewrite the respective index information of the rev / pack file in FS - * containing REVISION and use the svn_fs_fs__p2l_entry_t * array ENTRIES - * as the new index contents. Allocate temporaries from SCRATCH_POOL. - * - * Note that this becomes a no-op if ENTRIES is empty. You may use a zero- - * sized empty entry instead. - */ -svn_error_t * -svn_fs_fs__load_index(svn_fs_t *fs, - svn_revnum_t revision, - apr_array_header_t *entries, - apr_pool_t *scratch_pool); +SVN_FS_DECLARE_IOCTL_CODE(SVN_FS_FS__IOCTL_GET_STATS, SVN_FS_TYPE_FSFS, 1000); +typedef struct svn_fs_fs__ioctl_dump_index_input_t +{ + svn_revnum_t revision; + svn_fs_fs__dump_index_func_t callback_func; + void *callback_baton; +} svn_fs_fs__ioctl_dump_index_input_t; + +SVN_FS_DECLARE_IOCTL_CODE(SVN_FS_FS__IOCTL_DUMP_INDEX, SVN_FS_TYPE_FSFS, 1001); + +typedef struct svn_fs_fs__ioctl_load_index_input_t +{ + svn_revnum_t revision; + /* Array of svn_fs_fs__p2l_entry_t * entries. */ + apr_array_header_t *entries; +} svn_fs_fs__ioctl_load_index_input_t; + +SVN_FS_DECLARE_IOCTL_CODE(SVN_FS_FS__IOCTL_LOAD_INDEX, SVN_FS_TYPE_FSFS, 1002); + #ifdef __cplusplus } #endif /* __cplusplus */ Index: subversion/include/svn_error_codes.h =================================================================== --- subversion/include/svn_error_codes.h (revision 1857216) +++ subversion/include/svn_error_codes.h (working copy) @@ -888,6 +888,11 @@ SVN_ERROR_START SVN_ERR_FS_CATEGORY_START + 67, "Content checksums supposedly match but content does not.") + /** @since New in 1.13. */ + SVN_ERRDEF(SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE, + SVN_ERR_FS_CATEGORY_START + 68, + "Unrecognized filesystem I/O control code") + /* repos errors */ SVN_ERRDEF(SVN_ERR_REPOS_LOCKED, Index: subversion/include/svn_fs.h =================================================================== --- subversion/include/svn_fs.h (revision 1857216) +++ subversion/include/svn_fs.h (working copy) @@ -3503,6 +3503,54 @@ svn_fs_info_dup(const void *info, apr_pool_t *result_pool, apr_pool_t *scratch_pool); +/** + * A structure specifying the filesystem-specific input/output operation. + * + * @see #svn_fs_ioctl + * + * @since New in 1.13. + */ +typedef struct svn_fs_ioctl_code_t +{ + const char *fs_type; + int code; +} svn_fs_ioctl_code_t; + +/** + * A convenience macro to declare svn_fs_ioctl_code_t codes. + * + * @since New in 1.13. + */ +#define SVN_FS_DECLARE_IOCTL_CODE(name, fs_type, code) \ + static const svn_fs_ioctl_code_t name = { fs_type, code } + +/** + * Issue a filesystem-specific input/output operation defined by @ctlcode + * (usually, a low-level operation which cannot be expressed by other + * filesystem APIs). If @fs is @c NULL, issue a global operation. + * If @fs is not @c NULL, issue an operation that is specific to this + * filesystem instance. + * + * If the filesystem cannot handle this ioctl code, return the + * #SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE error. + * + * Allocate the result in @result_pool, use @a scratch_pool for temporary + * allocations. + * + * @see #svn_fs_ioctl_code_t + * + * @since New in 1.13. + */ +svn_error_t * +svn_fs_ioctl(svn_fs_t *fs, + svn_fs_ioctl_code_t ctlcode, + void *input, + void **output_p, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /** @} */ #ifdef __cplusplus Index: subversion/libsvn_fs/fs-loader.c =================================================================== --- subversion/libsvn_fs/fs-loader.c (revision 1857216) +++ subversion/libsvn_fs/fs-loader.c (working copy) @@ -2221,3 +2221,42 @@ svn_fs_info_dup(const void *info_void, return apr_pmemdup(result_pool, info, sizeof(*info)); } +svn_error_t * +svn_fs_ioctl(svn_fs_t *fs, + svn_fs_ioctl_code_t ctlcode, + void *input, + void **output_p, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + void *output; + + if (fs) + { + if (!fs->vtable->ioctl) + return svn_error_create(SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE, NULL, NULL); + + SVN_ERR(fs->vtable->ioctl(fs, ctlcode, input, &output, + cancel_func, cancel_baton, + result_pool, scratch_pool)); + } + else + { + fs_library_vtable_t *vtable; + + SVN_ERR(get_library_vtable(&vtable, ctlcode.fs_type, scratch_pool)); + + if (!vtable->ioctl) + return svn_error_create(SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE, NULL, NULL); + + SVN_ERR(vtable->ioctl(ctlcode, input, &output, + cancel_func, cancel_baton, + result_pool, scratch_pool)); + } + + if (output_p) + *output_p = output; + return SVN_NO_ERROR; +} Index: subversion/libsvn_fs/fs-loader.h =================================================================== --- subversion/libsvn_fs/fs-loader.h (revision 1857216) +++ subversion/libsvn_fs/fs-loader.h (working copy) @@ -159,6 +159,13 @@ typedef struct fs_library_vtable_t /* For svn_fs_info_fsfs_dup(). */ void *(*info_fsap_dup)(const void *fsap_info, apr_pool_t *result_pool); + + svn_error_t *(*ioctl)(svn_fs_ioctl_code_t ctlcode, + void *input, void **output_p, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); } fs_library_vtable_t; /* This is the type of symbol an FS module defines to fetch the @@ -266,6 +273,12 @@ typedef struct fs_vtable_t svn_error_t *(*bdb_set_errcall)(svn_fs_t *fs, void (*handler)(const char *errpfx, char *msg)); + svn_error_t *(*ioctl)(svn_fs_t *fs, svn_fs_ioctl_code_t ctlcode, + void *input, void **output_p, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); } fs_vtable_t; Index: subversion/libsvn_fs_base/fs.c =================================================================== --- subversion/libsvn_fs_base/fs.c (revision 1857216) +++ subversion/libsvn_fs_base/fs.c (working copy) @@ -574,6 +574,7 @@ static fs_vtable_t fs_vtable = { base_bdb_verify_root, base_bdb_freeze, base_bdb_set_errcall, + NULL /* ioctl */ }; /* Where the format number is stored. */ @@ -1515,7 +1516,8 @@ static fs_library_vtable_t library_vtable = { base_bdb_logfiles, svn_fs_base__id_parse, base_set_svn_fs_open, - NULL /* info_fsap_dup */ + NULL /* info_fsap_dup */, + NULL /* ioctl */ }; svn_error_t * Index: subversion/libsvn_fs_fs/dump-index.c =================================================================== --- subversion/libsvn_fs_fs/dump-index.c (revision 1857216) +++ subversion/libsvn_fs_fs/dump-index.c (working copy) @@ -21,8 +21,8 @@ */ #include "svn_pools.h" -#include "private/svn_fs_fs_private.h" +#include "fs_fs.h" #include "index.h" #include "rev_file.h" #include "util.h" Index: subversion/libsvn_fs_fs/fs.c =================================================================== --- subversion/libsvn_fs_fs/fs.c (revision 1857216) +++ subversion/libsvn_fs_fs/fs.c (working copy) @@ -47,6 +47,7 @@ #include "verify.h" #include "svn_private_config.h" #include "private/svn_fs_util.h" +#include "private/svn_fs_fs_private.h" #include "../libsvn_fs/fs-loader.h" @@ -254,7 +255,58 @@ fs_set_uuid(svn_fs_t *fs, } +static svn_error_t * +fs_ioctl(svn_fs_t *fs, svn_fs_ioctl_code_t ctlcode, + void *input_void, void **output_p, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (strcmp(ctlcode.fs_type, SVN_FS_TYPE_FSFS) == 0) + { + if (ctlcode.code == SVN_FS_FS__IOCTL_GET_STATS.code) + { + svn_fs_fs__ioctl_get_stats_input_t *input = input_void; + svn_fs_fs__ioctl_get_stats_output_t *output; + output = apr_pcalloc(result_pool, sizeof(*output)); + SVN_ERR(svn_fs_fs__get_stats(&output->stats, fs, + input->progress_func, + input->progress_baton, + cancel_func, cancel_baton, + result_pool, scratch_pool)); + *output_p = output; + } + else if (ctlcode.code == SVN_FS_FS__IOCTL_DUMP_INDEX.code) + { + svn_fs_fs__ioctl_dump_index_input_t *input = input_void; + + SVN_ERR(svn_fs_fs__dump_index(fs, input->revision, + input->callback_func, + input->callback_baton, + cancel_func, cancel_baton, + scratch_pool)); + *output_p = NULL; + } + else if (ctlcode.code == SVN_FS_FS__IOCTL_LOAD_INDEX.code) + { + svn_fs_fs__ioctl_load_index_input_t *input = input_void; + + SVN_ERR(svn_fs_fs__load_index(fs, input->revision, input->entries, + scratch_pool)); + *output_p = NULL; + } + else + return svn_error_create(SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE, NULL, NULL); + + } + else + return svn_error_create(SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE, NULL, NULL); + + return SVN_NO_ERROR; +} + /* The vtable associated with a specific open filesystem. */ static fs_vtable_t fs_vtable = { svn_fs_fs__youngest_rev, @@ -279,7 +331,8 @@ static fs_vtable_t fs_vtable = { fs_info, svn_fs_fs__verify_root, fs_freeze, - fs_set_errcall + fs_set_errcall, + fs_ioctl }; @@ -602,7 +655,8 @@ static fs_library_vtable_t library_vtable = { fs_logfiles, NULL /* parse_id */, fs_set_svn_fs_open, - fs_info_dup + fs_info_dup, + NULL /* ioctl */ }; svn_error_t * Index: subversion/libsvn_fs_fs/fs_fs.h =================================================================== --- subversion/libsvn_fs_fs/fs_fs.h (revision 1857216) +++ subversion/libsvn_fs_fs/fs_fs.h (working copy) @@ -304,4 +304,47 @@ svn_fs_fs__initialize_txn_caches(svn_fs_t *fs, void svn_fs_fs__reset_txn_caches(svn_fs_t *fs); +/* Scan all contents of the repository FS and return statistics in *STATS, + * allocated in RESULT_POOL. Report progress through PROGRESS_FUNC with + * PROGRESS_BATON, if PROGRESS_FUNC is not NULL. + * Use SCRATCH_POOL for temporary allocations. + */ +svn_error_t * +svn_fs_fs__get_stats(svn_fs_fs__stats_t **stats, + svn_fs_t *fs, + svn_fs_progress_notify_func_t progress_func, + void *progress_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Read the P2L index for the rev / pack file containing REVISION in FS. + * For each index entry, invoke CALLBACK_FUNC with CALLBACK_BATON. + * If not NULL, call CANCEL_FUNC with CANCEL_BATON from time to time. + * Use SCRATCH_POOL for temporary allocations. + */ +svn_error_t * +svn_fs_fs__dump_index(svn_fs_t *fs, + svn_revnum_t revision, + svn_fs_fs__dump_index_func_t callback_func, + void *callback_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool); + + +/* Rewrite the respective index information of the rev / pack file in FS + * containing REVISION and use the svn_fs_fs__p2l_entry_t * array ENTRIES + * as the new index contents. Allocate temporaries from SCRATCH_POOL. + * + * Note that this becomes a no-op if ENTRIES is empty. You may use a zero- + * sized empty entry instead. + */ +svn_error_t * +svn_fs_fs__load_index(svn_fs_t *fs, + svn_revnum_t revision, + apr_array_header_t *entries, + apr_pool_t *scratch_pool); + #endif Index: subversion/libsvn_fs_fs/load-index.c =================================================================== --- subversion/libsvn_fs_fs/load-index.c (revision 1857216) +++ subversion/libsvn_fs_fs/load-index.c (working copy) @@ -22,9 +22,9 @@ #include "svn_pools.h" -#include "private/svn_fs_fs_private.h" #include "private/svn_sorts_private.h" +#include "fs_fs.h" #include "index.h" #include "util.h" #include "transaction.h" Index: subversion/libsvn_fs_x/fs.c =================================================================== --- subversion/libsvn_fs_x/fs.c (revision 1857216) +++ subversion/libsvn_fs_x/fs.c (working copy) @@ -310,7 +310,8 @@ static fs_vtable_t fs_vtable = { x_info, svn_fs_x__verify_root, x_freeze, - x_set_errcall + x_set_errcall, + NULL /* ioctl */ }; @@ -641,7 +642,8 @@ static fs_library_vtable_t library_vtable = { x_logfiles, NULL /* parse_id */, x_set_svn_fs_open, - x_info_dup + x_info_dup, + NULL /* ioctl */ }; svn_error_t * Index: subversion/svnfsfs/dump-index-cmd.c =================================================================== --- subversion/svnfsfs/dump-index-cmd.c (revision 1857216) +++ subversion/svnfsfs/dump-index-cmd.c (working copy) @@ -79,6 +79,7 @@ dump_index(const char *path, apr_pool_t *pool) { svn_fs_t *fs; + svn_fs_fs__ioctl_dump_index_input_t input = {0}; /* Check repository type and open it. */ SVN_ERR(open_fs(&fs, path, pool)); @@ -87,8 +88,10 @@ dump_index(const char *path, printf(" Start Length Type Revision Item Checksum\n"); /* Dump the whole index contents */ - SVN_ERR(svn_fs_fs__dump_index(fs, revision, dump_index_entry, NULL, - check_cancel, NULL, pool)); + input.revision = revision; + input.callback_func = dump_index_entry; + SVN_ERR(svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_DUMP_INDEX, &input, NULL, + check_cancel, NULL, pool, pool)); return SVN_NO_ERROR; } Index: subversion/svnfsfs/load-index-cmd.c =================================================================== --- subversion/svnfsfs/load-index-cmd.c (revision 1857216) +++ subversion/svnfsfs/load-index-cmd.c (working copy) @@ -135,6 +135,7 @@ load_index(const char *path, svn_revnum_t revision = SVN_INVALID_REVNUM; apr_array_header_t *entries = apr_array_make(pool, 16, sizeof(void*)); apr_pool_t *iterpool = svn_pool_create(pool); + svn_fs_fs__ioctl_load_index_input_t ioctl_input = {0}; /* Check repository type and open it. */ SVN_ERR(open_fs(&fs, path, pool)); @@ -173,7 +174,10 @@ load_index(const char *path, } /* Rewrite the indexes. */ - SVN_ERR(svn_fs_fs__load_index(fs, revision, entries, iterpool)); + ioctl_input.revision = revision; + ioctl_input.entries = entries; + SVN_ERR(svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_LOAD_INDEX, &ioctl_input, NULL, + NULL, NULL, pool, pool)); svn_pool_destroy(iterpool); return SVN_NO_ERROR; Index: subversion/svnfsfs/stats-cmd.c =================================================================== --- subversion/svnfsfs/stats-cmd.c (revision 1857216) +++ subversion/svnfsfs/stats-cmd.c (working copy) @@ -500,15 +500,17 @@ svn_error_t * subcommand__stats(apr_getopt_t *os, void *baton, apr_pool_t *pool) { svnfsfs__opt_state *opt_state = baton; - svn_fs_fs__stats_t *stats; svn_fs_t *fs; + svn_fs_fs__ioctl_get_stats_input_t input = {0}; + svn_fs_fs__ioctl_get_stats_output_t *output; printf("Reading revisions\n"); SVN_ERR(open_fs(&fs, opt_state->repository_path, pool)); - SVN_ERR(svn_fs_fs__get_stats(&stats, fs, print_progress, NULL, - check_cancel, NULL, pool, pool)); - print_stats(stats, pool); + input.progress_func = print_progress; + SVN_ERR(svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_GET_STATS, &input, (void **)&output, + check_cancel, NULL, pool, pool)); + print_stats(output->stats, pool); return SVN_NO_ERROR; } Index: subversion/tests/libsvn_fs/fs-test.c =================================================================== --- subversion/tests/libsvn_fs/fs-test.c (revision 1857216) +++ subversion/tests/libsvn_fs/fs-test.c (working copy) @@ -7441,6 +7441,34 @@ test_closest_copy_file_replaced_with_dir(const svn return SVN_NO_ERROR; } +static svn_error_t * +tets_unrecognized_ioctl(const svn_test_opts_t *opts, + apr_pool_t *pool) +{ + svn_fs_t *fs; + svn_error_t *err; + svn_fs_ioctl_code_t code = {0}; + + SVN_ERR(svn_test__create_fs(&fs, "test-unrecognized-ioctl", opts, pool)); + + code.fs_type = "NON-EXISTING"; + code.code = 98765; + err = svn_fs_ioctl(fs, code, NULL, NULL, NULL, NULL, pool, pool); + SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE); + + code.fs_type = "NON-EXISTING"; + code.code = 98765; + err = svn_fs_ioctl(NULL, code, NULL, NULL, NULL, NULL, pool, pool); + SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_UNKNOWN_FS_TYPE); + + code.fs_type = opts->fs_type; + code.code = 98765; + err = svn_fs_ioctl(NULL, code, NULL, NULL, NULL, NULL, pool, pool); + SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE); + + return SVN_NO_ERROR; +} + /* ------------------------------------------------------------------------ */ /* The test table. */ @@ -7587,6 +7615,8 @@ static struct svn_test_descriptor_t test_funcs[] = "test issue SVN-4677 regression"), SVN_TEST_OPTS_PASS(test_closest_copy_file_replaced_with_dir, "svn_fs_closest_copy after replacing file with dir"), + SVN_TEST_OPTS_PASS(tets_unrecognized_ioctl, + "test svn_fs_ioctl with unrecognized code"), SVN_TEST_NULL }; Index: subversion/tests/libsvn_fs_fs/fs-fs-private-test.c =================================================================== --- subversion/tests/libsvn_fs_fs/fs-fs-private-test.c (revision 1857216) +++ subversion/tests/libsvn_fs_fs/fs-fs-private-test.c (working copy) @@ -199,8 +199,10 @@ get_repo_stats(const svn_test_opts_t *opts, svn_repos_t *repos; svn_revnum_t rev; apr_size_t i; - svn_fs_fs__stats_t *stats; svn_fs_fs__extension_info_t *extension_info; + svn_fs_fs__ioctl_get_stats_input_t input = {0}; + svn_fs_fs__ioctl_get_stats_output_t *output; + const svn_fs_fs__stats_t *stats; /* Bail (with success) on known-untestable scenarios */ if (strcmp(opts->fs_type, "fsfs") != 0) @@ -211,8 +213,9 @@ get_repo_stats(const svn_test_opts_t *opts, SVN_ERR(create_greek_repo(&repos, &rev, opts, REPO_NAME, pool, pool)); /* Gather statistics info on that repo. */ - SVN_ERR(svn_fs_fs__get_stats(&stats, svn_repos_fs(repos), NULL, NULL, - NULL, NULL, pool, pool)); + SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_GET_STATS, + &input, (void**)&output, NULL, NULL, pool, pool)); + stats = output->stats; /* Check that the stats make sense. */ SVN_TEST_ASSERT(stats->total_size > 1000 && stats->total_size < 10000); @@ -324,6 +327,7 @@ dump_index(const svn_test_opts_t *opts, svn_repos_t *repos; svn_revnum_t rev; dump_baton_t baton; + svn_fs_fs__ioctl_dump_index_input_t input = {0}; /* Bail (with success) on known-untestable scenarios */ if (strcmp(opts->fs_type, "fsfs") != 0) @@ -342,9 +346,13 @@ dump_index(const svn_test_opts_t *opts, baton.offset = 0; baton.revision = rev; baton.numbers_seen = svn_bit_array__create(100, pool); - SVN_ERR(svn_fs_fs__dump_index(svn_repos_fs(repos), rev, dump_index_entry, - &baton, NULL, NULL, pool)); + input.revision = rev; + input.callback_func = dump_index_entry; + input.callback_baton = &baton; + SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_DUMP_INDEX, + &input, NULL, NULL, NULL, pool, pool)); + /* Check that we've got all data (20 noderevs + 20 reps + 1 changes list). */ SVN_TEST_ASSERT(baton.invocations == 41); @@ -377,6 +385,8 @@ load_index(const svn_test_opts_t *opts, apr_pool_t apr_array_header_t *entries = apr_array_make(pool, 41, sizeof(void *)); apr_array_header_t *alt_entries = apr_array_make(pool, 1, sizeof(void *)); svn_fs_fs__p2l_entry_t entry; + svn_fs_fs__ioctl_dump_index_input_t dump_input = {0}; + svn_fs_fs__ioctl_load_index_input_t load_input = {0}; /* Bail (with success) on known-untestable scenarios */ if (strcmp(opts->fs_type, "fsfs") != 0) @@ -391,8 +401,11 @@ load_index(const svn_test_opts_t *opts, apr_pool_t SVN_ERR(create_greek_repo(&repos, &rev, opts, REPO_NAME, pool, pool)); /* Read the original index contents for REV in ENTRIES. */ - SVN_ERR(svn_fs_fs__dump_index(svn_repos_fs(repos), rev, receive_index, - entries, NULL, NULL, pool)); + dump_input.revision = rev; + dump_input.callback_func = receive_index; + dump_input.callback_baton = entries; + SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_DUMP_INDEX, + &dump_input, NULL, NULL, NULL, pool, pool)); /* Replace it with an index that declares the whole revision contents as * "unused". */ @@ -404,7 +417,11 @@ load_index(const svn_test_opts_t *opts, apr_pool_t entry.item.revision = SVN_INVALID_REVNUM; APR_ARRAY_PUSH(alt_entries, svn_fs_fs__p2l_entry_t *) = &entry; - SVN_ERR(svn_fs_fs__load_index(svn_repos_fs(repos), rev, alt_entries, pool)); + load_input.revision = rev; + load_input.entries = alt_entries; + SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_LOAD_INDEX, + &load_input, NULL, NULL, NULL, pool, pool)); + SVN_TEST_ASSERT_ERROR(svn_repos_verify_fs3(repos, rev, rev, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, pool), @@ -411,7 +428,10 @@ load_index(const svn_test_opts_t *opts, apr_pool_t SVN_ERR_FS_INDEX_CORRUPTION); /* Restore the original index. */ - SVN_ERR(svn_fs_fs__load_index(svn_repos_fs(repos), rev, entries, pool)); + load_input.revision = rev; + load_input.entries = entries; + SVN_ERR(svn_fs_ioctl(svn_repos_fs(repos), SVN_FS_FS__IOCTL_LOAD_INDEX, + &load_input, NULL, NULL, NULL, pool, pool)); SVN_ERR(svn_repos_verify_fs3(repos, rev, rev, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, pool));