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

Fix crash close_orphaned_sr_transactions() BF abort

Some implementations of provider `bf_abort()` require `victim_ctx`
to point to application side victim context. However, when
total order BF abort was done from `close_orphaned_sr_transactions()`,
the application side context was not available.

To fix this, added an interface method `call_in_operation_context()`
which allows invoking a function object with a reference to
application side operation context passed in as a parameter.
This method is used in `close_orphaned_sr_transactions()`
to call `client_state::total_order_bf_abort()` with appropriate
victim operation context.
This commit is contained in:
Teemu Ollakka
2023-09-16 10:11:49 +03:00
parent bd1a5c25a9
commit a7ce22ac91
4 changed files with 38 additions and 1 deletions

View File

@ -92,6 +92,14 @@ namespace db
return false; return false;
} }
void call_in_operation_context(
const std::function<void(wsrep::operation_context&)>& fn)
const override
{
wsrep::null_operation_context op;
fn(op);
}
void debug_sync(const char*) override { } void debug_sync(const char*) override { }
void debug_crash(const char*) override { } void debug_crash(const char*) override { }
private: private:

View File

@ -28,10 +28,13 @@
#define WSREP_CLIENT_SERVICE_HPP #define WSREP_CLIENT_SERVICE_HPP
#include "buffer.hpp" #include "buffer.hpp"
#include "operation_context.hpp"
#include "provider.hpp" #include "provider.hpp"
#include "mutex.hpp" #include "mutex.hpp"
#include "lock.hpp" #include "lock.hpp"
#include <functional>
namespace wsrep namespace wsrep
{ {
class client_service class client_service
@ -212,6 +215,15 @@ namespace wsrep
*/ */
virtual bool is_xa_rollback() = 0; virtual bool is_xa_rollback() = 0;
/**
* Perform a function call in operation context associated
* with the client service. The implementation must call @p fn
* with operation_context set appropriately.
*/
virtual void call_in_operation_context(
const std::function<void(wsrep::operation_context&)>& fn) const
= 0;
// //
// Debug interface // Debug interface
// //

View File

@ -1487,6 +1487,7 @@ void wsrep::server_state::close_orphaned_sr_transactions(
{ {
wsrep::client_id client_id(i->first); wsrep::client_id client_id(i->first);
wsrep::transaction_id transaction_id(i->second->transaction().id()); wsrep::transaction_id transaction_id(i->second->transaction().id());
auto& client_state = *i->second;
// It is safe to unlock the server state temporarily here. // It is safe to unlock the server state temporarily here.
// The processing happens inside view handler which is // The processing happens inside view handler which is
// protected by the provider commit ordering critical // protected by the provider commit ordering critical
@ -1497,7 +1498,15 @@ void wsrep::server_state::close_orphaned_sr_transactions(
// remains unlocked, so it should not be accessed after // remains unlocked, so it should not be accessed after
// the bf abort call. // the bf abort call.
lock.unlock(); lock.unlock();
i->second->total_order_bf_abort(current_view_.view_seqno()); client_state.client_service().call_in_operation_context(
[&client_state, this](wsrep::operation_context& op_ctx)
{
wsrep::unique_lock<wsrep::mutex> lock{
client_state.mutex()
};
client_state.total_order_bf_abort(
lock, current_view_.view_seqno(), op_ctx);
});
lock.lock(); lock.lock();
streaming_clients_map::const_iterator found_i; streaming_clients_map::const_iterator found_i;
while ((found_i = streaming_clients_.find(client_id)) != while ((found_i = streaming_clients_.find(client_id)) !=

View File

@ -186,6 +186,14 @@ namespace wsrep
return false; return false;
} }
void call_in_operation_context(
const std::function<void(wsrep::operation_context&)>& fn) const
WSREP_OVERRIDE
{
wsrep::null_operation_context op;
fn(op);
}
void debug_sync(const char* sync_point) WSREP_OVERRIDE void debug_sync(const char* sync_point) WSREP_OVERRIDE
{ {
if (sync_point_enabled_ == sync_point) if (sync_point_enabled_ == sync_point)