You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/03/05 21:34:28 UTC
svn commit: r1297221 [2/7] - in /subversion/branches/ev2-export: ./
build/ac-macros/ build/generator/ build/win32/ notes/
subversion/bindings/javahl/native/
subversion/bindings/javahl/tests/org/apache/subversion/javahl/
subversion/bindings/swig/include...
Modified: subversion/branches/ev2-export/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/util.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/util.c Mon Mar 5 20:34:22 2012
@@ -240,3 +240,163 @@ svn_client__assert_homogeneous_target_ty
return SVN_NO_ERROR;
}
+
+struct shim_callbacks_baton
+{
+ svn_wc_context_t *wc_ctx;
+ const char *anchor_abspath;
+};
+
+static svn_error_t *
+rationalize_shim_path(const char **local_abspath,
+ struct shim_callbacks_baton *scb,
+ const char *path,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (svn_path_is_url(path))
+ {
+ /* This is a copyfrom URL */
+ const char *wcroot_abspath;
+ const char *wcroot_url;
+ const char *relpath;
+
+ SVN_ERR(svn_wc__get_wc_root(&wcroot_abspath, scb->wc_ctx,
+ scb->anchor_abspath,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_wc__node_get_url(&wcroot_url, scb->wc_ctx, wcroot_abspath,
+ scratch_pool, scratch_pool));
+ relpath = svn_uri_skip_ancestor(wcroot_url, path, scratch_pool);
+ *local_abspath = svn_dirent_join(wcroot_abspath, relpath, result_pool);
+ }
+ else
+ *local_abspath = svn_dirent_join(scb->anchor_abspath, path, result_pool);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct shim_callbacks_baton *scb = baton;
+ const char *local_abspath;
+
+ /* Early out: if we didn't get an anchor_abspath, it means we don't have a
+ working copy, and hence no method of fetching the requisite information. */
+ if (!scb->anchor_abspath)
+ {
+ *props = apr_hash_make(result_pool);
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(rationalize_shim_path(&local_abspath, scb, path, scratch_pool,
+ scratch_pool));
+
+ SVN_ERR(svn_wc_get_pristine_props(props, scb->wc_ctx, local_abspath,
+ result_pool, scratch_pool));
+
+ if (!*props)
+ *props = apr_hash_make(result_pool);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *scratch_pool)
+{
+ struct shim_callbacks_baton *scb = baton;
+ svn_node_kind_t node_kind;
+ const char *local_abspath;
+
+ /* Early out: if we didn't get an anchor_abspath, it means we don't have a
+ working copy, and hence no method of fetching the requisite information. */
+ if (!scb->anchor_abspath)
+ {
+ *kind = svn_kind_unknown;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(rationalize_shim_path(&local_abspath, scb, path, scratch_pool,
+ scratch_pool));
+
+ SVN_ERR(svn_wc_read_kind(&node_kind, scb->wc_ctx, local_abspath, FALSE,
+ scratch_pool));
+ *kind = svn__kind_from_node_kind(node_kind, FALSE);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_base_func(const char **filename,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct shim_callbacks_baton *scb = baton;
+ const char *local_abspath;
+ svn_stream_t *pristine_stream;
+ svn_stream_t *temp_stream;
+ svn_error_t *err;
+
+ /* Early out: if we didn't get an anchor_abspath, it means we don't have a
+ working copy, and hence no method of fetching the requisite information. */
+ if (!scb->anchor_abspath)
+ {
+ *filename = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(rationalize_shim_path(&local_abspath, scb, path, scratch_pool,
+ scratch_pool));
+
+ err = svn_wc_get_pristine_contents2(&pristine_stream, scb->wc_ctx,
+ local_abspath, scratch_pool,
+ scratch_pool);
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ *filename = NULL;
+ return SVN_NO_ERROR;
+ }
+ else if (err)
+ return svn_error_trace(err);
+
+ SVN_ERR(svn_stream_open_unique(&temp_stream, filename, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, scratch_pool));
+ SVN_ERR(svn_stream_copy3(pristine_stream, temp_stream, NULL, NULL,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_delta_shim_callbacks_t *
+svn_client__get_shim_callbacks(svn_wc_context_t *wc_ctx,
+ const char *anchor_abspath,
+ apr_pool_t *result_pool)
+{
+ svn_delta_shim_callbacks_t *callbacks =
+ svn_delta_shim_callbacks_default(result_pool);
+ struct shim_callbacks_baton *scb = apr_pcalloc(result_pool, sizeof(*scb));
+
+ scb->wc_ctx = wc_ctx;
+ scb->anchor_abspath = apr_pstrdup(result_pool, anchor_abspath);
+
+ callbacks->fetch_props_func = fetch_props_func;
+ callbacks->fetch_kind_func = fetch_kind_func;
+ callbacks->fetch_base_func = fetch_base_func;
+ callbacks->fetch_baton = scb;
+
+ return callbacks;
+}
Modified: subversion/branches/ev2-export/subversion/libsvn_delta/compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/compat.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/compat.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/compat.c Mon Mar 5 20:34:22 2012
@@ -108,7 +108,11 @@ svn_compat_wrap_file_rev_handler(svn_fil
struct ev2_edit_baton
{
svn_editor_t *editor;
+
apr_hash_t *paths;
+ apr_array_header_t *path_order;
+ int paths_processed;
+
apr_pool_t *edit_pool;
struct svn_delta__extra_baton *exb;
svn_boolean_t closed;
@@ -200,10 +204,12 @@ add_action(struct ev2_edit_baton *eb,
if (action_list == NULL)
{
+ const char *path_dup = apr_pstrdup(eb->edit_pool, path);
+
action_list = apr_array_make(eb->edit_pool, 1,
sizeof(struct path_action *));
- apr_hash_set(eb->paths, apr_pstrdup(eb->edit_pool, path),
- APR_HASH_KEY_STRING, action_list);
+ apr_hash_set(eb->paths, path_dup, APR_HASH_KEY_STRING, action_list);
+ APR_ARRAY_PUSH(eb->path_order, const char *) = path_dup;
}
APR_ARRAY_PUSH(action_list, struct path_action *) = p_action;
@@ -229,7 +235,7 @@ get_children(struct ev2_edit_baton *eb,
/* Sanitize our paths. */
if (*p == '/')
p++;
-
+
/* Find potential children. */
child = svn_relpath_skip_ancestor(path, p);
if (!child || !*child)
@@ -245,7 +251,7 @@ get_children(struct ev2_edit_baton *eb,
return children;
}
-
+
static svn_error_t *
process_actions(void *edit_baton,
@@ -260,7 +266,7 @@ process_actions(void *edit_baton,
svn_boolean_t need_copy = FALSE;
const char *copyfrom_path;
svn_revnum_t copyfrom_rev;
- apr_array_header_t *children;
+ apr_array_header_t *children = NULL;
svn_stream_t *contents = NULL;
svn_checksum_t *checksum = NULL;
svn_revnum_t delete_revnum = SVN_INVALID_REVNUM;
@@ -351,7 +357,7 @@ process_actions(void *edit_baton,
struct path_checksum_args *pca = action->args;
/* We can only set text on files. */
- kind = svn_node_file;
+ kind = svn_kind_file;
SVN_ERR(svn_io_file_checksum2(&checksum, pca->path,
svn_checksum_sha1, scratch_pool));
@@ -463,29 +469,21 @@ run_ev2_actions(void *edit_baton,
apr_pool_t *scratch_pool)
{
struct ev2_edit_baton *eb = edit_baton;
- apr_array_header_t *sorted_hash;
apr_pool_t *iterpool;
- int i;
-
- /* Sort the paths touched by this edit.
- * Ev2 doesn't really have any particular need for depth-first-ness, but
- * we want to ensure all parent directories are handled before children in
- * the case of adds (which does introduce an element of depth-first-ness). */
- sorted_hash = svn_sort__hash(eb->paths, svn_sort_compare_items_as_paths,
- scratch_pool);
iterpool = svn_pool_create(scratch_pool);
- for (i = 0; i < sorted_hash->nelts; i++)
- {
- svn_sort__item_t *item = &APR_ARRAY_IDX(sorted_hash, i, svn_sort__item_t);
- apr_array_header_t *actions = item->value;
- const char *path = item->key;
+
+ /* Possibly pick up where we left off. Ocassionally, we do some of these
+ as part of close_edit() and then some more as part of abort_edit() */
+ for (; eb->paths_processed < eb->path_order->nelts; ++eb->paths_processed)
+ {
+ const char *path = APR_ARRAY_IDX(eb->path_order, eb->paths_processed,
+ const char *);
+ apr_array_header_t *actions = apr_hash_get(eb->paths, path,
+ APR_HASH_KEY_STRING);
svn_pool_clear(iterpool);
SVN_ERR(process_actions(edit_baton, path, actions, iterpool));
-
- /* Remove this item from the hash. */
- apr_hash_set(eb->paths, path, APR_HASH_KEY_STRING, NULL);
}
svn_pool_destroy(iterpool);
@@ -651,7 +649,7 @@ ev2_absent_directory(const char *path,
{
struct ev2_dir_baton *pb = parent_baton;
svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
-
+
*kind = svn_kind_dir;
SVN_ERR(add_action(pb->eb, path, ACTION_ADD_ABSENT, kind));
@@ -802,7 +800,7 @@ ev2_apply_textdelta(void *file_baton,
&hb->apply_handler, &hb->apply_baton);
hb->pool = handler_pool;
-
+
*handler_baton = hb;
*handler = window_handler;
@@ -854,7 +852,7 @@ ev2_absent_file(const char *path,
{
struct ev2_dir_baton *pb = parent_baton;
svn_kind_t *kind = apr_palloc(pb->eb->edit_pool, sizeof(*kind));
-
+
*kind = svn_kind_file;
SVN_ERR(add_action(pb->eb, path, ACTION_ADD_ABSENT, kind));
@@ -904,7 +902,7 @@ ev2_abort_edit(void *edit_baton,
* - EXB: An 'extra baton' which is used to communicate between the shims.
* Its callbacks should be invoked at the appropriate time by this
* shim.
- */
+ */
svn_error_t *
svn_delta__delta_from_editor(const svn_delta_editor_t **deditor,
void **dedit_baton,
@@ -942,6 +940,7 @@ svn_delta__delta_from_editor(const svn_d
eb->editor = editor;
eb->paths = apr_hash_make(pool);
+ eb->path_order = apr_array_make(pool, 1, sizeof(const char *));
eb->edit_pool = pool;
eb->found_abs_paths = found_abs_paths;
*eb->found_abs_paths = FALSE;
@@ -1122,7 +1121,7 @@ build(struct editor_baton *eb,
actual structures, not pointers to them. */
svn_prop_t *prop = &APR_ARRAY_IDX(propdiffs, i, svn_prop_t);
if (!prop->value)
- APR_ARRAY_PUSH(operation->prop_dels, const char *) =
+ APR_ARRAY_PUSH(operation->prop_dels, const char *) =
apr_pstrdup(eb->edit_pool, prop->name);
else
apr_hash_set(operation->prop_mods,
@@ -1551,7 +1550,8 @@ drive_tree(struct operation *op,
{
/* Open or create our baton. */
if (op->operation == OP_OPEN || op->operation == OP_PROPSET)
- SVN_ERR(editor->open_directory(path, parent_op->baton, op->base_revision,
+ SVN_ERR(editor->open_directory(path, parent_op->baton,
+ op->base_revision,
scratch_pool, &op->baton));
else if (op->operation == OP_ADD || op->operation == OP_REPLACE)
@@ -1591,7 +1591,7 @@ drive_tree(struct operation *op,
I don't know that that's a valid assumption... */
void *file_baton = NULL;
-
+
/* Open or create our baton. */
if (op->operation == OP_OPEN || op->operation == OP_PROPSET)
SVN_ERR(editor->open_file(path, parent_op->baton, op->base_revision,
@@ -1666,7 +1666,7 @@ drive_root(struct operation *root,
svn_pool_clear(iterpool);
SVN_ERR(drive_tree(child, root, editor, make_abs_paths, iterpool));
}
-
+
/* We need to close the root directory, but leave it to our caller to call
close_ or abort_edit(). */
SVN_ERR(editor->close_directory(root->baton, scratch_pool));
Modified: subversion/branches/ev2-export/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/editor.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/editor.c Mon Mar 5 20:34:22 2012
@@ -33,7 +33,7 @@
/* This enables runtime checks of the editor API constraints. This may
introduce additional memory and runtime overhead, and should not be used
in production builds.
-
+
### Remove before release? */
#define ENABLE_ORDERING_CHECK
#endif
@@ -420,7 +420,8 @@ svn_editor_add_file(svn_editor_t *editor
{
svn_error_t *err = SVN_NO_ERROR;
- SVN_ERR_ASSERT(checksum != NULL);
+ SVN_ERR_ASSERT(checksum != NULL
+ && checksum->kind == SVN_EDITOR_CHECKSUM_KIND);
SVN_ERR_ASSERT(contents != NULL);
SVN_ERR_ASSERT(props != NULL);
SHOULD_NOT_BE_FINISHED(editor);
@@ -539,6 +540,8 @@ svn_editor_alter_file(svn_editor_t *edit
SVN_ERR_ASSERT((checksum != NULL && contents != NULL)
|| (checksum == NULL && contents == NULL));
SVN_ERR_ASSERT(props != NULL || checksum != NULL);
+ if (checksum)
+ SVN_ERR_ASSERT(checksum->kind == SVN_EDITOR_CHECKSUM_KIND);
SHOULD_NOT_BE_FINISHED(editor);
SHOULD_ALLOW_ALTER(editor, relpath);
Modified: subversion/branches/ev2-export/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/svndiff.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/svndiff.c Mon Mar 5 20:34:22 2012
@@ -645,7 +645,7 @@ decode_window(svn_txdelta_window_t *wind
svn_stringbuf_t *ndout = svn_stringbuf_create_empty(pool);
/* these may in fact simply return references to insend */
-
+
SVN_ERR(zlib_decode(insend, newlen, ndout,
SVN_DELTA_WINDOW_SIZE));
SVN_ERR(zlib_decode(data, insend - data, instout,
Modified: subversion/branches/ev2-export/subversion/libsvn_delta/text_delta.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/text_delta.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/text_delta.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/text_delta.c Mon Mar 5 20:34:22 2012
@@ -291,7 +291,7 @@ svn_txdelta__remove_copy(svn_txdelta__op
/* we can't modify svn_txdelta_target ops -> stop there */
if (op->action_code == svn_txdelta_target)
break;
-
+
/* handle the case that we cannot remove the op entirely */
if (op->length + len > max_len)
{
@@ -303,18 +303,18 @@ svn_txdelta__remove_copy(svn_txdelta__op
op->length -= max_len - len;
len = max_len;
}
-
+
break;
}
-
+
/* drop the op entirely */
if (op->action_code == svn_txdelta_new)
build_baton->new_data->len -= op->length;
-
+
len += op->length;
--build_baton->num_ops;
}
-
+
return len;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_delta/xdelta.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/xdelta.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/xdelta.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/xdelta.c Mon Mar 5 20:34:22 2012
@@ -257,14 +257,18 @@ reverse_match_length(const char *a, cons
break;
pos -= sizeof(apr_size_t);
-
+
#endif
+ /* If we find a mismatch at -pos, pos-1 characters matched.
+ */
while (++pos <= max_len)
- if (a[-pos] != b[-pos])
- break;
-
- return pos-1;
+ if (a[0-pos] != b[0-pos])
+ return pos - 1;
+
+ /* No mismatch found -> at least MAX_LEN machting chars.
+ */
+ return max_len;
}
@@ -390,7 +394,7 @@ compute_delta(svn_txdelta__ops_baton_t *
apr_size_t lo = 0, pending_insert_start = 0;
/* Optimization: directly compare window starts. If more than 4
- * bytes match, we can immediately create a matching windows.
+ * bytes match, we can immediately create a matching windows.
* Shorter sequences result in a net data increase. */
lo = match_length(a, b, asize > bsize ? bsize : asize);
if ((lo > 4) || (lo == bsize))
@@ -442,7 +446,7 @@ compute_delta(svn_txdelta__ops_baton_t *
svn_txdelta__insert_op(build_baton, svn_txdelta_new,
0, lo - pending_insert_start,
b + pending_insert_start, pool);
- else
+ else
{
/* the match borders on the previous op. Maybe, we found a
* match that is better than / overlapping the previous one. */
Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c Mon Mar 5 20:34:22 2012
@@ -155,7 +155,7 @@ get_library_vtable_direct(fs_library_vta
/* Invoke the FS module's initfunc function with the common
pool protected by a lock. */
- SVN_MUTEX__WITH_LOCK(common_pool_lock,
+ SVN_MUTEX__WITH_LOCK(common_pool_lock,
initfunc(my_version, vtable, common_pool));
}
fs_version = (*vtable)->get_version();
@@ -357,7 +357,7 @@ svn_fs_create(svn_fs_t **fs_p, const cha
/* Perform the actual creation. */
*fs_p = fs_new(fs_config, pool);
-
+
SVN_MUTEX__WITH_LOCK(common_pool_lock,
vtable->create(*fs_p, path, pool, common_pool));
return SVN_NO_ERROR;
@@ -394,7 +394,9 @@ svn_error_t *
svn_fs_verify(const char *path,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *pool)
+ svn_revnum_t start,
+ svn_revnum_t end,
+ apr_pool_t *pool)
{
fs_library_vtable_t *vtable;
svn_fs_t *fs;
@@ -404,7 +406,7 @@ svn_fs_verify(const char *path,
SVN_MUTEX__WITH_LOCK(common_pool_lock,
vtable->verify_fs(fs, path, cancel_func, cancel_baton,
- pool, common_pool));
+ start, end, pool, common_pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h Mon Mar 5 20:34:22 2012
@@ -90,6 +90,8 @@ typedef struct fs_library_vtable_t
svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path,
/* ### notification? */
svn_cancel_func_t cancel_func, void *cancel_baton,
+ svn_revnum_t start,
+ svn_revnum_t end,
apr_pool_t *pool,
apr_pool_t *common_pool);
svn_error_t *(*delete_fs)(const char *path, apr_pool_t *pool);
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/env.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/env.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/env.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/env.c Mon Mar 5 20:34:22 2012
@@ -378,7 +378,7 @@ bdb_init_cb(void *baton, apr_pool_t *poo
{
bdb_cache_pool = svn_pool_create(pool);
bdb_cache = apr_hash_make(bdb_cache_pool);
-
+
SVN_ERR(svn_mutex__init(&bdb_cache_lock, TRUE, bdb_cache_pool));
apr_pool_cleanup_register(bdb_cache_pool, NULL, clear_cache,
apr_pool_cleanup_null);
@@ -493,7 +493,7 @@ static svn_error_t *
svn_fs_bdb__close_internal(bdb_env_t *bdb)
{
svn_error_t *err = SVN_NO_ERROR;
-
+
if (--bdb->refcount != 0)
{
/* If the environment is panicked and automatic recovery is not
@@ -543,7 +543,7 @@ svn_fs_bdb__close(bdb_env_baton_t *bdb_b
/* This may run during final pool cleanup when the lock is NULL. */
SVN_MUTEX__WITH_LOCK(bdb_cache_lock, svn_fs_bdb__close_internal(bdb));
-
+
return SVN_NO_ERROR;
}
@@ -587,7 +587,7 @@ cleanup_env_baton(void *data)
static svn_error_t *
-svn_fs_bdb__open_internal(bdb_env_baton_t **bdb_batonp,
+svn_fs_bdb__open_internal(bdb_env_baton_t **bdb_batonp,
const char *path,
u_int32_t flags, int mode,
apr_pool_t *pool)
@@ -643,7 +643,7 @@ svn_fs_bdb__open_internal(bdb_env_baton_
svn_error_clear(bdb_close(bdb));
return svn_error_trace(err);
}
-
+
apr_hash_set(bdb_cache, &bdb->key, sizeof bdb->key, bdb);
bdb->flags = flags;
bdb->refcount = 1;
@@ -669,11 +669,11 @@ svn_fs_bdb__open(bdb_env_baton_t **bdb_b
u_int32_t flags, int mode,
apr_pool_t *pool)
{
- SVN_MUTEX__WITH_LOCK(bdb_cache_lock,
- svn_fs_bdb__open_internal(bdb_batonp,
- path,
- flags,
- mode,
+ SVN_MUTEX__WITH_LOCK(bdb_cache_lock,
+ svn_fs_bdb__open_internal(bdb_batonp,
+ path,
+ flags,
+ mode,
pool));
return SVN_NO_ERROR;
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c Mon Mar 5 20:34:22 2012
@@ -333,9 +333,10 @@ bdb_write_config(svn_fs_t *fs)
"#\n"
"# Make sure you read the documentation at:\n"
"#\n"
- "# http://www.oracle.com/technology/documentation/berkeley-db/db/ref/lock/max.html\n"
+ "# http://docs.oracle.com/cd/E17076_02/html/programmer_reference/lock_max.html\n"
"#\n"
"# before tweaking these values.\n"
+ "#\n"
"set_lk_max_locks 2000\n"
"set_lk_max_lockers 2000\n"
"set_lk_max_objects 2000\n"
@@ -344,9 +345,9 @@ bdb_write_config(svn_fs_t *fs)
"#\n"
"# Make sure you read the documentation at:\n"
"#\n"
- "# http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_lg_bsize.html\n"
- "# http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/env_set_lg_max.html\n"
- "# http://www.oracle.com/technology/documentation/berkeley-db/db/ref/log/limits.html\n"
+ "# http://docs.oracle.com/cd/E17076_02/html/api_reference/C/envset_lg_bsize.html\n"
+ "# http://docs.oracle.com/cd/E17076_02/html/api_reference/C/envset_lg_max.html\n"
+ "# http://docs.oracle.com/cd/E17076_02/html/programmer_reference/log_limits.html\n"
"#\n"
"# Increase the size of the in-memory log buffer from the default\n"
"# of 32 Kbytes to 256 Kbytes. Decrease the log file size from\n"
@@ -354,24 +355,28 @@ bdb_write_config(svn_fs_t *fs)
"# space required for hot backups. The size of the log file must be\n"
"# at least four times the size of the in-memory log buffer.\n"
"#\n"
- "# Note: Decreasing the in-memory buffer size below 256 Kbytes\n"
- "# will hurt commit performance. For details, see this post from\n"
- "# Daniel Berlin <da...@dberlin.org>:\n"
+ "# Note: Decreasing the in-memory buffer size below 256 Kbytes will hurt\n"
+ "# hurt commit performance. For details, see:\n"
+ "#\n"
+ "# http://svn.haxx.se/dev/archive-2002-02/0141.shtml\n"
"#\n"
- "# http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgId=161960\n"
"set_lg_bsize 262144\n"
"set_lg_max 1048576\n"
"#\n"
"# If you see \"log region out of memory\" errors, bump lg_regionmax.\n"
- "# See http://www.oracle.com/technology/documentation/berkeley-db/db/ref/log/config.html\n"
- "# and http://svn.haxx.se/users/archive-2004-10/1001.shtml for more.\n"
+ "# For more information, see:\n"
+ "#\n"
+ "# http://docs.oracle.com/cd/E17076_02/html/programmer_reference/log_config.html\n"
+ "# http://svn.haxx.se/users/archive-2004-10/1000.shtml\n"
+ "#\n"
"set_lg_regionmax 131072\n"
"#\n"
/* ### Configure this with "svnadmin create --bdb-cache-size" */
"# The default cache size in BDB is only 256k. As explained in\n"
- "# http://svn.haxx.se/dev/archive-2004-12/0369.shtml, this is too\n"
+ "# http://svn.haxx.se/dev/archive-2004-12/0368.shtml, this is too\n"
"# small for most applications. Bump this number if \"db_stat -m\"\n"
"# shows too many cache misses.\n"
+ "#\n"
"set_cachesize 0 1048576 1\n";
/* Run-time configurable options.
@@ -397,11 +402,12 @@ bdb_write_config(svn_fs_t *fs)
"# Disable fsync of log files on transaction commit. Read the\n"
"# documentation about DB_TXN_NOSYNC at:\n"
"#\n"
- "# http://www.oracle.com/technology/documentation/berkeley-db/db/ref/log/config.html\n"
+ "# http://docs.oracle.com/cd/E17076_02/html/programmer_reference/log_config.html\n"
"#\n"
- "# [requires Berkeley DB 4.0]\n",
+ "# [requires Berkeley DB 4.0]\n"
+ "#\n",
/* inactive */
- "# set_flags DB_TXN_NOSYNC\n",
+ "#set_flags DB_TXN_NOSYNC\n",
/* active */
"set_flags DB_TXN_NOSYNC\n" },
/* Controlled by "svnadmin create --bdb-log-keep" */
@@ -411,11 +417,12 @@ bdb_write_config(svn_fs_t *fs)
"# Enable automatic removal of unused transaction log files.\n"
"# Read the documentation about DB_LOG_AUTOREMOVE at:\n"
"#\n"
- "# http://www.oracle.com/technology/documentation/berkeley-db/db/ref/log/config.html\n"
+ "# http://docs.oracle.com/cd/E17076_02/html/programmer_reference/log_config.html\n"
"#\n"
- "# [requires Berkeley DB 4.2]\n",
+ "# [requires Berkeley DB 4.2]\n"
+ "#\n",
/* inactive */
- "# set_flags DB_LOG_AUTOREMOVE\n",
+ "#set_flags DB_LOG_AUTOREMOVE\n",
/* active */
"set_flags DB_LOG_AUTOREMOVE\n" },
};
@@ -876,6 +883,8 @@ static svn_error_t *
base_verify(svn_fs_t *fs, const char *path,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_revnum_t start,
+ svn_revnum_t end,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/notes/structure
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/notes/structure?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/notes/structure (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/notes/structure Mon Mar 5 20:34:22 2012
@@ -104,8 +104,8 @@ structure summary" section of this docum
NODE-REVISION: how we represent a node revision
We represent a given revision of a file or directory node using a list
-skel (see skel.h for an explanation of skels). A node revision skel
-has the form:
+skel (see include/private/svn_skel.h for an explanation of skels).
+A node revision skel has the form:
(HEADER PROP-KEY KIND-SPECIFIC ...)
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/caching.c Mon Mar 5 20:34:22 2012
@@ -339,6 +339,27 @@ svn_fs_fs__initialize_caches(svn_fs_t *f
SVN_ERR(init_callbacks(ffd->fulltext_cache, fs, no_handler, pool));
+ /* initialize revprop cache, if full-text caching has been enabled */
+ if (cache_fulltexts)
+ {
+ SVN_ERR(create_cache(&(ffd->revprop_cache),
+ NULL,
+ membuffer,
+ 0, 0, /* Do not use inprocess cache */
+ svn_fs_fs__serialize_properties,
+ svn_fs_fs__deserialize_properties,
+ APR_HASH_KEY_STRING,
+ apr_pstrcat(pool, prefix, "REVPROP",
+ (char *)NULL),
+ fs->pool));
+ }
+ else
+ {
+ ffd->revprop_cache = NULL;
+ }
+
+ SVN_ERR(init_callbacks(ffd->revprop_cache, fs, no_handler, pool));
+
/* initialize txdelta window cache, if that has been enabled */
if (cache_txdeltas)
{
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c Mon Mar 5 20:34:22 2012
@@ -92,7 +92,7 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
/* ... not to mention locking the txn-current file. */
- SVN_ERR(svn_mutex__init(&ffsd->txn_current_lock,
+ SVN_ERR(svn_mutex__init(&ffsd->txn_current_lock,
SVN_FS_FS__USE_LOCK_MUTEX, common_pool));
SVN_ERR(svn_mutex__init(&ffsd->txn_list_lock,
@@ -243,6 +243,8 @@ static svn_error_t *
fs_verify(svn_fs_t *fs, const char *path,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_revnum_t start,
+ svn_revnum_t end,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
@@ -251,7 +253,7 @@ fs_verify(svn_fs_t *fs, const char *path
SVN_ERR(svn_fs_fs__open(fs, path, pool));
SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
SVN_ERR(fs_serialized_init(fs, common_pool, pool));
- return svn_fs_fs__verify(fs, cancel_func, cancel_baton, pool);
+ return svn_fs_fs__verify(fs, cancel_func, cancel_baton, start, end, pool);
}
static svn_error_t *
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.h Mon Mar 5 20:34:22 2012
@@ -60,6 +60,8 @@ extern "C" {
#define PATH_LOCKS_DIR "locks" /* Directory of locks */
#define PATH_MIN_UNPACKED_REV "min-unpacked-rev" /* Oldest revision which
has not been packed. */
+#define PATH_REVPROP_GEN "revprop-gen" /* File containing the
+ revprop change counter */
/* If you change this, look at tests/svn_test_fs.c(maybe_install_fsfs_conf) */
#define PATH_CONFIG "fsfs.conf" /* Configuration */
@@ -198,7 +200,8 @@ typedef struct fs_fs_shared_data_t
apr_pool_t *common_pool;
} fs_fs_shared_data_t;
-/* Private (non-shared) FSFS-specific data for each svn_fs_t object. */
+/* Private (non-shared) FSFS-specific data for each svn_fs_t object.
+ Any caches in here may be NULL. */
typedef struct fs_fs_data_t
{
/* The format number of this FS. */
@@ -224,17 +227,28 @@ typedef struct fs_fs_data_t
(svn_fs_id_t *). (Not threadsafe.) */
svn_cache__t *rev_root_id_cache;
- /* DAG node cache for immutable nodes */
+ /* DAG node cache for immutable nodes. Maps (revision, fspath)
+ to (dag_node_t *). */
svn_cache__t *rev_node_cache;
/* A cache of the contents of immutable directories; maps from
- unparsed FS ID to ###x. */
+ unparsed FS ID to a apr_hash_t * mapping (const char *) dirent
+ names to (svn_fs_dirent_t *). */
svn_cache__t *dir_cache;
/* Fulltext cache; currently only used with memcached. Maps from
- rep key to svn_string_t. */
+ rep key (revision/offset) to svn_string_t. */
svn_cache__t *fulltext_cache;
+ /* Revprop "generation" that is valid for this svn_fs_t.
+ It is the revprop change counter read once from "revprop-gen".
+ Will be read upon first access. 0 means that the value has not
+ been read from disk, yet. */
+ apr_int64_t revprop_generation;
+
+ /* Revision property cache. Maps from (rev,generation) to apr_hash_t. */
+ svn_cache__t *revprop_cache;
+
/* Pack manifest cache; a cache mapping (svn_revnum_t) shard number to
a manifest; and a manifest is a mapping from (svn_revnum_t) revision
number offset within a shard to (apr_off_t) byte-offset in the
@@ -244,7 +258,7 @@ typedef struct fs_fs_data_t
/* Cache for txdelta_window_t objects; the key is (revFilePath, offset) */
svn_cache__t *txdelta_window_cache;
- /* Cache for combined windows as svn_stringbuf_t objects;
+ /* Cache for combined windows as svn_stringbuf_t objects;
the key is (revFilePath, offset) */
svn_cache__t *combined_window_cache;
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c Mon Mar 5 20:34:22 2012
@@ -81,7 +81,7 @@
/* Begin deltification after a node history exceeded this this limit.
Useful values are 4 to 64 with 16 being a good compromise between
computational overhead and pository size savings.
- Should be a power of 2.
+ Should be a power of 2.
Values < 2 will result in standard skip-delta behavior. */
#define SVN_FS_FS_MAX_LINEAR_DELTIFICATION 16
@@ -225,6 +225,12 @@ path_lock(svn_fs_t *fs, apr_pool_t *pool
}
static const char *
+path_revprop_generation(svn_fs_t *fs, apr_pool_t *pool)
+{
+ return svn_dirent_join(fs->path, PATH_REVPROP_GEN, pool);
+}
+
+static const char *
path_rev_packed(svn_fs_t *fs, svn_revnum_t rev, const char *kind,
apr_pool_t *pool)
{
@@ -800,7 +806,7 @@ get_writable_proto_rev_body(svn_fs_t *fs
err = svn_error_compose_create(
err,
unlock_proto_rev_list_locked(fs, txn_id, *lockcookie, pool));
-
+
*lockcookie = NULL;
}
@@ -870,25 +876,39 @@ get_file_offset(apr_off_t *offset_p, apr
}
-/* Check that BUF, a nul-terminated buffer of text from format file PATH,
+/* Check that BUF, a nul-terminated buffer of text from file PATH,
contains only digits at OFFSET and beyond, raising an error if not.
+ TITLE contains a user-visible description of the file, usually the
+ short file name.
Uses POOL for temporary allocation. */
static svn_error_t *
-check_format_file_buffer_numeric(const char *buf, apr_off_t offset,
- const char *path, apr_pool_t *pool)
+check_file_buffer_numeric(const char *buf, apr_off_t offset,
+ const char *path, const char *title,
+ apr_pool_t *pool)
{
const char *p;
for (p = buf + offset; *p; p++)
if (!svn_ctype_isdigit(*p))
return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL,
- _("Format file '%s' contains unexpected non-digit '%c' within '%s'"),
- svn_dirent_local_style(path, pool), *p, buf);
+ _("%s file '%s' contains unexpected non-digit '%c' within '%s'"),
+ title, svn_dirent_local_style(path, pool), *p, buf);
return SVN_NO_ERROR;
}
+/* Check that BUF, a nul-terminated buffer of text from format file PATH,
+ contains only digits at OFFSET and beyond, raising an error if not.
+
+ Uses POOL for temporary allocation. */
+static svn_error_t *
+check_format_file_buffer_numeric(const char *buf, apr_off_t offset,
+ const char *path, apr_pool_t *pool)
+{
+ return check_file_buffer_numeric(buf, offset, path, "Format", pool);
+}
+
/* Read the format number and maximum number of files per directory
from PATH and return them in *PFORMAT and *MAX_FILES_PER_DIR
respectively.
@@ -1548,6 +1568,16 @@ ensure_revision_exists(svn_fs_t *fs,
_("No such revision %ld"), rev);
}
+svn_error_t *
+svn_fs_fs__revision_exists(svn_revnum_t rev,
+ svn_fs_t *fs,
+ apr_pool_t *pool)
+{
+ /* Different order of parameters. */
+ SVN_ERR(ensure_revision_exists(fs, rev, pool));
+ return SVN_NO_ERROR;
+}
+
/* Open the correct revision file for REV. If the filesystem FS has
been packed, *FILE will be set to the packed file; otherwise, set *FILE
to the revision file for REV. Return SVN_ERR_FS_NO_SUCH_REVISION if the
@@ -2677,6 +2707,105 @@ svn_fs_fs__rev_get_root(svn_fs_id_t **ro
return SVN_NO_ERROR;
}
+/* Reads the revprop_gen file and writes the content into the
+ REVPROP_GENERATION member of FS. Use pool for allocations. */
+static svn_error_t *
+read_revprop_generation(svn_fs_t *fs,
+ apr_pool_t *pool)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+
+ const char *path = path_revprop_generation(fs, pool);
+ svn_error_t *err;
+ char buf[80];
+ int i;
+
+ /* Read the raw data from the file, if it exists. If it does
+ not, set the generation to "1" and return.
+ We don't want to have this function fail. So, patiently
+ retry a couple of times the case the OS denied us access. */
+ apr_pool_t *iterpool = svn_pool_create(pool);
+ for (i = 0; i < RECOVERABLE_RETRY_COUNT; ++i)
+ {
+ apr_file_t *file;
+ apr_size_t len = sizeof(buf);
+
+ svn_pool_clear(iterpool);
+
+ err = svn_io_file_open(&file, path, APR_READ | APR_BUFFERED,
+ APR_OS_DEFAULT, iterpool);
+ if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+ {
+ /* No-one changed a revprop -> we are still at gen 1. */
+ ffd->revprop_generation = 1;
+ svn_error_clear(err);
+ return SVN_NO_ERROR;
+ }
+ svn_error_clear(err);
+
+ RETRY_RECOVERABLE(err, file,
+ svn_io_read_length_line(file,
+ buf,
+ &len,
+ iterpool));
+ IGNORE_RECOVERABLE(err, svn_io_file_close(file,
+ iterpool));
+
+ break;
+ }
+ SVN_ERR(err);
+
+ svn_pool_destroy(iterpool);
+
+ /* Check that the first line contains only digits. */
+ SVN_ERR(check_file_buffer_numeric(buf, 0, path,
+ "Revprop generations", pool));
+ SVN_ERR(svn_cstring_atoi64(&ffd->revprop_generation, buf));
+
+ /* Graceful behavior in case someone put a "0" in the file. */
+ if (ffd->revprop_generation <= 0)
+ ffd->revprop_generation = 1;
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+check_revprop_generation(svn_fs_t *fs,
+ apr_pool_t *pool)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+
+ return ffd->revprop_generation == 0
+ ? read_revprop_generation(fs, pool)
+ : SVN_NO_ERROR;
+}
+
+static svn_error_t *
+increment_revprop_generation(svn_fs_t *fs,
+ apr_pool_t *pool)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+
+ const char *path = path_revprop_generation(fs, pool);
+ const char *tmp_filename;
+ svn_string_t *generation;
+
+ SVN_ERR(read_revprop_generation(fs, pool));
+
+ /* Increment the key and add a trailing \n to the string so the
+ txn-current file has a newline in it. */
+ ++ffd->revprop_generation;
+ generation = svn_string_createf(pool, "%" APR_INT64_T_FMT "\n",
+ ffd->revprop_generation);
+
+ SVN_ERR(svn_io_write_unique(&tmp_filename,
+ svn_dirent_dirname(path, pool),
+ generation->data, generation->len,
+ svn_io_file_del_none, pool));
+ return move_into_place(tmp_filename, path,
+ svn_fs_fs__path_current(fs, pool), pool);
+}
+
/* Set the revision property list of revision REV in filesystem FS to
PROPLIST. Use POOL for temporary allocations. */
static svn_error_t *
@@ -2693,6 +2822,10 @@ set_revision_proplist(svn_fs_t *fs,
const char *tmp_path;
const char *perms_reference;
svn_stream_t *stream;
+ svn_node_kind_t kind;
+
+ /* test whether revprops already exist for this revision */
+ SVN_ERR(svn_io_check_path(final_path, &kind, pool));
/* ### do we have a directory sitting around already? we really shouldn't
### have to get the dirname here. */
@@ -2709,6 +2842,12 @@ set_revision_proplist(svn_fs_t *fs,
SVN_ERR(svn_fs_fs__path_rev_absolute(&perms_reference, fs, rev, pool));
SVN_ERR(move_into_place(tmp_path, final_path, perms_reference, pool));
+ /* Invalidate all cached revprops for this FS and for all other
+ users that haven't read any revprops, YET. Since writing revprops
+ implies a write lock, there can be no races. */
+ if (kind != svn_node_none)
+ SVN_ERR(increment_revprop_generation(fs, pool));
+
return SVN_NO_ERROR;
}
@@ -2722,8 +2861,22 @@ revision_proplist(apr_hash_t **proplist_
apr_pool_t *pool)
{
apr_hash_t *proplist;
+ fs_fs_data_t *ffd = fs->fsap_data;
+ const char *key;
SVN_ERR(ensure_revision_exists(fs, rev, pool));
+ SVN_ERR(check_revprop_generation(fs, pool));
+
+ /* Try cache lookup first. */
+ key = svn_fs_fs__combine_two_numbers(rev, ffd->revprop_generation, pool);
+ if (ffd->revprop_cache)
+ {
+ svn_boolean_t is_cached;
+ SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
+ ffd->revprop_cache, key, pool));
+ if (is_cached)
+ return SVN_NO_ERROR;
+ }
/* if (1); null condition for easier merging to revprop-packing */
{
@@ -2779,6 +2932,10 @@ revision_proplist(apr_hash_t **proplist_
svn_pool_destroy(iterpool);
}
+ /* Cache the result, if caching has been activated. */
+ if (ffd->revprop_cache)
+ SVN_ERR(svn_cache__set(ffd->revprop_cache, key, proplist, pool));
+
*proplist_p = proplist;
return SVN_NO_ERROR;
@@ -2879,7 +3036,7 @@ create_rep_state(struct rep_state **rep_
### going to jump straight to this comment anyway! */
return svn_error_createf(SVN_ERR_FS_CORRUPT, err,
"Corrupt representation '%s'",
- rep
+ rep
? representation_string(rep, ffd->format, TRUE,
TRUE, pool)
: "(null)");
@@ -2895,7 +3052,7 @@ struct rep_read_baton
/* If not NULL, this is the base for the first delta window in rs_list */
svn_stringbuf_t *base_window;
-
+
/* The state of all prior delta representations. */
apr_array_header_t *rs_list;
@@ -3139,14 +3296,14 @@ build_rep_list(apr_array_header_t **list
SVN_ERR(get_cached_combined_window(window_p, rs, &is_cached, pool));
if (is_cached)
{
- /* We already have a reconstructed window in our cache.
+ /* We already have a reconstructed window in our cache.
Write a pseudo rep_state with the full length. */
rs->off = rs->start;
rs->end = rs->start + (*window_p)->len;
*src_state = rs;
return SVN_NO_ERROR;
}
-
+
if (rep_args->is_delta == FALSE)
{
/* This is a plaintext, so just return the current rep_state. */
@@ -3205,7 +3362,7 @@ rep_read_get_baton(struct rep_read_baton
else
b->current_fulltext = NULL;
- SVN_ERR(build_rep_list(&b->rs_list, &b->base_window,
+ SVN_ERR(build_rep_list(&b->rs_list, &b->base_window,
&b->src_state, fs, rep,
b->filehandle_pool));
@@ -3286,7 +3443,7 @@ get_combined_window(svn_stringbuf_t **re
{
rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);
SVN_ERR(read_window(&window, rb->chunk_index, rs, window_pool));
-
+
APR_ARRAY_PUSH(windows, svn_txdelta_window_t *) = window;
if (window->src_ops == 0)
{
@@ -3294,7 +3451,7 @@ get_combined_window(svn_stringbuf_t **re
break;
}
}
-
+
/* Combine in the windows from the other delta reps. */
pool = svn_pool_create(rb->pool);
for (--i; i >= 0; --i)
@@ -3307,7 +3464,7 @@ get_combined_window(svn_stringbuf_t **re
new_pool = svn_pool_create(rb->pool);
buf = svn_stringbuf_create_ensure(window->tview_len, new_pool);
buf->len = window->tview_len;
-
+
svn_txdelta_apply_instructions(window, source ? source->data : NULL,
buf->data, &buf->len);
if (buf->len != window->tview_len)
@@ -3327,7 +3484,7 @@ get_combined_window(svn_stringbuf_t **re
}
svn_pool_destroy(window_pool);
-
+
*result = buf;
return SVN_NO_ERROR;
}
@@ -3519,7 +3676,7 @@ read_representation(svn_stream_t **conte
else
{
fs_fs_data_t *ffd = fs->fsap_data;
- const char *fulltext_key = NULL;
+ const char *fulltext_cache_key = NULL;
svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size;
struct rep_read_baton *rb;
@@ -3528,10 +3685,11 @@ read_representation(svn_stream_t **conte
{
svn_stringbuf_t *fulltext;
svn_boolean_t is_cached;
- fulltext_key = apr_psprintf(pool, "%ld/%" APR_OFF_T_FMT,
+ fulltext_cache_key = apr_psprintf(pool, "%ld/%" APR_OFF_T_FMT,
rep->revision, rep->offset);
SVN_ERR(svn_cache__get((void **) &fulltext, &is_cached,
- ffd->fulltext_cache, fulltext_key, pool));
+ ffd->fulltext_cache, fulltext_cache_key,
+ pool));
if (is_cached)
{
*contents_p = svn_stream_from_stringbuf(fulltext, pool);
@@ -3539,7 +3697,7 @@ read_representation(svn_stream_t **conte
}
}
- SVN_ERR(rep_read_get_baton(&rb, fs, rep, fulltext_key, pool));
+ SVN_ERR(rep_read_get_baton(&rb, fs, rep, fulltext_cache_key, pool));
*contents_p = svn_stream_create(rb, pool);
svn_stream_set_read(*contents_p, rep_read_contents);
@@ -5268,7 +5426,7 @@ choose_delta_base(representation_t **rep
count = noderev->predecessor_count;
count = count & (count - 1);
- /* We use skip delta for limiting the number of delta operations
+ /* We use skip delta for limiting the number of delta operations
along very long node histories. Close to HEAD however, we create
a linear history to minimize delta size. */
walk = noderev->predecessor_count - count;
@@ -5387,8 +5545,8 @@ rep_write_get_baton(struct rep_write_bat
limited by both, POOL and REP lifetime.
*/
static svn_error_t *
-get_shared_rep(representation_t **old_rep,
- svn_fs_t *fs,
+get_shared_rep(representation_t **old_rep,
+ svn_fs_t *fs,
representation_t *rep,
apr_hash_t *reps_hash,
apr_pool_t *pool)
@@ -5408,7 +5566,7 @@ get_shared_rep(representation_t **old_re
*old_rep = apr_hash_get(reps_hash,
rep->sha1_checksum->digest,
APR_SHA1_DIGESTSIZE);
-
+
/* If we haven't found anything yet, try harder and consult our DB. */
if (*old_rep == NULL)
{
@@ -5447,7 +5605,7 @@ get_shared_rep(representation_t **old_re
(*old_rep)->md5_checksum = rep->md5_checksum;
(*old_rep)->uniquifier = rep->uniquifier;
}
-
+
return SVN_NO_ERROR;
}
@@ -5771,7 +5929,7 @@ write_hash_delta_rep(representation_t *r
{
svn_txdelta_window_handler_t diff_wh;
void *diff_whb;
-
+
svn_stream_t *file_stream;
svn_stream_t *stream;
representation_t *base_rep;
@@ -5779,8 +5937,8 @@ write_hash_delta_rep(representation_t *r
svn_stream_t *source;
const char *header;
- apr_off_t rep_end = 0;
- apr_off_t delta_start = 0;
+ apr_off_t rep_end = 0;
+ apr_off_t delta_start = 0;
struct write_hash_baton *whb;
fs_fs_data_t *ffd = fs->fsap_data;
@@ -5809,7 +5967,7 @@ write_hash_delta_rep(representation_t *r
SVN_ERR(get_file_offset(&delta_start, file, pool));
file_stream = svn_stream_from_aprfile2(file, TRUE, pool);
-
+
/* Prepare to write the svndiff data. */
svn_txdelta_to_svndiff3(&diff_wh,
&diff_whb,
@@ -5865,6 +6023,8 @@ write_hash_delta_rep(representation_t *r
/* Sanity check ROOT_NODEREV, a candidate for being the root node-revision
of (not yet committed) revision REV in FS. Use POOL for temporary
allocations.
+
+ If you change this function, consider updating svn_fs_fs__verify() too.
*/
static svn_error_t *
validate_root_noderev(svn_fs_t *fs,
@@ -5911,8 +6071,11 @@ validate_root_noderev(svn_fs_t *fs,
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
_("predecessor count for "
"the root node-revision is wrong: "
- "found %d, committing r%ld"),
- root_noderev->predecessor_count, rev);
+ "found (%d+%ld != %d), committing r%ld"),
+ head_predecessor_count,
+ rev - head_revnum, /* This is equal to 1. */
+ root_noderev->predecessor_count,
+ rev);
}
return SVN_NO_ERROR;
@@ -6053,7 +6216,7 @@ write_final_rev(const svn_fs_id_t **new_
proplist, fs, noderev, reps_hash,
pool));
#else
- SVN_ERR(write_hash_rep(noderev->prop_rep, file, proplist,
+ SVN_ERR(write_hash_rep(noderev->prop_rep, file, proplist,
fs, reps_hash, pool));
#endif
}
@@ -6112,15 +6275,15 @@ write_final_rev(const svn_fs_id_t **new_
if (noderev->prop_rep && noderev->prop_rep->revision == rev)
{
/* Add new property reps to hash and on-disk cache. */
- representation_t *copy
+ representation_t *copy
= svn_fs_fs__rep_copy(noderev->prop_rep, reps_pool);
SVN_ERR_ASSERT(reps_to_cache && reps_pool);
APR_ARRAY_PUSH(reps_to_cache, representation_t *) = copy;
- apr_hash_set(reps_hash,
- copy->sha1_checksum->digest,
- APR_SHA1_DIGESTSIZE,
+ apr_hash_set(reps_hash,
+ copy->sha1_checksum->digest,
+ APR_SHA1_DIGESTSIZE,
copy);
}
}
@@ -6746,6 +6909,9 @@ svn_fs_fs__create(svn_fs_t *fs,
"", pool));
}
+ /* Create the revprop generation tracking file. */
+ SVN_ERR(increment_revprop_generation(fs, pool));
+
/* This filesystem is ready. Stamp it with a format number. */
SVN_ERR(write_format(path_format(fs, pool),
ffd->format, ffd->max_files_per_dir, FALSE, pool));
@@ -7878,7 +8044,7 @@ svn_fs_fs__pack(svn_fs_t *fs,
/** Verifying. **/
-/* Body of svn_fs_fs__verify().
+/* Used by svn_fs_fs__verify().
Implements svn_fs_fs__walk_rep_reference().walker. */
static svn_error_t *
verify_walker(representation_t *rep,
@@ -7899,23 +8065,93 @@ svn_error_t *
svn_fs_fs__verify(svn_fs_t *fs,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_revnum_t start,
+ svn_revnum_t end,
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
svn_boolean_t exists;
+ svn_revnum_t youngest = ffd->youngest_rev_cache; /* cache is current */
+ apr_pool_t *iterpool = svn_pool_create(pool);
if (ffd->format < SVN_FS_FS__MIN_REP_SHARING_FORMAT)
return SVN_NO_ERROR;
- /* Do not attempt to walk the rep-cache database if its file does not exists,
- since doing so would create it --- which may confuse the administrator. */
+ /* Input validation. */
+ if (! SVN_IS_VALID_REVNUM(start))
+ start = 0;
+ if (! SVN_IS_VALID_REVNUM(end))
+ end = youngest;
+ SVN_ERR(ensure_revision_exists(fs, start, iterpool));
+ SVN_ERR(ensure_revision_exists(fs, end, iterpool));
+
+ /* rep-cache verification. */
SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, fs, pool));
if (exists)
- /* Don't take any lock. */
+ /* Do not attempt to walk the rep-cache database if its file does not exist,
+ since doing so would create it --- which may confuse the administrator.
+ Don't take any lock. */
SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, NULL,
cancel_func, cancel_baton,
+ start, end,
pool));
+ /* Issue #4129: bogus pred-counts on the root node-rev. */
+ {
+ svn_revnum_t i;
+ int predecessor_predecessor_count;
+
+ /* Compute PREDECESSOR_PREDECESSOR_COUNT. */
+ if (start == 0)
+ /* The value that passes the if() at the end of the loop. */
+ predecessor_predecessor_count = -1;
+ else
+ {
+ svn_fs_id_t *root_id;
+ node_revision_t *root_noderev;
+ SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, start-1, iterpool));
+ SVN_ERR(svn_fs_fs__get_node_revision(&root_noderev, fs, root_id,
+ iterpool));
+ predecessor_predecessor_count = root_noderev->predecessor_count;
+ }
+
+ for (i = start; i <= end; i++)
+ {
+ /* ### Caching.
+
+ svn_fs_fs__rev_get_root() consults caches, which in verify we
+ don't want. But we can't easily bypass that, as
+ svn_fs_revision_root()+svn_fs_node_id()'s implementation uses
+ svn_fs_fs__rev_get_root() too.
+
+ ### A future revision will make fs_verify() disable caches when it
+ ### opens ffd.
+ */
+ svn_fs_id_t *root_id;
+ node_revision_t *root_noderev;
+
+ if ((i % 128) == 0) /* uneducated guess */
+ svn_pool_clear(iterpool);
+
+ /* Fetch ROOT_NODEREV. */
+ SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, i, iterpool));
+ SVN_ERR(svn_fs_fs__get_node_revision(&root_noderev, fs, root_id,
+ iterpool));
+
+ /* Check correctness. (Compare validate_root_noderev().) */
+ if (1+predecessor_predecessor_count != root_noderev->predecessor_count)
+ return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
+ _("predecessor count for "
+ "the root node-revision is wrong: "
+ "r%ld has %d, but r%ld has %d"),
+ i, root_noderev->predecessor_count,
+ i-1, predecessor_predecessor_count);
+
+ predecessor_predecessor_count = root_noderev->predecessor_count;
+ }
+ }
+
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -8079,7 +8315,7 @@ hotcopy_io_copy_dir_recursively(const ch
else if (this_entry.filetype == APR_DIR) /* recurse */
{
const char *src_target;
-
+
/* Prevent infinite recursion by filtering off our
newly created destination path. */
if (strcmp(src, dst_parent) == 0
@@ -8284,7 +8520,7 @@ hotcopy_remove_rev_files(svn_fs_t *dst_f
for (rev = start_rev; rev < end_rev; rev++)
{
const char *rev_path;
-
+
svn_pool_clear(iterpool);
/* If necessary, update paths for shard. */
@@ -8726,6 +8962,7 @@ hotcopy_create_empty_dest(svn_fs_t *src_
{
fs_fs_data_t *src_ffd = src_fs->fsap_data;
fs_fs_data_t *dst_ffd = dst_fs->fsap_data;
+ svn_node_kind_t kind;
dst_fs->path = apr_pstrdup(pool, dst_path);
@@ -8789,6 +9026,14 @@ hotcopy_create_empty_dest(svn_fs_t *src_
"", pool));
}
+ /* Copy the revprop generation file if it exists in SRC_FS. */
+ SVN_ERR(svn_io_check_path(path_revprop_generation(src_fs, pool),
+ &kind, pool));
+ if (kind == svn_node_file)
+ SVN_ERR(svn_io_copy_file(path_revprop_generation(src_fs, pool),
+ path_revprop_generation(dst_fs, pool),
+ TRUE, pool));
+
dst_ffd->youngest_rev_cache = 0;
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h Mon Mar 5 20:34:22 2012
@@ -42,6 +42,8 @@ svn_error_t *svn_fs_fs__upgrade(svn_fs_t
svn_error_t *svn_fs_fs__verify(svn_fs_t *fs,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_revnum_t start,
+ svn_revnum_t end,
apr_pool_t *pool);
/* Copy the fsfs filesystem SRC_FS at SRC_PATH into a new copy DST_FS at
@@ -106,6 +108,12 @@ svn_error_t *svn_fs_fs__youngest_rev(svn
svn_fs_t *fs,
apr_pool_t *pool);
+/* Return an error iff REV does not exist in FS. */
+svn_error_t *
+svn_fs_fs__revision_exists(svn_revnum_t rev,
+ svn_fs_t *fs,
+ apr_pool_t *pool);
+
/* Set *ROOT_ID to the node-id for the root of revision REV in
filesystem FS. Do any allocations in POOL. */
svn_error_t *svn_fs_fs__rev_get_root(svn_fs_id_t **root_id,
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql Mon Mar 5 20:34:22 2012
@@ -33,6 +33,11 @@ CREATE TABLE rep_cache (
expanded_size INTEGER NOT NULL
);
+/* There isn't an implicit index on a TEXT column, so create an explicit one. */
+CREATE INDEX I_HASH on REP_CACHE (hash);
+
+/* The index didn't exist until 1.7.5; therefore, some USER_VERSION=1
+ rep-cache.db files out there DO NOT contain an I_HASH index. */
PRAGMA USER_VERSION = 1;
@@ -47,9 +52,15 @@ INSERT OR FAIL INTO rep_cache (hash, rev
VALUES (?1, ?2, ?3, ?4, ?5)
--- STMT_GET_ALL_REPS
+-- STMT_GET_REPS_FOR_RANGE
SELECT hash, revision, offset, size, expanded_size
FROM rep_cache
+WHERE revision >= ?1 AND revision <= ?2
+
+
+-- STMT_GET_MAX_REV
+SELECT MAX(revision)
+FROM rep_cache
-- STMT_DEL_REPS_YOUNGER_THAN_REV
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c Mon Mar 5 20:34:22 2012
@@ -56,24 +56,9 @@ rep_has_been_born(representation_t *rep,
svn_fs_t *fs,
apr_pool_t *pool)
{
- fs_fs_data_t *ffd = fs->fsap_data;
- svn_revnum_t youngest;
-
SVN_ERR_ASSERT(rep);
- youngest = ffd->youngest_rev_cache;
- if (youngest < rep->revision)
- {
- /* Stale cache. */
- SVN_ERR(svn_fs_fs__youngest_rev(&youngest, fs, pool));
-
- /* Fresh cache. */
- if (youngest < rep->revision)
- return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- _("Youngest revision is r%ld, but "
- "rep-cache contains r%ld"),
- youngest, rep->revision);
- }
+ SVN_ERR(svn_fs_fs__revision_exists(rep->revision, fs, pool));
return SVN_NO_ERROR;
}
@@ -141,11 +126,13 @@ svn_error_t *
svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
svn_error_t *(*walker)(representation_t *,
void *,
- svn_fs_t *,
+ svn_fs_t *,
apr_pool_t *),
void *walker_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_revnum_t start,
+ svn_revnum_t end,
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
@@ -161,9 +148,25 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
if (! ffd->rep_cache_db)
SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool));
+ /* Check global invariants. */
+ if (start == 0)
+ {
+ svn_sqlite__stmt_t *stmt2;
+ svn_revnum_t max;
+
+ SVN_ERR(svn_sqlite__get_statement(&stmt2, ffd->rep_cache_db,
+ STMT_GET_MAX_REV));
+ SVN_ERR(svn_sqlite__step(&have_row, stmt2));
+ max = svn_sqlite__column_revnum(stmt2, 0);
+ SVN_ERR(svn_fs_fs__revision_exists(max, fs, iterpool));
+ SVN_ERR(svn_sqlite__reset(stmt2));
+ }
+
/* Get the statement. (There are no arguments to bind.) */
SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db,
- STMT_GET_ALL_REPS));
+ STMT_GET_REPS_FOR_RANGE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "rr",
+ start, end));
/* Walk the cache entries. */
SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -171,7 +174,7 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
{
representation_t *rep;
const char *sha1_digest;
-
+
/* Clear ITERPOOL occasionally. */
if (iterations++ % 16 == 0)
svn_pool_clear(iterpool);
@@ -191,10 +194,6 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
rep->size = svn_sqlite__column_int64(stmt, 3);
rep->expanded_size = svn_sqlite__column_int64(stmt, 4);
- /* Sanity check. */
- if (rep)
- SVN_ERR(rep_has_been_born(rep, fs, iterpool));
-
/* Walk. */
SVN_ERR(walker(rep, walker_baton, fs, iterpool));
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h Mon Mar 5 20:34:22 2012
@@ -50,11 +50,13 @@ svn_error_t *
svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
svn_error_t *(*walker)(representation_t *rep,
void *walker_baton,
- svn_fs_t *fs,
+ svn_fs_t *fs,
apr_pool_t *scratch_pool),
void *walker_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_revnum_t start,
+ svn_revnum_t end,
apr_pool_t *pool);
/* Return the representation REP in FS which has fulltext CHECKSUM.
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/structure Mon Mar 5 20:34:22 2012
@@ -266,7 +266,7 @@ Within a revision:
"r<rev>/<offset>" txn-id fields.
In Format 3 and above, this uniqueness is done by changing a temporary
- id of "_<base36>" to "<rev>-<base36>". Note that this means that the
+ id of "_<base36>" to "<base36>-<rev>". Note that this means that the
originating revision of a line of history or a copy can be determined
by looking at the node ID.
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c Mon Mar 5 20:34:22 2012
@@ -136,7 +136,7 @@ serialize_svn_string(svn_temp_serializer
* Thus, we cannot use svn_temp_serializer__add_string. */
svn_temp_serializer__push(context,
(const void * const *)&string->data,
- string->len);
+ string->len + 1);
/* back to the caller's nesting level */
svn_temp_serializer__pop(context);
@@ -579,6 +579,142 @@ svn_fs_fs__deserialize_manifest(void **o
return SVN_NO_ERROR;
}
+/* Auxilliary structure representing the content of a properties hash.
+ This structure is much easier to (de-)serialize than an apr_hash.
+ */
+typedef struct properties_data_t
+{
+ /* number of entries in the hash */
+ apr_size_t count;
+
+ /* reference to the keys */
+ const char **keys;
+
+ /* reference to the values */
+ const svn_string_t **values;
+} properties_data_t;
+
+/* Serialize COUNT C-style strings from *STRINGS into CONTEXT. */
+static void
+serialize_cstring_array(svn_temp_serializer__context_t *context,
+ const char ***strings,
+ apr_size_t count)
+{
+ apr_size_t i;
+ const char **entries = *strings;
+
+ /* serialize COUNT entries pointers (the array) */
+ svn_temp_serializer__push(context,
+ (const void * const *)strings,
+ count * sizeof(const char*));
+
+ /* serialize array elements */
+ for (i = 0; i < count; ++i)
+ svn_temp_serializer__add_string(context, &entries[i]);
+
+ svn_temp_serializer__pop(context);
+}
+
+/* Serialize COUNT svn_string_t* items from *STRINGS into CONTEXT. */
+static void
+serialize_svn_string_array(svn_temp_serializer__context_t *context,
+ const svn_string_t ***strings,
+ apr_size_t count)
+{
+ apr_size_t i;
+ const svn_string_t **entries = *strings;
+
+ /* serialize COUNT entries pointers (the array) */
+ svn_temp_serializer__push(context,
+ (const void * const *)strings,
+ count * sizeof(const char*));
+
+ /* serialize array elements */
+ for (i = 0; i < count; ++i)
+ serialize_svn_string(context, &entries[i]);
+
+ svn_temp_serializer__pop(context);
+}
+
+svn_error_t *
+svn_fs_fs__serialize_properties(char **data,
+ apr_size_t *data_len,
+ void *in,
+ apr_pool_t *pool)
+{
+ apr_hash_t *hash = in;
+ properties_data_t properties;
+ svn_temp_serializer__context_t *context;
+ apr_hash_index_t *hi;
+ svn_stringbuf_t *serialized;
+ apr_size_t i;
+
+ /* create our auxilliary data structure */
+ properties.count = apr_hash_count(hash);
+ properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1));
+ properties.values = apr_palloc(pool, sizeof(const char*) * properties.count);
+
+ /* populate it with the hash entries */
+ for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i)
+ {
+ properties.keys[i] = svn__apr_hash_index_key(hi);
+ properties.values[i] = svn__apr_hash_index_val(hi);
+ }
+
+ /* serialize it */
+ context = svn_temp_serializer__init(&properties,
+ sizeof(properties),
+ properties.count * 100,
+ pool);
+
+ properties.keys[i] = "";
+ serialize_cstring_array(context, &properties.keys, properties.count + 1);
+ serialize_svn_string_array(context, &properties.values, properties.count);
+
+ /* return the serialized result */
+ serialized = svn_temp_serializer__get(context);
+
+ *data = serialized->data;
+ *data_len = serialized->len;
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__deserialize_properties(void **out,
+ char *data,
+ apr_size_t data_len,
+ apr_pool_t *pool)
+{
+ apr_hash_t *hash = apr_hash_make(pool);
+ properties_data_t *properties = (properties_data_t *)data;
+ size_t i;
+
+ /* de-serialize our auxilliary data structure */
+ svn_temp_deserializer__resolve(properties, (void**)&properties->keys);
+ svn_temp_deserializer__resolve(properties, (void**)&properties->values);
+
+ /* de-serialize each entry and put it into the hash */
+ for (i = 0; i < properties->count; ++i)
+ {
+ apr_size_t len = properties->keys[i+1] - properties->keys[i] - 1;
+ svn_temp_deserializer__resolve(properties->keys,
+ (void**)&properties->keys[i]);
+
+ deserialize_svn_string(properties->values,
+ (svn_string_t **)&properties->values[i]);
+
+ apr_hash_set(hash,
+ properties->keys[i], len,
+ properties->values[i]);
+ }
+
+ /* done */
+ *out = hash;
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_fs_fs__serialize_id(char **data,
apr_size_t *data_len,
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.h Mon Mar 5 20:34:22 2012
@@ -113,6 +113,26 @@ svn_fs_fs__deserialize_manifest(void **o
apr_pool_t *pool);
/**
+ * Implements #svn_cache__serialize_func_t for a properties hash
+ * (@a in is an #apr_hash_t of svn_string_t elements, keyed by const char*).
+ */
+svn_error_t *
+svn_fs_fs__serialize_properties(char **data,
+ apr_size_t *data_len,
+ void *in,
+ apr_pool_t *pool);
+
+/**
+ * Implements #svn_cache__deserialize_func_t for a properties hash
+ * (@a *out is an #apr_hash_t of svn_string_t elements, keyed by const char*).
+ */
+svn_error_t *
+svn_fs_fs__deserialize_properties(void **out,
+ char *data,
+ apr_size_t data_len,
+ apr_pool_t *pool);
+
+/**
* Implements #svn_cache__serialize_func_t for #svn_fs_id_t
*/
svn_error_t *
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c Mon Mar 5 20:34:22 2012
@@ -115,7 +115,7 @@ typedef struct fs_rev_root_data_t
typedef struct fs_txn_root_data_t
{
/* Cache of txn DAG nodes (without their nested noderevs, because
- * it's mutable). */
+ * it's mutable). Same keys/values as ffd->rev_node_cache. */
svn_cache__t *txn_node_cache;
} fs_txn_root_data_t;
@@ -2807,8 +2807,10 @@ find_youngest_copyroot(svn_revnum_t *rev
parent_path_t *parent_path,
apr_pool_t *pool)
{
- svn_revnum_t rev_mine, rev_parent = -1;
- const char *path_mine, *path_parent;
+ svn_revnum_t rev_mine;
+ svn_revnum_t rev_parent = SVN_INVALID_REVNUM;
+ const char *path_mine;
+ const char *path_parent = NULL;
/* First find our parent's youngest copyroot. */
if (parent_path->parent)
Modified: subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.c Mon Mar 5 20:34:22 2012
@@ -1304,6 +1304,15 @@ svn_ra_print_ra_libraries(svn_stringbuf_
}
+svn_error_t *
+svn_ra__register_editor_shim_callbacks(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks)
+{
+ SVN_ERR(session->vtable->register_editor_shim_callbacks(session, callbacks));
+ return SVN_NO_ERROR;
+}
+
+
/* Return the library version number. */
const svn_version_t *
svn_ra_version(void)
Modified: subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra/ra_loader.h Mon Mar 5 20:34:22 2012
@@ -293,6 +293,8 @@ typedef struct svn_ra__vtable_t {
svn_revnum_t end_revision,
svn_revnum_t *revision_deleted,
apr_pool_t *pool);
+ svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks);
} svn_ra__vtable_t;
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c Mon Mar 5 20:34:22 2012
@@ -153,7 +153,7 @@ cache_init(void *baton, apr_pool_t *pool
SVN_ERR(svn_error_quick_wrap(svn_cstring_atoui64(&memory_cache_size,
memory_cache_size_str),
_("memory-cache-size invalid")));
- settings.cache_size = 1024 * 1024 * memory_cache_size;
+ settings.cache_size = 1024 * 1024 * memory_cache_size;
svn_cache_config_set(&settings);
}
@@ -1505,6 +1505,15 @@ svn_ra_local__get_deleted_rev(svn_ra_ses
return SVN_NO_ERROR;
}
+static svn_error_t *
+svn_ra_local__register_editor_shim_callbacks(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks)
+{
+ /* This is currenly a no-op, since we don't provide our own editor, just
+ use the one the libsvn_repos hands back to us. */
+ return SVN_NO_ERROR;
+}
+
/*----------------------------------------------------------------*/
static const svn_version_t *
@@ -1551,7 +1560,8 @@ static const svn_ra__vtable_t ra_local_v
svn_ra_local__replay,
svn_ra_local__has_capability,
svn_ra_local__replay_range,
- svn_ra_local__get_deleted_rev
+ svn_ra_local__get_deleted_rev,
+ svn_ra_local__register_editor_shim_callbacks
};
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/commit.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/commit.c Mon Mar 5 20:34:22 2012
@@ -1570,8 +1570,6 @@ svn_error_t * svn_ra_neon__get_commit_ed
svn_delta_editor_t *commit_editor;
commit_ctx_t *cc;
apr_hash_index_t *hi;
- svn_delta_shim_callbacks_t *shim_callbacks =
- svn_delta_shim_callbacks_default(pool);
/* Build the main commit editor's baton. */
cc = apr_pcalloc(pool, sizeof(*cc));
@@ -1622,7 +1620,7 @@ svn_error_t * svn_ra_neon__get_commit_ed
*edit_baton = cc;
SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
- shim_callbacks, pool, pool));
+ ras->shim_callbacks, pool, pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/log.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/log.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/log.c Mon Mar 5 20:34:22 2012
@@ -166,7 +166,7 @@ log_start_element(int *elem, void *baton
lb->want_cdata = lb->cdata;
svn_stringbuf_setempty(lb->cdata);
lb->cdata_encoding = NULL;
-
+
/* Some tags might contain encoded CDATA. */
if ((elm->id == ELEM_comment) ||
(elm->id == ELEM_creator_displayname) ||
@@ -280,7 +280,7 @@ maybe_decode_log_cdata(const svn_string_
return SVN_NO_ERROR;
}
-
+
/*
* This implements the `svn_ra_neon__xml_endelm_cb' prototype.
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/ra_neon.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/ra_neon.h?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/ra_neon.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/ra_neon.h Mon Mar 5 20:34:22 2012
@@ -131,6 +131,9 @@ typedef struct svn_ra_neon__session_t {
deadprop-count property.*/
svn_tristate_t supports_deadprop_count;
+ /* Ev2 shim callbacks. */
+ svn_delta_shim_callbacks_t *shim_callbacks;
+
/*** HTTP v2 protocol stuff. ***
*
* We assume that if mod_dav_svn sends one of the special v2 OPTIONs
@@ -1181,6 +1184,10 @@ svn_ra_neon__get_deadprop_count_support(
const char *final_url,
apr_pool_t *pool);
+svn_error_t *
+svn_ra_neon__register_editor_shim_callbacks(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/session.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/session.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/session.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/session.c Mon Mar 5 20:34:22 2012
@@ -1229,7 +1229,8 @@ static const svn_ra__vtable_t neon_vtabl
svn_ra_neon__replay,
svn_ra_neon__has_capability,
svn_ra_neon__replay_range,
- svn_ra_neon__get_deleted_rev
+ svn_ra_neon__get_deleted_rev,
+ svn_ra_neon__register_editor_shim_callbacks
};
svn_error_t *
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_neon/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_neon/util.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_neon/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_neon/util.c Mon Mar 5 20:34:22 2012
@@ -38,6 +38,7 @@
#include "svn_utf.h"
#include "svn_xml.h"
#include "svn_props.h"
+#include "../libsvn_ra/ra_loader.h"
#include "private/svn_fspath.h"
#include "svn_private_config.h"
@@ -1649,3 +1650,13 @@ svn_ra_neon__get_deadprop_count_support(
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_ra_neon__register_editor_shim_callbacks(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks)
+{
+ svn_ra_neon__session_t *ras = session->priv;
+
+ ras->shim_callbacks = callbacks;
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c?rev=1297221&r1=1297220&r2=1297221&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c Mon Mar 5 20:34:22 2012
@@ -328,7 +328,7 @@ checkout_dir(dir_context_t *dir)
return SVN_NO_ERROR;
}
- /* Is this directory or one of our parent dirs newly added?
+ /* Is this directory or one of our parent dirs newly added?
* If so, we're already implicitly checked out. */
while (p_dir)
{
@@ -2319,8 +2319,6 @@ svn_ra_serf__get_commit_editor(svn_ra_se
svn_delta_editor_t *editor;
commit_context_t *ctx;
apr_hash_index_t *hi;
- svn_delta_shim_callbacks_t *shim_callbacks =
- svn_delta_shim_callbacks_default(pool);
ctx = apr_pcalloc(pool, sizeof(*ctx));
@@ -2368,7 +2366,8 @@ svn_ra_serf__get_commit_editor(svn_ra_se
*edit_baton = ctx;
SVN_ERR(svn_editor__insert_shims(ret_editor, edit_baton, *ret_editor,
- *edit_baton, shim_callbacks, pool, pool));
+ *edit_baton, session->shim_callbacks,
+ pool, pool));
return SVN_NO_ERROR;
}