diff --git a/include/wsrep/client_state.hpp b/include/wsrep/client_state.hpp index a9d36c4..c18bdf5 100644 --- a/include/wsrep/client_state.hpp +++ b/include/wsrep/client_state.hpp @@ -270,6 +270,25 @@ namespace wsrep return transaction_.start_transaction(id); } + /** + * Establish read view ID of the transaction. + * + * This method should be preferably called immediately before any + * first read or write operation in the transaction is performed, + * Then it can be called with default NULL parameter and will use + * the current last committed GTID. + * Alternatively it can be called at any time before commit with an + * explicit GTID that corresponds to transaction read view. + * + * @param gtid optional explicit GTID of the transaction read view. + */ + int assign_read_view(const wsrep::gtid* const gtid = NULL) + { + assert(mode_ == m_local); + assert(state_ == s_exec); + return transaction_.assign_read_view(gtid); + } + /** * Append a key into transaction write set. */ diff --git a/include/wsrep/provider.hpp b/include/wsrep/provider.hpp index 2cac898..7e6a166 100644 --- a/include/wsrep/provider.hpp +++ b/include/wsrep/provider.hpp @@ -274,6 +274,8 @@ namespace wsrep // Write set replication // TODO: Rename to assing_read_view() virtual int start_transaction(wsrep::ws_handle&) = 0; + virtual enum status assign_read_view( + wsrep::ws_handle&, const wsrep::gtid*) = 0; virtual int append_key(wsrep::ws_handle&, const wsrep::key&) = 0; virtual enum status append_data( wsrep::ws_handle&, const wsrep::const_buffer&) = 0; diff --git a/include/wsrep/transaction.hpp b/include/wsrep/transaction.hpp index b8fadb9..f282ead 100644 --- a/include/wsrep/transaction.hpp +++ b/include/wsrep/transaction.hpp @@ -138,6 +138,8 @@ namespace wsrep const wsrep::ws_meta& ws_meta, bool is_commit); + int assign_read_view(const wsrep::gtid* gtid); + int append_key(const wsrep::key&); int append_data(const wsrep::const_buffer&); diff --git a/src/provider.cpp b/src/provider.cpp index 6bc855b..57c90ff 100644 --- a/src/provider.cpp +++ b/src/provider.cpp @@ -75,7 +75,7 @@ std::string wsrep::provider::capability::str(int caps) WSREP_PRINT_CAPABILITY(annotation, "ANNOTATION"); WSREP_PRINT_CAPABILITY(preordered, "PREORDERED"); WSREP_PRINT_CAPABILITY(streaming, "STREAMING"); - WSREP_PRINT_CAPABILITY(snapshot, "SNAPSHOT"); + WSREP_PRINT_CAPABILITY(snapshot, "READ_VIEW"); WSREP_PRINT_CAPABILITY(nbo, "NBO"); #undef WSREP_PRINT_CAPABILITY @@ -107,7 +107,7 @@ std::string wsrep::flags_to_string(int flags) if (flags & provider::flag::prepare) oss << "prepare | "; if (flags & provider::flag::snapshot) - oss << "snapshot | "; + oss << "read_view | "; if (flags & provider::flag::implicit_deps) oss << "implicit_deps | "; diff --git a/src/transaction.cpp b/src/transaction.cpp index ff4074f..1607ce6 100644 --- a/src/transaction.cpp +++ b/src/transaction.cpp @@ -208,6 +208,19 @@ int wsrep::transaction::prepare_for_ordering( return 0; } +int wsrep::transaction::assign_read_view(const wsrep::gtid* const gtid) +{ + try + { + return provider().assign_read_view(ws_handle_, gtid); + } + catch (...) + { + wsrep::log_error() << "Failed to assign read view"; + return 1; + } +} + int wsrep::transaction::append_key(const wsrep::key& key) { try diff --git a/src/wsrep_provider_v26.cpp b/src/wsrep_provider_v26.cpp index c49a5c6..3fee80e 100644 --- a/src/wsrep_provider_v26.cpp +++ b/src/wsrep_provider_v26.cpp @@ -690,6 +690,25 @@ wsrep::wsrep_provider_v26::run_applier( return map_return_value(wsrep_->recv(wsrep_, applier_ctx)); } +enum wsrep::provider::status +wsrep::wsrep_provider_v26::assign_read_view(wsrep::ws_handle& ws_handle, + const wsrep::gtid* gtid) +{ + const wsrep_gtid_t* gtid_ptr(NULL); + wsrep_gtid_t tmp; + + if (gtid) + { + ::memcpy(&tmp.uuid, gtid->id().data(), sizeof(tmp.uuid)); + tmp.seqno = gtid->seqno().get(); + gtid_ptr = &tmp; + } + + mutable_ws_handle mwsh(ws_handle); + return map_return_value(wsrep_->assign_read_view(wsrep_, mwsh.native(), + gtid_ptr)); +} + int wsrep::wsrep_provider_v26::append_key(wsrep::ws_handle& ws_handle, const wsrep::key& key) { @@ -714,7 +733,7 @@ int wsrep::wsrep_provider_v26::append_key(wsrep::ws_handle& ws_handle, enum wsrep::provider::status wsrep::wsrep_provider_v26::append_data(wsrep::ws_handle& ws_handle, - const wsrep::const_buffer& data) + const wsrep::const_buffer& data) { const wsrep_buf_t wsrep_buf = {data.data(), data.size()}; mutable_ws_handle mwsh(ws_handle); diff --git a/src/wsrep_provider_v26.hpp b/src/wsrep_provider_v26.hpp index 695cd40..12d6265 100644 --- a/src/wsrep_provider_v26.hpp +++ b/src/wsrep_provider_v26.hpp @@ -46,6 +46,8 @@ namespace wsrep enum wsrep::provider::status run_applier(wsrep::high_priority_service*); int start_transaction(wsrep::ws_handle&) { return 0; } + enum wsrep::provider::status + assign_read_view(wsrep::ws_handle&, const wsrep::gtid*); int append_key(wsrep::ws_handle&, const wsrep::key&); enum wsrep::provider::status append_data(wsrep::ws_handle&, const wsrep::const_buffer&); diff --git a/test/mock_provider.hpp b/test/mock_provider.hpp index 7a27671..e1d9489 100644 --- a/test/mock_provider.hpp +++ b/test/mock_provider.hpp @@ -143,6 +143,10 @@ namespace wsrep } } + enum wsrep::provider::status + assign_read_view(wsrep::ws_handle&, const wsrep::gtid*) + WSREP_OVERRIDE + { return wsrep::provider::success; } int append_key(wsrep::ws_handle&, const wsrep::key&) WSREP_OVERRIDE { return 0; } diff --git a/test/transaction_test.cpp b/test/transaction_test.cpp index 166ff99..c62ef4b 100644 --- a/test/transaction_test.cpp +++ b/test/transaction_test.cpp @@ -68,6 +68,9 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(transaction_1pc, T, BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1)); BOOST_REQUIRE(tc.state() == wsrep::transaction::s_executing); + // Establish default read view + BOOST_REQUIRE(0 == cc.assign_read_view(NULL)); + // Verify that the commit can be succesfully executed in separate command BOOST_REQUIRE(cc.after_statement() == 0); cc.after_command_before_result();