diff --git a/arangod/RocksDBEngine/RocksDBCollection.cpp b/arangod/RocksDBEngine/RocksDBCollection.cpp index fe32f176ff..d4ce9b6f0f 100644 --- a/arangod/RocksDBEngine/RocksDBCollection.cpp +++ b/arangod/RocksDBEngine/RocksDBCollection.cpp @@ -728,7 +728,7 @@ Result RocksDBCollection::truncate(transaction::Methods* trx, TRI_ASSERT(key.isString()); TRI_ASSERT(rid != 0); - RocksDBSavePoint guard(mthds, trx->isSingleOperationTransaction()); + RocksDBSavePoint guard(trx, TRI_VOC_DOCUMENT_OPERATION_REMOVE); state->prepareOperation(_logicalCollection.id(), rid, // actual revision ID!! @@ -896,10 +896,9 @@ Result RocksDBCollection::insert(arangodb::transaction::Methods* trx, } } - auto state = RocksDBTransactionState::toState(trx); - auto mthds = RocksDBTransactionState::toMethods(trx); - RocksDBSavePoint guard(mthds, trx->isSingleOperationTransaction()); + RocksDBSavePoint guard(trx, TRI_VOC_DOCUMENT_OPERATION_INSERT); + auto state = RocksDBTransactionState::toState(trx); state->prepareOperation( _logicalCollection.id(), revisionId, TRI_VOC_DOCUMENT_OPERATION_INSERT ); @@ -1010,8 +1009,7 @@ Result RocksDBCollection::update(arangodb::transaction::Methods* trx, VPackSlice const newDoc(builder->slice()); auto state = RocksDBTransactionState::toState(trx); - RocksDBSavePoint guard(RocksDBTransactionState::toMethods(trx), - trx->isSingleOperationTransaction()); + RocksDBSavePoint guard(trx, TRI_VOC_DOCUMENT_OPERATION_UPDATE); // add possible log statement under guard state->prepareOperation( @@ -1119,8 +1117,7 @@ Result RocksDBCollection::replace(transaction::Methods* trx, VPackSlice const newDoc(builder->slice()); auto state = RocksDBTransactionState::toState(trx); - RocksDBSavePoint guard(RocksDBTransactionState::toMethods(trx), - trx->isSingleOperationTransaction()); + RocksDBSavePoint guard(trx, TRI_VOC_DOCUMENT_OPERATION_REPLACE); // add possible log statement under guard state->prepareOperation( @@ -1202,8 +1199,7 @@ Result RocksDBCollection::remove(arangodb::transaction::Methods* trx, } auto state = RocksDBTransactionState::toState(trx); - RocksDBSavePoint guard(RocksDBTransactionState::toMethods(trx), - trx->isSingleOperationTransaction()); + RocksDBSavePoint guard(trx, TRI_VOC_DOCUMENT_OPERATION_REMOVE); // add possible log statement under guard state->prepareOperation( diff --git a/arangod/RocksDBEngine/RocksDBMethods.cpp b/arangod/RocksDBEngine/RocksDBMethods.cpp index 8128b91104..30eb8e273c 100644 --- a/arangod/RocksDBEngine/RocksDBMethods.cpp +++ b/arangod/RocksDBEngine/RocksDBMethods.cpp @@ -24,6 +24,7 @@ #include "Logger/Logger.h" #include "RocksDBEngine/RocksDBCommon.h" #include "RocksDBEngine/RocksDBTransactionState.h" +#include "Transaction/Methods.h" #include #include @@ -37,12 +38,15 @@ using namespace arangodb; // ================= RocksDBSavePoint ================== RocksDBSavePoint::RocksDBSavePoint( - RocksDBMethods* trx, bool handled) - : _trx(trx), _handled(handled) { + transaction::Methods* trx, TRI_voc_document_operation_e operationType) + : _trx(trx), + _operationType(operationType), + _handled(_trx->isSingleOperationTransaction()) { TRI_ASSERT(trx != nullptr); if (!_handled) { + auto mthds = RocksDBTransactionState::toMethods(_trx); // only create a savepoint when necessary - _trx->SetSavePoint(); + mthds->SetSavePoint(); } } @@ -71,7 +75,8 @@ void RocksDBSavePoint::finish(bool hasPerformedIntermediateCommit) { // leave the savepoint alone, because it belonged to another // transaction, and the current transaction will not have any // savepoint - _trx->PopSavePoint(); + auto mthds = RocksDBTransactionState::toMethods(_trx); + mthds->PopSavePoint(); } // this will prevent the rollback call in the destructor @@ -80,7 +85,12 @@ void RocksDBSavePoint::finish(bool hasPerformedIntermediateCommit) { void RocksDBSavePoint::rollback() { TRI_ASSERT(!_handled); - _trx->RollbackToSavePoint(); + auto mthds = RocksDBTransactionState::toMethods(_trx); + mthds->RollbackToSavePoint(); + + auto state = RocksDBTransactionState::toState(_trx); + state->rollbackOperation(_operationType); + _handled = true; // in order to not roll back again by accident } diff --git a/arangod/RocksDBEngine/RocksDBMethods.h b/arangod/RocksDBEngine/RocksDBMethods.h index 2dd1e92b31..76e6b80da6 100644 --- a/arangod/RocksDBEngine/RocksDBMethods.h +++ b/arangod/RocksDBEngine/RocksDBMethods.h @@ -38,6 +38,9 @@ struct ReadOptions; } // namespace rocksdb namespace arangodb { +namespace transaction { +class Methods; +} class RocksDBKey; class RocksDBMethods; @@ -45,7 +48,7 @@ class RocksDBTransactionState; class RocksDBSavePoint { public: - RocksDBSavePoint(RocksDBMethods* trx, bool handled); + RocksDBSavePoint(transaction::Methods* trx, TRI_voc_document_operation_e operationType); ~RocksDBSavePoint(); /// @brief acknowledges the current savepoint, so there @@ -58,7 +61,8 @@ class RocksDBSavePoint { void rollback(); private: - RocksDBMethods* _trx; + transaction::Methods* _trx; + TRI_voc_document_operation_e const _operationType; bool _handled; }; diff --git a/arangod/RocksDBEngine/RocksDBTransactionState.cpp b/arangod/RocksDBEngine/RocksDBTransactionState.cpp index b9b987f6a6..84ee4d3814 100644 --- a/arangod/RocksDBEngine/RocksDBTransactionState.cpp +++ b/arangod/RocksDBEngine/RocksDBTransactionState.cpp @@ -478,6 +478,32 @@ void RocksDBTransactionState::prepareOperation(TRI_voc_cid_t cid, TRI_voc_rid_t } } +/// @brief undo the effects of the previous prepareOperation call +void RocksDBTransactionState::rollbackOperation(TRI_voc_document_operation_e operationType) { + bool singleOp = hasHint(transaction::Hints::Hint::SINGLE_OPERATION); + if (singleOp) { + switch (operationType) { + case TRI_VOC_DOCUMENT_OPERATION_INSERT: + case TRI_VOC_DOCUMENT_OPERATION_UPDATE: + case TRI_VOC_DOCUMENT_OPERATION_REPLACE: + case TRI_VOC_DOCUMENT_OPERATION_REMOVE: +#ifdef ARANGODB_ENABLE_MAINTAINER_MODE + --_numLogdata; +#endif + break; + default: { + break; + } + } + } else { + if (operationType == TRI_VOC_DOCUMENT_OPERATION_REMOVE) { +#ifdef ARANGODB_ENABLE_MAINTAINER_MODE + --_numLogdata; +#endif + } + } +} + /// @brief add an operation for a transaction collection Result RocksDBTransactionState::addOperation( TRI_voc_cid_t cid, TRI_voc_rid_t revisionId, diff --git a/arangod/RocksDBEngine/RocksDBTransactionState.h b/arangod/RocksDBEngine/RocksDBTransactionState.h index 42b3d46bb9..d1cc0bbeb8 100644 --- a/arangod/RocksDBEngine/RocksDBTransactionState.h +++ b/arangod/RocksDBEngine/RocksDBTransactionState.h @@ -108,6 +108,9 @@ class RocksDBTransactionState final : public TransactionState { void prepareOperation(TRI_voc_cid_t cid, TRI_voc_rid_t rid, TRI_voc_document_operation_e operationType); + /// @brief undo the effects of the previous prepareOperation call + void rollbackOperation(TRI_voc_document_operation_e operationType); + /// @brief add an operation for a transaction collection /// sets hasPerformedIntermediateCommit to true if an intermediate commit was performed Result addOperation(TRI_voc_cid_t collectionId,