Author: kotkov
Date: Fri Apr 12 21:28:17 2019
New Revision: 1857435

URL: http://svn.apache.org/viewvc?rev=1857435&view=rev
Log:
Reimplement fsfs private operations required by `svnfsfs` (stats, dump index,
load index) as "ioctls".

Technically we achieve this by introducing the new svn_fs_ioctl() API that
adds a generic way of performing backend-specific I/O operations.

This change serves two purposes:

- It allows 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).

- It solves a 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.


* subversion/include/svn_fs.h
  (svn_fs_ioctl, SVN_FS_DECLARE_IOCTL_CODE, svn_fs_ioctl_code_t): New.

* subversion/include/svn_error_codes.h
  (SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE): New error code.

* subversion/include/private/svn_fs_fs_private.h
  (svn_fs_fs__get_stats, svn_fs_fs__dump_index, svn_fs_fs__load_index):
   These functions are now implemented as...
  (SVN_FS_FS__IOCTL_GET_STATS, SVN_FS_FS__IOCTL_DUMP_INDEX,
   SVN_FS_FS__IOCTL_LOAD_INDEX): ...these new ioctls, which ...
  (svn_fs_fs__ioctl_get_stats_input_t, svn_fs_fs__ioctl_get_stats_output_t,
   svn_fs_fs__ioctl_dump_index_input_t, svn_fs_fs__ioctl_load_index_input_t):
   ...use these new structures.

* subversion/libsvn_fs/fs-loader.h
  (fs_library_vtable_t.ioctl, fs_vtable_t.ioctl): New vtable members.

* subversion/libsvn_fs/fs-loader.c
  (svn_fs_ioctl): Implement the new API by forwarding it to an appropriate
   vtable member.

* subversion/libsvn_fs_fs/fs_fs.h
  (svn_fs_fs__get_stats, svn_fs_fs__dump_index, svn_fs_fs__load_index):
   These functions are now declared here.

* subversion/libsvn_fs_fs/fs.c
  (): Include `svn_fs_fs_private.h`.
  (fs_ioctl): Implement the ioctl dispatcher for three current fsfs-specific
   operations.
  (fs_vtable): Initialize the `ioctl` field.
  (library_vtable): Initialize the `ioctl` field to NULL.

* subversion/libsvn_fs_fs/dump-index.c,
  subversion/libsvn_fs_fs/load-index.c,
  subversion/libsvn_fs_fs/stats.c
  (): Tweak includes.

* subversion/libsvn_fs_base/fs.c
  (library_vtable, fs_vtable): Initialize the `ioctl` field to NULL.

* subversion/libsvn_fs_x/fs.c
  (library_vtable, fs_vtable): Initialize the `ioctl` field to NULL.

* subversion/svnfsfs/dump-index-cmd.c
  (dump_index): Invoke an appropriate svn_fs_ioctl().

* subversion/svnfsfs/load-index-cmd.c
  (load_index): Invoke an appropriate svn_fs_ioctl().

* subversion/svnfsfs/stats-cmd.c
  (subcommand__stats): Invoke an appropriate svn_fs_ioctl().

* subversion/tests/libsvn_fs/fs-test.c
  (test_unrecognized_ioctl): New test.
  (test_funcs): Run the new test.

* subversion/tests/libsvn_fs_fs/fs-fs-private-test.c
  (get_repo_stats, dump_index, load_index): Switch to svn_fs_ioctl().

* build.conf
  (svnfsfs, fs-fs-private-test): Don't link to libsvn_fs_fs.

Modified:
    subversion/trunk/build.conf
    subversion/trunk/subversion/include/private/svn_fs_fs_private.h
    subversion/trunk/subversion/include/svn_error_codes.h
    subversion/trunk/subversion/include/svn_fs.h
    subversion/trunk/subversion/libsvn_fs/fs-loader.c
    subversion/trunk/subversion/libsvn_fs/fs-loader.h
    subversion/trunk/subversion/libsvn_fs_base/fs.c
    subversion/trunk/subversion/libsvn_fs_fs/dump-index.c
    subversion/trunk/subversion/libsvn_fs_fs/fs.c
    subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h
    subversion/trunk/subversion/libsvn_fs_fs/load-index.c
    subversion/trunk/subversion/libsvn_fs_fs/stats.c
    subversion/trunk/subversion/libsvn_fs_x/fs.c
    subversion/trunk/subversion/svnfsfs/dump-index-cmd.c
    subversion/trunk/subversion/svnfsfs/load-index-cmd.c
    subversion/trunk/subversion/svnfsfs/stats-cmd.c
    subversion/trunk/subversion/tests/libsvn_fs/fs-test.c
    subversion/trunk/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c

Modified: subversion/trunk/build.conf
URL: 
http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Fri Apr 12 21:28:17 2019
@@ -442,7 +442,7 @@ description = Subversion FSFS Repository
 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
 

Modified: subversion/trunk/subversion/include/private/svn_fs_fs_private.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_fs_fs_private.h?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_fs_fs_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_fs_fs_private.h Fri Apr 12 
21:28:17 2019
@@ -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,33 +309,36 @@ 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
 }

Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Fri Apr 12 21:28:17 
2019
@@ -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,

Modified: subversion/trunk/subversion/include/svn_fs.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_fs.h?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_fs.h (original)
+++ subversion/trunk/subversion/include/svn_fs.h Fri Apr 12 21:28:17 2019
@@ -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

Modified: subversion/trunk/subversion/libsvn_fs/fs-loader.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs/fs-loader.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/trunk/subversion/libsvn_fs/fs-loader.c Fri Apr 12 21:28:17 2019
@@ -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;
+}

Modified: subversion/trunk/subversion/libsvn_fs/fs-loader.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs/fs-loader.h?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/trunk/subversion/libsvn_fs/fs-loader.h Fri Apr 12 21:28:17 2019
@@ -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;
 
 

Modified: subversion/trunk/subversion/libsvn_fs_base/fs.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_base/fs.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_base/fs.c Fri Apr 12 21:28:17 2019
@@ -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_vtabl
   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 *

Modified: subversion/trunk/subversion/libsvn_fs_fs/dump-index.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/dump-index.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/dump-index.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/dump-index.c Fri Apr 12 21:28:17 
2019
@@ -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"

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.c Fri Apr 12 21:28:17 2019
@@ -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,6 +255,56 @@ 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 = {
@@ -279,7 +330,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 +654,8 @@ static fs_library_vtable_t library_vtabl
   fs_logfiles,
   NULL /* parse_id */,
   fs_set_svn_fs_open,
-  fs_info_dup
+  fs_info_dup,
+  NULL /* ioctl */
 };
 
 svn_error_t *

Modified: subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs_fs.h Fri Apr 12 21:28:17 2019
@@ -304,4 +304,47 @@ svn_fs_fs__initialize_txn_caches(svn_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

Modified: subversion/trunk/subversion/libsvn_fs_fs/load-index.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/load-index.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/load-index.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/load-index.c Fri Apr 12 21:28:17 
2019
@@ -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"

Modified: subversion/trunk/subversion/libsvn_fs_fs/stats.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/stats.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/stats.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/stats.c Fri Apr 12 21:28:17 2019
@@ -28,7 +28,6 @@
 #include "private/svn_cache.h"
 #include "private/svn_sorts_private.h"
 #include "private/svn_string_private.h"
-#include "private/svn_fs_fs_private.h"
 
 #include "index.h"
 #include "pack.h"

Modified: subversion/trunk/subversion/libsvn_fs_x/fs.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/fs.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/fs.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/fs.c Fri Apr 12 21:28:17 2019
@@ -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_vtabl
   x_logfiles,
   NULL /* parse_id */,
   x_set_svn_fs_open,
-  x_info_dup
+  x_info_dup,
+  NULL /* ioctl */
 };
 
 svn_error_t *

Modified: subversion/trunk/subversion/svnfsfs/dump-index-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svnfsfs/dump-index-cmd.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/svnfsfs/dump-index-cmd.c (original)
+++ subversion/trunk/subversion/svnfsfs/dump-index-cmd.c Fri Apr 12 21:28:17 
2019
@@ -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;
 }

Modified: subversion/trunk/subversion/svnfsfs/load-index-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svnfsfs/load-index-cmd.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/svnfsfs/load-index-cmd.c (original)
+++ subversion/trunk/subversion/svnfsfs/load-index-cmd.c Fri Apr 12 21:28:17 
2019
@@ -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;

Modified: subversion/trunk/subversion/svnfsfs/stats-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svnfsfs/stats-cmd.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/svnfsfs/stats-cmd.c (original)
+++ subversion/trunk/subversion/svnfsfs/stats-cmd.c Fri Apr 12 21:28:17 2019
@@ -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;
 }

Modified: subversion/trunk/subversion/tests/libsvn_fs/fs-test.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_fs/fs-test.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_fs/fs-test.c Fri Apr 12 21:28:17 
2019
@@ -7441,6 +7441,34 @@ test_closest_copy_file_replaced_with_dir
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_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
                        "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(test_unrecognized_ioctl,
+                       "test svn_fs_ioctl with unrecognized code"),
     SVN_TEST_NULL
   };
 

Modified: subversion/trunk/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c?rev=1857435&r1=1857434&r2=1857435&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c 
(original)
+++ subversion/trunk/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c Fri Apr 
12 21:28:17 2019
@@ -199,8 +199,10 @@ get_repo_stats(const svn_test_opts_t *op
   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 *op
   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,8 +346,12 @@ 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_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,
   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,14 +417,21 @@ load_index(const svn_test_opts_t *opts,
   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),
                         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));
 


Reply via email to