1
0
mirror of https://github.com/codership/wsrep-lib.git synced 2025-07-28 20:02:00 +03:00

Read recovered position from sst_received() after initialization

In general the position where the storage recovers after a SST
cannot be known untile the recovery process is over. This in turn
means that the position cannot be known when the server_state
sst_received() method is called. Worked around the problem by
introducing get_position() method into server service which
can be used to get the position from stable storage after SST
has completed and the state has been recovered.
This commit is contained in:
Teemu Ollakka
2019-01-14 13:11:57 +02:00
parent 17fc8c16de
commit 89b3561ad8
8 changed files with 43 additions and 13 deletions

View File

@ -128,6 +128,11 @@ wsrep::view db::server_service::get_view(wsrep::client_service&,
return my_view; return my_view;
} }
wsrep::gtid db::server_service::get_position(wsrep::client_service&)
{
throw wsrep::not_implemented_error();
}
void db::server_service::log_state_change( void db::server_service::log_state_change(
enum wsrep::server_state::state prev_state, enum wsrep::server_state::state prev_state,
enum wsrep::server_state::state current_state) enum wsrep::server_state::state current_state)

View File

@ -50,6 +50,7 @@ namespace db
const wsrep::view&) override; const wsrep::view&) override;
wsrep::view get_view(wsrep::client_service&, const wsrep::id&) wsrep::view get_view(wsrep::client_service&, const wsrep::id&)
override; override;
wsrep::gtid get_position(wsrep::client_service&) override;
void log_state_change(enum wsrep::server_state::state, void log_state_change(enum wsrep::server_state::state,
enum wsrep::server_state::state) override; enum wsrep::server_state::state) override;
int wait_committing_transactions(int) override; int wait_committing_transactions(int) override;

View File

@ -67,7 +67,7 @@ void db::simulator::sst(db::server& server,
db::client dummy(*(i->second), wsrep::client_id(-1), db::client dummy(*(i->second), wsrep::client_id(-1),
wsrep::client_state::m_local, params()); wsrep::client_state::m_local, params());
i->second->server_state().sst_received(dummy.client_service(), gtid, 0); i->second->server_state().sst_received(dummy.client_service(), 0);
server.server_state().sst_sent(gtid, 0); server.server_state().sst_sent(gtid, 0);
} }

View File

@ -141,6 +141,16 @@ namespace wsrep
wsrep::client_service& client_service, wsrep::client_service& client_service,
const wsrep::id& own_id) = 0; const wsrep::id& own_id) = 0;
/**
* Get the current replication position from the server
* storage.
*
* @param client_service Reference to client_service
*
* @return Current position GTID.
*/
virtual wsrep::gtid get_position(
wsrep::client_service& client_service) = 0;
/** /**
* Log a state change event. * Log a state change event.
* *

View File

@ -460,11 +460,9 @@ namespace wsrep
* and will wait until the initialization is complete. * and will wait until the initialization is complete.
* *
* @param client_service * @param client_service
* @param gtid GTID provided by the SST transfer
* @param error code of the SST operation * @param error code of the SST operation
*/ */
void sst_received(wsrep::client_service& cs, void sst_received(wsrep::client_service& cs, int error);
const wsrep::gtid& gtid, int error);
/** /**
* This method must be called after the server initialization * This method must be called after the server initialization

View File

@ -524,16 +524,16 @@ void wsrep::server_state::sst_sent(const wsrep::gtid& gtid, int error)
} }
void wsrep::server_state::sst_received(wsrep::client_service& cs, void wsrep::server_state::sst_received(wsrep::client_service& cs,
const wsrep::gtid& gtid,
int const error) int const error)
{ {
wsrep::log_info() << "SST received: " << gtid; wsrep::log_info() << "SST received";
wsrep::gtid gtid(wsrep::gtid::undefined());
wsrep::unique_lock<wsrep::mutex> lock(mutex_); wsrep::unique_lock<wsrep::mutex> lock(mutex_);
assert(state_ == s_joiner || state_ == s_initialized); assert(state_ == s_joiner || state_ == s_initialized);
// Run initialization only if the SST was successful. // Run initialization only if the SST was successful.
// In case of SST failure the system is in undefined state // In case of SST failure the system is in undefined state
// may not be recoverable. // may not be recoverable.
if (error == 0) if (error == 0)
{ {
if (server_service_.sst_before_init()) if (server_service_.sst_before_init())
@ -558,6 +558,8 @@ void wsrep::server_state::sst_received(wsrep::client_service& cs,
"wsrep::sst_received() called before connection to cluster"); "wsrep::sst_received() called before connection to cluster");
} }
gtid = server_service_.get_position(cs);
wsrep::log_info() << "Recovered position from storage: " << gtid;
wsrep::view const v(server_service_.get_view(cs, id_)); wsrep::view const v(server_service_.get_view(cs, id_));
wsrep::log_info() << "Recovered view from SST:\n" << v; wsrep::log_info() << "Recovered view from SST:\n" << v;

View File

@ -42,6 +42,7 @@ namespace wsrep
, last_client_id_(0) , last_client_id_(0)
, last_transaction_id_(0) , last_transaction_id_(0)
, logged_view_() , logged_view_()
, position_()
{ } { }
wsrep::storage_service* storage_service(wsrep::client_service&) wsrep::storage_service* storage_service(wsrep::client_service&)
@ -143,6 +144,10 @@ namespace wsrep
return my_view; return my_view;
} }
wsrep::gtid get_position(wsrep::client_service&) WSREP_OVERRIDE
{
return position_;
}
void log_state_change(enum wsrep::server_state::state, void log_state_change(enum wsrep::server_state::state,
enum wsrep::server_state::state) enum wsrep::server_state::state)
{ } { }
@ -198,11 +203,16 @@ namespace wsrep
{ {
logged_view_ = view; logged_view_ = view;
} }
void position(const wsrep::gtid& position)
{
position_ = position;
}
private: private:
wsrep::server_state& server_state_; wsrep::server_state& server_state_;
unsigned long long last_client_id_; unsigned long long last_client_id_;
unsigned long long last_transaction_id_; unsigned long long last_transaction_id_;
wsrep::view logged_view_; wsrep::view logged_view_;
wsrep::gtid position_;
}; };

View File

@ -338,7 +338,8 @@ BOOST_FIXTURE_TEST_CASE(server_state_sst_first_join_with_sst,
// Get_view() is called from sst_received(). This emulates the // Get_view() is called from sst_received(). This emulates the
// case where SST contains the view in which SST happens. // case where SST contains the view in which SST happens.
server_service.logged_view(second_view); server_service.logged_view(second_view);
ss.sst_received(cc, wsrep::gtid(cluster_id, wsrep::seqno(2)), 0); server_service.position(wsrep::gtid(cluster_id, wsrep::seqno(2)));
ss.sst_received(cc, 0);
clear_sync_point_action(); clear_sync_point_action();
BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joined); BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joined);
ss.on_sync(); ss.on_sync();
@ -423,8 +424,8 @@ BOOST_FIXTURE_TEST_CASE(
connect_in_view(second_view); connect_in_view(second_view);
ss.prepare_for_sst(); ss.prepare_for_sst();
BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joiner); BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joiner);
ss.sst_received(cc, wsrep::gtid(wsrep::id::undefined(), server_service.position(wsrep::gtid::undefined());
wsrep::seqno::undefined()), 1); ss.sst_received(cc, 1);
disconnect(); disconnect();
} }
@ -436,7 +437,8 @@ BOOST_FIXTURE_TEST_CASE(
ss.prepare_for_sst(); ss.prepare_for_sst();
BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joiner); BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joiner);
initialization_failure_action(); initialization_failure_action();
BOOST_REQUIRE_EXCEPTION(ss.sst_received(cc, second_view.state_id(), 0), server_service.position(wsrep::gtid(second_view.state_id()));
BOOST_REQUIRE_EXCEPTION(ss.sst_received(cc, 0),
wsrep::runtime_error, exception_check); wsrep::runtime_error, exception_check);
BOOST_REQUIRE(ss.state() == wsrep::server_state::s_initializing); BOOST_REQUIRE(ss.state() == wsrep::server_state::s_initializing);
BOOST_REQUIRE_EXCEPTION(ss.on_view(second_view, &hps), BOOST_REQUIRE_EXCEPTION(ss.on_view(second_view, &hps),
@ -459,7 +461,8 @@ BOOST_FIXTURE_TEST_CASE(
// Get_view() is called from sst_received(). This emulates the // Get_view() is called from sst_received(). This emulates the
// case where SST contains the view in which SST happens. // case where SST contains the view in which SST happens.
server_service.logged_view(second_view); server_service.logged_view(second_view);
ss.sst_received(cc, wsrep::gtid(cluster_id, wsrep::seqno(2)), 0); server_service.position(wsrep::gtid(cluster_id, wsrep::seqno(2)));
ss.sst_received(cc, 0);
clear_sync_point_action(); clear_sync_point_action();
BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joined); BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joined);
disconnect(); disconnect();
@ -499,7 +502,8 @@ BOOST_FIXTURE_TEST_CASE(server_state_init_first_join_with_sst,
prepare_for_sst(); prepare_for_sst();
BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joiner); BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joiner);
server_service.logged_view(second_view); server_service.logged_view(second_view);
ss.sst_received(cc, wsrep::gtid(cluster_id, wsrep::seqno(2)), 0); server_service.position(wsrep::gtid(cluster_id, wsrep::seqno(2)));
ss.sst_received(cc, 0);
BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joined); BOOST_REQUIRE(ss.state() == wsrep::server_state::s_joined);
ss.on_sync(); ss.on_sync();
BOOST_REQUIRE(ss.state() == wsrep::server_state::s_synced); BOOST_REQUIRE(ss.state() == wsrep::server_state::s_synced);