1
0
Fork 0

blind commit of work, as I managed to break my local git repository (#5456)

This commit is contained in:
Jan 2018-05-25 13:07:28 +02:00 committed by GitHub
parent c31c07ccaa
commit f55df6786a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 187 additions and 529 deletions

View File

@ -231,7 +231,6 @@ void AqlItemBlock::shrink(size_t nrItems) {
void AqlItemBlock::rescale(size_t nrItems, RegisterId nrRegs) {
TRI_ASSERT(_valueCount.empty());
TRI_ASSERT(nrRegs > 0);
TRI_ASSERT(nrRegs <= ExecutionNode::MaxRegisterId);
size_t const targetSize = nrItems * nrRegs;

View File

@ -28,42 +28,30 @@
#include "VocBase/vocbase.h"
using namespace arangodb::aql;
void SingletonBlock::deleteInputVariables() {
delete _inputRegisterValues;
_inputRegisterValues = nullptr;
}
void SingletonBlock::buildWhitelist() {
if (!_whitelistBuilt) {
auto en = ExecutionNode::castTo<SingletonNode const*>(getPlanNode());
auto const& registerPlan = en->getRegisterPlan()->varInfo;
std::unordered_set<Variable const*> const& varsUsedLater = en->getVarsUsedLater();
SingletonBlock::SingletonBlock(ExecutionEngine* engine, SingletonNode const* ep)
: ExecutionBlock(engine, ep) {
auto en = ExecutionNode::castTo<SingletonNode const*>(getPlanNode());
auto const& registerPlan = en->getRegisterPlan()->varInfo;
std::unordered_set<Variable const*> const& varsUsedLater = en->getVarsUsedLater();
for (auto const& it : varsUsedLater) {
auto it2 = registerPlan.find(it->id);
for (auto const& it : varsUsedLater) {
auto it2 = registerPlan.find(it->id);
if (it2 != registerPlan.end()) {
_whitelist.emplace((*it2).second.registerId);
}
if (it2 != registerPlan.end()) {
_whitelist.emplace((*it2).second.registerId);
}
}
_whitelistBuilt = true;
}
/// @brief initializeCursor, store a copy of the register values coming from
/// above
int SingletonBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
DEBUG_BEGIN_BLOCK();
// Create a deep copy of the register values given to us:
deleteInputVariables();
if (items != nullptr) {
// build a whitelist with all the registers that we will copy from above
buildWhitelist();
deleteInputVariables();
TRI_ASSERT(_whitelistBuilt);
_inputRegisterValues = items->slice(pos, _whitelist);
_inputRegisterValues.reset(items->slice(pos, _whitelist));
}
_done = false;
@ -75,11 +63,8 @@ int SingletonBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
/// @brief shutdown the singleton block
int SingletonBlock::shutdown(int errorCode) {
int res = ExecutionBlock::shutdown(errorCode);
deleteInputVariables();
return res;
_inputRegisterValues.reset();
return ExecutionBlock::shutdown(errorCode);
}
int SingletonBlock::getOrSkipSome(size_t atMost, bool skipping,
@ -96,9 +81,6 @@ int SingletonBlock::getOrSkipSome(size_t atMost, bool skipping,
try {
if (_inputRegisterValues != nullptr) {
buildWhitelist();
TRI_ASSERT(_whitelistBuilt);
skipped++;
for (RegisterId reg = 0; reg < _inputRegisterValues->getNrRegs();
++reg) {

View File

@ -37,15 +37,7 @@ class ExecutionEngine;
class SingletonBlock final : public ExecutionBlock {
public:
SingletonBlock(ExecutionEngine* engine, SingletonNode const* ep)
: ExecutionBlock(engine, ep), _inputRegisterValues(nullptr), _whitelistBuilt(false) {}
~SingletonBlock() { deleteInputVariables(); }
int initialize() override final {
deleteInputVariables();
return ExecutionBlock::initialize();
}
SingletonBlock(ExecutionEngine* engine, SingletonNode const* ep);
/// @brief initializeCursor, store a copy of the register values coming from
/// above
@ -56,19 +48,13 @@ class SingletonBlock final : public ExecutionBlock {
bool hasMore() override final { return !_done; }
private:
void deleteInputVariables();
void buildWhitelist();
int getOrSkipSome(size_t atMost, bool skipping,
AqlItemBlock*& result, size_t& skipped) override;
/// @brief _inputRegisterValues
AqlItemBlock* _inputRegisterValues;
std::unique_ptr<AqlItemBlock> _inputRegisterValues;
std::unordered_set<RegisterId> _whitelist;
bool _whitelistBuilt;
};
class FilterBlock final : public ExecutionBlock {
@ -110,13 +96,12 @@ class LimitBlock final : public ExecutionBlock {
_state(0), // start in the beginning
_fullCount(ep->_fullCount) {}
~LimitBlock() {}
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
virtual int getOrSkipSome(size_t atMost, bool skipping,
AqlItemBlock*& result, size_t& skipped) override;
int getOrSkipSome(size_t atMost, bool skipping,
AqlItemBlock*& result, size_t& skipped) override;
private:
/// @brief _offset
size_t _offset;
@ -138,8 +123,6 @@ class ReturnBlock final : public ExecutionBlock {
ReturnBlock(ExecutionEngine* engine, ReturnNode const* ep)
: ExecutionBlock(engine, ep), _returnInheritedResults(false) {}
~ReturnBlock() {}
/// @brief getSome
AqlItemBlock* getSome(size_t atMost) override final;
@ -161,8 +144,6 @@ class NoResultsBlock final : public ExecutionBlock {
NoResultsBlock(ExecutionEngine* engine, ExecutionNode const* ep)
: ExecutionBlock(engine, ep) {}
~NoResultsBlock() {}
/// @brief initializeCursor, store a copy of the register values coming from
/// above
int initializeCursor(AqlItemBlock* items, size_t pos) override final;

View File

@ -58,6 +58,7 @@ using StringBuffer = arangodb::basics::StringBuffer;
GatherBlock::GatherBlock(ExecutionEngine* engine, GatherNode const* en)
: ExecutionBlock(engine, en),
_atDep(0),
_sortRegisters(),
_isSimple(en->elements().empty()),
_heap(en->_sortmode == 'h' ? new Heap : nullptr) {
@ -87,16 +88,6 @@ GatherBlock::~GatherBlock() {
_gatherBlockBuffer.clear();
}
/// @brief initialize
int GatherBlock::initialize() {
DEBUG_BEGIN_BLOCK();
_atDep = 0;
return ExecutionBlock::initialize();
// cppcheck-suppress style
DEBUG_END_BLOCK();
}
/// @brief shutdown: need our own method since our _buffer is different
int GatherBlock::shutdown(int errorCode) {
DEBUG_BEGIN_BLOCK();
@ -1209,71 +1200,37 @@ RemoteBlock::RemoteBlock(ExecutionEngine* engine, RemoteNode const* en,
!ownName.empty()));
}
RemoteBlock::~RemoteBlock() {}
/// @brief local helper to send a request
std::unique_ptr<ClusterCommResult> RemoteBlock::sendRequest(
arangodb::rest::RequestType type, std::string const& urlPart,
std::string const& body) const {
DEBUG_BEGIN_BLOCK();
auto cc = ClusterComm::instance();
if (cc != nullptr) {
if (cc == nullptr) {
// nullptr only happens on controlled shutdown
// Later, we probably want to set these sensibly:
ClientTransactionID const clientTransactionId = std::string("AQL");
CoordTransactionID const coordTransactionId = TRI_NewTickServer();
std::unordered_map<std::string, std::string> headers;
if (!_ownName.empty()) {
headers.emplace("Shard-Id", _ownName);
}
++_engine->_stats.httpRequests;
{
JobGuard guard(SchedulerFeature::SCHEDULER);
guard.block();
std::string const url = std::string("/_db/") +
arangodb::basics::StringUtils::urlEncode(_engine->getQuery()->trx()->vocbase().name()) +
urlPart + _queryId;
auto result =
cc->syncRequest(clientTransactionId, coordTransactionId, _server, type,
std::move(url), body, headers, defaultTimeOut);
return result;
}
}
return std::make_unique<ClusterCommResult>();
// cppcheck-suppress style
DEBUG_END_BLOCK();
}
/// @brief initialize
int RemoteBlock::initialize() {
DEBUG_BEGIN_BLOCK();
if (!_isResponsibleForInitializeCursor) {
// do nothing...
return TRI_ERROR_NO_ERROR;
return std::make_unique<ClusterCommResult>();
}
std::unique_ptr<ClusterCommResult> res =
sendRequest(rest::RequestType::PUT, "/_api/aql/initialize/", "{}");
throwExceptionAfterBadSyncRequest(res.get(), false);
// If we get here, then res->result is the response which will be
// a serialized AqlItemBlock:
StringBuffer const& responseBodyBuf(res->result->getBody());
std::shared_ptr<VPackBuilder> builder =
VPackParser::fromJson(responseBodyBuf.c_str(), responseBodyBuf.length());
VPackSlice slice = builder->slice();
if (slice.hasKey("code")) {
return slice.get("code").getNumericValue<int>();
// Later, we probably want to set these sensibly:
ClientTransactionID const clientTransactionId = std::string("AQL");
CoordTransactionID const coordTransactionId = TRI_NewTickServer();
std::unordered_map<std::string, std::string> headers;
if (!_ownName.empty()) {
headers.emplace("Shard-Id", _ownName);
}
std::string url = std::string("/_db/") +
arangodb::basics::StringUtils::urlEncode(_engine->getQuery()->trx()->vocbase().name()) +
urlPart + _queryId;
++_engine->_stats.requests;
{
JobGuard guard(SchedulerFeature::SCHEDULER);
guard.block();
return cc->syncRequest(clientTransactionId, coordTransactionId, _server, type,
std::move(url), body, headers, defaultTimeOut);
}
return TRI_ERROR_INTERNAL;
// cppcheck-suppress style
DEBUG_END_BLOCK();
@ -1288,6 +1245,12 @@ int RemoteBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
// do nothing...
return TRI_ERROR_NO_ERROR;
}
if (items == nullptr) {
// we simply ignore the initialCursor request, as the remote side
// will initialize the cursor lazily
return TRI_ERROR_NO_ERROR;
}
VPackOptions options(VPackOptions::Defaults);
options.buildUnindexedArrays = true;
@ -1295,21 +1258,15 @@ int RemoteBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
VPackBuilder builder(&options);
builder.openObject();
if (items == nullptr) {
// first call, items is still a nullptr
builder.add("exhausted", VPackValue(true));
builder.add("error", VPackValue(false));
} else {
builder.add("exhausted", VPackValue(false));
builder.add("error", VPackValue(false));
builder.add("pos", VPackValue(pos));
builder.add(VPackValue("items"));
builder.openObject();
items->toVelocyPack(_engine->getQuery()->trx(), builder);
builder.close();
}
builder.add("exhausted", VPackValue(false));
builder.add("error", VPackValue(false));
builder.add("pos", VPackValue(pos));
builder.add(VPackValue("items"));
builder.openObject();
items->toVelocyPack(_engine->getQuery()->trx(), builder);
builder.close();
builder.close();
std::string bodyString(builder.slice().toJson());

View File

@ -63,9 +63,6 @@ class GatherBlock : public ExecutionBlock {
~GatherBlock();
/// @brief initialize
int initialize() override;
/// @brief shutdown: need our own method since our _buffer is different
int shutdown(int) override final;
@ -203,8 +200,6 @@ class ScatterBlock : public BlockWithClients {
std::vector<std::string> const& shardIds)
: BlockWithClients(engine, ep, shardIds) {}
~ScatterBlock() {}
/// @brief initializeCursor
int initializeCursor(AqlItemBlock* items, size_t pos) override;
@ -230,8 +225,6 @@ class DistributeBlock : public BlockWithClients {
std::vector<std::string> const& shardIds,
Collection const* collection);
~DistributeBlock() {}
/// @brief initializeCursor
int initializeCursor(AqlItemBlock* items, size_t pos) override;
@ -297,14 +290,9 @@ class RemoteBlock final : public ExecutionBlock {
std::string const& server, std::string const& ownName,
std::string const& queryId);
~RemoteBlock();
/// @brief timeout
static double const defaultTimeOut;
/// @brief initialize
int initialize() override final;
/// @brief initializeCursor, could be called multiple times
int initializeCursor(AqlItemBlock* items, size_t pos) override final;
@ -319,7 +307,7 @@ class RemoteBlock final : public ExecutionBlock {
/// @brief hasMore
bool hasMore() override final;
private:
/// @brief internal method to send a request
std::unique_ptr<arangodb::ClusterCommResult> sendRequest(
@ -327,14 +315,14 @@ class RemoteBlock final : public ExecutionBlock {
std::string const& body) const;
/// @brief our server, can be like "shard:S1000" or like "server:Claus"
std::string _server;
std::string const _server;
/// @brief our own identity, in case of the coordinator this is empty,
/// in case of the DBservers, this is the shard ID as a string
std::string _ownName;
std::string const _ownName;
/// @brief the ID of the query on the server as a string
std::string _queryId;
std::string const _queryId;
/// @brief whether or not this block will forward initialize,
/// initializeCursor or shutDown requests

View File

@ -241,23 +241,10 @@ SortedCollectBlock::SortedCollectBlock(ExecutionEngine* engine,
}
}
}
}
SortedCollectBlock::~SortedCollectBlock() {}
/// @brief initialize
int SortedCollectBlock::initialize() {
int res = ExecutionBlock::initialize();
if (res != TRI_ERROR_NO_ERROR) {
return res;
}
// reserve space for the current row
_currentGroup.initialize(_groupRegisters.size());
_pos = 0;
return TRI_ERROR_NO_ERROR;
}
int SortedCollectBlock::initializeCursor(AqlItemBlock* items,
@ -604,8 +591,6 @@ HashedCollectBlock::HashedCollectBlock(ExecutionEngine* engine,
TRI_ASSERT(!_groupRegisters.empty());
}
HashedCollectBlock::~HashedCollectBlock() {}
int HashedCollectBlock::getOrSkipSome(size_t atMost,
bool skipping, AqlItemBlock*& result,
size_t& skipped) {
@ -874,17 +859,6 @@ DistinctCollectBlock::~DistinctCollectBlock() {
clearValues();
}
/// @brief initialize
int DistinctCollectBlock::initialize() {
int res = ExecutionBlock::initialize();
if (res != TRI_ERROR_NO_ERROR) {
return res;
}
return TRI_ERROR_NO_ERROR;
}
int DistinctCollectBlock::initializeCursor(AqlItemBlock* items,
size_t pos) {
DEBUG_BEGIN_BLOCK();

View File

@ -85,10 +85,6 @@ class SortedCollectBlock final : public ExecutionBlock {
public:
SortedCollectBlock(ExecutionEngine*, CollectNode const*);
~SortedCollectBlock();
int initialize() override final;
/// @brief initializeCursor
int initializeCursor(AqlItemBlock* items, size_t pos) override;
@ -132,7 +128,6 @@ class SortedCollectBlock final : public ExecutionBlock {
class HashedCollectBlock : public ExecutionBlock {
public:
HashedCollectBlock(ExecutionEngine*, CollectNode const*);
~HashedCollectBlock();
private:
int getOrSkipSome(size_t atMost, bool skipping,
@ -157,8 +152,6 @@ class DistinctCollectBlock : public ExecutionBlock {
DistinctCollectBlock(ExecutionEngine*, CollectNode const*);
~DistinctCollectBlock();
int initialize() override final;
/// @brief initializeCursor
int initializeCursor(AqlItemBlock* items, size_t pos) override;

View File

@ -50,10 +50,6 @@ EnumerateCollectionBlock::EnumerateCollectionBlock(
TRI_ASSERT(_cursor->ok());
buildCallback();
}
int EnumerateCollectionBlock::initialize() {
DEBUG_BEGIN_BLOCK();
if (ServerState::instance()->isRunningInCluster() && _collection->isSatellite()) {
auto logicalCollection = _collection->getCollection();
@ -90,11 +86,6 @@ int EnumerateCollectionBlock::initialize() {
"collection " + _collection->name + " did not come into sync in time (" + std::to_string(maxWait) +")");
}
}
return ExecutionBlock::initialize();
// cppcheck-suppress style
DEBUG_END_BLOCK();
}
int EnumerateCollectionBlock::initializeCursor(AqlItemBlock* items,

View File

@ -46,11 +46,6 @@ class EnumerateCollectionBlock final : public ExecutionBlock, public DocumentPro
EnumerateCollectionBlock(ExecutionEngine* engine,
EnumerateCollectionNode const* ep);
~EnumerateCollectionBlock() = default;
/// @brief initialize, here we fetch all docs from the database
int initialize() override final;
/// @brief initializeCursor
int initializeCursor(AqlItemBlock* items, size_t pos) override;

View File

@ -87,8 +87,17 @@ bool ExecutionBlock::removeDependency(ExecutionBlock* ep) {
return false;
}
/// @brief whether or not the query was killed
bool ExecutionBlock::isKilled() const { return _engine->getQuery()->killed(); }
/// @brief whether or not the query was killed
void ExecutionBlock::throwIfKilled() {
if (isKilled()) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_KILLED);
}
}
int ExecutionBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
DEBUG_BEGIN_BLOCK();
for (auto& d : _dependencies) {
int res = d->initializeCursor(items, pos);
@ -104,29 +113,6 @@ int ExecutionBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
_done = false;
return TRI_ERROR_NO_ERROR;
DEBUG_END_BLOCK();
}
/// @brief whether or not the query was killed
bool ExecutionBlock::isKilled() const { return _engine->getQuery()->killed(); }
/// @brief whether or not the query was killed
void ExecutionBlock::throwIfKilled() {
if (isKilled()) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_KILLED);
}
}
/// @brief initialize
int ExecutionBlock::initialize() {
for (auto it = _dependencies.begin(); it != _dependencies.end(); ++it) {
int res = (*it)->initialize();
if (res != TRI_ERROR_NO_ERROR) {
return res;
}
}
return TRI_ERROR_NO_ERROR;
}
/// @brief shutdown, will be called exactly once for the whole query

View File

@ -102,16 +102,7 @@ class ExecutionBlock {
/// @brief remove a dependency, returns true if the pointer was found and
/// removed, please note that this does not delete ep!
bool removeDependency(ExecutionBlock* ep);
/// @brief access the pos-th dependency
ExecutionBlock* operator[](size_t pos) {
if (pos >= _dependencies.size()) {
return nullptr;
}
return _dependencies.at(pos);
}
/// @brief Methods for execution
/// Lifecycle is:
/// CONSTRUCTOR
@ -123,8 +114,6 @@ class ExecutionBlock {
/// then the ExecutionEngine automatically calls
/// shutdown()
/// DESTRUCTOR
/// @brief initialize
virtual int initialize();
/// @brief initializeCursor, could be called multiple times
virtual int initializeCursor(AqlItemBlock* items, size_t pos);
@ -223,7 +212,7 @@ class ExecutionBlock {
/// @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;

View File

@ -181,6 +181,7 @@ ExecutionEngine::ExecutionEngine(Query* query)
_root(nullptr),
_query(query),
_resultRegister(0),
_initializeCursorCalled(false),
_wasShutdown(false),
_previouslyLockedShards(nullptr),
_lockedShards(nullptr) {
@ -582,7 +583,6 @@ ExecutionEngine* ExecutionEngine::instantiateFromPlan(
engine->_root = root;
if (plan->isResponsibleForInitialize()) {
root->initialize();
root->initializeCursor(nullptr, 0);
}

View File

@ -70,24 +70,26 @@ class ExecutionEngine {
/// @brief initializeCursor, could be called multiple times
int initializeCursor(AqlItemBlock* items, size_t pos) {
_initializeCursorCalled = true;
return _root->initializeCursor(items, pos);
}
/// @brief initialize
int initialize() {
return _root->initialize();
}
/// @brief shutdown, will be called exactly once for the whole query
int shutdown(int errorCode);
/// @brief getSome
AqlItemBlock* getSome(size_t atMost) {
if (!_initializeCursorCalled) {
initializeCursor(nullptr, 0);
}
return _root->getSome(atMost);
}
/// @brief skipSome
size_t skipSome(size_t atMost) {
if (!_initializeCursorCalled) {
initializeCursor(nullptr, 0);
}
return _root->skipSome(atMost);
}
@ -96,12 +98,18 @@ class ExecutionEngine {
/// @brief skip
bool skip(size_t number, size_t& actuallySkipped) {
if (!_initializeCursorCalled) {
initializeCursor(nullptr, 0);
}
return _root->skip(number, actuallySkipped);
}
/// @brief hasMore
inline bool hasMore() const { return _root->hasMore(); }
/// @brief whether or not initializeCursor was called
bool initializeCursorCalled() const { return _initializeCursorCalled; }
/// @brief add a block to the engine
TEST_VIRTUAL void addBlock(ExecutionBlock*);
@ -148,9 +156,12 @@ class ExecutionEngine {
/// @brief the register the final result of the query is stored in
RegisterId _resultRegister;
/// @brief whether or not initializeCursor was called
bool _initializeCursorCalled;
/// @brief whether or not shutdown() was executed
bool _wasShutdown;
/// @brief _previouslyLockedShards, this is read off at instanciating
/// time from a thread local variable
std::unordered_set<std::string>* _previouslyLockedShards;

View File

@ -24,6 +24,7 @@
////////////////////////////////////////////////////////////////////////////////
#include "ExecutionNode.h"
#include "Aql/AqlItemBlock.h"
#include "Aql/Ast.h"
#include "Aql/BasicBlocks.h"
#include "Aql/CalculationBlock.h"

View File

@ -343,7 +343,7 @@ class ExecutionNode {
static constexpr unsigned SERIALIZE_PARENTS = 1;
/// include estimate cost (used in the explainer)
static constexpr unsigned SERIALIZE_ESTIMATES = 1 << 1;
/// print all ExecutionNode information required in cluster snippets
/// Print all ExecutionNode information required in cluster snippets
static constexpr unsigned SERIALIZE_DETAILS = 1 << 2;
/// include additional function info for explain
static constexpr unsigned SERIALIZE_FUNCTIONS = 1 << 3;

View File

@ -40,7 +40,7 @@ void ExecutionStats::toVelocyPack(VPackBuilder& builder, bool reportFullCount) c
builder.add("scannedFull", VPackValue(scannedFull));
builder.add("scannedIndex", VPackValue(scannedIndex));
builder.add("filtered", VPackValue(filtered));
builder.add("httpRequests", VPackValue(httpRequests));
builder.add("httpRequests", VPackValue(requests));
if (reportFullCount) {
// fullCount is optional
builder.add("fullCount", VPackValue(fullCount > count ? fullCount : count));
@ -75,7 +75,7 @@ void ExecutionStats::add(ExecutionStats const& summand) {
scannedFull += summand.scannedFull;
scannedIndex += summand.scannedIndex;
filtered += summand.filtered;
httpRequests += summand.httpRequests;
requests += summand.requests;
if (summand.fullCount > 0) {
fullCount += summand.fullCount;
}
@ -98,7 +98,7 @@ ExecutionStats::ExecutionStats()
scannedFull(0),
scannedIndex(0),
filtered(0),
httpRequests(0),
requests(0),
fullCount(0),
count(0),
executionTime(0.0) {}
@ -117,13 +117,9 @@ ExecutionStats::ExecutionStats(VPackSlice const& slice)
filtered = slice.get("filtered").getNumber<int64_t>();
if (slice.hasKey("httpRequests")) {
httpRequests = slice.get("httpRequests").getNumber<int64_t>();
requests = slice.get("httpRequests").getNumber<int64_t>();
}
/*
if (slice.hasKey("count")) {
count = slice.get("count").getNumber<int64_t>();
}
*/
// note: fullCount is an optional attribute!
if (slice.hasKey("fullCount")) {
fullCount = slice.get("fullCount").getNumber<int64_t>();

View File

@ -73,7 +73,7 @@ struct ExecutionStats {
scannedFull = 0;
scannedIndex = 0;
filtered = 0;
httpRequests = 0;
requests = 0;
fullCount = 0;
count = 0;
executionTime = 0.0;
@ -93,9 +93,9 @@ struct ExecutionStats {
/// @brief number of documents filtered away
int64_t filtered;
/// @brief total number of HTTP requests made
int64_t httpRequests;
/// @brief total number of requests made
int64_t requests;
/// @brief total number of results, before applying last limit
int64_t fullCount;

View File

@ -136,6 +136,8 @@ IndexBlock::IndexBlock(ExecutionEngine* engine, IndexNode const* en)
// build the _documentProducer callback for extracting
// documents from the index
buildCallback();
initializeOnce();
}
IndexBlock::~IndexBlock() { cleanupNonConstExpressions(); }
@ -211,40 +213,11 @@ void IndexBlock::executeExpressions() {
tmp->changeMember(idx, evaluatedNode);
}
}
/*AstNode* oldOrMember = _condition->getMember(toReplace->orMember);
AstNode* orMember = ast->shallowCopyForModify(oldOrMember);
TRI_DEFER(FINALIZE_SUBTREE(orMember));
newCondition->changeMember(toReplace->orMember, orMember);
AstNode* oldAndMember = orMember->getMember(toReplace->andMember);
AstNode* andMember = ast->shallowCopyForModify(oldAndMember);
TRI_DEFER(FINALIZE_SUBTREE(andMember));
orMember->changeMember(toReplace->andMember, andMember);
if (toReplace->funcMember < 0) {
andMember->changeMember(toReplace->operatorMember, evaluatedNode);
} else {
AstNode* oldFuncMember = andMember->getMember(toReplace->funcMember);
AstNode* funcMember = ast->shallowCopyForModify(oldFuncMember);
TRI_DEFER(FINALIZE_SUBTREE(funcMember));
andMember->changeMember(toReplace->operatorMember, funcMember);
AstNode* oldArrayMember = funcMember->getMember(0);
AstNode* arrayMember = ast->shallowCopyForModify(oldArrayMember);
TRI_DEFER(FINALIZE_SUBTREE(arrayMember));
funcMember->changeMember(0, arrayMember);
arrayMember->changeMember(toReplace->funcMember, evaluatedNode);
}*/
}
DEBUG_END_BLOCK();
}
int IndexBlock::initialize() {
DEBUG_BEGIN_BLOCK();
int res = ExecutionBlock::initialize();
void IndexBlock::initializeOnce() {
auto en = ExecutionNode::castTo<IndexNode const*>(getPlanNode());
auto ast = en->_plan->getAst();
@ -284,8 +257,8 @@ int IndexBlock::initialize() {
};
if (_condition == nullptr) {
// This Node has no condition. Iterate over the complete index.
return res;
// this node has no condition. Iterate over the complete index.
return;
}
auto outVariable = en->outVariable();
@ -371,11 +344,6 @@ int IndexBlock::initialize() {
}
}
}
return res;
// cppcheck-suppress style
DEBUG_END_BLOCK();
}
// init the ranges for reading, this should be called once per new incoming

View File

@ -63,9 +63,6 @@ class IndexBlock final : public ExecutionBlock, public DocumentProducingBlock {
~IndexBlock();
/// @brief initialize, here we fetch all docs from the database
int initialize() override;
/// @brief initializeCursor, here we release our docs from this collection
int initializeCursor(AqlItemBlock* items, size_t pos) override;
@ -75,6 +72,8 @@ class IndexBlock final : public ExecutionBlock, public DocumentProducingBlock {
size_t skipSome(size_t atMost) override final;
private:
void initializeOnce();
/// @brief adds a SORT to a dynamic IN condition
arangodb::aql::AstNode* makeUnique(arangodb::aql::AstNode*) const;

View File

@ -907,7 +907,7 @@ QueryResult Query::explain() {
try {
init();
enterState(QueryExecutionState::ValueType::PARSING);
Parser parser(this);
parser.parse(true);
@ -983,8 +983,7 @@ QueryResult Query::explain() {
!_isModificationQuery && _warnings.empty() &&
_ast->root()->isCacheable());
}
// technically no need to commit, as we are only explaining here
auto commitResult = _trx->commit();
if (commitResult.fail()) {
THROW_ARANGO_EXCEPTION(commitResult);

View File

@ -584,12 +584,7 @@ void RestAqlHandler::useQuery(std::string const& operation,
void RestAqlHandler::getInfoQuery(std::string const& operation,
std::string const& idString) {
bool found;
std::string shardId;
std::string const& shardIdCharP = _request->header("shard-id", found);
if (found && !shardIdCharP.empty()) {
shardId = shardIdCharP;
}
std::string const& shardId = _request->header("shard-id", found);
Query* query = nullptr;
if (findQuery(idString, query)) {
@ -761,11 +756,20 @@ bool RestAqlHandler::findQuery(std::string const& idString, Query*& query) {
void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
VPackSlice const querySlice) {
bool found;
std::string shardId;
std::string const& shardIdCharP = _request->header("shard-id", found);
std::string const& shardId = _request->header("shard-id", found);
if (found && !shardIdCharP.empty()) {
shardId = shardIdCharP;
// upon first usage, the "initializeCursor" method must be called
// note: if the operation is "initializeCursor" itself, we do not initialize
// the cursor here but let the case for "initializeCursor" process it.
// this is because the request may contain additional data
if ((operation == "getSome" || operation == "skipSome") &&
!query->engine()->initializeCursorCalled()) {
int res = query->engine()->initializeCursor(nullptr, 0);
if (res != TRI_ERROR_NO_ERROR) {
generateError(GeneralResponse::responseCode(res),
res, "cannot initialize cursor for AQL query");
return;
}
}
VPackBuilder answerBuilder;
@ -781,19 +785,8 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
JobGuard guard(SchedulerFeature::SCHEDULER);
guard.block();
try {
res = query->trx()->lockCollections();
} catch (std::exception const& ex) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
std::string("lock lead to an exception: ") + ex.what());
return;
} catch (...) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
"lock lead to an exception");
return;
}
// let exceptions propagate from here
res = query->trx()->lockCollections();
}
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
@ -817,155 +810,62 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
answerBuilder.add("exhausted", VPackValue(true));
answerBuilder.add("error", VPackValue(false));
} else {
try {
items->toVelocyPack(query->trx(), answerBuilder);
} catch (...) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
"cannot transform AqlItemBlock to VelocyPack");
return;
}
items->toVelocyPack(query->trx(), answerBuilder);
}
} else if (operation == "skipSome") {
auto atMost = VelocyPackHelper::getNumericValue<size_t>(
querySlice, "atMost", ExecutionBlock::DefaultBatchSize());
size_t skipped;
try {
if (shardId.empty()) {
skipped = query->engine()->skipSome(atMost);
} else {
auto block =
static_cast<BlockWithClients*>(query->engine()->root());
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"unexpected node type");
}
skipped = block->skipSomeForShard(atMost, shardId);
if (shardId.empty()) {
skipped = query->engine()->skipSome(atMost);
} else {
auto block =
static_cast<BlockWithClients*>(query->engine()->root());
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"unexpected node type");
}
} catch (std::exception const& ex) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
std::string("skipSome lead to an exception: ") + ex.what());
return;
} catch (...) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
"skipSome lead to an exception");
return;
skipped = block->skipSomeForShard(atMost, shardId);
}
answerBuilder.add("skipped", VPackValue(static_cast<double>(skipped)));
answerBuilder.add("skipped", VPackValue(skipped));
answerBuilder.add("error", VPackValue(false));
} else if (operation == "skip") {
auto number =
VelocyPackHelper::getNumericValue<size_t>(querySlice, "number", 1);
try {
bool exhausted;
if (shardId.empty()) {
size_t numActuallySkipped = 0;
exhausted = query->engine()->skip(number, numActuallySkipped);
} else {
auto block =
static_cast<BlockWithClients*>(query->engine()->root());
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"unexpected node type");
}
exhausted = block->skipForShard(number, shardId);
}
answerBuilder.add("exhausted", VPackValue(exhausted));
answerBuilder.add("error", VPackValue(false));
} catch (std::exception const& ex) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
std::string("skip lead to an exception: ") + ex.what());
return;
} catch (...) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
"skip lead to an exception");
return;
}
} else if (operation == "initialize") {
int res;
try {
res = query->engine()->initialize();
} catch (arangodb::basics::Exception const& ex) {
generateError(rest::ResponseCode::SERVER_ERROR, ex.code(), std::string("initialize lead to an exception: ") + ex.what());
return;
} catch (std::exception const& ex) {
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_HTTP_SERVER_ERROR, std::string("initialize lead to an exception: ") + ex.what());
return;
} catch (...) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
"initialize lead to an exception");
return;
}
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
answerBuilder.add(StaticStrings::Code, VPackValue(static_cast<double>(res)));
// this is a no-op now
answerBuilder.add(StaticStrings::Error, VPackValue(false));
answerBuilder.add(StaticStrings::Code, VPackValue(TRI_ERROR_NO_ERROR));
} else if (operation == "initializeCursor") {
auto pos =
VelocyPackHelper::getNumericValue<size_t>(querySlice, "pos", 0);
std::unique_ptr<AqlItemBlock> items;
int res;
try {
if (VelocyPackHelper::getBooleanValue(querySlice, "exhausted",
true)) {
res = query->engine()->initializeCursor(nullptr, 0);
} else {
items.reset(new AqlItemBlock(query->resourceMonitor(),
querySlice.get("items")));
res = query->engine()->initializeCursor(items.get(), pos);
}
} catch (arangodb::basics::Exception const& ex) {
generateError(rest::ResponseCode::SERVER_ERROR, ex.code(), std::string("initializeCursor lead to an exception: ") + ex.what());
return;
} catch (std::exception const& ex) {
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_HTTP_SERVER_ERROR, std::string("initializeCursor lead to an exception: ") + ex.what());
return;
} catch (...) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
"initializeCursor lead to an exception");
return;
if (VelocyPackHelper::getBooleanValue(querySlice, "exhausted", true)) {
res = query->engine()->initializeCursor(nullptr, 0);
} else {
items.reset(new AqlItemBlock(query->resourceMonitor(),
querySlice.get("items")));
res = query->engine()->initializeCursor(items.get(), pos);
}
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
answerBuilder.add(StaticStrings::Code, VPackValue(static_cast<double>(res)));
answerBuilder.add(StaticStrings::Code, VPackValue(res));
} else if (operation == "shutdown") {
int res = TRI_ERROR_INTERNAL;
int errorCode = VelocyPackHelper::getNumericValue<int>(
querySlice, "code", TRI_ERROR_INTERNAL);
try {
res = query->engine()->shutdown(
errorCode); // pass errorCode to shutdown
int res = query->engine()->shutdown(errorCode); // pass errorCode to shutdown
// return statistics
answerBuilder.add(VPackValue("stats"));
query->getStats(answerBuilder);
// return statistics
answerBuilder.add(VPackValue("stats"));
query->getStats(answerBuilder);
// return warnings if present
query->addWarningsToVelocyPack(answerBuilder);
// return warnings if present
query->addWarningsToVelocyPack(answerBuilder);
// return the query to the registry
_queryRegistry->close(&_vocbase, _qId);
// return the query to the registry
_queryRegistry->close(&_vocbase, _qId);
// delete the query from the registry
_queryRegistry->destroy(&_vocbase, _qId, errorCode);
_qId = 0;
} catch (arangodb::basics::Exception const& ex) {
generateError(rest::ResponseCode::SERVER_ERROR, ex.code(), std::string("shutdown lead to an exception: ") + ex.what());
return;
} catch (std::exception const& ex) {
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_HTTP_SERVER_ERROR, std::string("shutdown lead to an exception: ") + ex.what());
return;
} catch (...) {
generateError(rest::ResponseCode::SERVER_ERROR,
TRI_ERROR_HTTP_SERVER_ERROR,
"shutdown lead to an exception");
return;
}
// delete the query from the registry
_queryRegistry->destroy(&_vocbase, _qId, errorCode);
_qId = 0;
answerBuilder.add(StaticStrings::Error, VPackValue(res != TRI_ERROR_NO_ERROR));
answerBuilder.add(StaticStrings::Code, VPackValue(res));
} else {
@ -974,17 +874,13 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
}
}
sendResponse(rest::ResponseCode::OK, answerBuilder.slice(),
transactionContext.get());
sendResponse(rest::ResponseCode::OK, answerBuilder.slice(), transactionContext.get());
} catch (arangodb::basics::Exception const& ex) {
generateError(rest::ResponseCode::BAD, ex.code(), ex.message());
return;
generateError(GeneralResponse::responseCode(ex.code()), ex.code(), ex.message());
} catch (std::exception const& ex) {
generateError(rest::ResponseCode::BAD, TRI_ERROR_FAILED, ex.what());
return;
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL, ex.what());
} catch (...) {
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
return;
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL, "unknown exception caught in handleUsequery");
}
}
@ -993,7 +889,6 @@ std::shared_ptr<VPackBuilder> RestAqlHandler::parseVelocyPackBody() {
try {
std::shared_ptr<VPackBuilder> body = _request->toVelocyPackBuilderPtr();
if (body == nullptr) {
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "cannot parse json object";
generateError(rest::ResponseCode::BAD,
TRI_ERROR_HTTP_CORRUPTED_JSON, "cannot parse json object");
return nullptr;
@ -1009,7 +904,6 @@ std::shared_ptr<VPackBuilder> RestAqlHandler::parseVelocyPackBody() {
}
return body;
} catch (...) {
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "cannot parse json object";
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_CORRUPTED_JSON,
"cannot parse json object");
}

View File

@ -100,14 +100,7 @@ ShortestPathBlock::ShortestPathBlock(ExecutionEngine* engine,
if (arangodb::ServerState::instance()->isCoordinator()) {
_engines = ep->engines();
}
}
ShortestPathBlock::~ShortestPathBlock() {
}
int ShortestPathBlock::initialize() {
DEBUG_BEGIN_BLOCK();
int res = ExecutionBlock::initialize();
auto varInfo = getPlanNode()->getRegisterPlan()->varInfo;
if (usesVertexOutput()) {
@ -124,11 +117,6 @@ int ShortestPathBlock::initialize() {
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
_edgeReg = it->second.registerId;
}
return res;
// cppcheck-suppress style
DEBUG_END_BLOCK();
}
int ShortestPathBlock::initializeCursor(AqlItemBlock* items, size_t pos) {

View File

@ -45,11 +45,6 @@ class ShortestPathBlock : public ExecutionBlock {
public:
ShortestPathBlock(ExecutionEngine* engine, ShortestPathNode const* ep);
~ShortestPathBlock();
/// @brief initialize, here we fetch all docs from the database
int initialize() override;
/// @brief initializeCursor
int initializeCursor(AqlItemBlock* items, size_t pos) override;
@ -62,11 +57,8 @@ class ShortestPathBlock : public ExecutionBlock {
// will only return less than atMost if there aren't atMost many
// things to skip overall.
size_t skipSome(size_t atMost) override final;
private:
/// SECTION private Functions
/// @brief Compute the next shortest path
bool nextPath(AqlItemBlock const*);

View File

@ -30,7 +30,9 @@
#include "Aql/ExecutionPlan.h"
#include "Aql/ShortestPathBlock.h"
#include "Aql/Query.h"
#include "Graph/ShortestPathFinder.h"
#include "Graph/ShortestPathOptions.h"
#include "Graph/ShortestPathResult.h"
#include "Indexes/Index.h"
#include "Utils/CollectionNameResolver.h"
#include "VocBase/LogicalCollection.h"

View File

@ -41,17 +41,6 @@ SubqueryBlock::SubqueryBlock(ExecutionEngine* engine, SubqueryNode const* en,
TRI_ASSERT(_outReg < ExecutionNode::MaxRegisterId);
}
/// @brief initialize, tell dependency and the subquery
int SubqueryBlock::initialize() {
int res = ExecutionBlock::initialize();
if (res != TRI_ERROR_NO_ERROR) {
return res;
}
return getSubquery()->initialize();
}
/// @brief getSome
AqlItemBlock* SubqueryBlock::getSome(size_t atMost) {
DEBUG_BEGIN_BLOCK();

View File

@ -39,9 +39,6 @@ class SubqueryBlock : public ExecutionBlock {
SubqueryBlock(ExecutionEngine*, SubqueryNode const*, ExecutionBlock*);
~SubqueryBlock() = default;
/// @brief initialize, tell dependency and the subquery
int initialize() override final;
/// @brief getSome
AqlItemBlock* getSome(size_t atMost) override final;
@ -50,7 +47,7 @@ class SubqueryBlock : public ExecutionBlock {
/// @brief getter for the pointer to the subquery
ExecutionBlock* getSubquery() { return _subquery; }
private:
/// @brief execute the subquery and return its results
std::vector<AqlItemBlock*>* executeSubquery();

View File

@ -123,30 +123,7 @@ TraversalBlock::TraversalBlock(ExecutionEngine* engine, TraversalNode const* ep)
if (arangodb::ServerState::instance()->isCoordinator()) {
_engines = ep->engines();
}
}
TraversalBlock::~TraversalBlock() {
freeCaches();
}
void TraversalBlock::freeCaches() {
for (auto& v : _vertices) {
v.destroy();
}
_vertices.clear();
for (auto& e : _edges) {
e.destroy();
}
_edges.clear();
for (auto& p : _paths) {
p.destroy();
}
_paths.clear();
}
int TraversalBlock::initialize() {
DEBUG_BEGIN_BLOCK();
int res = ExecutionBlock::initialize();
auto varInfo = getPlanNode()->getRegisterPlan()->varInfo;
if (usesVertexOutput()) {
@ -170,11 +147,25 @@ int TraversalBlock::initialize() {
TRI_ASSERT(it->second.registerId < ExecutionNode::MaxRegisterId);
_pathReg = it->second.registerId;
}
}
return res;
TraversalBlock::~TraversalBlock() {
freeCaches();
}
// cppcheck-suppress style
DEBUG_END_BLOCK();
void TraversalBlock::freeCaches() {
for (auto& v : _vertices) {
v.destroy();
}
_vertices.clear();
for (auto& e : _edges) {
e.destroy();
}
_edges.clear();
for (auto& p : _paths) {
p.destroy();
}
_paths.clear();
}
int TraversalBlock::initializeCursor(AqlItemBlock* items, size_t pos) {

View File

@ -43,9 +43,6 @@ class TraversalBlock final : public ExecutionBlock {
~TraversalBlock();
/// @brief initialize, here we fetch all docs from the database
int initialize() override;
/// @brief initializeCursor
int initializeCursor(AqlItemBlock* items, size_t pos) override;
@ -59,7 +56,6 @@ class TraversalBlock final : public ExecutionBlock {
size_t skipSome(size_t atMost) override final;
private:
/// @brief cleanup, here we clean up all internally generated values
void freeCaches();