1
0
Fork 0
arangodb/arangod/Wal/DocumentOperation.h

155 lines
4.8 KiB
C++

#ifndef TRIAGENS_VOC_BASE_DOCUMENT_OPERATION_H
#define TRIAGENS_VOC_BASE_DOCUMENT_OPERATION_H 1
#include "Basics/Common.h"
#include "VocBase/document-collection.h"
#include "VocBase/headers.h"
#include "VocBase/voc-types.h"
#include "Wal/Marker.h"
struct TRI_transaction_collection_s;
namespace triagens {
namespace wal {
class Marker;
struct DocumentOperation {
enum class StatusType : uint8_t {
CREATED,
INDEXED,
HANDLED,
SWAPPED,
REVERTED
};
DocumentOperation (Marker* marker,
bool freeMarker,
struct TRI_transaction_collection_s* trxCollection,
TRI_voc_document_operation_e type,
TRI_voc_rid_t rid)
: marker(marker),
trxCollection(trxCollection),
header(nullptr),
rid(rid),
tick(0),
type(type),
status(StatusType::CREATED),
freeMarker(freeMarker) {
TRI_ASSERT(marker != nullptr);
}
~DocumentOperation () {
if (status == StatusType::HANDLED) {
if (type == TRI_VOC_DOCUMENT_OPERATION_REMOVE) {
TRI_document_collection_t* document = trxCollection->_collection->_collection;
document->_headersPtr->release(header, false); // PROTECTED by trx in trxCollection
}
}
else if (status != StatusType::REVERTED) {
revert();
}
if (marker != nullptr && freeMarker) {
delete marker;
}
}
DocumentOperation* swap () {
DocumentOperation* copy = new DocumentOperation(marker, freeMarker, trxCollection, type, rid);
copy->tick = tick;
copy->header = header;
copy->oldHeader = oldHeader;
copy->status = status;
type = TRI_VOC_DOCUMENT_OPERATION_UNKNOWN;
freeMarker = false;
marker = nullptr;
header = nullptr;
status = StatusType::SWAPPED;
return copy;
}
void init () {
if (type == TRI_VOC_DOCUMENT_OPERATION_UPDATE ||
type == TRI_VOC_DOCUMENT_OPERATION_REMOVE) {
// copy the old header into a safe area
TRI_ASSERT(header != nullptr);
oldHeader = *header;
}
}
void indexed () {
TRI_ASSERT(status == StatusType::CREATED);
status = StatusType::INDEXED;
}
void handle () {
TRI_ASSERT(header != nullptr);
TRI_ASSERT(status == StatusType::INDEXED);
TRI_document_collection_t* document = trxCollection->_collection->_collection;
if (type == TRI_VOC_DOCUMENT_OPERATION_UPDATE) {
// move header to the end of the list
document->_headersPtr->moveBack(header, &oldHeader); // PROTECTED by trx in trxCollection
}
// free the local marker buffer
marker->freeBuffer();
status = StatusType::HANDLED;
}
void revert () {
if (header == nullptr || status == StatusType::SWAPPED || status == StatusType::REVERTED) {
return;
}
TRI_document_collection_t* document = trxCollection->_collection->_collection;
if (status == StatusType::INDEXED || status == StatusType::HANDLED) {
TRI_RollbackOperationDocumentCollection(document, type, header, &oldHeader);
}
if (type == TRI_VOC_DOCUMENT_OPERATION_INSERT) {
document->_headersPtr->release(header, true); // PROTECTED by trx in trxCollection
}
else if (type == TRI_VOC_DOCUMENT_OPERATION_UPDATE) {
document->_headersPtr->move(header, &oldHeader); // PROTECTED by trx in trxCollection
header->copy(oldHeader);
}
else if (type == TRI_VOC_DOCUMENT_OPERATION_REMOVE) {
if (status != StatusType::CREATED) {
document->_headersPtr->relink(header, &oldHeader); // PROTECTED by trx in trxCollection
}
}
status = StatusType::REVERTED;
}
Marker* marker;
struct TRI_transaction_collection_s* trxCollection;
TRI_doc_mptr_t* header;
TRI_doc_mptr_copy_t oldHeader;
TRI_voc_rid_t const rid;
TRI_voc_tick_t tick;
TRI_voc_document_operation_e type;
StatusType status;
bool freeMarker;
};
}
}
#endif
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End: