diff --git a/include/wsrep/server_state.hpp b/include/wsrep/server_state.hpp index 729d863..a93e303 100644 --- a/include/wsrep/server_state.hpp +++ b/include/wsrep/server_state.hpp @@ -597,6 +597,9 @@ namespace wsrep // Close transactions when handling disconnect from the group. void close_transactions_at_disconnect(wsrep::high_priority_service&); + // Common actions on final view + void go_final(wsrep::unique_lock&, + const wsrep::view&, wsrep::high_priority_service*); wsrep::mutex& mutex_; wsrep::condition_variable& cond_; diff --git a/src/server_state.cpp b/src/server_state.cpp index 393c386..1def89f 100644 --- a/src/server_state.cpp +++ b/src/server_state.cpp @@ -591,25 +591,36 @@ wsrep::server_state::causal_read(int timeout) const void wsrep::server_state::on_connect(const wsrep::view& view) { // Sanity checks - if (id_.is_undefined() == false) - { - wsrep::log_warning() << "Unexpected connection in connected state. " - << "Received view: " << view - << "Previous ID: " << id_; - assert(0); - } - if (view.own_index() < 0 || size_t(view.own_index()) >= view.members().size()) { std::ostringstream os; os << "Invalid view on connect: own index out of range: " << view; +#ifndef NDEBUG wsrep::log_error() << os.str(); assert(0); +#endif throw wsrep::runtime_error(os.str()); } - id_ = view.members()[view.own_index()].id(); + if (id_.is_undefined() == false && + id_ != view.members()[view.own_index()].id()) + { + std::ostringstream os; + os << "Connection in connected state.\n" + << "Connected view:\n" << view + << "Previous view:\n" << current_view_ + << "Current own ID: " << id_; +#ifndef NDEBUG + wsrep::log_error() << os.str(); + assert(0); +#endif + throw wsrep::runtime_error(os.str()); + } + else + { + id_ = view.members()[view.own_index()].id(); + } wsrep::log_info() << "Server " << name_ @@ -623,6 +634,20 @@ void wsrep::server_state::on_connect(const wsrep::view& view) state(lock, s_connected); } +void wsrep::server_state::go_final(wsrep::unique_lock& lock, + const wsrep::view& view, + wsrep::high_priority_service* hps) +{ + assert(view.final()); + assert(hps); + if (hps) + { + close_transactions_at_disconnect(*hps); + } + state(lock, s_disconnected); + id_ = wsrep::id::undefined(); +} + void wsrep::server_state::on_view(const wsrep::view& view, wsrep::high_priority_service* high_priority_service) { @@ -730,13 +755,7 @@ void wsrep::server_state::on_view(const wsrep::view& view, wsrep::log_info() << "Non-primary view"; if (view.final()) { - assert(high_priority_service); - if (high_priority_service) - { - close_transactions_at_disconnect(*high_priority_service); - } - id_ = id::undefined(); - state(lock, s_disconnected); + go_final(lock, view, high_priority_service); } else if (state_ != s_disconnecting) { @@ -745,15 +764,8 @@ void wsrep::server_state::on_view(const wsrep::view& view, } else { - assert(view.final()); - assert(high_priority_service); - if (high_priority_service) - { - close_transactions_at_disconnect(*high_priority_service); - } wsrep::unique_lock lock(mutex_); - state(lock, s_disconnected); - id_ = wsrep::id::undefined(); + go_final(lock, view, high_priority_service); } server_service_.log_view(high_priority_service, view); diff --git a/src/wsrep_provider_v26.cpp b/src/wsrep_provider_v26.cpp index afc5c3b..717b54f 100644 --- a/src/wsrep_provider_v26.cpp +++ b/src/wsrep_provider_v26.cpp @@ -347,9 +347,12 @@ namespace assert(app_ctx); wsrep::server_state& server_state( *reinterpret_cast(app_ctx)); - assert(server_state.id().is_undefined()); wsrep::view view(view_from_native(*view_info, server_state.id())); assert(view.own_index() >= 0); + assert(// first connect + server_state.id().is_undefined() || + // reconnect to primary component + server_state.id() == view.members()[view.own_index()].id()); try { server_state.on_connect(view);