mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'engine-api' of github.com:arangodb/arangodb into engine-api
This commit is contained in:
commit
cc999641a5
|
@ -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?
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -60,7 +60,6 @@ namespace arangodb {
|
|||
namespace transaction {
|
||||
class Methods;
|
||||
}
|
||||
;
|
||||
|
||||
namespace aql {
|
||||
class AqlItemBlock;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -106,6 +106,7 @@ class MMFilesTransactionState final : public TransactionState {
|
|||
|
||||
private:
|
||||
rocksdb::Transaction* _rocksTransaction;
|
||||
bool _beginWritten;
|
||||
bool _hasOperations;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 + "} ";
|
||||
}
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ class Logger {
|
|||
static LogTopic SUPERVISION;
|
||||
static LogTopic SYSCALL;
|
||||
static LogTopic THREADS;
|
||||
static LogTopic TRANSACTIONS;
|
||||
static LogTopic V8;
|
||||
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue