#include "transaction/transaction_context.h"
#include "common/exception/transaction_manager.h"
#include "main/client_context.h"
#include "main/database.h"
#include "transaction/transaction_manager.h"
using namespace lbug::common;
namespace lbug {
namespace transaction {
TransactionContext::TransactionContext(main::ClientContext& clientContext)
: clientContext{clientContext}, mode{TransactionMode::AUTO}, activeTransaction{nullptr} {}
TransactionContext::~TransactionContext() = default;
void TransactionContext::beginReadTransaction() {
std::unique_lock lck{mtx};
mode = TransactionMode::MANUAL;
beginTransactionInternal(TransactionType::READ_ONLY);
}
void TransactionContext::beginWriteTransaction() {
std::unique_lock lck{mtx};
mode = TransactionMode::MANUAL;
beginTransactionInternal(TransactionType::WRITE);
}
void TransactionContext::beginAutoTransaction(bool readOnlyStatement) {
if (hasActiveTransaction()) {
throw TransactionManagerException(
"Cannot start a new transaction while there is an active transaction.");
}
beginTransactionInternal(
readOnlyStatement ? TransactionType::READ_ONLY : TransactionType::WRITE);
}
void TransactionContext::beginRecoveryTransaction() {
std::unique_lock lck{mtx};
mode = TransactionMode::MANUAL;
beginTransactionInternal(TransactionType::RECOVERY);
}
void TransactionContext::validateManualTransaction(bool readOnlyStatement) const {
DASSERT(hasActiveTransaction());
if (activeTransaction->isReadOnly() && !readOnlyStatement) {
throw TransactionManagerException(
"Can not execute a write query inside a read-only transaction.");
}
}
void TransactionContext::commit() {
if (!hasActiveTransaction()) {
return;
}
clientContext.getDatabase()->getTransactionManager()->commit(clientContext, activeTransaction);
clearTransaction();
}
void TransactionContext::rollback() {
if (!hasActiveTransaction()) {
return;
}
clientContext.getDatabase()->getTransactionManager()->rollback(clientContext,
activeTransaction);
clearTransaction();
}
void TransactionContext::clearTransaction() {
activeTransaction = nullptr;
mode = TransactionMode::AUTO;
}
TransactionContext* TransactionContext::Get(const main::ClientContext& context) {
return context.transactionContext.get();
}
void TransactionContext::beginTransactionInternal(TransactionType transactionType) {
DASSERT(!activeTransaction);
activeTransaction = clientContext.getDatabase()->getTransactionManager()->beginTransaction(
clientContext, transactionType);
}
} }