From 48c5ff938e7e3b25ba2cad6986b1b4872effe91d Mon Sep 17 00:00:00 2001 From: Willi Goesgens Date: Mon, 6 Oct 2014 14:15:41 +0200 Subject: [PATCH 1/6] If we clone an ExecutionNode for the same AST we also have to copy the evaluation members, but we don't need a deep-copy. --- arangod/Aql/ExecutionNode.cpp | 23 ++++++++++++++--------- arangod/Aql/ExecutionNode.h | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/arangod/Aql/ExecutionNode.cpp b/arangod/Aql/ExecutionNode.cpp index 2e3e1b057f..c5f19c8400 100644 --- a/arangod/Aql/ExecutionNode.cpp +++ b/arangod/Aql/ExecutionNode.cpp @@ -347,7 +347,7 @@ void ExecutionNode::CloneHelper (ExecutionNode *other, other->_varUsageValid = _varUsageValid; auto allVars = plan->getAst()->variables(); - + // Create new structures on the new AST... other->_varsUsedLater.reserve(_varsUsedLater.size()); for (auto orgVar: _varsUsedLater) { other->_varsUsedLater.insert(allVars->getVariable(orgVar->id)); @@ -362,6 +362,12 @@ void ExecutionNode::CloneHelper (ExecutionNode *other, other->_varOverview = othervarOverview; } } + else { + // point to current AST -> don't do deep copies. + other->_varsUsedLater = _varsUsedLater; + other->_varsValid = _varsValid; + other->_varOverview = _varOverview; + } if (withDependencies) { cloneDependencies(plan, other, withProperties); } @@ -700,15 +706,14 @@ void ExecutionNode::planRegisters (ExecutionNode* super) { v.reset(new VarOverview(*(super->_varOverview), super->_depth)); } v->setSharedPtr(&v); -// if (!_varUsageValid) { - walk(v.get()); + + walk(v.get()); // Now handle the subqueries: - for (auto s : v->subQueryNodes) { - auto sq = static_cast(s); - sq->getSubquery()->planRegisters(s); - } - v->reset(); -// } + for (auto s : v->subQueryNodes) { + auto sq = static_cast(s); + sq->getSubquery()->planRegisters(s); + } + v->reset(); // Just for debugging: /* diff --git a/arangod/Aql/ExecutionNode.h b/arangod/Aql/ExecutionNode.h index f9e9b76180..288d007ce6 100644 --- a/arangod/Aql/ExecutionNode.h +++ b/arangod/Aql/ExecutionNode.h @@ -573,7 +573,7 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// VarOverview const* getVarOverview () const { - TRI_ASSERT(_varOverview != nullptr); + TRI_ASSERT(_varOverview.get() != nullptr); return _varOverview.get(); } From 53f38b5c0a41dae7ec8b0a9541f347daf36ea3a8 Mon Sep 17 00:00:00 2001 From: Thomas Schmidts Date: Mon, 6 Oct 2014 14:23:36 +0200 Subject: [PATCH 2/6] AQL Graph Operations now have the right options. This fixes #1019 --- js/server/modules/org/arangodb/ahuacatl.js | 33 +++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/js/server/modules/org/arangodb/ahuacatl.js b/js/server/modules/org/arangodb/ahuacatl.js index 9ccfd6613f..ddfb8643f1 100644 --- a/js/server/modules/org/arangodb/ahuacatl.js +++ b/js/server/modules/org/arangodb/ahuacatl.js @@ -5556,8 +5556,6 @@ function GRAPH_TRAVERSAL (vertexCollection, /// `GRAPH_TRAVERSAL (graphName, startVertexExample, direction, options)` /// /// This function performs traversals on the given graph. -/// For a more detailed documentation on the optional parameters see -/// [Traversals](../Traversals/README.md). /// /// The complexity of this function strongly depends on the usage. /// @@ -5567,8 +5565,31 @@ function GRAPH_TRAVERSAL (vertexCollection, /// vertices (see [example](#short_explanation_of_the_example_parameter)). /// * *direction* : The direction of the edges as a string. Possible values /// are *outbound*, *inbound* and *any* (default). -/// * *options* (optional) : Object containing optional options, see -/// [Traversals](../Traversals/README.md): +/// * *options*: Object containing optional options. +/// +/// *Options*: +/// +/// * *strategy*: determines the visitation strategy. Possible values are +/// *depthfirst* and *breadthfirst*. Default is *breadthfirst*. +/// * *order*: determines the visitation order. Possible values are +/// *preorder* and *postorder*. +/// * *itemOrder*: determines the order in which connections returned by the +/// expander will be processed. Possible values are *forward* and *backward*. +/// * *maxDepth*: if set to a value greater than *0*, this will limit the +/// traversal to this maximum depth. +/// * *minDepth*: if set to a value greater than *0*, all vertices found on +/// a level below the *minDepth* level will not be included in the result. +/// * *maxIterations*: the maximum number of iterations that the traversal is +/// allowed to perform. It is sensible to set this number so unbounded traversals +/// will terminate at some point. +/// * *uniqueness*: an object that defines how repeated visitations of vertices should +/// be handled. The *uniqueness* object can have a sub-attribute *vertices*, and a +/// sub-attribute *edges*. Each sub-attribute can have one of the following values: +/// * *"none"*: no uniqueness constraints +/// * *"path"*: element is excluded if it is already contained in the current path. +/// This setting may be sensible for graphs that contain cycles (e.g. A -> B -> C -> A). +/// * *"global"*: element is excluded if it was already found/visited at any +/// point during the traversal. /// /// @EXAMPLES /// @@ -5746,8 +5767,6 @@ function GENERAL_GRAPH_DISTANCE_TO (graphName, /// This function creates a tree format from the result for a better visualization of /// the path. /// This function performs traversals on the given graph. -/// For a more detailed documentation on the optional parameters see -/// [Traversals](../Traversals/README.md). /// /// The complexity of this function strongly depends on the usage. /// @@ -5761,7 +5780,7 @@ function GENERAL_GRAPH_DISTANCE_TO (graphName, /// * *connectName* : The result attribute which /// contains the connection. /// * *options* (optional) : An object containing options, see -/// [Traversals](../Traversals/README.md): +/// [Graph Traversals](../AQL/GraphOperations.html#graph_traversal): /// /// @EXAMPLES /// From b528531187e66e93fd0691043688c45c11ab2f13 Mon Sep 17 00:00:00 2001 From: Thomas Schmidts Date: Mon, 6 Oct 2014 15:06:50 +0200 Subject: [PATCH 3/6] Added note that by-example-hash is used internally. Fixed #984 --- js/actions/api-simple.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/actions/api-simple.js b/js/actions/api-simple.js index da321546de..acc5aff119 100644 --- a/js/actions/api-simple.js +++ b/js/actions/api-simple.js @@ -46,6 +46,8 @@ var API = "_api/simple/"; /// /// @RESTHEADER{PUT /_api/simple/by-example-hash, Hash index} /// +/// **Note**: This is only used internally and should not be accesible by the user. +/// /// @RESTBODYPARAM{query,string,required} /// Contains the query specification. /// @@ -93,6 +95,8 @@ var API = "_api/simple/"; /// /// @RESTHEADER{PUT /_api/simple/by-example-skiplist, Skiplist index} /// +/// **Note**: This is only used internally and should not be accesible by the user. +/// /// @RESTBODYPARAM{query,string,required} /// Contains the query specification. /// From 0f83d8132f82f289243ef430924eab36a27e4313 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 6 Oct 2014 18:39:01 +0200 Subject: [PATCH 4/6] fixed some transaction threading errors --- arangod/Aql/ExecutionEngine.cpp | 20 ++++++++----- arangod/Aql/ExecutionNode.cpp | 11 +++++-- arangod/Aql/ExecutionNode.h | 2 +- arangod/Aql/ExecutionPlan.cpp | 5 ++-- arangod/Aql/Query.cpp | 43 +++++++--------------------- arangod/Aql/Query.h | 12 -------- arangod/Aql/RestAqlHandler.cpp | 16 +++++++++-- arangod/Aql/VariableGenerator.cpp | 3 +- arangod/Utils/AqlTransaction.h | 2 ++ arangod/Utils/V8TransactionContext.h | 10 +++++++ lib/V8/v8-globals.cpp | 4 +-- 11 files changed, 62 insertions(+), 66 deletions(-) diff --git a/arangod/Aql/ExecutionEngine.cpp b/arangod/Aql/ExecutionEngine.cpp index 051e65e47f..2c899c14da 100644 --- a/arangod/Aql/ExecutionEngine.cpp +++ b/arangod/Aql/ExecutionEngine.cpp @@ -324,6 +324,13 @@ struct CoordinatorInstanciator : public WalkerWorker { auto* newPlan = new ExecutionPlan(otherQuery->ast()); otherQuery->setPlan(newPlan); + + // clone all variables + for (auto it2 : query->ast()->variables()->variables(true)) { + auto var = query->ast()->variables()->getVariable(it2.first); + TRI_ASSERT(var != nullptr); + otherQuery->ast()->variables()->createVariable(var); + } ExecutionNode const* current = (*it).nodes.front(); ExecutionNode* previous = nullptr; @@ -364,8 +371,7 @@ struct CoordinatorInstanciator : public WalkerWorker { // create a remote id for the engine that we can pass to // the plans to be created for the DBServers id = TRI_NewTickServer(); - -std::cout << "REGISTERING QUERY ON COORDINATOR WITH ID: " << id << "\n"; + queryRegistry->insert(otherQuery->vocbase(), id, otherQuery, 3600.0); } } @@ -494,7 +500,7 @@ std::cout << "REGISTERING QUERY ON COORDINATOR WITH ID: " << id << "\n"; result.set("options", options); std::unique_ptr body(new std::string(triagens::basics::JsonHelper::toString(result.json()))); - std::cout << "GENERATED A PLAN FOR THE REMOTE SERVERS: " << *(body.get()) << "\n"; + // std::cout << "GENERATED A PLAN FOR THE REMOTE SERVERS: " << *(body.get()) << "\n"; // TODO: pass connectedId to the shard so it can fetch data using the correct query id auto headers = new std::map; @@ -536,18 +542,18 @@ std::cout << "REGISTERING QUERY ON COORDINATOR WITH ID: " << id << "\n"; triagens::basics::Json response(TRI_UNKNOWN_MEM_ZONE, triagens::basics::JsonHelper::fromString(res->answer->body())); std::string queryId = triagens::basics::JsonHelper::getStringValue(response.json(), "queryId", ""); - std::cout << "DB SERVER ANSWERED WITHOUT ERROR: " << res->answer->body() << ", SHARDID:" << res->shardID << ", QUERYID: " << queryId << "\n"; + // std::cout << "DB SERVER ANSWERED WITHOUT ERROR: " << res->answer->body() << ", SHARDID:" << res->shardID << ", QUERYID: " << queryId << "\n"; queryIds.emplace(std::make_pair(res->shardID, queryId)); } else { - std::cout << "DB SERVER ANSWERED WITH ERROR: " << res->answer->body() << "\n"; + // std::cout << "DB SERVER ANSWERED WITH ERROR: " << res->answer->body() << "\n"; } } delete res; } - std::cout << "GOT ALL RESPONSES FROM DB SERVERS: " << nrok << "\n"; + // std::cout << "GOT ALL RESPONSES FROM DB SERVERS: " << nrok << "\n"; if (nrok != (int) shardIds.size()) { // TODO: provide sensible error message with more details @@ -701,8 +707,8 @@ ExecutionEngine* ExecutionEngine::instanciateFromPlan (QueryRegistry* queryRegis try { if (! plan->varUsageComputed()) { plan->findVarUsage(); + plan->planRegisters(); } - plan->planRegisters(); ExecutionBlock* root = nullptr; diff --git a/arangod/Aql/ExecutionNode.cpp b/arangod/Aql/ExecutionNode.cpp index 619188fec9..56ff8562e3 100644 --- a/arangod/Aql/ExecutionNode.cpp +++ b/arangod/Aql/ExecutionNode.cpp @@ -339,7 +339,7 @@ triagens::basics::Json ExecutionNode::toJson (TRI_memory_zone_t* zone, /// @brief execution Node clone utility to be called by derives //////////////////////////////////////////////////////////////////////////////// -void ExecutionNode::CloneHelper (ExecutionNode *other, +void ExecutionNode::CloneHelper (ExecutionNode* other, ExecutionPlan* plan, bool withDependencies, bool withProperties) const { @@ -352,12 +352,16 @@ void ExecutionNode::CloneHelper (ExecutionNode *other, // Create new structures on the new AST... other->_varsUsedLater.reserve(_varsUsedLater.size()); for (auto orgVar: _varsUsedLater) { - other->_varsUsedLater.insert(allVars->getVariable(orgVar->id)); + auto var = allVars->getVariable(orgVar->id); + TRI_ASSERT(var != nullptr); + other->_varsUsedLater.insert(var); } other->_varsValid.reserve(_varsValid.size()); for (auto orgVar: _varsValid) { - other->_varsValid.insert(allVars->getVariable(orgVar->id)); + auto var = allVars->getVariable(orgVar->id); + TRI_ASSERT(var != nullptr); + other->_varsValid.insert(var); } if (_varOverview.get() != nullptr) { auto othervarOverview = std::shared_ptr(_varOverview->clone(plan)); @@ -1008,6 +1012,7 @@ ExecutionNode* EnumerateCollectionNode::clone (ExecutionPlan* plan, auto outVariable = _outVariable; if (withProperties) { outVariable = plan->getAst()->variables()->createVariable(outVariable); + TRI_ASSERT(outVariable != nullptr); } auto c = new EnumerateCollectionNode(plan, _id, _vocbase, _collection, outVariable); diff --git a/arangod/Aql/ExecutionNode.h b/arangod/Aql/ExecutionNode.h index b4c2d7fcc6..6801ed1cf8 100644 --- a/arangod/Aql/ExecutionNode.h +++ b/arangod/Aql/ExecutionNode.h @@ -2955,7 +2955,7 @@ namespace triagens { bool withProperties) const { auto c = new ScatterNode(plan, _id, _vocbase, _collection); - CloneHelper (c, plan, withDependencies, withProperties); + CloneHelper(c, plan, withDependencies, withProperties); return static_cast(c); } diff --git a/arangod/Aql/ExecutionPlan.cpp b/arangod/Aql/ExecutionPlan.cpp index f4f475409b..adb23074c8 100644 --- a/arangod/Aql/ExecutionPlan.cpp +++ b/arangod/Aql/ExecutionPlan.cpp @@ -140,8 +140,8 @@ ExecutionPlan* ExecutionPlan::instanciateFromJson (Ast* ast, } } -ExecutionPlan* ExecutionPlan::clone (Query &onThatQuery) { - ExecutionPlan *OtherPlan = new ExecutionPlan(onThatQuery.ast()); +ExecutionPlan* ExecutionPlan::clone (Query& onThatQuery) { + ExecutionPlan* OtherPlan = new ExecutionPlan(onThatQuery.ast()); for (auto it: _ids) { OtherPlan->registerNode(it.second->clone(OtherPlan, false, true)); @@ -985,7 +985,6 @@ void ExecutionPlan::checkLinkage () { //////////////////////////////////////////////////////////////////////////////// struct VarUsageFinder : public WalkerWorker { - std::unordered_set _usedLater; std::unordered_set _valid; std::unordered_map _varSetBy; diff --git a/arangod/Aql/Query.cpp b/arangod/Aql/Query.cpp index 9ed5d9de20..fa29c82da5 100644 --- a/arangod/Aql/Query.cpp +++ b/arangod/Aql/Query.cpp @@ -242,6 +242,13 @@ Query* Query::clone (QueryPart part) { if (_plan != nullptr) { theClone->_plan = _plan->clone(*theClone); + + // clone all variables + for (auto it : _ast->variables()->variables(true)) { + auto var = _ast->variables()->getVariable(it.first); + TRI_ASSERT(var != nullptr); + theClone->ast()->variables()->createVariable(var); + } } theClone->_trx = _trx; @@ -365,9 +372,6 @@ QueryResult Query::prepare (QueryRegistry* registry) { std::shared_ptr trx(new AQL_TRANSACTION_V8(_vocbase, _collections.collections())); _trx = trx; - // create the transaction object, but do not start it yet - // _trx = new std::shared_ptr(_vocbase, _collections.collections()); - if (_queryString != nullptr) { // we have an AST int res = _trx->begin(); @@ -527,35 +531,6 @@ QueryResult Query::execute (QueryRegistry* registry) { } } -//////////////////////////////////////////////////////////////////////////////// -/// @brief close transaction to suspend query -//////////////////////////////////////////////////////////////////////////////// - -#if 0 -int Query::closeTransaction () { - TRI_ASSERT(_trx != nullptr); - _trx->commit(); - delete _trx; - _trx = nullptr; - return TRI_ERROR_NO_ERROR; -} -#endif - -//////////////////////////////////////////////////////////////////////////////// -/// @brief reopen transaction after suspend of query -//////////////////////////////////////////////////////////////////////////////// - -#if 0 -int Query::reOpenTransaction () { - TRI_ASSERT(_trx == nullptr); - _trx = new AQL_TRANSACTION_V8(_vocbase, _collections.collections()); - if (_trx == nullptr) { - return TRI_ERROR_INTERNAL; - } - return _trx->begin(); -} -#endif - //////////////////////////////////////////////////////////////////////////////// /// @brief parse an AQL query //////////////////////////////////////////////////////////////////////////////// @@ -594,7 +569,7 @@ QueryResult Query::explain () { // std::cout << "AST: " << triagens::basics::JsonHelper::toString(parser.ast()->toJson(TRI_UNKNOWN_MEM_ZONE)) << "\n"; // create the transaction object, but do not start it yet - std::shared_ptr trx(new AQL_TRANSACTION_V8(_vocbase, _collections.collections())); + std::shared_ptr trx(new AQL_TRANSACTION_V8(_vocbase, _collections.collections())); _trx = trx; // we have an AST @@ -631,6 +606,7 @@ QueryResult Query::explain () { TRI_ASSERT(it != nullptr); it->findVarUsage(); + it->planRegisters(); out.add(it->toJson(parser.ast(), TRI_UNKNOWN_MEM_ZONE, verbosePlans())); } @@ -641,6 +617,7 @@ QueryResult Query::explain () { plan = opt.stealBest(); // Now we own the best one again TRI_ASSERT(plan != nullptr); plan->findVarUsage(); + plan->planRegisters(); result.json = plan->toJson(parser.ast(), TRI_UNKNOWN_MEM_ZONE, verbosePlans()).steal(); delete plan; diff --git a/arangod/Aql/Query.h b/arangod/Aql/Query.h index 099367f9be..5abde636b1 100644 --- a/arangod/Aql/Query.h +++ b/arangod/Aql/Query.h @@ -406,18 +406,6 @@ namespace triagens { void cleanupPlanAndEngine (); -//////////////////////////////////////////////////////////////////////////////// -/// @brief close transaction to suspend query -//////////////////////////////////////////////////////////////////////////////// - - // int closeTransaction (); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief reopen transaction after suspend of query -//////////////////////////////////////////////////////////////////////////////// - - // int reOpenTransaction (); - // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- diff --git a/arangod/Aql/RestAqlHandler.cpp b/arangod/Aql/RestAqlHandler.cpp index efd581457e..35132e3198 100644 --- a/arangod/Aql/RestAqlHandler.cpp +++ b/arangod/Aql/RestAqlHandler.cpp @@ -163,7 +163,7 @@ void RestAqlHandler::createQueryFromJson () { answerBody("queryId", Json(StringUtils::itoa(_qId))) ("ttl", Json(ttl)); -// std::cout << "RESPONSE BODY IS: " << answerBody.toString() << "\n"; + //std::cout << "RESPONSE BODY IS: " << answerBody.toString() << "\n"; _response->body().appendText(answerBody.toString()); } @@ -588,6 +588,12 @@ triagens::rest::HttpHandler::status_t RestAqlHandler::execute () { auto context = _applicationV8->enterContext("STANDARD", _vocbase, false, false); + + // assert that everything is cleaned up when we enter the context + TRI_v8_global_t* v8g = static_cast(context->_isolate->GetData()); + TRI_ASSERT(v8g->_currentTransaction == nullptr); + TRI_ASSERT(v8g->_resolver == nullptr); + if (nullptr == context) { generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL, "cannot enter V8 context"); @@ -661,9 +667,13 @@ triagens::rest::HttpHandler::status_t RestAqlHandler::execute () { } } + + // must have cleaned everything up + TRI_ASSERT(v8g->_currentTransaction == nullptr); + TRI_ASSERT(v8g->_resolver == nullptr); _applicationV8->exitContext(context); -// std::cout << "REQUEST HANDLING DONE: " << triagens::arango::ServerState::instance()->getId() << ": " << _request->fullUrl() << ": " << _response->responseCode() << ", CONTENT-LENGTH: " << _response->contentLength() << "\n"; +//std::cout << "REQUEST HANDLING DONE: " << triagens::arango::ServerState::instance()->getId() << ": " << _request->fullUrl() << ": " << _response->responseCode() << ", CONTENT-LENGTH: " << _response->contentLength() << "\n"; return status_t(HANDLER_DONE); } @@ -741,7 +751,7 @@ void RestAqlHandler::handleUseQuery (std::string const& operation, else { try { answerBody = items->toJson(query->trx()); -// std::cout << "ANSWERBODY: " << JsonHelper::toString(answerBody.json()) << "\n\n"; +//std::cout << "ANSWERBODY: " << JsonHelper::toString(answerBody.json()) << "\n\n"; } catch (...) { generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_HTTP_SERVER_ERROR, diff --git a/arangod/Aql/VariableGenerator.cpp b/arangod/Aql/VariableGenerator.cpp index e7814e68db..02963edd62 100644 --- a/arangod/Aql/VariableGenerator.cpp +++ b/arangod/Aql/VariableGenerator.cpp @@ -222,9 +222,8 @@ triagens::basics::Json VariableGenerator::toJson (TRI_memory_zone_t* zone) const //////////////////////////////////////////////////////////////////////////////// void VariableGenerator::fromJson (Json const& query) { - Json jsonAllVariablesList = query.get("variables"); - if (!jsonAllVariablesList.isList()) { + if (! jsonAllVariablesList.isList()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "variables needs to be a list"); } diff --git a/arangod/Utils/AqlTransaction.h b/arangod/Utils/AqlTransaction.h index ef16296683..69295d52a3 100644 --- a/arangod/Utils/AqlTransaction.h +++ b/arangod/Utils/AqlTransaction.h @@ -166,6 +166,8 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// int registerTransactionWithContext () { + // modify the v8g globals to match the globals of the current isolate / thread + this->setV8Globals(static_cast(v8::Isolate::GetCurrent()->GetData())); // This calls the method in the V8TransactionContext return this->registerTransaction(this->_trx); } diff --git a/arangod/Utils/V8TransactionContext.h b/arangod/Utils/V8TransactionContext.h index 1185671c1e..b2ec9a419b 100644 --- a/arangod/Utils/V8TransactionContext.h +++ b/arangod/Utils/V8TransactionContext.h @@ -77,6 +77,16 @@ namespace triagens { public: +//////////////////////////////////////////////////////////////////////////////// +/// @brief set the thread-specific pointer to the v8 globals +/// it is necessary to update this pointer if the same transaction is going to +/// be used in multiple requests / threads +//////////////////////////////////////////////////////////////////////////////// + + inline void setV8Globals (TRI_v8_global_t* v8g) { + _v8g = v8g; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief return the resolver //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/V8/v8-globals.cpp b/lib/V8/v8-globals.cpp index 5f7c4e79d4..cfb7e408f8 100644 --- a/lib/V8/v8-globals.cpp +++ b/lib/V8/v8-globals.cpp @@ -224,8 +224,8 @@ TRI_v8_global_s::~TRI_v8_global_s () { /// @brief creates a global context //////////////////////////////////////////////////////////////////////////////// -TRI_v8_global_t* TRI_CreateV8Globals(v8::Isolate* isolate) { - TRI_v8_global_t* v8g = (TRI_v8_global_t*) isolate->GetData(); +TRI_v8_global_t* TRI_CreateV8Globals (v8::Isolate* isolate) { + TRI_v8_global_t* v8g = static_cast(isolate->GetData()); if (v8g == nullptr) { v8g = new TRI_v8_global_t(isolate); From a62d83603e2e5784bdce4110d48b7f422de847ce Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 6 Oct 2014 18:43:50 +0200 Subject: [PATCH 5/6] fixed missing register planning --- arangod/Aql/ExecutionEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arangod/Aql/ExecutionEngine.cpp b/arangod/Aql/ExecutionEngine.cpp index 2c899c14da..1c4f9c401e 100644 --- a/arangod/Aql/ExecutionEngine.cpp +++ b/arangod/Aql/ExecutionEngine.cpp @@ -707,8 +707,8 @@ ExecutionEngine* ExecutionEngine::instanciateFromPlan (QueryRegistry* queryRegis try { if (! plan->varUsageComputed()) { plan->findVarUsage(); - plan->planRegisters(); } + plan->planRegisters(); ExecutionBlock* root = nullptr; From 41e215ba0ddba9dccea153d311e1498f35b36e52 Mon Sep 17 00:00:00 2001 From: Willi Goesgens Date: Tue, 7 Oct 2014 09:23:59 +0200 Subject: [PATCH 6/6] Add count of how many tests failed to the summary. --- js/server/modules/org/arangodb/testing.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/js/server/modules/org/arangodb/testing.js b/js/server/modules/org/arangodb/testing.js index 8914574223..d70b0fed6e 100644 --- a/js/server/modules/org/arangodb/testing.js +++ b/js/server/modules/org/arangodb/testing.js @@ -1114,6 +1114,8 @@ function unitTestPrettyPrintResults(r) { var testrun; var test; var oneTest; + var testFail = 0; + var testSuiteFail = 0; try { for (testrun in r) { @@ -1125,6 +1127,7 @@ function unitTestPrettyPrintResults(r) { print(" " + test + ": Success"); } else { + testSuiteFail += 1; if (r[testrun][test].hasOwnProperty('message')) { print(" " + test + ": Fail - Whole testsuite failed!"); if (typeof r[testrun][test].message === "object" && @@ -1141,6 +1144,7 @@ function unitTestPrettyPrintResults(r) { if ((r[testrun][test].hasOwnProperty(oneTest)) && (internalMembers.indexOf(oneTest) === -1) && (!r[testrun][test][oneTest].status)) { + testFail =+ 1; print(" -> " + oneTest + " Failed; Verbose message:"); print(r[testrun][test][oneTest].message); } @@ -1152,6 +1156,9 @@ function unitTestPrettyPrintResults(r) { } } print("Overall state: " + ((r.all_ok === true) ? "Success" : "Fail")); + if ((r.all_ok !== true) { + print(" Suites failed: " + testSuiteFail + " Tests Failed: " + testFail); + } } catch (x) { print("exception caught while pretty printing result: ");