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 2015/08/06 16:01:40 UTC
svn commit: r1694500 [4/7] - in /subversion/branches/fsx-1.10: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/
subversion/bindings/ctypes-python/csvn/ext/
subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apac...
Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/caching.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/caching.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/caching.c Thu Aug 6 14:01:38 2015
@@ -259,42 +259,42 @@ init_callbacks(svn_cache__t *cache,
svn_cache__error_handler_t error_handler,
apr_pool_t *pool)
{
- if (cache != NULL)
- {
#ifdef SVN_DEBUG_CACHE_DUMP_STATS
- /* schedule printing the access statistics upon pool cleanup,
- * i.e. end of FSX session.
- */
- dump_cache_baton_t *baton;
-
- baton = apr_palloc(pool, sizeof(*baton));
- baton->pool = pool;
- baton->cache = cache;
-
- apr_pool_cleanup_register(pool,
- baton,
- dump_cache_statistics,
- apr_pool_cleanup_null);
-#endif
+ /* schedule printing the access statistics upon pool cleanup,
+ * i.e. end of FSX session.
+ */
+ dump_cache_baton_t *baton;
- if (error_handler)
- SVN_ERR(svn_cache__set_error_handler(cache,
- error_handler,
- fs,
- pool));
+ baton = apr_palloc(pool, sizeof(*baton));
+ baton->pool = pool;
+ baton->cache = cache;
+
+ apr_pool_cleanup_register(pool,
+ baton,
+ dump_cache_statistics,
+ apr_pool_cleanup_null);
+#endif
- }
+ if (error_handler)
+ SVN_ERR(svn_cache__set_error_handler(cache,
+ error_handler,
+ fs,
+ pool));
return SVN_NO_ERROR;
}
/* Sets *CACHE_P to cache instance based on provided options.
- * Creates memcache if MEMCACHE is not NULL. Creates membuffer cache if
- * MEMBUFFER is not NULL. Fallbacks to inprocess cache if MEMCACHE and
- * MEMBUFFER are NULL and pages is non-zero. Sets *CACHE_P to NULL
- * otherwise. Use the given PRIORITY class for the new cache. If it
- * is 0, then use the default priority class.
+ *
+ * If DUMMY_CACHE is set, create a null cache. Otherwise, creates a memcache
+ * if MEMCACHE is not NULL or a membuffer cache if MEMBUFFER is not NULL.
+ * Falls back to inprocess cache if no other cache type has been selected
+ * and PAGES is not 0. Create a null cache otherwise.
+ *
+ * Use the given PRIORITY class for the new cache. If PRIORITY is 0, then
+ * use the default priority class. HAS_NAMESPACE indicates whether we
+ * prefixed this cache instance with a namespace.
*
* Unless NO_HANDLER is true, register an error handler that reports errors
* as warnings to the FS warning callback.
@@ -312,8 +312,10 @@ create_cache(svn_cache__t **cache_p,
apr_ssize_t klen,
const char *prefix,
apr_uint32_t priority,
+ svn_boolean_t has_namespace,
svn_fs_t *fs,
svn_boolean_t no_handler,
+ svn_boolean_t dummy_cache,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -323,7 +325,11 @@ create_cache(svn_cache__t **cache_p,
if (priority == 0)
priority = SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY;
- if (memcache)
+ if (dummy_cache)
+ {
+ SVN_ERR(svn_cache__create_null(cache_p, prefix, result_pool));
+ }
+ else if (memcache)
{
SVN_ERR(svn_cache__create_memcache(cache_p, memcache,
serializer, deserializer, klen,
@@ -334,9 +340,12 @@ create_cache(svn_cache__t **cache_p,
}
else if (membuffer)
{
+ /* We assume caches with namespaces to be relatively short-lived,
+ * i.e. their data will not be needed after a while. */
SVN_ERR(svn_cache__create_membuffer_cache(
cache_p, membuffer, serializer, deserializer,
- klen, prefix, priority, FALSE, result_pool, scratch_pool));
+ klen, prefix, priority, FALSE, has_namespace,
+ result_pool, scratch_pool));
}
else if (pages)
{
@@ -346,7 +355,7 @@ create_cache(svn_cache__t **cache_p,
}
else
{
- *cache_p = NULL;
+ SVN_ERR(svn_cache__create_null(cache_p, prefix, result_pool));
}
SVN_ERR(init_callbacks(*cache_p, fs, error_handler, result_pool));
@@ -371,6 +380,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
svn_boolean_t cache_fulltexts;
svn_boolean_t cache_revprops;
const char *cache_namespace;
+ svn_boolean_t has_namespace;
/* Evaluating the cache configuration. */
SVN_ERR(read_config(&cache_namespace,
@@ -382,6 +392,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
prefix = apr_pstrcat(scratch_pool, "ns:", cache_namespace, ":", prefix,
SVN_VA_NULL);
+ has_namespace = strlen(cache_namespace) > 0;
membuffer = svn_cache__get_global_membuffer_cache();
@@ -419,8 +430,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
sizeof(svn_fs_x__id_t),
apr_pstrcat(scratch_pool, prefix, "DIR", SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
/* Only 16 bytes per entry (a revision number + the corresponding offset).
@@ -435,8 +447,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "PACK-MANIFEST",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
/* initialize node revision cache, if caching has been enabled */
@@ -450,8 +463,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "NODEREVS",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
/* initialize representation header cache, if caching has been enabled */
@@ -465,8 +479,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "REPHEADER",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
/* initialize node change list cache, if caching has been enabled */
@@ -480,106 +495,90 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "CHANGES",
SVN_VA_NULL),
0,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
/* if enabled, cache fulltext and other derived information */
- if (cache_fulltexts)
- {
- SVN_ERR(create_cache(&(ffd->fulltext_cache),
- ffd->memcache,
- membuffer,
- 0, 0, /* Do not use inprocess cache */
- /* Values are svn_stringbuf_t */
- NULL, NULL,
- sizeof(svn_fs_x__pair_cache_key_t),
- apr_pstrcat(scratch_pool, prefix, "TEXT",
- SVN_VA_NULL),
- SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
- fs,
- no_handler,
- fs->pool, scratch_pool));
-
- SVN_ERR(create_cache(&(ffd->properties_cache),
- NULL,
- membuffer,
- 0, 0, /* Do not use inprocess cache */
- svn_fs_x__serialize_properties,
- svn_fs_x__deserialize_properties,
- sizeof(svn_fs_x__pair_cache_key_t),
- apr_pstrcat(scratch_pool, prefix, "PROP",
- SVN_VA_NULL),
- SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
- fs,
- no_handler,
- fs->pool, scratch_pool));
- }
- else
- {
- ffd->fulltext_cache = NULL;
- ffd->properties_cache = NULL;
- }
+ SVN_ERR(create_cache(&(ffd->fulltext_cache),
+ ffd->memcache,
+ membuffer,
+ 0, 0, /* Do not use inprocess cache */
+ /* Values are svn_stringbuf_t */
+ NULL, NULL,
+ sizeof(svn_fs_x__pair_cache_key_t),
+ apr_pstrcat(scratch_pool, prefix, "TEXT",
+ SVN_VA_NULL),
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ has_namespace,
+ fs,
+ no_handler, !cache_fulltexts,
+ fs->pool, scratch_pool));
+
+ SVN_ERR(create_cache(&(ffd->properties_cache),
+ NULL,
+ membuffer,
+ 0, 0, /* Do not use inprocess cache */
+ svn_fs_x__serialize_properties,
+ svn_fs_x__deserialize_properties,
+ sizeof(svn_fs_x__pair_cache_key_t),
+ apr_pstrcat(scratch_pool, prefix, "PROP",
+ SVN_VA_NULL),
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ has_namespace,
+ fs,
+ no_handler, !cache_fulltexts,
+ fs->pool, scratch_pool));
/* if enabled, cache revprops */
- if (cache_revprops)
- {
- SVN_ERR(create_cache(&(ffd->revprop_cache),
- NULL,
- membuffer,
- 0, 0, /* Do not use inprocess cache */
- svn_fs_x__serialize_properties,
- svn_fs_x__deserialize_properties,
- sizeof(svn_fs_x__pair_cache_key_t),
- apr_pstrcat(scratch_pool, prefix, "REVPROP",
- SVN_VA_NULL),
- SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
- fs,
- no_handler,
- fs->pool, scratch_pool));
- }
- else
- {
- ffd->revprop_cache = NULL;
- }
+ SVN_ERR(create_cache(&(ffd->revprop_cache),
+ NULL,
+ membuffer,
+ 0, 0, /* Do not use inprocess cache */
+ svn_fs_x__serialize_properties,
+ svn_fs_x__deserialize_properties,
+ sizeof(svn_fs_x__pair_cache_key_t),
+ apr_pstrcat(scratch_pool, prefix, "REVPROP",
+ SVN_VA_NULL),
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ has_namespace,
+ fs,
+ no_handler, !cache_revprops,
+ fs->pool, scratch_pool));
/* if enabled, cache text deltas and their combinations */
- if (cache_txdeltas)
- {
- SVN_ERR(create_cache(&(ffd->txdelta_window_cache),
- NULL,
- membuffer,
- 0, 0, /* Do not use inprocess cache */
- svn_fs_x__serialize_txdelta_window,
- svn_fs_x__deserialize_txdelta_window,
- sizeof(svn_fs_x__window_cache_key_t),
- apr_pstrcat(scratch_pool, prefix, "TXDELTA_WINDOW",
- SVN_VA_NULL),
- SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
- fs,
- no_handler,
- fs->pool, scratch_pool));
-
- SVN_ERR(create_cache(&(ffd->combined_window_cache),
- NULL,
- membuffer,
- 0, 0, /* Do not use inprocess cache */
- /* Values are svn_stringbuf_t */
- NULL, NULL,
- sizeof(svn_fs_x__window_cache_key_t),
- apr_pstrcat(scratch_pool, prefix, "COMBINED_WINDOW",
- SVN_VA_NULL),
- SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
- fs,
- no_handler,
- fs->pool, scratch_pool));
- }
- else
- {
- ffd->txdelta_window_cache = NULL;
- ffd->combined_window_cache = NULL;
- }
+ SVN_ERR(create_cache(&(ffd->txdelta_window_cache),
+ NULL,
+ membuffer,
+ 0, 0, /* Do not use inprocess cache */
+ svn_fs_x__serialize_txdelta_window,
+ svn_fs_x__deserialize_txdelta_window,
+ sizeof(svn_fs_x__window_cache_key_t),
+ apr_pstrcat(scratch_pool, prefix, "TXDELTA_WINDOW",
+ SVN_VA_NULL),
+ SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
+ has_namespace,
+ fs,
+ no_handler, !cache_txdeltas,
+ fs->pool, scratch_pool));
+
+ SVN_ERR(create_cache(&(ffd->combined_window_cache),
+ NULL,
+ membuffer,
+ 0, 0, /* Do not use inprocess cache */
+ /* Values are svn_stringbuf_t */
+ NULL, NULL,
+ sizeof(svn_fs_x__window_cache_key_t),
+ apr_pstrcat(scratch_pool, prefix, "COMBINED_WINDOW",
+ SVN_VA_NULL),
+ SVN_CACHE__MEMBUFFER_LOW_PRIORITY,
+ has_namespace,
+ fs,
+ no_handler, !cache_txdeltas,
+ fs->pool, scratch_pool));
+ /* Caches for our various container types. */
SVN_ERR(create_cache(&(ffd->noderevs_container_cache),
NULL,
membuffer,
@@ -590,8 +589,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "NODEREVSCNT",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
SVN_ERR(create_cache(&(ffd->changes_container_cache),
NULL,
@@ -603,8 +603,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "CHANGESCNT",
SVN_VA_NULL),
0,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
SVN_ERR(create_cache(&(ffd->reps_container_cache),
NULL,
@@ -616,10 +617,12 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "REPSCNT",
SVN_VA_NULL),
0,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
+ /* Cache index info. */
SVN_ERR(create_cache(&(ffd->l2p_header_cache),
NULL,
membuffer,
@@ -631,8 +634,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "L2P_HEADER",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
SVN_ERR(create_cache(&(ffd->l2p_page_cache),
NULL,
@@ -645,8 +649,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "L2P_PAGE",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
SVN_ERR(create_cache(&(ffd->p2l_header_cache),
NULL,
@@ -658,8 +663,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "P2L_HEADER",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
SVN_ERR(create_cache(&(ffd->p2l_page_cache),
NULL,
@@ -671,8 +677,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs
apr_pstrcat(scratch_pool, prefix, "P2L_PAGE",
SVN_VA_NULL),
SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
+ has_namespace,
fs,
- no_handler,
+ no_handler, FALSE,
fs->pool, scratch_pool));
return SVN_NO_ERROR;
Modified: subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_x.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_x.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_x.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_fs_x/fs_x.c Thu Aug 6 14:01:38 2015
@@ -1145,17 +1145,18 @@ change_rev_prop_body(void *baton,
{
change_rev_prop_baton_t *cb = baton;
apr_hash_t *table;
+ const svn_string_t *present_value;
/* Read current revprop values from disk (never from cache).
Even if somehow the cache got out of sync, we want to make sure that
we read, update and write up-to-date data. */
SVN_ERR(svn_fs_x__get_revision_proplist(&table, cb->fs, cb->rev, TRUE,
scratch_pool, scratch_pool));
+ present_value = svn_hash_gets(table, cb->name);
if (cb->old_value_p)
{
const svn_string_t *wanted_value = *cb->old_value_p;
- const svn_string_t *present_value = svn_hash_gets(table, cb->name);
if ((!wanted_value != !present_value)
|| (wanted_value && present_value
&& !svn_string_compare(wanted_value, present_value)))
@@ -1168,6 +1169,13 @@ change_rev_prop_body(void *baton,
}
/* Fall through. */
}
+
+ /* If the prop-set is a no-op, skip the actual write. */
+ if ((!present_value && !cb->value)
+ || (present_value && cb->value
+ && svn_string_compare(present_value, cb->value)))
+ return SVN_NO_ERROR;
+
svn_hash_sets(table, cb->name, cb->value);
return svn_fs_x__set_revision_proplist(cb->fs, cb->rev, table,
Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/client.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/client.c Thu Aug 6 14:01:38 2015
@@ -2291,7 +2291,7 @@ static svn_error_t *ra_svn_unlock_compat
const void *key;
const char *path;
void *val;
- const char *token;
+ const svn_string_t *token;
svn_error_t *err, *callback_err = NULL;
svn_pool_clear(iterpool);
@@ -2299,7 +2299,7 @@ static svn_error_t *ra_svn_unlock_compat
apr_hash_this(hi, &key, NULL, &val);
path = key;
if (strcmp(val, "") != 0)
- token = val;
+ token = svn_string_create(val, iterpool);
else
token = NULL;
Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/editorp.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/editorp.c Thu Aug 6 14:01:38 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,7 +506,16 @@ 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"));
@@ -883,11 +909,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 apr_array_header_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 },
@@ -911,6 +941,92 @@ 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)
{
@@ -939,13 +1055,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_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;
@@ -958,13 +1077,12 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
svn_pool_clear(subpool);
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
Modified: subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/marshal.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_ra_svn/marshal.c Thu Aug 6 14:01:38 2015
@@ -60,9 +60,10 @@
/* We don't use "words" longer than this in our protocol. The longest word
* we are currently using is only about 16 chars long but we leave room for
- * longer future capability and command names.
+ * longer future capability and command names. See read_item() to understand
+ * why MAX_WORD_LENGTH - 1 should be a multiple of 8.
*/
-#define MAX_WORD_LENGTH 31
+#define MAX_WORD_LENGTH 25
/* The generic parsers will use the following value to limit the recursion
* depth to some reasonable value. The current protocol implementation
@@ -512,22 +513,65 @@ svn_ra_svn__write_number(svn_ra_svn_conn
return write_number(conn, pool, number, ' ');
}
+/* Write string S of length LEN to TARGET and return the first position
+ after the written data.
+
+ NOTE: This function assumes that TARGET has enough room for S, the LEN
+ prefix and the required separators. The available buffer size
+ should be SVN_INT64_BUFFER_SIZE + LEN + 1 to avoid any chance of
+ overflow.
+ */
+static char *
+write_ncstring_quick(char *target,
+ const char *s,
+ apr_size_t len)
+{
+ /* Write string length. */
+ if (len < 10)
+ {
+ *target = (char)(len + '0');
+ target++;
+ }
+ else
+ {
+ target += svn__ui64toa(target, len);
+ }
+
+ /* Separator & contents. */
+ target[0] = ':';
+ memcpy(target + 1, s, len);
+ target[len + 1] = ' ';
+
+ /* First location after the string. */
+ return target + len + 2;
+}
+
+
static svn_error_t *
svn_ra_svn__write_ncstring(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *s,
apr_size_t len)
{
- if (len < 10)
- {
- SVN_ERR(writebuf_writechar(conn, pool, (char)(len + '0')));
- SVN_ERR(writebuf_writechar(conn, pool, ':'));
+ apr_size_t needed = SVN_INT64_BUFFER_SIZE + len + 1;
+
+ /* In most cases, there is enough left room in the WRITE_BUF
+ the we can serialize directly into it. */
+ if (conn->write_pos + needed < sizeof(conn->write_buf))
+ {
+ /* Quick path. */
+ conn->write_pos = write_ncstring_quick(conn->write_buf
+ + conn->write_pos, s, len)
+ - conn->write_buf;
}
else
- SVN_ERR(write_number(conn, pool, len, ':'));
+ {
+ /* Slower fallback code. */
+ SVN_ERR(write_number(conn, pool, len, ':'));
- SVN_ERR(writebuf_write(conn, pool, s, len));
- SVN_ERR(writebuf_writechar(conn, pool, ' '));
+ SVN_ERR(writebuf_write(conn, pool, s, len));
+ SVN_ERR(writebuf_writechar(conn, pool, ' '));
+ }
return SVN_NO_ERROR;
}
@@ -755,6 +799,52 @@ write_tuple_string_opt(svn_ra_svn_conn_t
return str ? svn_ra_svn__write_string(conn, pool, str) : SVN_NO_ERROR;
}
+/* Optimized sending code for the "(s?)" pattern. */
+static svn_error_t *
+write_tuple_string_opt_list(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool,
+ const svn_string_t *str)
+{
+ apr_size_t needed;
+
+ /* Special case. */
+ if (!str)
+ return writebuf_write(conn, pool, "( ) ", 4);
+
+ /* If there is at least this much the room left in the WRITE_BUF,
+ we can serialize directly into it. */
+ needed = 2 /* open list */
+ + SVN_INT64_BUFFER_SIZE /* string length + separator */
+ + str->len /* string contents */
+ + 2; /* close list */
+
+ if (conn->write_pos + needed <= sizeof(conn->write_buf))
+ {
+ /* Quick path. */
+ /* Open list. */
+ char *p = conn->write_buf + conn->write_pos;
+ p[0] = '(';
+ p[1] = ' ';
+
+ /* Write string. */
+ p = write_ncstring_quick(p + 2, str->data, str->len);
+
+ /* Close list. */
+ p[0] = ')';
+ p[1] = ' ';
+ conn->write_pos = p + 2 - conn->write_buf;
+ }
+ else
+ {
+ /* Standard code path (fallback). */
+ SVN_ERR(svn_ra_svn__start_list(conn, pool));
+ SVN_ERR(svn_ra_svn__write_string(conn, pool, str));
+ SVN_ERR(svn_ra_svn__end_list(conn, pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
write_tuple_start_list(svn_ra_svn_conn_t *conn,
apr_pool_t *pool)
@@ -809,14 +899,14 @@ static svn_error_t *
write_cmd_add_node(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *parent_token,
- const char *token,
+ const svn_string_t *parent_token,
+ const svn_string_t *token,
const char *copy_path,
svn_revnum_t copy_rev)
{
SVN_ERR(write_tuple_cstring(conn, pool, path));
- SVN_ERR(write_tuple_cstring(conn, pool, parent_token));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, parent_token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(write_tuple_start_list(conn, pool));
SVN_ERR(write_tuple_cstring_opt(conn, pool, copy_path));
SVN_ERR(write_tuple_revision_opt(conn, pool, copy_rev));
@@ -829,13 +919,13 @@ static svn_error_t *
write_cmd_open_node(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *parent_token,
- const char *token,
+ const svn_string_t *parent_token,
+ const svn_string_t *token,
svn_revnum_t rev)
{
SVN_ERR(write_tuple_cstring(conn, pool, path));
- SVN_ERR(write_tuple_cstring(conn, pool, parent_token));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, parent_token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(write_tuple_start_list(conn, pool));
SVN_ERR(write_tuple_revision_opt(conn, pool, rev));
SVN_ERR(write_tuple_end_list(conn, pool));
@@ -846,15 +936,13 @@ write_cmd_open_node(svn_ra_svn_conn_t *c
static svn_error_t *
write_cmd_change_node_prop(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- const char *token,
+ const svn_string_t *token,
const char *name,
const svn_string_t *value)
{
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(write_tuple_cstring(conn, pool, name));
- SVN_ERR(write_tuple_start_list(conn, pool));
- SVN_ERR(write_tuple_string_opt(conn, pool, value));
- SVN_ERR(write_tuple_end_list(conn, pool));
+ SVN_ERR(write_tuple_string_opt_list(conn, pool, value));
return SVN_NO_ERROR;
}
@@ -863,10 +951,10 @@ static svn_error_t *
write_cmd_absent_node(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *token)
+ const svn_string_t *token)
{
SVN_ERR(write_tuple_cstring(conn, pool, path));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
return SVN_NO_ERROR;
}
@@ -1060,17 +1148,40 @@ static svn_error_t *read_item(svn_ra_svn
char *p = buffer + 1;
buffer[0] = c;
- while (1)
+ if (conn->read_ptr + MAX_WORD_LENGTH <= conn->read_end)
{
- SVN_ERR(readbuf_getchar(conn, pool, p));
- if (!svn_ctype_isalnum(*p) && *p != '-')
- break;
+ /* Fast path: we can simply take a chunk from the read
+ * buffer and inspect it with no overflow checks etc.
+ *
+ * Copying these 24 bytes unconditionally is also faster
+ * than a variable-sized memcpy. Note that P is at BUFFER[1].
+ */
+ memcpy(p, conn->read_ptr, MAX_WORD_LENGTH - 1);
+ *end = 0;
+
+ /* This will terminate at P == END because of *END == NUL. */
+ while (svn_ctype_isalnum(*p) || *p == '-')
+ ++p;
- if (++p == end)
- return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
- _("Word is too long"));
+ /* Only now do we mark data as actually read. */
+ conn->read_ptr += p - buffer;
+ }
+ else
+ {
+ /* Slow path. Byte-by-byte copying and checking for
+ * input and output buffer boundaries. */
+ for (p = buffer + 1; p != end; ++p)
+ {
+ SVN_ERR(readbuf_getchar(conn, pool, p));
+ if (!svn_ctype_isalnum(*p) && *p != '-')
+ break;
+ }
}
+ if (p == end)
+ return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ _("Word is too long"));
+
c = *p;
*p = '\0';
@@ -1673,13 +1784,13 @@ svn_error_t *
svn_ra_svn__write_cmd_open_root(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
svn_revnum_t rev,
- const char *token)
+ const svn_string_t *token)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( open-root ( "));
SVN_ERR(write_tuple_start_list(conn, pool));
SVN_ERR(write_tuple_revision_opt(conn, pool, rev));
SVN_ERR(write_tuple_end_list(conn, pool));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(writebuf_write_literal(conn, pool, ") ) "));
return SVN_NO_ERROR;
@@ -1690,14 +1801,14 @@ svn_ra_svn__write_cmd_delete_entry(svn_r
apr_pool_t *pool,
const char *path,
svn_revnum_t rev,
- const char *token)
+ const svn_string_t *token)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( delete-entry ( "));
SVN_ERR(write_tuple_cstring(conn, pool, path));
SVN_ERR(write_tuple_start_list(conn, pool));
SVN_ERR(write_tuple_revision_opt(conn, pool, rev));
SVN_ERR(write_tuple_end_list(conn, pool));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(writebuf_write_literal(conn, pool, ") ) "));
return SVN_NO_ERROR;
@@ -1707,8 +1818,8 @@ svn_error_t *
svn_ra_svn__write_cmd_add_dir(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *parent_token,
- const char *token,
+ const svn_string_t *parent_token,
+ const svn_string_t *token,
const char *copy_path,
svn_revnum_t copy_rev)
{
@@ -1724,8 +1835,8 @@ svn_error_t *
svn_ra_svn__write_cmd_open_dir(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *parent_token,
- const char *token,
+ const svn_string_t *parent_token,
+ const svn_string_t *token,
svn_revnum_t rev)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( open-dir ( "));
@@ -1738,7 +1849,7 @@ svn_ra_svn__write_cmd_open_dir(svn_ra_sv
svn_error_t *
svn_ra_svn__write_cmd_change_dir_prop(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- const char *token,
+ const svn_string_t *token,
const char *name,
const svn_string_t *value)
{
@@ -1752,10 +1863,10 @@ svn_ra_svn__write_cmd_change_dir_prop(sv
svn_error_t *
svn_ra_svn__write_cmd_close_dir(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- const char *token)
+ const svn_string_t *token)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( close-dir ( "));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(writebuf_write_literal(conn, pool, ") ) "));
return SVN_NO_ERROR;
@@ -1765,7 +1876,7 @@ svn_error_t *
svn_ra_svn__write_cmd_absent_dir(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *parent_token)
+ const svn_string_t *parent_token)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( absent-dir ( "));
SVN_ERR(write_cmd_absent_node(conn, pool, path, parent_token));
@@ -1778,8 +1889,8 @@ svn_error_t *
svn_ra_svn__write_cmd_add_file(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *parent_token,
- const char *token,
+ const svn_string_t *parent_token,
+ const svn_string_t *token,
const char *copy_path,
svn_revnum_t copy_rev)
{
@@ -1795,8 +1906,8 @@ svn_error_t *
svn_ra_svn__write_cmd_open_file(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *parent_token,
- const char *token,
+ const svn_string_t *parent_token,
+ const svn_string_t *token,
svn_revnum_t rev)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( open-file ( "));
@@ -1809,7 +1920,7 @@ svn_ra_svn__write_cmd_open_file(svn_ra_s
svn_error_t *
svn_ra_svn__write_cmd_change_file_prop(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- const char *token,
+ const svn_string_t *token,
const char *name,
const svn_string_t *value)
{
@@ -1823,11 +1934,11 @@ svn_ra_svn__write_cmd_change_file_prop(s
svn_error_t *
svn_ra_svn__write_cmd_close_file(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- const char *token,
+ const svn_string_t *token,
const char *text_checksum)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( close-file ( "));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(write_tuple_start_list(conn, pool));
SVN_ERR(write_tuple_cstring_opt(conn, pool, text_checksum));
SVN_ERR(write_tuple_end_list(conn, pool));
@@ -1840,7 +1951,7 @@ svn_error_t *
svn_ra_svn__write_cmd_absent_file(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *parent_token)
+ const svn_string_t *parent_token)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( absent-file ( "));
SVN_ERR(write_cmd_absent_node(conn, pool, path, parent_token));
@@ -1852,11 +1963,11 @@ svn_ra_svn__write_cmd_absent_file(svn_ra
svn_error_t *
svn_ra_svn__write_cmd_textdelta_chunk(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- const char *token,
+ const svn_string_t *token,
const svn_string_t *chunk)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( textdelta-chunk ( "));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(write_tuple_string(conn, pool, chunk));
SVN_ERR(writebuf_write_literal(conn, pool, ") ) "));
@@ -1866,10 +1977,10 @@ svn_ra_svn__write_cmd_textdelta_chunk(sv
svn_error_t *
svn_ra_svn__write_cmd_textdelta_end(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- const char *token)
+ const svn_string_t *token)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( textdelta-end ( "));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(writebuf_write_literal(conn, pool, ") ) "));
return SVN_NO_ERROR;
@@ -1878,11 +1989,11 @@ svn_ra_svn__write_cmd_textdelta_end(svn_
svn_error_t *
svn_ra_svn__write_cmd_apply_textdelta(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
- const char *token,
+ const svn_string_t *token,
const char *base_checksum)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( apply-textdelta ( "));
- SVN_ERR(write_tuple_cstring(conn, pool, token));
+ SVN_ERR(write_tuple_string(conn, pool, token));
SVN_ERR(write_tuple_start_list(conn, pool));
SVN_ERR(write_tuple_cstring_opt(conn, pool, base_checksum));
SVN_ERR(write_tuple_end_list(conn, pool));
@@ -2020,9 +2131,7 @@ svn_ra_svn__write_cmd_change_rev_prop2(s
SVN_ERR(writebuf_write_literal(conn, pool, "( change-rev-prop2 ( "));
SVN_ERR(write_tuple_revision(conn, pool, rev));
SVN_ERR(write_tuple_cstring(conn, pool, name));
- SVN_ERR(write_tuple_start_list(conn, pool));
- SVN_ERR(write_tuple_string_opt(conn, pool, value));
- SVN_ERR(write_tuple_end_list(conn, pool));
+ SVN_ERR(write_tuple_string_opt_list(conn, pool, value));
SVN_ERR(write_tuple_start_list(conn, pool));
SVN_ERR(write_tuple_boolean(conn, pool, dont_care));
SVN_ERR(write_tuple_string_opt(conn, pool, old_value));
@@ -2274,14 +2383,12 @@ svn_error_t *
svn_ra_svn__write_cmd_unlock(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
- const char *token,
+ const svn_string_t *token,
svn_boolean_t break_lock)
{
SVN_ERR(writebuf_write_literal(conn, pool, "( unlock ( "));
SVN_ERR(write_tuple_cstring(conn, pool, path));
- SVN_ERR(write_tuple_start_list(conn, pool));
- SVN_ERR(write_tuple_cstring_opt(conn, pool, token));
- SVN_ERR(write_tuple_end_list(conn, pool));
+ SVN_ERR(write_tuple_string_opt_list(conn, pool, token));
SVN_ERR(write_tuple_boolean(conn, pool, break_lock));
SVN_ERR(writebuf_write_literal(conn, pool, ") ) "));
@@ -2431,6 +2538,49 @@ svn_error_t *svn_ra_svn__write_cmd_failu
return writebuf_write_literal(conn, pool, ") ) ");
}
+/* Initializer for static svn_string_t . */
+#define STATIC_SVN_STRING(x) { x, sizeof(x) - 1 }
+
+/* Return a pre-cooked serialized representation for the changed path
+ flags NODE_KIND, TEXT_MODIFIED and PROPS_MODIFIED. If we don't
+ have a suitable pre-cooked string, return an empty string. */
+static const svn_string_t *
+changed_path_flags(svn_node_kind_t node_kind,
+ svn_boolean_t text_modified,
+ svn_boolean_t props_modified)
+{
+ const static svn_string_t file_flags[4]
+ = { STATIC_SVN_STRING(" ) ( 4:file false false ) ) "),
+ STATIC_SVN_STRING(" ) ( 4:file false true ) ) "),
+ STATIC_SVN_STRING(" ) ( 4:file true false ) ) "),
+ STATIC_SVN_STRING(" ) ( 4:file true true ) ) ") };
+
+ const static svn_string_t dir_flags[4]
+ = { STATIC_SVN_STRING(" ) ( 3:dir false false ) ) "),
+ STATIC_SVN_STRING(" ) ( 3:dir false true ) ) "),
+ STATIC_SVN_STRING(" ) ( 3:dir true false ) ) "),
+ STATIC_SVN_STRING(" ) ( 3:dir true true ) ) ") };
+
+ const static svn_string_t no_flags = STATIC_SVN_STRING("");
+
+ /* Select the array based on the NODE_KIND. */
+ const svn_string_t *flags;
+ if (node_kind == svn_node_file)
+ flags = file_flags;
+ else if (node_kind == svn_node_dir)
+ flags = dir_flags;
+ else
+ return &no_flags;
+
+ /* Select the correct array entry. */
+ if (text_modified)
+ flags += 2;
+ if (props_modified)
+ flags++;
+
+ return flags;
+}
+
svn_error_t *
svn_ra_svn__write_data_log_changed_path(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
@@ -2442,21 +2592,77 @@ svn_ra_svn__write_data_log_changed_path(
svn_boolean_t text_modified,
svn_boolean_t props_modified)
{
- SVN_ERR(write_tuple_start_list(conn, pool));
+ apr_size_t path_len = strlen(path);
+ apr_size_t copyfrom_len = copyfrom_path ? strlen(copyfrom_path) : 0;
+ const svn_string_t *flags_str = changed_path_flags(node_kind,
+ text_modified,
+ props_modified);
+
+ /* How much buffer space do we need (worst case)? */
+ apr_size_t needed = 2 /* list start */
+ + path_len + SVN_INT64_BUFFER_SIZE
+ /* path */
+ + 2 /* action */
+ + 2 + copyfrom_len + 2 * SVN_INT64_BUFFER_SIZE
+ /* list start + copy-from info */
+ + flags_str->len; /* flags and closing lists */
+
+ /* If the remaining buffer is big enough and we've got all parts,
+ directly copy into the buffer. */
+ if ( (conn->write_pos + needed <= sizeof(conn->write_buf))
+ && (flags_str->len > 0))
+ {
+ /* Quick path. */
+ /* Open list. */
+ char *p = conn->write_buf + conn->write_pos;
+ p[0] = '(';
+ p[1] = ' ';
+
+ /* Write path. */
+ p = write_ncstring_quick(p + 2, path, path_len);
+
+ /* Action */
+ p[0] = action;
+ p[1] = ' ';
+ p[2] = '(';
+
+ /* Copy-from info (if given) */
+ if (copyfrom_path)
+ {
+ p[3] = ' ';
+ p = write_ncstring_quick(p + 4, copyfrom_path, copyfrom_len);
+ p += svn__ui64toa(p, copyfrom_rev);
+ }
+ else
+ {
+ p += 3;
+ }
- SVN_ERR(write_tuple_cstring(conn, pool, path));
- SVN_ERR(writebuf_writechar(conn, pool, action));
- SVN_ERR(writebuf_writechar(conn, pool, ' '));
- SVN_ERR(write_tuple_start_list(conn, pool));
- SVN_ERR(write_tuple_cstring_opt(conn, pool, copyfrom_path));
- SVN_ERR(write_tuple_revision_opt(conn, pool, copyfrom_rev));
- SVN_ERR(write_tuple_end_list(conn, pool));
- SVN_ERR(write_tuple_start_list(conn, pool));
- SVN_ERR(write_tuple_cstring(conn, pool, svn_node_kind_to_word(node_kind)));
- SVN_ERR(write_tuple_boolean(conn, pool, text_modified));
- SVN_ERR(write_tuple_boolean(conn, pool, props_modified));
+ /* Close with flags. */
+ memcpy(p, flags_str->data, flags_str->len);
+ conn->write_pos = p + flags_str->len - conn->write_buf;
+ }
+ else
+ {
+ /* Standard code path (fallback). */
+ SVN_ERR(write_tuple_start_list(conn, pool));
- return writebuf_write_literal(conn, pool, ") ) ");
+ SVN_ERR(svn_ra_svn__write_ncstring(conn, pool, path, path_len));
+ SVN_ERR(writebuf_writechar(conn, pool, action));
+ SVN_ERR(writebuf_writechar(conn, pool, ' '));
+ SVN_ERR(write_tuple_start_list(conn, pool));
+ SVN_ERR(write_tuple_cstring_opt(conn, pool, copyfrom_path));
+ SVN_ERR(write_tuple_revision_opt(conn, pool, copyfrom_rev));
+ SVN_ERR(write_tuple_end_list(conn, pool));
+ SVN_ERR(write_tuple_start_list(conn, pool));
+ SVN_ERR(write_tuple_cstring(conn, pool, svn_node_kind_to_word(node_kind)));
+ SVN_ERR(write_tuple_boolean(conn, pool, text_modified));
+ SVN_ERR(write_tuple_boolean(conn, pool, props_modified));
+
+ SVN_ERR(writebuf_write_literal(conn, pool, ") ) "));
+ }
+
+ return SVN_NO_ERROR;
}
svn_error_t *
@@ -2471,15 +2677,9 @@ svn_ra_svn__write_data_log_entry(svn_ra_
unsigned revprop_count)
{
SVN_ERR(write_tuple_revision(conn, pool, revision));
- SVN_ERR(write_tuple_start_list(conn, pool));
- SVN_ERR(write_tuple_string_opt(conn, pool, author));
- SVN_ERR(write_tuple_end_list(conn, pool));
- SVN_ERR(write_tuple_start_list(conn, pool));
- SVN_ERR(write_tuple_string_opt(conn, pool, date));
- SVN_ERR(write_tuple_end_list(conn, pool));
- SVN_ERR(write_tuple_start_list(conn, pool));
- SVN_ERR(write_tuple_string_opt(conn, pool, message));
- SVN_ERR(write_tuple_end_list(conn, pool));
+ SVN_ERR(write_tuple_string_opt_list(conn, pool, author));
+ SVN_ERR(write_tuple_string_opt_list(conn, pool, date));
+ SVN_ERR(write_tuple_string_opt_list(conn, pool, message));
SVN_ERR(write_tuple_boolean(conn, pool, has_children));
SVN_ERR(write_tuple_boolean(conn, pool, invalid_revnum));
SVN_ERR(svn_ra_svn__write_number(conn, pool, revprop_count));
Modified: subversion/branches/fsx-1.10/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_repos/deprecated.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_repos/deprecated.c Thu Aug 6 14:01:38 2015
@@ -731,6 +731,33 @@ repos_notify_handler(void *baton,
}
}
+svn_error_t *
+svn_repos_dump_fs3(svn_repos_t *repos,
+ svn_stream_t *stream,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_boolean_t incremental,
+ svn_boolean_t use_deltas,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_repos_dump_fs4(repos,
+ stream,
+ start_rev,
+ end_rev,
+ incremental,
+ use_deltas,
+ TRUE,
+ TRUE,
+ notify_func,
+ notify_baton,
+ cancel_func,
+ cancel_baton,
+ pool));
+}
svn_error_t *
svn_repos_dump_fs2(svn_repos_t *repos,
@@ -774,9 +801,9 @@ svn_repos_verify_fs2(svn_repos_t *repos,
end_rev,
FALSE,
FALSE,
- FALSE,
notify_func,
notify_baton,
+ NULL, NULL,
cancel_func,
cancel_baton,
pool));
Modified: subversion/branches/fsx-1.10/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_repos/dump.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_repos/dump.c Thu Aug 6 14:01:38 2015
@@ -1919,33 +1919,44 @@ get_dump_editor(const svn_delta_editor_t
/* Helper for svn_repos_dump_fs.
Write a revision record of REV in FS to writable STREAM, using POOL.
+ Dump revision properties as well if INCLUDE_REVPROPS has been set.
*/
static svn_error_t *
write_revision_record(svn_stream_t *stream,
svn_fs_t *fs,
svn_revnum_t rev,
+ svn_boolean_t include_revprops,
apr_pool_t *pool)
{
apr_hash_t *props;
apr_time_t timetemp;
svn_string_t *datevalue;
- SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, pool));
+ if (include_revprops)
+ {
+ SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, pool));
- /* Run revision date properties through the time conversion to
- canonicalize them. */
- /* ### Remove this when it is no longer needed for sure. */
- datevalue = svn_hash_gets(props, SVN_PROP_REVISION_DATE);
- if (datevalue)
- {
- SVN_ERR(svn_time_from_cstring(&timetemp, datevalue->data, pool));
- datevalue = svn_string_create(svn_time_to_cstring(timetemp, pool),
- pool);
- svn_hash_sets(props, SVN_PROP_REVISION_DATE, datevalue);
+ /* Run revision date properties through the time conversion to
+ canonicalize them. */
+ /* ### Remove this when it is no longer needed for sure. */
+ datevalue = svn_hash_gets(props, SVN_PROP_REVISION_DATE);
+ if (datevalue)
+ {
+ SVN_ERR(svn_time_from_cstring(&timetemp, datevalue->data, pool));
+ datevalue = svn_string_create(svn_time_to_cstring(timetemp, pool),
+ pool);
+ svn_hash_sets(props, SVN_PROP_REVISION_DATE, datevalue);
+ }
+ }
+ else
+ {
+ /* Although we won't use it, we still need this container for the
+ call below. */
+ props = apr_hash_make(pool);
}
SVN_ERR(svn_repos__dump_revision_record(stream, rev, NULL, props,
- TRUE /*props_section_always*/,
+ include_revprops,
pool));
return SVN_NO_ERROR;
}
@@ -1954,12 +1965,14 @@ write_revision_record(svn_stream_t *stre
/* The main dumper. */
svn_error_t *
-svn_repos_dump_fs3(svn_repos_t *repos,
+svn_repos_dump_fs4(svn_repos_t *repos,
svn_stream_t *stream,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
svn_boolean_t incremental,
svn_boolean_t use_deltas,
+ svn_boolean_t include_revprops,
+ svn_boolean_t include_changes,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
@@ -1970,7 +1983,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
void *dump_edit_baton = NULL;
svn_revnum_t rev;
svn_fs_t *fs = svn_repos_fs(repos);
- apr_pool_t *subpool = svn_pool_create(pool);
+ apr_pool_t *iterpool = svn_pool_create(pool);
svn_revnum_t youngest;
const char *uuid;
int version;
@@ -2029,18 +2042,20 @@ svn_repos_dump_fs3(svn_repos_t *repos,
svn_fs_root_t *to_root;
svn_boolean_t use_deltas_for_rev;
- svn_pool_clear(subpool);
+ svn_pool_clear(iterpool);
/* Check for cancellation. */
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
/* Write the revision record. */
- SVN_ERR(write_revision_record(stream, fs, rev, subpool));
+ SVN_ERR(write_revision_record(stream, fs, rev, include_revprops,
+ iterpool));
/* When dumping revision 0, we just write out the revision record.
- The parser might want to use its properties. */
- if (rev == 0)
+ The parser might want to use its properties.
+ If we don't want revision changes at all, skip in any case. */
+ if (rev == 0 || !include_changes)
goto loop_end;
/* Fetch the editor which dumps nodes to a file. Regardless of
@@ -2052,10 +2067,10 @@ svn_repos_dump_fs3(svn_repos_t *repos,
&found_old_mergeinfo, NULL,
notify_func, notify_baton,
start_rev, use_deltas_for_rev, FALSE, FALSE,
- subpool));
+ iterpool));
/* Drive the editor in one way or another. */
- SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, subpool));
+ SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, iterpool));
/* If this is the first revision of a non-incremental dump,
we're in for a full tree dump. Otherwise, we want to simply
@@ -2064,7 +2079,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
{
/* Compare against revision 0, so everything appears to be added. */
svn_fs_root_t *from_root;
- SVN_ERR(svn_fs_revision_root(&from_root, fs, 0, subpool));
+ SVN_ERR(svn_fs_revision_root(&from_root, fs, 0, iterpool));
SVN_ERR(svn_repos_dir_delta2(from_root, "", "",
to_root, "",
dump_editor, dump_edit_baton,
@@ -2074,25 +2089,25 @@ svn_repos_dump_fs3(svn_repos_t *repos,
svn_depth_infinity,
FALSE, /* don't send entry props */
FALSE, /* don't ignore ancestry */
- subpool));
+ iterpool));
}
else
{
/* The normal case: compare consecutive revs. */
SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
dump_editor, dump_edit_baton,
- NULL, NULL, subpool));
+ NULL, NULL, iterpool));
/* While our editor close_edit implementation is a no-op, we still
do this for completeness. */
- SVN_ERR(dump_editor->close_edit(dump_edit_baton, subpool));
+ SVN_ERR(dump_editor->close_edit(dump_edit_baton, iterpool));
}
loop_end:
if (notify_func)
{
notify->revision = rev;
- notify_func(notify_baton, notify, subpool);
+ notify_func(notify_baton, notify, iterpool);
}
}
@@ -2103,12 +2118,12 @@ svn_repos_dump_fs3(svn_repos_t *repos,
warning, since the inline warnings already issued might easily be
missed. */
- notify = svn_repos_notify_create(svn_repos_notify_dump_end, subpool);
- notify_func(notify_baton, notify, subpool);
+ notify = svn_repos_notify_create(svn_repos_notify_dump_end, iterpool);
+ notify_func(notify_baton, notify, iterpool);
if (found_old_reference)
{
- notify_warning(subpool, notify_func, notify_baton,
+ notify_warning(iterpool, notify_func, notify_baton,
svn_repos_notify_warning_found_old_reference,
_("The range of revisions dumped "
"contained references to "
@@ -2120,7 +2135,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
in dumped mergeinfo. */
if (found_old_mergeinfo)
{
- notify_warning(subpool, notify_func, notify_baton,
+ notify_warning(iterpool, notify_func, notify_baton,
svn_repos_notify_warning_found_old_mergeinfo,
_("The range of revisions dumped "
"contained mergeinfo "
@@ -2129,7 +2144,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
}
}
- svn_pool_destroy(subpool);
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -2265,24 +2280,6 @@ verify_close_directory(void *dir_baton,
return close_directory(dir_baton, pool);
}
-static void
-notify_verification_error(svn_revnum_t rev,
- svn_error_t *err,
- svn_repos_notify_func_t notify_func,
- void *notify_baton,
- apr_pool_t *pool)
-{
- svn_repos_notify_t *notify_failure;
-
- if (notify_func == NULL)
- return;
-
- notify_failure = svn_repos_notify_create(svn_repos_notify_failure, pool);
- notify_failure->err = err;
- notify_failure->revision = rev;
- notify_func(notify_baton, notify_failure, pool);
-}
-
/* Verify revision REV in file system FS. */
static svn_error_t *
verify_one_revision(svn_fs_t *fs,
@@ -2359,15 +2356,42 @@ verify_fs_notify_func(svn_revnum_t revis
notify_baton->notify, pool);
}
+static svn_error_t *
+report_error(svn_revnum_t revision,
+ svn_error_t *verify_err,
+ svn_repos_verify_callback_t verify_callback,
+ void *verify_baton,
+ apr_pool_t *pool)
+{
+ if (verify_callback)
+ {
+ svn_error_t *cb_err;
+
+ /* The caller provided us with a callback, so make him responsible
+ for what's going to happen with the error. */
+ cb_err = verify_callback(verify_baton, revision, verify_err, pool);
+ svn_error_clear(verify_err);
+ SVN_ERR(cb_err);
+
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ /* No callback -- no second guessing. Just return the error. */
+ return svn_error_trace(verify_err);
+ }
+}
+
svn_error_t *
svn_repos_verify_fs3(svn_repos_t *repos,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
- svn_boolean_t keep_going,
svn_boolean_t check_normalization,
svn_boolean_t metadata_only,
svn_repos_notify_func_t notify_func,
void *notify_baton,
+ svn_repos_verify_callback_t verify_callback,
+ void *verify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
@@ -2380,8 +2404,6 @@ svn_repos_verify_fs3(svn_repos_t *repos,
svn_fs_progress_notify_func_t verify_notify = NULL;
struct verify_fs_notify_func_baton_t *verify_notify_baton = NULL;
svn_error_t *err;
- svn_boolean_t failed_metadata = FALSE;
- svn_revnum_t failed_revisions = 0;
/* Determine the current youngest revision of the filesystem. */
SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
@@ -2430,20 +2452,8 @@ svn_repos_verify_fs3(svn_repos_t *repos,
}
else if (err)
{
- notify_verification_error(SVN_INVALID_REVNUM, err, notify_func,
- notify_baton, iterpool);
-
- if (!keep_going)
- {
- /* Return the error, the caller doesn't want us to continue. */
- return svn_error_trace(err);
- }
- else
- {
- /* Clear the error and keep going. */
- failed_metadata = TRUE;
- svn_error_clear(err);
- }
+ SVN_ERR(report_error(SVN_INVALID_REVNUM, err, verify_callback,
+ verify_baton, iterpool));
}
if (!metadata_only)
@@ -2463,20 +2473,8 @@ svn_repos_verify_fs3(svn_repos_t *repos,
}
else if (err)
{
- notify_verification_error(rev, err, notify_func, notify_baton,
- iterpool);
-
- if (!keep_going)
- {
- /* Return the error, the caller doesn't want us to continue. */
- return svn_error_trace(err);
- }
- else
- {
- /* Clear the error and keep going. */
- ++failed_revisions;
- svn_error_clear(err);
- }
+ SVN_ERR(report_error(rev, err, verify_callback, verify_baton,
+ iterpool));
}
else if (notify_func)
{
@@ -2495,40 +2493,5 @@ svn_repos_verify_fs3(svn_repos_t *repos,
svn_pool_destroy(iterpool);
- /* Summarize the results. */
- if (failed_metadata || 0 != failed_revisions)
- {
- const char *const repos_path =
- svn_dirent_local_style(svn_repos_path(repos, pool), pool);
-
- if (0 == failed_revisions)
- {
- return svn_error_createf(
- SVN_ERR_REPOS_VERIFY_FAILED, NULL,
- _("Metadata verification failed on repository '%s'"),
- repos_path);
- }
- else
- {
- const char* format_string;
-
- if (failed_metadata)
- format_string = apr_psprintf(
- pool, _("Verification of metadata and"
- " %%%s out of %%%s revisions"
- " failed on repository '%%s'"),
- SVN_REVNUM_T_FMT, SVN_REVNUM_T_FMT);
- else
- format_string = apr_psprintf(
- pool, _("Verification of %%%s out of %%%s revisions"
- " failed on repository '%%s'"),
- SVN_REVNUM_T_FMT, SVN_REVNUM_T_FMT);
-
- return svn_error_createf(
- SVN_ERR_REPOS_VERIFY_FAILED, NULL, format_string,
- failed_revisions, end_rev - start_rev + 1, repos_path);
- }
- }
-
return SVN_NO_ERROR;
}
Modified: subversion/branches/fsx-1.10/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_repos/fs-wrap.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_repos/fs-wrap.c Thu Aug 6 14:01:38 2015
@@ -975,15 +975,18 @@ pack_notify_func(void *baton,
{
struct pack_notify_baton *pnb = baton;
svn_repos_notify_t *notify;
+ svn_repos_notify_action_t repos_action;
/* Simple conversion works for these values. */
SVN_ERR_ASSERT(pack_action >= svn_fs_pack_notify_start
- && pack_action <= svn_fs_pack_notify_end_revprop);
+ && pack_action <= svn_fs_pack_notify_noop);
- notify = svn_repos_notify_create(pack_action
- + svn_repos_notify_pack_shard_start
- - svn_fs_pack_notify_start,
- pool);
+ repos_action = pack_action == svn_fs_pack_notify_noop
+ ? svn_repos_notify_pack_noop
+ : pack_action + svn_repos_notify_pack_shard_start
+ - svn_fs_pack_notify_start;
+
+ notify = svn_repos_notify_create(repos_action, pool);
notify->shard = shard;
pnb->notify_func(pnb->notify_baton, notify, pool);
Modified: subversion/branches/fsx-1.10/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_repos/load-fs-vtable.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_repos/load-fs-vtable.c Thu Aug 6 14:01:38 2015
@@ -1271,3 +1271,215 @@ svn_repos_load_fs5(svn_repos_t *repos,
return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE,
cancel_func, cancel_baton, pool);
}
+
+/*----------------------------------------------------------------------*/
+
+/** The same functionality for revprops only **/
+
+/* Implement svn_repos_parse_fns3_t.new_revision_record.
+ *
+ * Because the revision is supposed to already exist, we don't need to
+ * start transactions etc. */
+static svn_error_t *
+revprops_new_revision_record(void **revision_baton,
+ apr_hash_t *headers,
+ void *parse_baton,
+ apr_pool_t *pool)
+{
+ struct parse_baton *pb = parse_baton;
+ struct revision_baton *rb;
+
+ rb = make_revision_baton(headers, pb, pool);
+
+ /* If we're skipping this revision, try to notify someone. */
+ if (rb->skipped && pb->notify_func)
+ {
+ /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
+ svn_repos_notify_t *notify = svn_repos_notify_create(
+ svn_repos_notify_load_skipped_rev,
+ pb->notify_pool);
+
+ notify->old_revision = rb->rev;
+ pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
+ svn_pool_clear(pb->notify_pool);
+ }
+
+ /* If we're parsing revision 0, only the revision props are (possibly)
+ interesting to us: when loading the stream into an empty
+ filesystem, then we want new filesystem's revision 0 to have the
+ same props. Otherwise, we just ignore revision 0 in the stream. */
+
+ *revision_baton = rb;
+ return SVN_NO_ERROR;
+}
+
+/* Implement svn_repos_parse_fns3_t.close_revision.
+ *
+ * Simply set the revprops we previously parsed and send notifications.
+ * This is the place where we will detect missing revisions. */
+static svn_error_t *
+revprops_close_revision(void *baton)
+{
+ struct revision_baton *rb = baton;
+ struct parse_baton *pb = rb->pb;
+ apr_hash_t *orig_props;
+ apr_hash_t *new_props;
+ apr_array_header_t *diff;
+ int i;
+
+ /* If we're skipping this revision we're done here. */
+ if (rb->skipped)
+ return SVN_NO_ERROR;
+
+ /* If the dumpstream doesn't have an 'svn:date' property and we
+ aren't ignoring the dates in the dumpstream altogether, remove
+ any 'svn:date' revision property that was set by FS layer when
+ the TXN was created. */
+ if (! (pb->ignore_dates || rb->datestamp))
+ {
+ svn_prop_t *prop = &APR_ARRAY_PUSH(rb->revprops, svn_prop_t);
+ prop->name = SVN_PROP_REVISION_DATE;
+ prop->value = NULL;
+ }
+
+ SVN_ERR(svn_fs_revision_proplist(&orig_props, pb->fs, rb->rev, rb->pool));
+ new_props = svn_prop_array_to_hash(rb->revprops, rb->pool);
+ SVN_ERR(svn_prop_diffs(&diff, new_props, orig_props, rb->pool));
+
+ for (i = 0; i < diff->nelts; i++)
+ {
+ const svn_prop_t *prop = &APR_ARRAY_IDX(diff, i, svn_prop_t);
+
+ SVN_ERR(change_rev_prop(pb->repos, rb->rev, prop->name, prop->value,
+ pb->validate_props, rb->pool));
+ }
+
+ if (pb->notify_func)
+ {
+ /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
+ svn_repos_notify_t *notify = svn_repos_notify_create(
+ svn_repos_notify_load_revprop_set,
+ pb->notify_pool);
+
+ notify->new_revision = rb->rev;
+ notify->old_revision = SVN_INVALID_REVNUM;
+ pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
+ svn_pool_clear(pb->notify_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Set *CALLBACKS and *PARSE_BATON to a vtable parser which commits new
+ * revisions to the fs in REPOS. Allocate the objects in RESULT_POOL.
+ *
+ * START_REV and END_REV act as filters, the lower and upper (inclusive)
+ * range values of revisions in DUMPSTREAM which will be loaded. Either
+ * both of these values are #SVN_INVALID_REVNUM (in which case no
+ * revision-based filtering occurs at all), or both are valid revisions
+ * (where START_REV is older than or equivalent to END_REV).
+ *
+ * START_REV and END_REV act as filters, the lower and upper (inclusive)
+ * range values of revisions which will
+ * be loaded. Either both of these values are #SVN_INVALID_REVNUM (in
+ * which case no revision-based filtering occurs at all), or both are
+ * valid revisions (where START_REV is older than or equivalent to
+ * END_REV). They refer to dump stream revision numbers rather than
+ * committed revision numbers.
+ *
+ * If VALIDATE_PROPS is set, then validate Subversion revision properties
+ * (those in the svn: namespace) against established rules for those things.
+ *
+ * If IGNORE_DATES is set, ignore any revision datestamps found in
+ * DUMPSTREAM, keeping whatever timestamps the revisions currently have.
+ */
+static svn_error_t *
+build_revprop_parser(const svn_repos_parse_fns3_t **callbacks,
+ void **parse_baton,
+ svn_repos_t *repos,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_boolean_t validate_props,
+ svn_boolean_t ignore_dates,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ apr_pool_t *result_pool)
+{
+ svn_repos_parse_fns3_t *parser = apr_pcalloc(result_pool, sizeof(*parser));
+ struct parse_baton *pb = apr_pcalloc(result_pool, sizeof(*pb));
+
+ SVN_ERR_ASSERT((SVN_IS_VALID_REVNUM(start_rev) &&
+ SVN_IS_VALID_REVNUM(end_rev))
+ || ((! SVN_IS_VALID_REVNUM(start_rev)) &&
+ (! SVN_IS_VALID_REVNUM(end_rev))));
+ if (SVN_IS_VALID_REVNUM(start_rev))
+ SVN_ERR_ASSERT(start_rev <= end_rev);
+
+ parser->magic_header_record = magic_header_record;
+ parser->uuid_record = uuid_record;
+ parser->new_revision_record = revprops_new_revision_record;
+ parser->new_node_record = NULL;
+ parser->set_revision_property = set_revision_property;
+ parser->set_node_property = NULL;
+ parser->remove_node_props = NULL;
+ parser->set_fulltext = NULL;
+ parser->close_node = NULL;
+ parser->close_revision = revprops_close_revision;
+ parser->delete_node_property = NULL;
+ parser->apply_textdelta = NULL;
+
+ pb->repos = repos;
+ pb->fs = svn_repos_fs(repos);
+ pb->use_history = FALSE;
+ pb->validate_props = validate_props;
+ pb->notify_func = notify_func;
+ pb->notify_baton = notify_baton;
+ pb->uuid_action = svn_repos_load_uuid_ignore; /* Never touch the UUID. */
+ pb->parent_dir = NULL;
+ pb->pool = result_pool;
+ pb->notify_pool = svn_pool_create(result_pool);
+ pb->rev_map = NULL;
+ pb->oldest_dumpstream_rev = SVN_INVALID_REVNUM;
+ pb->last_rev_mapped = SVN_INVALID_REVNUM;
+ pb->start_rev = start_rev;
+ pb->end_rev = end_rev;
+ pb->use_pre_commit_hook = FALSE;
+ pb->use_post_commit_hook = FALSE;
+ pb->ignore_dates = ignore_dates;
+
+ *callbacks = parser;
+ *parse_baton = pb;
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_repos_load_fs_revprops(svn_repos_t *repos,
+ svn_stream_t *dumpstream,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_boolean_t validate_props,
+ svn_boolean_t ignore_dates,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ const svn_repos_parse_fns3_t *parser;
+ void *parse_baton;
+
+ /* This is really simple. */
+
+ SVN_ERR(build_revprop_parser(&parser, &parse_baton,
+ repos,
+ start_rev, end_rev,
+ validate_props,
+ ignore_dates,
+ notify_func,
+ notify_baton,
+ scratch_pool));
+
+ return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE,
+ cancel_func, cancel_baton, scratch_pool);
+}
Modified: subversion/branches/fsx-1.10/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_repos/rev_hunt.c?rev=1694500&r1=1694499&r2=1694500&view=diff
==============================================================================
--- subversion/branches/fsx-1.10/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/fsx-1.10/subversion/libsvn_repos/rev_hunt.c Thu Aug 6 14:01:38 2015
@@ -710,23 +710,6 @@ svn_repos_trace_node_locations(svn_fs_t
if (! prev_path)
break;
- if (authz_read_func)
- {
- svn_boolean_t readable;
- svn_fs_root_t *tmp_root;
-
- SVN_ERR(svn_fs_revision_root(&tmp_root, fs, revision, currpool));
- SVN_ERR(authz_read_func(&readable, tmp_root, path,
- authz_read_baton, currpool));
- if (! readable)
- {
- svn_pool_destroy(lastpool);
- svn_pool_destroy(currpool);
-
- return SVN_NO_ERROR;
- }
- }
-
/* Assign the current path to all younger revisions until we reach
the copy target rev. */
while ((revision_ptr < revision_ptr_end)
@@ -749,6 +732,20 @@ svn_repos_trace_node_locations(svn_fs_t
path = prev_path;
revision = prev_rev;
+ if (authz_read_func)
+ {
+ svn_boolean_t readable;
+ SVN_ERR(svn_fs_revision_root(&root, fs, revision, currpool));
+ SVN_ERR(authz_read_func(&readable, root, path,
+ authz_read_baton, currpool));
+ if (!readable)
+ {
+ svn_pool_destroy(lastpool);
+ svn_pool_destroy(currpool);
+ return SVN_NO_ERROR;
+ }
+ }
+
/* Clear last pool and switch. */
svn_pool_clear(lastpool);
tmppool = lastpool;