You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ar...@apache.org on 2011/11/21 08:08:07 UTC
svn commit: r1204374 [14/29] - in /subversion/branches/svn-bisect: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/ build/win32/
contrib/client-side/ contrib/client-side/emacs/ notes/ notes/wc-ng/
subversion/bindings/javahl/native...
Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/load-fs-vtable.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/load-fs-vtable.c Mon Nov 21 07:07:56 2011
@@ -63,6 +63,12 @@ struct parse_baton
svn_repos_notify_t *notify;
apr_pool_t *pool;
+ /* Start and end (inclusive) of revision range we'll pay attention
+ to, or a pair of SVN_INVALID_REVNUMs if we're not filtering by
+ revisions. */
+ svn_revnum_t start_rev;
+ svn_revnum_t end_rev;
+
/* A hash mapping copy-from revisions and mergeinfo range revisions
(svn_revnum_t *) in the dump stream to their corresponding revisions
(svn_revnum_t *) in the loaded repository. The hash and its
@@ -84,13 +90,13 @@ struct parse_baton
struct revision_baton
{
svn_revnum_t rev;
-
svn_fs_txn_t *txn;
svn_fs_root_t *txn_root;
const svn_string_t *datestamp;
apr_int32_t rev_offset;
+ svn_boolean_t skipped;
struct parse_baton *pb;
apr_pool_t *pool;
@@ -320,8 +326,8 @@ renumber_mergeinfo_revs(svn_string_t **f
}
if (predates_stream_mergeinfo)
- SVN_ERR(svn_mergeinfo_merge(final_mergeinfo, predates_stream_mergeinfo,
- subpool));
+ SVN_ERR(svn_mergeinfo_merge2(final_mergeinfo, predates_stream_mergeinfo,
+ subpool, subpool));
SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool));
@@ -451,7 +457,14 @@ make_revision_baton(apr_hash_t *headers,
if ((val = apr_hash_get(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER,
APR_HASH_KEY_STRING)))
- rb->rev = SVN_STR_TO_REV(val);
+ {
+ rb->rev = SVN_STR_TO_REV(val);
+
+ /* If we're filtering revisions, is this one we'll skip? */
+ rb->skipped = (SVN_IS_VALID_REVNUM(pb->start_rev)
+ && ((rb->rev < pb->start_rev) ||
+ (rb->rev > pb->end_rev)));
+ }
return rb;
}
@@ -476,7 +489,7 @@ new_revision_record(void **revision_bato
It might be positive or negative. */
rb->rev_offset = (apr_int32_t) (rb->rev) - (head_rev + 1);
- if (rb->rev > 0)
+ if ((rb->rev > 0) && (! rb->skipped))
{
/* Create a new fs txn. */
SVN_ERR(svn_fs_begin_txn2(&(rb->txn), pb->fs, head_rev, 0, pool));
@@ -493,6 +506,14 @@ new_revision_record(void **revision_bato
if (!SVN_IS_VALID_REVNUM(pb->oldest_old_rev))
pb->oldest_old_rev = rb->rev;
}
+
+ /* If we're skipping this revision, try to notify someone. */
+ if (rb->skipped && pb->notify_func)
+ {
+ pb->notify->action = svn_repos_notify_load_skipped_rev;
+ pb->notify->old_revision = rb->rev;
+ pb->notify_func(pb->notify_baton, pb->notify, rb->pool);
+ }
/* If we're parsing revision 0, only the revision are (possibly)
interesting to us: when loading the stream into an empty
@@ -607,6 +628,13 @@ new_node_record(void **node_baton,
SVN_ERR(make_node_baton(&nb, headers, rb, pool));
+ /* If we're skipping this revision, we're done here. */
+ if (rb->skipped)
+ {
+ *node_baton = nb;
+ return SVN_NO_ERROR;
+ }
+
/* Make sure we have an action we recognize. */
if (nb->action < svn_node_action_change
|| nb->action > svn_node_action_replace)
@@ -652,6 +680,10 @@ set_revision_property(void *baton,
{
struct revision_baton *rb = baton;
+ /* If we're skipping this revision, we're done here. */
+ if (rb->skipped)
+ return SVN_NO_ERROR;
+
if (rb->rev > 0)
{
if (rb->pb->validate_props)
@@ -691,6 +723,10 @@ set_node_property(void *baton,
struct revision_baton *rb = nb->rb;
struct parse_baton *pb = rb->pb;
+ /* If we're skipping this revision, we're done here. */
+ if (rb->skipped)
+ return SVN_NO_ERROR;
+
if (strcmp(name, SVN_PROP_MERGEINFO) == 0)
{
svn_string_t *renumbered_mergeinfo;
@@ -764,6 +800,10 @@ remove_node_props(void *baton)
apr_hash_t *proplist;
apr_hash_index_t *hi;
+ /* If we're skipping this revision, we're done here. */
+ if (rb->skipped)
+ return SVN_NO_ERROR;
+
SVN_ERR(svn_fs_node_proplist(&proplist,
rb->txn_root, nb->path, nb->pool));
@@ -788,6 +828,10 @@ apply_textdelta(svn_txdelta_window_handl
struct node_baton *nb = node_baton;
struct revision_baton *rb = nb->rb;
+ /* If we're skipping this revision, we're done here. */
+ if (rb->skipped)
+ return SVN_NO_ERROR;
+
return svn_fs_apply_textdelta(handler, handler_baton,
rb->txn_root, nb->path,
svn_checksum_to_cstring(nb->base_checksum,
@@ -805,6 +849,10 @@ set_fulltext(svn_stream_t **stream,
struct node_baton *nb = node_baton;
struct revision_baton *rb = nb->rb;
+ /* If we're skipping this revision, we're done here. */
+ if (rb->skipped)
+ return SVN_NO_ERROR;
+
return svn_fs_apply_text(stream,
rb->txn_root, nb->path,
svn_checksum_to_cstring(nb->result_checksum,
@@ -820,6 +868,10 @@ close_node(void *baton)
struct revision_baton *rb = nb->rb;
struct parse_baton *pb = rb->pb;
+ /* If we're skipping this revision, we're done here. */
+ if (rb->skipped)
+ return SVN_NO_ERROR;
+
if (pb->notify_func)
{
pb->notify->action = svn_repos_notify_load_node_done;
@@ -839,7 +891,9 @@ close_revision(void *baton)
svn_revnum_t committed_rev;
svn_error_t *err;
- if (rb->rev <= 0)
+ /* If we're skipping this revision or it has an invalid revision
+ number, we're done here. */
+ if (rb->skipped || (rb->rev <= 0))
return SVN_NO_ERROR;
/* Run the pre-commit hook, if so commanded. */
@@ -943,9 +997,11 @@ close_revision(void *baton)
svn_error_t *
-svn_repos_get_fs_build_parser3(const svn_repos_parse_fns2_t **callbacks,
+svn_repos_get_fs_build_parser4(const svn_repos_parse_fns2_t **callbacks,
void **parse_baton,
svn_repos_t *repos,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
svn_boolean_t use_history,
svn_boolean_t validate_props,
enum svn_repos_load_uuid uuid_action,
@@ -960,6 +1016,13 @@ svn_repos_get_fs_build_parser3(const svn
if (parent_dir)
parent_dir = svn_relpath_canonicalize(parent_dir, pool);
+ 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->new_revision_record = new_revision_record;
parser->new_node_record = new_node_record;
parser->uuid_record = uuid_record;
@@ -985,6 +1048,8 @@ svn_repos_get_fs_build_parser3(const svn
pb->rev_map = apr_hash_make(pool);
pb->oldest_old_rev = SVN_INVALID_REVNUM;
pb->last_rev_mapped = SVN_INVALID_REVNUM;
+ pb->start_rev = start_rev;
+ pb->end_rev = end_rev;
*callbacks = parser;
*parse_baton = pb;
@@ -994,8 +1059,10 @@ svn_repos_get_fs_build_parser3(const svn
svn_error_t *
-svn_repos_load_fs3(svn_repos_t *repos,
+svn_repos_load_fs4(svn_repos_t *repos,
svn_stream_t *dumpstream,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
enum svn_repos_load_uuid uuid_action,
const char *parent_dir,
svn_boolean_t use_pre_commit_hook,
@@ -1013,8 +1080,9 @@ svn_repos_load_fs3(svn_repos_t *repos,
/* This is really simple. */
- SVN_ERR(svn_repos_get_fs_build_parser3(&parser, &parse_baton,
+ SVN_ERR(svn_repos_get_fs_build_parser4(&parser, &parse_baton,
repos,
+ start_rev, end_rev,
TRUE, /* look for copyfrom revs */
validate_props,
uuid_action,
Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/log.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/log.c Mon Nov 21 07:07:56 2011
@@ -665,7 +665,7 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
APR_ARRAY_PUSH(query_paths, const char *) = changed_path;
SVN_ERR(svn_fs_get_mergeinfo2(&tmp_catalog, root,
query_paths, svn_mergeinfo_inherited,
- FALSE, FALSE, iterpool));
+ FALSE, TRUE, iterpool, iterpool));
tmp_mergeinfo = apr_hash_get(tmp_catalog, changed_path,
APR_HASH_KEY_STRING);
if (tmp_mergeinfo)
@@ -684,7 +684,7 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
APR_ARRAY_PUSH(query_paths, const char *) = base_path;
SVN_ERR(svn_fs_get_mergeinfo2(&tmp_catalog, base_root,
query_paths, svn_mergeinfo_inherited,
- FALSE, FALSE, iterpool));
+ FALSE, TRUE, iterpool, iterpool));
tmp_mergeinfo = apr_hash_get(tmp_catalog, base_path,
APR_HASH_KEY_STRING);
if (tmp_mergeinfo)
@@ -711,17 +711,16 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
if (prev_mergeinfo_value)
SVN_ERR(svn_mergeinfo_parse(&prev_mergeinfo,
prev_mergeinfo_value->data, iterpool));
- SVN_ERR(svn_mergeinfo_diff(&deleted, &added, prev_mergeinfo,
- mergeinfo, FALSE, iterpool));
+ SVN_ERR(svn_mergeinfo_diff2(&deleted, &added, prev_mergeinfo,
+ mergeinfo, FALSE, result_pool,
+ iterpool));
/* Toss interesting stuff into our return catalogs. */
hash_path = apr_pstrdup(result_pool, changed_path);
apr_hash_set(*deleted_mergeinfo_catalog, hash_path,
- APR_HASH_KEY_STRING, svn_mergeinfo_dup(deleted,
- result_pool));
+ APR_HASH_KEY_STRING, deleted);
apr_hash_set(*added_mergeinfo_catalog, hash_path,
- APR_HASH_KEY_STRING, svn_mergeinfo_dup(added,
- result_pool));
+ APR_HASH_KEY_STRING, added);
}
}
@@ -795,8 +794,9 @@ get_combined_mergeinfo_changes(svn_merge
const char *prev_path;
svn_revnum_t appeared_rev, prev_rev;
svn_fs_root_t *prev_root;
- svn_mergeinfo_catalog_t catalog;
- svn_mergeinfo_t prev_mergeinfo, mergeinfo, deleted, added;
+ svn_mergeinfo_catalog_t catalog, inherited_catalog;
+ svn_mergeinfo_t prev_mergeinfo, mergeinfo, deleted, added,
+ prev_inherited_mergeinfo, inherited_mergeinfo;
apr_array_header_t *query_paths;
svn_pool_clear(iterpool);
@@ -836,8 +836,8 @@ get_combined_mergeinfo_changes(svn_merge
query_paths = apr_array_make(iterpool, 1, sizeof(const char *));
APR_ARRAY_PUSH(query_paths, const char *) = prev_path;
err = svn_fs_get_mergeinfo2(&catalog, prev_root, query_paths,
- svn_mergeinfo_inherited, FALSE, FALSE,
- iterpool);
+ svn_mergeinfo_inherited, FALSE, TRUE,
+ iterpool, iterpool);
if (err && (err->apr_err == SVN_ERR_FS_NOT_FOUND ||
err->apr_err == SVN_ERR_FS_NOT_DIRECTORY ||
err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR))
@@ -847,30 +847,66 @@ get_combined_mergeinfo_changes(svn_merge
continue;
}
SVN_ERR(err);
+
+ /* Issue #4022 'svn log -g interprets change in inherited mergeinfo due
+ to move as a merge': A copy where the source and destination inherit
+ mergeinfo from the same parent means the inherited mergeinfo of the
+ source and destination will differ, but this diffrence is not
+ indicative of a merge unless the mergeinfo on the inherited parent
+ has actually changed.
+
+ To check for this we must fetch the "raw" previous inherited
+ mergeinfo and the "raw" mergeinfo @REV then compare these. */
+ SVN_ERR(svn_fs_get_mergeinfo2(&inherited_catalog, prev_root, query_paths,
+ svn_mergeinfo_nearest_ancestor, FALSE,
+ FALSE, /* adjust_inherited_mergeinfo */
+ iterpool, iterpool));
+
prev_mergeinfo = apr_hash_get(catalog, prev_path, APR_HASH_KEY_STRING);
+ prev_inherited_mergeinfo = apr_hash_get(inherited_catalog, prev_path, APR_HASH_KEY_STRING);
/* Fetch the current mergeinfo (as of REV, and including
inherited stuff) for this path. */
APR_ARRAY_IDX(query_paths, 0, const char *) = path;
SVN_ERR(svn_fs_get_mergeinfo2(&catalog, root, query_paths,
- svn_mergeinfo_inherited, FALSE, FALSE,
- iterpool));
+ svn_mergeinfo_inherited, FALSE, TRUE,
+ iterpool, iterpool));
+
+ /* Issue #4022 again, fetch the raw inherited mergeinfo. */
+ SVN_ERR(svn_fs_get_mergeinfo2(&inherited_catalog, root, query_paths,
+ svn_mergeinfo_nearest_ancestor, FALSE,
+ FALSE, /* adjust_inherited_mergeinfo */
+ iterpool, iterpool));
+
mergeinfo = apr_hash_get(catalog, path, APR_HASH_KEY_STRING);
+ inherited_mergeinfo = apr_hash_get(inherited_catalog, path, APR_HASH_KEY_STRING);
if (!prev_mergeinfo && !mergeinfo)
continue;
+ /* Last bit of issue #4022 checking. */
+ if (prev_inherited_mergeinfo && inherited_mergeinfo)
+ {
+ svn_boolean_t inherits_same_mergeinfo;
+
+ SVN_ERR(svn_mergeinfo__equals(&inherits_same_mergeinfo,
+ prev_inherited_mergeinfo,
+ inherited_mergeinfo,
+ TRUE, iterpool));
+ /* If a copy rather than an actual merge brought about an
+ inherited mergeinfo change then we are finished. */
+ if (inherits_same_mergeinfo)
+ continue;
+ }
+
/* Compare, constrast, and combine the results. */
- SVN_ERR(svn_mergeinfo_diff(&deleted, &added, prev_mergeinfo,
- mergeinfo, FALSE, iterpool));
- SVN_ERR(svn_mergeinfo_merge(*deleted_mergeinfo,
- svn_mergeinfo_dup(deleted, result_pool),
- result_pool));
- SVN_ERR(svn_mergeinfo_merge(*added_mergeinfo,
- svn_mergeinfo_dup(added, result_pool),
- result_pool));
+ SVN_ERR(svn_mergeinfo_diff2(&deleted, &added, prev_mergeinfo,
+ mergeinfo, FALSE, result_pool, iterpool));
+ SVN_ERR(svn_mergeinfo_merge2(*deleted_mergeinfo, deleted,
+ result_pool, iterpool));
+ SVN_ERR(svn_mergeinfo_merge2(*added_mergeinfo, added,
+ result_pool, iterpool));
}
- svn_pool_destroy(iterpool);
/* Merge all the mergeinfos which are, or are children of, one of
our paths of interest into one giant delta mergeinfo. */
@@ -891,20 +927,22 @@ get_combined_mergeinfo_changes(svn_merge
for (i = 0; i < paths->nelts; i++)
{
const char *path = APR_ARRAY_IDX(paths, i, const char *);
- if (! svn_dirent_is_ancestor(path, changed_path))
+ if (! svn_fspath__skip_ancestor(path, changed_path))
continue;
+ svn_pool_clear(iterpool);
deleted = apr_hash_get(deleted_mergeinfo_catalog, key, klen);
- SVN_ERR(svn_mergeinfo_merge(*deleted_mergeinfo,
- svn_mergeinfo_dup(deleted, result_pool),
- result_pool));
- SVN_ERR(svn_mergeinfo_merge(*added_mergeinfo,
- svn_mergeinfo_dup(added, result_pool),
- result_pool));
+ SVN_ERR(svn_mergeinfo_merge2(*deleted_mergeinfo,
+ svn_mergeinfo_dup(deleted, result_pool),
+ result_pool, iterpool));
+ SVN_ERR(svn_mergeinfo_merge2(*added_mergeinfo,
+ svn_mergeinfo_dup(added, result_pool),
+ result_pool, iterpool));
break;
}
}
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -1026,8 +1064,9 @@ fill_log_entry(svn_log_entry_t *log_entr
If DESCENDING_ORDER is true, send child messages in descending order.
- If REVPROPS is NULL, retrieve all revprops; else, retrieve only the
- revprops named in the array (i.e. retrieve none if the array is empty).
+ If REVPROPS is NULL, retrieve all revision properties; else, retrieve
+ only the revision properties named by the (const char *) array elements
+ (i.e. retrieve none if the array is empty).
LOG_TARGET_HISTORY_AS_MERGEINFO, HANDLING_MERGED_REVISION, and
NESTED_MERGES are as per the arguments of the same name to DO_LOGS. If
@@ -1103,8 +1142,7 @@ send_log(svn_revnum_t rev,
apr_array_header_t *rangelist =
svn__apr_hash_index_val(hi2);
- if (svn_fspath__is_ancestor(mergeinfo_path,
- changed_path))
+ if (svn_fspath__skip_ancestor(mergeinfo_path, changed_path))
{
int i;
@@ -1741,8 +1779,8 @@ store_search(svn_mergeinfo_t processed,
apr_hash_set(mergeinfo, apr_pstrdup(processed_pool, path),
APR_HASH_KEY_STRING, ranges);
}
- SVN_ERR(svn_mergeinfo_merge(processed, mergeinfo,
- apr_hash_pool_get(processed)));
+ SVN_ERR(svn_mergeinfo_merge2(processed, mergeinfo,
+ apr_hash_pool_get(processed), scratch_pool));
return SVN_NO_ERROR;
}
@@ -2113,10 +2151,10 @@ get_paths_history_as_mergeinfo(svn_merge
SVN_ERR(svn_mergeinfo__mergeinfo_from_segments(
&path_history_mergeinfo, loc_seg_baton.history_segments, iterpool));
- SVN_ERR(svn_mergeinfo_merge(*paths_history_mergeinfo,
- svn_mergeinfo_dup(path_history_mergeinfo,
- result_pool),
- result_pool));
+ SVN_ERR(svn_mergeinfo_merge2(*paths_history_mergeinfo,
+ svn_mergeinfo_dup(path_history_mergeinfo,
+ result_pool),
+ result_pool, iterpool));
}
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/replay.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/replay.c Mon Nov 21 07:07:56 2011
@@ -136,7 +136,7 @@ struct path_driver_cb_baton
void *authz_read_baton;
const char *base_path; /* relpath */
- int base_path_len;
+ size_t base_path_len;
svn_revnum_t low_water_mark;
/* Stack of active copy operations. */
@@ -372,7 +372,7 @@ path_driver_cb_func(void **dir_baton,
svn_fs_root_t *source_root = cb->compare_root;
const char *source_fspath = NULL;
const char *base_path = cb->base_path;
- int base_path_len = cb->base_path_len;
+ size_t base_path_len = cb->base_path_len;
*dir_baton = NULL;
@@ -573,8 +573,9 @@ path_driver_cb_func(void **dir_baton,
struct copy_info);
if (info->copyfrom_path)
{
- const char *relpath = svn_relpath__is_child(info->path,
- edit_path, pool);
+ const char *relpath = svn_relpath_skip_ancestor(info->path,
+ edit_path);
+ SVN_ERR_ASSERT(relpath && *relpath);
SVN_ERR(svn_fs_revision_root(&source_root,
svn_fs_root_fs(root),
info->copyfrom_rev, pool));
Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/reporter.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/reporter.c Mon Nov 21 07:07:56 2011
@@ -32,17 +32,19 @@
#include "svn_props.h"
#include "repos.h"
#include "svn_private_config.h"
+
#include "private/svn_dep_compat.h"
#include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
#define NUM_CACHED_SOURCE_ROOTS 4
-/* Theory of operation: we write report operations out to a temporary
- file as we receive them. When the report is finished, we read the
+/* Theory of operation: we write report operations out to a spill-buffer
+ as we receive them. When the report is finished, we read the
operations back out again, using them to guide the progression of
the delta between the source and target revs.
- Temporary file format: we use a simple ad-hoc format to store the
+ Spill-buffer content format: we use a simple ad-hoc format to store the
report operations. Each report operation is the concatention of
the following ("+/-" indicates the single character '+' or '-';
<length> and <revnum> are written out as decimal strings):
@@ -122,8 +124,8 @@ typedef struct report_baton_t
svn_repos_authz_func_t authz_read_func;
void *authz_read_baton;
- /* The temporary file in which we are stashing the report. */
- apr_file_t *tempfile;
+ /* The spill-buffer holding the report. */
+ svn_spillbuf_reader_t *reader;
/* For the actual editor drive, we'll need a lookahead path info
entry, a cache of FS roots, and a pool to store them. */
@@ -158,14 +160,14 @@ static svn_error_t *delta_dirs(report_ba
/* --- READING PREVIOUSLY STORED REPORT INFORMATION --- */
static svn_error_t *
-read_number(apr_uint64_t *num, apr_file_t *temp, apr_pool_t *pool)
+read_number(apr_uint64_t *num, svn_spillbuf_reader_t *reader, apr_pool_t *pool)
{
char c;
*num = 0;
while (1)
{
- SVN_ERR(svn_io_file_getc(&c, temp, pool));
+ SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
if (c == ':')
break;
*num = *num * 10 + (c - '0');
@@ -174,13 +176,14 @@ read_number(apr_uint64_t *num, apr_file_
}
static svn_error_t *
-read_string(const char **str, apr_file_t *temp, apr_pool_t *pool)
+read_string(const char **str, svn_spillbuf_reader_t *reader, apr_pool_t *pool)
{
apr_uint64_t len;
apr_size_t size;
+ apr_size_t amt;
char *buf;
- SVN_ERR(read_number(&len, temp, pool));
+ SVN_ERR(read_number(&len, reader, pool));
/* Len can never be less than zero. But could len be so large that
len + 1 wraps around and we end up passing 0 to apr_palloc(),
@@ -201,22 +204,26 @@ read_string(const char **str, apr_file_t
size = (apr_size_t)len;
buf = apr_palloc(pool, size+1);
- SVN_ERR(svn_io_file_read_full2(temp, buf, size, NULL, NULL, pool));
+ if (size > 0)
+ {
+ SVN_ERR(svn_spillbuf__reader_read(&amt, reader, buf, size, pool));
+ SVN_ERR_ASSERT(amt == size);
+ }
buf[len] = 0;
*str = buf;
return SVN_NO_ERROR;
}
static svn_error_t *
-read_rev(svn_revnum_t *rev, apr_file_t *temp, apr_pool_t *pool)
+read_rev(svn_revnum_t *rev, svn_spillbuf_reader_t *reader, apr_pool_t *pool)
{
char c;
apr_uint64_t num;
- SVN_ERR(svn_io_file_getc(&c, temp, pool));
+ SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
if (c == '+')
{
- SVN_ERR(read_number(&num, temp, pool));
+ SVN_ERR(read_number(&num, reader, pool));
*rev = (svn_revnum_t) num;
}
else
@@ -225,15 +232,15 @@ read_rev(svn_revnum_t *rev, apr_file_t *
}
/* Read a single character to set *DEPTH (having already read '+')
- from TEMP. PATH is the path to which the depth applies, and is
+ from READER. PATH is the path to which the depth applies, and is
used for error reporting only. */
static svn_error_t *
-read_depth(svn_depth_t *depth, apr_file_t *temp, const char *path,
+read_depth(svn_depth_t *depth, svn_spillbuf_reader_t *reader, const char *path,
apr_pool_t *pool)
{
char c;
- SVN_ERR(svn_io_file_getc(&c, temp, pool));
+ SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
switch (c)
{
case 'X':
@@ -260,14 +267,16 @@ read_depth(svn_depth_t *depth, apr_file_
return SVN_NO_ERROR;
}
-/* Read a report operation *PI out of TEMP. Set *PI to NULL if we
+/* Read a report operation *PI out of READER. Set *PI to NULL if we
have reached the end of the report. */
static svn_error_t *
-read_path_info(path_info_t **pi, apr_file_t *temp, apr_pool_t *pool)
+read_path_info(path_info_t **pi,
+ svn_spillbuf_reader_t *reader,
+ apr_pool_t *pool)
{
char c;
- SVN_ERR(svn_io_file_getc(&c, temp, pool));
+ SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
if (c == '-')
{
*pi = NULL;
@@ -275,23 +284,23 @@ read_path_info(path_info_t **pi, apr_fil
}
*pi = apr_palloc(pool, sizeof(**pi));
- SVN_ERR(read_string(&(*pi)->path, temp, pool));
- SVN_ERR(svn_io_file_getc(&c, temp, pool));
+ SVN_ERR(read_string(&(*pi)->path, reader, pool));
+ SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
if (c == '+')
- SVN_ERR(read_string(&(*pi)->link_path, temp, pool));
+ SVN_ERR(read_string(&(*pi)->link_path, reader, pool));
else
(*pi)->link_path = NULL;
- SVN_ERR(read_rev(&(*pi)->rev, temp, pool));
- SVN_ERR(svn_io_file_getc(&c, temp, pool));
+ SVN_ERR(read_rev(&(*pi)->rev, reader, pool));
+ SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
if (c == '+')
- SVN_ERR(read_depth(&((*pi)->depth), temp, (*pi)->path, pool));
+ SVN_ERR(read_depth(&((*pi)->depth), reader, (*pi)->path, pool));
else
(*pi)->depth = svn_depth_infinity;
- SVN_ERR(svn_io_file_getc(&c, temp, pool));
+ SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
(*pi)->start_empty = (c == '+');
- SVN_ERR(svn_io_file_getc(&c, temp, pool));
+ SVN_ERR(svn_spillbuf__reader_getc(&c, reader, pool));
if (c == '+')
- SVN_ERR(read_string(&(*pi)->lock_token, temp, pool));
+ SVN_ERR(read_string(&(*pi)->lock_token, reader, pool));
else
(*pi)->lock_token = NULL;
(*pi)->pool = pool;
@@ -306,7 +315,7 @@ relevant(path_info_t *pi, const char *pr
(!*prefix || pi->path[plen] == '/'));
}
-/* Fetch the next pathinfo from B->tempfile for a descendant of
+/* Fetch the next pathinfo from B->reader for a descendant of
PREFIX. If the next pathinfo is for an immediate child of PREFIX,
set *ENTRY to the path component of the report information and
*INFO to the path information for that entry. If the next pathinfo
@@ -353,7 +362,7 @@ fetch_path_info(report_baton_t *b, const
*entry = relpath;
*info = b->lookahead;
subpool = svn_pool_create(b->pool);
- SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+ SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
}
}
return SVN_NO_ERROR;
@@ -371,7 +380,7 @@ skip_path_info(report_baton_t *b, const
{
svn_pool_destroy(b->lookahead->pool);
subpool = svn_pool_create(b->pool);
- SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+ SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
}
return SVN_NO_ERROR;
}
@@ -1233,6 +1242,8 @@ drive(report_baton_t *b, svn_revnum_t s_
/* Collect information about the source and target nodes. */
s_fullpath = svn_fspath__join(b->fs_base, b->s_operand, pool);
+ /* ### Weird: When I have a file external defined as "^/A/a X/xa",
+ * ### S_FULLPATH becomes "/A/a/xa" here, which is complete nonsense. */
SVN_ERR(get_source_root(b, &s_root, s_rev));
SVN_ERR(fake_dirent(&s_entry, s_root, s_fullpath, pool));
SVN_ERR(fake_dirent(&t_entry, b->t_root, b->t_path, pool));
@@ -1277,7 +1288,6 @@ drive(report_baton_t *b, svn_revnum_t s_
static svn_error_t *
finish_report(report_baton_t *b, apr_pool_t *pool)
{
- apr_off_t offset;
path_info_t *info;
apr_pool_t *subpool;
svn_revnum_t s_rev;
@@ -1286,14 +1296,12 @@ finish_report(report_baton_t *b, apr_poo
/* Save our pool to manage the lookahead and fs_root cache with. */
b->pool = pool;
- /* Add an end marker and rewind the temporary file. */
- SVN_ERR(svn_io_file_write_full(b->tempfile, "-", 1, NULL, pool));
- offset = 0;
- SVN_ERR(svn_io_file_seek(b->tempfile, APR_SET, &offset, pool));
+ /* Add the end marker. */
+ SVN_ERR(svn_spillbuf__reader_write(b->reader, "-", 1, pool));
/* Read the first pathinfo from the report and verify that it is a top-level
set_path entry. */
- SVN_ERR(read_path_info(&info, b->tempfile, pool));
+ SVN_ERR(read_path_info(&info, b->reader, pool));
if (!info || strcmp(info->path, b->s_operand) != 0
|| info->link_path || !SVN_IS_VALID_REVNUM(info->rev))
return svn_error_create(SVN_ERR_REPOS_BAD_REVISION_REPORT, NULL,
@@ -1302,7 +1310,7 @@ finish_report(report_baton_t *b, apr_poo
/* Initialize the lookahead pathinfo. */
subpool = svn_pool_create(pool);
- SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+ SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
if (b->lookahead && strcmp(b->lookahead->path, b->s_operand) == 0)
{
@@ -1320,7 +1328,7 @@ finish_report(report_baton_t *b, apr_poo
b->lookahead->depth = info->depth;
}
info = b->lookahead;
- SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+ SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
}
/* Open the target root and initialize the source root cache. */
@@ -1342,7 +1350,7 @@ finish_report(report_baton_t *b, apr_poo
/* --- COLLECTING THE REPORT INFORMATION --- */
-/* Record a report operation into the temporary file. Return an error
+/* Record a report operation into the spill buffer. Return an error
if DEPTH is svn_depth_unknown. */
static svn_error_t *
write_path_info(report_baton_t *b, const char *path, const char *lpath,
@@ -1381,7 +1389,7 @@ write_path_info(report_baton_t *b, const
rep = apr_psprintf(pool, "+%" APR_SIZE_T_FMT ":%s%s%s%s%c%s",
strlen(path), path, lrep, rrep, drep,
start_empty ? '+' : '-', ltrep);
- return svn_io_file_write_full(b->tempfile, rep, strlen(rep), NULL, pool);
+ return svn_spillbuf__reader_write(b->reader, rep, strlen(rep), pool);
}
svn_error_t *
@@ -1420,20 +1428,14 @@ svn_error_t *
svn_repos_finish_report(void *baton, apr_pool_t *pool)
{
report_baton_t *b = baton;
- svn_error_t *finish_err, *close_err;
-
- finish_err = finish_report(b, pool);
- close_err = svn_io_file_close(b->tempfile, pool);
- return svn_error_trace(svn_error_compose_create(finish_err, close_err));
+ return svn_error_trace(finish_report(b, pool));
}
svn_error_t *
svn_repos_abort_report(void *baton, apr_pool_t *pool)
{
- report_baton_t *b = baton;
-
- return svn_error_trace(svn_io_file_close(b->tempfile, pool));
+ return SVN_NO_ERROR;
}
/* --- BEGINNING THE REPORT --- */
@@ -1482,10 +1484,9 @@ svn_repos_begin_report2(void **report_ba
b->authz_read_baton = authz_read_baton;
b->revision_infos = apr_hash_make(pool);
b->pool = pool;
-
- SVN_ERR(svn_io_open_unique_file3(&b->tempfile, NULL, NULL,
- svn_io_file_del_on_pool_cleanup,
- pool, pool));
+ b->reader = svn_spillbuf__reader_create(1000 /* blocksize */,
+ 1000000 /* maxsize */,
+ pool);
/* Hand reporter back to client. */
*report_baton = b;
Modified: subversion/branches/svn-bisect/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_repos/rev_hunt.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_repos/rev_hunt.c Mon Nov 21 07:07:56 2011
@@ -590,7 +590,7 @@ svn_repos__prev_location(svn_revnum_t *a
apr_pool_t *pool)
{
svn_fs_root_t *root, *copy_root;
- const char *copy_path, *copy_src_path, *remainder = "";
+ const char *copy_path, *copy_src_path, *remainder;
svn_revnum_t copy_src_rev;
/* Initialize return variables. */
@@ -623,8 +623,7 @@ svn_repos__prev_location(svn_revnum_t *a
*/
SVN_ERR(svn_fs_copied_from(©_src_rev, ©_src_path,
copy_root, copy_path, pool));
- if (! strcmp(copy_path, path) == 0)
- remainder = svn_fspath__is_child(copy_path, path, pool);
+ remainder = svn_fspath__skip_ancestor(copy_path, path);
if (prev_path)
*prev_path = svn_fspath__join(copy_src_path, remainder, pool);
if (appeared_rev)
@@ -983,31 +982,27 @@ get_path_mergeinfo(apr_hash_t **mergeinf
svn_fs_t *fs,
const char *path,
svn_revnum_t revnum,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_mergeinfo_catalog_t tmp_catalog;
svn_fs_root_t *root;
- apr_pool_t *subpool = svn_pool_create(pool);
- apr_array_header_t *paths = apr_array_make(subpool, 1,
+ apr_array_header_t *paths = apr_array_make(scratch_pool, 1,
sizeof(const char *));
APR_ARRAY_PUSH(paths, const char *) = path;
- SVN_ERR(svn_fs_revision_root(&root, fs, revnum, subpool));
+ SVN_ERR(svn_fs_revision_root(&root, fs, revnum, scratch_pool));
/* We do not need to call svn_repos_fs_get_mergeinfo() (which performs authz)
because we will filter out unreadable revisions in
find_interesting_revision(), above */
SVN_ERR(svn_fs_get_mergeinfo2(&tmp_catalog, root, paths,
- svn_mergeinfo_inherited, FALSE, FALSE,
- subpool));
+ svn_mergeinfo_inherited, FALSE, TRUE,
+ result_pool, scratch_pool));
*mergeinfo = apr_hash_get(tmp_catalog, path, APR_HASH_KEY_STRING);
- if (*mergeinfo)
- *mergeinfo = svn_mergeinfo_dup(*mergeinfo, pool);
- else
- *mergeinfo = apr_hash_make(pool);
-
- svn_pool_destroy(subpool);
+ if (!*mergeinfo)
+ *mergeinfo = apr_hash_make(result_pool);
return SVN_NO_ERROR;
}
@@ -1044,9 +1039,9 @@ static svn_error_t *
get_merged_mergeinfo(apr_hash_t **merged_mergeinfo,
svn_repos_t *repos,
struct path_revision *old_path_rev,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- apr_pool_t *subpool = svn_pool_create(pool);
apr_hash_t *curr_mergeinfo, *prev_mergeinfo, *deleted, *changed;
svn_error_t *err;
svn_fs_root_t *root;
@@ -1056,8 +1051,8 @@ get_merged_mergeinfo(apr_hash_t **merged
/* Getting/parsing/diffing svn:mergeinfo is expensive, so only do it
if there is a property change. */
SVN_ERR(svn_fs_revision_root(&root, repos->fs, old_path_rev->revnum,
- subpool));
- SVN_ERR(svn_fs_paths_changed2(&changed_paths, root, subpool));
+ scratch_pool));
+ SVN_ERR(svn_fs_paths_changed2(&changed_paths, root, scratch_pool));
while (1)
{
svn_fs_path_change2_t *changed_path = apr_hash_get(changed_paths,
@@ -1067,17 +1062,17 @@ get_merged_mergeinfo(apr_hash_t **merged
break;
if (svn_fspath__is_root(path, strlen(path)))
{
- svn_pool_destroy(subpool);
*merged_mergeinfo = NULL;
return SVN_NO_ERROR;
}
- path = svn_fspath__dirname(path, subpool);
+ path = svn_fspath__dirname(path, scratch_pool);
}
/* First, find the mergeinfo difference for old_path_rev->revnum, and
old_path_rev->revnum - 1. */
err = get_path_mergeinfo(&curr_mergeinfo, repos->fs, old_path_rev->path,
- old_path_rev->revnum, subpool);
+ old_path_rev->revnum, scratch_pool,
+ scratch_pool);
if (err)
{
if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
@@ -1086,7 +1081,6 @@ get_merged_mergeinfo(apr_hash_t **merged
best we can do is ignore it and act is if there are
no mergeinfo differences. */
svn_error_clear(err);
- svn_pool_destroy(subpool);
*merged_mergeinfo = NULL;
return SVN_NO_ERROR;
}
@@ -1097,14 +1091,14 @@ get_merged_mergeinfo(apr_hash_t **merged
}
err = get_path_mergeinfo(&prev_mergeinfo, repos->fs, old_path_rev->path,
- old_path_rev->revnum - 1, subpool);
+ old_path_rev->revnum - 1, scratch_pool,
+ scratch_pool);
if (err && (err->apr_err == SVN_ERR_FS_NOT_FOUND
|| err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR))
{
/* If the path doesn't exist in the previous revision or it does exist
but has invalid mergeinfo (Issue #3896), assume no merges. */
svn_error_clear(err);
- svn_pool_destroy(subpool);
*merged_mergeinfo = NULL;
return SVN_NO_ERROR;
}
@@ -1112,18 +1106,17 @@ get_merged_mergeinfo(apr_hash_t **merged
SVN_ERR(err);
/* Then calculate and merge the differences. */
- SVN_ERR(svn_mergeinfo_diff(&deleted, &changed, prev_mergeinfo, curr_mergeinfo,
- FALSE, subpool));
- SVN_ERR(svn_mergeinfo_merge(changed, deleted, subpool));
+ SVN_ERR(svn_mergeinfo_diff2(&deleted, &changed, prev_mergeinfo,
+ curr_mergeinfo, FALSE, result_pool,
+ scratch_pool));
+ SVN_ERR(svn_mergeinfo_merge2(changed, deleted, result_pool, scratch_pool));
/* Store the result. */
if (apr_hash_count(changed))
- *merged_mergeinfo = svn_mergeinfo_dup(changed, pool);
+ *merged_mergeinfo = changed;
else
*merged_mergeinfo = NULL;
- svn_pool_destroy(subpool);
-
return SVN_NO_ERROR;
}
@@ -1206,7 +1199,7 @@ find_interesting_revisions(apr_array_hea
if (include_merged_revisions)
SVN_ERR(get_merged_mergeinfo(&path_rev->merged_mergeinfo, repos,
- path_rev, result_pool));
+ path_rev, result_pool, iterpool));
else
path_rev->merged_mergeinfo = NULL;
Propchange: subversion/branches/svn-bisect/subversion/libsvn_subr/adler32.c
('svn:mergeinfo' removed)
Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/cache-inprocess.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/cache-inprocess.c Mon Nov 21 07:07:56 2011
@@ -30,6 +30,7 @@
#include "svn_private_config.h"
#include "cache.h"
+#include "private/svn_mutex.h"
/* The (internal) cache object. */
typedef struct inprocess_cache_t {
@@ -80,12 +81,10 @@ typedef struct inprocess_cache_t {
*/
apr_size_t data_size;
-#if APR_HAS_THREADS
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe. */
- apr_thread_mutex_t *mutex;
-#endif
+ svn_mutex__t *mutex;
} inprocess_cache_t;
/* A cache page; all items on the page are allocated from the same
@@ -182,39 +181,28 @@ duplicate_key(inprocess_cache_t *cache,
return apr_pmemdup(pool, key, cache->klen);
}
-/* If applicable, locks CACHE's mutex. */
static svn_error_t *
-lock_cache(inprocess_cache_t *cache)
+inprocess_cache_get_internal(char **buffer,
+ apr_size_t *size,
+ inprocess_cache_t *cache,
+ const void *key,
+ apr_pool_t *result_pool)
{
-#if APR_HAS_THREADS
- apr_status_t status;
- if (! cache->mutex)
- return SVN_NO_ERROR;
-
- status = apr_thread_mutex_lock(cache->mutex);
- if (status)
- return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
-#endif
+ struct cache_entry *entry = apr_hash_get(cache->hash, key, cache->klen);
- return SVN_NO_ERROR;
-}
-
-/* If applicable, unlocks CACHE's mutex, then returns ERR. */
-static svn_error_t *
-unlock_cache(inprocess_cache_t *cache,
- svn_error_t *err)
-{
-#if APR_HAS_THREADS
- apr_status_t status;
- if (! cache->mutex)
- return err;
+ *buffer = NULL;
+ if (entry)
+ {
+ SVN_ERR(move_page_to_front(cache, entry->page));
- status = apr_thread_mutex_unlock(cache->mutex);
- if (status && !err)
- return svn_error_wrap_apr(status, _("Can't unlock cache mutex"));
-#endif
+ /* duplicate the buffer entry */
+ *buffer = apr_palloc(result_pool, entry->size);
+ memcpy(*buffer, entry->value, entry->size);
- return err;
+ *size = entry->size;
+ }
+
+ return SVN_NO_ERROR;
}
static svn_error_t *
@@ -225,38 +213,24 @@ inprocess_cache_get(void **value_p,
apr_pool_t *result_pool)
{
inprocess_cache_t *cache = cache_void;
- svn_error_t *err = NULL;
- struct cache_entry *entry;
char* buffer;
+ apr_size_t size;
- SVN_ERR(lock_cache(cache));
-
- entry = apr_hash_get(cache->hash, key, cache->klen);
- if (! entry)
- {
- *found = FALSE;
- return unlock_cache(cache, SVN_NO_ERROR);
- }
-
- SVN_ERR(move_page_to_front(cache, entry->page));
-
- /* duplicate the buffer entry */
- buffer = apr_palloc(result_pool, entry->size);
- memcpy(buffer, entry->value, entry->size);
-
- /* the cache is no longer being accessed */
- SVN_ERR(unlock_cache(cache, SVN_NO_ERROR));
-
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_get_internal(&buffer,
+ &size,
+ cache,
+ key,
+ result_pool));
+
/* deserialize the buffer content. Usually, this will directly
modify the buffer content directly.
*/
- *found = TRUE;
- if (entry->value)
- err = cache->deserialize_func(value_p, buffer, entry->size, result_pool);
- else
- *value_p = NULL;
-
- return err;
+ *value_p = NULL;
+ *found = buffer != NULL;
+ return buffer && size
+ ? cache->deserialize_func(value_p, buffer, size, result_pool)
+ : SVN_NO_ERROR;
}
/* Removes PAGE from the LRU list, removes all of its entries from
@@ -292,16 +266,12 @@ erase_page(inprocess_cache_t *cache,
static svn_error_t *
-inprocess_cache_set(void *cache_void,
- const void *key,
- void *value,
- apr_pool_t *scratch_pool)
+inprocess_cache_set_internal(inprocess_cache_t *cache,
+ const void *key,
+ void *value,
+ apr_pool_t *scratch_pool)
{
- inprocess_cache_t *cache = cache_void;
struct cache_entry *existing_entry;
- svn_error_t *err = SVN_NO_ERROR;
-
- SVN_ERR(lock_cache(cache));
existing_entry = apr_hash_get(cache->hash, key, cache->klen);
@@ -333,11 +303,13 @@ inprocess_cache_set(void *cache_void,
cache->data_size -= existing_entry->size;
if (value)
{
- err = cache->serialize_func((char **)&existing_entry->value,
- &existing_entry->size,
- value,
- page->page_pool);
+ SVN_ERR(cache->serialize_func((char **)&existing_entry->value,
+ &existing_entry->size,
+ value,
+ page->page_pool));
cache->data_size += existing_entry->size;
+ if (existing_entry->size == 0)
+ existing_entry->value = NULL;
}
else
{
@@ -345,7 +317,7 @@ inprocess_cache_set(void *cache_void,
existing_entry->size = 0;
}
- goto cleanup;
+ return SVN_NO_ERROR;
}
/* Do we not have a partial page to put it on, but we are allowed to
@@ -383,11 +355,13 @@ inprocess_cache_set(void *cache_void,
new_entry->key = duplicate_key(cache, key, page->page_pool);
if (value)
{
- err = cache->serialize_func((char **)&new_entry->value,
- &new_entry->size,
- value,
- page->page_pool);
+ SVN_ERR(cache->serialize_func((char **)&new_entry->value,
+ &new_entry->size,
+ value,
+ page->page_pool));
cache->data_size += new_entry->size;
+ if (new_entry->size == 0)
+ new_entry->value = NULL;
}
else
{
@@ -395,9 +369,6 @@ inprocess_cache_set(void *cache_void,
new_entry->size = 0;
}
- if (err)
- goto cleanup;
-
/* Add the entry to the page's list. */
new_entry->page = page;
new_entry->next_entry = page->first_entry;
@@ -418,8 +389,24 @@ inprocess_cache_set(void *cache_void,
}
}
- cleanup:
- return unlock_cache(cache, err);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_set(void *cache_void,
+ const void *key,
+ void *value,
+ apr_pool_t *scratch_pool)
+{
+ inprocess_cache_t *cache = cache_void;
+
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_set_internal(cache,
+ key,
+ value,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
}
/* Baton type for svn_cache__iter. */
@@ -455,10 +442,33 @@ inprocess_cache_iter(svn_boolean_t *comp
b.user_cb = user_cb;
b.user_baton = user_baton;
- SVN_ERR(lock_cache(cache));
- return unlock_cache(cache,
- svn_iter_apr_hash(completed, cache->hash, iter_cb, &b,
- scratch_pool));
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ svn_iter_apr_hash(completed, cache->hash,
+ iter_cb, &b, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_get_partial_internal(void **value_p,
+ svn_boolean_t *found,
+ inprocess_cache_t *cache,
+ const void *key,
+ svn_cache__partial_getter_func_t func,
+ void *baton,
+ apr_pool_t *result_pool)
+{
+ struct cache_entry *entry = apr_hash_get(cache->hash, key, cache->klen);
+ if (! entry)
+ {
+ *found = FALSE;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(move_page_to_front(cache, entry->page));
+
+ *found = TRUE;
+ return func(value_p, entry->value, entry->size, baton, result_pool);
}
static svn_error_t *
@@ -471,23 +481,40 @@ inprocess_cache_get_partial(void **value
apr_pool_t *result_pool)
{
inprocess_cache_t *cache = cache_void;
- struct cache_entry *entry;
- SVN_ERR(lock_cache(cache));
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_get_partial_internal(value_p,
+ found,
+ cache,
+ key,
+ func,
+ baton,
+ result_pool));
- entry = apr_hash_get(cache->hash, key, cache->klen);
- if (! entry)
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+inprocess_cache_set_partial_internal(inprocess_cache_t *cache,
+ const void *key,
+ svn_cache__partial_setter_func_t func,
+ void *baton,
+ apr_pool_t *scratch_pool)
+{
+ struct cache_entry *entry = apr_hash_get(cache->hash, key, cache->klen);
+ if (entry)
{
- *found = FALSE;
- return unlock_cache(cache, SVN_NO_ERROR);
- }
+ SVN_ERR(move_page_to_front(cache, entry->page));
- SVN_ERR(move_page_to_front(cache, entry->page));
+ cache->data_size -= entry->size;
+ SVN_ERR(func((char **)&entry->value,
+ &entry->size,
+ baton,
+ entry->page->page_pool));
+ cache->data_size += entry->size;
+ }
- *found = TRUE;
- return unlock_cache(cache,
- func(value_p, entry->value, entry->size, baton,
- result_pool));
+ return SVN_NO_ERROR;
}
static svn_error_t *
@@ -498,25 +525,15 @@ inprocess_cache_set_partial(void *cache_
apr_pool_t *scratch_pool)
{
inprocess_cache_t *cache = cache_void;
- struct cache_entry *entry;
- svn_error_t *err = SVN_NO_ERROR;
-
- SVN_ERR(lock_cache(cache));
-
- entry = apr_hash_get(cache->hash, key, cache->klen);
- if (! entry)
- return unlock_cache(cache, err);
- SVN_ERR(move_page_to_front(cache, entry->page));
-
- cache->data_size -= entry->size;
- err = func((char **)&entry->value,
- &entry->size,
- baton,
- entry->page->page_pool);
- cache->data_size += entry->size;
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_set_partial_internal(cache,
+ key,
+ func,
+ baton,
+ scratch_pool));
- return unlock_cache(cache, err);
+ return SVN_NO_ERROR;
}
static svn_boolean_t
@@ -532,15 +549,10 @@ inprocess_cache_is_cachable(void *cache_
}
static svn_error_t *
-inprocess_cache_get_info(void *cache_void,
- svn_cache__info_t *info,
- svn_boolean_t reset,
- apr_pool_t *result_pool)
+inprocess_cache_get_info_internal(inprocess_cache_t *cache,
+ svn_cache__info_t *info,
+ apr_pool_t *result_pool)
{
- inprocess_cache_t *cache = cache_void;
-
- SVN_ERR(lock_cache(cache));
-
info->id = apr_pstrdup(result_pool, cache->id);
info->used_entries = apr_hash_count(cache->hash);
@@ -552,10 +564,26 @@ inprocess_cache_get_info(void *cache_voi
+ cache->items_per_page * sizeof(struct cache_page)
+ info->used_entries * sizeof(struct cache_entry);
- return unlock_cache(cache, SVN_NO_ERROR);
+ return SVN_NO_ERROR;
}
+static svn_error_t *
+inprocess_cache_get_info(void *cache_void,
+ svn_cache__info_t *info,
+ svn_boolean_t reset,
+ apr_pool_t *result_pool)
+{
+ inprocess_cache_t *cache = cache_void;
+
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ inprocess_cache_get_info_internal(cache,
+ info,
+ result_pool));
+
+ return SVN_NO_ERROR;
+}
+
static svn_cache__vtable_t inprocess_cache_vtable = {
inprocess_cache_get,
inprocess_cache_set,
@@ -602,17 +630,7 @@ svn_cache__create_inprocess(svn_cache__t
/* The sentinel doesn't need a pool. (We're happy to crash if we
* accidentally try to treat it like a real page.) */
-#if APR_HAS_THREADS
- if (thread_safe)
- {
- apr_status_t status = apr_thread_mutex_create(&(cache->mutex),
- APR_THREAD_MUTEX_DEFAULT,
- pool);
- if (status)
- return svn_error_wrap_apr(status,
- _("Can't create cache mutex"));
- }
-#endif
+ SVN_ERR(svn_mutex__init(&cache->mutex, thread_safe, pool));
cache->cache_pool = pool;
Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/cache-membuffer.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/cache-membuffer.c Mon Nov 21 07:07:56 2011
@@ -30,6 +30,7 @@
#include "cache.h"
#include "svn_string.h"
#include "private/svn_dep_compat.h"
+#include "private/svn_mutex.h"
/*
* This svn_cache__t implementation actually consists of two parts:
@@ -423,13 +424,11 @@ struct svn_membuffer_t
*/
apr_uint64_t total_hits;
-#if APR_HAS_THREADS
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe.
*/
- apr_thread_mutex_t *mutex;
-#endif
+ svn_mutex__t *mutex;
};
/* Align integer VALUE to the next ITEM_ALIGNMENT boundary.
@@ -440,43 +439,6 @@ struct svn_membuffer_t
*/
#define ALIGN_POINTER(pointer) ((void*)ALIGN_VALUE((apr_size_t)(char*)(pointer)))
-/* Acquire the cache mutex, if necessary.
- */
-static svn_error_t *
-lock_cache(svn_membuffer_t *cache)
-{
-#if APR_HAS_THREADS
- if (cache->mutex)
- {
- apr_status_t status = apr_thread_mutex_lock(cache->mutex);
- if (status)
- return svn_error_wrap_apr(status, _("Can't lock cache mutex"));
- }
-#endif
-
- return SVN_NO_ERROR;
-}
-
-/* Release the cache mutex, if necessary.
- */
-static svn_error_t *
-unlock_cache(svn_membuffer_t *cache, svn_error_t *err)
-{
-#if APR_HAS_THREADS
- if (cache->mutex)
- {
- apr_status_t status = apr_thread_mutex_unlock(cache->mutex);
- if (err)
- return err;
-
- if (status)
- return svn_error_wrap_apr(status, _("Can't unlock cache mutex"));
- }
-#endif
-
- return err;
-}
-
/* Resolve a dictionary entry reference, i.e. return the entry
* for the given IDX.
*/
@@ -713,7 +675,7 @@ initialize_group(svn_membuffer_t *cache,
static entry_t *
find_entry(svn_membuffer_t *cache,
apr_uint32_t group_index,
- unsigned char *to_find,
+ const unsigned char *to_find,
svn_boolean_t find_empty)
{
entry_t *group;
@@ -1076,25 +1038,10 @@ svn_cache__membuffer_cache_create(svn_me
return svn_error_wrap_apr(APR_ENOMEM, _("OOM"));
}
-#if APR_HAS_THREADS
/* A lock for intra-process synchronization to the cache, or NULL if
* the cache's creator doesn't feel the cache needs to be
* thread-safe. */
-
- c[seg].mutex = NULL;
- if (thread_safe)
- {
- apr_status_t status =
- apr_thread_mutex_create(&(c[seg].mutex),
- APR_THREAD_MUTEX_DEFAULT,
- pool);
- if (status)
- return svn_error_wrap_apr(status, _("Can't create cache mutex"));
- }
-#else
- if (thread_safe)
- return svn_error_wrap_apr(APR_ENOTIMPL, _("APR doesn't support threads"));
-#endif
+ SVN_ERR(svn_mutex__init(&c[seg].mutex, thread_safe, pool));
}
/* done here
@@ -1104,48 +1051,30 @@ svn_cache__membuffer_cache_create(svn_me
}
-/* Try to insert the ITEM and use the KEY to unqiuely identify it.
+/* Try to insert the serialized item given in BUFFER with SIZE into
+ * the group GROUP_INDEX of CACHE and uniquely identify it by hash
+ * value TO_FIND.
+ *
* However, there is no guarantee that it will actually be put into
- * the cache. If there is already some data associated to the KEY,
+ * the cache. If there is already some data associated with TO_FIND,
* it will be removed from the cache even if the new data cannot
* be inserted.
- *
- * The SERIALIZER is called to transform the ITEM into a single,
- * flat data buffer. Temporary allocations may be done in POOL.
+ *
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_get_partial instead.
*/
static svn_error_t *
-membuffer_cache_set(svn_membuffer_t *cache,
- const void *key,
- apr_size_t key_len,
- void *item,
- svn_cache__serialize_func_t serializer,
- DEBUG_CACHE_MEMBUFFER_TAG_ARG
- apr_pool_t *scratch_pool)
+membuffer_cache_set_internal(svn_membuffer_t *cache,
+ const unsigned char *to_find,
+ apr_uint32_t group_index,
+ char *buffer,
+ apr_size_t size,
+ DEBUG_CACHE_MEMBUFFER_TAG_ARG
+ apr_pool_t *scratch_pool)
{
- apr_uint32_t group_index;
- unsigned char to_find[KEY_SIZE];
- entry_t *entry;
- char *buffer;
- apr_size_t size;
-
- /* find the entry group that will hold the key.
- */
- group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
- if (group_index == NO_INDEX)
- return SVN_NO_ERROR;
-
- /* Serialize data data.
- */
- if (item)
- SVN_ERR(serializer(&buffer, &size, item, scratch_pool));
-
- /* The actual cache data access needs to sync'ed
- */
- SVN_ERR(lock_cache(cache));
-
/* if necessary, enlarge the insertion window.
*/
- if ( item != NULL
+ if ( buffer != NULL
&& cache->data_size / 4 > size
&& ensure_data_insertable(cache, size))
{
@@ -1153,7 +1082,7 @@ membuffer_cache_set(svn_membuffer_t *cac
* Get an unused entry for the key and and initialize it with
* the serialized item's (future) posion within data buffer.
*/
- entry = find_entry(cache, group_index, to_find, TRUE);
+ entry_t *entry = find_entry(cache, group_index, to_find, TRUE);
entry->size = size;
entry->offset = cache->current_data;
@@ -1182,44 +1111,76 @@ membuffer_cache_set(svn_membuffer_t *cac
*/
find_entry(cache, group_index, to_find, TRUE);
}
-
- /* done here -> unlock the cache
- */
- return unlock_cache(cache, SVN_NO_ERROR);
+ return SVN_NO_ERROR;
}
-/* Look for the *ITEM identified by KEY. If no item has been stored
- * for KEY, *ITEM will be NULL. Otherwise, the DESERIALIZER is called
- * re-construct the proper object from the serialized data.
- * Allocations will be done in POOL.
+/* Try to insert the ITEM and use the KEY to unqiuely identify it.
+ * However, there is no guarantee that it will actually be put into
+ * the cache. If there is already some data associated to the KEY,
+ * it will be removed from the cache even if the new data cannot
+ * be inserted.
+ *
+ * The SERIALIZER is called to transform the ITEM into a single,
+ * flat data buffer. Temporary allocations may be done in POOL.
*/
static svn_error_t *
-membuffer_cache_get(svn_membuffer_t *cache,
+membuffer_cache_set(svn_membuffer_t *cache,
const void *key,
apr_size_t key_len,
- void **item,
- svn_cache__deserialize_func_t deserializer,
+ void *item,
+ svn_cache__serialize_func_t serializer,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
- apr_pool_t *result_pool)
+ apr_pool_t *scratch_pool)
{
apr_uint32_t group_index;
unsigned char to_find[KEY_SIZE];
- entry_t *entry;
- char *buffer;
+ char *buffer = NULL;
apr_size_t size;
/* find the entry group that will hold the key.
*/
- group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
+ group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
if (group_index == NO_INDEX)
- {
- /* Some error occured, return "item not found".
- */
- *item = NULL;
- return SVN_NO_ERROR;
- }
+ return SVN_NO_ERROR;
+
+ /* Serialize data data.
+ */
+ if (item)
+ SVN_ERR(serializer(&buffer, &size, item, scratch_pool));
- SVN_ERR(lock_cache(cache));
+ /* The actual cache data access needs to sync'ed
+ */
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ membuffer_cache_set_internal(cache,
+ to_find,
+ group_index,
+ buffer,
+ size,
+ DEBUG_CACHE_MEMBUFFER_TAG
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. If no item has been stored for KEY,
+ * *BUFFER will be NULL. Otherwise, return a copy of the serialized
+ * data in *BUFFER and return its size in *ITEM_SIZE. Allocations will
+ * be done in POOL.
+ *
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_get_partial instead.
+ */
+static svn_error_t *
+membuffer_cache_get_internal(svn_membuffer_t *cache,
+ apr_uint32_t group_index,
+ const unsigned char *to_find,
+ char **buffer,
+ apr_size_t *item_size,
+ DEBUG_CACHE_MEMBUFFER_TAG_ARG
+ apr_pool_t *result_pool)
+{
+ entry_t *entry;
+ apr_size_t size;
/* The actual cache data access needs to sync'ed
*/
@@ -1229,13 +1190,15 @@ membuffer_cache_get(svn_membuffer_t *cac
{
/* no such entry found.
*/
- *item = NULL;
- return unlock_cache(cache, SVN_NO_ERROR);
+ *buffer = NULL;
+ *item_size = 0;
+
+ return SVN_NO_ERROR;
}
-
+
size = ALIGN_VALUE(entry->size);
- buffer = ALIGN_POINTER(apr_palloc(result_pool, size + ITEM_ALIGNMENT-1));
- memcpy(buffer, (const char*)cache->data + entry->offset, size);
+ *buffer = ALIGN_POINTER(apr_palloc(result_pool, size + ITEM_ALIGNMENT-1));
+ memcpy(*buffer, (const char*)cache->data + entry->offset, size);
#ifdef SVN_DEBUG_CACHE_MEMBUFFER
@@ -1258,45 +1221,91 @@ membuffer_cache_get(svn_membuffer_t *cac
cache->hit_count++;
cache->total_hits++;
- SVN_ERR(unlock_cache(cache, SVN_NO_ERROR));
-
- /* re-construct the original data object from its serialized form.
- */
- return deserializer(item, buffer, entry->size, result_pool);
+ *item_size = entry->size;
+
+ return SVN_NO_ERROR;
}
-/* Look for the cache entry identified by KEY and KEY_LEN. FOUND indicates
- * whether that entry exists. If not found, *ITEM will be NULL. Otherwise,
- * the DESERIALIZER is called with that entry and the BATON provided
- * and will extract the desired information. The result is set in *ITEM.
+/* Look for the *ITEM identified by KEY. If no item has been stored
+ * for KEY, *ITEM will be NULL. Otherwise, the DESERIALIZER is called
+ * re-construct the proper object from the serialized data.
* Allocations will be done in POOL.
*/
static svn_error_t *
-membuffer_cache_get_partial(svn_membuffer_t *cache,
- const void *key,
- apr_size_t key_len,
- void **item,
- svn_boolean_t *found,
- svn_cache__partial_getter_func_t deserializer,
- void *baton,
- DEBUG_CACHE_MEMBUFFER_TAG_ARG
- apr_pool_t *result_pool)
+membuffer_cache_get(svn_membuffer_t *cache,
+ const void *key,
+ apr_size_t key_len,
+ void **item,
+ svn_cache__deserialize_func_t deserializer,
+ DEBUG_CACHE_MEMBUFFER_TAG_ARG
+ apr_pool_t *result_pool)
{
apr_uint32_t group_index;
unsigned char to_find[KEY_SIZE];
- entry_t *entry;
- svn_error_t *err = SVN_NO_ERROR;
+ char *buffer;
+ apr_size_t size;
+ /* find the entry group that will hold the key.
+ */
group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
+ if (group_index == NO_INDEX)
+ {
+ /* Some error occured, return "item not found".
+ */
+ *item = NULL;
+ return SVN_NO_ERROR;
+ }
- SVN_ERR(lock_cache(cache));
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ membuffer_cache_get_internal(cache,
+ group_index,
+ to_find,
+ &buffer,
+ &size,
+ DEBUG_CACHE_MEMBUFFER_TAG
+ result_pool));
- entry = find_entry(cache, group_index, to_find, FALSE);
+ /* re-construct the original data object from its serialized form.
+ */
+ if (buffer == NULL)
+ {
+ *item = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ return deserializer(item, buffer, size, result_pool);
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. FOUND indicates whether that entry exists.
+ * If not found, *ITEM will be NULL.
+ *
+ * Otherwise, the DESERIALIZER is called with that entry and the BATON
+ * provided and will extract the desired information. The result is set
+ * in *ITEM. Allocations will be done in POOL.
+ *
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_get_partial instead.
+ */
+static svn_error_t *
+membuffer_cache_get_partial_internal(svn_membuffer_t *cache,
+ apr_uint32_t group_index,
+ const unsigned char *to_find,
+ void **item,
+ svn_boolean_t *found,
+ svn_cache__partial_getter_func_t deserializer,
+ void *baton,
+ DEBUG_CACHE_MEMBUFFER_TAG_ARG
+ apr_pool_t *result_pool)
+{
+ entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
cache->total_reads++;
if (entry == NULL)
{
*item = NULL;
*found = FALSE;
+
+ return SVN_NO_ERROR;
}
else
{
@@ -1324,50 +1333,75 @@ membuffer_cache_get_partial(svn_membuffe
#endif
- err = deserializer(item,
- (const char*)cache->data + entry->offset,
- entry->size,
- baton,
- result_pool);
+ return deserializer(item,
+ (const char*)cache->data + entry->offset,
+ entry->size,
+ baton,
+ result_pool);
}
-
- /* done here -> unlock the cache
- */
- return unlock_cache(cache, err);
}
-/* Look for the cache entry identified by KEY and KEY_LEN. If no entry
- * has been found, the function returns without modifying the cache.
- * Otherwise, FUNC is called with that entry and the BATON provided
- * and may modify the cache entry. Allocations will be done in POOL.
+/* Look for the cache entry identified by KEY and KEY_LEN. FOUND indicates
+ * whether that entry exists. If not found, *ITEM will be NULL. Otherwise,
+ * the DESERIALIZER is called with that entry and the BATON provided
+ * and will extract the desired information. The result is set in *ITEM.
+ * Allocations will be done in POOL.
*/
static svn_error_t *
-membuffer_cache_set_partial(svn_membuffer_t *cache,
+membuffer_cache_get_partial(svn_membuffer_t *cache,
const void *key,
apr_size_t key_len,
- svn_cache__partial_setter_func_t func,
+ void **item,
+ svn_boolean_t *found,
+ svn_cache__partial_getter_func_t deserializer,
void *baton,
DEBUG_CACHE_MEMBUFFER_TAG_ARG
- apr_pool_t *scratch_pool)
+ apr_pool_t *result_pool)
{
apr_uint32_t group_index;
unsigned char to_find[KEY_SIZE];
- entry_t *entry;
- svn_error_t *err = SVN_NO_ERROR;
- /* cache item lookup
- */
- group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
+ group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
- SVN_ERR(lock_cache(cache));
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ membuffer_cache_get_partial_internal
+ (cache, group_index, to_find, item, found,
+ deserializer, baton, DEBUG_CACHE_MEMBUFFER_TAG
+ result_pool));
- entry = find_entry(cache, group_index, to_find, FALSE);
+ return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. If no entry has been found, the function
+ * returns without modifying the cache.
+ *
+ * Otherwise, FUNC is called with that entry and the BATON provided
+ * and may modify the cache entry. Allocations will be done in POOL.
+ *
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_set_partial instead.
+ */
+static svn_error_t *
+membuffer_cache_set_partial_internal(svn_membuffer_t *cache,
+ apr_uint32_t group_index,
+ const unsigned char *to_find,
+ svn_cache__partial_setter_func_t func,
+ void *baton,
+ DEBUG_CACHE_MEMBUFFER_TAG_ARG
+ apr_pool_t *scratch_pool)
+{
+ /* cache item lookup
+ */
+ entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
cache->total_reads++;
/* this function is a no-op if the item is not in cache
*/
if (entry != NULL)
{
+ svn_error_t *err;
+
/* access the serialized cache item */
char *data = (char*)cache->data + entry->offset;
char *orig_data = data;
@@ -1441,9 +1475,39 @@ membuffer_cache_set_partial(svn_membuffe
}
}
+ return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry identified by KEY and KEY_LEN. If no entry
+ * has been found, the function returns without modifying the cache.
+ * Otherwise, FUNC is called with that entry and the BATON provided
+ * and may modify the cache entry. Allocations will be done in POOL.
+ */
+static svn_error_t *
+membuffer_cache_set_partial(svn_membuffer_t *cache,
+ const void *key,
+ apr_size_t key_len,
+ svn_cache__partial_setter_func_t func,
+ void *baton,
+ DEBUG_CACHE_MEMBUFFER_TAG_ARG
+ apr_pool_t *scratch_pool)
+{
+ apr_uint32_t group_index;
+ unsigned char to_find[KEY_SIZE];
+
+ /* cache item lookup
+ */
+ group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
+
+ SVN_MUTEX__WITH_LOCK(cache->mutex,
+ membuffer_cache_set_partial_internal
+ (cache, group_index, to_find, func, baton,
+ DEBUG_CACHE_MEMBUFFER_TAG_ARG
+ scratch_pool));
+
/* done here -> unlock the cache
*/
- return unlock_cache(cache, err);
+ return SVN_NO_ERROR;
}
/* Implement the svn_cache__t interface on top of a shared membuffer cache.
@@ -1652,6 +1716,8 @@ svn_membuffer_cache_iter(svn_boolean_t *
_("Can't iterate a membuffer-based cache"));
}
+/* Implement svn_cache__vtable_t.get_partial
+ */
static svn_error_t *
svn_membuffer_cache_get_partial(void **value_p,
svn_boolean_t *found,
@@ -1695,6 +1761,8 @@ svn_membuffer_cache_get_partial(void **v
return SVN_NO_ERROR;
}
+/* Implement svn_cache__vtable_t.set_partial
+ */
static svn_error_t *
svn_membuffer_cache_set_partial(void *cache_void,
const void *key,
@@ -1728,6 +1796,8 @@ svn_membuffer_cache_set_partial(void *ca
return SVN_NO_ERROR;
}
+/* Implement svn_cache__vtable_t.is_cachable
+ */
static svn_boolean_t
svn_membuffer_cache_is_cachable(void *cache_void, apr_size_t size)
{
@@ -1740,6 +1810,25 @@ svn_membuffer_cache_is_cachable(void *ca
&& (size < APR_UINT32_MAX - ITEM_ALIGNMENT);
}
+/* Add statistics of SEGMENT to INFO.
+ */
+static svn_error_t *
+svn_membuffer_get_segment_info(svn_membuffer_t *segment,
+ svn_cache__info_t *info)
+{
+ info->data_size += segment->data_size;
+ info->used_size += segment->data_used;
+ info->total_size += segment->data_size +
+ segment->group_count * GROUP_SIZE * sizeof(entry_t);
+
+ info->used_entries += segment->used_entries;
+ info->total_entries += segment->group_count * GROUP_SIZE;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implement svn_cache__vtable_t.get_info
+ */
static svn_error_t *
svn_membuffer_cache_get_info(void *cache_void,
svn_cache__info_t *info,
@@ -1765,18 +1854,8 @@ svn_membuffer_cache_get_info(void *cache
for (i = 0; i < cache->membuffer->segment_count; ++i)
{
svn_membuffer_t *segment = cache->membuffer + i;
-
- SVN_ERR(lock_cache(segment));
-
- info->data_size += segment->data_size;
- info->used_size += segment->data_used;
- info->total_size += segment->data_size +
- segment->group_count * GROUP_SIZE * sizeof(entry_t);
-
- info->used_entries += segment->used_entries;
- info->total_entries += segment->group_count * GROUP_SIZE;
-
- SVN_ERR(unlock_cache(segment, SVN_NO_ERROR));
+ SVN_MUTEX__WITH_LOCK(segment->mutex,
+ svn_membuffer_get_segment_info(segment, info));
}
return SVN_NO_ERROR;
Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/cmdline.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/cmdline.c Mon Nov 21 07:07:56 2011
@@ -37,7 +37,6 @@
#include <apr_errno.h> /* for apr_strerror */
#include <apr_general.h> /* for apr_initialize/apr_terminate */
-#include <apr_atomic.h> /* for apr_atomic_init */
#include <apr_strings.h> /* for apr_snprintf */
#include <apr_pools.h>
@@ -74,6 +73,7 @@ svn_cmdline_init(const char *progname, F
apr_status_t status;
apr_pool_t *pool;
svn_error_t *err;
+ char prefix_buf[64]; /* 64 is probably bigger than most program names */
#ifndef WIN32
{
@@ -198,11 +198,17 @@ svn_cmdline_init(const char *progname, F
return EXIT_FAILURE;
}
- /* This has to happen before any pools are created. */
+ strncpy(prefix_buf, progname, sizeof(prefix_buf) - 3);
+ prefix_buf[sizeof(prefix_buf) - 3] = '\0';
+ strcat(prefix_buf, ": ");
+
+ /* DSO pool must be created before any other pools used by the
+ application so that pool cleanup doesn't unload DSOs too
+ early. See docstring of svn_dso_initialize2(). */
if ((err = svn_dso_initialize2()))
{
- if (error_stream && err->message)
- fprintf(error_stream, "%s", err->message);
+ if (error_stream)
+ svn_handle_error2(err, error_stream, TRUE, prefix_buf);
svn_error_clear(err);
return EXIT_FAILURE;
@@ -224,8 +230,8 @@ svn_cmdline_init(const char *progname, F
if ((err = svn_nls_init()))
{
- if (error_stream && err->message)
- fprintf(error_stream, "%s", err->message);
+ if (error_stream)
+ svn_handle_error2(err, error_stream, TRUE, prefix_buf);
svn_error_clear(err);
return EXIT_FAILURE;
@@ -631,7 +637,7 @@ svn_cmdline__print_xml_prop(svn_stringbu
const char *encoding = NULL;
if (*outstr == NULL)
- *outstr = svn_stringbuf_create("", pool);
+ *outstr = svn_stringbuf_create_empty(pool);
if (svn_xml_is_xml_safe(propval->data, propval->len))
{
Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/config.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/config.c Mon Nov 21 07:07:56 2011
@@ -88,8 +88,8 @@ svn_config_create(svn_config_t **cfgp,
cfg->pool = result_pool;
cfg->x_pool = svn_pool_create(result_pool);
cfg->x_values = FALSE;
- cfg->tmp_key = svn_stringbuf_create("", result_pool);
- cfg->tmp_value = svn_stringbuf_create("", result_pool);
+ cfg->tmp_key = svn_stringbuf_create_empty(result_pool);
+ cfg->tmp_value = svn_stringbuf_create_empty(result_pool);
cfg->section_names_case_sensitive = section_names_case_sensitive;
*cfgp = cfg;
Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/config_file.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/config_file.c Mon Nov 21 07:07:56 2011
@@ -386,9 +386,9 @@ svn_config__parse_file(svn_config_t *cfg
pool);
ctx.line = 1;
ctx.have_ungotten_char = FALSE;
- ctx.section = svn_stringbuf_create("", pool);
- ctx.option = svn_stringbuf_create("", pool);
- ctx.value = svn_stringbuf_create("", pool);
+ ctx.section = svn_stringbuf_create_empty(pool);
+ ctx.option = svn_stringbuf_create_empty(pool);
+ ctx.value = svn_stringbuf_create_empty(pool);
do
{
@@ -1071,6 +1071,11 @@ svn_config_ensure(const char *config_dir
"### Set interactive-conflicts to 'no' to disable interactive" NL
"### conflict resolution prompting. It defaults to 'yes'." NL
"# interactive-conflicts = no" NL
+ "### Set memory-cache-size to define the size of the memory cache" NL
+ "### used by the client when accessing a FSFS repository via" NL
+ "### ra_local (the file:// scheme). The value represents the number" NL
+ "### of MB used by the cache." NL
+ "# memory-cache-size = 16" NL
"" NL
"### Section for configuring automatic properties." NL
"[auto-props]" NL
Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/config_win.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/config_win.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/config_win.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/config_win.c Mon Nov 21 07:07:56 2011
@@ -200,9 +200,9 @@ svn_config__parse_registry(svn_config_t
subpool = svn_pool_create(pool);
- section = svn_stringbuf_create("", subpool);
- option = svn_stringbuf_create("", subpool);
- value = svn_stringbuf_create("", subpool);
+ section = svn_stringbuf_create_empty(subpool);
+ option = svn_stringbuf_create_empty(subpool);
+ value = svn_stringbuf_create_empty(subpool);
/* The top-level values belong to the [DEFAULT] section */
svn_err = parse_section(cfg, hkey, SVN_CONFIG__DEFAULT_SECTION,
Modified: subversion/branches/svn-bisect/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_subr/deprecated.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/svn-bisect/subversion/libsvn_subr/deprecated.c Mon Nov 21 07:07:56 2011
@@ -1073,6 +1073,53 @@ svn_rangelist_inheritable(apr_array_head
pool, pool));
}
+svn_error_t *
+svn_rangelist_merge(apr_array_header_t **rangelist,
+ const apr_array_header_t *changes,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_rangelist_merge2(*rangelist, changes,
+ pool, pool));
+}
+
+svn_error_t *
+svn_mergeinfo_diff(svn_mergeinfo_t *deleted, svn_mergeinfo_t *added,
+ svn_mergeinfo_t from, svn_mergeinfo_t to,
+ svn_boolean_t consider_inheritance,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_mergeinfo_diff2(deleted, added, from, to,
+ consider_inheritance, pool,
+ pool));
+}
+
+svn_error_t *
+svn_mergeinfo_merge(svn_mergeinfo_t mergeinfo,
+ svn_mergeinfo_t changes,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_mergeinfo_merge2(mergeinfo, changes, pool,
+ pool));
+}
+
+svn_error_t *
+svn_mergeinfo_remove(svn_mergeinfo_t *mergeinfo, svn_mergeinfo_t eraser,
+ svn_mergeinfo_t whiteboard, apr_pool_t *pool)
+{
+ return svn_mergeinfo_remove2(mergeinfo, eraser, whiteboard, TRUE, pool,
+ pool);
+}
+
+svn_error_t *
+svn_mergeinfo_intersect(svn_mergeinfo_t *mergeinfo,
+ svn_mergeinfo_t mergeinfo1,
+ svn_mergeinfo_t mergeinfo2,
+ apr_pool_t *pool)
+{
+ return svn_mergeinfo_intersect2(mergeinfo, mergeinfo1, mergeinfo2,
+ TRUE, pool, pool);
+}
+
/*** From config.c ***/
svn_error_t *
@@ -1126,12 +1173,3 @@ svn_xml_make_header(svn_stringbuf_t **st
{
svn_xml_make_header2(str, NULL, pool);
}
-
-svn_error_t *
-svn_rangelist_merge(apr_array_header_t **rangelist,
- const apr_array_header_t *changes,
- apr_pool_t *pool)
-{
- return svn_error_trace(svn_rangelist_merge2(*rangelist, changes,
- pool, pool));
-}