diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index 9cf47d396a..7cd0f3d45e 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -26,6 +26,7 @@ //////////////////////////////////////////////////////////////////////////////// #include "Aql/ExecutionBlock.h" +#include "Aql/ExecutionEngine.h" #include "Basics/StringUtils.h" #include "Basics/json-utilities.h" #include "Utils/Exception.h" @@ -105,6 +106,20 @@ size_t const ExecutionBlock::DefaultBatchSize = 1000; // --SECTION-- constructors / destructors // ----------------------------------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + +ExecutionBlock::ExecutionBlock (ExecutionEngine* engine, + ExecutionNode const* ep) + : _engine(engine), + _trx(engine->getTransaction()), + _exeNode(ep), + _varOverview(nullptr), + _depth(0), + _done(false) { +} + //////////////////////////////////////////////////////////////////////////////// /// @brief destructor //////////////////////////////////////////////////////////////////////////////// @@ -513,9 +528,9 @@ int SingletonBlock::getOrSkipSome (size_t atLeast, // --SECTION-- class EnumerateCollectionBlock // ----------------------------------------------------------------------------- -EnumerateCollectionBlock::EnumerateCollectionBlock (AQL_TRANSACTION_V8* trx, +EnumerateCollectionBlock::EnumerateCollectionBlock (ExecutionEngine* engine, EnumerateCollectionNode const* ep) - : ExecutionBlock(trx, ep), + : ExecutionBlock(engine, ep), _collection(ep->_collection), _posInAllDocs(0) { } @@ -1884,13 +1899,12 @@ AqlItemBlock* ReturnBlock::getSome (size_t atLeast, // --SECTION-- class ModificationBlock // ----------------------------------------------------------------------------- -ModificationBlock::ModificationBlock (AQL_TRANSACTION_V8* trx, +ModificationBlock::ModificationBlock (ExecutionEngine* engine, ModificationNode const* ep) - : ExecutionBlock(trx, ep), + : ExecutionBlock(engine, ep), _collection(ep->_collection) { } - ModificationBlock::~ModificationBlock () { } @@ -1989,16 +2003,37 @@ int ModificationBlock::extractKey (AqlValue const& value, return TRI_ERROR_ARANGO_DOCUMENT_KEY_MISSING; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief process the result of a data-modification operation +//////////////////////////////////////////////////////////////////////////////// + +void ModificationBlock::handleResult (int code, + bool ignoreErrors) { + if (code == TRI_ERROR_NO_ERROR) { + // update the success counter + ++_engine->_stats.writesExecuted; + } + else { + if (ignoreErrors) { + // update the ignored counter + ++_engine->_stats.writesIgnored; + } + else { + // bubble up the error + THROW_ARANGO_EXCEPTION(code); + } + } +} + // ----------------------------------------------------------------------------- // --SECTION-- class RemoveBlock // ----------------------------------------------------------------------------- -RemoveBlock::RemoveBlock (AQL_TRANSACTION_V8* trx, +RemoveBlock::RemoveBlock (ExecutionEngine* engine, RemoveNode const* ep) - : ModificationBlock(trx, ep) { + : ModificationBlock(engine, ep) { } - RemoveBlock::~RemoveBlock () { } @@ -2055,12 +2090,8 @@ void RemoveBlock::work (std::vector& blocks) { nullptr, ep->_options.waitForSync); } - - if (errorCode != TRI_ERROR_NO_ERROR && - ! ep->_options.ignoreErrors) { - // bubble up the error - THROW_ARANGO_EXCEPTION(errorCode); - } + + handleResult(errorCode, ep->_options.ignoreErrors); } // done with a block @@ -2075,9 +2106,9 @@ void RemoveBlock::work (std::vector& blocks) { // --SECTION-- class InsertBlock // ----------------------------------------------------------------------------- -InsertBlock::InsertBlock (AQL_TRANSACTION_V8* trx, +InsertBlock::InsertBlock (ExecutionEngine* engine, InsertNode const* ep) - : ModificationBlock(trx, ep) { + : ModificationBlock(engine, ep) { } InsertBlock::~InsertBlock () { @@ -2172,10 +2203,7 @@ void InsertBlock::work (std::vector& blocks) { } } - if (errorCode != TRI_ERROR_NO_ERROR && - ! ep->_options.ignoreErrors) { - THROW_ARANGO_EXCEPTION(errorCode); - } + handleResult(errorCode, ep->_options.ignoreErrors); } // done with a block @@ -2190,9 +2218,9 @@ void InsertBlock::work (std::vector& blocks) { // --SECTION-- class UpdateBlock // ----------------------------------------------------------------------------- -UpdateBlock::UpdateBlock (AQL_TRANSACTION_V8* trx, +UpdateBlock::UpdateBlock (ExecutionEngine* engine, UpdateNode const* ep) - : ModificationBlock(trx, ep) { + : ModificationBlock(engine, ep) { } UpdateBlock::~UpdateBlock () { @@ -2293,10 +2321,7 @@ void UpdateBlock::work (std::vector& blocks) { } } - if (errorCode != TRI_ERROR_NO_ERROR && - ! ep->_options.ignoreErrors) { - THROW_ARANGO_EXCEPTION(errorCode); - } + handleResult(errorCode, ep->_options.ignoreErrors); } // done with a block @@ -2311,9 +2336,9 @@ void UpdateBlock::work (std::vector& blocks) { // --SECTION-- class ReplaceBlock // ----------------------------------------------------------------------------- -ReplaceBlock::ReplaceBlock (AQL_TRANSACTION_V8* trx, +ReplaceBlock::ReplaceBlock (ExecutionEngine* engine, ReplaceNode const* ep) - : ModificationBlock(trx, ep) { + : ModificationBlock(engine, ep) { } ReplaceBlock::~ReplaceBlock () { @@ -2385,10 +2410,7 @@ void ReplaceBlock::work (std::vector& blocks) { errorCode = _trx->update(trxCollection, key, 0, &mptr, json.json(), TRI_DOC_UPDATE_LAST_WRITE, 0, nullptr, ep->_options.waitForSync); } - if (errorCode != TRI_ERROR_NO_ERROR && - ! ep->_options.ignoreErrors) { - THROW_ARANGO_EXCEPTION(errorCode); - } + handleResult(errorCode, ep->_options.ignoreErrors); } // done with a block diff --git a/arangod/Aql/ExecutionBlock.h b/arangod/Aql/ExecutionBlock.h index 2e4504bbb4..9d2494ebff 100644 --- a/arangod/Aql/ExecutionBlock.h +++ b/arangod/Aql/ExecutionBlock.h @@ -43,6 +43,8 @@ namespace triagens { namespace aql { + class ExecutionEngine; + // ----------------------------------------------------------------------------- // --SECTION-- AggregatorGroup // ----------------------------------------------------------------------------- @@ -99,11 +101,8 @@ namespace triagens { /// @brief constructor //////////////////////////////////////////////////////////////////////////////// - ExecutionBlock (AQL_TRANSACTION_V8* trx, - ExecutionNode const* ep) - : _trx(trx), _exeNode(ep), _done(false), _depth(0), - _varOverview(nullptr) { - } + ExecutionBlock (ExecutionEngine*, + ExecutionNode const*); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor @@ -266,6 +265,7 @@ namespace triagens { void inheritRegisters (AqlItemBlock const* src, AqlItemBlock* dst, size_t row); + //////////////////////////////////////////////////////////////////////////////// /// @brief the following is internal to pull one more block and append it to /// our _buffer deque. Returns true if a new block was appended and false if @@ -332,6 +332,12 @@ namespace triagens { AqlItemBlock*& result, size_t& skipped); +//////////////////////////////////////////////////////////////////////////////// +/// @brief the execution engine +//////////////////////////////////////////////////////////////////////////////// + + ExecutionEngine* _engine; + //////////////////////////////////////////////////////////////////////////////// /// @brief the transaction for this query //////////////////////////////////////////////////////////////////////////////// @@ -362,18 +368,18 @@ namespace triagens { std::deque _buffer; +//////////////////////////////////////////////////////////////////////////////// +/// @brief info about variables, filled in by staticAnalysis +//////////////////////////////////////////////////////////////////////////////// + + std::shared_ptr _varOverview; + //////////////////////////////////////////////////////////////////////////////// /// @brief current working position in the first entry of _buffer //////////////////////////////////////////////////////////////////////////////// size_t _pos; -//////////////////////////////////////////////////////////////////////////////// -/// @brief if this is set, we are done, this is reset to false by execute() -//////////////////////////////////////////////////////////////////////////////// - - bool _done; - //////////////////////////////////////////////////////////////////////////////// /// @brief depth of frames (number of FOR statements here or above) //////////////////////////////////////////////////////////////////////////////// @@ -381,10 +387,14 @@ namespace triagens { int _depth; // will be filled in by staticAnalysis //////////////////////////////////////////////////////////////////////////////// -/// @brief info about variables, filled in by staticAnalysis +/// @brief if this is set, we are done, this is reset to false by execute() //////////////////////////////////////////////////////////////////////////////// - std::shared_ptr _varOverview; + bool _done; + +// ----------------------------------------------------------------------------- +// --SECTION-- public variables +// ----------------------------------------------------------------------------- public: @@ -403,8 +413,10 @@ namespace triagens { public: - SingletonBlock (AQL_TRANSACTION_V8* trx, SingletonNode const* ep) - : ExecutionBlock(trx, ep), _inputRegisterValues(nullptr) { + SingletonBlock (ExecutionEngine* engine, + SingletonNode const* ep) + : ExecutionBlock(engine, ep), + _inputRegisterValues(nullptr) { } ~SingletonBlock () { @@ -467,7 +479,7 @@ namespace triagens { public: - EnumerateCollectionBlock (AQL_TRANSACTION_V8* trx, + EnumerateCollectionBlock (ExecutionEngine* engine, EnumerateCollectionNode const* ep); ~EnumerateCollectionBlock (); @@ -557,9 +569,9 @@ namespace triagens { public: - EnumerateListBlock (AQL_TRANSACTION_V8* trx, - EnumerateListNode const* ep) - : ExecutionBlock(trx, ep) { + EnumerateListBlock (ExecutionEngine* engine, + EnumerateListNode const* ep) + : ExecutionBlock(engine, ep) { } @@ -638,9 +650,9 @@ namespace triagens { public: - CalculationBlock (AQL_TRANSACTION_V8* trx, + CalculationBlock (ExecutionEngine* engine, CalculationNode const* en) - : ExecutionBlock(trx, en), + : ExecutionBlock(engine, en), _expression(en->expression()), _outReg(0) { @@ -668,11 +680,12 @@ namespace triagens { virtual AqlItemBlock* getSome (size_t atLeast, size_t atMost); + private: + //////////////////////////////////////////////////////////////////////////////// /// @brief we hold a pointer to the expression in the plan //////////////////////////////////////////////////////////////////////////////// - private: Expression* _expression; //////////////////////////////////////////////////////////////////////////////// @@ -709,10 +722,11 @@ namespace triagens { public: - SubqueryBlock (AQL_TRANSACTION_V8* trx, + SubqueryBlock (ExecutionEngine* engine, SubqueryNode const* en, ExecutionBlock* subquery) - : ExecutionBlock(trx, en), _outReg(0), + : ExecutionBlock(engine, en), + _outReg(0), _subquery(subquery) { } @@ -755,8 +769,9 @@ namespace triagens { public: - FilterBlock (AQL_TRANSACTION_V8* trx, FilterNode const* ep) - : ExecutionBlock(trx, ep) { + FilterBlock (ExecutionEngine* engine, + FilterNode const* ep) + : ExecutionBlock(engine, ep) { } ~FilterBlock () { @@ -822,9 +837,9 @@ namespace triagens { public: - AggregateBlock (AQL_TRANSACTION_V8* trx, + AggregateBlock (ExecutionEngine* engine, ExecutionNode const* ep) - : ExecutionBlock(trx, ep), + : ExecutionBlock(engine, ep), _groupRegister(0), _variableNames() { } @@ -886,9 +901,9 @@ namespace triagens { public: - SortBlock (AQL_TRANSACTION_V8* trx, + SortBlock (ExecutionEngine* engine, ExecutionNode const* ep) - : ExecutionBlock(trx, ep), + : ExecutionBlock(engine, ep), _stable(false) { } @@ -955,8 +970,11 @@ namespace triagens { public: - LimitBlock (AQL_TRANSACTION_V8* trx, LimitNode const* ep) - : ExecutionBlock(trx, ep), _offset(ep->_offset), _limit(ep->_limit), + LimitBlock (ExecutionEngine* engine, + LimitNode const* ep) + : ExecutionBlock(engine, ep), + _offset(ep->_offset), + _limit(ep->_limit), _state(0) { // start in the beginning } @@ -1010,8 +1028,9 @@ namespace triagens { /// @brief constructor //////////////////////////////////////////////////////////////////////////////// - ReturnBlock (AQL_TRANSACTION_V8* trx, ReturnNode const* ep) - : ExecutionBlock(trx, ep) { + ReturnBlock (ExecutionEngine* engine, + ReturnNode const* ep) + : ExecutionBlock(engine, ep) { } @@ -1043,7 +1062,8 @@ namespace triagens { /// @brief constructor //////////////////////////////////////////////////////////////////////////////// - ModificationBlock (AQL_TRANSACTION_V8*, ModificationNode const*); + ModificationBlock (ExecutionEngine*, + ModificationNode const*); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor @@ -1086,6 +1106,13 @@ namespace triagens { TRI_document_collection_t const*, std::string&) const; +//////////////////////////////////////////////////////////////////////////////// +/// @brief process the result of a data-modification operation +//////////////////////////////////////////////////////////////////////////////// + + void handleResult (int, + bool); + // ----------------------------------------------------------------------------- // --SECTION-- protected variables // ----------------------------------------------------------------------------- @@ -1100,7 +1127,6 @@ namespace triagens { }; - // ----------------------------------------------------------------------------- // --SECTION-- RemoveBlock // ----------------------------------------------------------------------------- @@ -1113,7 +1139,8 @@ namespace triagens { /// @brief constructor //////////////////////////////////////////////////////////////////////////////// - RemoveBlock (AQL_TRANSACTION_V8* trx, RemoveNode const* ep); + RemoveBlock (ExecutionEngine*, + RemoveNode const*); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor @@ -1147,7 +1174,8 @@ namespace triagens { /// @brief constructor //////////////////////////////////////////////////////////////////////////////// - InsertBlock (AQL_TRANSACTION_V8* trx, InsertNode const* ep); + InsertBlock (ExecutionEngine*, + InsertNode const*); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor @@ -1181,7 +1209,8 @@ namespace triagens { /// @brief constructor //////////////////////////////////////////////////////////////////////////////// - UpdateBlock (AQL_TRANSACTION_V8* trx, UpdateNode const* ep); + UpdateBlock (ExecutionEngine*, + UpdateNode const*); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor @@ -1215,7 +1244,8 @@ namespace triagens { /// @brief constructor //////////////////////////////////////////////////////////////////////////////// - ReplaceBlock (AQL_TRANSACTION_V8* trx, ReplaceNode const* ep); + ReplaceBlock (ExecutionEngine*, + ReplaceNode const*); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor @@ -1245,8 +1275,9 @@ namespace triagens { public: - NoResultsBlock (AQL_TRANSACTION_V8* trx, SingletonNode const* ep) - : ExecutionBlock(trx, ep) { + NoResultsBlock (ExecutionEngine* engine, + SingletonNode const* ep) + : ExecutionBlock(engine, ep) { } ~NoResultsBlock () { diff --git a/arangod/Aql/ExecutionEngine.cpp b/arangod/Aql/ExecutionEngine.cpp index 39925093f3..16418711d4 100644 --- a/arangod/Aql/ExecutionEngine.cpp +++ b/arangod/Aql/ExecutionEngine.cpp @@ -45,7 +45,8 @@ using namespace triagens::aql; //////////////////////////////////////////////////////////////////////////////// ExecutionEngine::ExecutionEngine (AQL_TRANSACTION_V8* trx) - : _blocks(), + : _stats(), + _blocks(), _root(nullptr), _trx(trx) { @@ -88,42 +89,42 @@ struct Instanciator : public WalkerWorker { switch (en->getType()) { case ExecutionNode::SINGLETON: { - eb = new SingletonBlock(engine->getTransaction(), + eb = new SingletonBlock(engine, static_cast(en)); break; } case ExecutionNode::ENUMERATE_COLLECTION: { - eb = new EnumerateCollectionBlock(engine->getTransaction(), + eb = new EnumerateCollectionBlock(engine, static_cast(en)); break; } case ExecutionNode::ENUMERATE_LIST: { - eb = new EnumerateListBlock(engine->getTransaction(), + eb = new EnumerateListBlock(engine, static_cast(en)); break; } case ExecutionNode::CALCULATION: { - eb = new CalculationBlock(engine->getTransaction(), + eb = new CalculationBlock(engine, static_cast(en)); break; } case ExecutionNode::FILTER: { - eb = new FilterBlock(engine->getTransaction(), + eb = new FilterBlock(engine, static_cast(en)); break; } case ExecutionNode::LIMIT: { - eb = new LimitBlock(engine->getTransaction(), + eb = new LimitBlock(engine, static_cast(en)); break; } case ExecutionNode::SORT: { - eb = new SortBlock(engine->getTransaction(), + eb = new SortBlock(engine, static_cast(en)); break; } case ExecutionNode::AGGREGATE: { - eb = new AggregateBlock(engine->getTransaction(), + eb = new AggregateBlock(engine, static_cast(en)); break; } @@ -133,41 +134,41 @@ struct Instanciator : public WalkerWorker { TRI_ASSERT(it != cache.end()); - eb = new SubqueryBlock(engine->getTransaction(), + eb = new SubqueryBlock(engine, static_cast(en), it->second); break; } case ExecutionNode::RETURN: { - eb = new ReturnBlock(engine->getTransaction(), + eb = new ReturnBlock(engine, static_cast(en)); root = eb; break; } case ExecutionNode::REMOVE: { - eb = new RemoveBlock(engine->getTransaction(), + eb = new RemoveBlock(engine, static_cast(en)); root = eb; break; } case ExecutionNode::INSERT: { - eb = new InsertBlock(engine->getTransaction(), + eb = new InsertBlock(engine, static_cast(en)); root = eb; break; } case ExecutionNode::UPDATE: { - eb = new UpdateBlock(engine->getTransaction(), + eb = new UpdateBlock(engine, static_cast(en)); root = eb; break; } case ExecutionNode::REPLACE: { - eb = new ReplaceBlock(engine->getTransaction(), + eb = new ReplaceBlock(engine, static_cast(en)); root = eb; diff --git a/arangod/Aql/ExecutionEngine.h b/arangod/Aql/ExecutionEngine.h index 019d487cdd..a4e10eed44 100644 --- a/arangod/Aql/ExecutionEngine.h +++ b/arangod/Aql/ExecutionEngine.h @@ -35,6 +35,7 @@ #include "arangod/Aql/AqlItemBlock.h" #include "arangod/Aql/ExecutionBlock.h" #include "arangod/Aql/ExecutionPlan.h" +#include "arangod/Aql/ExecutionStats.h" #include "Utils/AqlTransaction.h" namespace triagens { @@ -124,7 +125,7 @@ namespace triagens { /// @brief hasMore //////////////////////////////////////////////////////////////////////////////// - bool hasMore () { + inline bool hasMore () const { return _root->hasMore(); } @@ -132,7 +133,7 @@ namespace triagens { /// @brief count //////////////////////////////////////////////////////////////////////////////// - int64_t count () { + inline int64_t count () const { return _root->count(); } @@ -140,7 +141,7 @@ namespace triagens { /// @brief remaining //////////////////////////////////////////////////////////////////////////////// - int64_t remaining () { + inline int64_t remaining () const { return _root->remaining(); } @@ -150,6 +151,19 @@ namespace triagens { void addBlock (ExecutionBlock*); +// ----------------------------------------------------------------------------- +// --SECTION-- public variables +// ----------------------------------------------------------------------------- + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief execution statistics for the query +/// note that the statistics are modification by execution blocks +//////////////////////////////////////////////////////////////////////////////// + + ExecutionStats _stats; + // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- diff --git a/arangod/Aql/ExecutionStats.cpp b/arangod/Aql/ExecutionStats.cpp new file mode 100644 index 0000000000..1c4401c33d --- /dev/null +++ b/arangod/Aql/ExecutionStats.cpp @@ -0,0 +1,58 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief Aql, execution statistics +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2014 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Jan Steemann +/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany +/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "Aql/ExecutionStats.h" + +using namespace triagens::aql; +using Json = triagens::basics::Json; + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief convert the statistics to JSON +//////////////////////////////////////////////////////////////////////////////// + +Json ExecutionStats::toJson () const { + Json json(Json::Array); + json.set("writesExecuted", Json(static_cast(writesExecuted))); + json.set("writesIgnored", Json(static_cast(writesIgnored))); + + return json; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + +// Local Variables: +// mode: outline-minor +// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" +// End: diff --git a/arangod/Aql/ExecutionStats.h b/arangod/Aql/ExecutionStats.h new file mode 100644 index 0000000000..0791615f8e --- /dev/null +++ b/arangod/Aql/ExecutionStats.h @@ -0,0 +1,73 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief Aql, execution statistics +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2014 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Jan Steemann +/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany +/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef ARANGODB_AQL_EXECUTION_STATS_H +#define ARANGODB_AQL_EXECUTION_STATS_H 1 + +#include "Basics/Common.h" +#include "Basics/JsonHelper.h" + +namespace triagens { + namespace aql { + + struct ExecutionStats { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief convert the statistics to JSON +//////////////////////////////////////////////////////////////////////////////// + + triagens::basics::Json toJson () const; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief counter for successfully executed write operations +//////////////////////////////////////////////////////////////////////////////// + + int64_t writesExecuted = 0; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief counter for ignored write operations (ignore due to errors) +//////////////////////////////////////////////////////////////////////////////// + + int64_t writesIgnored = 0; + + }; + + } +} + +#endif + +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + +// Local Variables: +// mode: outline-minor +// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" +// End: diff --git a/arangod/Aql/Query.cpp b/arangod/Aql/Query.cpp index d81942a2a4..5b58a18eee 100644 --- a/arangod/Aql/Query.cpp +++ b/arangod/Aql/Query.cpp @@ -248,6 +248,7 @@ QueryResult Query::execute () { plan = opt.stealBest(); // Now we own the best one again triagens::basics::Json json(triagens::basics::Json::List); + triagens::basics::Json stats; try { auto engine = ExecutionEngine::instanciateFromPlan(&trx, plan); @@ -268,6 +269,8 @@ QueryResult Query::execute () { delete value; } + stats = engine->_stats.toJson(); + delete engine; } catch (...) { @@ -284,7 +287,8 @@ QueryResult Query::execute () { trx.commit(); QueryResult result(TRI_ERROR_NO_ERROR); - result.json = json.steal(); + result.json = json.steal(); + result.stats = stats.steal(); return result; } catch (triagens::arango::Exception const& ex) { diff --git a/arangod/Aql/QueryResult.h b/arangod/Aql/QueryResult.h index 0ee6e94ed8..e7617dc64b 100644 --- a/arangod/Aql/QueryResult.h +++ b/arangod/Aql/QueryResult.h @@ -47,8 +47,11 @@ namespace triagens { code = other.code; details = other.details; json = other.json; + stats = other.stats; zone = other.zone; + other.json = nullptr; + other.stats = nullptr; } QueryResult (int code, @@ -56,27 +59,25 @@ namespace triagens { : code(code), details(details), zone(TRI_UNKNOWN_MEM_ZONE), - json(nullptr) { + json(nullptr), + stats(nullptr) { } explicit QueryResult (int code) - : code(code), - details(""), - zone(TRI_UNKNOWN_MEM_ZONE), - json(nullptr) { + : QueryResult(code, "") { } QueryResult () - : code(TRI_ERROR_NO_ERROR), - details(), - zone(TRI_UNKNOWN_MEM_ZONE), - json(nullptr) { + : QueryResult(TRI_ERROR_NO_ERROR) { } ~QueryResult () { if (json != nullptr) { TRI_FreeJson(zone, json); } + if (stats != nullptr) { + TRI_FreeJson(zone, stats); + } } int code; @@ -85,6 +86,7 @@ namespace triagens { std::vector collectionNames; TRI_memory_zone_t* zone; TRI_json_t* json; + TRI_json_t* stats; }; } diff --git a/arangod/CMakeLists.txt b/arangod/CMakeLists.txt index 6fe93b464e..0d88d71b62 100644 --- a/arangod/CMakeLists.txt +++ b/arangod/CMakeLists.txt @@ -66,6 +66,7 @@ add_executable( Aql/ExecutionEngine.cpp Aql/ExecutionNode.cpp Aql/ExecutionPlan.cpp + Aql/ExecutionStats.cpp Aql/Expression.cpp Aql/Function.cpp Aql/grammar.cpp diff --git a/arangod/Makefile.files b/arangod/Makefile.files index 9c703ae340..184bbb6cbf 100644 --- a/arangod/Makefile.files +++ b/arangod/Makefile.files @@ -47,6 +47,7 @@ arangod_libarangod_a_SOURCES = \ arangod/Aql/ExecutionEngine.cpp \ arangod/Aql/ExecutionNode.cpp \ arangod/Aql/ExecutionPlan.cpp \ + arangod/Aql/ExecutionStats.cpp \ arangod/Aql/Expression.cpp \ arangod/Aql/Function.cpp \ arangod/Aql/grammar.cpp \ diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index ba77a915de..2f4768293a 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -1063,6 +1063,9 @@ static v8::Handle JS_ExecuteAql (v8::Arguments const& argv) { if (queryResult.json != nullptr) { result->Set(TRI_V8_STRING("json"), TRI_ObjectJson(queryResult.json)); } + if (queryResult.stats != nullptr) { + result->Set(TRI_V8_STRING("stats"), TRI_ObjectJson(queryResult.stats)); + } return scope.Close(result); }