Author: prabhugs
Date: Thu Jun 13 12:49:49 2013
New Revision: 1492651
URL: http://svn.apache.org/r1492651
Log:
Merge the verify-keep-going branch to trunk.
Implement a new "--keep-going" switch to svnadmin verify. Use this switch to
continue verify even after a repository corruption is seen. Without this
switch the verify process would stop when it sees any repository corruption.
* subversion/include/svn_error_codes.h
Add a new error code to describe the repository is corrupt.
* subversion/include/svn_repos.h
(svn_repos_verify_fs3): New function to handle the keepg-goin switch.
* subversion/libsvn_repos/deprecated.c
(svn_repos_verify_fs2): Deprecated. Call svn_repos_verify_fs3() with
keep-going
as False by default.
* subversion/libsvn_repos/dump.c
(notify_verification_error): Notify upon repository verification failure.
(verify_one_revision): Wrapper function to verify a revision.
(svn_repos_verify_fs3): Handle the keep-going switch. If set True, continue
the verify process and notify the corruption.
* subversion/svnadmin/svnadmin.c
Handle keep-going switch.
* subversion/tests/cmdline/svnadmin_tests.py
(verify_keep_going): Add a few test cases to test the keept-going switch.
* tools/dist/make-deps-tarball.sh
Just mergeinfo property change.
For a detailed log description refer the branch.
Approved by: stsp
Modified:
subversion/trunk/ (props changed)
subversion/trunk/subversion/include/svn_error_codes.h
subversion/trunk/subversion/include/svn_repos.h
subversion/trunk/subversion/libsvn_repos/deprecated.c
subversion/trunk/subversion/libsvn_repos/dump.c
subversion/trunk/subversion/svnadmin/svnadmin.c
subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py
subversion/trunk/tools/dist/make-deps-tarball.sh (props changed)
Propchange: subversion/trunk/
------------------------------------------------------------------------------
Merged /subversion/branches/verify-keep-going:r1439280-1492639
Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1492651&r1=1492650&r2=1492651&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Thu Jun 13 12:49:49
2013
@@ -850,6 +850,11 @@ SVN_ERROR_START
SVN_ERR_REPOS_CATEGORY_START + 10,
"Repository upgrade is not supported")
+ /** @since New in 1.9. */
+ SVN_ERRDEF(SVN_ERR_REPOS_CORRUPTED,
+ SVN_ERR_REPOS_CATEGORY_START + 11,
+ "Repository is corrupt")
+
/* generic RA errors */
SVN_ERRDEF(SVN_ERR_RA_ILLEGAL_URL,
Modified: subversion/trunk/subversion/include/svn_repos.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_repos.h?rev=1492651&r1=1492650&r2=1492651&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_repos.h (original)
+++ subversion/trunk/subversion/include/svn_repos.h Thu Jun 13 12:49:49 2013
@@ -251,7 +251,10 @@ typedef enum svn_repos_notify_action_t
svn_repos_notify_load_skipped_rev,
/** The structure of a revision is being verified. @since New in 1.8. */
- svn_repos_notify_verify_rev_structure
+ svn_repos_notify_verify_rev_structure,
+
+ /** A revision is found with corruption/errors. @since New in 1.9. */
+ svn_repos_notify_failure
} svn_repos_notify_action_t;
@@ -323,6 +326,11 @@ typedef struct svn_repos_notify_t
/** For #svn_repos_notify_load_node_start, the path of the node. */
const char *path;
+ /** For #svn_repos_notify_failure, this error chain indicates what
+ went wrong during verification.
+ @since New in 1.9. */
+ svn_error_t *err;
+
/* NOTE: Add new fields at the end to preserve binary compatibility.
Also, if you add fields here, you have to update
svn_repos_notify_create(). */
@@ -2592,12 +2600,39 @@ svn_repos_info_format(int *repos_format,
* the verified revision and @a warning_text @c NULL. For warnings call @a
* notify_func with @a warning_text set.
*
+ * For every revision verification failure, if @a notify_func is not @c NULL,
+ * call @a notify_func with @a rev set to the corrupt revision and @err set to
+ * the corresponding error message.
+ *
* If @a cancel_func is not @c NULL, call it periodically with @a
* cancel_baton as argument to see if the caller wishes to cancel the
* verification.
*
+ * If @a keep_going is @c TRUE, the verify process notifies the error message
+ * and continues. If @a notify_func is @c NULL, the verification failure is
+ * not notified. Finally, return an error if there were any failures during
+ * verification, or SVN_NO_ERROR if there were no failures.
+ *
+ * @since New in 1.9.
+ */
+svn_error_t *
+svn_repos_verify_fs3(svn_repos_t *repos,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_boolean_t keep_going,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Like svn_repos_verify_fs3(), but with @a keep_going set to @c FALSE.
+ *
* @since New in 1.7.
+ * @deprecated Provided for backward compatibility with the 1.7 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_repos_verify_fs2(svn_repos_t *repos,
svn_revnum_t start_rev,
Modified: subversion/trunk/subversion/libsvn_repos/deprecated.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/deprecated.c?rev=1492651&r1=1492650&r2=1492651&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_repos/deprecated.c Thu Jun 13 12:49:49
2013
@@ -727,6 +727,27 @@ svn_repos_dump_fs2(svn_repos_t *repos,
}
svn_error_t *
+svn_repos_verify_fs2(svn_repos_t *repos,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_repos_verify_fs3(repos,
+ start_rev,
+ end_rev,
+ FALSE,
+ notify_func,
+ notify_baton,
+ cancel_func,
+ cancel_baton,
+ pool));
+}
+
+svn_error_t *
svn_repos_verify_fs(svn_repos_t *repos,
svn_stream_t *feedback_stream,
svn_revnum_t start_rev,
Modified: subversion/trunk/subversion/libsvn_repos/dump.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/dump.c?rev=1492651&r1=1492650&r2=1492651&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/dump.c (original)
+++ subversion/trunk/subversion/libsvn_repos/dump.c Thu Jun 13 12:49:49 2013
@@ -1332,6 +1332,71 @@ verify_close_directory(void *dir_baton,
return close_directory(dir_baton, pool);
}
+static void
+notify_verification_error(svn_revnum_t rev,
+ svn_error_t *err,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ apr_pool_t *pool)
+{
+ svn_repos_notify_t *notify_failure;
+
+ if (notify_func == NULL)
+ return;
+
+ notify_failure = svn_repos_notify_create(svn_repos_notify_failure, pool);
+ notify_failure->err = err;
+ notify_failure->revision = rev;
+ notify_func(notify_baton, notify_failure, pool);
+}
+
+/* Verify revision REV in file system FS. */
+static svn_error_t *
+verify_one_revision(svn_fs_t *fs,
+ svn_revnum_t rev,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_revnum_t start_rev,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ const svn_delta_editor_t *dump_editor;
+ void *dump_edit_baton;
+ svn_fs_root_t *to_root;
+ apr_hash_t *props;
+ const svn_delta_editor_t *cancel_editor;
+ void *cancel_edit_baton;
+
+ /* Get cancellable dump editor, but with our close_directory handler.*/
+ SVN_ERR(get_dump_editor(&dump_editor, &dump_edit_baton,
+ fs, rev, "",
+ svn_stream_empty(scratch_pool),
+ NULL, NULL,
+ verify_close_directory,
+ notify_func, notify_baton,
+ start_rev,
+ FALSE, TRUE, /* use_deltas, verify */
+ scratch_pool));
+ SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
+ dump_editor, dump_edit_baton,
+ &cancel_editor,
+ &cancel_edit_baton,
+ scratch_pool));
+ SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, scratch_pool));
+ SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
+ cancel_editor, cancel_edit_baton,
+ NULL, NULL, scratch_pool));
+
+ /* While our editor close_edit implementation is a no-op, we still
+ do this for completeness. */
+ SVN_ERR(cancel_editor->close_edit(cancel_edit_baton, scratch_pool));
+
+ SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
/* Baton type used for forwarding notifications from FS API to REPOS API. */
struct verify_fs2_notify_func_baton_t
{
@@ -1359,9 +1424,10 @@ verify_fs2_notify_func(svn_revnum_t revi
}
svn_error_t *
-svn_repos_verify_fs2(svn_repos_t *repos,
+svn_repos_verify_fs3(svn_repos_t *repos,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
+ svn_boolean_t keep_going,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
@@ -1375,6 +1441,8 @@ svn_repos_verify_fs2(svn_repos_t *repos,
svn_repos_notify_t *notify;
svn_fs_progress_notify_func_t verify_notify = NULL;
struct verify_fs2_notify_func_baton_t *verify_notify_baton = NULL;
+ svn_error_t *err;
+ svn_boolean_t found_corruption = FALSE;
/* Determine the current youngest revision of the filesystem. */
SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
@@ -1403,7 +1471,6 @@ svn_repos_verify_fs2(svn_repos_t *repos,
{
notify = svn_repos_notify_create(svn_repos_notify_verify_rev_end,
pool);
-
verify_notify = verify_fs2_notify_func;
verify_notify_baton = apr_palloc(pool, sizeof(*verify_notify_baton));
verify_notify_baton->notify_func = notify_func;
@@ -1413,49 +1480,50 @@ svn_repos_verify_fs2(svn_repos_t *repos,
}
/* Verify global metadata and backend-specific data first. */
- SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), svn_fs_config(fs, pool),
- start_rev, end_rev,
- verify_notify, verify_notify_baton,
- cancel_func, cancel_baton, pool));
+ err = svn_fs_verify(svn_fs_path(fs, pool), svn_fs_config(fs, pool),
+ start_rev, end_rev,
+ verify_notify, verify_notify_baton,
+ cancel_func, cancel_baton, pool);
- for (rev = start_rev; rev <= end_rev; rev++)
+ if (err && !keep_going)
{
- const svn_delta_editor_t *dump_editor;
- void *dump_edit_baton;
- const svn_delta_editor_t *cancel_editor;
- void *cancel_edit_baton;
- svn_fs_root_t *to_root;
- apr_hash_t *props;
+ found_corruption = TRUE;
+ notify_verification_error(SVN_INVALID_REVNUM, err, notify_func,
+ notify_baton, iterpool);
+ svn_error_clear(err);
+ return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, NULL,
+ _("Repository '%s' failed to verify"),
+ svn_dirent_local_style(svn_repos_path(repos,
+ pool),
+ pool));
+ }
+ else
+ {
+ if (err)
+ found_corruption = TRUE;
+ svn_error_clear(err);
+ }
+ for (rev = start_rev; rev <= end_rev; rev++)
+ {
svn_pool_clear(iterpool);
- /* Get cancellable dump editor, but with our close_directory handler. */
- SVN_ERR(get_dump_editor(&dump_editor, &dump_edit_baton,
- fs, rev, "",
- svn_stream_empty(iterpool),
- NULL, NULL,
- verify_close_directory,
- notify_func, notify_baton,
- start_rev,
- FALSE, TRUE, /* use_deltas, verify */
- iterpool));
- SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
- dump_editor, dump_edit_baton,
- &cancel_editor,
- &cancel_edit_baton,
- iterpool));
-
- SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, iterpool));
- SVN_ERR(svn_fs_verify_root(to_root, iterpool));
-
- SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
- cancel_editor, cancel_edit_baton,
- NULL, NULL, iterpool));
- /* While our editor close_edit implementation is a no-op, we still
- do this for completeness. */
- SVN_ERR(cancel_editor->close_edit(cancel_edit_baton, iterpool));
+ /* Wrapper function to catch the possible errors. */
+ err = verify_one_revision(fs, rev, notify_func, notify_baton, start_rev,
+ cancel_func, cancel_baton, iterpool);
- SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, iterpool));
+ if (err)
+ {
+ found_corruption = TRUE;
+ notify_verification_error(rev, err, notify_func, notify_baton,
+ iterpool);
+ svn_error_clear(err);
+
+ if (keep_going)
+ continue;
+ else
+ break;
+ }
if (notify_func)
{
@@ -1474,5 +1542,12 @@ svn_repos_verify_fs2(svn_repos_t *repos,
/* Per-backend verification. */
svn_pool_destroy(iterpool);
+ if (found_corruption)
+ return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, NULL,
+ _("Repository '%s' failed to verify"),
+ svn_dirent_local_style(svn_repos_path(repos,
+ pool),
+ pool));
+
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/svnadmin/svnadmin.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svnadmin/svnadmin.c?rev=1492651&r1=1492650&r2=1492651&view=diff
==============================================================================
--- subversion/trunk/subversion/svnadmin/svnadmin.c (original)
+++ subversion/trunk/subversion/svnadmin/svnadmin.c Thu Jun 13 12:49:49 2013
@@ -180,6 +180,7 @@ enum svnadmin__cmdline_options_t
{
svnadmin__version = SVN_OPT_FIRST_LONGOPT_ID,
svnadmin__incremental,
+ svnadmin__keep_going,
svnadmin__deltas,
svnadmin__ignore_uuid,
svnadmin__force_uuid,
@@ -288,6 +289,9 @@ static const apr_getopt_option_t options
{"pre-1.6-compatible", svnadmin__pre_1_6_compatible, 0,
N_("deprecated; see --compatible-version")},
+ {"keep-going", svnadmin__keep_going, 0,
+ N_("continue verification after detecting a corruption")},
+
{"memory-cache-size", 'M', 1,
N_("size of the extra in-memory cache in MB used to\n"
" minimize redundant operations. Default:
16.\n"
@@ -491,7 +495,7 @@ static const svn_opt_subcommand_desc2_t
{"verify", subcommand_verify, {0}, N_
("usage: svnadmin verify REPOS_PATH\n\n"
"Verify the data stored in the repository.\n"),
- {'t', 'r', 'q', 'M'} },
+ {'t', 'r', 'q', svnadmin__keep_going, 'M'} },
{ NULL, NULL, {0}, NULL, {0} }
};
@@ -522,6 +526,7 @@ struct svnadmin_opt_state
svn_boolean_t clean_logs; /* --clean-logs */
svn_boolean_t bypass_hooks; /* --bypass-hooks */
svn_boolean_t wait; /* --wait */
+ svn_boolean_t keep_going; /* --keep-going */
svn_boolean_t bypass_prop_validation; /*
--bypass-prop-validation */
enum svn_repos_load_uuid uuid_action; /* --ignore-uuid,
--force-uuid */
@@ -822,6 +827,16 @@ repos_notify_handler(void *baton,
notify->warning_str);
return;
+ case svn_repos_notify_failure:
+ if (notify->revision != SVN_INVALID_REVNUM)
+ cmdline_stream_printf(feedback_stream, scratch_pool,
+ _("* Error verifying revision %ld.\n"),
+ notify->revision);
+ if (notify->err)
+ svn_handle_error2(notify->err, stderr, FALSE /* non-fatal */,
+ "svnadmin: ");
+ return;
+
case svn_repos_notify_dump_rev_end:
cmdline_stream_printf(feedback_stream, scratch_pool,
_("* Dumped revision %ld.\n"),
@@ -1657,10 +1672,12 @@ subcommand_verify(apr_getopt_t *os, void
if (! opt_state->quiet)
progress_stream = recode_stream_create(stdout, pool);
- return svn_repos_verify_fs2(repos, lower, upper,
- !opt_state->quiet
- ? repos_notify_handler : NULL,
- progress_stream, check_cancel, NULL, pool);
+ return svn_error_trace(svn_repos_verify_fs3(repos, lower, upper,
+ opt_state->keep_going,
+ !opt_state->quiet
+ ? repos_notify_handler : NULL,
+ progress_stream, check_cancel,
+ NULL, pool));
}
/* This implements `svn_opt_subcommand_t'. */
@@ -2281,6 +2298,9 @@ sub_main(int argc, const char *argv[], a
opt_state.compatible_version = compatible_version;
}
break;
+ case svnadmin__keep_going:
+ opt_state.keep_going = TRUE;
+ break;
case svnadmin__fs_type:
SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.fs_type, opt_arg,
pool));
break;
Modified: subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py?rev=1492651&r1=1492650&r2=1492651&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svnadmin_tests.py Thu Jun 13
12:49:49 2013
@@ -1826,6 +1826,66 @@ def recover_old(sbox):
svntest.main.run_svnadmin("recover", sbox.repo_dir)
+def verify_keep_going(sbox):
+ "svnadmin verify --keep-going test"
+
+ sbox.build(create_wc = False)
+ repo_url = sbox.repo_url
+ B_url = sbox.repo_url + '/B'
+ C_url = sbox.repo_url + '/C'
+
+ # Create A/B/E/bravo in r2.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mkdir', '-m', 'log_msg',
+ B_url)
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mkdir', '-m', 'log_msg',
+ C_url)
+
+ r2 = fsfs_file(sbox.repo_dir, 'revs', '2')
+ fp = open(r2, 'a')
+ fp.write("""inserting junk to corrupt the rev""")
+ fp.close()
+ exit_code, output, errput = svntest.main.run_svnadmin("verify",
+ "--keep-going",
+ sbox.repo_dir)
+
+ exp_out = svntest.verify.RegexListOutput([".*Verifying repository metadata",
+ ".*Verified revision 0.",
+ ".*Verified revision 1.",
+ ".*Error verifying revision 2.",
+ ".*Verified revision 3."])
+
+ exp_err = svntest.verify.RegexListOutput(["svnadmin: E160004:.*",
+ "svnadmin: E165011:.*"], False)
+
+
+ if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin
verify'.",
+ output, errput, exp_out, exp_err):
+ raise svntest.Failure
+
+ exit_code, output, errput = svntest.main.run_svnadmin("verify",
+ sbox.repo_dir)
+
+ exp_out = svntest.verify.RegexListOutput([".*Verifying repository metadata",
+ ".*Verified revision 0.",
+ ".*Verified revision 1.",
+ ".*Error verifying revision 2."])
+
+ if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin
verify'.",
+ output, errput, exp_out, exp_err):
+ raise svntest.Failure
+
+
+ exit_code, output, errput = svntest.main.run_svnadmin("verify",
+ "--quiet",
+ sbox.repo_dir)
+
+ if svntest.verify.verify_outputs("Output of 'svnadmin verify' is
unexpected.",
+ None, errput, None, "svnadmin: E165011:.*"):
+ raise svntest.Failure
+
########################################################################
# Run the tests
@@ -1862,6 +1922,7 @@ test_list = [ None,
locking,
mergeinfo_race,
recover_old,
+ verify_keep_going,
]
if __name__ == '__main__':
Propchange: subversion/trunk/tools/dist/make-deps-tarball.sh
------------------------------------------------------------------------------
Merged
/subversion/branches/verify-keep-going/tools/dist/make-deps-tarball.sh:r1439280-1492639