diff --git a/include/wsrep/client_state.hpp b/include/wsrep/client_state.hpp index 0406653..2199016 100644 --- a/include/wsrep/client_state.hpp +++ b/include/wsrep/client_state.hpp @@ -622,6 +622,10 @@ namespace wsrep return current_error_; } + enum wsrep::provider::status current_error_status() const + { + return current_error_status_; + } protected: /** * Client context constuctor. This is protected so that it @@ -651,6 +655,7 @@ namespace wsrep , last_written_gtid_() , debug_log_level_(0) , current_error_(wsrep::e_success) + , current_error_status_(wsrep::provider::success) { } private: @@ -666,7 +671,13 @@ namespace wsrep void debug_log_state(const char*) const; void state(wsrep::unique_lock& lock, enum state state); void mode(wsrep::unique_lock& lock, enum mode mode); - void override_error(enum wsrep::client_error error); + + // Override current client error status. Optionally provide + // an error status from the provider if the error was caused + // by the provider call. + void override_error(enum wsrep::client_error error, + enum wsrep::provider::status status = + wsrep::provider::success); wsrep::thread::id owning_thread_id_; wsrep::thread::id current_thread_id_; @@ -685,7 +696,8 @@ namespace wsrep wsrep::gtid sync_wait_gtid_; wsrep::gtid last_written_gtid_; int debug_log_level_; - wsrep::client_error current_error_; + enum wsrep::client_error current_error_; + enum wsrep::provider::status current_error_status_; }; static inline const char* to_c_string( diff --git a/include/wsrep/server_state.hpp b/include/wsrep/server_state.hpp index 0c3dc5a..f02ac80 100644 --- a/include/wsrep/server_state.hpp +++ b/include/wsrep/server_state.hpp @@ -428,6 +428,14 @@ namespace wsrep */ void initialized(); + /** + * Return true if the server has been initialized. + */ + bool is_initialized() const + { + wsrep::unique_lock lock(mutex_); + return init_initialized_; + } /** * */ diff --git a/src/client_state.cpp b/src/client_state.cpp index b185d59..be39039 100644 --- a/src/client_state.cpp +++ b/src/client_state.cpp @@ -48,7 +48,8 @@ void wsrep::client_state::cleanup() debug_log_state("cleanup: leave"); } -void wsrep::client_state::override_error(enum wsrep::client_error error) +void wsrep::client_state::override_error(enum wsrep::client_error error, + enum wsrep::provider::status status) { assert(wsrep::this_thread::get_id() == owning_thread_id_); if (current_error_ != wsrep::e_success && @@ -57,6 +58,7 @@ void wsrep::client_state::override_error(enum wsrep::client_error error) throw wsrep::runtime_error("Overriding error with success"); } current_error_ = error; + current_error_status_ = status; } @@ -254,7 +256,8 @@ int wsrep::client_state::enter_toi(const wsrep::key_array& keys, break; } default: - override_error(wsrep::e_error_during_commit); + override_error(wsrep::e_error_during_commit, + wsrep::provider::error_certification_failed); ret = 1; break; } @@ -283,7 +286,8 @@ int wsrep::client_state::leave_toi() break; default: assert(0); - override_error(wsrep::e_error_during_commit); + override_error(wsrep::e_error_during_commit, + wsrep::provider::error_unknown); ret = 1; break; } diff --git a/src/server_state.cpp b/src/server_state.cpp index 1a99ba1..665eb23 100644 --- a/src/server_state.cpp +++ b/src/server_state.cpp @@ -342,6 +342,7 @@ std::string wsrep::server_state::prepare_for_sst() { wsrep::unique_lock lock(mutex_); state(lock, s_joiner); + lock.unlock(); return server_service_.sst_request(); } @@ -517,6 +518,12 @@ void wsrep::server_state::on_view(const wsrep::view& view) state(lock, s_joiner); state(lock, s_initializing); } + else if (state_ == s_joiner) + { + // Got partiioned from the cluster, got IST and + // started applying actions. + state(lock, s_joined); + } } else { @@ -739,7 +746,7 @@ void wsrep::server_state::state( { 1, 0, 0, 1, 0, 1, 0, 0, 0}, /* ized */ { 1, 0, 0, 1, 1, 0, 0, 1, 0}, /* cted */ { 1, 1, 0, 0, 0, 1, 0, 0, 0}, /* jer */ - { 1, 0, 0, 0, 0, 0, 0, 1, 1}, /* jed */ + { 1, 0, 0, 1, 0, 0, 0, 1, 1}, /* jed */ { 1, 0, 0, 0, 0, 1, 0, 0, 1}, /* dor */ { 1, 0, 0, 1, 0, 1, 1, 0, 1}, /* sed */ { 1, 0, 0, 0, 0, 0, 0, 0, 0} /* ding */ diff --git a/src/transaction.cpp b/src/transaction.cpp index 15f7fe0..c8cd372 100644 --- a/src/transaction.cpp +++ b/src/transaction.cpp @@ -175,7 +175,9 @@ int wsrep::transaction::before_prepare( lock.unlock(); if (client_service_.statement_allowed_for_streaming() == false) { - client_state_.override_error(wsrep::e_error_during_commit); + client_state_.override_error( + wsrep::e_error_during_commit, + wsrep::provider::error_not_allowed); ret = 1; } else @@ -897,14 +899,14 @@ int wsrep::transaction::certify_commit( case wsrep::provider::error_warning: assert(ordered() == false); state(lock, s_must_abort); - client_state_.override_error(wsrep::e_error_during_commit); + client_state_.override_error(wsrep::e_error_during_commit, cert_ret); break; case wsrep::provider::error_transaction_missing: state(lock, s_must_abort); // The execution should never reach this point if the // transaction has not generated any keys or data. wsrep::log_warning() << "Transaction was missing in provider"; - client_state_.override_error(wsrep::e_error_during_commit); + client_state_.override_error(wsrep::e_error_during_commit, cert_ret); break; case wsrep::provider::error_bf_abort: // Transaction was replicated succesfully and it was either @@ -925,7 +927,7 @@ int wsrep::transaction::certify_commit( break; case wsrep::provider::error_size_exceeded: state(lock, s_must_abort); - client_state_.override_error(wsrep::e_error_during_commit); + client_state_.override_error(wsrep::e_error_during_commit, cert_ret); break; case wsrep::provider::error_connection_failed: // Galera provider may return CONN_FAIL if the trx is @@ -938,7 +940,8 @@ int wsrep::transaction::certify_commit( } else { - client_state_.override_error(wsrep::e_error_during_commit); + client_state_.override_error(wsrep::e_error_during_commit, + cert_ret); state(lock, s_must_abort); } break; @@ -947,16 +950,16 @@ int wsrep::transaction::certify_commit( { state(lock, s_must_abort); } - client_state_.override_error(wsrep::e_error_during_commit); + client_state_.override_error(wsrep::e_error_during_commit, cert_ret); break; case wsrep::provider::error_fatal: - client_state_.override_error(wsrep::e_error_during_commit); + client_state_.override_error(wsrep::e_error_during_commit, cert_ret); state(lock, s_must_abort); client_service_.emergency_shutdown(); break; case wsrep::provider::error_not_implemented: case wsrep::provider::error_not_allowed: - client_state_.override_error(wsrep::e_error_during_commit); + client_state_.override_error(wsrep::e_error_during_commit, cert_ret); state(lock, s_must_abort); wsrep::log_warning() << "Certification operation was not allowed: " << "id: " << id().get() @@ -964,7 +967,7 @@ int wsrep::transaction::certify_commit( break; default: state(lock, s_must_abort); - client_state_.override_error(wsrep::e_error_during_commit); + client_state_.override_error(wsrep::e_error_during_commit, cert_ret); break; } diff --git a/src/wsrep_provider_v26.cpp b/src/wsrep_provider_v26.cpp index e8e637d..366612e 100644 --- a/src/wsrep_provider_v26.cpp +++ b/src/wsrep_provider_v26.cpp @@ -337,9 +337,17 @@ namespace try { std::string req(server_state.prepare_for_sst()); - *sst_req = ::malloc(req.size() + 1); - memcpy(*sst_req, req.data(), req.size() + 1); - *sst_req_len = req.size() + 1; + if (req.size() > 0) + { + *sst_req = ::malloc(req.size() + 1); + memcpy(*sst_req, req.data(), req.size() + 1); + *sst_req_len = req.size() + 1; + } + else + { + *sst_req = 0; + *sst_req_len = 0; + } return WSREP_CB_SUCCESS; } catch (const wsrep::runtime_error& e)