Julian Foad wrote:
[...]
>   * simplify implementation by using the existing 
> svn_fs_fs__dump_index() API with a simple callback

Here's v2, functionally identical, with that simplification.

-- 
- Julian
Add an API and CLI to report a revision's size on disk.

### So far, this patch only works with FSFS logical addressing mode.

It reports the total size in bytes of the representation on disk of
a revision, excluding its indexes.

    $ svnfsfs rev-size /path/to/repo -r1
    1238 bytes in revision 1


* subversion/include/private/svn_fs_fs_private.h,
  subversion/libsvn_fs_fs/stats.c
  (svn_fs_fs__get_rev_size,
   rev_size_index_entry_cb,
   rev_size_baton_t): New.

* subversion/svnfsfs/svnfsfs.h,
  subversion/svnfsfs/stats-cmd.c
  (subcommand__rev_size): New.

* subversion/svnfsfs/svnfsfs.c
  (cmd_table): Add and document the 'rev-size' command.
--This line, and those below, will be ignored--

Index: subversion/include/private/svn_fs_fs_private.h
===================================================================
--- subversion/include/private/svn_fs_fs_private.h	(revision 1855386)
+++ subversion/include/private/svn_fs_fs_private.h	(working copy)
@@ -268,12 +268,21 @@ svn_fs_fs__get_stats(svn_fs_fs__stats_t
                      void *progress_baton,
                      svn_cancel_func_t cancel_func,
                      void *cancel_baton,
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool);
 
+/* Set *REV_SIZE to the total size of objects belonging to revision REVISION
+ * in FS.
+ */
+svn_error_t *
+svn_fs_fs__get_rev_size(apr_off_t *rev_size,
+                        svn_fs_t *fs,
+                        svn_revnum_t revision,
+                        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.
  *
  * The parts are: node_id, copy_id and txn_id for in-txn IDs as well as
  * node_id, copy_id and rev_item for in-revision IDs.  This struct is the
Index: subversion/libsvn_fs_fs/stats.c
===================================================================
--- subversion/libsvn_fs_fs/stats.c	(revision 1855386)
+++ subversion/libsvn_fs_fs/stats.c	(working copy)
@@ -1394,6 +1394,43 @@ svn_fs_fs__get_stats(svn_fs_fs__stats_t
                        scratch_pool));
   SVN_ERR(read_revisions(query, scratch_pool, scratch_pool));
   aggregate_stats(query->revisions, *stats);
 
   return SVN_NO_ERROR;
 }
+
+struct rev_size_baton_t {
+  svn_revnum_t revision;
+  apr_off_t rev_size;
+};
+
+/* Implements svn_fs_fs__dump_index_func_t, summing object sizes for
+ * revision BATON->revision into BATON->rev_size.
+ */
+static svn_error_t *
+rev_size_index_entry_cb(const svn_fs_fs__p2l_entry_t *entry,
+                        void *baton,
+                        apr_pool_t *scratch_pool)
+{
+  struct rev_size_baton_t *b = baton;
+
+  if (entry->item.revision == b->revision)
+    b->rev_size += entry->size;
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__get_rev_size(apr_off_t *rev_size,
+                        svn_fs_t *fs,
+                        svn_revnum_t revision,
+                        apr_pool_t *scratch_pool)
+{
+  struct rev_size_baton_t b;
+
+  b.revision = revision;
+  b.rev_size = 0;
+  SVN_ERR(svn_fs_fs__dump_index(fs, revision,
+                                rev_size_index_entry_cb, &b,
+                                NULL, NULL, scratch_pool));
+  *rev_size = b.rev_size;
+  return SVN_NO_ERROR;
+}
Index: subversion/svnfsfs/stats-cmd.c
===================================================================
--- subversion/svnfsfs/stats-cmd.c	(revision 1855386)
+++ subversion/svnfsfs/stats-cmd.c	(working copy)
@@ -509,6 +509,30 @@ subcommand__stats(apr_getopt_t *os, void
                                check_cancel, NULL, pool, pool));
 
   print_stats(stats, pool);
 
   return SVN_NO_ERROR;
 }
+
+/* This implements `svn_opt_subcommand_t'. */
+svn_error_t *
+subcommand__rev_size(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+  svnfsfs__opt_state *opt_state = baton;
+  svn_revnum_t revision;
+  apr_off_t rev_size;
+  svn_fs_t *fs;
+
+  if (opt_state->start_revision.kind != svn_opt_revision_number
+      || opt_state->end_revision.kind != svn_opt_revision_unspecified)
+    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                            _("Invalid revision specifier"));
+  revision = opt_state->start_revision.value.number;
+
+  SVN_ERR(open_fs(&fs, opt_state->repository_path, pool));
+  SVN_ERR(svn_fs_fs__get_rev_size(&rev_size, fs, revision, pool));
+
+  printf("%"APR_OFF_T_FMT" bytes in revision %ld\n",
+         rev_size, revision);
+
+  return SVN_NO_ERROR;
+}
Index: subversion/svnfsfs/svnfsfs.c
===================================================================
--- subversion/svnfsfs/svnfsfs.c	(revision 1855386)
+++ subversion/svnfsfs/svnfsfs.c	(working copy)
@@ -166,12 +166,20 @@ static const svn_opt_subcommand_desc3_t
     "usage: svnfsfs stats REPOS_PATH\n"
     "\n"), N_(
     "Write object size statistics to console.\n"
    )},
    {'M'} },
 
+  {"rev-size", subcommand__rev_size, {0}, {N_(
+    "usage: svnfsfs rev-size REPOS_PATH -r REVISION\n"
+    "\n"), N_(
+    "Write to console the total size in bytes of the representation on disk of\n"
+    "revision REVISION, excluding its indexes.\n"
+   )},
+   {'r', 'M'} },
+
   { NULL, NULL, {0}, {NULL}, {0} }
 };
 
 
 svn_error_t *
 open_fs(svn_fs_t **fs,
Index: subversion/svnfsfs/svnfsfs.h
===================================================================
--- subversion/svnfsfs/svnfsfs.h	(revision 1855386)
+++ subversion/svnfsfs/svnfsfs.h	(working copy)
@@ -49,13 +49,14 @@ typedef struct svnfsfs__opt_state
 
 /* Declare all the command procedures */
 svn_opt_subcommand_t
   subcommand__help,
   subcommand__dump_index,
   subcommand__load_index,
-  subcommand__stats;
+  subcommand__stats,
+  subcommand__rev_size;
 
 
 /* Check that the filesystem at PATH is an FSFS repository and then open it.
  * Return the filesystem in *FS, allocated in POOL. */
 svn_error_t *
 open_fs(svn_fs_t **fs,

Reply via email to