You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/01/20 18:52:21 UTC
svn commit: r1653314 [2/20] - in /subversion/branches/move-tracking-2: ./
notes/ subversion/ subversion/bindings/swig/
subversion/bindings/swig/include/ subversion/bindings/swig/perl/native/
subversion/bindings/swig/perl/native/t/ subversion/bindings/s...
Modified: subversion/branches/move-tracking-2/subversion/include/svn_version.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_version.h?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_version.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_version.h Tue Jan 20 17:52:18 2015
@@ -82,7 +82,7 @@ extern "C" {
/** Version tag: a string describing the version.
*
- * This tag remains " (dev build)" in the repository so that we can
+ * This tag remains " (under development)" in the repository so that we can
* always see from "svn --version" that the software has been built
* from the repository rather than a "blessed" distribution.
*
@@ -175,10 +175,25 @@ struct svn_version_t
* Generate the implementation of a version query function.
*
* @since New in 1.1.
+ * @since Since 1.9, embeds a string into the compiled object
+ * file that can be queried with the 'what' utility.
*/
-#define SVN_VERSION_BODY \
- SVN_VERSION_DEFINE(versioninfo); \
- return &versioninfo
+#define SVN_VERSION_BODY \
+ static struct versioninfo_t \
+ { \
+ const char *const str; \
+ const svn_version_t num; \
+ } const versioninfo = \
+ { \
+ "@(#)" SVN_VERSION, \
+ { \
+ SVN_VER_MAJOR, \
+ SVN_VER_MINOR, \
+ SVN_VER_PATCH, \
+ SVN_VER_NUMTAG \
+ } \
+ }; \
+ return &versioninfo.num
/**
* Check library version compatibility. Return #TRUE if the client's
Modified: subversion/branches/move-tracking-2/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_wc.h?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_wc.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_wc.h Tue Jan 20 17:52:18 2015
@@ -907,13 +907,15 @@ svn_wc_external_item_dup(const svn_wc_ex
*
* Allocate the table, keys, and values in @a pool.
*
- * Use @a parent_directory only in constructing error strings.
+ * @a defining_directory is the path or URL of the directory on which
+ * the svn:externals property corresponding to @a desc is set.
+ * @a defining_directory is only used when constructing error strings.
*
* @since New in 1.5.
*/
svn_error_t *
svn_wc_parse_externals_description3(apr_array_header_t **externals_p,
- const char *parent_directory,
+ const char *defining_directory,
const char *desc,
svn_boolean_t canonicalize_url,
apr_pool_t *pool);
Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/add.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/add.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/add.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/add.c Tue Jan 20 17:52:18 2015
@@ -1270,11 +1270,7 @@ svn_client__make_local_parents(const cha
else
SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT, scratch_pool));
- /* Should no longer use svn_depth_empty to indicate that only the directory
- itself is added, since it not only constraints the operation depth, but
- also defines the depth of the target directory now. Moreover, the new
- directory will have no children at all.*/
- err = svn_client_add5(local_abspath, svn_depth_infinity, FALSE, FALSE, FALSE,
+ err = svn_client_add5(local_abspath, svn_depth_empty, FALSE, FALSE, FALSE,
make_parents, ctx, scratch_pool);
/* If we created a new directory, but couldn't add it to version
Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/copy.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/copy.c Tue Jan 20 17:52:18 2015
@@ -1058,8 +1058,13 @@ repos_to_repos_copy(const apr_array_head
SVN_ERR(svn_ra_check_path(ra_session, dst_rel, SVN_INVALID_REVNUM,
&dst_kind, pool));
if (dst_kind != svn_node_none)
- return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
- _("Path '%s' already exists"), dst_rel);
+ {
+ const char *path = svn_uri_skip_ancestor(repos_root,
+ pair->dst_abspath_or_url,
+ pool);
+ return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
+ _("Path '/%s' already exists"), path);
+ }
/* More info for our INFO structure. */
info->src_path = src_rel;
Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/diff.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/diff.c Tue Jan 20 17:52:18 2015
@@ -154,9 +154,6 @@ adjust_paths_for_diff_labels(const char
new_path = ".";
else
return MAKE_ERR_BAD_RELATIVE_PATH(new_path, relative_to_dir);
-
- child_path = svn_dirent_is_child(relative_to_dir, new_path1,
- result_pool);
}
{
Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/locking_commands.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/locking_commands.c Tue Jan 20 17:52:18 2015
@@ -402,10 +402,9 @@ organize_lock_targets(apr_array_header_t
_("Unable to lock/unlock across multiple "
"repositories"));
- /* Now we need to create a couple of different hash mappings. */
+ /* Now we need to create our mapping. */
rel_fs_paths = apr_hash_make(result_pool);
- target_urls = apr_array_make(scratch_pool, targets->nelts,
- sizeof(const char *));
+
for (hi = apr_hash_first(scratch_pool, wc_info);
hi;
hi = apr_hash_next(hi))
Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/log.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/log.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/log.c Tue Jan 20 17:52:18 2015
@@ -852,10 +852,12 @@ svn_client_log5(const apr_array_header_t
svn_ra_session_t *ra_session;
const char *old_session_url;
const char *ra_target;
+ const char *path_or_url;
svn_opt_revision_t youngest_opt_rev;
svn_revnum_t youngest_rev;
svn_revnum_t oldest_rev;
svn_opt_revision_t peg_rev;
+ svn_client__pathrev_t *ra_session_loc;
svn_client__pathrev_t *actual_loc;
apr_array_header_t *log_segments;
apr_array_header_t *revision_ranges;
@@ -875,7 +877,7 @@ svn_client_log5(const apr_array_header_t
SVN_ERR(resolve_log_targets(&relative_targets, &ra_target, &peg_rev,
targets, ctx, pool, pool));
- SVN_ERR(svn_client__ra_session_from_path2(&ra_session, NULL,
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &ra_session_loc,
ra_target, NULL, &peg_rev, &peg_rev,
ctx, pool));
@@ -889,11 +891,22 @@ svn_client_log5(const apr_array_header_t
opt_rev_ranges, &peg_rev,
ctx, pool, pool));
+ /* For some peg revisions we must resolve revision and url via a local path
+ so use the original RA_TARGET. For others, use the potentially corrected
+ (redirected) ra session URL. */
+ if (peg_rev.kind == svn_opt_revision_previous ||
+ peg_rev.kind == svn_opt_revision_base ||
+ peg_rev.kind == svn_opt_revision_committed ||
+ peg_rev.kind == svn_opt_revision_working)
+ path_or_url = ra_target;
+ else
+ path_or_url = ra_session_loc->url;
+
/* Make ACTUAL_LOC and RA_SESSION point to the youngest operative rev. */
youngest_opt_rev.kind = svn_opt_revision_number;
youngest_opt_rev.value.number = youngest_rev;
SVN_ERR(svn_client__resolve_rev_and_url(&actual_loc, ra_session,
- ra_target, &peg_rev,
+ path_or_url, &peg_rev,
&youngest_opt_rev, ctx, pool));
SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
actual_loc->url, pool));
Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/mtcc.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/mtcc.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/mtcc.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/mtcc.c Tue Jan 20 17:52:18 2015
@@ -337,7 +337,6 @@ svn_client__mtcc_create(svn_client__mtcc
*mtcc = apr_pcalloc(mtcc_pool, sizeof(**mtcc));
(*mtcc)->pool = mtcc_pool;
- (*mtcc)->base_revision = base_revision;
(*mtcc)->root_op = mtcc_op_create(NULL, FALSE, TRUE, mtcc_pool);
@@ -350,9 +349,12 @@ svn_client__mtcc_create(svn_client__mtcc
SVN_ERR(svn_ra_get_latest_revnum((*mtcc)->ra_session, &(*mtcc)->head_revision,
scratch_pool));
- if (! SVN_IS_VALID_REVNUM(base_revision))
- base_revision = (*mtcc)->head_revision;
- else if (base_revision > (*mtcc)->head_revision)
+ if (SVN_IS_VALID_REVNUM(base_revision))
+ (*mtcc)->base_revision = base_revision;
+ else
+ (*mtcc)->base_revision = (*mtcc)->head_revision;
+
+ if ((*mtcc)->base_revision > (*mtcc)->head_revision)
return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
_("No such revision %ld (HEAD is %ld)"),
base_revision, (*mtcc)->head_revision);
Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/patch.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/patch.c Tue Jan 20 17:52:18 2015
@@ -48,6 +48,7 @@
#include "private/svn_dep_compat.h"
#include "private/svn_string_private.h"
#include "private/svn_subr_private.h"
+#include "private/svn_sorts_private.h"
typedef struct hunk_info_t {
/* The hunk. */
@@ -1578,7 +1579,8 @@ match_existing_target(svn_boolean_t *mat
/* Determine the line at which a HUNK applies to CONTENT of the TARGET
* file, and return an appropriate hunk_info object in *HI, allocated from
* RESULT_POOL. Use fuzz factor FUZZ. Set HI->FUZZ to FUZZ. If no correct
- * line can be determined, set HI->REJECTED to TRUE.
+ * line can be determined, set HI->REJECTED to TRUE. PREVIOUS_OFFSET
+ * is the offset at which the previous matching hunk was applied, or zero.
* IGNORE_WHITESPACE tells whether whitespace should be considered when
* matching. IS_PROP_HUNK indicates whether the hunk patches file content
* or a property.
@@ -1590,6 +1592,7 @@ static svn_error_t *
get_hunk_info(hunk_info_t **hi, patch_target_t *target,
target_content_t *content,
svn_diff_hunk_t *hunk, svn_linenum_t fuzz,
+ apr_int64_t previous_offset,
svn_boolean_t ignore_whitespace,
svn_boolean_t is_prop_hunk,
svn_cancel_func_t cancel_func, void *cancel_baton,
@@ -1599,7 +1602,7 @@ get_hunk_info(hunk_info_t **hi, patch_ta
svn_linenum_t original_start;
svn_boolean_t already_applied;
- original_start = svn_diff_hunk_get_original_start(hunk);
+ original_start = svn_diff_hunk_get_original_start(hunk) + previous_offset;
already_applied = FALSE;
/* An original offset of zero means that this hunk wants to create
@@ -1707,7 +1710,9 @@ get_hunk_info(hunk_info_t **hi, patch_ta
modified_start = svn_diff_hunk_get_modified_start(hunk);
if (modified_start == 0)
{
- /* Patch wants to delete the file. */
+ /* Patch wants to delete the file.
+
+ ### locally_deleted is always false here? */
already_applied = target->locally_deleted;
}
else
@@ -1728,27 +1733,85 @@ get_hunk_info(hunk_info_t **hi, patch_ta
if (! already_applied)
{
- /* Scan the whole file again from the start. */
- SVN_ERR(seek_to_line(content, 1, scratch_pool));
+ int i;
+ svn_linenum_t search_start = 1, search_end = 0;
+ svn_linenum_t matched_line2;
+
+ /* Search for closest match before or after original
+ start. We have no backward search so search forwards
+ from the previous match (or start of file) to the
+ original start looking for the last match. Then
+ search forwards from the original start looking for a
+ better match. Finally search forwards from the start
+ of file to the previous hunk if that could result in
+ a better match. */
+
+ for (i = content->hunks->nelts; i > 0; --i)
+ {
+ const hunk_info_t *prev
+ = APR_ARRAY_IDX(content->hunks, i - 1, const hunk_info_t *);
+ if (!prev->rejected)
+ {
+ svn_linenum_t length;
+
+ length = svn_diff_hunk_get_original_length(prev->hunk);
+ search_start = prev->matched_line + length;
+ break;
+ }
+ }
- /* Scan forward towards the hunk's line and look for a line
- * where the hunk matches. */
+ /* Search from the previous match, or start of file,
+ towards the original location. */
+ SVN_ERR(seek_to_line(content, search_start, scratch_pool));
SVN_ERR(scan_for_match(&matched_line, content, hunk, FALSE,
original_start, fuzz,
ignore_whitespace, FALSE,
cancel_func, cancel_baton,
scratch_pool));
- /* In tie-break situations, we arbitrarily prefer early matches
- * to save us from scanning the rest of the file. */
- if (matched_line == 0)
+ /* If a match we only need to search forwards for a
+ better match, otherwise to the end of the file. */
+ if (matched_line)
+ search_end = original_start + (original_start - matched_line);
+
+ /* Search from original location, towards the end. */
+ SVN_ERR(seek_to_line(content, original_start + 1, scratch_pool));
+ SVN_ERR(scan_for_match(&matched_line2, content, hunk,
+ TRUE, search_end, fuzz, ignore_whitespace,
+ FALSE, cancel_func, cancel_baton,
+ scratch_pool));
+
+ /* Chose the forward match if it is closer than the
+ backward match or if there is no backward match. */
+ if (matched_line2
+ && (!matched_line
+ || (matched_line2 - original_start
+ < original_start - matched_line)))
+ matched_line = matched_line2;
+
+ /* Search from before previous hunk if there could be a
+ better match. */
+ if (search_start > 1
+ && (!matched_line
+ || (matched_line > original_start
+ && (matched_line - original_start
+ > original_start - search_start))))
{
- /* Scan forward towards the end of the file and look
- * for a line where the hunk matches. */
- SVN_ERR(scan_for_match(&matched_line, content, hunk,
- TRUE, 0, fuzz, ignore_whitespace,
- FALSE, cancel_func, cancel_baton,
+ svn_linenum_t search_start2 = 1;
+
+ if (matched_line
+ && matched_line - original_start < original_start)
+ search_start2
+ = original_start - (matched_line - original_start) + 1;
+
+ SVN_ERR(seek_to_line(content, search_start2, scratch_pool));
+ SVN_ERR(scan_for_match(&matched_line2, content, hunk, FALSE,
+ search_start - 1, fuzz,
+ ignore_whitespace, FALSE,
+ cancel_func, cancel_baton,
scratch_pool));
+ if (matched_line2)
+ matched_line = matched_line2;
}
}
}
@@ -2139,6 +2202,48 @@ send_patch_notification(const patch_targ
return SVN_NO_ERROR;
}
+/* Implements the callback for svn_sort__array. Puts hunks that match
+ before hunks that do not match, puts hunks that match in order
+ based on postion matched, puts hunks that do not match in order
+ based on original position. */
+static int
+sort_matched_hunks(const void *a, const void *b)
+{
+ const hunk_info_t *item1 = *((const hunk_info_t * const *)a);
+ const hunk_info_t *item2 = *((const hunk_info_t * const *)b);
+ svn_boolean_t matched1 = !item1->rejected && !item1->already_applied;
+ svn_boolean_t matched2 = !item2->rejected && !item2->already_applied;
+ svn_linenum_t original1, original2;
+
+ if (matched1 && matched2)
+ {
+ /* Both match so use order matched in file. */
+ if (item1->matched_line > item2->matched_line)
+ return 1;
+ else if (item1->matched_line == item2->matched_line)
+ return 0;
+ else
+ return -1;
+ }
+ else if (matched2)
+ /* Only second matches, put it before first. */
+ return 1;
+ else if (matched1)
+ /* Only first matches, put it before second. */
+ return -1;
+
+ /* Neither matches, sort by original_start. */
+ original1 = svn_diff_hunk_get_original_start(item1->hunk);
+ original2 = svn_diff_hunk_get_original_start(item2->hunk);
+ if (original1 > original2)
+ return 1;
+ else if (original1 == original2)
+ return 0;
+ else
+ return -1;
+}
+
+
/* Apply a PATCH to a working copy at ABS_WC_PATH and put the result
* into temporary files, to be installed in the working copy later.
* Return information about the patch target in *PATCH_TARGET, allocated
@@ -2167,6 +2272,7 @@ apply_one_patch(patch_target_t **patch_t
int i;
static const svn_linenum_t MAX_FUZZ = 2;
apr_hash_index_t *hash_index;
+ apr_int64_t previous_offset = 0;
SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx, strip_count,
remove_tempfiles, result_pool, scratch_pool));
@@ -2209,6 +2315,7 @@ apply_one_patch(patch_target_t **patch_t
do
{
SVN_ERR(get_hunk_info(&hi, target, target->content, hunk, fuzz,
+ previous_offset,
ignore_whitespace,
FALSE /* is_prop_hunk */,
cancel_func, cancel_baton,
@@ -2217,9 +2324,17 @@ apply_one_patch(patch_target_t **patch_t
}
while (hi->rejected && fuzz <= MAX_FUZZ && ! hi->already_applied);
+ if (hi->matched_line)
+ previous_offset
+ = hi->matched_line - svn_diff_hunk_get_original_start(hunk);
+
APR_ARRAY_PUSH(target->content->hunks, hunk_info_t *) = hi;
}
+ /* Hunks are applied in the order determined by the matched line and
+ this may be different from the order of the original lines. */
+ svn_sort__array(target->content->hunks, sort_matched_hunks);
+
/* Apply or reject hunks. */
for (i = 0; i < target->content->hunks->nelts; i++)
{
@@ -2291,7 +2406,7 @@ apply_one_patch(patch_target_t **patch_t
do
{
SVN_ERR(get_hunk_info(&hi, target, prop_target->content,
- hunk, fuzz,
+ hunk, fuzz, 0,
ignore_whitespace,
TRUE /* is_prop_hunk */,
cancel_func, cancel_baton,
Modified: subversion/branches/move-tracking-2/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_diff/diff_file.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_diff/diff_file.c Tue Jan 20 17:52:18 2015
@@ -544,7 +544,6 @@ find_identical_suffix(apr_off_t *suffix_
int suffix_lines_to_keep = SUFFIX_LINES_TO_KEEP;
svn_boolean_t is_match;
apr_off_t lines = 0;
- svn_boolean_t had_cr;
svn_boolean_t had_nl;
apr_size_t i;
@@ -685,7 +684,6 @@ find_identical_suffix(apr_off_t *suffix_
/* We skipped some bytes, so there are no closing EOLs */
had_nl = FALSE;
- had_cr = FALSE;
}
/* The > min_curp[i] check leaves at least one final byte for checking
@@ -712,7 +710,7 @@ find_identical_suffix(apr_off_t *suffix_
one file reaches its end. */
do
{
- had_cr = FALSE;
+ svn_boolean_t had_cr = FALSE;
while (!is_one_at_eof(file_for_suffix, file_len)
&& *file_for_suffix[0].curp != '\n'
&& *file_for_suffix[0].curp != '\r')
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_base/fs.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_base/fs.c Tue Jan 20 17:52:18 2015
@@ -1516,6 +1516,7 @@ svn_fs_base__init(const svn_version_t *l
{
{ "svn_subr", svn_subr_version },
{ "svn_delta", svn_delta_version },
+ { "svn_fs_util", svn_fs_util__version },
{ NULL, NULL }
};
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/caching.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/caching.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/caching.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/caching.c Tue Jan 20 17:52:18 2015
@@ -676,12 +676,44 @@ struct txn_cleanup_baton_t
/* the position where to reset it */
svn_cache__t **to_reset;
+
+ /* pool that TXN_CACHE was allocated in */
+ apr_pool_t *txn_pool;
+
+ /* pool that the FS containing the TO_RESET pointer was allocator */
+ apr_pool_t *fs_pool;
};
+/* Forward declaration. */
+static apr_status_t
+remove_txn_cache_fs(void *baton_void);
+
/* APR pool cleanup handler that will reset the cache pointer given in
- BATON_VOID. */
+ BATON_VOID when the TXN_POOL gets cleaned up. */
static apr_status_t
-remove_txn_cache(void *baton_void)
+remove_txn_cache_txn(void *baton_void)
+{
+ struct txn_cleanup_baton_t *baton = baton_void;
+
+ /* be careful not to hurt performance by resetting newer txn's caches. */
+ if (*baton->to_reset == baton->txn_cache)
+ {
+ /* This is equivalent to calling svn_fs_fs__reset_txn_caches(). */
+ *baton->to_reset = NULL;
+ }
+
+ /* It's cleaned up now. Prevent double cleanup. */
+ apr_pool_cleanup_kill(baton->fs_pool,
+ baton,
+ remove_txn_cache_fs);
+
+ return APR_SUCCESS;
+}
+
+/* APR pool cleanup handler that will reset the cache pointer given in
+ BATON_VOID when the FS_POOL gets cleaned up. */
+static apr_status_t
+remove_txn_cache_fs(void *baton_void)
{
struct txn_cleanup_baton_t *baton = baton_void;
@@ -689,19 +721,25 @@ remove_txn_cache(void *baton_void)
if (*baton->to_reset == baton->txn_cache)
{
/* This is equivalent to calling svn_fs_fs__reset_txn_caches(). */
- *baton->to_reset = NULL;
+ *baton->to_reset = NULL;
}
+ /* It's cleaned up now. Prevent double cleanup. */
+ apr_pool_cleanup_kill(baton->txn_pool,
+ baton,
+ remove_txn_cache_txn);
+
return APR_SUCCESS;
}
/* This function sets / registers the required callbacks for a given
- * transaction-specific *CACHE object, if CACHE is not NULL and a no-op
- * otherwise. In particular, it will ensure that *CACHE gets reset to NULL
- * upon POOL destruction latest.
+ * transaction-specific *CACHE object in FS, if CACHE is not NULL and
+ * a no-op otherwise. In particular, it will ensure that *CACHE gets
+ * reset to NULL upon POOL or FS->POOL destruction latest.
*/
static void
-init_txn_callbacks(svn_cache__t **cache,
+init_txn_callbacks(svn_fs_t *fs,
+ svn_cache__t **cache,
apr_pool_t *pool)
{
if (*cache != NULL)
@@ -711,10 +749,20 @@ init_txn_callbacks(svn_cache__t **cache,
baton = apr_palloc(pool, sizeof(*baton));
baton->txn_cache = *cache;
baton->to_reset = cache;
+ baton->txn_pool = pool;
+ baton->fs_pool = fs->pool;
+ /* If any of these pools gets cleaned, we must reset the cache.
+ * We don't know which one will get cleaned up first, so register
+ * cleanup actions for both and during the cleanup action, unregister
+ * the respective other action. */
apr_pool_cleanup_register(pool,
baton,
- remove_txn_cache,
+ remove_txn_cache_txn,
+ apr_pool_cleanup_null);
+ apr_pool_cleanup_register(fs->pool,
+ baton,
+ remove_txn_cache_fs,
apr_pool_cleanup_null);
}
}
@@ -764,7 +812,7 @@ svn_fs_fs__initialize_txn_caches(svn_fs_
pool, pool));
/* reset the transaction-specific cache if the pool gets cleaned up. */
- init_txn_callbacks(&(ffd->txn_dir_cache), pool);
+ init_txn_callbacks(fs, &(ffd->txn_dir_cache), pool);
return SVN_NO_ERROR;
}
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/dag.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/dag.c Tue Jan 20 17:52:18 2015
@@ -866,14 +866,20 @@ svn_fs_fs__dag_delete_if_mutable(svn_fs_
{
apr_array_header_t *entries;
int i;
+ apr_pool_t *iterpool = svn_pool_create(pool);
/* Loop over directory entries */
SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, node, pool));
if (entries)
for (i = 0; i < entries->nelts; ++i)
- SVN_ERR(svn_fs_fs__dag_delete_if_mutable(fs,
- APR_ARRAY_IDX(entries, i, svn_fs_dirent_t *)->id,
- pool));
+ {
+ svn_pool_clear(iterpool);
+ SVN_ERR(svn_fs_fs__dag_delete_if_mutable(fs,
+ APR_ARRAY_IDX(entries, i, svn_fs_dirent_t *)->id,
+ iterpool));
+ }
+
+ svn_pool_destroy(iterpool);
}
/* ... then delete the node itself, after deleting any mutable
@@ -1099,6 +1105,15 @@ svn_fs_fs__dag_dup(const dag_node_t *nod
return new_node;
}
+dag_node_t *
+svn_fs_fs__dag_copy_into_pool(dag_node_t *node,
+ apr_pool_t *pool)
+{
+ return (node->node_pool == pool
+ ? node
+ : svn_fs_fs__dag_dup(node, pool));
+}
+
svn_error_t *
svn_fs_fs__dag_serialize(void **data,
apr_size_t *data_len,
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/dag.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/dag.h?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/dag.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/dag.h Tue Jan 20 17:52:18 2015
@@ -80,6 +80,12 @@ dag_node_t *
svn_fs_fs__dag_dup(const dag_node_t *node,
apr_pool_t *pool);
+/* If NODE has been allocated in POOL, return NODE. Otherwise, return
+ a copy created in POOL with svn_fs_fs__dag_dup. */
+dag_node_t *
+svn_fs_fs__dag_copy_into_pool(dag_node_t *node,
+ apr_pool_t *pool);
+
/* Serialize a DAG node, except don't try to preserve the 'fs' member.
Implements svn_cache__serialize_func_t */
svn_error_t *
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c Tue Jan 20 17:52:18 2015
@@ -597,6 +597,7 @@ svn_fs_fs__init(const svn_version_t *loa
{
{ "svn_subr", svn_subr_version },
{ "svn_delta", svn_delta_version },
+ { "svn_fs_util", svn_fs_util__version },
{ NULL, NULL }
};
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/index.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/index.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/index.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/index.c Tue Jan 20 17:52:18 2015
@@ -836,8 +836,8 @@ svn_fs_fs__l2p_index_append(svn_checksum
/* 1 page with up to L2P_PAGE_SIZE entries.
* fsfs.conf settings validation guarantees this to fit into
* our address space. */
- apr_size_t last_buffer_size
- = (apr_size_t)svn_spillbuf__get_size(buffer);
+ apr_uint64_t last_buffer_size
+ = (apr_uint64_t)svn_spillbuf__get_size(buffer);
svn_pool_clear(iterpool);
@@ -1980,8 +1980,8 @@ svn_fs_fs__p2l_index_append(svn_checksum
apr_uint64_t last_entry_end = 0;
apr_uint64_t last_page_end = 0;
- apr_size_t last_buffer_size = 0; /* byte offset in the spill buffer at
- the begin of the current revision */
+ apr_uint64_t last_buffer_size = 0; /* byte offset in the spill buffer at
+ the begin of the current revision */
apr_uint64_t file_size = 0;
/* temporary data structures that collect the data which will be moved
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/lock.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/lock.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/lock.c Tue Jan 20 17:52:18 2015
@@ -103,8 +103,7 @@ hash_store(apr_hash_t *hash,
of that value (if it exists). */
static const char *
hash_fetch(apr_hash_t *hash,
- const char *key,
- apr_pool_t *pool)
+ const char *key)
{
svn_string_t *str = svn_hash_gets(hash, key);
return str ? str->data : NULL;
@@ -284,7 +283,7 @@ read_digest_file(apr_hash_t **children_p
/* If our caller cares, see if we have a lock path in our hash. If
so, we'll assume we have a lock here. */
- val = hash_fetch(hash, PATH_KEY, pool);
+ val = hash_fetch(hash, PATH_KEY);
if (val && lock_p)
{
const char *path = val;
@@ -293,30 +292,30 @@ read_digest_file(apr_hash_t **children_p
lock = svn_lock_create(pool);
lock->path = path;
- if (! ((lock->token = hash_fetch(hash, TOKEN_KEY, pool))))
+ if (! ((lock->token = hash_fetch(hash, TOKEN_KEY))))
return svn_error_trace(err_corrupt_lockfile(fs_path, path));
- if (! ((lock->owner = hash_fetch(hash, OWNER_KEY, pool))))
+ if (! ((lock->owner = hash_fetch(hash, OWNER_KEY))))
return svn_error_trace(err_corrupt_lockfile(fs_path, path));
- if (! ((val = hash_fetch(hash, IS_DAV_COMMENT_KEY, pool))))
+ if (! ((val = hash_fetch(hash, IS_DAV_COMMENT_KEY))))
return svn_error_trace(err_corrupt_lockfile(fs_path, path));
lock->is_dav_comment = (val[0] == '1');
- if (! ((val = hash_fetch(hash, CREATION_DATE_KEY, pool))))
+ if (! ((val = hash_fetch(hash, CREATION_DATE_KEY))))
return svn_error_trace(err_corrupt_lockfile(fs_path, path));
SVN_ERR(svn_time_from_cstring(&(lock->creation_date), val, pool));
- if ((val = hash_fetch(hash, EXPIRATION_DATE_KEY, pool)))
+ if ((val = hash_fetch(hash, EXPIRATION_DATE_KEY)))
SVN_ERR(svn_time_from_cstring(&(lock->expiration_date), val, pool));
- lock->comment = hash_fetch(hash, COMMENT_KEY, pool);
+ lock->comment = hash_fetch(hash, COMMENT_KEY);
*lock_p = lock;
}
/* If our caller cares, see if we have any children for this path. */
- val = hash_fetch(hash, CHILDREN_KEY, pool);
+ val = hash_fetch(hash, CHILDREN_KEY);
if (val && children_p)
{
apr_array_header_t *kiddos = svn_cstring_split(val, "\n", FALSE, pool);
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/revprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/revprops.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/revprops.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/revprops.c Tue Jan 20 17:52:18 2015
@@ -208,7 +208,9 @@ parse_revprop(apr_hash_t **properties,
svn_stream_t *stream = svn_stream_from_string(content, scratch_pool);
*properties = apr_hash_make(pool);
- SVN_ERR(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR, pool));
+ SVN_ERR_W(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR, pool),
+ apr_psprintf(scratch_pool, "Failed to parse revprops for r%ld.",
+ revision));
return SVN_NO_ERROR;
}
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c Tue Jan 20 17:52:18 2015
@@ -249,8 +249,8 @@ add_to_histogram(svn_fs_fs__histogram_t
*/
static void
add_change(svn_fs_fs__stats_t *stats,
- apr_int64_t rep_size,
- apr_int64_t expanded_size,
+ apr_uint64_t rep_size,
+ apr_uint64_t expanded_size,
svn_revnum_t revision,
const char *path,
rep_kind_t kind,
@@ -293,29 +293,25 @@ add_change(svn_fs_fs__stats_t *stats,
/* specific histograms by type */
switch (kind)
{
- case unused_rep: add_to_histogram(&stats->unused_rep_histogram,
- rep_size);
- break;
- case dir_property_rep: add_to_histogram(&stats->dir_prop_rep_histogram,
- rep_size);
- add_to_histogram(&stats->dir_prop_histogram,
- expanded_size);
- break;
- case file_property_rep: add_to_histogram(&stats->file_prop_rep_histogram,
- rep_size);
- add_to_histogram(&stats->file_prop_histogram,
- expanded_size);
- break;
- case dir_rep: add_to_histogram(&stats->dir_rep_histogram,
- rep_size);
- add_to_histogram(&stats->dir_histogram,
- expanded_size);
- break;
- case file_rep: add_to_histogram(&stats->file_rep_histogram,
- rep_size);
- add_to_histogram(&stats->file_histogram,
- expanded_size);
- break;
+ case unused_rep:
+ add_to_histogram(&stats->unused_rep_histogram, rep_size);
+ break;
+ case dir_property_rep:
+ add_to_histogram(&stats->dir_prop_rep_histogram, rep_size);
+ add_to_histogram(&stats->dir_prop_histogram, expanded_size);
+ break;
+ case file_property_rep:
+ add_to_histogram(&stats->file_prop_rep_histogram, rep_size);
+ add_to_histogram(&stats->file_prop_histogram, expanded_size);
+ break;
+ case dir_rep:
+ add_to_histogram(&stats->dir_rep_histogram, rep_size);
+ add_to_histogram(&stats->dir_histogram, expanded_size);
+ break;
+ case file_rep:
+ add_to_histogram(&stats->file_rep_histogram, rep_size);
+ add_to_histogram(&stats->file_histogram, expanded_size);
+ break;
}
/* by extension */
@@ -618,13 +614,12 @@ read_noderev(query_t *query,
/* record largest changes */
if (text && text->ref_count == 1)
- add_change(query->stats, (apr_int64_t)text->size,
- (apr_int64_t)text->expanded_size, text->revision,
+ add_change(query->stats, text->size, text->expanded_size, text->revision,
noderev->created_path, text->kind, !noderev->predecessor_id);
if (props && props->ref_count == 1)
- add_change(query->stats, (apr_int64_t)props->size,
- (apr_int64_t)props->expanded_size, props->revision,
- noderev->created_path, props->kind, !noderev->predecessor_id);
+ add_change(query->stats, props->size, props->expanded_size,
+ props->revision, noderev->created_path, props->kind,
+ !noderev->predecessor_id);
/* if this is a directory and has not been processed, yet, read and
* process it recursively */
@@ -1250,7 +1245,7 @@ svn_fs_fs__get_stats(svn_fs_fs__stats_t
query_t *query;
*stats = create_stats(result_pool);
- SVN_ERR(create_query(&query, fs, *stats, progress_func, progress_func,
+ SVN_ERR(create_query(&query, fs, *stats, progress_func, progress_baton,
cancel_func, cancel_baton, scratch_pool,
scratch_pool));
SVN_ERR(read_revisions(query, scratch_pool, scratch_pool));
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c Tue Jan 20 17:52:18 2015
@@ -3191,44 +3191,41 @@ verify_locks(svn_fs_t *fs,
apr_hash_t *changed_paths,
apr_pool_t *pool)
{
- apr_pool_t *subpool = svn_pool_create(pool);
- apr_hash_index_t *hi;
+ apr_pool_t *iterpool;
apr_array_header_t *changed_paths_sorted;
svn_stringbuf_t *last_recursed = NULL;
int i;
/* Make an array of the changed paths, and sort them depth-first-ily. */
- changed_paths_sorted = apr_array_make(pool,
- apr_hash_count(changed_paths) + 1,
- sizeof(const char *));
- for (hi = apr_hash_first(pool, changed_paths); hi; hi = apr_hash_next(hi))
- {
- APR_ARRAY_PUSH(changed_paths_sorted, const char *) =
- apr_hash_this_key(hi);
- }
- svn_sort__array(changed_paths_sorted, svn_sort_compare_paths);
+ changed_paths_sorted = svn_sort__hash(changed_paths,
+ svn_sort_compare_items_as_paths,
+ pool);
/* Now, traverse the array of changed paths, verify locks. Note
that if we need to do a recursive verification a path, we'll skip
over children of that path when we get to them. */
+ iterpool = svn_pool_create(pool);
for (i = 0; i < changed_paths_sorted->nelts; i++)
{
+ const svn_sort__item_t *item;
const char *path;
svn_fs_path_change2_t *change;
svn_boolean_t recurse = TRUE;
- svn_pool_clear(subpool);
- path = APR_ARRAY_IDX(changed_paths_sorted, i, const char *);
+ svn_pool_clear(iterpool);
+
+ item = &APR_ARRAY_IDX(changed_paths_sorted, i, svn_sort__item_t);
+
+ /* Fetch the change associated with our path. */
+ path = item->key;
+ change = item->value;
/* If this path has already been verified as part of a recursive
check of one of its parents, no need to do it again. */
if (last_recursed
- && svn_dirent_is_child(last_recursed->data, path, subpool))
+ && svn_fspath__skip_ancestor(last_recursed->data, path))
continue;
- /* Fetch the change associated with our path. */
- change = svn_hash_gets(changed_paths, path);
-
/* What does it mean to succeed at lock verification for a given
path? For an existing file or directory getting modified
(text, props), it means we hold the lock on the file or
@@ -3241,7 +3238,7 @@ verify_locks(svn_fs_t *fs,
if (change->change_kind == svn_fs_path_change_modify)
recurse = FALSE;
SVN_ERR(svn_fs_fs__allow_locked_operation(path, fs, recurse, TRUE,
- subpool));
+ iterpool));
/* If we just did a recursive check, remember the path we
checked (so children can be skipped). */
@@ -3253,7 +3250,7 @@ verify_locks(svn_fs_t *fs,
svn_stringbuf_set(last_recursed, path);
}
}
- svn_pool_destroy(subpool);
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/tree.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/tree.c Tue Jan 20 17:52:18 2015
@@ -100,7 +100,6 @@ typedef struct fs_txn_root_data_t
static svn_error_t * get_dag(dag_node_t **dag_node_p,
svn_fs_root_t *root,
const char *path,
- svn_boolean_t needs_lock_cache,
apr_pool_t *pool);
static svn_fs_root_t *make_revision_root(svn_fs_t *fs, svn_revnum_t rev,
@@ -159,34 +158,10 @@ typedef struct cache_entry_t
*/
enum { BUCKET_COUNT = 256 };
-/* Each pool that has received a DAG node, will hold at least on lock on
- our cache to ensure that the node remains valid despite being allocated
- in the cache's pool. This is the structure to represent the lock.
- */
-typedef struct cache_lock_t
-{
- /* pool holding the lock */
- apr_pool_t *pool;
-
- /* cache being locked */
- fs_fs_dag_cache_t *cache;
-
- /* next lock. NULL at EOL */
- struct cache_lock_t *next;
-
- /* previous lock. NULL at list head. Only then this==cache->first_lock */
- struct cache_lock_t *prev;
-} cache_lock_t;
-
/* The actual cache structure. All nodes will be allocated in POOL.
When the number of INSERTIONS (i.e. objects created form that pool)
exceeds a certain threshold, the pool will be cleared and the cache
with it.
-
- To ensure that nodes returned from this structure remain valid, the
- cache will get locked for the lifetime of the _receiving_ pools (i.e.
- those in which we would allocate the node if there was no cache.).
- The cache will only be cleared FIRST_LOCK is 0.
*/
struct fs_fs_dag_cache_t
{
@@ -203,109 +178,29 @@ struct fs_fs_dag_cache_t
Thus, remember the last hit location for optimistic lookup. */
apr_size_t last_hit;
- /* List of receiving pools that are still alive. */
- cache_lock_t *first_lock;
+ /* Position of the last bucket hit that actually had a DAG node in it.
+ LAST_HIT may refer to a bucket that matches path@rev but has not
+ its NODE element set, yet.
+ This value is a mere hint for optimistic lookup and any value is
+ valid (as long as it is < BUCKET_COUNT). */
+ apr_size_t last_non_empty;
};
-/* Cleanup function to be called when a receiving pool gets cleared.
- Unlocks the cache once.
- */
-static apr_status_t
-unlock_cache(void *baton_void)
-{
- cache_lock_t *lock = baton_void;
-
- /* remove lock from chain. Update the head */
- if (lock->next)
- lock->next->prev = lock->prev;
- if (lock->prev)
- lock->prev->next = lock->next;
- else
- lock->cache->first_lock = lock->next;
-
- return APR_SUCCESS;
-}
-
-/* Cleanup function to be called when the cache itself gets destroyed.
- In that case, we must unregister all unlock requests.
- */
-static apr_status_t
-unregister_locks(void *baton_void)
-{
- fs_fs_dag_cache_t *cache = baton_void;
- cache_lock_t *lock;
-
- for (lock = cache->first_lock; lock; lock = lock->next)
- apr_pool_cleanup_kill(lock->pool,
- lock,
- unlock_cache);
-
- return APR_SUCCESS;
-}
-
fs_fs_dag_cache_t*
svn_fs_fs__create_dag_cache(apr_pool_t *pool)
{
fs_fs_dag_cache_t *result = apr_pcalloc(pool, sizeof(*result));
result->pool = svn_pool_create(pool);
- apr_pool_cleanup_register(pool,
- result,
- unregister_locks,
- apr_pool_cleanup_null);
-
return result;
}
-/* Prevent the entries in CACHE from being destroyed, for as long as the
- POOL lives.
- */
-static void
-lock_cache(fs_fs_dag_cache_t* cache, apr_pool_t *pool)
-{
- /* we only need to lock / unlock once per pool. Since we will often ask
- for multiple nodes with the same pool, we can reduce the overhead.
- However, if e.g. pools are being used in an alternating pattern,
- we may lock the cache more than once for the same pool (and register
- just as many cleanup actions).
- */
- cache_lock_t *lock = cache->first_lock;
-
- /* try to find an existing lock for POOL.
- But limit the time spent on chasing pointers. */
- int limiter = 8;
- while (lock && --limiter)
- {
- if (lock->pool == pool)
- return;
-
- lock = lock->next;
- }
-
- /* create a new lock and put it at the beginning of the lock chain */
- lock = apr_palloc(pool, sizeof(*lock));
- lock->cache = cache;
- lock->pool = pool;
- lock->next = cache->first_lock;
- lock->prev = NULL;
-
- if (cache->first_lock)
- cache->first_lock->prev = lock;
- cache->first_lock = lock;
-
- /* instruct POOL to remove the look upon cleanup */
- apr_pool_cleanup_register(pool,
- lock,
- unlock_cache,
- apr_pool_cleanup_null);
-}
-
/* Clears the CACHE at regular intervals (destroying all cached nodes)
*/
static void
auto_clear_dag_cache(fs_fs_dag_cache_t* cache)
{
- if (cache->first_lock == NULL && cache->insertions > BUCKET_COUNT)
+ if (cache->insertions > BUCKET_COUNT)
{
svn_pool_clear(cache->pool);
@@ -338,6 +233,10 @@ cache_lookup( fs_fs_dag_cache_t *cache
&& (result->path_len == path_len)
&& !memcmp(result->path, path, path_len))
{
+ /* Remember the position of the last node we found in this cache. */
+ if (result->node)
+ cache->last_non_empty = cache->last_hit;
+
return result;
}
@@ -409,10 +308,38 @@ cache_lookup( fs_fs_dag_cache_t *cache
cache->insertions++;
}
+ else if (result->node)
+ {
+ /* This bucket is valid & has a suitable DAG node in it.
+ Remember its location. */
+ cache->last_non_empty = bucket_index;
+ }
return result;
}
+/* Optimistic lookup using the last seen non-empty location in CACHE.
+ Return the node of that entry, if it is still in use and matches PATH.
+ Return NULL otherwise. Since the caller usually already knows the path
+ length, provide it in PATH_LEN. */
+static dag_node_t *
+cache_lookup_last_path(fs_fs_dag_cache_t *cache,
+ const char *path,
+ apr_size_t path_len)
+{
+ cache_entry_t *result = &cache->buckets[cache->last_non_empty];
+ assert(strlen(path) == path_len);
+
+ if ( result->node
+ && (result->path_len == path_len)
+ && !memcmp(result->path, path, path_len))
+ {
+ return result->node;
+ }
+
+ return NULL;
+}
+
/* 2nd level cache */
/* Find and return the DAG node cache for ROOT and the key that
@@ -449,15 +376,11 @@ locate_cache(svn_cache__t **cache,
/* Return NODE for PATH from ROOT's node cache, or NULL if the node
isn't cached; read it from the FS. *NODE remains valid until either
POOL or the FS gets cleared or destroyed (whichever comes first).
-
- Since locking can be expensive and POOL may be long-living, for
- nodes that will not need to survive the next call to this function,
- set NEEDS_LOCK_CACHE to FALSE. */
+ */
static svn_error_t *
dag_node_cache_get(dag_node_t **node_p,
svn_fs_root_t *root,
const char *path,
- svn_boolean_t needs_lock_cache,
apr_pool_t *pool)
{
svn_boolean_t found;
@@ -493,11 +416,6 @@ dag_node_cache_get(dag_node_t **node_p,
{
node = bucket->node;
}
-
- /* if we found a node, make sure it remains valid at least as long
- as it would when allocated in POOL. */
- if (node && needs_lock_cache)
- lock_cache(ffd->dag_node_cache, pool);
}
else
{
@@ -848,7 +766,7 @@ get_copy_inheritance(copy_id_inherit_t *
SVN_ERR(svn_fs_fs__dag_get_copyroot(©root_rev, ©root_path,
child->node));
SVN_ERR(svn_fs_fs__revision_root(©root_root, fs, copyroot_rev, pool));
- SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, FALSE, pool));
+ SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool));
copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
if (svn_fs_fs__id_compare(copyroot_id, child_id) == svn_fs_node_unrelated)
@@ -880,7 +798,8 @@ make_parent_path(dag_node_t *node,
apr_pool_t *pool)
{
parent_path_t *parent_path = apr_pcalloc(pool, sizeof(*parent_path));
- parent_path->node = node;
+ if (node)
+ parent_path->node = svn_fs_fs__dag_copy_into_pool(node, pool);
parent_path->entry = entry;
parent_path->parent = parent;
parent_path->copy_inherit = copy_id_inherit_unknown;
@@ -912,6 +831,56 @@ typedef enum open_path_flags_t {
open_path_allow_null = 8
} open_path_flags_t;
+/* Try a short-cut for the open_path() function using the last node accessed.
+ * If that ROOT is that nodes's "created rev" and PATH of PATH_LEN chars is
+ * its "created path", return the node in *NODE_P. Set it to NULL otherwise.
+ *
+ * This function is used to support ra_serf-style access patterns where we
+ * are first asked for path@rev and then for path@c_rev of the same node.
+ * The shortcut works by ignoring the "rev" part of the cache key and then
+ * checking whether we got lucky. Lookup and verification are both quick
+ * plus there are many early outs for common types of mismatch.
+ */
+static svn_error_t *
+try_match_last_node(dag_node_t **node_p,
+ svn_fs_root_t *root,
+ const char *path,
+ apr_size_t path_len,
+ apr_pool_t *scratch_pool)
+{
+ fs_fs_data_t *ffd = root->fs->fsap_data;
+
+ /* Optimistic lookup: if the last node returned from the cache applied to
+ the same PATH, return it in NODE. */
+ dag_node_t *node
+ = cache_lookup_last_path(ffd->dag_node_cache, path, path_len);
+
+ /* Did we get a bucket with a committed node? */
+ if (node && !svn_fs_fs__dag_check_mutable(node))
+ {
+ /* Get the path&rev pair at which this node was created.
+ This is repository location for which this node is _known_ to be
+ the right lookup result irrespective of how we found it. */
+ const char *created_path
+ = svn_fs_fs__dag_get_created_path(node);
+ svn_revnum_t revision;
+ SVN_ERR(svn_fs_fs__dag_get_revision(&revision, node, scratch_pool));
+
+ /* Is it an exact match? */
+ if (revision == root->rev && strcmp(created_path, path) == 0)
+ {
+ /* Cache it under its full path@rev access path. */
+ SVN_ERR(dag_node_cache_set(root, path, node, scratch_pool));
+
+ *node_p = node;
+ return SVN_NO_ERROR;
+ }
+ }
+
+ *node_p = NULL;
+ return SVN_NO_ERROR;
+}
+
/* Open the node identified by PATH in ROOT, allocating in POOL. Set
*PARENT_PATH_P to a path from the node up to ROOT. The resulting
@@ -959,20 +928,55 @@ open_path(parent_path_t **parent_path_p,
at the respective position and replacing that with a '/' in the next
iteration. This is correct as we assert() PATH to be canonical. */
svn_stringbuf_t *path_so_far = svn_stringbuf_create(path, pool);
+ apr_size_t path_len = path_so_far->len;
- /* callers often traverse the tree in some path-based order. That means
- a sibling of PATH has been presently accessed. Try to start the lookup
- directly at the parent node, if the caller did not requested the full
- parent chain. */
+ /* Callers often traverse the DAG in some path-based order or along the
+ history segments. That allows us to try a few guesses about where to
+ find the next item. This is only useful if the caller didn't request
+ the full parent chain. */
assert(svn_fs__is_canonical_abspath(path));
path_so_far->len = 0; /* "" */
if (flags & open_path_node_only)
{
- const char *directory = svn_dirent_dirname(path, pool);
+ const char *directory;
+
+ /* First attempt: Assume that we access the DAG for the same path as
+ in the last lookup but for a different revision that happens to be
+ the last revision that touched the respective node. This is a
+ common pattern when e.g. checking out over ra_serf. Note that this
+ will only work for committed data as the revision info for nodes in
+ txns is bogus.
+
+ This shortcut is quick and will exit this function upon success.
+ So, try it first. */
+ if (!root->is_txn_root)
+ {
+ dag_node_t *node;
+ SVN_ERR(try_match_last_node(&node, root, path, path_len, iterpool));
+
+ /* Did the shortcut work? */
+ if (node)
+ {
+ /* Construct and return the result. */
+ svn_pool_destroy(iterpool);
+
+ parent_path = make_parent_path(node, 0, 0, pool);
+ parent_path->copy_inherit = copy_id_inherit_self;
+ *parent_path_p = parent_path;
+
+ return SVN_NO_ERROR;
+ }
+ }
+
+ /* Second attempt: Try starting the lookup immediately at the parent
+ node. We will often have recently accessed either a sibling or
+ said parent DIRECTORY itself for the same revision. */
+ directory = svn_dirent_dirname(path, pool);
if (directory[1] != 0) /* root nodes are covered anyway */
{
- SVN_ERR(dag_node_cache_get(&here, root, directory, TRUE, pool));
- /* did the shortcut work? */
+ SVN_ERR(dag_node_cache_get(&here, root, directory, pool));
+
+ /* Did the shortcut work? */
if (here)
{
apr_size_t dirname_len = strlen(directory);
@@ -1016,15 +1020,12 @@ open_path(parent_path_t **parent_path_p,
path_so_far->len += strlen(entry) + 1;
path_so_far->data[path_so_far->len] = '\0';
- if (*entry == '\0')
- {
- /* Given the behavior of svn_fs__next_entry_name(), this
- happens when the path either starts or ends with a slash.
- In either case, we stay put: the current directory stays
- the same, and we add nothing to the parent path. */
- child = here;
- }
- else
+ /* Given the behavior of svn_fs__next_entry_name(), ENTRY may be an
+ empty string when the path either starts or ends with a slash.
+ In either case, we stay put: the current directory stays the
+ same, and we add nothing to the parent path. We only need to
+ process non-empty path segments. */
+ if (*entry != '\0')
{
copy_id_inherit_t inherit;
const char *copy_path = NULL;
@@ -1037,7 +1038,7 @@ open_path(parent_path_t **parent_path_p,
complete path. */
if (next || !(flags & open_path_uncached))
SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far->data,
- TRUE, pool));
+ pool));
if (cached_node)
child = cached_node;
else
@@ -1073,7 +1074,7 @@ open_path(parent_path_t **parent_path_p,
if (flags & open_path_node_only)
{
/* Shortcut: the caller only wants the final DAG node. */
- parent_path->node = child;
+ parent_path->node = svn_fs_fs__dag_copy_into_pool(child, pool);
}
else
{
@@ -1104,7 +1105,10 @@ open_path(parent_path_t **parent_path_p,
apr_psprintf(iterpool, _("Failure opening '%s'"), path));
rest = next;
- here = child;
+
+ /* The NODE in PARENT_PATH equals CHILD but lives in POOL, i.e.
+ * it will survive the cleanup of ITERPOOL.*/
+ here = parent_path->node;
}
svn_pool_destroy(iterpool);
@@ -1176,8 +1180,7 @@ make_path_mutable(svn_fs_root_t *root,
parent_path->node));
SVN_ERR(svn_fs_fs__revision_root(©root_root, root->fs,
copyroot_rev, pool));
- SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path,
- FALSE, pool));
+ SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool));
child_id = svn_fs_fs__dag_get_id(parent_path->node);
copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
@@ -1215,15 +1218,11 @@ make_path_mutable(svn_fs_root_t *root,
/* Open the node identified by PATH in ROOT. Set DAG_NODE_P to the
node we find, allocated in POOL. Return the error
SVN_ERR_FS_NOT_FOUND if this node doesn't exist.
-
- Since locking can be expensive and POOL may be long-living, for
- nodes that will not need to survive the next call to this function,
- set NEEDS_LOCK_CACHE to FALSE. */
+ */
static svn_error_t *
get_dag(dag_node_t **dag_node_p,
svn_fs_root_t *root,
const char *path,
- svn_boolean_t needs_lock_cache,
apr_pool_t *pool)
{
parent_path_t *parent_path;
@@ -1232,7 +1231,7 @@ get_dag(dag_node_t **dag_node_p,
/* First we look for the DAG in our cache
(if the path may be canonical). */
if (*path == '/')
- SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache, pool));
+ SVN_ERR(dag_node_cache_get(&node, root, path, pool));
if (! node)
{
@@ -1242,8 +1241,7 @@ get_dag(dag_node_t **dag_node_p,
* performance benefit over previously checking path for being
* canonical. */
path = svn_fs__canonicalize_abspath(path, pool);
- SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache,
- pool));
+ SVN_ERR(dag_node_cache_get(&node, root, path, pool));
if (! node)
{
@@ -1258,7 +1256,7 @@ get_dag(dag_node_t **dag_node_p,
}
}
- *dag_node_p = node;
+ *dag_node_p = svn_fs_fs__dag_copy_into_pool(node, pool);
return SVN_NO_ERROR;
}
@@ -1322,7 +1320,7 @@ svn_fs_fs__node_id(const svn_fs_id_t **i
{
dag_node_t *node;
- SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+ SVN_ERR(get_dag(&node, root, path, pool));
*id_p = svn_fs_fs__id_copy(svn_fs_fs__dag_get_id(node), pool);
}
return SVN_NO_ERROR;
@@ -1371,12 +1369,12 @@ fs_node_relation(svn_fs_node_relation_t
/* We checked for all separations between ID spaces (repos, txn).
* Now, we can simply test for the ID values themselves. */
- SVN_ERR(get_dag(&node, root_a, path_a, FALSE, pool));
+ SVN_ERR(get_dag(&node, root_a, path_a, pool));
id = svn_fs_fs__dag_get_id(node);
rev_item_a = *svn_fs_fs__id_rev_item(id);
node_id_a = *svn_fs_fs__id_node_id(id);
- SVN_ERR(get_dag(&node, root_b, path_b, FALSE, pool));
+ SVN_ERR(get_dag(&node, root_b, path_b, pool));
id = svn_fs_fs__dag_get_id(node);
rev_item_b = *svn_fs_fs__id_rev_item(id);
node_id_b = *svn_fs_fs__id_node_id(id);
@@ -1399,7 +1397,7 @@ svn_fs_fs__node_created_rev(svn_revnum_t
{
dag_node_t *node;
- SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+ SVN_ERR(get_dag(&node, root, path, pool));
return svn_fs_fs__dag_get_revision(revision, node, pool);
}
@@ -1414,7 +1412,7 @@ fs_node_created_path(const char **create
{
dag_node_t *node;
- SVN_ERR(get_dag(&node, root, path, TRUE, pool));
+ SVN_ERR(get_dag(&node, root, path, pool));
*created_path = svn_fs_fs__dag_get_created_path(node);
return SVN_NO_ERROR;
@@ -1478,7 +1476,7 @@ fs_node_prop(svn_string_t **value_p,
dag_node_t *node;
apr_hash_t *proplist;
- SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+ SVN_ERR(get_dag(&node, root, path, pool));
SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, node, pool));
*value_p = NULL;
if (proplist)
@@ -1501,7 +1499,7 @@ fs_node_proplist(apr_hash_t **table_p,
apr_hash_t *table;
dag_node_t *node;
- SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+ SVN_ERR(get_dag(&node, root, path, pool));
SVN_ERR(svn_fs_fs__dag_get_proplist(&table, node, pool));
*table_p = table ? table : apr_hash_make(pool);
@@ -1622,8 +1620,8 @@ fs_props_changed(svn_boolean_t *changed_
(SVN_ERR_FS_GENERAL, NULL,
_("Cannot compare property value between two different filesystems"));
- SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool));
- SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool));
+ SVN_ERR(get_dag(&node1, root1, path1, pool));
+ SVN_ERR(get_dag(&node2, root2, path2, pool));
return svn_fs_fs__dag_things_different(changed_p, NULL,
node1, node2, strict, pool);
}
@@ -1636,7 +1634,7 @@ fs_props_changed(svn_boolean_t *changed_
static svn_error_t *
get_root(dag_node_t **node, svn_fs_root_t *root, apr_pool_t *pool)
{
- return get_dag(node, root, "/", TRUE, pool);
+ return get_dag(node, root, "/", pool);
}
@@ -2367,7 +2365,7 @@ fs_dir_entries(apr_hash_t **table_p,
int i;
/* Get the entries for this path in the caller's pool. */
- SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+ SVN_ERR(get_dag(&node, root, path, pool));
SVN_ERR(svn_fs_fs__dag_dir_entries(&table, node, pool));
/* Convert directory array to hash. */
@@ -2567,7 +2565,7 @@ copy_helper(svn_fs_root_t *from_root,
_("Copy immutable tree not supported"));
/* Get the NODE for FROM_PATH in FROM_ROOT.*/
- SVN_ERR(get_dag(&from_node, from_root, from_path, TRUE, pool));
+ SVN_ERR(get_dag(&from_node, from_root, from_path, pool));
/* Build up the parent path from TO_PATH in TO_ROOT. If the last
component does not exist, it's not that big a deal. We'll just
@@ -2644,7 +2642,7 @@ copy_helper(svn_fs_root_t *from_root,
pool));
/* Make a record of this modification in the changes table. */
- SVN_ERR(get_dag(&new_node, to_root, to_path, TRUE, pool));
+ SVN_ERR(get_dag(&new_node, to_root, to_path, pool));
SVN_ERR(add_change(to_root->fs, txn_id, to_path,
svn_fs_fs__dag_get_id(new_node), kind, FALSE,
FALSE, FALSE, svn_fs_fs__dag_node_kind(from_node),
@@ -2725,7 +2723,7 @@ fs_copied_from(svn_revnum_t *rev_p,
/* There is no cached entry, look it up the old-fashioned
way. */
- SVN_ERR(get_dag(&node, root, path, TRUE, pool));
+ SVN_ERR(get_dag(&node, root, path, pool));
SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(rev_p, node));
SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(path_p, node));
@@ -2796,7 +2794,7 @@ fs_file_length(svn_filesize_t *length_p,
dag_node_t *file;
/* First create a dag_node_t from the root/path pair. */
- SVN_ERR(get_dag(&file, root, path, FALSE, pool));
+ SVN_ERR(get_dag(&file, root, path, pool));
/* Now fetch its length */
return svn_fs_fs__dag_file_length(length_p, file, pool);
@@ -2815,7 +2813,7 @@ fs_file_checksum(svn_checksum_t **checks
{
dag_node_t *file;
- SVN_ERR(get_dag(&file, root, path, FALSE, pool));
+ SVN_ERR(get_dag(&file, root, path, pool));
return svn_fs_fs__dag_file_checksum(checksum, file, kind, pool);
}
@@ -2834,7 +2832,7 @@ fs_file_contents(svn_stream_t **contents
svn_stream_t *file_stream;
/* First create a dag_node_t from the root/path pair. */
- SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+ SVN_ERR(get_dag(&node, root, path, pool));
/* Then create a readable stream from the dag_node_t. */
SVN_ERR(svn_fs_fs__dag_get_contents(&file_stream, node, pool));
@@ -2857,7 +2855,7 @@ fs_try_process_file_contents(svn_boolean
apr_pool_t *pool)
{
dag_node_t *node;
- SVN_ERR(get_dag(&node, root, path, FALSE, pool));
+ SVN_ERR(get_dag(&node, root, path, pool));
return svn_fs_fs__dag_try_process_file_contents(success, node,
processor, baton, pool);
@@ -3181,8 +3179,8 @@ fs_contents_changed(svn_boolean_t *chang
(SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path2);
}
- SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool));
- SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool));
+ SVN_ERR(get_dag(&node1, root1, path1, pool));
+ SVN_ERR(get_dag(&node2, root2, path2, pool));
return svn_fs_fs__dag_things_different(NULL, changed_p,
node1, node2, strict, pool);
}
@@ -3202,10 +3200,10 @@ fs_get_file_delta_stream(svn_txdelta_str
dag_node_t *source_node, *target_node;
if (source_root && source_path)
- SVN_ERR(get_dag(&source_node, source_root, source_path, TRUE, pool));
+ SVN_ERR(get_dag(&source_node, source_root, source_path, pool));
else
source_node = NULL;
- SVN_ERR(get_dag(&target_node, target_root, target_path, TRUE, pool));
+ SVN_ERR(get_dag(&target_node, target_root, target_path, pool));
/* Create a delta stream that turns the source into the target. */
return svn_fs_fs__dag_get_file_delta_stream(stream_p, source_node,
@@ -3669,7 +3667,7 @@ history_prev(svn_fs_history_t **prev_his
SVN_ERR(svn_fs_fs__revision_root(©root_root, fs, copyroot_rev,
scratch_pool));
- SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, FALSE, scratch_pool));
+ SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, scratch_pool));
copy_dst = svn_fs_fs__dag_get_created_path(node);
/* If our current path was the very destination of the copy,
@@ -3753,12 +3751,14 @@ fs_history_prev(svn_fs_history_t **prev_
}
else
{
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
prev_history = history;
while (1)
{
+ svn_pool_clear(iterpool);
SVN_ERR(history_prev(&prev_history, prev_history, cross_copies,
- result_pool, scratch_pool));
+ result_pool, iterpool));
if (! prev_history)
break;
@@ -3766,6 +3766,8 @@ fs_history_prev(svn_fs_history_t **prev_
if (fhd->is_interesting)
break;
}
+
+ svn_pool_destroy(iterpool);
}
*prev_history_p = prev_history;
@@ -3859,7 +3861,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs
svn_pool_clear(iterpool);
kid_path = svn_fspath__join(this_path, dirent->name, iterpool);
- SVN_ERR(get_dag(&kid_dag, root, kid_path, TRUE, iterpool));
+ SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool));
SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag));
SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag));
@@ -4105,7 +4107,7 @@ add_descendant_mergeinfo(svn_mergeinfo_c
dag_node_t *this_dag;
svn_boolean_t go_down;
- SVN_ERR(get_dag(&this_dag, root, path, TRUE, scratch_pool));
+ SVN_ERR(get_dag(&this_dag, root, path, scratch_pool));
SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down,
this_dag));
if (go_down)
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/verify.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/verify.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/verify.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/verify.c Tue Jan 20 17:52:18 2015
@@ -405,7 +405,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs,
"refers to revision %ld outside "
"the rev / pack file (%ld-%ld)"),
apr_off_t_toa(pool, entry->offset),
- (long)entry->item.number,
+ entry->item.revision,
start, start + count - 1);
}
else
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_util/fs-util.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_util/fs-util.c?rev=1653314&r1=1653313&r2=1653314&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_util/fs-util.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_util/fs-util.c Tue Jan 20 17:52:18 2015
@@ -38,6 +38,14 @@
#include "private/svn_subr_private.h"
#include "../libsvn_fs/fs-loader.h"
+
+const svn_version_t *
+svn_fs_util__version(void)
+{
+ SVN_VERSION_BODY;
+}
+
+
/* Return TRUE, if PATH of PATH_LEN > 0 chars starts with a '/' and does
* not end with a '/' and does not contain duplicate '/'.
*/
Propchange: subversion/branches/move-tracking-2/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Jan 20 17:52:18 2015
@@ -20,6 +20,7 @@
/subversion/branches/fsfs-lock-many/subversion/libsvn_fs_x:1571740-1577217
/subversion/branches/fsfs-pack/subversion/libsvn_fs_x:873717-874575
/subversion/branches/fsx/subversion/libsvn_fs_x:1507845-1508040
+/subversion/branches/fsx-id/subversion/libsvn_fs_x:1645603-1649011
/subversion/branches/gnome-keyring/subversion/libsvn_fs_x:870558-871410
/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_x:1005036-1150766
/subversion/branches/gtest_addition/subversion/libsvn_fs_x:1452117-1502138
@@ -85,5 +86,5 @@
/subversion/branches/verify-at-commit/subversion/libsvn_fs_x:1462039-1462408
/subversion/branches/verify-keep-going/subversion/libsvn_fs_x:1439280-1492639,1546002-1546110
/subversion/branches/wc-collate-path/subversion/libsvn_fs_x:1402685-1480384
-/subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629
-/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1606692-1641646
+/subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162
4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612
+/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1606692-1653312