You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/11/30 11:24:23 UTC
svn commit: r1717223 [28/50] - in /subversion/branches/ra-git: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/
contrib/hook-scripts/ notes/ notes/api-errata/1.9/ notes/move-tracking/
subversion/ subversion/bindings/ctypes-python/...
Modified: subversion/branches/ra-git/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_svn/editorp.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_svn/editorp.c Mon Nov 30 10:24:16 2015
@@ -39,8 +39,11 @@
#include "svn_pools.h"
#include "svn_private_config.h"
+#include "private/svn_atomic.h"
#include "private/svn_fspath.h"
#include "private/svn_editor.h"
+#include "private/svn_string_private.h"
+#include "private/svn_subr_private.h"
#include "ra_svn.h"
@@ -57,7 +60,7 @@ typedef struct ra_svn_edit_baton_t {
svn_ra_svn_conn_t *conn;
svn_ra_svn_edit_callback callback; /* Called on successful completion. */
void *callback_baton;
- int next_token;
+ apr_uint64_t next_token;
svn_boolean_t got_status;
} ra_svn_edit_baton_t;
@@ -66,13 +69,19 @@ typedef struct ra_svn_baton_t {
svn_ra_svn_conn_t *conn;
apr_pool_t *pool;
ra_svn_edit_baton_t *eb;
- const char *token;
+ svn_string_t *token;
} ra_svn_baton_t;
+/* Forward declaration. */
+typedef struct ra_svn_token_entry_t ra_svn_token_entry_t;
+
typedef struct ra_svn_driver_state_t {
const svn_delta_editor_t *editor;
void *edit_baton;
apr_hash_t *tokens;
+
+ /* Entry for the last token seen. May be NULL. */
+ ra_svn_token_entry_t *last_token;
svn_boolean_t *aborted;
svn_boolean_t done;
apr_pool_t *pool;
@@ -90,26 +99,33 @@ typedef struct ra_svn_driver_state_t {
field in this structure is vestigial for files, and we use it for a
different purpose instead: at apply-textdelta time, we set it to a
subpool of the file pool, which is destroyed in textdelta-end. */
-typedef struct ra_svn_token_entry_t {
+struct ra_svn_token_entry_t {
svn_string_t *token;
void *baton;
svn_boolean_t is_file;
svn_stream_t *dstream; /* svndiff stream for apply_textdelta */
apr_pool_t *pool;
-} ra_svn_token_entry_t;
+};
/* --- CONSUMING AN EDITOR BY PASSING EDIT OPERATIONS OVER THE NET --- */
-static const char *make_token(char type, ra_svn_edit_baton_t *eb,
- apr_pool_t *pool)
-{
- return apr_psprintf(pool, "%c%d", type, eb->next_token++);
+static svn_string_t *
+make_token(char type,
+ ra_svn_edit_baton_t *eb,
+ apr_pool_t *pool)
+{
+ apr_size_t len;
+ char buffer[1 + SVN_INT64_BUFFER_SIZE];
+ buffer[0] = type;
+ len = 1 + svn__ui64toa(&buffer[1], eb->next_token++);
+
+ return svn_string_ncreate(buffer, len, pool);
}
static ra_svn_baton_t *ra_svn_make_baton(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
ra_svn_edit_baton_t *eb,
- const char *token)
+ svn_string_t *token)
{
ra_svn_baton_t *b;
@@ -171,7 +187,7 @@ static svn_error_t *ra_svn_open_root(voi
apr_pool_t *pool, void **root_baton)
{
ra_svn_edit_baton_t *eb = edit_baton;
- const char *token = make_token('d', eb, pool);
+ svn_string_t *token = make_token('d', eb, pool);
SVN_ERR(check_for_error(eb, pool));
SVN_ERR(svn_ra_svn__write_cmd_open_root(eb->conn, pool, rev, token));
@@ -196,7 +212,7 @@ static svn_error_t *ra_svn_add_dir(const
apr_pool_t *pool, void **child_baton)
{
ra_svn_baton_t *b = parent_baton;
- const char *token = make_token('d', b->eb, pool);
+ svn_string_t *token = make_token('d', b->eb, pool);
SVN_ERR_ASSERT((copy_path && SVN_IS_VALID_REVNUM(copy_rev))
|| (!copy_path && !SVN_IS_VALID_REVNUM(copy_rev)));
@@ -212,7 +228,7 @@ static svn_error_t *ra_svn_open_dir(cons
void **child_baton)
{
ra_svn_baton_t *b = parent_baton;
- const char *token = make_token('d', b->eb, pool);
+ svn_string_t *token = make_token('d', b->eb, pool);
SVN_ERR(check_for_error(b->eb, pool));
SVN_ERR(svn_ra_svn__write_cmd_open_dir(b->conn, pool, path, b->token,
@@ -265,7 +281,7 @@ static svn_error_t *ra_svn_add_file(cons
void **file_baton)
{
ra_svn_baton_t *b = parent_baton;
- const char *token = make_token('c', b->eb, pool);
+ svn_string_t *token = make_token('c', b->eb, pool);
SVN_ERR_ASSERT((copy_path && SVN_IS_VALID_REVNUM(copy_rev))
|| (!copy_path && !SVN_IS_VALID_REVNUM(copy_rev)));
@@ -283,7 +299,7 @@ static svn_error_t *ra_svn_open_file(con
void **file_baton)
{
ra_svn_baton_t *b = parent_baton;
- const char *token = make_token('c', b->eb, pool);
+ svn_string_t *token = make_token('c', b->eb, pool);
SVN_ERR(check_for_error(b->eb, b->pool));
SVN_ERR(svn_ra_svn__write_cmd_open_file(b->conn, pool, path, b->token,
@@ -480,6 +496,7 @@ static ra_svn_token_entry_t *store_token
entry->pool = pool;
apr_hash_set(ds->tokens, entry->token->data, entry->token->len, entry);
+ ds->last_token = entry;
return entry;
}
@@ -489,36 +506,59 @@ static svn_error_t *lookup_token(ra_svn_
svn_boolean_t is_file,
ra_svn_token_entry_t **entry)
{
- *entry = apr_hash_get(ds->tokens, token->data, token->len);
+ if (ds->last_token && svn_string_compare(ds->last_token->token, token))
+ {
+ *entry = ds->last_token;
+ }
+ else
+ {
+ *entry = apr_hash_get(ds->tokens, token->data, token->len);
+ ds->last_token = *entry;
+ }
+
if (!*entry || (*entry)->is_file != is_file)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
_("Invalid file or dir token during edit"));
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_target_rev(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+/* Remove a TOKEN entry from DS. */
+static void remove_token(ra_svn_driver_state_t *ds,
+ svn_string_t *token)
+{
+ apr_hash_set(ds->tokens, token->data, token->len, NULL);
+
+ /* Reset this unconditionally. In most cases, LAST_TOKEN->TOKEN will
+ match TOKEN anyway and if it doesn't, lookup_token() will suffer only
+ a minor performance hit. */
+ ds->last_token = NULL;
+}
+
+static svn_error_t *
+ra_svn_handle_target_rev(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
svn_revnum_t rev;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "r", &rev));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "r", &rev));
SVN_CMD_ERR(ds->editor->set_target_revision(ds->edit_baton, rev, pool));
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_open_root(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_open_root(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
svn_revnum_t rev;
apr_pool_t *subpool;
svn_string_t *token;
void *root_baton;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)s", &rev, &token));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)s", &rev, &token));
subpool = svn_pool_create(ds->pool);
SVN_CMD_ERR(ds->editor->open_root(ds->edit_baton, rev, subpool,
&root_baton));
@@ -526,17 +566,18 @@ static svn_error_t *ra_svn_handle_open_r
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_delete_entry(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_delete_entry(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
const char *path;
svn_string_t *token;
svn_revnum_t rev;
ra_svn_token_entry_t *entry;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)s",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)s",
&path, &rev, &token));
SVN_ERR(lookup_token(ds, token, FALSE, &entry));
path = svn_relpath_canonicalize(path, pool);
@@ -544,10 +585,11 @@ static svn_error_t *ra_svn_handle_delete
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_add_dir(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_add_dir(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
const char *path, *copy_path;
svn_string_t *token, *child_token;
@@ -556,7 +598,7 @@ static svn_error_t *ra_svn_handle_add_di
apr_pool_t *subpool;
void *child_baton;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?cr)", &path, &token,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?cr)", &path, &token,
&child_token, ©_path, ©_rev));
SVN_ERR(lookup_token(ds, token, FALSE, &entry));
subpool = svn_pool_create(entry->pool);
@@ -578,10 +620,11 @@ static svn_error_t *ra_svn_handle_add_di
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_open_dir(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_open_dir(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
const char *path;
svn_string_t *token, *child_token;
@@ -590,7 +633,7 @@ static svn_error_t *ra_svn_handle_open_d
apr_pool_t *subpool;
void *child_baton;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?r)", &path, &token,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?r)", &path, &token,
&child_token, &rev));
SVN_ERR(lookup_token(ds, token, FALSE, &entry));
subpool = svn_pool_create(entry->pool);
@@ -601,17 +644,18 @@ static svn_error_t *ra_svn_handle_open_d
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_change_dir_prop(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_change_dir_prop(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
svn_string_t *token;
const char *name;
svn_string_t *value;
ra_svn_token_entry_t *entry;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "sc(?s)", &token, &name,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "sc(?s)", &token, &name,
&value));
SVN_ERR(lookup_token(ds, token, FALSE, &entry));
SVN_CMD_ERR(ds->editor->change_dir_prop(entry->baton, name, value,
@@ -619,36 +663,38 @@ static svn_error_t *ra_svn_handle_change
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_close_dir(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_close_dir(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
svn_string_t *token;
ra_svn_token_entry_t *entry;
/* Parse and look up the directory token. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s", &token));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "s", &token));
SVN_ERR(lookup_token(ds, token, FALSE, &entry));
/* Close the directory and destroy the baton. */
SVN_CMD_ERR(ds->editor->close_directory(entry->baton, pool));
- apr_hash_set(ds->tokens, token->data, token->len, NULL);
+ remove_token(ds, token);
svn_pool_destroy(entry->pool);
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_absent_dir(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_absent_dir(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
const char *path;
svn_string_t *token;
ra_svn_token_entry_t *entry;
/* Parse parameters and look up the directory token. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &path, &token));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "cs", &path, &token));
SVN_ERR(lookup_token(ds, token, FALSE, &entry));
/* Call the editor. */
@@ -656,17 +702,18 @@ static svn_error_t *ra_svn_handle_absent
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_add_file(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_add_file(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
const char *path, *copy_path;
svn_string_t *token, *file_token;
svn_revnum_t copy_rev;
ra_svn_token_entry_t *entry, *file_entry;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?cr)", &path, &token,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?cr)", &path, &token,
&file_token, ©_path, ©_rev));
SVN_ERR(lookup_token(ds, token, FALSE, &entry));
ds->file_refs++;
@@ -691,17 +738,18 @@ static svn_error_t *ra_svn_handle_add_fi
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_open_file(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_open_file(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
const char *path;
svn_string_t *token, *file_token;
svn_revnum_t rev;
ra_svn_token_entry_t *entry, *file_entry;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?r)", &path, &token,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?r)", &path, &token,
&file_token, &rev));
SVN_ERR(lookup_token(ds, token, FALSE, &entry));
ds->file_refs++;
@@ -716,10 +764,11 @@ static svn_error_t *ra_svn_handle_open_f
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_apply_textdelta(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_apply_textdelta(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
svn_string_t *token;
ra_svn_token_entry_t *entry;
@@ -728,7 +777,7 @@ static svn_error_t *ra_svn_handle_apply_
char *base_checksum;
/* Parse arguments and look up the token. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s(?c)",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "s(?c)",
&token, &base_checksum));
SVN_ERR(lookup_token(ds, token, TRUE, &entry));
if (entry->dstream)
@@ -741,17 +790,18 @@ static svn_error_t *ra_svn_handle_apply_
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_textdelta_chunk(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_textdelta_chunk(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
svn_string_t *token;
ra_svn_token_entry_t *entry;
svn_string_t *str;
/* Parse arguments and look up the token. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ss", &token, &str));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "ss", &token, &str));
SVN_ERR(lookup_token(ds, token, TRUE, &entry));
if (!entry->dstream)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
@@ -760,16 +810,17 @@ static svn_error_t *ra_svn_handle_textde
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_textdelta_end(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_textdelta_end(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
svn_string_t *token;
ra_svn_token_entry_t *entry;
/* Parse arguments and look up the token. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s", &token));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "s", &token));
SVN_ERR(lookup_token(ds, token, TRUE, &entry));
if (!entry->dstream)
return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
@@ -780,55 +831,58 @@ static svn_error_t *ra_svn_handle_textde
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_change_file_prop(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_change_file_prop(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
const char *name;
svn_string_t *token, *value;
ra_svn_token_entry_t *entry;
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "sc(?s)", &token, &name,
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "sc(?s)", &token, &name,
&value));
SVN_ERR(lookup_token(ds, token, TRUE, &entry));
SVN_CMD_ERR(ds->editor->change_file_prop(entry->baton, name, value, pool));
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_close_file(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_close_file(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
svn_string_t *token;
ra_svn_token_entry_t *entry;
const char *text_checksum;
/* Parse arguments and look up the file token. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s(?c)",
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "s(?c)",
&token, &text_checksum));
SVN_ERR(lookup_token(ds, token, TRUE, &entry));
/* Close the file and destroy the baton. */
SVN_CMD_ERR(ds->editor->close_file(entry->baton, text_checksum, pool));
- apr_hash_set(ds->tokens, token->data, token->len, NULL);
+ remove_token(ds, token);
if (--ds->file_refs == 0)
svn_pool_clear(ds->file_pool);
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_absent_file(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_absent_file(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
const char *path;
svn_string_t *token;
ra_svn_token_entry_t *entry;
/* Parse parameters and look up the parent directory token. */
- SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &path, &token));
+ SVN_ERR(svn_ra_svn__parse_tuple(params, "cs", &path, &token));
SVN_ERR(lookup_token(ds, token, FALSE, &entry));
/* Call the editor. */
@@ -836,22 +890,32 @@ static svn_error_t *ra_svn_handle_absent
return SVN_NO_ERROR;
}
-static svn_error_t *ra_svn_handle_close_edit(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_close_edit(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
SVN_CMD_ERR(ds->editor->close_edit(ds->edit_baton, pool));
ds->done = TRUE;
+#ifdef SVN_DEBUG
+ /* Before enabling this in non-maintainer mode:
+ * Note that this code is used on both client *and* server */
+ if (apr_hash_count(ds->tokens) != 0)
+ return svn_error_create(
+ SVN_ERR_FS_INCORRECT_EDITOR_COMPLETION, NULL,
+ _("Closing editor with directories or files open"));
+#endif
if (ds->aborted)
*ds->aborted = FALSE;
return svn_ra_svn__write_cmd_response(conn, pool, "");
}
-static svn_error_t *ra_svn_handle_abort_edit(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_abort_edit(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
ds->done = TRUE;
if (ds->aborted)
@@ -860,10 +924,11 @@ static svn_error_t *ra_svn_handle_abort_
return svn_ra_svn__write_cmd_response(conn, pool, "");
}
-static svn_error_t *ra_svn_handle_finish_replay(svn_ra_svn_conn_t *conn,
- apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds)
+static svn_error_t *
+ra_svn_handle_finish_replay(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds)
{
if (!ds->for_replay)
return svn_error_createf
@@ -875,11 +940,15 @@ static svn_error_t *ra_svn_handle_finish
return SVN_NO_ERROR;
}
+/* Common function signature for all editor command handlers. */
+typedef svn_error_t *(*cmd_handler_t)(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_ra_svn__list_t *params,
+ ra_svn_driver_state_t *ds);
+
static const struct {
const char *cmd;
- svn_error_t *(*handler)(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
- const apr_array_header_t *params,
- ra_svn_driver_state_t *ds);
+ cmd_handler_t handler;
} ra_svn_edit_cmds[] = {
{ "change-file-prop", ra_svn_handle_change_file_prop },
{ "open-file", ra_svn_handle_open_file },
@@ -903,12 +972,98 @@ static const struct {
{ NULL }
};
+/* All editor commands are kept in a collision-free hash table. */
+
+/* Hash table entry.
+ It is similar to ra_svn_edit_cmds but uses our SVN string type. */
+typedef struct cmd_t {
+ svn_string_t cmd;
+ cmd_handler_t handler;
+} cmd_t;
+
+/* The actual hash table. It will be filled once before first usage.
+
+ If you add more commands, you may have to tweak the table size to
+ eliminate collisions. Alternatively, you may modify the hash function.
+
+ Be sure to initialize all elements with 0 as the has conflict detection
+ will rely on it (see init_cmd_hash).
+ */
+#define CMD_HASH_SIZE 67
+static cmd_t cmd_hash[CMD_HASH_SIZE] = { { { NULL } } };
+
+/* Init flag that controls CMD_HASH's atomic initialization. */
+static volatile svn_atomic_t cmd_hash_initialized = FALSE;
+
+/* Super-fast hash function that works very well with the structure of our
+ command words. It produces no conflicts for them.
+
+ Return the index within CMD_HASH that a command NAME of LEN chars would
+ be found. LEN > 0.
+ */
+static apr_size_t
+cmd_hash_func(const char *name,
+ apr_size_t len)
+{
+ apr_size_t value = (apr_byte_t)(name[0] - 'a') % 8
+ + 1 * (apr_byte_t)(name[len - 1] - 'a') % 8
+ + 10 * (len - 7);
+ return value % CMD_HASH_SIZE;
+}
+
+/* svn_atomic__init_once callback that fills the CMD_HASH table. It will
+ error out on hash collisions. BATON and POOL are not used. */
+static svn_error_t *
+init_cmd_hash(void *baton,
+ apr_pool_t *pool)
+{
+ int i;
+ for (i = 0; ra_svn_edit_cmds[i].cmd; i++)
+ {
+ apr_size_t len = strlen(ra_svn_edit_cmds[i].cmd);
+ apr_size_t value = cmd_hash_func(ra_svn_edit_cmds[i].cmd, len);
+ SVN_ERR_ASSERT(cmd_hash[value].cmd.data == NULL);
+
+ cmd_hash[value].cmd.data = ra_svn_edit_cmds[i].cmd;
+ cmd_hash[value].cmd.len = len;
+ cmd_hash[value].handler = ra_svn_edit_cmds[i].handler;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Return the command handler function for the command name CMD.
+ Return NULL if no such handler exists */
+static cmd_handler_t
+cmd_lookup(const char *cmd)
+{
+ apr_size_t value;
+ apr_size_t len = strlen(cmd);
+
+ /* Malicious data that our hash function may not like? */
+ if (len == 0)
+ return NULL;
+
+ /* Hash lookup. */
+ value = cmd_hash_func(cmd, len);
+
+ /* Hit? */
+ if (cmd_hash[value].cmd.len != len)
+ return NULL;
+
+ if (memcmp(cmd_hash[value].cmd.data, cmd, len))
+ return NULL;
+
+ /* Yes! */
+ return cmd_hash[value].handler;
+}
+
static svn_error_t *blocked_write(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
void *baton)
{
ra_svn_driver_state_t *ds = baton;
const char *cmd;
- apr_array_header_t *params;
+ svn_ra_svn__list_t *params;
/* We blocked trying to send an error. Read and discard an editing
* command in order to avoid deadlock. */
@@ -931,13 +1086,16 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
ra_svn_driver_state_t state;
apr_pool_t *subpool = svn_pool_create(pool);
const char *cmd;
- int i;
svn_error_t *err, *write_err;
- apr_array_header_t *params;
+ svn_ra_svn__list_t *params;
+
+ SVN_ERR(svn_atomic__init_once(&cmd_hash_initialized, init_cmd_hash, NULL,
+ pool));
state.editor = editor;
state.edit_baton = edit_baton;
- state.tokens = apr_hash_make(pool);
+ state.tokens = svn_hash__make(pool);
+ state.last_token = NULL;
state.aborted = aborted;
state.done = FALSE;
state.pool = pool;
@@ -948,15 +1106,18 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
while (!state.done)
{
svn_pool_clear(subpool);
+
+ /* WRT to applying I/O limits, treat each editor command as a separate
+ * protocol command. */
+ svn_ra_svn__reset_command_io_counters(conn);
if (editor)
{
+ cmd_handler_t handler;
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;
+ handler = cmd_lookup(cmd);
- if (ra_svn_edit_cmds[i].cmd)
- err = (*ra_svn_edit_cmds[i].handler)(conn, subpool, params, &state);
+ if (handler)
+ err = (*handler)(conn, subpool, params, &state);
else if (strcmp(cmd, "failure") == 0)
{
/* While not really an editor command this can occur when
@@ -964,7 +1125,7 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
command */
if (aborted)
*aborted = TRUE;
- err = svn_ra_svn__handle_failure_status(params, pool);
+ err = svn_ra_svn__handle_failure_status(params);
return svn_error_compose_create(
err,
editor->abort_edit(edit_baton, subpool));
Modified: subversion/branches/ra-git/subversion/libsvn_ra_svn/internal_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_ra_svn/internal_auth.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_ra_svn/internal_auth.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_ra_svn/internal_auth.c Mon Nov 30 10:24:16 2015
@@ -37,16 +37,16 @@
#include "ra_svn.h"
-svn_boolean_t svn_ra_svn__find_mech(const apr_array_header_t *mechlist,
+svn_boolean_t svn_ra_svn__find_mech(const svn_ra_svn__list_t *mechlist,
const char *mech)
{
int i;
- svn_ra_svn_item_t *elt;
+ svn_ra_svn__item_t *elt;
for (i = 0; i < mechlist->nelts; i++)
{
- elt = &APR_ARRAY_IDX(mechlist, i, svn_ra_svn_item_t);
- if (elt->kind == SVN_RA_SVN_WORD && strcmp(elt->u.word, mech) == 0)
+ elt = &SVN_RA_SVN__LIST_ITEM(mechlist, i);
+ if (elt->kind == SVN_RA_SVN_WORD && strcmp(elt->u.word.data, mech) == 0)
return TRUE;
}
return FALSE;
@@ -69,7 +69,7 @@ static svn_error_t *read_success(svn_ra_
svn_error_t *
svn_ra_svn__do_internal_auth(svn_ra_svn__session_baton_t *sess,
- const apr_array_header_t *mechlist,
+ const svn_ra_svn__list_t *mechlist,
const char *realm, apr_pool_t *pool)
{
svn_ra_svn_conn_t *conn = sess->conn;
@@ -95,7 +95,7 @@ svn_ra_svn__do_internal_auth(svn_ra_svn_
{
SVN_ERR(svn_auth_first_credentials(&creds, &iterstate,
SVN_AUTH_CRED_SIMPLE, realmstring,
- sess->callbacks->auth_baton, pool));
+ sess->auth_baton, pool));
if (!creds)
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
_("Can't get password"));