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;