diff --git a/programs/keeper/Keeper.cpp b/programs/keeper/Keeper.cpp index 1d9bbef58a5..d5af2d6148e 100644 --- a/programs/keeper/Keeper.cpp +++ b/programs/keeper/Keeper.cpp @@ -239,6 +239,18 @@ std::string Keeper::getDefaultConfigFileName() const return "keeper_config.xml"; } +void Keeper::handleCustomArguments(const std::string & arg, const std::string & value) +{ + if (arg == "force-recovery") + { + assert(value.empty()); + config().setBool("keeper_server.recover", true); + return; + } + + throw Exception(ErrorCodes::LOGICAL_ERROR, "Invalid argument {} provided", arg); +} + void Keeper::defineOptions(Poco::Util::OptionSet & options) { options.addOption( @@ -251,6 +263,12 @@ void Keeper::defineOptions(Poco::Util::OptionSet & options) .required(false) .repeatable(false) .binding("version")); + options.addOption( + Poco::Util::Option("force-recovery", "force-recovery", "Force recovery mode allowing Keeper to overwrite cluster configuration") + .required(false) + .repeatable(false) + .noArgument() + .callback(Poco::Util::OptionCallback(this, &Keeper::handleCustomArguments))); BaseDaemon::defineOptions(options); } diff --git a/programs/keeper/Keeper.h b/programs/keeper/Keeper.h index 5b8fbadd0a2..db7a117c2e2 100644 --- a/programs/keeper/Keeper.h +++ b/programs/keeper/Keeper.h @@ -43,6 +43,8 @@ public: protected: void logRevision() const override; + void handleCustomArguments(const std::string & arg, const std::string & value); + int run() override; void initialize(Application & self) override; diff --git a/src/Coordination/KeeperServer.cpp b/src/Coordination/KeeperServer.cpp index 25d985a7ea3..13d7f67e697 100644 --- a/src/Coordination/KeeperServer.cpp +++ b/src/Coordination/KeeperServer.cpp @@ -102,7 +102,7 @@ KeeperServer::KeeperServer( checkAndGetSuperdigest(configuration_and_settings_->super_digest))) , state_manager(nuraft::cs_new(server_id, "keeper_server", configuration_and_settings_->log_storage_path, config, coordination_settings)) , log(&Poco::Logger::get("KeeperServer")) - , recover(config.getBool("recover")) + , recover(config.has("keeper_server.recover") && config.getBool("keeper_server.recover")) { if (coordination_settings->quorum_reads) LOG_WARNING(log, "Quorum reads enabled, Keeper will work slower."); @@ -127,7 +127,6 @@ void KeeperServer::loadLatestConfig() state_manager->save_config(*latest_log_store_config); - state_machine->commit_config(latest_log_store_config->get_log_idx(), latest_log_store_config); return; } @@ -182,6 +181,13 @@ void KeeperServer::startup(bool enable_ipv6) params.return_method_ = nuraft::raft_params::async_handler; + if (recover) + { + LOG_INFO(log, "Custom quorum size"); + params.with_custom_commit_quorum_size(1); + params.with_custom_election_quorum_size(1); + } + nuraft::asio_service::options asio_opts{}; if (state_manager->isSecure()) { @@ -226,13 +232,12 @@ void KeeperServer::launchRaftServer( nuraft::ptr casted_state_manager = state_manager; nuraft::ptr casted_state_machine = state_machine; - loadLatestConfig(); - /// raft_server creates unique_ptr from it nuraft::context * ctx = new nuraft::context( casted_state_manager, casted_state_machine, asio_listener, logger, rpc_cli_factory, scheduler, params); + loadLatestConfig(); raft_instance = nuraft::cs_new(ctx, init_options); raft_instance->start_server(init_options.skip_initial_election_timeout_);