Author: stefan2
Date: Tue Jan 21 03:06:00 2014
New Revision: 1559912
URL: http://svn.apache.org/r1559912
Log:
Speed up 'svn log -g' to almost the same speed as 'svn log'. Also, provide
a basis for speeding up other mergeinfo detection based code.
The problem is that svn_fs_path_change2_t used to report mergeinfo changes
as simple prop changes. Since most files are being created with default
props attached to them, this creates a lot of unnecessary property read
and comparison operations.
The idea is to a derive a mergeinfo-mod flag from the FS propset function
and store that in FSFS f7+ repositories (FSX will follow later). An extended
svn_fs_path_change2_t makes the information visible to the user.
* subversion/include/svn_fs.h
(svn_fs_path_change2_t): Add mergeinfo-mod as a tristate since we don't
have that information in old repositories.
* subversion/libsvn_fs_util/fs-util.c
(svn_fs__path_change_create_internal): Make sure the new member is always
initialized properly.
* subversion/libsvn_repos/log.c
(fs_mergeinfo_changed): Use the new information to skip unnecessary node
prop processing.
* subversion/libsvn_fs_fs/structure
(): Extend documentation to cover the new flag as well.
* subversion/libsvn_fs_fs/fs.h
(SVN_FS_FS__MIN_MERGEINFO_IN_CHANGES_FORMAT): New format capability flag.
* subversion/libsvn_fs_fs/low_level.c
(read_change): Detect the presense of the mergeinfo-mod flag and parse
it if found.
(write_change_entry): Write the mergeinfo-mod flag dependent on whether
its value is known and the new INCLUDE_MERGEINFO_MODS
parameter has been set.
(svn_fs_fs__write_changes): Include mergeinfo-mod only if supported by
the current FS format.
* subversion/libsvn_fs_fs/transaction.h
(svn_fs_fs__add_change): Add mergeinfo-mod parameter.
* subversion/libsvn_fs_fs/transaction.c
(replace_change): Copy mergeinfo-mod info as well.
(fold_change): Combine mergeinfo-mod info as well.
(svn_fs_fs__add_change): Store mergeinfo-mod info as well.
* subversion/libsvn_fs_fs/tree.c
(add_change): Add mergeinfo-mod pass-through parameter.
(fs_change_node_prop): Determine whether merge info was touched.
(fs_make_dir,
fs_delete_node,
copy_helper,
fs_make_file,
apply_textdelta,
apply_text): These never modify mergeinfo.
Modified:
subversion/trunk/subversion/include/svn_fs.h
subversion/trunk/subversion/libsvn_fs_fs/fs.h
subversion/trunk/subversion/libsvn_fs_fs/low_level.c
subversion/trunk/subversion/libsvn_fs_fs/structure
subversion/trunk/subversion/libsvn_fs_fs/transaction.c
subversion/trunk/subversion/libsvn_fs_fs/transaction.h
subversion/trunk/subversion/libsvn_fs_fs/tree.c
subversion/trunk/subversion/libsvn_fs_util/fs-util.c
subversion/trunk/subversion/libsvn_repos/log.c
Modified: subversion/trunk/subversion/include/svn_fs.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_fs.h?rev=1559912&r1=1559911&r2=1559912&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_fs.h (original)
+++ subversion/trunk/subversion/include/svn_fs.h Tue Jan 21 03:06:00 2014
@@ -1378,6 +1378,9 @@ typedef struct svn_fs_path_change2_t
svn_revnum_t copyfrom_rev;
const char *copyfrom_path;
+ /** were there mergeinfo mods?
+ * (Note: Pre-1.9 repositories will report #svn_tristate_unknown.) */
+ svn_tristate_t mergeinfo_mod;
/* NOTE! Please update svn_fs_path_change2_create() when adding new
fields here. */
} svn_fs_path_change2_t;
Modified: subversion/trunk/subversion/libsvn_fs_fs/fs.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/fs.h?rev=1559912&r1=1559911&r2=1559912&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/fs.h Tue Jan 21 03:06:00 2014
@@ -170,6 +170,9 @@ extern "C" {
/* The minimum format number that supports packed revprops. */
#define SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT 7
+/* Minimum format number that stores mergeinfo-mode flag in changed paths */
+#define SVN_FS_FS__MIN_MERGEINFO_IN_CHANGES_FORMAT 7
+
/* Minimum format number that will record moves */
#define SVN_FS_FS__MIN_MOVE_SUPPORT_FORMAT 7
Modified: subversion/trunk/subversion/libsvn_fs_fs/low_level.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/low_level.c?rev=1559912&r1=1559911&r2=1559912&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/low_level.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/low_level.c Tue Jan 21 03:06:00
2014
@@ -297,6 +297,30 @@ read_change(change_t **change_p,
_("Invalid prop-mod flag in rev-file"));
}
+ /* Get the mergeinfo-mod flag if given. Otherwise, the next thing
+ is the path starting with a slash. */
+ if (*last_str != '/')
+ {
+ str = svn_cstring_tokenize(" ", &last_str);
+ if (str == NULL)
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ _("Invalid changes line in rev-file"));
+
+ if (strcmp(str, FLAG_TRUE) == 0)
+ {
+ info->mergeinfo_mod = svn_tristate_true;
+ }
+ else if (strcmp(str, FLAG_FALSE) == 0)
+ {
+ info->mergeinfo_mod = svn_tristate_false;
+ }
+ else
+ {
+ return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+ _("Invalid mergeinfo-mod flag in rev-file"));
+ }
+ }
+
/* Get the changed path. */
change->path.len = strlen(last_str);
change->path.data = apr_pstrmemdup(pool, last_str, change->path.len);
@@ -353,18 +377,21 @@ svn_fs_fs__read_changes(apr_array_header
/* Write a single change entry, path PATH, change CHANGE, and copyfrom
string COPYFROM, into the file specified by FILE. Only include the
- node kind field if INCLUDE_NODE_KIND is true. All temporary
+ node kind field if INCLUDE_NODE_KIND is true. Only include the
+ mergeinfo-mod field if INCLUDE_MERGEINFO_MODS is true. All temporary
allocations are in POOL. */
static svn_error_t *
write_change_entry(svn_stream_t *stream,
const char *path,
svn_fs_path_change2_t *change,
svn_boolean_t include_node_kind,
+ svn_boolean_t include_mergeinfo_mods,
apr_pool_t *pool)
{
const char *idstr;
const char *change_string = NULL;
const char *kind_string = "";
+ const char *mergeinfo_string = "";
svn_stringbuf_t *buf;
apr_size_t len;
@@ -411,10 +438,18 @@ write_change_entry(svn_stream_t *stream,
? SVN_FS_FS__KIND_DIR
: SVN_FS_FS__KIND_FILE);
}
- buf = svn_stringbuf_createf(pool, "%s %s%s %s %s %s\n",
+
+ if (include_mergeinfo_mods && change->mergeinfo_mod != svn_tristate_unknown)
+ mergeinfo_string = apr_psprintf(pool, " %s",
+ change->mergeinfo_mod == svn_tristate_true
+ ? FLAG_TRUE
+ : FLAG_FALSE);
+
+ buf = svn_stringbuf_createf(pool, "%s %s%s %s %s%s %s\n",
idstr, change_string, kind_string,
change->text_mod ? FLAG_TRUE : FLAG_FALSE,
change->prop_mod ? FLAG_TRUE : FLAG_FALSE,
+ mergeinfo_string,
path);
if (SVN_IS_VALID_REVNUM(change->copyfrom_rev))
@@ -442,6 +477,8 @@ svn_fs_fs__write_changes(svn_stream_t *s
fs_fs_data_t *ffd = fs->fsap_data;
svn_boolean_t include_node_kinds =
ffd->format >= SVN_FS_FS__MIN_KIND_IN_CHANGED_FORMAT;
+ svn_boolean_t include_mergeinfo_mods =
+ ffd->format >= SVN_FS_FS__MIN_MERGEINFO_IN_CHANGES_FORMAT;
apr_array_header_t *sorted_changed_paths;
int i;
@@ -464,7 +501,7 @@ svn_fs_fs__write_changes(svn_stream_t *s
/* Write out the new entry into the final rev-file. */
SVN_ERR(write_change_entry(stream, path, change, include_node_kinds,
- iterpool));
+ include_mergeinfo_mods, iterpool));
}
if (terminate_list)
Modified: subversion/trunk/subversion/libsvn_fs_fs/structure
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/structure?rev=1559912&r1=1559911&r2=1559912&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/structure (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/structure Tue Jan 21 03:06:00 2014
@@ -180,6 +180,7 @@ Mergeinfo metadata:
Revision changed paths list:
Format 1-3: Does not contain the node's kind.
Format 4+: Contains the node's kind.
+ Format 7+: Contains the mergeinfo-mod flag.
Shard packing:
Format 4: Applied to revision data only.
@@ -574,20 +575,23 @@ its location is not yet known.
The changed-path data is represented as a series of changed-path
items, each consisting of two lines. The first line has the format
-"<id> <action> <text-mod> <prop-mod> <path>\n", where <id> is the
-node-rev ID of the new node-rev, <action> is "add", "delete",
-"replace", or "modify", <text-mod> and <prop-mod> are "true" or
-"false" indicating whether the text and/or properties changed, and
-<path> is the changed pathname. For deletes, <id> is the node-rev ID
-of the deleted node-rev, and <text-mod> and <prop-mod> are always
-"false". The second line has the format "<rev> <path>\n" containing
-the node-rev's copyfrom information if it has any; if it does not, the
-second line is blank.
+"<id> <action> <text-mod> <prop-mod> <mergeinfo-mod> <path>\n",
+where <id> is the node-rev ID of the new node-rev, <action> is "add",
+"delete", "replace", or "modify", <text-mod>, <prop-mod>, and
+<mergeinfo-mod> are "true" or "false" indicating whether the text,
+properties and/or mergeinfo changed, and <path> is the changed pathname.
+For deletes, <id> is the node-rev ID of the deleted node-rev, and
+<text-mod> and <prop-mod> are always "false". The second line has the
+format "<rev> <path>\n" containing the node-rev's copyfrom information
+if it has any; if it does not, the second line is blank.
Starting with FS format 4, <action> may contain the kind ("file" or
"dir") of the node, after a hyphen; for example, an added directory
may be represented as "add-dir".
+Before with FS format 7, <mergeinfo-mod> flag is not available. It may
+also be missing in revisions upgraded from pre-f7 formats.
+
In physical addressing mode, at the very end of a rev file is a pair of
lines containing "\n<root-offset> <cp-offset>\n", where <root-offset> is
the offset of the root directory node revision and <cp-offset> is the
Modified: subversion/trunk/subversion/libsvn_fs_fs/transaction.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/transaction.c?rev=1559912&r1=1559911&r2=1559912&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/transaction.c Tue Jan 21 03:06:00
2014
@@ -621,6 +621,7 @@ replace_change(svn_fs_path_change2_t *ol
pool);
old_change->text_mod = new_change->text_mod;
old_change->prop_mod = new_change->prop_mod;
+ old_change->mergeinfo_mod = new_change->mergeinfo_mod;
if (new_change->copyfrom_rev == SVN_INVALID_REVNUM)
{
old_change->copyfrom_rev = SVN_INVALID_REVNUM;
@@ -716,6 +717,7 @@ fold_change(apr_hash_t *changes,
old_change->change_kind = svn_fs_path_change_delete;
old_change->text_mod = info->text_mod;
old_change->prop_mod = info->prop_mod;
+ old_change->mergeinfo_mod = info->mergeinfo_mod;
old_change->copyfrom_rev = SVN_INVALID_REVNUM;
old_change->copyfrom_path = NULL;
}
@@ -743,6 +745,8 @@ fold_change(apr_hash_t *changes,
old_change->text_mod = TRUE;
if (info->prop_mod)
old_change->prop_mod = TRUE;
+ if (info->mergeinfo_mod == svn_tristate_true)
+ old_change->mergeinfo_mod = svn_tristate_true;
break;
}
@@ -1570,6 +1574,7 @@ svn_fs_fs__add_change(svn_fs_t *fs,
svn_fs_path_change_kind_t change_kind,
svn_boolean_t text_mod,
svn_boolean_t prop_mod,
+ svn_boolean_t mergeinfo_mod,
svn_node_kind_t node_kind,
svn_revnum_t copyfrom_rev,
const char *copyfrom_path,
@@ -1587,6 +1592,9 @@ svn_fs_fs__add_change(svn_fs_t *fs,
change = svn_fs__path_change_create_internal(id, change_kind, pool);
change->text_mod = text_mod;
change->prop_mod = prop_mod;
+ change->mergeinfo_mod = mergeinfo_mod
+ ? svn_tristate_true
+ : svn_tristate_false;
change->node_kind = node_kind;
change->copyfrom_rev = copyfrom_rev;
change->copyfrom_path = apr_pstrdup(pool, copyfrom_path);
Modified: subversion/trunk/subversion/libsvn_fs_fs/transaction.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/transaction.h?rev=1559912&r1=1559911&r2=1559912&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/transaction.h (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/transaction.h Tue Jan 21 03:06:00
2014
@@ -138,12 +138,12 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
/* Add a change to the changes record for filesystem FS in transaction
TXN_ID. Mark path PATH, having node-id ID, as changed according to
- the type in CHANGE_KIND. If the text representation was changed
- set TEXT_MOD to TRUE, and likewise for PROP_MOD. If this change
- was the result of a copy, set COPYFROM_REV and COPYFROM_PATH to the
- revision and path of the copy source, otherwise they should be set
- to SVN_INVALID_REVNUM and NULL. Perform any temporary allocations
- from POOL. */
+ the type in CHANGE_KIND. If the text representation was changed set
+ TEXT_MOD to TRUE, and likewise for PROP_MOD as well as MERGEINFO_MOD.
+ If this change was the result of a copy, set COPYFROM_REV and
+ COPYFROM_PATH to the revision and path of the copy source, otherwise
+ they should be set to SVN_INVALID_REVNUM and NULL. Perform any
+ temporary allocations from POOL. */
svn_error_t *
svn_fs_fs__add_change(svn_fs_t *fs,
const svn_fs_fs__id_part_t *txn_id,
@@ -152,6 +152,7 @@ svn_fs_fs__add_change(svn_fs_t *fs,
svn_fs_path_change_kind_t change_kind,
svn_boolean_t text_mod,
svn_boolean_t prop_mod,
+ svn_boolean_t mergeinfo_mod,
svn_node_kind_t node_kind,
svn_revnum_t copyfrom_rev,
const char *copyfrom_path,
Modified: subversion/trunk/subversion/libsvn_fs_fs/tree.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/tree.c?rev=1559912&r1=1559911&r2=1559912&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/tree.c Tue Jan 21 03:06:00 2014
@@ -1275,11 +1275,11 @@ get_dag(dag_node_t **dag_node_p,
/* Add a change to the changes table in FS, keyed on transaction id
TXN_ID, and indicated that a change of kind CHANGE_KIND occurred on
PATH (whose node revision id is--or was, in the case of a
- deletion--NODEREV_ID), and optionally that TEXT_MODs or PROP_MODs
- occurred. If the change resulted from a copy, COPYFROM_REV and
- COPYFROM_PATH specify under which revision and path the node was
- copied from. If this was not part of a copy, COPYFROM_REV should
- be SVN_INVALID_REVNUM. Do all this as part of POOL. */
+ deletion--NODEREV_ID), and optionally that TEXT_MODs, PROP_MODs or
+ MERGEINFO_MODs occurred. If the change resulted from a copy,
+ COPYFROM_REV and COPYFROM_PATH specify under which revision and path
+ the node was copied from. If this was not part of a copy, COPYFROM_REV
+ should be SVN_INVALID_REVNUM. Do all this as part of POOL. */
static svn_error_t *
add_change(svn_fs_t *fs,
const svn_fs_fs__id_part_t *txn_id,
@@ -1288,6 +1288,7 @@ add_change(svn_fs_t *fs,
svn_fs_path_change_kind_t change_kind,
svn_boolean_t text_mod,
svn_boolean_t prop_mod,
+ svn_boolean_t mergeinfo_mod,
svn_node_kind_t node_kind,
svn_revnum_t copyfrom_rev,
const char *copyfrom_path,
@@ -1295,7 +1296,8 @@ add_change(svn_fs_t *fs,
{
return svn_fs_fs__add_change(fs, txn_id,
svn_fs__canonicalize_abspath(path, pool),
- noderev_id, change_kind, text_mod, prop_mod,
+ noderev_id, change_kind,
+ text_mod, prop_mod, mergeinfo_mod,
node_kind, copyfrom_rev, copyfrom_path,
pool);
}
@@ -1542,6 +1544,7 @@ fs_change_node_prop(svn_fs_root_t *root,
parent_path_t *parent_path;
apr_hash_t *proplist;
const svn_fs_fs__id_part_t *txn_id;
+ svn_boolean_t modeinfo_mod = FALSE;
if (! root->is_txn_root)
return SVN_FS__NOT_TXN(root);
@@ -1585,6 +1588,8 @@ fs_change_node_prop(svn_fs_root_t *root,
SVN_ERR(svn_fs_fs__dag_set_has_mergeinfo(parent_path->node,
(value != NULL), pool));
}
+
+ modeinfo_mod = TRUE;
}
/* Set the property. */
@@ -1597,7 +1602,7 @@ fs_change_node_prop(svn_fs_root_t *root,
/* Make a record of this modification in the changes table. */
return add_change(root->fs, txn_id, path,
svn_fs_fs__dag_get_id(parent_path->node),
- svn_fs_path_change_modify, FALSE, TRUE,
+ svn_fs_path_change_modify, FALSE, TRUE, modeinfo_mod,
svn_fs_fs__dag_node_kind(parent_path->node),
SVN_INVALID_REVNUM, NULL, pool);
}
@@ -2441,8 +2446,8 @@ fs_make_dir(svn_fs_root_t *root,
/* Make a record of this modification in the changes table. */
return add_change(root->fs, txn_id, path, svn_fs_fs__dag_get_id(sub_dir),
- svn_fs_path_change_add, FALSE, FALSE, svn_node_dir,
- SVN_INVALID_REVNUM, NULL, pool);
+ svn_fs_path_change_add, FALSE, FALSE, FALSE,
+ svn_node_dir, SVN_INVALID_REVNUM, NULL, pool);
}
@@ -2499,7 +2504,7 @@ fs_delete_node(svn_fs_root_t *root,
/* Make a record of this modification in the changes table. */
return add_change(root->fs, txn_id, path,
svn_fs_fs__dag_get_id(parent_path->node),
- svn_fs_path_change_delete, FALSE, FALSE, kind,
+ svn_fs_path_change_delete, FALSE, FALSE, FALSE, kind,
SVN_INVALID_REVNUM, NULL, pool);
}
@@ -2748,8 +2753,8 @@ copy_helper(svn_fs_root_t *from_root,
/* Make a record of this modification in the changes table. */
SVN_ERR(get_dag(&new_node, to_root, to_path, TRUE, pool));
SVN_ERR(add_change(to_root->fs, txn_id, to_path,
- svn_fs_fs__dag_get_id(new_node), kind, FALSE, FALSE,
- svn_fs_fs__dag_node_kind(from_node),
+ svn_fs_fs__dag_get_id(new_node), kind, FALSE,
+ FALSE, FALSE, svn_fs_fs__dag_node_kind(from_node),
from_root->rev, from_canonpath, pool));
}
else
@@ -2904,8 +2909,8 @@ fs_make_file(svn_fs_root_t *root,
/* Make a record of this modification in the changes table. */
return add_change(root->fs, txn_id, path, svn_fs_fs__dag_get_id(child),
- svn_fs_path_change_add, TRUE, FALSE, svn_node_file,
- SVN_INVALID_REVNUM, NULL, pool);
+ svn_fs_path_change_add, TRUE, FALSE, FALSE,
+ svn_node_file, SVN_INVALID_REVNUM, NULL, pool);
}
@@ -3163,8 +3168,8 @@ apply_textdelta(void *baton, apr_pool_t
/* Make a record of this modification in the changes table. */
return add_change(tb->root->fs, txn_id, tb->path,
svn_fs_fs__dag_get_id(tb->node),
- svn_fs_path_change_modify, TRUE, FALSE, svn_node_file,
- SVN_INVALID_REVNUM, NULL, pool);
+ svn_fs_path_change_modify, TRUE, FALSE, FALSE,
+ svn_node_file, SVN_INVALID_REVNUM, NULL, pool);
}
@@ -3298,8 +3303,8 @@ apply_text(void *baton, apr_pool_t *pool
/* Make a record of this modification in the changes table. */
return add_change(tb->root->fs, txn_id, tb->path,
svn_fs_fs__dag_get_id(tb->node),
- svn_fs_path_change_modify, TRUE, FALSE, svn_node_file,
- SVN_INVALID_REVNUM, NULL, pool);
+ svn_fs_path_change_modify, TRUE, FALSE, FALSE,
+ svn_node_file, SVN_INVALID_REVNUM, NULL, pool);
}
Modified: subversion/trunk/subversion/libsvn_fs_util/fs-util.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_util/fs-util.c?rev=1559912&r1=1559911&r2=1559912&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_util/fs-util.c (original)
+++ subversion/trunk/subversion/libsvn_fs_util/fs-util.c Tue Jan 21 03:06:00
2014
@@ -198,6 +198,7 @@ svn_fs__path_change_create_internal(cons
change = apr_pcalloc(pool, sizeof(*change));
change->node_rev_id = node_rev_id;
change->change_kind = change_kind;
+ change->mergeinfo_mod = svn_tristate_unknown;
return change;
}
Modified: subversion/trunk/subversion/libsvn_repos/log.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/log.c?rev=1559912&r1=1559911&r2=1559912&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/log.c (original)
+++ subversion/trunk/subversion/libsvn_repos/log.c Tue Jan 21 03:06:00 2014
@@ -788,6 +788,10 @@ fs_mergeinfo_changed(svn_mergeinfo_catal
changed_path = key;
change = val;
+ /* If there was no mergeinfo change on this item, ignore it. */
+ if (change->mergeinfo_mod == svn_tristate_false)
+ continue;
+
/* If there was no property change on this item, ignore it. */
if (! change->prop_mod)
continue;