diff --git a/include/libnuraft/peer.hxx b/include/libnuraft/peer.hxx index d802004d..a2a76a4d 100644 --- a/include/libnuraft/peer.hxx +++ b/include/libnuraft/peer.hxx @@ -241,6 +241,10 @@ public: void shutdown(); + void reopen(context& ctx, timer_task::executor& hb_exec); + + bool is_abandoned() const { return abandoned_; } + // Time that sent the last request. void reset_ls_timer() { last_sent_timer_.reset(); } uint64_t get_ls_timer_us() { return last_sent_timer_.get_us(); } @@ -626,6 +630,7 @@ private: */ std::atomic self_mark_down_; + /** * Logger instance. */ diff --git a/src/handle_timeout.cxx b/src/handle_timeout.cxx index 05ffee82..be57337a 100644 --- a/src/handle_timeout.cxx +++ b/src/handle_timeout.cxx @@ -34,6 +34,14 @@ namespace nuraft { void raft_server::enable_hb_for_peer(peer& p) { p.enable_hb(true); p.resume_hb_speed(); + if (p.is_abandoned()) { + timer_task::executor exec = + (timer_task::executor) + std::bind( &raft_server::handle_hb_timeout, + this, + std::placeholders::_1 ); + p.reopen(*ctx_, exec); + } p_tr("peer %d, interval: %d\n", p.get_id(), p.get_current_hb_interval()); schedule_task(p.get_hb_task(), p.get_current_hb_interval()); } @@ -343,6 +351,7 @@ void raft_server::cancel_schedulers() { cancel_task(p->get_hb_task()); } // Shutdown peer to cut off smart pointers. + p_tr("cancel_schedulers shutdown peer: %d", p->get_id()); p->shutdown(); // Free user context of snapshot if exists. diff --git a/src/peer.cxx b/src/peer.cxx index 1479a906..32a53362 100644 --- a/src/peer.cxx +++ b/src/peer.cxx @@ -313,6 +313,7 @@ bool peer::recreate_rpc(ptr& config, } void peer::shutdown() { + p_tr("peer %d shutdown", get_id()); // Should set the flag to block all incoming requests. abandoned_ = true; @@ -326,5 +327,19 @@ void peer::shutdown() { hb_task_.reset(); } + +void peer::reopen(context& ctx, timer_task::executor& hb_exec) { + p_tr("peer %d reopen", get_id()); + abandoned_ = false; + + scheduler_ = ctx.scheduler_; + hb_task_ = cs_new< timer_task, + timer_task::executor&, + int32 > + ( hb_exec, config_->get_id(), + timer_task_type::heartbeat_timer ) ; + p_tr("call peer %d reopen succeeded", get_id()); +} + } // namespace nuraft;