mirror of
https://github.com/codership/wsrep-lib.git
synced 2025-07-28 20:02:00 +03:00
Support for detaching prepared XA transactions
Add support for detaching XA transactions. This is useful for handling the case where the DBMS client has a transaction in prepared state and disconnects. Before disconnect, the DBMS calls the newly introduced client_state::xa_detach(), to cleanup the local transaction and convert it to a high priority transaction. The DBMS may later attempt to terminate the transaction through client_state::commit_by_xid() or client_state::rollback_by_xid(). Also in this patch: - Fix client_state::close() so that it does not rollback transactions in prepared state - Changed class wsrep::xid representation to hold enough information so that DBMS can convert to its native representation - Fix potential infinite loop in server_state::find_streaming_applier(wsrep:xid&) - Append SR keys on prepare fragment and make it pa_unsafe - Handle one phase commit (simply fall back to two phase) - Do not rollback prepared streaming clients in server_state::close_orphaned_transactions()
This commit is contained in:
@ -66,6 +66,10 @@ namespace wsrep
|
||||
: buffer_()
|
||||
{ }
|
||||
|
||||
mutable_buffer(const mutable_buffer& b)
|
||||
: buffer_(b.buffer_)
|
||||
{ }
|
||||
|
||||
void resize(size_t s) { buffer_.resize(s); }
|
||||
|
||||
void clear()
|
||||
@ -111,6 +115,11 @@ namespace wsrep
|
||||
buffer_ = other.buffer_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const mutable_buffer& other) const
|
||||
{
|
||||
return buffer_ == other.buffer_;
|
||||
}
|
||||
private:
|
||||
std::vector<char> buffer_;
|
||||
};
|
||||
|
@ -589,6 +589,21 @@ namespace wsrep
|
||||
return transaction_.commit_or_rollback_by_xid(xid, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach a prepared XA transaction
|
||||
*
|
||||
* This method cleans up a local XA transaction in prepared state
|
||||
* and converts it to high priority mode.
|
||||
* This can be used to handle the case where the client of a XA
|
||||
* transaction disconnects, and the transaction must not rollback.
|
||||
* After this call, a different client may later attempt to terminate
|
||||
* the transaction by calling method commit_by_xid() or rollback_by_xid().
|
||||
*/
|
||||
void xa_detach()
|
||||
{
|
||||
transaction_.xa_detach();
|
||||
}
|
||||
|
||||
//
|
||||
// BF aborting
|
||||
//
|
||||
|
@ -125,17 +125,17 @@ namespace wsrep
|
||||
|
||||
bool is_xa() const
|
||||
{
|
||||
return !xid_.empty();
|
||||
return !xid_.is_null();
|
||||
}
|
||||
|
||||
void assign_xid(const wsrep::xid& xid)
|
||||
{
|
||||
assert(active());
|
||||
assert(xid_.empty());
|
||||
assert(!is_xa());
|
||||
xid_ = xid;
|
||||
}
|
||||
|
||||
const wsrep::xid xid() const
|
||||
const wsrep::xid& xid() const
|
||||
{
|
||||
return xid_;
|
||||
}
|
||||
@ -144,6 +144,8 @@ namespace wsrep
|
||||
|
||||
int commit_or_rollback_by_xid(const wsrep::xid& xid, bool commit);
|
||||
|
||||
void xa_detach();
|
||||
|
||||
bool pa_unsafe() const { return pa_unsafe_; }
|
||||
void pa_unsafe(bool pa_unsafe) { pa_unsafe_ = pa_unsafe; }
|
||||
|
||||
|
@ -21,23 +21,80 @@
|
||||
#define WSREP_XID_HPP
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include "buffer.hpp"
|
||||
|
||||
namespace wsrep
|
||||
{
|
||||
class xid
|
||||
{
|
||||
public:
|
||||
xid() : xid_() { }
|
||||
xid(const std::string& str) : xid_(str) { }
|
||||
xid(const char* s) : xid_(s) { }
|
||||
bool empty() const { return xid_.empty(); }
|
||||
void clear() { xid_.clear(); }
|
||||
bool operator==(const xid& other) const { return xid_ == other.xid_; }
|
||||
xid()
|
||||
: format_id_(-1)
|
||||
, gtrid_len_(0)
|
||||
, bqual_len_(0)
|
||||
, data_()
|
||||
{ }
|
||||
|
||||
xid(long format_id, long gtrid_len,
|
||||
long bqual_len, const char* data)
|
||||
: format_id_(format_id)
|
||||
, gtrid_len_(gtrid_len)
|
||||
, bqual_len_(bqual_len)
|
||||
, data_()
|
||||
{
|
||||
const long len = gtrid_len_ + bqual_len_;
|
||||
if (len > 0)
|
||||
{
|
||||
data_.push_back(data, data + len);
|
||||
}
|
||||
}
|
||||
|
||||
xid(const xid& xid)
|
||||
: format_id_(xid.format_id_)
|
||||
, gtrid_len_(xid.gtrid_len_)
|
||||
, bqual_len_(xid.bqual_len_)
|
||||
, data_(xid.data_)
|
||||
{ }
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
return format_id_ == -1;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
format_id_ = -1;
|
||||
data_.clear();
|
||||
}
|
||||
|
||||
xid& operator= (const xid& other)
|
||||
{
|
||||
format_id_ = other.format_id_;
|
||||
gtrid_len_ = other.gtrid_len_;
|
||||
bqual_len_ = other.bqual_len_;
|
||||
data_ = other.data_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const xid& other) const
|
||||
{
|
||||
if (format_id_ != other.format_id_ ||
|
||||
gtrid_len_ != other.gtrid_len_ ||
|
||||
bqual_len_ != other.bqual_len_ ||
|
||||
data_.size() != other.data_.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return data_ == other.data_;
|
||||
}
|
||||
|
||||
friend std::string to_string(const wsrep::xid& xid);
|
||||
friend std::ostream& operator<<(std::ostream& os, const wsrep::xid& xid);
|
||||
private:
|
||||
std::string xid_;
|
||||
protected:
|
||||
long format_id_;
|
||||
long gtrid_len_;
|
||||
long bqual_len_;
|
||||
mutable_buffer data_;
|
||||
};
|
||||
|
||||
std::string to_string(const wsrep::xid& xid);
|
||||
|
Reference in New Issue
Block a user