1
0
Fork 0

honor transaction options

This commit is contained in:
jsteemann 2017-06-01 02:01:33 +02:00
parent 8b6e9ec793
commit b91eab0ce8
13 changed files with 57 additions and 37 deletions

View File

@ -31,6 +31,13 @@
using namespace arangodb; using namespace arangodb;
using namespace arangodb::aql; using namespace arangodb::aql;
/// @brief clone, used to make daughter transactions for parts of a
/// distributed AQL query running on the coordinator
transaction::Methods* AqlTransaction::clone(transaction::Options const& options) const {
return new AqlTransaction(transaction::StandaloneContext::Create(vocbase()),
&_collections, options, false);
}
/// @brief add a collection to the transaction /// @brief add a collection to the transaction
Result AqlTransaction::processCollection(aql::Collection* collection) { Result AqlTransaction::processCollection(aql::Collection* collection) {
if (ServerState::instance()->isCoordinator()) { if (ServerState::instance()->isCoordinator()) {

View File

@ -45,8 +45,7 @@ class AqlTransaction final : public transaction::Methods {
transaction::Options const& options, transaction::Options const& options,
bool isMainTransaction) bool isMainTransaction)
: transaction::Methods(transactionContext, options), : transaction::Methods(transactionContext, options),
_collections(*collections), _collections(*collections) {
_options(options) {
if (!isMainTransaction) { if (!isMainTransaction) {
addHint(transaction::Hints::Hint::LOCK_NEVER); addHint(transaction::Hints::Hint::LOCK_NEVER);
} else { } else {
@ -90,12 +89,8 @@ class AqlTransaction final : public transaction::Methods {
LogicalCollection* documentCollection(TRI_voc_cid_t cid); LogicalCollection* documentCollection(TRI_voc_cid_t cid);
/// @brief clone, used to make daughter transactions for parts of a /// @brief clone, used to make daughter transactions for parts of a
/// distributed /// distributed AQL query running on the coordinator
/// AQL query running on the coordinator transaction::Methods* clone(transaction::Options const&) const override;
transaction::Methods* clone() const override {
return new AqlTransaction(transaction::StandaloneContext::Create(vocbase()),
&_collections, _options, false);
}
/// @brief lockCollections, this is needed in a corner case in AQL: we need /// @brief lockCollections, this is needed in a corner case in AQL: we need
/// to lock all shards in a controlled way when we set up a distributed /// to lock all shards in a controlled way when we set up a distributed
@ -109,7 +104,6 @@ class AqlTransaction final : public transaction::Methods {
/// operation /// operation
private: private:
std::map<std::string, aql::Collection*> _collections; std::map<std::string, aql::Collection*> _collections;
transaction::Options _options;
}; };
} }

View File

@ -100,6 +100,14 @@ Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
if (aql == nullptr) { if (aql == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_SHUTTING_DOWN); THROW_ARANGO_EXCEPTION(TRI_ERROR_SHUTTING_DOWN);
} }
if (_contextOwnedByExterior) {
// copy transaction options from global state into our local query options
TransactionState* state = transaction::V8Context::getParentState();
if (state != nullptr) {
_queryOptions.transactionOptions = state->options();
}
}
// populate query options // populate query options
if (_options != nullptr) { if (_options != nullptr) {
@ -248,8 +256,9 @@ Query* Query::clone(QueryPart part, bool withPlan) {
TRI_ASSERT(clone->_trx == nullptr); TRI_ASSERT(clone->_trx == nullptr);
clone->_trx = _trx->clone(); // A daughter transaction which does not // A daughter transaction which does not
// actually lock the collections // actually lock the collections
clone->_trx = _trx->clone(_queryOptions.transactionOptions);
Result res = clone->_trx->begin(); Result res = clone->_trx->begin();
@ -418,12 +427,12 @@ ExecutionPlan* Query::prepare() {
std::unique_ptr<ExecutionPlan> plan; std::unique_ptr<ExecutionPlan> plan;
if (!_queryString.empty()) { if (!_queryString.empty()) {
auto parser = std::make_unique<Parser>(this); Parser parser(this);
parser->parse(false); parser.parse(false);
// put in bind parameters // put in bind parameters
parser->ast()->injectBindParameters(_bindParameters); parser.ast()->injectBindParameters(_bindParameters);
_isModificationQuery = parser->isModificationQuery(); _isModificationQuery = parser.isModificationQuery();
} }
TRI_ASSERT(_trx == nullptr); TRI_ASSERT(_trx == nullptr);

View File

@ -68,7 +68,7 @@ QueryOptions::QueryOptions() :
auto queryCacheMode = QueryCache::instance()->mode(); auto queryCacheMode = QueryCache::instance()->mode();
cache = (queryCacheMode == CACHE_ALWAYS_ON); cache = (queryCacheMode == CACHE_ALWAYS_ON);
} }
void QueryOptions::fromVelocyPack(VPackSlice const& slice) { void QueryOptions::fromVelocyPack(VPackSlice const& slice) {
if (!slice.isObject()) { if (!slice.isObject()) {
return; return;

View File

@ -106,7 +106,7 @@ BaseEngine::BaseEngine(TRI_vocbase_t* vocbase, VPackSlice info)
// created transaction is considered a "MAIN" part and will not switch // created transaction is considered a "MAIN" part and will not switch
// off collection locking completely! // off collection locking completely!
_query = _query =
new aql::Query(true, vocbase, aql::QueryString(), params, opts, aql::PART_DEPENDENT); new aql::Query(false, vocbase, aql::QueryString(), params, opts, aql::PART_DEPENDENT);
_query->injectTransaction(_trx); _query->injectTransaction(_trx);
VPackSlice variablesSlice = info.get(VARIABLES); VPackSlice variablesSlice = info.get(VARIABLES);

View File

@ -306,10 +306,10 @@ bool RestQueryHandler::parseQuery() {
"expecting a JSON object as body"); "expecting a JSON object as body");
}; };
std::string const&& queryString = std::string const queryString =
VelocyPackHelper::checkAndGetStringValue(body, "query"); VelocyPackHelper::checkAndGetStringValue(body, "query");
Query query(true, _vocbase, QueryString(queryString), Query query(false, _vocbase, QueryString(queryString),
nullptr, nullptr, PART_MAIN); nullptr, nullptr, PART_MAIN);
auto parseResult = query.parse(); auto parseResult = query.parse();

View File

@ -438,15 +438,16 @@ RocksDBOperationResult RocksDBTransactionState::addOperation(
// "transaction size" counters have reached their limit // "transaction size" counters have reached their limit
if (_options.intermediateCommitCount <= numOperations || if (_options.intermediateCommitCount <= numOperations ||
_options.intermediateCommitSize <= newSize) { _options.intermediateCommitSize <= newSize) {
internalCommit(); // LOG_TOPIC(ERR, Logger::FIXME) << "INTERMEDIATE COMMIT!";
_numInserts = 0; internalCommit();
_numUpdates = 0; _numInserts = 0;
_numRemoves = 0; _numUpdates = 0;
_numRemoves = 0;
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE #ifdef ARANGODB_ENABLE_MAINTAINER_MODE
_numLogdata = 0; _numLogdata = 0;
#endif #endif
createTransaction(); createTransaction();
} }
return res; return res;
} }

View File

@ -68,6 +68,8 @@ class TransactionState {
bool isDBServer() const { return ServerState::isDBServer(_serverRole); } bool isDBServer() const { return ServerState::isDBServer(_serverRole); }
bool isCoordinator() const { return ServerState::isCoordinator(_serverRole); } bool isCoordinator() const { return ServerState::isCoordinator(_serverRole); }
transaction::Options& options() { return _options; }
transaction::Options const& options() const { return _options; }
TRI_vocbase_t* vocbase() const { return _vocbase; } TRI_vocbase_t* vocbase() const { return _vocbase; }
TRI_voc_tid_t id() const { return _id; } TRI_voc_tid_t id() const { return _id; }
transaction::Status status() const { return _status; } transaction::Status status() const { return _status; }

View File

@ -2701,14 +2701,12 @@ std::vector<std::shared_ptr<Index>> transaction::Methods::indexesForCollection(
} }
/// @brief Lock all collections. Only works for selected sub-classes /// @brief Lock all collections. Only works for selected sub-classes
int transaction::Methods::lockCollections() { int transaction::Methods::lockCollections() {
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
} }
/// @brief Clone this transaction. Only works for selected sub-classes /// @brief Clone this transaction. Only works for selected sub-classes
transaction::Methods* transaction::Methods::clone(transaction::Options const&) const {
transaction::Methods* transaction::Methods::clone() const {
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
} }

View File

@ -373,7 +373,7 @@ class Methods {
virtual int lockCollections(); virtual int lockCollections();
/// @brief Clone this transaction. Only works for selected sub-classes /// @brief Clone this transaction. Only works for selected sub-classes
virtual transaction::Methods* clone() const; virtual transaction::Methods* clone(transaction::Options const&) const;
/// @brief return the collection name resolver /// @brief return the collection name resolver
CollectionNameResolver const* resolver() const; CollectionNameResolver const* resolver() const;

View File

@ -115,15 +115,21 @@ bool transaction::V8Context::isGlobal() const {
return _sharedTransactionContext == this; return _sharedTransactionContext == this;
} }
/// @brief check whether the transaction is embedded /// @brief return parent transaction state or none
bool transaction::V8Context::IsEmbedded() { TransactionState* transaction::V8Context::getParentState() {
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>( TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(
v8::Isolate::GetCurrent()->GetData(V8PlatformFeature::V8_DATA_SLOT)); v8::Isolate::GetCurrent()->GetData(V8PlatformFeature::V8_DATA_SLOT));
if (v8g->_transactionContext == nullptr) { if (v8g == nullptr ||
return false; v8g->_transactionContext == nullptr) {
return nullptr;
} }
return static_cast<transaction::V8Context*>(v8g->_transactionContext) return static_cast<transaction::V8Context*>(v8g->_transactionContext)
->_currentTransaction != nullptr; ->_currentTransaction;
}
/// @brief check whether the transaction is embedded
bool transaction::V8Context::isEmbedded() {
return (getParentState() != nullptr);
} }
/// @brief create a context, returned in a shared ptr /// @brief create a context, returned in a shared ptr

View File

@ -69,8 +69,11 @@ class V8Context final : public Context {
/// @brief whether or not the transaction context is a global one /// @brief whether or not the transaction context is a global one
bool isGlobal() const; bool isGlobal() const;
/// @brief return parent transaction state or none
static TransactionState* getParentState();
/// @brief check whether the transaction is embedded /// @brief check whether the transaction is embedded
static bool IsEmbedded(); static bool isEmbedded();
/// @brief create a context, returned in a shared ptr /// @brief create a context, returned in a shared ptr
static std::shared_ptr<transaction::V8Context> Create(TRI_vocbase_t*, bool); static std::shared_ptr<transaction::V8Context> Create(TRI_vocbase_t*, bool);

View File

@ -36,7 +36,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#define PREVENT_EMBEDDED_TRANSACTION() \ #define PREVENT_EMBEDDED_TRANSACTION() \
if (arangodb::transaction::V8Context::IsEmbedded()) { \ if (arangodb::transaction::V8Context::isEmbedded()) { \
TRI_V8_THROW_EXCEPTION(TRI_ERROR_TRANSACTION_DISALLOWED_OPERATION); \ TRI_V8_THROW_EXCEPTION(TRI_ERROR_TRANSACTION_DISALLOWED_OPERATION); \
} }