You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2012/09/20 22:22:55 UTC

svn commit: r1388195 - in /subversion/branches/10Gb/subversion: include/svn_repos.h libsvn_repos/deprecated.c libsvn_repos/reporter.c

Author: stefan2
Date: Thu Sep 20 20:22:54 2012
New Revision: 1388195

URL: http://svn.apache.org/viewvc?rev=1388195&view=rev
Log:
On the 10Gb branch: attempt zero-copy reporting for files contents
below a given threshold.

Since we push data directly from the membuffer to the network stack,
the respective membuffer segment will remain read-only to all other
requests until the OS accepted all data for that file. 

* subversion/include/svn_repos.h
  (svn_repos_begin_report3): rev API
  (svn_repos_begin_report2): deprecate the old one
  (svn_repos_set_path3,
   svn_repos_link_path3,
   svn_repos_delete_path,
   svn_repos_finish_report,
   svn_repos_abort_report,
   svn_repos_dir_delta2,
   svn_repos_node_t): update docstring references to rev'ed API

* subversion/libsvn_repos/deprecated.c
  (svn_repos_begin_report2): implement in terms of the rev'ed API

* subversion/libsvn_repos/reporter.c
  (report_baton_t): add zero_copy_limit member
  (zero_copy_baton_t): baton for the ...
  (send_zero_copy_delta): svn_fs_process_content_func_t implementation
  (delta_files): if we send deltas against empty, use zero-copy code
  (svn_repos_begin_report3): implement rev'ed API

Modified:
    subversion/branches/10Gb/subversion/include/svn_repos.h
    subversion/branches/10Gb/subversion/libsvn_repos/deprecated.c
    subversion/branches/10Gb/subversion/libsvn_repos/reporter.c

Modified: subversion/branches/10Gb/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/10Gb/subversion/include/svn_repos.h?rev=1388195&r1=1388194&r2=1388195&view=diff
==============================================================================
--- subversion/branches/10Gb/subversion/include/svn_repos.h (original)
+++ subversion/branches/10Gb/subversion/include/svn_repos.h Thu Sep 20 20:22:54 2012
@@ -842,6 +842,13 @@ svn_repos_hooks_setenv(svn_repos_t *repo
  * avoid sending data through @a editor/@a edit_baton which is not
  * authorized for transmission.
  *
+ * @a zero_copy_limit controls up to which size in bytes data blocks may
+ * be sent using the zero-copy code path.  On that path, a number of
+ * in-memory copy operations have been eliminated to maximize throughput.
+ * However, until the whole block has been pushed to the network stack,
+ * other clients may get blocked.  Thus, be careful when using larger
+ * values here.  0 disables the optimization.
+ *
  * All allocation for the context and collected state will occur in
  * @a pool.
  *
@@ -874,7 +881,33 @@ svn_repos_hooks_setenv(svn_repos_t *repo
  * than or equal to the depth of the working copy, then the editor
  * operations will affect only paths at or above @a depth.
  *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_repos_begin_report3(void **report_baton,
+                        svn_revnum_t revnum,
+                        svn_repos_t *repos,
+                        const char *fs_base,
+                        const char *target,
+                        const char *tgt_path,
+                        svn_boolean_t text_deltas,
+                        svn_depth_t depth,
+                        svn_boolean_t ignore_ancestry,
+                        svn_boolean_t send_copyfrom_args,
+                        const svn_delta_editor_t *editor,
+                        void *edit_baton,
+                        svn_repos_authz_func_t authz_read_func,
+                        void *authz_read_baton,
+                        apr_size_t zero_copy_limit,
+                        apr_pool_t *pool);
+
+/**
+ * The same as svn_repos_begin_report3(), but setting the @a zero_copy_limit
+ * to 0.
+ *
  * @since New in 1.5.
+ * 
+ * @deprecated Provided for backward compatibility with the 1.8 API.
  */
 svn_error_t *
 svn_repos_begin_report2(void **report_baton,
@@ -926,7 +959,7 @@ svn_repos_begin_report(void **report_bat
 
 
 /**
- * Given a @a report_baton constructed by svn_repos_begin_report2(),
+ * Given a @a report_baton constructed by svn_repos_begin_report3(),
  * record the presence of @a path, at @a revision with depth @a depth,
  * in the current tree.
  *
@@ -997,7 +1030,7 @@ svn_repos_set_path(void *report_baton,
                    apr_pool_t *pool);
 
 /**
- * Given a @a report_baton constructed by svn_repos_begin_report2(),
+ * Given a @a report_baton constructed by svn_repos_begin_report3(),
  * record the presence of @a path in the current tree, containing the contents
  * of @a link_path at @a revision with depth @a depth.
  *
@@ -1063,7 +1096,7 @@ svn_repos_link_path(void *report_baton,
                     svn_boolean_t start_empty,
                     apr_pool_t *pool);
 
-/** Given a @a report_baton constructed by svn_repos_begin_report2(),
+/** Given a @a report_baton constructed by svn_repos_begin_report3(),
  * record the non-existence of @a path in the current tree.
  *
  * @a path may not be underneath a path on which svn_repos_set_path3()
@@ -1079,7 +1112,7 @@ svn_repos_delete_path(void *report_baton
                       const char *path,
                       apr_pool_t *pool);
 
-/** Given a @a report_baton constructed by svn_repos_begin_report2(),
+/** Given a @a report_baton constructed by svn_repos_begin_report3(),
  * finish the report and drive the editor as specified when the report
  * baton was constructed.
  *
@@ -1096,7 +1129,7 @@ svn_repos_finish_report(void *report_bat
                         apr_pool_t *pool);
 
 
-/** Given a @a report_baton constructed by svn_repos_begin_report2(),
+/** Given a @a report_baton constructed by svn_repos_begin_report3(),
  * abort the report.  This function can be called anytime before
  * svn_repos_finish_report() is called.
  *
@@ -1170,7 +1203,7 @@ svn_repos_abort_report(void *report_bato
  * the total size of the delta.
  *
  * ### svn_repos_dir_delta2 is mostly superseded by the reporter
- * ### functionality (svn_repos_begin_report2 and friends).
+ * ### functionality (svn_repos_begin_report3 and friends).
  * ### svn_repos_dir_delta2 does allow the roots to be transaction
  * ### roots rather than just revision roots, and it has the
  * ### entry_props flag.  Almost all of Subversion's own code uses the
@@ -2316,7 +2349,7 @@ svn_repos_fs_change_txn_props(svn_fs_txn
  * @{
  *
  * As it turns out, the svn_repos_replay2(), svn_repos_dir_delta2() and
- * svn_repos_begin_report2() interfaces can be extremely useful for
+ * svn_repos_begin_report3() interfaces can be extremely useful for
  * examining the repository, or more exactly, changes to the repository.
  * These drivers allows for differences between two trees to be
  * described using an editor.
@@ -2369,7 +2402,7 @@ typedef struct svn_repos_node_t
  * repos's filesystem.
  *
  * The editor can also be driven by svn_repos_dir_delta2() or
- * svn_repos_begin_report2(), but unless you have special needs,
+ * svn_repos_begin_report3(), but unless you have special needs,
  * svn_repos_replay2() is preferred.
  *
  * Invoke svn_repos_node_from_baton() on @a edit_baton to obtain the root

Modified: subversion/branches/10Gb/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/10Gb/subversion/libsvn_repos/deprecated.c?rev=1388195&r1=1388194&r2=1388195&view=diff
==============================================================================
--- subversion/branches/10Gb/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/10Gb/subversion/libsvn_repos/deprecated.c Thu Sep 20 20:22:54 2012
@@ -254,6 +254,41 @@ svn_repos_begin_report(void **report_bat
 }
 
 svn_error_t *
+svn_repos_begin_report2(void **report_baton,
+                        svn_revnum_t revnum,
+                        svn_repos_t *repos,
+                        const char *fs_base,
+                        const char *target,
+                        const char *tgt_path,
+                        svn_boolean_t text_deltas,
+                        svn_depth_t depth,
+                        svn_boolean_t ignore_ancestry,
+                        svn_boolean_t send_copyfrom_args,
+                        const svn_delta_editor_t *editor,
+                        void *edit_baton,
+                        svn_repos_authz_func_t authz_read_func,
+                        void *authz_read_baton,
+                        apr_pool_t *pool)
+{
+  return svn_repos_begin_report3(report_baton,
+                                 revnum,
+                                 repos,
+                                 fs_base,
+                                 target,
+                                 tgt_path,
+                                 text_deltas,
+                                 depth,
+                                 ignore_ancestry,
+                                 send_copyfrom_args,
+                                 editor,
+                                 edit_baton,
+                                 authz_read_func,
+                                 authz_read_baton,
+                                 0,     /* disable zero-copy code path */
+                                 pool);
+}
+
+svn_error_t *
 svn_repos_set_path2(void *baton, const char *path, svn_revnum_t rev,
                     svn_boolean_t start_empty, const char *lock_token,
                     apr_pool_t *pool)

Modified: subversion/branches/10Gb/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/10Gb/subversion/libsvn_repos/reporter.c?rev=1388195&r1=1388194&r2=1388195&view=diff
==============================================================================
--- subversion/branches/10Gb/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/10Gb/subversion/libsvn_repos/reporter.c Thu Sep 20 20:22:54 2012
@@ -102,13 +102,15 @@ typedef struct revision_info_t
    driven by the client as it describes its working copy revisions. */
 typedef struct report_baton_t
 {
-  /* Parameters remembered from svn_repos_begin_report2 */
+  /* Parameters remembered from svn_repos_begin_report3 */
   svn_repos_t *repos;
   const char *fs_base;         /* fspath corresponding to wc anchor */
   const char *s_operand;       /* anchor-relative wc target (may be empty) */
   svn_revnum_t t_rev;          /* Revnum which the edit will bring the wc to */
   const char *t_path;          /* FS path the edit will bring the wc to */
   svn_boolean_t text_deltas;   /* Whether to report text deltas */
+  apr_size_t zero_copy_limit;  /* Max item size that will be sent using
+                                  the zero-copy code path. */
 
   /* If the client requested a specific depth, record it here; if the
      client did not, then this is svn_depth_unknown, and the depth of
@@ -592,6 +594,53 @@ delta_proplists(report_baton_t *b, svn_r
   return SVN_NO_ERROR;
 }
 
+/* Baton type to be passed into send_zero_copy_delta.
+ */
+typedef struct zero_copy_baton_t
+{
+  /* don't process data larger than this limit */
+  apr_size_t zero_copy_limit;
+
+  /* window handler and baton to send the data to */
+  svn_txdelta_window_handler_t dhandler;
+  void *dbaton;
+
+  /* return value: will be set to TRUE, if the data was processed. */
+  svn_boolean_t zero_copy_succeeded;
+} zero_copy_baton_t;
+
+/* Implement svn_fs_process_content_func_t.  If LEN is smaller than the
+ * limit given in *BATON, send the CONTENTS as an delta windows to the
+ * handler given in BATON and set the ZERO_COPY_SUCCEEDED flag in that
+ * BATON.  Otherwise, reset it to FALSE.
+ * Use POOL for temporary allocations.
+ */
+static svn_error_t *
+send_zero_copy_delta(const unsigned char *contents,
+                     apr_size_t len,
+                     void *baton,
+                     apr_pool_t *pool)
+{
+  zero_copy_baton_t *zero_copy_baton = baton;
+
+  /* if the item is too large, the caller must revert to traditional
+     streaming code. */
+  if (len > zero_copy_baton->zero_copy_limit)
+    {
+      zero_copy_baton->zero_copy_succeeded = FALSE;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(svn_txdelta_send_contents(contents, len,
+                                    zero_copy_baton->dhandler,
+                                    zero_copy_baton->dbaton, pool));
+
+  /* all fine now */
+  zero_copy_baton->zero_copy_succeeded = FALSE;
+  return SVN_NO_ERROR;
+}
+
+
 /* Make the appropriate edits on FILE_BATON to change its contents and
    properties from those in S_REV/S_PATH to those in B->t_root/T_PATH,
    possibly using LOCK_TOKEN to determine if the client's lock on the file
@@ -645,6 +694,23 @@ delta_files(report_baton_t *b, void *fil
     {
       if (b->text_deltas)
         {
+          /* if we send deltas against empty streams, we may use our
+             zero-copy code. */
+          if (b->zero_copy_limit > 0 && s_path == NULL)
+            {
+              zero_copy_baton_t baton = {b->zero_copy_limit, dbaton, FALSE};
+              svn_boolean_t called = FALSE;
+              SVN_ERR(svn_fs_try_process_file_content(&called,
+                                                      b->t_root, t_path,
+                                                      send_zero_copy_delta,
+                                                      &baton, pool));
+
+              /* data has been available and small enough,
+                 i.e. been processed? */
+              if (called && baton.zero_copy_succeeded)
+                return SVN_NO_ERROR;
+            }
+
           SVN_ERR(svn_fs_get_file_delta_stream(&dstream, s_root, s_path,
                                                b->t_root, t_path, pool));
           SVN_ERR(svn_txdelta_send_txstream(dstream, dhandler, dbaton, pool));
@@ -1463,7 +1529,7 @@ svn_repos_abort_report(void *baton, apr_
 
 
 svn_error_t *
-svn_repos_begin_report2(void **report_baton,
+svn_repos_begin_report3(void **report_baton,
                         svn_revnum_t revnum,
                         svn_repos_t *repos,
                         const char *fs_base,
@@ -1477,6 +1543,7 @@ svn_repos_begin_report2(void **report_ba
                         void *edit_baton,
                         svn_repos_authz_func_t authz_read_func,
                         void *authz_read_baton,
+                        apr_size_t zero_copy_limit,
                         apr_pool_t *pool)
 {
   report_baton_t *b;
@@ -1495,6 +1562,7 @@ svn_repos_begin_report2(void **report_ba
   b->t_path = switch_path ? svn_fspath__canonicalize(switch_path, pool)
                           : svn_fspath__join(b->fs_base, s_operand, pool);
   b->text_deltas = text_deltas;
+  b->zero_copy_limit = zero_copy_limit;
   b->requested_depth = depth;
   b->ignore_ancestry = ignore_ancestry;
   b->send_copyfrom_args = send_copyfrom_args;