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, &copy_path, &copy_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, &copy_path, &copy_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, &params));
-          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"));