repair: Fix repair_tracker done

If it throws after repair_tracker.start and before the when_all below,
the repair_tracker.done will never be called for this repair id.

Fixes #2660
This commit is contained in:
Asias He
2017-08-02 16:12:16 +08:00
parent a998b7b3eb
commit abcff4c78e

View File

@@ -38,6 +38,7 @@
#include <cryptopp/sha.h>
#include <seastar/core/gate.hh>
#include <seastar/util/defer.hh>
static logging::logger rlogger("repair");
@@ -1050,6 +1051,7 @@ static int do_repair_start(seastar::sharded<database>& db, sstring keyspace,
int id = repair_tracker.next_repair_command();
rlogger.info("starting user-requested repair for keyspace {}, repair id {}, options {}", keyspace, id, options_map);
repair_tracker.start(id);
auto fail = defer([&repair_tracker, id] { repair_tracker.done(id, false); });
// If the "ranges" option is not explicitly specified, we repair all the
// local ranges (the token ranges for which this node holds a replica of).
@@ -1137,17 +1139,16 @@ static int do_repair_start(seastar::sharded<database>& db, sstring keyspace,
repair_results.push_back(std::move(f));
}
when_all(repair_results.begin(), repair_results.end()).then([id] (std::vector<future<>> results) {
when_all(repair_results.begin(), repair_results.end()).then([id, fail = std::move(fail)] (std::vector<future<>> results) mutable {
if (std::any_of(results.begin(), results.end(), [] (auto&& f) { return f.failed(); })) {
repair_tracker.done(id, false);
rlogger.info("repair {} failed", id);
} else {
fail.cancel();
repair_tracker.done(id, true);
rlogger.info("repair {} completed successfully", id);
}
return make_ready_future<>();
}).handle_exception([id] (std::exception_ptr eptr) {
repair_tracker.done(id, false);
rlogger.info("repair {} failed: {}", id, eptr);
});