1
0
Fork 0

Merge branch 'engine-api' of github.com:arangodb/arangodb into engine-api

This commit is contained in:
Michael Hackstein 2017-02-15 12:36:53 +01:00
commit cc999641a5
33 changed files with 262 additions and 563 deletions

View File

@ -97,6 +97,9 @@ MMFiles are known to the following files:
- OperationOptions
- revoryMarker
- re-enable RocksDB storage engine (e.g arangod.cpp)
- implement RocksDB storage engine
Questions
---------
* For GeoIndex `ignoreNull: true` and `constraint: false` are only set in Cluster mode. Is that art or can it go away?

View File

@ -24,6 +24,7 @@
#include "AgencyFeature.h"
#include "Agency/Agent.h"
#include "Cluster/ServerState.h"
#include "Logger/Logger.h"
#include "ProgramOptions/ProgramOptions.h"
#include "ProgramOptions/Section.h"

View File

@ -120,7 +120,7 @@ class AqlTransaction final : public transaction::Methods {
//////////////////////////////////////////////////////////////////////////////
transaction::Methods* clone() const override {
return new AqlTransaction(StandaloneTransactionContext::Create(_vocbase),
return new AqlTransaction(StandaloneTransactionContext::Create(vocbase()),
&_collections, false);
}

View File

@ -27,6 +27,7 @@
#include "Basics/Exceptions.h"
#include "Basics/ScopeGuard.h"
#include "Basics/VelocyPackHelper.h"
#include "StorageEngine/TransactionState.h"
#include "V8/v8-globals.h"
#include "VocBase/vocbase.h"
@ -161,8 +162,7 @@ void CalculationBlock::doEvaluation(AqlItemBlock* result) {
throw;
}
} else {
bool const isRunningInCluster =
arangodb::ServerState::instance()->isRunningInCluster();
bool const isRunningInCluster = transaction()->state()->isRunningInCluster();
// must have a V8 context here to protect Expression::execute()
arangodb::basics::ScopeGuard guard{

View File

@ -23,12 +23,6 @@
#include "ClusterBlocks.h"
#include <velocypack/Builder.h>
#include <velocypack/Collection.h>
#include <velocypack/Parser.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
#include "Aql/AqlItemBlock.h"
#include "Aql/AqlValue.h"
#include "Aql/BlockCollector.h"
@ -42,11 +36,18 @@
#include "Cluster/ClusterComm.h"
#include "Cluster/ClusterInfo.h"
#include "Cluster/ClusterMethods.h"
#include "Cluster/ServerState.h"
#include "Scheduler/JobGuard.h"
#include "Scheduler/SchedulerFeature.h"
#include "VocBase/ticks.h"
#include "VocBase/vocbase.h"
#include <velocypack/Builder.h>
#include <velocypack/Collection.h>
#include <velocypack/Parser.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
using namespace arangodb::aql;

View File

@ -60,7 +60,6 @@ namespace arangodb {
namespace transaction {
class Methods;
}
;
namespace aql {
class AqlItemBlock;

View File

@ -23,19 +23,20 @@
#include "ModificationBlocks.h"
#include <velocypack/Builder.h>
#include <velocypack/Collection.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
#include "Aql/AqlValue.h"
#include "Aql/Collection.h"
#include "Aql/ExecutionEngine.h"
#include "Basics/Exceptions.h"
#include "Cluster/ClusterMethods.h"
#include "StorageEngine/TransactionState.h"
#include "Utils/OperationOptions.h"
#include "VocBase/vocbase.h"
#include <velocypack/Builder.h>
#include <velocypack/Collection.h>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb::aql;
ModificationBlock::ModificationBlock(ExecutionEngine* engine,
@ -63,7 +64,7 @@ ModificationBlock::ModificationBlock(ExecutionEngine* engine,
}
// check if we're a DB server in a cluster
_isDBServer = arangodb::ServerState::instance()->isDBServer();
_isDBServer = transaction()->state()->isDBServer();
if (_isDBServer) {
_usesDefaultSharding = _collection->usesDefaultSharding();

View File

@ -28,6 +28,7 @@
#include "Aql/Collection.h"
#include "Aql/Condition.h"
#include "Aql/Graphs.h"
#include "Cluster/ServerState.h"
#include "Cluster/TraverserEngineRegistry.h"
#include "VocBase/LogicalCollection.h"
#include "VocBase/TraverserOptions.h"

View File

@ -1931,7 +1931,7 @@ int MMFilesCollection::update(arangodb::transaction::Methods* trx,
TRI_RidToString(revisionId), options.mergeObjects,
options.keepNull, *builder.get());
if (ServerState::isDBServer(trx->serverRole())) {
if (trx->state()->isDBServer()) {
// Need to check that no sharding keys have changed:
if (arangodb::shardKeysChanged(_logicalCollection->dbName(),
trx->resolver()->getCollectionNameCluster(
@ -2055,7 +2055,7 @@ int MMFilesCollection::replace(
isEdgeCollection, TRI_RidToString(revisionId),
*builder.get());
if (ServerState::isDBServer(trx->serverRole())) {
if (trx->state()->isDBServer()) {
// Need to check that no sharding keys have changed:
if (arangodb::shardKeysChanged(_logicalCollection->dbName(),
trx->resolver()->getCollectionNameCluster(

View File

@ -539,13 +539,13 @@ void MMFilesPrimaryIndex::handleValNode(transaction::Methods* trx,
TRI_ASSERT(cid != 0);
TRI_ASSERT(key != nullptr);
if (!trx->isCluster() && cid != _collection->cid()) {
if (!trx->state()->isRunningInCluster() && cid != _collection->cid()) {
// only continue lookup if the id value is syntactically correct and
// refers to "our" collection, using local collection id
return;
}
if (trx->isCluster() && cid != _collection->planId()) {
if (trx->state()->isRunningInCluster() && cid != _collection->planId()) {
// only continue lookup if the id value is syntactically correct and
// refers to "our" collection, using cluster collection id
return;

View File

@ -117,7 +117,7 @@ void MMFilesTransactionCollection::freeOperations(transaction::Methods* activeTr
return;
}
bool const isSingleOperationTransaction = _transaction->_hints.has(transaction::Hints::Hint::SINGLE_OPERATION);
bool const isSingleOperationTransaction = _transaction->hasHint(transaction::Hints::Hint::SINGLE_OPERATION);
if (mustRollback) {
// revert all operations
@ -153,8 +153,8 @@ void MMFilesTransactionCollection::freeOperations(transaction::Methods* activeTr
bool MMFilesTransactionCollection::canAccess(AccessMode::Type accessType) const {
if (_collection == nullptr) {
if (!_transaction->_hints.has(transaction::Hints::Hint::LOCK_NEVER) ||
!_transaction->_hints.has(transaction::Hints::Hint::NO_USAGE_LOCK)) {
if (!_transaction->hasHint(transaction::Hints::Hint::LOCK_NEVER) ||
!_transaction->hasHint(transaction::Hints::Hint::NO_USAGE_LOCK)) {
// not opened. probably a mistake made by the caller
return false;
}
@ -202,15 +202,15 @@ int MMFilesTransactionCollection::use(int nestingLevel) {
if (_collection == nullptr) {
// open the collection
if (!_transaction->_hints.has(transaction::Hints::Hint::LOCK_NEVER) &&
!_transaction->_hints.has(transaction::Hints::Hint::NO_USAGE_LOCK)) {
if (!_transaction->hasHint(transaction::Hints::Hint::LOCK_NEVER) &&
!_transaction->hasHint(transaction::Hints::Hint::NO_USAGE_LOCK)) {
// use and usage-lock
TRI_vocbase_col_status_e status;
LOG_TRX(_transaction, nestingLevel) << "using collection " << _cid;
_collection = _transaction->_vocbase->useCollection(_cid, status);
_collection = _transaction->vocbase()->useCollection(_cid, status);
} else {
// use without usage-lock (lock already set externally)
_collection = _transaction->_vocbase->lookupCollection(_cid);
_collection = _transaction->vocbase()->lookupCollection(_cid);
if (_collection == nullptr) {
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
@ -243,7 +243,7 @@ int MMFilesTransactionCollection::use(int nestingLevel) {
if (nestingLevel == 0 &&
AccessMode::isWriteOrExclusive(_accessType)) {
// read-lock the compaction lock
if (!_transaction->_hints.has(transaction::Hints::Hint::NO_COMPACTION_LOCK)) {
if (!_transaction->hasHint(transaction::Hints::Hint::NO_COMPACTION_LOCK)) {
if (!_compactionLocked) {
logicalToMMFiles(_collection)->preventCompaction();
_compactionLocked = true;
@ -256,10 +256,10 @@ int MMFilesTransactionCollection::use(int nestingLevel) {
_originalRevision = _collection->revision();
}
bool shouldLock = _transaction->_hints.has(transaction::Hints::Hint::LOCK_ENTIRELY);
bool shouldLock = _transaction->hasHint(transaction::Hints::Hint::LOCK_ENTIRELY);
if (!shouldLock) {
shouldLock = (AccessMode::isWriteOrExclusive(_accessType) && !_transaction->_hints.has(transaction::Hints::Hint::SINGLE_OPERATION));
shouldLock = (AccessMode::isWriteOrExclusive(_accessType) && !_transaction->hasHint(transaction::Hints::Hint::SINGLE_OPERATION));
}
if (shouldLock && !isLocked()) {
@ -283,7 +283,7 @@ void MMFilesTransactionCollection::unuse(int nestingLevel) {
// the top level transaction releases all collections
if (nestingLevel == 0 && _collection != nullptr) {
if (!_transaction->_hints.has(transaction::Hints::Hint::NO_COMPACTION_LOCK)) {
if (!_transaction->hasHint(transaction::Hints::Hint::NO_COMPACTION_LOCK)) {
if (AccessMode::isWriteOrExclusive(_accessType) && _compactionLocked) {
// read-unlock the compaction lock
logicalToMMFiles(_collection)->allowCompaction();
@ -301,14 +301,14 @@ void MMFilesTransactionCollection::release() {
// unuse collection, remove usage-lock
LOG_TRX(_transaction, 0) << "unusing collection " << _cid;
_transaction->_vocbase->releaseCollection(_collection);
_transaction->vocbase()->releaseCollection(_collection);
_collection = nullptr;
}
}
/// @brief lock a collection
int MMFilesTransactionCollection::doLock(AccessMode::Type type, int nestingLevel) {
if (_transaction->_hints.has(transaction::Hints::Hint::LOCK_NEVER)) {
if (_transaction->hasHint(transaction::Hints::Hint::LOCK_NEVER)) {
// never lock
return TRI_ERROR_NO_ERROR;
}
@ -334,13 +334,13 @@ int MMFilesTransactionCollection::doLock(AccessMode::Type type, int nestingLevel
auto physical = static_cast<MMFilesCollection*>(collection->getPhysical());
TRI_ASSERT(physical != nullptr);
double timeout = _transaction->_timeout;
if (_transaction->_hints.has(transaction::Hints::Hint::TRY_LOCK)) {
double timeout = _transaction->timeout();
if (_transaction->hasHint(transaction::Hints::Hint::TRY_LOCK)) {
// give up early if we cannot acquire the lock instantly
timeout = 0.00000001;
}
bool const useDeadlockDetector = !_transaction->_hints.has(transaction::Hints::Hint::SINGLE_OPERATION);
bool const useDeadlockDetector = !_transaction->hasHint(transaction::Hints::Hint::SINGLE_OPERATION);
int res;
if (!isWrite(type)) {
@ -360,7 +360,7 @@ int MMFilesTransactionCollection::doLock(AccessMode::Type type, int nestingLevel
/// @brief unlock a collection
int MMFilesTransactionCollection::doUnlock(AccessMode::Type type, int nestingLevel) {
if (_transaction->_hints.has(transaction::Hints::Hint::LOCK_NEVER)) {
if (_transaction->hasHint(transaction::Hints::Hint::LOCK_NEVER)) {
// never unlock
return TRI_ERROR_NO_ERROR;
}
@ -396,7 +396,7 @@ int MMFilesTransactionCollection::doUnlock(AccessMode::Type type, int nestingLev
return TRI_ERROR_INTERNAL;
}
bool const useDeadlockDetector = !_transaction->_hints.has(transaction::Hints::Hint::SINGLE_OPERATION);
bool const useDeadlockDetector = !_transaction->hasHint(transaction::Hints::Hint::SINGLE_OPERATION);
LogicalCollection* collection = _collection;
TRI_ASSERT(collection != nullptr);

View File

@ -53,6 +53,7 @@ static inline MMFilesLogfileManager* GetMMFilesLogfileManager() {
MMFilesTransactionState::MMFilesTransactionState(TRI_vocbase_t* vocbase)
: TransactionState(vocbase),
_rocksTransaction(nullptr),
_beginWritten(false),
_hasOperations(false) {}
/// @brief free a transaction container

View File

@ -106,6 +106,7 @@ class MMFilesTransactionState final : public TransactionState {
private:
rocksdb::Transaction* _rocksTransaction;
bool _beginWritten;
bool _hasOperations;
};

View File

@ -26,10 +26,10 @@
#include "Basics/Common.h"
#include "StorageEngine/TransactionState.h"
#include "Utils/DatabaseGuard.h"
#include "Utils/StandaloneTransactionContext.h"
#include "Transaction/Methods.h"
struct TRI_vocbase_t;
#include "VocBase/vocbase.h"
namespace arangodb {
@ -37,28 +37,20 @@ class ReplicationTransaction : public transaction::Methods {
public:
/// @brief create the transaction
ReplicationTransaction(TRI_vocbase_t* vocbase)
: transaction::Methods(StandaloneTransactionContext::Create(vocbase)) {
_vocbase->use();
}
/// @brief end the transaction
~ReplicationTransaction() { _vocbase->release(); }
: transaction::Methods(StandaloneTransactionContext::Create(vocbase)),
_guard(vocbase) {}
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief get a collection by id
/// this will automatically add the collection to the transaction
//////////////////////////////////////////////////////////////////////////////
inline TransactionCollection* trxCollection(TRI_voc_cid_t cid) {
TRI_ASSERT(cid > 0);
TransactionCollection* trxCollection = _state->collection(cid, AccessMode::Type::WRITE);
if (trxCollection == nullptr) {
int res = _state->addCollection(cid, AccessMode::Type::WRITE, 0, true, true);
int res = _state->addCollection(cid, AccessMode::Type::WRITE, 0, true);
if (res == TRI_ERROR_NO_ERROR) {
res = _state->ensureCollections();
@ -73,6 +65,9 @@ class ReplicationTransaction : public transaction::Methods {
return trxCollection;
}
private:
DatabaseGuard _guard;
};
}

View File

@ -75,11 +75,17 @@
#include "Ssl/SslServerFeature.h"
#include "Statistics/StatisticsFeature.h"
#include "StorageEngine/EngineSelectorFeature.h"
#include "MMFiles/MMFilesEngine.h"
#include "MMFiles/MMFilesLogfileManager.h"
// TODO - the following MMFiles includes should probably be removed
#include "MMFiles/MMFilesLogfileManager.h"
#include "MMFiles/MMFilesPersistentIndexFeature.h"
#include "MMFiles/MMFilesWalRecoveryFeature.h"
#include "StorageEngine/RocksDBEngine.h"
// #include "StorageEngine/RocksDBEngine.h" // enable when adding Rocksdb Engine
// this include will be disabled until
// we begin to implement the RocksDB
// engine
#include "MMFiles/MMFilesEngine.h"
#include "V8Server/FoxxQueuesFeature.h"
#include "V8Server/V8DealerFeature.h"
@ -185,7 +191,7 @@ static int runServer(int argc, char** argv) {
// storage engines
server.addFeature(new MMFilesEngine(&server));
server.addFeature(new MMFilesWalRecoveryFeature(&server));
//server.addFeature(new RocksDBEngine(&server));
//server.addFeature(new RocksDBEngine(&server)); //enable RocksDB storage here
try {
server.run(argc, argv);

View File

@ -33,13 +33,12 @@ class LogicalCollection;
namespace transaction {
class Methods;
}
;
class TransactionState;
/// @brief collection used in a transaction
class TransactionCollection {
public:
TransactionCollection(TransactionCollection const&) = delete;
TransactionCollection& operator=(TransactionCollection const&) = delete;

View File

@ -41,12 +41,12 @@ TransactionState::TransactionState(TRI_vocbase_t* vocbase)
_status(transaction::Status::CREATED),
_arena(),
_collections{_arena}, // assign arena to vector
_serverRole(ServerState::instance()->getRole()),
_hints(),
_timeout(transaction::Methods::DefaultLockTimeout),
_nestingLevel(0),
_allowImplicit(true),
_waitForSync(false),
_beginWritten(false),
_timeout(transaction::Methods::DefaultLockTimeout) {}
_allowImplicitCollections(true),
_waitForSync(false) {}
/// @brief free a transaction container
TransactionState::~TransactionState() {
@ -92,17 +92,14 @@ TransactionCollection* TransactionState::collection(TRI_voc_cid_t cid, AccessMod
/// @brief add a collection to a transaction
int TransactionState::addCollection(TRI_voc_cid_t cid,
AccessMode::Type accessType,
int nestingLevel, bool force,
bool allowImplicitCollections) {
int nestingLevel, bool force) {
LOG_TRX(this, nestingLevel) << "adding collection " << cid;
allowImplicitCollections &= _allowImplicit;
// LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "cid: " << cid
// << ", accessType: " << accessType
// << ", nestingLevel: " << nestingLevel
// << ", force: " << force
// << ", allowImplicitCollections: " << allowImplicitCollections;
// << ", allowImplicitCollections: " << _allowImplicitCollections;
// upgrade transaction type if required
if (nestingLevel == 0) {
@ -133,7 +130,7 @@ int TransactionState::addCollection(TRI_voc_cid_t cid,
return TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION;
}
if (!AccessMode::isWriteOrExclusive(accessType) && !allowImplicitCollections) {
if (!AccessMode::isWriteOrExclusive(accessType) && !_allowImplicitCollections) {
return TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION;
}

View File

@ -26,7 +26,7 @@
#include "Basics/Common.h"
#include "Basics/SmallVector.h"
#include "Transaction/Methods.h"
#include "Cluster/ServerState.h"
#include "Transaction/Hints.h"
#include "Transaction/Status.h"
#include "VocBase/AccessMode.h"
@ -35,11 +35,11 @@
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
#define LOG_TRX(trx, level) \
LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "trx #" << trx->_id << "." << level << " (" << transaction::statusString(trx->_status) << "): "
LOG_TOPIC(TRACE, arangodb::Logger::TRANSACTIONS) << "#" << trx->id() << "." << level << " (" << transaction::statusString(trx->status()) << "): "
#else
#define LOG_TRX(...) while (0) LOG_TOPIC(TRACE, arangodb::Logger::FIXME)
#define LOG_TRX(...) while (0) LOG_TOPIC(TRACE, arangodb::Logger::TRANSACTIONS)
#endif
@ -49,7 +49,6 @@ namespace arangodb {
namespace transaction {
class Methods;
}
;
class TransactionCollection;
/// @brief transaction type
@ -62,22 +61,40 @@ class TransactionState {
explicit TransactionState(TRI_vocbase_t* vocbase);
virtual ~TransactionState();
bool isRunningInCluster() const { return ServerState::isRunningInCluster(_serverRole); }
bool isDBServer() const { return ServerState::isDBServer(_serverRole); }
bool isCoordinator() const { return ServerState::isCoordinator(_serverRole); }
TRI_vocbase_t* vocbase() const { return _vocbase; }
TRI_voc_tid_t id() const { return _id; }
transaction::Status status() const { return _status; }
int increaseNesting() { return ++_nestingLevel; }
int decreaseNesting() {
TRI_ASSERT(_nestingLevel > 0);
return --_nestingLevel;
}
double timeout() const { return _timeout; }
void timeout(double value) {
if (value > 0.0) {
_timeout = value;
}
}
bool waitForSync() const { return _waitForSync; }
void waitForSync(bool value) { _waitForSync = value; }
bool allowImplicitCollections() const { return _allowImplicitCollections; }
void allowImplicitCollections(bool value) { _allowImplicitCollections = value; }
std::vector<std::string> collectionNames() const;
/// @brief return the collection from a transaction
TransactionCollection* collection(TRI_voc_cid_t cid, AccessMode::Type accessType);
/// @brief add a collection to a transaction
int addCollection(TRI_voc_cid_t cid, AccessMode::Type accessType, int nestingLevel, bool force, bool allowImplicitCollections);
int addCollection(TRI_voc_cid_t cid, AccessMode::Type accessType, int nestingLevel, bool force);
/// @brief make sure all declared collections are used & locked
int ensureCollections(int nestingLevel = 0);
@ -99,9 +116,10 @@ class TransactionState {
void updateStatus(transaction::Status status);
/// @brief whether or not a specific hint is set for the transaction
bool hasHint(transaction::Hints::Hint hint) const {
return _hints.has(hint);
}
bool hasHint(transaction::Hints::Hint hint) const { return _hints.has(hint); }
/// @brief set a hint for the transaction
void setHint(transaction::Hints::Hint hint) { _hints.set(hint); }
/// @brief begin a transaction
virtual int beginTransaction(transaction::Hints hints, int nestingLevel) = 0;
@ -112,7 +130,6 @@ class TransactionState {
/// @brief abort a transaction
virtual int abortTransaction(transaction::Methods* trx, int nestingLevel) = 0;
/// TODO: implement this in base class
virtual bool hasFailedOperations() const = 0;
protected:
@ -134,22 +151,22 @@ class TransactionState {
/// the transaction
void clearQueryCache();
public:
protected:
TRI_vocbase_t* _vocbase; // vocbase
TRI_voc_tid_t _id; // local trx id
AccessMode::Type _type; // access type (read|write)
transaction::Status _status; // current status
protected:
SmallVector<TransactionCollection*>::allocator_type::arena_type _arena; // memory for collections
SmallVector<TransactionCollection*> _collections; // list of participating collections
public:
transaction::Hints _hints; // hints;
ServerState::RoleEnum const _serverRole; // role of the server
transaction::Hints _hints; // hints;
double _timeout; // timeout for lock acquisition
int _nestingLevel;
bool _allowImplicit;
bool _allowImplicitCollections;
bool _waitForSync; // whether or not the transaction had a synchronous op
bool _beginWritten; // whether or not the begin marker was already written
double _timeout; // timeout for lock acquisition
};
}

View File

@ -68,6 +68,8 @@ using namespace arangodb;
using namespace arangodb::transaction;
using namespace arangodb::transaction::helpers;
namespace {
static void throwCollectionNotFound(char const* name) {
if (name == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
@ -75,23 +77,6 @@ static void throwCollectionNotFound(char const* name) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, std::string(TRI_errno_string(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND)) + ": " + name);
}
/// @brief Get the field names of the used index
std::vector<std::vector<std::string>> transaction::Methods::IndexHandle::fieldNames() const {
return _index->fieldNames();
}
/// @brief IndexHandle getter method
std::shared_ptr<arangodb::Index> transaction::Methods::IndexHandle::getIndex() const {
return _index;
}
/// @brief IndexHandle toVelocyPack method passthrough
void transaction::Methods::IndexHandle::toVelocyPack(
arangodb::velocypack::Builder& builder,
bool withFigures) const {
_index->toVelocyPack(builder, withFigures);
}
/// @brief tests if the given index supports the sort condition
static bool indexSupportsSort(Index const* idx, arangodb::aql::Variable const* reference,
arangodb::aql::SortCondition const* sortCondition,
@ -116,7 +101,7 @@ static bool indexSupportsSort(Index const* idx, arangodb::aql::Variable const* r
/// @brief Return an Operation Result that parses the error information returned
/// by the DBServer.
static OperationResult DBServerResponseBad(std::shared_ptr<VPackBuilder> resultBody) {
static OperationResult dbServerResponseBad(std::shared_ptr<VPackBuilder> resultBody) {
VPackSlice res = resultBody->slice();
return OperationResult(
arangodb::basics::VelocyPackHelper::getNumericValue<int>(
@ -146,7 +131,7 @@ static void createBabiesError(VPackBuilder& builder,
}
}
static OperationResult EmptyResult(bool waitForSync) {
static OperationResult emptyResult(bool waitForSync) {
VPackBuilder resultBuilder;
resultBuilder.openArray();
resultBuilder.close();
@ -154,22 +139,35 @@ static OperationResult EmptyResult(bool waitForSync) {
return OperationResult(resultBuilder.steal(), nullptr, "", TRI_ERROR_NO_ERROR,
waitForSync, errorCounter);
}
}
/// @brief Get the field names of the used index
std::vector<std::vector<std::string>> transaction::Methods::IndexHandle::fieldNames() const {
return _index->fieldNames();
}
/// @brief IndexHandle getter method
std::shared_ptr<arangodb::Index> transaction::Methods::IndexHandle::getIndex() const {
return _index;
}
/// @brief IndexHandle toVelocyPack method passthrough
void transaction::Methods::IndexHandle::toVelocyPack(
arangodb::velocypack::Builder& builder,
bool withFigures) const {
_index->toVelocyPack(builder, withFigures);
}
TRI_vocbase_t* transaction::Methods::vocbase() const { return _state->vocbase(); }
/// @brief add a transaction hint
void transaction::Methods::addHint(transaction::Hints::Hint hint, bool passthrough) {
_hints.set(hint);
if (passthrough && _state != nullptr) {
_state->_hints.set(hint);
}
}
/// @brief remove a transaction hint
void transaction::Methods::removeHint(transaction::Hints::Hint hint, bool passthrough) {
_hints.unset(hint);
if (passthrough && _state != nullptr) {
_state->_hints.unset(hint);
if (passthrough) {
_state->setHint(hint);
}
}
@ -180,21 +178,9 @@ bool transaction::Methods::isSingleOperationTransaction() const {
/// @brief get the status of the transaction
transaction::Status transaction::Methods::getStatus() const {
if (_state != nullptr) {
return _state->_status;
}
return transaction::Status::UNDEFINED;
return _state->status();
}
/// @brief set the allowImplicitCollections property
void transaction::Methods::setAllowImplicitCollections(bool value) {
_allowImplicitCollections = value;
if (_state != nullptr) {
_state->_allowImplicit = value;
}
}
/// @brief sort ORs for the same attribute so they are in ascending value
/// order. this will only work if the condition is for a single attribute
/// the usedIndexes vector may also be re-sorted
@ -564,35 +550,37 @@ thread_local std::unordered_set<std::string>* transaction::Methods::_makeNolockH
transaction::Methods::Methods(std::shared_ptr<TransactionContext> transactionContext)
: _serverRole(ServerState::ROLE_UNDEFINED),
_nestingLevel(0),
: _nestingLevel(0),
_hints(0),
_allowImplicitCollections(true),
_isReal(true),
_state(nullptr),
_vocbase(transactionContext->vocbase()),
_resolver(nullptr),
_transactionContext(transactionContext),
_transactionContextPtr(transactionContext.get()) {
TRI_ASSERT(_vocbase != nullptr);
TRI_ASSERT(_transactionContext != nullptr);
TRI_ASSERT(_transactionContextPtr != nullptr);
_serverRole = ServerState::instance()->getRole();
if (ServerState::isCoordinator(_serverRole)) {
_isReal = false;
TRI_vocbase_t* vocbase = _transactionContextPtr->vocbase();
// brief initialize the transaction
// this will first check if the transaction is embedded in a parent
// transaction. if not, it will create a transaction of its own
// check in the context if we are running embedded
TransactionState* parent = _transactionContextPtr->getParentTransaction();
if (parent != nullptr) {
// yes, we are embedded
setupEmbedded(vocbase);
} else {
// non-embedded
setupToplevel(vocbase);
}
setupTransaction();
TRI_ASSERT(_state != nullptr);
}
/// @brief destroy the transaction
transaction::Methods::~Methods() {
if (_state == nullptr) {
return;
}
if (isEmbeddedTransaction()) {
_state->_nestingLevel--;
_state->decreaseNesting();
} else {
if (getStatus() == transaction::Status::RUNNING) {
// auto abort a running transaction
@ -604,8 +592,14 @@ transaction::Methods::~Methods() {
}
}
// free the data associated with the transaction
freeTransaction();
// free the state associated with the transaction
TRI_ASSERT(getStatus() != transaction::Status::RUNNING);
// store result
_transactionContextPtr->storeTransactionResult(_state->id(), _state->hasFailedOperations());
_transactionContextPtr->unregisterTransaction();
delete _state;
_state = nullptr;
}
}
@ -710,7 +704,7 @@ void transaction::Methods::buildDocumentIdentity(LogicalCollection* collection,
std::string temp;
temp.reserve(64);
if (ServerState::isRunningInCluster(_serverRole)) {
if (_state->isRunningInCluster()) {
std::string resolved = resolver()->getCollectionNameCluster(cid);
#ifdef USE_ENTERPRISE
if (resolved.compare(0, 7, "_local_") == 0) {
@ -758,9 +752,9 @@ int transaction::Methods::begin() {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid transaction state");
}
if (!_isReal) {
if (_state->isCoordinator()) {
if (_nestingLevel == 0) {
_state->_status = transaction::Status::RUNNING;
_state->updateStatus(transaction::Status::RUNNING);
}
return TRI_ERROR_NO_ERROR;
}
@ -775,9 +769,9 @@ int transaction::Methods::commit() {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
if (!_isReal) {
if (_state->isCoordinator()) {
if (_nestingLevel == 0) {
_state->_status = transaction::Status::COMMITTED;
_state->updateStatus(transaction::Status::COMMITTED);
}
return TRI_ERROR_NO_ERROR;
}
@ -792,9 +786,9 @@ int transaction::Methods::abort() {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
if (!_isReal) {
if (_state->isCoordinator()) {
if (_nestingLevel == 0) {
_state->_status = transaction::Status::ABORTED;
_state->updateStatus(transaction::Status::ABORTED);
}
return TRI_ERROR_NO_ERROR;
@ -833,7 +827,7 @@ OperationResult transaction::Methods::any(std::string const& collectionName) {
/// as long as the collection is not modified.
OperationResult transaction::Methods::any(std::string const& collectionName,
uint64_t skip, uint64_t limit) {
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return anyCoordinator(collectionName, skip, limit);
}
return anyLocal(collectionName, skip, limit);
@ -901,7 +895,7 @@ TRI_voc_cid_t transaction::Methods::addCollectionAtRuntime(TRI_voc_cid_t cid,
auto collection = this->trxCollection(cid);
if (collection == nullptr) {
int res = _state->addCollection(cid, type, _nestingLevel, true, _allowImplicitCollections);
int res = _state->addCollection(cid, type, _nestingLevel, true);
if (res != TRI_ERROR_NO_ERROR) {
if (res == TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION) {
@ -958,7 +952,7 @@ bool transaction::Methods::isDocumentCollection(std::string const& collectionNam
/// @brief return the type of a collection
TRI_col_type_e transaction::Methods::getCollectionType(std::string const& collectionName) {
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return resolver()->getCollectionTypeCluster(collectionName);
}
return resolver()->getCollectionType(collectionName);
@ -973,7 +967,7 @@ std::string transaction::Methods::collectionName(TRI_voc_cid_t cid) {
void transaction::Methods::invokeOnAllElements(std::string const& collectionName,
std::function<bool(DocumentIdentifierToken const&)> callback) {
TRI_ASSERT(getStatus() == transaction::Status::RUNNING);
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
}
@ -1016,7 +1010,7 @@ int transaction::Methods::documentFastPath(std::string const& collectionName,
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
}
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
OperationOptions options; // use default configuration
options.ignoreRevs = true;
@ -1125,7 +1119,7 @@ OperationResult transaction::Methods::clusterResultInsert(
case rest::ResponseCode::PRECONDITION_FAILED:
return OperationResult(TRI_ERROR_ARANGO_CONFLICT);
case rest::ResponseCode::BAD:
return DBServerResponseBad(resultBody);
return dbServerResponseBad(resultBody);
case rest::ResponseCode::NOT_FOUND:
return OperationResult(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
case rest::ResponseCode::CONFLICT:
@ -1133,7 +1127,6 @@ OperationResult transaction::Methods::clusterResultInsert(
default:
return OperationResult(TRI_ERROR_INTERNAL);
}
}
/// @brief Create Cluster Communication result for modify
@ -1158,7 +1151,7 @@ OperationResult transaction::Methods::clusterResultModify(
responseCode == rest::ResponseCode::CREATED,
errorCounter);
case rest::ResponseCode::BAD:
return DBServerResponseBad(resultBody);
return dbServerResponseBad(resultBody);
case rest::ResponseCode::NOT_FOUND:
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND);
default:
@ -1182,7 +1175,7 @@ OperationResult transaction::Methods::clusterResultRemove(
: TRI_ERROR_NO_ERROR,
responseCode != rest::ResponseCode::ACCEPTED, errorCounter);
case rest::ResponseCode::BAD:
return DBServerResponseBad(resultBody);
return dbServerResponseBad(resultBody);
case rest::ResponseCode::NOT_FOUND:
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND);
default:
@ -1201,7 +1194,7 @@ OperationResult transaction::Methods::document(std::string const& collectionName
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
}
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return documentCoordinator(collectionName, value, options);
}
@ -1226,7 +1219,7 @@ OperationResult transaction::Methods::documentCoordinator(std::string const& col
}
int res = arangodb::getDocumentOnCoordinator(
_vocbase->name(), collectionName, value, options, headers, responseCode, errorCounter, resultBody);
databaseName(), collectionName, value, options, headers, responseCode, errorCounter, resultBody);
if (res == TRI_ERROR_NO_ERROR) {
return clusterResultDocument(responseCode, resultBody, errorCounter);
@ -1338,13 +1331,13 @@ OperationResult transaction::Methods::insert(std::string const& collectionName,
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
}
if (value.isArray() && value.length() == 0) {
return EmptyResult(options.waitForSync);
return emptyResult(options.waitForSync);
}
// Validate Edges
OperationOptions optionsCopy = options;
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return insertCoordinator(collectionName, value, optionsCopy);
}
@ -1365,7 +1358,7 @@ OperationResult transaction::Methods::insertCoordinator(std::string const& colle
auto resultBody = std::make_shared<VPackBuilder>();
int res = arangodb::createDocumentOnCoordinator(
_vocbase->name(), collectionName, options, value, responseCode,
databaseName(), collectionName, options, value, responseCode,
errorCounter, resultBody);
if (res == TRI_ERROR_NO_ERROR) {
@ -1476,7 +1469,7 @@ OperationResult transaction::Methods::insertLocal(std::string const& collectionN
// Now see whether or not we have to do synchronous replication:
std::shared_ptr<std::vector<ServerID> const> followers;
bool doingSynchronousReplication = false;
if (ServerState::isDBServer(_serverRole)) {
if (_state->isDBServer()) {
// Now replicate the same operation on all followers:
auto const& followerInfo = collection->followers();
followers = followerInfo->get();
@ -1491,7 +1484,7 @@ OperationResult transaction::Methods::insertLocal(std::string const& collectionN
// Now replicate the good operations on all followers:
std::string path
= "/_db/" +
arangodb::basics::StringUtils::urlEncode(_vocbase->name()) +
arangodb::basics::StringUtils::urlEncode(databaseName()) +
"/_api/document/" +
arangodb::basics::StringUtils::urlEncode(collection->name())
+ "?isRestore=true";
@ -1595,12 +1588,12 @@ OperationResult transaction::Methods::update(std::string const& collectionName,
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
}
if (newValue.isArray() && newValue.length() == 0) {
return EmptyResult(options.waitForSync);
return emptyResult(options.waitForSync);
}
OperationOptions optionsCopy = options;
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return updateCoordinator(collectionName, newValue, optionsCopy);
}
@ -1622,7 +1615,7 @@ OperationResult transaction::Methods::updateCoordinator(std::string const& colle
auto resultBody = std::make_shared<VPackBuilder>();
int res = arangodb::modifyDocumentOnCoordinator(
_vocbase->name(), collectionName, newValue, options,
databaseName(), collectionName, newValue, options,
true /* isPatch */, headers, responseCode, errorCounter,
resultBody);
@ -1646,12 +1639,12 @@ OperationResult transaction::Methods::replace(std::string const& collectionName,
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
}
if (newValue.isArray() && newValue.length() == 0) {
return EmptyResult(options.waitForSync);
return emptyResult(options.waitForSync);
}
OperationOptions optionsCopy = options;
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return replaceCoordinator(collectionName, newValue, optionsCopy);
}
@ -1672,7 +1665,7 @@ OperationResult transaction::Methods::replaceCoordinator(std::string const& coll
auto resultBody = std::make_shared<VPackBuilder>();
int res = arangodb::modifyDocumentOnCoordinator(
_vocbase->name(), collectionName, newValue, options,
databaseName(), collectionName, newValue, options,
false /* isPatch */, headers, responseCode, errorCounter,
resultBody);
@ -1785,7 +1778,7 @@ OperationResult transaction::Methods::modifyLocal(
// Now see whether or not we have to do synchronous replication:
std::shared_ptr<std::vector<ServerID> const> followers;
bool doingSynchronousReplication = false;
if (ServerState::isDBServer(_serverRole)) {
if (_state->isDBServer()) {
// Now replicate the same operation on all followers:
auto const& followerInfo = collection->followers();
followers = followerInfo->get();
@ -1803,7 +1796,7 @@ OperationResult transaction::Methods::modifyLocal(
// nullptr only happens on controlled shutdown
std::string path
= "/_db/" +
arangodb::basics::StringUtils::urlEncode(_vocbase->name()) +
arangodb::basics::StringUtils::urlEncode(databaseName()) +
"/_api/document/" +
arangodb::basics::StringUtils::urlEncode(collection->name())
+ "?isRestore=true";
@ -1905,12 +1898,12 @@ OperationResult transaction::Methods::remove(std::string const& collectionName,
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
}
if (value.isArray() && value.length() == 0) {
return EmptyResult(options.waitForSync);
return emptyResult(options.waitForSync);
}
OperationOptions optionsCopy = options;
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return removeCoordinator(collectionName, value, optionsCopy);
}
@ -1930,7 +1923,7 @@ OperationResult transaction::Methods::removeCoordinator(std::string const& colle
auto resultBody = std::make_shared<VPackBuilder>();
int res = arangodb::deleteDocumentOnCoordinator(
_vocbase->name(), collectionName, value, options, responseCode,
databaseName(), collectionName, value, options, responseCode,
errorCounter, resultBody);
if (res == TRI_ERROR_NO_ERROR) {
@ -2029,7 +2022,7 @@ OperationResult transaction::Methods::removeLocal(std::string const& collectionN
// Now see whether or not we have to do synchronous replication:
std::shared_ptr<std::vector<ServerID> const> followers;
bool doingSynchronousReplication = false;
if (ServerState::isDBServer(_serverRole)) {
if (_state->isDBServer()) {
// Now replicate the same operation on all followers:
auto const& followerInfo = collection->followers();
followers = followerInfo->get();
@ -2048,7 +2041,7 @@ OperationResult transaction::Methods::removeLocal(std::string const& collectionN
std::string path
= "/_db/" +
arangodb::basics::StringUtils::urlEncode(_vocbase->name()) +
arangodb::basics::StringUtils::urlEncode(databaseName()) +
"/_api/document/" +
arangodb::basics::StringUtils::urlEncode(collection->name())
+ "?isRestore=true";
@ -2143,7 +2136,7 @@ OperationResult transaction::Methods::all(std::string const& collectionName,
OperationOptions optionsCopy = options;
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return allCoordinator(collectionName, skip, limit, optionsCopy);
}
@ -2216,7 +2209,7 @@ OperationResult transaction::Methods::truncate(std::string const& collectionName
OperationOptions optionsCopy = options;
OperationResult result;
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
result = truncateCoordinator(collectionName, optionsCopy);
} else {
result = truncateLocal(collectionName, optionsCopy);
@ -2231,7 +2224,7 @@ OperationResult transaction::Methods::truncate(std::string const& collectionName
OperationResult transaction::Methods::truncateCoordinator(std::string const& collectionName,
OperationOptions& options) {
return OperationResult(
arangodb::truncateCollectionOnCoordinator(_vocbase->name(),
arangodb::truncateCollectionOnCoordinator(databaseName(),
collectionName));
}
#endif
@ -2260,7 +2253,7 @@ OperationResult transaction::Methods::truncateLocal(std::string const& collectio
}
// Now see whether or not we have to do synchronous replication:
if (ServerState::isDBServer(_serverRole)) {
if (_state->isDBServer()) {
std::shared_ptr<std::vector<ServerID> const> followers;
// Now replicate the same operation on all followers:
auto const& followerInfo = collection->followers();
@ -2273,8 +2266,8 @@ OperationResult transaction::Methods::truncateLocal(std::string const& collectio
// nullptr only happens on controlled shutdown
std::string path
= "/_db/" +
arangodb::basics::StringUtils::urlEncode(_vocbase->name()) +
"/_api/collection/" + collectionName + "/truncate";
arangodb::basics::StringUtils::urlEncode(databaseName()) +
"/_api/collection/" + arangodb::basics::StringUtils::urlEncode(collectionName) + "/truncate";
auto body = std::make_shared<std::string>();
@ -2320,7 +2313,7 @@ OperationResult transaction::Methods::truncateLocal(std::string const& collectio
OperationResult transaction::Methods::count(std::string const& collectionName, bool aggregate) {
TRI_ASSERT(getStatus() == transaction::Status::RUNNING);
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return countCoordinator(collectionName, aggregate);
}
@ -2332,7 +2325,7 @@ OperationResult transaction::Methods::count(std::string const& collectionName, b
OperationResult transaction::Methods::countCoordinator(std::string const& collectionName,
bool aggregate) {
std::vector<std::pair<std::string, uint64_t>> count;
int res = arangodb::countOnCoordinator(_vocbase->name(), collectionName, count);
int res = arangodb::countOnCoordinator(databaseName(), collectionName, count);
if (res != TRI_ERROR_NO_ERROR) {
return OperationResult(res);
@ -2552,7 +2545,7 @@ OperationCursor* transaction::Methods::indexScanForCondition(
arangodb::aql::AstNode const* condition, arangodb::aql::Variable const* var,
ManagedDocumentResult* mmdr,
uint64_t limit, uint64_t batchSize, bool reverse) {
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
// The index scan is only available on DBServers and Single Server.
THROW_ARANGO_EXCEPTION(TRI_ERROR_CLUSTER_ONLY_ON_DBSERVER);
}
@ -2588,7 +2581,7 @@ std::unique_ptr<OperationCursor> transaction::Methods::indexScan(
uint64_t skip, uint64_t limit, uint64_t batchSize, bool reverse) {
// For now we assume indexId is the iid part of the index.
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
// The index scan is only available on DBServers and Single Server.
THROW_ARANGO_EXCEPTION(TRI_ERROR_CLUSTER_ONLY_ON_DBSERVER);
}
@ -2753,7 +2746,7 @@ int transaction::Methods::unlock(TransactionCollection* trxCollection,
std::vector<std::shared_ptr<Index>> transaction::Methods::indexesForCollection(
std::string const& collectionName) {
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
return indexesForCollectionCoordinator(collectionName);
}
// For a DBserver we use the local case.
@ -2780,7 +2773,7 @@ transaction::Methods* transaction::Methods::clone() const {
std::shared_ptr<Index> transaction::Methods::indexForCollectionCoordinator(
std::string const& name, std::string const& id) const {
auto clusterInfo = arangodb::ClusterInfo::instance();
auto collectionInfo = clusterInfo->getCollection(_vocbase->name(), name);
auto collectionInfo = clusterInfo->getCollection(databaseName(), name);
auto idxs = collectionInfo->getIndexes();
TRI_idx_iid_t iid = basics::StringUtils::uint64(id);
@ -2796,7 +2789,7 @@ std::shared_ptr<Index> transaction::Methods::indexForCollectionCoordinator(
std::vector<std::shared_ptr<Index>>
transaction::Methods::indexesForCollectionCoordinator(std::string const& name) const {
auto clusterInfo = arangodb::ClusterInfo::instance();
auto collectionInfo = clusterInfo->getCollection(_vocbase->name(), name);
auto collectionInfo = clusterInfo->getCollection(databaseName(), name);
return collectionInfo->getIndexes();
}
@ -2805,7 +2798,7 @@ transaction::Methods::indexesForCollectionCoordinator(std::string const& name) c
transaction::Methods::IndexHandle transaction::Methods::getIndexByIdentifier(
std::string const& collectionName, std::string const& indexHandle) {
if (ServerState::isCoordinator(_serverRole)) {
if (_state->isCoordinator()) {
if (indexHandle.empty()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
"The index id cannot be empty.");
@ -2858,7 +2851,7 @@ transaction::Methods::IndexHandle transaction::Methods::getIndexByIdentifier(
int transaction::Methods::addCollectionEmbedded(TRI_voc_cid_t cid, char const* name, AccessMode::Type type) {
TRI_ASSERT(_state != nullptr);
int res = _state->addCollection(cid, type, _nestingLevel, false, _allowImplicitCollections);
int res = _state->addCollection(cid, type, _nestingLevel, false);
if (res != TRI_ERROR_NO_ERROR) {
if (res == TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION) {
@ -2883,7 +2876,7 @@ int transaction::Methods::addCollectionToplevel(TRI_voc_cid_t cid, char const* n
// transaction already started?
res = TRI_ERROR_TRANSACTION_INTERNAL;
} else {
res = _state->addCollection(cid, type, _nestingLevel, false, _allowImplicitCollections);
res = _state->addCollection(cid, type, _nestingLevel, false);
}
if (res != TRI_ERROR_NO_ERROR) {
@ -2898,71 +2891,34 @@ int transaction::Methods::addCollectionToplevel(TRI_voc_cid_t cid, char const* n
return res;
}
/// @brief initialize the transaction
/// this will first check if the transaction is embedded in a parent
/// transaction. if not, it will create a transaction of its own
void transaction::Methods::setupTransaction() {
// check in the context if we are running embedded
_state = _transactionContext->getParentTransaction();
if (_state != nullptr) {
// yes, we are embedded
setupEmbedded();
_allowImplicitCollections = _state->_allowImplicit;
} else {
// non-embedded
setupToplevel();
}
}
/// @brief set up an embedded transaction
void transaction::Methods::setupEmbedded() {
TRI_ASSERT(_nestingLevel == 0);
_nestingLevel = ++_state->_nestingLevel;
if (!_transactionContext->isEmbeddable()) {
void transaction::Methods::setupEmbedded(TRI_vocbase_t*) {
if (!_transactionContextPtr->isEmbeddable()) {
// we are embedded but this is disallowed...
THROW_ARANGO_EXCEPTION(TRI_ERROR_TRANSACTION_NESTED);
}
TRI_ASSERT(_nestingLevel == 0);
_state = _transactionContextPtr->getParentTransaction();
TRI_ASSERT(_state != nullptr);
_nestingLevel = _state->increaseNesting();
}
/// @brief set up a top-level transaction
void transaction::Methods::setupToplevel() {
void transaction::Methods::setupToplevel(TRI_vocbase_t* vocbase) {
TRI_ASSERT(_nestingLevel == 0);
// we are not embedded. now start our own transaction
StorageEngine* engine = EngineSelectorFeature::ENGINE;
_state = engine->createTransactionState(_vocbase);
_state = engine->createTransactionState(vocbase);
if (_state == nullptr) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to set up transaction state");
}
TRI_ASSERT(_state != nullptr);
// register the transaction in the context
_transactionContext->registerTransaction(_state);
}
/// @brief free transaction
void transaction::Methods::freeTransaction() {
TRI_ASSERT(!isEmbeddedTransaction());
if (_state != nullptr) {
TRI_ASSERT(getStatus() != transaction::Status::RUNNING);
auto id = _state->_id;
bool hasFailedOperations = _state->hasFailedOperations();
delete _state;
_state = nullptr;
// store result
_transactionContext->storeTransactionResult(id, hasFailedOperations);
_transactionContext->unregisterTransaction();
}
}
bool transaction::Methods::isCluster() {
return arangodb::ServerState::instance()->isRunningInCluster(_serverRole);
_transactionContextPtr->registerTransaction(_state);
}
int transaction::Methods::resolveId(char const* handle, size_t length,

View File

@ -27,7 +27,6 @@
#include "Basics/Common.h"
#include "Basics/Exceptions.h"
#include "Basics/StringRef.h"
#include "Cluster/ServerState.h"
#include "Utils/OperationResult.h"
#include "Transaction/Hints.h"
#include "Transaction/Status.h"
@ -140,16 +139,12 @@ class Methods {
};
/// @brief return database of transaction
inline TRI_vocbase_t* vocbase() const { return _vocbase; }
TRI_vocbase_t* vocbase() const;
inline std::string const& databaseName() const { return vocbase()->name(); }
/// @brief return internals of transaction
inline TransactionState* state() const { return _state; }
/// @brief return role of server in cluster
inline ServerState::RoleEnum serverRole() const { return _serverRole; }
bool isCluster();
int resolveId(char const* handle, size_t length, TRI_voc_cid_t& cid, char const*& key, size_t& outLength);
/// @brief return a pointer to the transaction context
@ -164,9 +159,6 @@ class Methods {
/// @brief add a transaction hint
void addHint(transaction::Hints::Hint hint, bool passthrough);
/// @brief remove a transaction hint
void removeHint(transaction::Hints::Hint hint, bool passthrough);
/// @brief return the collection name resolver
CollectionNameResolver const* resolver();
@ -476,9 +468,6 @@ class Methods {
/// @brief add a collection by name
int addCollection(std::string const&, AccessMode::Type);
/// @brief set the allowImplicitCollections property
void setAllowImplicitCollections(bool value);
/// @brief read- or write-lock a collection
int lock(TransactionCollection*, AccessMode::Type);
@ -550,43 +539,23 @@ class Methods {
/// @brief add a collection to a top-level transaction
int addCollectionToplevel(TRI_voc_cid_t, char const* name, AccessMode::Type);
/// @brief initialize the transaction
/// this will first check if the transaction is embedded in a parent
/// transaction. if not, it will create a transaction of its own
void setupTransaction();
/// @brief set up an embedded transaction
void setupEmbedded();
void setupEmbedded(TRI_vocbase_t*);
/// @brief set up a top-level transaction
void setupToplevel();
/// @brief free transaction
void freeTransaction();
void setupToplevel(TRI_vocbase_t*);
private:
/// @brief role of server in cluster
ServerState::RoleEnum _serverRole;
/// @brief how deep the transaction is down in a nested transaction structure
int _nestingLevel;
/// @brief transaction hints
transaction::Hints _hints;
/// @brief allow implicit collections for transaction
bool _allowImplicitCollections;
/// @brief whether or not this is a "real" transaction
bool _isReal;
protected:
/// @brief the state
TransactionState* _state;
/// @brief the vocbase
TRI_vocbase_t* const _vocbase;
/// @brief collection name resolver (cached)
CollectionNameResolver const* _resolver;

View File

@ -28,8 +28,7 @@
#include "Basics/Exceptions.h"
#include "RestServer/DatabaseFeature.h"
#include "RestServer/FeatureCacheFeature.h"
struct TRI_vocbase_t;
#include "VocBase/vocbase.h"
namespace arangodb {
@ -37,11 +36,14 @@ class DatabaseGuard {
public:
DatabaseGuard(DatabaseGuard const&) = delete;
DatabaseGuard& operator=(DatabaseGuard const&) = delete;
explicit DatabaseGuard(TRI_vocbase_t* vocbase)
: _vocbase(vocbase) {
TRI_ASSERT(vocbase != nullptr);
_vocbase->use();
}
//////////////////////////////////////////////////////////////////////////////
/// @brief create the guard, using a database id
//////////////////////////////////////////////////////////////////////////////
explicit DatabaseGuard(TRI_voc_tick_t id)
: _vocbase(nullptr) {
@ -53,10 +55,7 @@ class DatabaseGuard {
}
}
//////////////////////////////////////////////////////////////////////////////
/// @brief create the guard, using a database name
//////////////////////////////////////////////////////////////////////////////
explicit DatabaseGuard(std::string const& name)
: _vocbase(nullptr) {
@ -68,28 +67,19 @@ class DatabaseGuard {
}
}
//////////////////////////////////////////////////////////////////////////////
/// @brief destroy the guard
//////////////////////////////////////////////////////////////////////////////
~DatabaseGuard() {
TRI_ASSERT(_vocbase != nullptr);
_vocbase->release();
}
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief return the database pointer
//////////////////////////////////////////////////////////////////////////////
inline TRI_vocbase_t* database() const { return _vocbase; }
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief pointer to database
//////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* _vocbase;
};
}

View File

@ -27,18 +27,12 @@
using namespace arangodb;
////////////////////////////////////////////////////////////////////////////////
/// @brief create the context
////////////////////////////////////////////////////////////////////////////////
StandaloneTransactionContext::StandaloneTransactionContext(TRI_vocbase_t* vocbase)
: TransactionContext(vocbase) {
}
//////////////////////////////////////////////////////////////////////////////
/// @brief order a custom type handler for the collection
//////////////////////////////////////////////////////////////////////////////
std::shared_ptr<VPackCustomTypeHandler> StandaloneTransactionContext::orderCustomTypeHandler() {
if (_customTypeHandler == nullptr) {
_customTypeHandler.reset(TransactionContext::createCustomTypeHandler(_vocbase, getResolver()));
@ -50,10 +44,7 @@ std::shared_ptr<VPackCustomTypeHandler> StandaloneTransactionContext::orderCusto
return _customTypeHandler;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the resolver
////////////////////////////////////////////////////////////////////////////////
CollectionNameResolver const* StandaloneTransactionContext::getResolver() {
if (_resolver == nullptr) {
createResolver();
@ -62,37 +53,7 @@ CollectionNameResolver const* StandaloneTransactionContext::getResolver() {
return _resolver;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get parent transaction (if any)
////////////////////////////////////////////////////////////////////////////////
TransactionState* StandaloneTransactionContext::getParentTransaction() const {
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief register the transaction in the context
////////////////////////////////////////////////////////////////////////////////
void StandaloneTransactionContext::registerTransaction(TransactionState*) {}
////////////////////////////////////////////////////////////////////////////////
/// @brief unregister the transaction from the context
/// nothing special to do. cleanup will be done by the parent's destructor
////////////////////////////////////////////////////////////////////////////////
void StandaloneTransactionContext::unregisterTransaction() {}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the transaction is embeddable
////////////////////////////////////////////////////////////////////////////////
bool StandaloneTransactionContext::isEmbeddable() const { return false; }
////////////////////////////////////////////////////////////////////////////////
/// @brief create a context, returned in a shared ptr
////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<StandaloneTransactionContext> StandaloneTransactionContext::Create(TRI_vocbase_t* vocbase) {
return std::make_shared<StandaloneTransactionContext>(vocbase);
}

View File

@ -36,60 +36,33 @@ class StandaloneTransactionContext final : public TransactionContext {
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief create the context
//////////////////////////////////////////////////////////////////////////////
explicit StandaloneTransactionContext(TRI_vocbase_t*);
//////////////////////////////////////////////////////////////////////////////
/// @brief destroy the context
//////////////////////////////////////////////////////////////////////////////
~StandaloneTransactionContext() = default;
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief order a custom type handler
//////////////////////////////////////////////////////////////////////////////
std::shared_ptr<VPackCustomTypeHandler> orderCustomTypeHandler() override final;
//////////////////////////////////////////////////////////////////////////////
/// @brief return the resolver
//////////////////////////////////////////////////////////////////////////////
CollectionNameResolver const* getResolver() override final;
//////////////////////////////////////////////////////////////////////////////
/// @brief return the parent transaction (none in our case)
//////////////////////////////////////////////////////////////////////////////
TransactionState* getParentTransaction() const override { return nullptr; }
TransactionState* getParentTransaction() const override;
//////////////////////////////////////////////////////////////////////////////
/// @brief register the transaction, does nothing
//////////////////////////////////////////////////////////////////////////////
void registerTransaction(TransactionState*) override {}
void registerTransaction(TransactionState*) override;
//////////////////////////////////////////////////////////////////////////////
/// @brief unregister the transaction
//////////////////////////////////////////////////////////////////////////////
void unregisterTransaction() noexcept override {}
void unregisterTransaction() override;
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the transaction is embeddable
//////////////////////////////////////////////////////////////////////////////
bool isEmbeddable() const override;
bool isEmbeddable() const override { return false; }
//////////////////////////////////////////////////////////////////////////////
/// @brief create a context, returned in a shared ptr
//////////////////////////////////////////////////////////////////////////////
static std::shared_ptr<StandaloneTransactionContext> Create(TRI_vocbase_t*);
};

View File

@ -63,10 +63,7 @@ struct CustomTypeHandler final : public VPackCustomTypeHandler {
CollectionNameResolver const* resolver;
};
//////////////////////////////////////////////////////////////////////////////
/// @brief create the context
//////////////////////////////////////////////////////////////////////////////
TransactionContext::TransactionContext(TRI_vocbase_t* vocbase)
: _vocbase(vocbase),
_resolver(nullptr),
@ -81,10 +78,7 @@ TransactionContext::TransactionContext(TRI_vocbase_t* vocbase)
_dumpOptions.escapeUnicode = true;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief destroy the context
//////////////////////////////////////////////////////////////////////////////
TransactionContext::~TransactionContext() {
// unregister the transaction from the logfile manager
if (_transaction.id > 0) {
@ -109,21 +103,15 @@ TransactionContext::~TransactionContext() {
_resolver = nullptr;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief factory to create a custom type handler, not managed
//////////////////////////////////////////////////////////////////////////////
VPackCustomTypeHandler* TransactionContext::createCustomTypeHandler(TRI_vocbase_t* vocbase,
CollectionNameResolver const* resolver) {
return new CustomTypeHandler(vocbase, resolver);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief order a document ditch for the collection
/// this will create one if none exists. if no ditch can be created, the
/// function will return a nullptr!
//////////////////////////////////////////////////////////////////////////////
DocumentDitch* TransactionContext::orderDitch(LogicalCollection* collection) {
TRI_voc_cid_t cid = collection->cid();
@ -154,11 +142,8 @@ DocumentDitch* TransactionContext::orderDitch(LogicalCollection* collection) {
return ditch;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief return the ditch for a collection
/// this will return a nullptr if no ditch exists
//////////////////////////////////////////////////////////////////////////////
DocumentDitch* TransactionContext::ditch(TRI_voc_cid_t cid) const {
auto it = _ditches.find(cid);
@ -168,10 +153,7 @@ DocumentDitch* TransactionContext::ditch(TRI_voc_cid_t cid) const {
return (*it).second;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief temporarily lease a StringBuffer object
//////////////////////////////////////////////////////////////////////////////
basics::StringBuffer* TransactionContext::leaseStringBuffer(size_t initialSize) {
if (_stringBuffer == nullptr) {
_stringBuffer.reset(new basics::StringBuffer(TRI_UNKNOWN_MEM_ZONE, initialSize, false));
@ -182,18 +164,12 @@ basics::StringBuffer* TransactionContext::leaseStringBuffer(size_t initialSize)
return _stringBuffer.release();
}
//////////////////////////////////////////////////////////////////////////////
/// @brief return a temporary StringBuffer object
//////////////////////////////////////////////////////////////////////////////
void TransactionContext::returnStringBuffer(basics::StringBuffer* stringBuffer) {
_stringBuffer.reset(stringBuffer);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief temporarily lease a Builder object
//////////////////////////////////////////////////////////////////////////////
VPackBuilder* TransactionContext::leaseBuilder() {
if (_builders.empty()) {
// create a new builder and return it
@ -208,10 +184,7 @@ VPackBuilder* TransactionContext::leaseBuilder() {
return b;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief return a temporary Builder object
//////////////////////////////////////////////////////////////////////////////
void TransactionContext::returnBuilder(VPackBuilder* builder) {
try {
// put builder back into our vector of builders
@ -222,10 +195,7 @@ void TransactionContext::returnBuilder(VPackBuilder* builder) {
}
}
//////////////////////////////////////////////////////////////////////////////
/// @brief get velocypack options with a custom type handler
//////////////////////////////////////////////////////////////////////////////
VPackOptions* TransactionContext::getVPackOptions() {
if (_customTypeHandler == nullptr) {
// this modifies options!
@ -234,10 +204,7 @@ VPackOptions* TransactionContext::getVPackOptions() {
return &_options;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief get velocypack options with a custom type handler for dumping
//////////////////////////////////////////////////////////////////////////////
VPackOptions* TransactionContext::getVPackOptionsForDump() {
if (_customTypeHandler == nullptr) {
// this modifies options!
@ -246,10 +213,7 @@ VPackOptions* TransactionContext::getVPackOptionsForDump() {
return &_dumpOptions;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a resolver
////////////////////////////////////////////////////////////////////////////////
CollectionNameResolver const* TransactionContext::createResolver() {
TRI_ASSERT(_resolver == nullptr);
_resolver = new CollectionNameResolver(_vocbase);
@ -257,12 +221,9 @@ CollectionNameResolver const* TransactionContext::createResolver() {
return _resolver;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief unregister the transaction
/// this will save the transaction's id and status locally
//////////////////////////////////////////////////////////////////////////////
void TransactionContext::storeTransactionResult(TRI_voc_tid_t id, bool hasFailedOperations) {
void TransactionContext::storeTransactionResult(TRI_voc_tid_t id, bool hasFailedOperations) noexcept {
TRI_ASSERT(_transaction.id == 0);
_transaction.id = id;

View File

@ -59,134 +59,74 @@ class TransactionContext {
protected:
//////////////////////////////////////////////////////////////////////////////
/// @brief create the context
//////////////////////////////////////////////////////////////////////////////
explicit TransactionContext(TRI_vocbase_t* vocbase);
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief destroy the context
//////////////////////////////////////////////////////////////////////////////
virtual ~TransactionContext();
//////////////////////////////////////////////////////////////////////////////
/// @brief factory to create a custom type handler, not managed
//////////////////////////////////////////////////////////////////////////////
static arangodb::velocypack::CustomTypeHandler* createCustomTypeHandler(
TRI_vocbase_t*,
arangodb::CollectionNameResolver const*);
//////////////////////////////////////////////////////////////////////////////
/// @brief return the vocbase
//////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* vocbase() const { return _vocbase; }
//////////////////////////////////////////////////////////////////////////////
/// @brief order a document ditch for the collection
/// this will create one if none exists. if no ditch can be created, the
/// function will return a nullptr!
//////////////////////////////////////////////////////////////////////////////
DocumentDitch* orderDitch(arangodb::LogicalCollection*);
//////////////////////////////////////////////////////////////////////////////
/// @brief return the ditch for a collection
/// this will return a nullptr if no ditch exists
//////////////////////////////////////////////////////////////////////////////
DocumentDitch* ditch(TRI_voc_cid_t) const;
//////////////////////////////////////////////////////////////////////////////
/// @brief temporarily lease a StringBuffer object
//////////////////////////////////////////////////////////////////////////////
basics::StringBuffer* leaseStringBuffer(size_t initialSize);
//////////////////////////////////////////////////////////////////////////////
/// @brief return a temporary StringBuffer object
//////////////////////////////////////////////////////////////////////////////
void returnStringBuffer(basics::StringBuffer* stringBuffer);
//////////////////////////////////////////////////////////////////////////////
/// @brief temporarily lease a Builder object
//////////////////////////////////////////////////////////////////////////////
arangodb::velocypack::Builder* leaseBuilder();
//////////////////////////////////////////////////////////////////////////////
/// @brief return a temporary Builder object
//////////////////////////////////////////////////////////////////////////////
void returnBuilder(arangodb::velocypack::Builder*);
//////////////////////////////////////////////////////////////////////////////
/// @brief get velocypack options with a custom type handler
//////////////////////////////////////////////////////////////////////////////
arangodb::velocypack::Options* getVPackOptions();
//////////////////////////////////////////////////////////////////////////////
/// @brief get velocypack options for dumping
//////////////////////////////////////////////////////////////////////////////
arangodb::velocypack::Options* getVPackOptionsForDump();
//////////////////////////////////////////////////////////////////////////////
/// @brief unregister the transaction
/// this will save the transaction's id and status locally
//////////////////////////////////////////////////////////////////////////////
void storeTransactionResult(TRI_voc_tid_t, bool);
void storeTransactionResult(TRI_voc_tid_t id, bool hasFailedOperations) noexcept;
//////////////////////////////////////////////////////////////////////////////
/// @brief get a custom type handler
//////////////////////////////////////////////////////////////////////////////
virtual std::shared_ptr<VPackCustomTypeHandler> orderCustomTypeHandler() = 0;
//////////////////////////////////////////////////////////////////////////////
/// @brief return the resolver
//////////////////////////////////////////////////////////////////////////////
virtual CollectionNameResolver const* getResolver() = 0;
//////////////////////////////////////////////////////////////////////////////
/// @brief get parent transaction (if any)
//////////////////////////////////////////////////////////////////////////////
virtual TransactionState* getParentTransaction() const = 0;
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the transaction is embeddable
//////////////////////////////////////////////////////////////////////////////
virtual bool isEmbeddable() const = 0;
//////////////////////////////////////////////////////////////////////////////
/// @brief register the transaction in the context
//////////////////////////////////////////////////////////////////////////////
virtual void registerTransaction(TransactionState*) = 0;
//////////////////////////////////////////////////////////////////////////////
/// @brief unregister the transaction
//////////////////////////////////////////////////////////////////////////////
virtual void unregisterTransaction() = 0;
protected:
//////////////////////////////////////////////////////////////////////////////
/// @brief create a resolver
//////////////////////////////////////////////////////////////////////////////
CollectionNameResolver const* createResolver();
protected:

View File

@ -44,11 +44,6 @@ class UserTransaction final : public transaction::Methods {
: transaction::Methods(transactionContext) {
addHint(transaction::Hints::Hint::LOCK_ENTIRELY, false);
if (_state != nullptr) {
_state->timeout(lockTimeout);
_state->waitForSync(waitForSync);
}
for (auto const& it : exclusiveCollections) {
addCollection(it, AccessMode::Type::EXCLUSIVE);
}
@ -60,8 +55,10 @@ class UserTransaction final : public transaction::Methods {
for (auto const& it : readCollections) {
addCollection(it, AccessMode::Type::READ);
}
setAllowImplicitCollections(allowImplicitCollections);
_state->timeout(lockTimeout);
_state->waitForSync(waitForSync);
_state->allowImplicitCollections(allowImplicitCollections);
}
};

View File

@ -30,10 +30,7 @@
using namespace arangodb;
////////////////////////////////////////////////////////////////////////////////
/// @brief create the context
////////////////////////////////////////////////////////////////////////////////
V8TransactionContext::V8TransactionContext(TRI_vocbase_t* vocbase,
bool embeddable)
: TransactionContext(vocbase),
@ -45,10 +42,7 @@ V8TransactionContext::V8TransactionContext(TRI_vocbase_t* vocbase,
_currentTransaction(nullptr),
_embeddable(embeddable) {}
//////////////////////////////////////////////////////////////////////////////
/// @brief order a custom type handler for the collection
//////////////////////////////////////////////////////////////////////////////
std::shared_ptr<VPackCustomTypeHandler>
V8TransactionContext::orderCustomTypeHandler() {
if (_customTypeHandler == nullptr) {
@ -70,10 +64,7 @@ V8TransactionContext::orderCustomTypeHandler() {
return _customTypeHandler;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the resolver
////////////////////////////////////////////////////////////////////////////////
CollectionNameResolver const* V8TransactionContext::getResolver() {
if (_resolver == nullptr) {
V8TransactionContext* main = _sharedTransactionContext->_mainScope;
@ -90,19 +81,13 @@ CollectionNameResolver const* V8TransactionContext::getResolver() {
return _resolver;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get parent transaction (if any)
////////////////////////////////////////////////////////////////////////////////
TransactionState* V8TransactionContext::getParentTransaction() const {
TRI_ASSERT(_sharedTransactionContext != nullptr);
return _sharedTransactionContext->_currentTransaction;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief register the transaction in the context
////////////////////////////////////////////////////////////////////////////////
void V8TransactionContext::registerTransaction(TransactionState* trx) {
TRI_ASSERT(_sharedTransactionContext != nullptr);
TRI_ASSERT(_sharedTransactionContext->_currentTransaction == nullptr);
@ -111,41 +96,26 @@ void V8TransactionContext::registerTransaction(TransactionState* trx) {
_sharedTransactionContext->_mainScope = this;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief unregister the transaction from the context
////////////////////////////////////////////////////////////////////////////////
void V8TransactionContext::unregisterTransaction() {
void V8TransactionContext::unregisterTransaction() noexcept {
TRI_ASSERT(_sharedTransactionContext != nullptr);
_sharedTransactionContext->_currentTransaction = nullptr;
_sharedTransactionContext->_mainScope = nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the transaction is embeddable
////////////////////////////////////////////////////////////////////////////////
bool V8TransactionContext::isEmbeddable() const { return _embeddable; }
////////////////////////////////////////////////////////////////////////////////
/// @brief make this context a global context
/// this is only called upon V8 context initialization
////////////////////////////////////////////////////////////////////////////////
void V8TransactionContext::makeGlobal() { _sharedTransactionContext = this; }
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the transaction context is a global one
////////////////////////////////////////////////////////////////////////////////
bool V8TransactionContext::isGlobal() const {
return _sharedTransactionContext == this;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief check whether the transaction is embedded
////////////////////////////////////////////////////////////////////////////////
bool V8TransactionContext::IsEmbedded() {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(
v8::Isolate::GetCurrent()->GetData(V8PlatformFeature::V8_DATA_SLOT));
@ -156,10 +126,7 @@ bool V8TransactionContext::IsEmbedded() {
->_currentTransaction != nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a context, returned in a shared ptr
////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<V8TransactionContext> V8TransactionContext::Create(
TRI_vocbase_t* vocbase, bool embeddable) {
return std::make_shared<V8TransactionContext>(vocbase, embeddable);

View File

@ -36,98 +36,53 @@ class V8TransactionContext final : public TransactionContext {
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief create the context
//////////////////////////////////////////////////////////////////////////////
V8TransactionContext(TRI_vocbase_t*, bool);
//////////////////////////////////////////////////////////////////////////////
/// @brief destroy the context
//////////////////////////////////////////////////////////////////////////////
~V8TransactionContext() = default;
//////////////////////////////////////////////////////////////////////////////
/// @brief order a custom type handler
//////////////////////////////////////////////////////////////////////////////
std::shared_ptr<VPackCustomTypeHandler> orderCustomTypeHandler() override final;
//////////////////////////////////////////////////////////////////////////////
/// @brief return the resolver
//////////////////////////////////////////////////////////////////////////////
CollectionNameResolver const* getResolver() override final;
//////////////////////////////////////////////////////////////////////////////
/// @brief get parent transaction (if any)
//////////////////////////////////////////////////////////////////////////////
TransactionState* getParentTransaction() const override;
//////////////////////////////////////////////////////////////////////////////
/// @brief register the transaction in the context
//////////////////////////////////////////////////////////////////////////////
void registerTransaction(TransactionState* trx) override;
//////////////////////////////////////////////////////////////////////////////
/// @brief unregister the transaction from the context
//////////////////////////////////////////////////////////////////////////////
void unregisterTransaction() noexcept override;
void unregisterTransaction() override;
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the transaction is embeddable
//////////////////////////////////////////////////////////////////////////////
bool isEmbeddable() const override;
//////////////////////////////////////////////////////////////////////////////
/// @brief make this transaction context a global context
//////////////////////////////////////////////////////////////////////////////
void makeGlobal();
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the transaction context is a global one
//////////////////////////////////////////////////////////////////////////////
bool isGlobal() const;
//////////////////////////////////////////////////////////////////////////////
/// @brief check whether the transaction is embedded
//////////////////////////////////////////////////////////////////////////////
static bool IsEmbedded();
//////////////////////////////////////////////////////////////////////////////
/// @brief create a context, returned in a shared ptr
//////////////////////////////////////////////////////////////////////////////
static std::shared_ptr<V8TransactionContext> Create(TRI_vocbase_t*, bool);
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief the v8 thread-local "global" transaction context
//////////////////////////////////////////////////////////////////////////////
V8TransactionContext* _sharedTransactionContext;
V8TransactionContext* _mainScope;
//////////////////////////////////////////////////////////////////////////////
/// @brief the currently ongoing transaction
//////////////////////////////////////////////////////////////////////////////
TransactionState* _currentTransaction;
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not further transactions can be embedded
//////////////////////////////////////////////////////////////////////////////
bool const _embeddable;
};
}

View File

@ -23,15 +23,12 @@
#include "AuthInfo.h"
#include <velocypack/Builder.h>
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
#include "Aql/Query.h"
#include "Basics/ReadLocker.h"
#include "Basics/VelocyPackHelper.h"
#include "Basics/WriteLocker.h"
#include "Basics/tri-strings.h"
#include "Cluster/ServerState.h"
#include "GeneralServer/GeneralServerFeature.h"
#include "Logger/Logger.h"
#include "RestServer/DatabaseFeature.h"
@ -39,6 +36,10 @@
#include "Utils/SingleCollectionTransaction.h"
#include "Utils/StandaloneTransactionContext.h"
#include <velocypack/Builder.h>
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::velocypack;

View File

@ -2130,7 +2130,7 @@ int LogicalCollection::newObjectForInsert(
uint8_t* p = builder.add(StaticStrings::IdString,
VPackValuePair(9ULL, VPackValueType::Custom));
*p++ = 0xf3; // custom type for _id
if (ServerState::isDBServer(trx->serverRole()) && !_isSystem) {
if (trx->state()->isDBServer() && !_isSystem) {
// db server in cluster, note: the local collections _statistics,
// _statisticsRaw and _statistics15 (which are the only system
// collections)

View File

@ -26,6 +26,7 @@
#include "Basics/Common.h"
#include "Aql/FixedVarExpressionContext.h"
#include "StorageEngine/TransactionState.h"
#include "Transaction/Methods.h"
namespace arangodb {
@ -123,7 +124,7 @@ struct TraverserOptions {
_tmpVar(nullptr),
_ctx(new aql::FixedVarExpressionContext()),
_traverser(nullptr),
_isCoordinator(arangodb::ServerState::instance()->isCoordinator()),
_isCoordinator(trx->state()->isCoordinator()),
minDepth(1),
maxDepth(1),
useBreadthFirst(false),

View File

@ -62,6 +62,7 @@ LogTopic Logger::STARTUP("startup", LogLevel::INFO);
LogTopic Logger::SUPERVISION("supervision", LogLevel::INFO);
LogTopic Logger::SYSCALL("syscall", LogLevel::WARN);
LogTopic Logger::THREADS("threads", LogLevel::WARN);
LogTopic Logger::TRANSACTIONS("trx", LogLevel::WARN);
LogTopic Logger::V8("v8", LogLevel::WARN);
#ifdef USE_ENTERPRISE
@ -121,6 +122,10 @@ LogTopic::LogTopic(std::string const& name, LogLevel level)
_name(name),
_level(level) {
if (name != "fixme") {
// "fixme" is a remainder from ArangoDB < 3.2, when it was
// allowed to log messages without a topic. From 3.2 onwards,
// logging is always topic-based, and all previously topicless
// log invocations now use the log topic "fixme".
_displayName = std::string("{") + name + "} ";
}

View File

@ -148,6 +148,7 @@ class Logger {
static LogTopic SUPERVISION;
static LogTopic SYSCALL;
static LogTopic THREADS;
static LogTopic TRANSACTIONS;
static LogTopic V8;
public: