From 3ab448831cb55e627fe014b8d64bbd3ab33d4d41 Mon Sep 17 00:00:00 2001 From: Michael Hackstein Date: Wed, 23 Oct 2019 00:08:05 +0200 Subject: [PATCH] Added empty dummy stubs for execute() in ExecutionBlock --- arangod/Aql/BlocksWithClients.cpp | 7 +++ arangod/Aql/BlocksWithClients.h | 2 + arangod/Aql/ExecutionBlock.h | 18 +++++- arangod/Aql/ExecutionBlockImpl.cpp | 78 ++++++++++++++----------- arangod/Aql/ExecutionBlockImpl.h | 16 ++++- arangod/Aql/IdExecutor.cpp | 31 +++++++--- arangod/Aql/IdExecutor.h | 2 + arangod/Aql/RemoteExecutor.cpp | 11 +++- arangod/Aql/RemoteExecutor.h | 12 ++-- tests/Aql/WaitingExecutionBlockMock.cpp | 7 +++ tests/Aql/WaitingExecutionBlockMock.h | 4 ++ 11 files changed, 134 insertions(+), 54 deletions(-) diff --git a/arangod/Aql/BlocksWithClients.cpp b/arangod/Aql/BlocksWithClients.cpp index 5108d19273..7adda6f3ec 100644 --- a/arangod/Aql/BlocksWithClients.cpp +++ b/arangod/Aql/BlocksWithClients.cpp @@ -23,6 +23,7 @@ #include "BlocksWithClients.h" +#include "Aql/AqlCallStack.h" #include "Aql/AqlItemBlock.h" #include "Aql/AqlTransaction.h" #include "Aql/AqlValue.h" @@ -137,3 +138,9 @@ std::pair BlocksWithClients::skipSome(size_t) { TRI_ASSERT(false); THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); } + +std::tuple BlocksWithClients::execute(AqlCallStack stack) { + // This will not be implemented here! + TRI_ASSERT(false); + THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); +} diff --git a/arangod/Aql/BlocksWithClients.h b/arangod/Aql/BlocksWithClients.h index bdc659a1ae..ca29e4cd47 100644 --- a/arangod/Aql/BlocksWithClients.h +++ b/arangod/Aql/BlocksWithClients.h @@ -80,6 +80,8 @@ class BlocksWithClients : public ExecutionBlock { virtual std::pair skipSomeForShard(size_t atMost, std::string const& shardId) = 0; + std::tuple execute(AqlCallStack stack) override; + protected: /// @brief getClientId: get the number (used internally) /// corresponding to diff --git a/arangod/Aql/ExecutionBlock.h b/arangod/Aql/ExecutionBlock.h index 8dbba6258c..29bc09dc42 100644 --- a/arangod/Aql/ExecutionBlock.h +++ b/arangod/Aql/ExecutionBlock.h @@ -39,6 +39,7 @@ class Methods; } namespace aql { +class AqlCallStack; class InputAqlItemRow; class ExecutionEngine; class ExecutionNode; @@ -96,8 +97,8 @@ class ExecutionBlock { void traceGetSomeBegin(size_t atMost); // Trace the end of a getSome call, potentially with result - std::pair traceGetSomeEnd( - ExecutionState state, SharedAqlItemBlockPtr result); + std::pair traceGetSomeEnd(ExecutionState state, + SharedAqlItemBlockPtr result); void traceSkipSomeBegin(size_t atMost); @@ -122,6 +123,19 @@ class ExecutionBlock { /// @brief add a dependency void addDependency(ExecutionBlock* ep); + /// @brief main function to produce data in this ExecutionBlock. + /// It gets the AqlCallStack defining the operations required in every + /// subquery level. It will then perform the requested amount of offset, data and fullcount. + /// The AqlCallStack is copied on purpose, so this block can modify it. + /// Will return + /// 1. state: + /// * WAITING: We have async operation going on, nothing happend, please call again + /// * HASMORE: Here is some data in the request range, there is still more, if required call again + /// * DONE: Here is some data, and there will be no further data available. + /// 2. size_t: Amount of documents skipped. + /// 3. SharedAqlItemBlockPtr: The next data block. + virtual std::tuple execute(AqlCallStack stack) = 0; + protected: /// @brief the execution engine ExecutionEngine* _engine; diff --git a/arangod/Aql/ExecutionBlockImpl.cpp b/arangod/Aql/ExecutionBlockImpl.cpp index 1880a006aa..7f9656966d 100644 --- a/arangod/Aql/ExecutionBlockImpl.cpp +++ b/arangod/Aql/ExecutionBlockImpl.cpp @@ -26,6 +26,7 @@ #include "ExecutionBlockImpl.h" #include "Aql/AllRowsFetcher.h" +#include "Aql/AqlCallStack.h" #include "Aql/AqlItemBlock.h" #include "Aql/CalculationExecutor.h" #include "Aql/ConstFetcher.h" @@ -46,6 +47,7 @@ #include "Aql/InputAqlItemRow.h" #include "Aql/KShortestPathsExecutor.h" #include "Aql/LimitExecutor.h" +#include "Aql/MaterializeExecutor.h" #include "Aql/ModificationExecutor.h" #include "Aql/ModificationExecutorTraits.h" #include "Aql/MultiDependencySingleRowFetcher.h" @@ -63,7 +65,6 @@ #include "Aql/SubqueryExecutor.h" #include "Aql/SubqueryStartExecutor.h" #include "Aql/TraversalExecutor.h" -#include "Aql/MaterializeExecutor.h" #include @@ -79,18 +80,18 @@ using namespace arangodb::aql; * constexpr bool someClassHasSomeMethod = hasSomeMethod::value; */ -#define CREATE_HAS_MEMBER_CHECK(methodName, checkName) \ - template \ - class checkName { \ - template \ - static std::true_type test(decltype(&C::methodName)); \ - template \ +#define CREATE_HAS_MEMBER_CHECK(methodName, checkName) \ + template \ + class checkName { \ + template \ + static std::true_type test(decltype(&C::methodName)); \ + template \ static std::true_type test(decltype(&C::template methodName<>)); \ - template \ - static std::false_type test(...); \ - \ - public: \ - static constexpr bool value = decltype(test(0))::value; \ + template \ + static std::false_type test(...); \ + \ + public: \ + static constexpr bool value = decltype(test(0))::value; \ } CREATE_HAS_MEMBER_CHECK(initializeCursor, hasInitializeCursor); @@ -301,23 +302,24 @@ static SkipVariants constexpr skipType() { static_assert(!useFetcher || hasSkipRows::value, "Fetcher is chosen for skipping, but has not skipRows method!"); - static_assert(useExecutor == - (std::is_same::value || - std::is_same>::value || - std::is_same>::value || - std::is_same>::value || - std::is_same>::value || - std::is_same>::value || - std::is_same>::value || - std::is_same>::value || - std::is_same>::value || - std::is_same::value || - std::is_same::value || - std::is_same>>::value || - std::is_same::value || - std::is_same::value || - std::is_same::value), - "Unexpected executor for SkipVariants::EXECUTOR"); + static_assert( + useExecutor == + (std::is_same::value || + std::is_same>::value || + std::is_same>::value || + std::is_same>::value || + std::is_same>::value || + std::is_same>::value || + std::is_same>::value || + std::is_same>::value || + std::is_same>::value || + std::is_same::value || + std::is_same::value || + std::is_same>>::value || + std::is_same::value || + std::is_same::value || + std::is_same::value), + "Unexpected executor for SkipVariants::EXECUTOR"); // The LimitExecutor will not work correctly with SkipVariants::FETCHER! static_assert( @@ -386,7 +388,6 @@ std::pair ExecutionBlockImpl::skipSomeOnceWith return {state, skipped}; } - template struct InitializeCursor {}; @@ -453,6 +454,13 @@ std::pair ExecutionBlockImpl::shutdown(int err return ExecutionBlock::shutdown(errorCode); } +template +std::tuple ExecutionBlockImpl::execute(AqlCallStack stack) { + // TODO implement! + TRI_ASSERT(false); + THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); +} + // Work around GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480 // Without the namespaces it fails with // error: specialization of 'template std::pair arangodb::aql::ExecutionBlockImpl::initializeCursor(arangodb::aql::AqlItemBlock*, size_t)' in different namespace @@ -568,8 +576,8 @@ std::pair ExecutionBlockImpl>::s } template <> -std::pair -ExecutionBlockImpl>>::shutdown(int errorCode) { +std::pair ExecutionBlockImpl< + IdExecutor>>::shutdown(int errorCode) { if (this->infos().isResponsibleForInitializeCursor()) { return ExecutionBlock::shutdown(errorCode); } @@ -766,8 +774,10 @@ template class ::arangodb::aql::ExecutionBlockImpl>; template class ::arangodb::aql::ExecutionBlockImpl>; template class ::arangodb::aql::ExecutionBlockImpl>; -template class ::arangodb::aql::ExecutionBlockImpl>>; -template class ::arangodb::aql::ExecutionBlockImpl>>; +template class ::arangodb::aql::ExecutionBlockImpl< + IdExecutor>>; +template class ::arangodb::aql::ExecutionBlockImpl< + IdExecutor>>; template class ::arangodb::aql::ExecutionBlockImpl; template class ::arangodb::aql::ExecutionBlockImpl; template class ::arangodb::aql::ExecutionBlockImpl>>; diff --git a/arangod/Aql/ExecutionBlockImpl.h b/arangod/Aql/ExecutionBlockImpl.h index 3b451241df..53f2738dbe 100644 --- a/arangod/Aql/ExecutionBlockImpl.h +++ b/arangod/Aql/ExecutionBlockImpl.h @@ -98,7 +98,8 @@ class ExecutionBlockImpl final : public ExecutionBlock { typename aql::DependencyProxy; static_assert( - Executor::Properties::allowsBlockPassthrough == BlockPassthrough::Disable || Executor::Properties::preservesOrder, + Executor::Properties::allowsBlockPassthrough == BlockPassthrough::Disable || + Executor::Properties::preservesOrder, "allowsBlockPassthrough must imply preservesOrder, but does not!"); public: @@ -174,6 +175,19 @@ class ExecutionBlockImpl final : public ExecutionBlock { /// central place. std::pair shutdown(int) override; + /// @brief main function to produce data in this ExecutionBlock. + /// It gets the AqlCallStack defining the operations required in every + /// subquery level. It will then perform the requested amount of offset, data and fullcount. + /// The AqlCallStack is copied on purpose, so this block can modify it. + /// Will return + /// 1. state: + /// * WAITING: We have async operation going on, nothing happend, please call again + /// * HASMORE: Here is some data in the request range, there is still more, if required call again + /// * DONE: Here is some data, and there will be no further data available. + /// 2. size_t: Amount of documents skipped. + /// 3. SharedAqlItemBlockPtr: The next data block. + std::tuple execute(AqlCallStack stack) override; + private: /** * @brief Inner getSome() part, without the tracing calls. diff --git a/arangod/Aql/IdExecutor.cpp b/arangod/Aql/IdExecutor.cpp index d2dd944c5c..0b4f99b936 100644 --- a/arangod/Aql/IdExecutor.cpp +++ b/arangod/Aql/IdExecutor.cpp @@ -22,6 +22,7 @@ #include "IdExecutor.h" +#include "Aql/AqlCallStack.h" #include "Aql/AqlValue.h" #include "Aql/ConstFetcher.h" #include "Aql/ExecutionEngine.h" @@ -43,9 +44,8 @@ constexpr BlockPassthrough IdExecutor::Properties::allowsBloc template constexpr bool IdExecutor::Properties::inputSizeRestrictsOutputSize; -ExecutionBlockImpl>::ExecutionBlockImpl(ExecutionEngine* engine, - ExecutionNode const* node, - RegisterId outputRegister, bool doCount) +ExecutionBlockImpl>::ExecutionBlockImpl( + ExecutionEngine* engine, ExecutionNode const* node, RegisterId outputRegister, bool doCount) : ExecutionBlock(engine, node), _currentDependency(0), _outputRegister(outputRegister), @@ -56,7 +56,8 @@ ExecutionBlockImpl>::ExecutionBlockIm } } -std::pair ExecutionBlockImpl>::skipSome(size_t atMost) { +std::pair +ExecutionBlockImpl>::skipSome(size_t atMost) { traceSkipSomeBegin(atMost); if (isDone()) { return traceSkipSomeEnd(ExecutionState::DONE, 0); @@ -73,7 +74,8 @@ std::pair ExecutionBlockImpl ExecutionBlockImpl>::getSome(size_t atMost) { +std::pair +ExecutionBlockImpl>::getSome(size_t atMost) { traceGetSomeBegin(atMost); if (isDone()) { return traceGetSomeEnd(ExecutionState::DONE, nullptr); @@ -99,10 +101,18 @@ bool aql::ExecutionBlockImpl>::isDone return _currentDependency >= _dependencies.size(); } -RegisterId ExecutionBlockImpl>::getOutputRegisterId() const noexcept { +RegisterId ExecutionBlockImpl>::getOutputRegisterId() const + noexcept { return _outputRegister; } +std::tuple +ExecutionBlockImpl>::execute(AqlCallStack stack) { + // TODO Implement me + TRI_ASSERT(false); + THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); +} + ExecutionBlock& ExecutionBlockImpl>::currentDependency() const { TRI_ASSERT(_currentDependency < _dependencies.size()); TRI_ASSERT(_dependencies[_currentDependency] != nullptr); @@ -209,10 +219,13 @@ template class ::arangodb::aql::IdExecutor>; template std::tuple::Stats, SharedAqlItemBlockPtr> -IdExecutor::fetchBlockForPassthrough(size_t atMost); +IdExecutor::fetchBlockForPassthrough( + size_t atMost); template std::tuple>::Stats, SharedAqlItemBlockPtr> -IdExecutor>::fetchBlockForPassthrough(size_t atMost); +IdExecutor>::fetchBlockForPassthrough< + BlockPassthrough::Enable, void>(size_t atMost); template std::tuple -IdExecutor>::skipRows(size_t atMost); +IdExecutor>::skipRows< + BlockPassthrough::Disable, void>(size_t atMost); diff --git a/arangod/Aql/IdExecutor.h b/arangod/Aql/IdExecutor.h index c0beeaa907..3981848896 100644 --- a/arangod/Aql/IdExecutor.h +++ b/arangod/Aql/IdExecutor.h @@ -93,6 +93,8 @@ class ExecutionBlockImpl> : public Ex RegisterId getOutputRegisterId() const noexcept; + std::tuple execute(AqlCallStack stack) override; + private: bool isDone() const noexcept; diff --git a/arangod/Aql/RemoteExecutor.cpp b/arangod/Aql/RemoteExecutor.cpp index 01dbe671ba..37ca55970b 100644 --- a/arangod/Aql/RemoteExecutor.cpp +++ b/arangod/Aql/RemoteExecutor.cpp @@ -22,6 +22,7 @@ #include "RemoteExecutor.h" +#include "Aql/AqlCallStack.h" #include "Aql/ClusterNodes.h" #include "Aql/ExecutionEngine.h" #include "Aql/ExecutorInfos.h" @@ -142,8 +143,6 @@ std::pair ExecutionBlockImpl ExecutionBlockImpl::shutdown(i return {ExecutionState::WAITING, TRI_ERROR_NO_ERROR}; } +std::tuple ExecutionBlockImpl::execute( + AqlCallStack stack) { + TRI_ASSERT(false); + THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); +} + namespace { Result handleErrorResponse(network::EndpointSpec const& spec, fuerte::Error err, fuerte::Response* response) { @@ -390,7 +395,7 @@ Result handleErrorResponse(network::EndpointSpec const& spec, fuerte::Error err, .append(spec.serverId) .append("': "); } - + int res = TRI_ERROR_INTERNAL; if (err != fuerte::Error::NoError) { res = network::fuerteToArangoErrorCode(err); diff --git a/arangod/Aql/RemoteExecutor.h b/arangod/Aql/RemoteExecutor.h index 5cb40b2e9a..40f735f7c6 100644 --- a/arangod/Aql/RemoteExecutor.h +++ b/arangod/Aql/RemoteExecutor.h @@ -24,8 +24,8 @@ #define ARANGOD_AQL_REMOTE_EXECUTOR_H #include "Aql/ClusterNodes.h" -#include "Aql/ExecutorInfos.h" #include "Aql/ExecutionBlockImpl.h" +#include "Aql/ExecutorInfos.h" #include @@ -62,6 +62,8 @@ class ExecutionBlockImpl : public ExecutionBlock { std::pair shutdown(int errorCode) override; + std::tuple execute(AqlCallStack stack) override; + #ifdef ARANGODB_ENABLE_MAINTAINER_MODE // only for asserts: public: @@ -109,16 +111,16 @@ class ExecutionBlockImpl : public ExecutionBlock { /// @brief the last remote response Result object, may contain an error. arangodb::Result _lastError; - + std::mutex _communicationMutex; - + unsigned _lastTicket; /// used to check for canceled requests - + bool _hasTriggeredShutdown; // _communicationMutex *must* be locked for this! unsigned generateNewTicket(); - + bool _didSendShutdownRequest = false; void traceGetSomeRequest(velocypack::Slice slice, size_t atMost); diff --git a/tests/Aql/WaitingExecutionBlockMock.cpp b/tests/Aql/WaitingExecutionBlockMock.cpp index 4706dd4f4d..6e938d4f3c 100644 --- a/tests/Aql/WaitingExecutionBlockMock.cpp +++ b/tests/Aql/WaitingExecutionBlockMock.cpp @@ -22,6 +22,7 @@ #include "WaitingExecutionBlockMock.h" +#include "Aql/AqlCallStack.h" #include "Aql/AqlItemBlock.h" #include "Aql/ExecutionEngine.h" #include "Aql/ExecutionState.h" @@ -113,3 +114,9 @@ std::pair WaitingExecutionBlockMock::skip return {ExecutionState::HASMORE, skipped}; } } + +std::tuple WaitingExecutionBlockMock::execute(AqlCallStack stack) { + // TODO implement! + TRI_ASSERT(false); + THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); +} \ No newline at end of file diff --git a/tests/Aql/WaitingExecutionBlockMock.h b/tests/Aql/WaitingExecutionBlockMock.h index 598308e25d..f644b37ccc 100644 --- a/tests/Aql/WaitingExecutionBlockMock.h +++ b/tests/Aql/WaitingExecutionBlockMock.h @@ -95,6 +95,10 @@ class WaitingExecutionBlockMock final : public arangodb::aql::ExecutionBlock { */ std::pair skipSome(size_t atMost) override; + // TODO: Document and implement me! + std::tuple execute( + arangodb::aql::AqlCallStack stack) override; + private: std::deque _data; arangodb::aql::ResourceMonitor _resourceMonitor;