1
0
mirror of https://github.com/codership/wsrep-lib.git synced 2025-07-03 16:22:35 +03:00

1. Never transition from s_donor directly to s_synced, always wait

for SYNCED event as expected.
2. Fix transition to `s_joined` only after we have a complete state.
   Complete state is reached in the following 3 cases:
   - SST seqno exceeds connected seqno
   - view seqno equals connected seqno (view processed == view connected)
   - current state is `s_donor`

Refs codership/wsrep-lib#175
This commit is contained in:
Alexey Yurchenko
2021-11-28 23:06:39 +02:00
parent 31a35bf573
commit 8f59e7b30b
2 changed files with 23 additions and 45 deletions

View File

@ -76,6 +76,8 @@ wsrep::reporter::substate_map(enum wsrep::server_state::state const state)
return s_disconnected_initializing; return s_disconnected_initializing;
else if (s_joining_sst == state_) else if (s_joining_sst == state_)
return s_joining_initializing; return s_joining_initializing;
else if (s_joining_initializing == state_)
return s_joining_initializing; // continuation
else else
{ {
assert(0); assert(0);
@ -87,6 +89,8 @@ wsrep::reporter::substate_map(enum wsrep::server_state::state const state)
return s_disconnected_initialized; return s_disconnected_initialized;
else if (s_joining_initializing == state_) else if (s_joining_initializing == state_)
return s_joining_ist; return s_joining_ist;
else if (s_joining_ist == state_)
return s_joining_ist; // continuation
else else
{ {
assert(0); assert(0);

View File

@ -668,8 +668,10 @@ int wsrep::server_state::start_sst(const std::string& sst_request,
if (server_service_.start_sst(sst_request, gtid, bypass)) if (server_service_.start_sst(sst_request, gtid, bypass))
{ {
lock.lock(); lock.lock();
wsrep::log_warning() << "SST start failed"; wsrep::log_warning() << "SST preparation failed";
state(lock, s_synced); // v26 API does not have JOINED event, so in anticipation of SYNCED
// we must do it here.
state(lock, s_joined);
ret = 1; ret = 1;
} }
return ret; return ret;
@ -683,6 +685,8 @@ void wsrep::server_state::sst_sent(const wsrep::gtid& gtid, int error)
wsrep::log_info() << "SST sending failed: " << error; wsrep::log_info() << "SST sending failed: " << error;
wsrep::unique_lock<wsrep::mutex> lock(mutex_); wsrep::unique_lock<wsrep::mutex> lock(mutex_);
// v26 API does not have JOINED event, so in anticipation of SYNCED
// we must do it here.
state(lock, s_joined); state(lock, s_joined);
lock.unlock(); lock.unlock();
enum provider::status const retval(provider().sst_sent(gtid, error)); enum provider::status const retval(provider().sst_sent(gtid, error));
@ -719,7 +723,6 @@ void wsrep::server_state::sst_received(wsrep::client_service& cs,
assert(init_initialized_); assert(init_initialized_);
} }
} }
state(lock, s_joined);
lock.unlock(); lock.unlock();
if (id_.is_undefined()) if (id_.is_undefined())
@ -893,7 +896,7 @@ void wsrep::server_state::on_connect(const wsrep::view& view)
} }
void wsrep::server_state::on_primary_view( void wsrep::server_state::on_primary_view(
const wsrep::view& view WSREP_UNUSED, const wsrep::view& view,
wsrep::high_priority_service* high_priority_service) wsrep::high_priority_service* high_priority_service)
{ {
wsrep::unique_lock<wsrep::mutex> lock(mutex_); wsrep::unique_lock<wsrep::mutex> lock(mutex_);
@ -930,15 +933,8 @@ void wsrep::server_state::on_primary_view(
// If server side has already been initialized, // If server side has already been initialized,
// skip directly to s_joined. // skip directly to s_joined.
state(lock, s_initialized); state(lock, s_initialized);
state(lock, s_joined);
} }
} }
else if (state_ == s_joiner)
{
// Got partiioned from the cluster, got IST and
// started applying actions.
state(lock, s_joined);
}
} }
else else
{ {
@ -946,14 +942,7 @@ void wsrep::server_state::on_primary_view(
{ {
state(lock, s_joiner); state(lock, s_joiner);
} }
if (init_initialized_ && state_ != s_joined)
{
// If server side has already been initialized,
// skip directly to s_joined.
state(lock, s_joined);
}
} }
if (init_initialized_ == false) if (init_initialized_ == false)
{ {
lock.unlock(); lock.unlock();
@ -978,27 +967,11 @@ void wsrep::server_state::on_primary_view(
close_orphaned_sr_transactions(lock, *high_priority_service); close_orphaned_sr_transactions(lock, *high_priority_service);
} }
if (server_service_.sst_before_init()) if (state(lock) < s_joined &&
view.state_id().seqno() >= connected_gtid().seqno())
{ {
if (state_ == s_initialized) // If we progressed beyond connected seqno, it means we have full state
{ state(lock, s_joined);
state(lock, s_joined);
if (init_synced_)
{
state(lock, s_synced);
}
}
}
else
{
if (state_ == s_joiner)
{
state(lock, s_joined);
if (init_synced_)
{
state(lock, s_synced);
}
}
} }
} }
@ -1079,13 +1052,14 @@ void wsrep::server_state::on_sync()
{ {
case s_synced: case s_synced:
break; break;
case s_connected: case s_connected: // Seed node path: provider becomes
state(lock, s_joiner); state(lock, s_joiner); // synced with itself before anything
WSREP_FALLTHROUGH; WSREP_FALLTHROUGH; // else. Then goes DB initialization.
case s_joiner: case s_joiner: // |
state(lock, s_initializing); state(lock, s_initializing); // V
break; break;
case s_donor: case s_donor:
assert(false); // this should never happen
state(lock, s_joined); state(lock, s_joined);
state(lock, s_synced); state(lock, s_synced);
break; break;
@ -1352,14 +1326,14 @@ void wsrep::server_state::state(
assert(lock.owns_lock()); assert(lock.owns_lock());
static const char allowed[n_states_][n_states_] = static const char allowed[n_states_][n_states_] =
{ {
/* dis, ing, ized, cted, jer, jed, dor, sed, ding */ /* dis, ing, ized, cted, jer, jed, dor, sed, ding to/from */
{ 0, 1, 0, 1, 0, 0, 0, 0, 0}, /* dis */ { 0, 1, 0, 1, 0, 0, 0, 0, 0}, /* dis */
{ 1, 0, 1, 0, 0, 0, 0, 0, 1}, /* ing */ { 1, 0, 1, 0, 0, 0, 0, 0, 1}, /* ing */
{ 1, 0, 0, 1, 0, 1, 0, 0, 1}, /* ized */ { 1, 0, 0, 1, 0, 1, 0, 0, 1}, /* ized */
{ 1, 0, 0, 1, 1, 0, 0, 1, 1}, /* cted */ { 1, 0, 0, 1, 1, 0, 0, 1, 1}, /* cted */
{ 1, 1, 0, 0, 0, 1, 0, 0, 1}, /* jer */ { 1, 1, 0, 0, 0, 1, 0, 0, 1}, /* jer */
{ 1, 0, 0, 1, 0, 0, 1, 1, 1}, /* jed */ { 1, 0, 0, 1, 0, 0, 1, 1, 1}, /* jed */
{ 1, 0, 0, 1, 0, 1, 0, 1, 1}, /* dor */ { 1, 0, 0, 1, 0, 1, 0, 0, 1}, /* dor */
{ 1, 0, 0, 1, 0, 1, 1, 0, 1}, /* sed */ { 1, 0, 0, 1, 0, 1, 1, 0, 1}, /* sed */
{ 1, 0, 0, 0, 0, 0, 0, 0, 0} /* ding */ { 1, 0, 0, 0, 0, 0, 0, 0, 0} /* ding */
}; };