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/25 16:06:34 UTC
svn commit: r1389867 - in /subversion/branches/10Gb:
subversion/libsvn_ra_svn/editorp.c subversion/libsvn_ra_svn/marshal.c
subversion/libsvn_ra_svn/ra_svn.h
tools/client-side/svn-bench/null-export-cmd.c
Author: stefan2
Date: Tue Sep 25 14:06:34 2012
New Revision: 1389867
URL: http://svn.apache.org/viewvc?rev=1389867&view=rev
Log:
On the 10Gb branch: minimize client-side processing overhead for
null-export in quiet mode. For ra_svn, skip through the command
stream without further processing as to not become the bottleneck
when running against a fast server. The other RA modules don't
have that problem, yet.
* subversion/libsvn_ra_svn/ra_svn.h
(svn_ra_svn__read_command_only): declare new private API
* subversion/libsvn_ra_svn/marshal.c
(readbuf_skip,
read_command_only): new skip-command processing utilities
(svn_ra_svn__read_command_only): implement new private API
* subversion/libsvn_ra_svn/editorp.c
(svn_ra_svn_drive_editor2): allow for EDITOR to be NULL;
skip command processing if there is no editor
* tools/client-side/svn-bench/null-export-cmd.c
(bench_null_export): add QUIET parameter; don't use an
editor for ra_svn in that mode
(svn_cl__null_export): update
Modified:
subversion/branches/10Gb/subversion/libsvn_ra_svn/editorp.c
subversion/branches/10Gb/subversion/libsvn_ra_svn/marshal.c
subversion/branches/10Gb/subversion/libsvn_ra_svn/ra_svn.h
subversion/branches/10Gb/tools/client-side/svn-bench/null-export-cmd.c
Modified: subversion/branches/10Gb/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/10Gb/subversion/libsvn_ra_svn/editorp.c?rev=1389867&r1=1389866&r2=1389867&view=diff
==============================================================================
--- subversion/branches/10Gb/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/10Gb/subversion/libsvn_ra_svn/editorp.c Tue Sep 25 14:06:34 2012
@@ -929,30 +929,47 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
while (!state.done)
{
svn_pool_clear(subpool);
- SVN_ERR(svn_ra_svn_read_tuple(conn, subpool, "wl", &cmd, ¶ms));
- for (i = 0; ra_svn_edit_cmds[i].cmd; i++)
+ if (editor)
{
- if (strcmp(cmd, ra_svn_edit_cmds[i].cmd) == 0)
- break;
- }
- if (ra_svn_edit_cmds[i].cmd)
- err = (*ra_svn_edit_cmds[i].handler)(conn, subpool, params, &state);
- else if (strcmp(cmd, "failure") == 0)
- {
- /* While not really an editor command this can occur when
- reporter->finish_report() fails before the first editor command */
- if (aborted)
- *aborted = TRUE;
- err = svn_ra_svn__handle_failure_status(params, pool);
- return svn_error_compose_create(
- err,
- editor->abort_edit(edit_baton, subpool));
+ SVN_ERR(svn_ra_svn_read_tuple(conn, subpool, "wl", &cmd, ¶ms));
+ for (i = 0; ra_svn_edit_cmds[i].cmd; i++)
+ if (strcmp(cmd, ra_svn_edit_cmds[i].cmd) == 0)
+ break;
+
+ if (ra_svn_edit_cmds[i].cmd)
+ err = (*ra_svn_edit_cmds[i].handler)(conn, subpool, params, &state);
+ else if (strcmp(cmd, "failure") == 0)
+ {
+ /* While not really an editor command this can occur when
+ reporter->finish_report() fails before the first editor
+ command */
+ if (aborted)
+ *aborted = TRUE;
+ err = svn_ra_svn__handle_failure_status(params, pool);
+ return svn_error_compose_create(
+ err,
+ editor->abort_edit(edit_baton, subpool));
+ }
+ else
+ {
+ err = svn_error_createf(SVN_ERR_RA_SVN_UNKNOWN_CMD, NULL,
+ _("Unknown command '%s'"), cmd);
+ err = svn_error_create(SVN_ERR_RA_SVN_CMD_ERR, err, NULL);
+ }
}
else
{
- err = svn_error_createf(SVN_ERR_RA_SVN_UNKNOWN_CMD, NULL,
- _("Unknown command '%s'"), cmd);
- err = svn_error_create(SVN_ERR_RA_SVN_CMD_ERR, err, NULL);
+ const char* command = NULL;
+ SVN_ERR(svn_ra_svn__read_command_only(conn, subpool, &command));
+ if (strcmp(command, "close-edit") == 0)
+ {
+ state.done = TRUE;
+ if (aborted)
+ *aborted = FALSE;
+ err = svn_ra_svn_write_cmd_response(conn, pool, "");
+ }
+ else
+ err = NULL;
}
if (err && err->apr_err == SVN_ERR_RA_SVN_CMD_ERR)
@@ -962,7 +979,8 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
if (!state.done)
{
/* Abort the edit and use non-blocking I/O to write the error. */
- svn_error_clear(editor->abort_edit(edit_baton, subpool));
+ if (editor)
+ svn_error_clear(editor->abort_edit(edit_baton, subpool));
svn_ra_svn__set_block_handler(conn, blocked_write, &state);
}
write_err = svn_ra_svn_write_cmd_failure(
Modified: subversion/branches/10Gb/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/10Gb/subversion/libsvn_ra_svn/marshal.c?rev=1389867&r1=1389866&r2=1389867&view=diff
==============================================================================
--- subversion/branches/10Gb/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/10Gb/subversion/libsvn_ra_svn/marshal.c Tue Sep 25 14:06:34 2012
@@ -352,6 +352,33 @@ static svn_error_t *readbuf_input(svn_ra
return SVN_NO_ERROR;
}
+/* Treat the next LEN input bytes from CONN as "read" */
+static svn_error_t *readbuf_skip(svn_ra_svn_conn_t *conn, apr_size_t len)
+{
+ apr_ssize_t buflen, copylen;
+
+ do
+ {
+ buflen = conn->read_end - conn->read_ptr;
+ copylen = (buflen < len) ? buflen : len;
+ conn->read_ptr += copylen;
+ len -= copylen;
+ if (len == 0)
+ break;
+
+ buflen = sizeof(conn->read_buf);
+ SVN_ERR(svn_ra_svn__stream_read(conn->stream, conn->read_buf, &buflen));
+ if (buflen == 0)
+ return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL, NULL);
+
+ conn->read_end = conn->read_buf + buflen;
+ conn->read_ptr = conn->read_buf;
+ }
+ while (len > 0);
+
+ return SVN_NO_ERROR;
+}
+
/* Read data from the socket into the read buffer, which must be empty. */
static svn_error_t *readbuf_fill(svn_ra_svn_conn_t *conn, apr_pool_t *pool)
{
@@ -1070,6 +1097,95 @@ static svn_error_t *read_item(svn_ra_svn
return SVN_NO_ERROR;
}
+/* Given the first non-whitespace character FIRST_CHAR, read the first
+ * command (word) encountered in CONN into *ITEM. If ITEM is NULL, skip
+ * to the end of the current list. Use POOL for allocations. */
+static svn_error_t *
+read_command_only(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+ const char **item, char first_char)
+{
+ char c = first_char;
+
+ /* Determine the item type and read it in. Make sure that c is the
+ * first character at the end of the item so we can test to make
+ * sure it's whitespace. */
+ if (svn_ctype_isdigit(c))
+ {
+ /* It's a number or a string. Read the number part, either way. */
+ apr_uint64_t val, prev_val=0;
+ val = c - '0';
+ while (1)
+ {
+ prev_val = val;
+ SVN_ERR(readbuf_getchar(conn, pool, &c));
+ if (!svn_ctype_isdigit(c))
+ break;
+ val = val * 10 + (c - '0');
+ if (prev_val >= (APR_UINT64_MAX / 10)) /* > maximum value? */
+ return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ _("Number is larger than maximum"));
+ }
+ if (c == ':')
+ {
+ /* It's a string. */
+ SVN_ERR(readbuf_skip(conn, val));
+ SVN_ERR(readbuf_getchar(conn, pool, &c));
+ }
+ }
+ else if (svn_ctype_isalpha(c))
+ {
+ /* It's a word. */
+ if (item)
+ {
+ /* This is the word we want to read */
+
+ char *buf = apr_palloc(pool, 32);
+ apr_size_t len = 1;
+ buf[0] = c;
+
+ while (1)
+ {
+ SVN_ERR(readbuf_getchar(conn, pool, &c));
+ if (!svn_ctype_isalnum(c) && c != '-')
+ break;
+ buf[len] = c;
+ if (++len == 32)
+ return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ _("Word too long"));
+ }
+ buf[len] = 0;
+ *item = buf;
+ }
+ else
+ {
+ /* we don't need the actual word, just skip it */
+ do
+ {
+ SVN_ERR(readbuf_getchar(conn, pool, &c));
+ }
+ while (svn_ctype_isalnum(c) || c == '-');
+ }
+ }
+ else if (c == '(')
+ {
+ /* Read in the list items. */
+ while (1)
+ {
+ SVN_ERR(readbuf_getchar_skip_whitespace(conn, pool, &c));
+ if (c == ')')
+ break;
+
+ if (item && *item == NULL)
+ SVN_ERR(read_command_only(conn, pool, item, c));
+ else
+ SVN_ERR(read_command_only(conn, pool, NULL, c));
+ }
+ SVN_ERR(readbuf_getchar(conn, pool, &c));
+ }
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *svn_ra_svn_read_item(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
svn_ra_svn_item_t **item)
{
@@ -1218,6 +1334,18 @@ svn_error_t *svn_ra_svn_read_tuple(svn_r
return err;
}
+svn_error_t *svn_ra_svn__read_command_only(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const char **command)
+{
+ char c;
+ SVN_ERR(readbuf_getchar_skip_whitespace(conn, pool, &c));
+
+ *command = NULL;
+ return read_command_only(conn, pool, command, c);
+}
+
+
svn_error_t *svn_ra_svn_parse_proplist(const apr_array_header_t *list,
apr_pool_t *pool,
apr_hash_t **props)
Modified: subversion/branches/10Gb/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/10Gb/subversion/libsvn_ra_svn/ra_svn.h?rev=1389867&r1=1389866&r2=1389867&view=diff
==============================================================================
--- subversion/branches/10Gb/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/10Gb/subversion/libsvn_ra_svn/ra_svn.h Tue Sep 25 14:06:34 2012
@@ -189,6 +189,13 @@ svn_error_t *svn_ra_svn__stream_write(sv
svn_error_t *svn_ra_svn__stream_read(svn_ra_svn__stream_t *stream,
char *data, apr_size_t *len);
+/* Read the command word from CONN, return it in *COMMAND and skip to the
+ * end of the command. Allocate data in POOL.
+ */
+svn_error_t *svn_ra_svn__read_command_only(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const char **command);
+
/* Set the timeout for operations on STREAM to INTERVAL. */
void svn_ra_svn__stream_timeout(svn_ra_svn__stream_t *stream,
apr_interval_time_t interval);
Modified: subversion/branches/10Gb/tools/client-side/svn-bench/null-export-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/10Gb/tools/client-side/svn-bench/null-export-cmd.c?rev=1389867&r1=1389866&r2=1389867&view=diff
==============================================================================
--- subversion/branches/10Gb/tools/client-side/svn-bench/null-export-cmd.c (original)
+++ subversion/branches/10Gb/tools/client-side/svn-bench/null-export-cmd.c Tue Sep 25 14:06:34 2012
@@ -168,7 +168,7 @@ close_file(void *file_baton,
/*** Public Interfaces ***/
-svn_error_t *
+static svn_error_t *
bench_null_export(svn_revnum_t *result_rev,
const char *from_path_or_url,
svn_opt_revision_t *peg_revision,
@@ -176,6 +176,7 @@ bench_null_export(svn_revnum_t *result_r
svn_depth_t depth,
void *baton,
svn_client_ctx_t *ctx,
+ svn_boolean_t quiet,
apr_pool_t *pool)
{
svn_revnum_t edit_revision = SVN_INVALID_REVNUM;
@@ -223,7 +224,7 @@ bench_null_export(svn_revnum_t *result_r
else if (kind == svn_node_dir)
{
void *edit_baton = NULL;
- const svn_delta_editor_t *export_editor;
+ const svn_delta_editor_t *export_editor = NULL;
const svn_ra_reporter3_t *reporter;
void *report_baton;
@@ -238,8 +239,8 @@ bench_null_export(svn_revnum_t *result_r
editor->change_file_prop = change_file_prop;
editor->change_dir_prop = change_dir_prop;
- export_editor = editor;
- if (ctx->cancel_func)
+ /* for ra_svn, we don't need an editior in quiet mode */
+ if (!quiet || strncmp(loc->repos_root_url, "svn:", 4))
SVN_ERR(svn_delta_get_cancellation_editor(ctx->cancel_func,
ctx->cancel_baton,
editor,
@@ -339,7 +340,7 @@ svn_cl__null_export(apr_getopt_t *os,
&(opt_state->start_revision),
opt_state->depth,
&eb,
- ctx, pool);
+ ctx, opt_state->quiet, pool);
if (!opt_state->quiet)
SVN_ERR(svn_cmdline_printf(pool,