diff --git a/arangod/Aql/ShortestPathBlock.cpp b/arangod/Aql/ShortestPathBlock.cpp index 801569e4c6..79122ebd5f 100644 --- a/arangod/Aql/ShortestPathBlock.cpp +++ b/arangod/Aql/ShortestPathBlock.cpp @@ -44,105 +44,6 @@ using namespace arangodb::aql; /// Will be handed over to the path finder namespace arangodb { namespace aql { -struct ConstDistanceExpanderLocal { - private: - /// @brief reference to the Block - ShortestPathBlock const* _block; - - /// @brief Defines if this expander follows the edges in reverse - bool _isReverse; - - public: - ConstDistanceExpanderLocal(ShortestPathBlock const* block, bool isReverse) - : _block(block), _isReverse(isReverse) {} - - void operator()(VPackSlice const& v, std::vector& resEdges, - std::vector& neighbors) { - TRI_ASSERT(v.isString()); - std::string id = v.copyString(); - ManagedDocumentResult* mmdr = _block->_mmdr.get(); - std::unique_ptr edgeCursor; - for (auto const& edgeCollection : _block->_collectionInfos) { - TRI_ASSERT(edgeCollection != nullptr); - if (_isReverse) { - edgeCursor = edgeCollection->getReverseEdges(id, mmdr); - } else { - edgeCursor = edgeCollection->getEdges(id, mmdr); - } - - LogicalCollection* collection = edgeCursor->collection(); - auto cb = [&](DocumentIdentifierToken const& element) { - if (collection->readDocument(_block->transaction(), element, *mmdr)) { - VPackSlice edge(mmdr->vpack()); - VPackSlice from = transaction::helpers::extractFromFromDocument(edge); - if (from == v) { - VPackSlice to = transaction::helpers::extractToFromDocument(edge); - if (to != v) { - resEdges.emplace_back(edge); - neighbors.emplace_back(to); - } - } else { - resEdges.emplace_back(edge); - neighbors.emplace_back(from); - } - } - }; - while (edgeCursor->getMore(cb, 1000)) { - } - } - } -}; - -/// @brief Cluster class to expand edges. -/// Will be handed over to the path finder -struct ConstDistanceExpanderCluster { - private: - /// @brief reference to the Block - ShortestPathBlock* _block; - - /// @brief Defines if this expander follows the edges in reverse - bool _isReverse; - - public: - ConstDistanceExpanderCluster(ShortestPathBlock* block, bool isReverse) - : _block(block), _isReverse(isReverse) {} - - void operator()(VPackSlice const& v, std::vector& resEdges, - std::vector& neighbors) { - int res = TRI_ERROR_NO_ERROR; - for (auto const& edgeCollection : _block->_collectionInfos) { - VPackBuilder result; - TRI_ASSERT(edgeCollection != nullptr); - if (_isReverse) { - res = edgeCollection->getReverseEdgesCoordinator(v, result); - } else { - res = edgeCollection->getEdgesCoordinator(v, result); - } - - if (res != TRI_ERROR_NO_ERROR) { - THROW_ARANGO_EXCEPTION(res); - } - - VPackSlice edges = result.slice().get("edges"); - for (auto const& edge : VPackArrayIterator(edges)) { - VPackSlice from = transaction::helpers::extractFromFromDocument(edge); - if (from == v) { - VPackSlice to = transaction::helpers::extractToFromDocument(edge); - if (to != v) { - resEdges.emplace_back(edge); - neighbors.emplace_back(to); - } - } else { - resEdges.emplace_back(edge); - neighbors.emplace_back(from); - } - } - // Make sure the data Slices are pointing to is not running out of scope. - // This is not thread-safe! - _block->_coordinatorCache.emplace_back(result.steal()); - } - } -}; /// @brief Expander for weighted edges struct EdgeWeightExpanderLocal { @@ -354,9 +255,8 @@ ShortestPathBlock::ShortestPathBlock(ExecutionEngine* engine, EdgeWeightExpanderCluster(this, false), EdgeWeightExpanderCluster(this, true), _opts.bidirectional)); } else { - _finder.reset(new arangodb::graph::ConstantWeightShortestPathFinder( - ConstDistanceExpanderCluster(this, false), - ConstDistanceExpanderCluster(this, true))); + _finder.reset( + new arangodb::graph::ConstantWeightShortestPathFinder(this)); } } else { if (_opts.useWeight) { @@ -364,9 +264,8 @@ ShortestPathBlock::ShortestPathBlock(ExecutionEngine* engine, EdgeWeightExpanderLocal(this, false), EdgeWeightExpanderLocal(this, true), _opts.bidirectional)); } else { - _finder.reset(new arangodb::graph::ConstantWeightShortestPathFinder( - ConstDistanceExpanderLocal(this, false), - ConstDistanceExpanderLocal(this, true))); + _finder.reset( + new arangodb::graph::ConstantWeightShortestPathFinder(this)); } } } diff --git a/arangod/Aql/ShortestPathBlock.h b/arangod/Aql/ShortestPathBlock.h index 1ba18fafba..b9dffbe2a4 100644 --- a/arangod/Aql/ShortestPathBlock.h +++ b/arangod/Aql/ShortestPathBlock.h @@ -33,6 +33,7 @@ class ManagedDocumentResult; namespace graph { class ShortestPathFinder; +class ConstantWeightShortestPathFinder; } namespace traverser { @@ -45,11 +46,12 @@ namespace aql { class ShortestPathNode; class ShortestPathBlock : public ExecutionBlock { - friend struct ConstDistanceExpanderLocal; - friend struct ConstDistanceExpanderCluster; friend struct EdgeWeightExpanderLocal; friend struct EdgeWeightExpanderCluster; + // TODO ONLY TEMPORARY + friend class graph::ConstantWeightShortestPathFinder; + public: ShortestPathBlock(ExecutionEngine* engine, ShortestPathNode const* ep); diff --git a/arangod/Graph/ConstantWeightShortestPathFinder.cpp b/arangod/Graph/ConstantWeightShortestPathFinder.cpp index fbc856ed8b..12c9d17693 100644 --- a/arangod/Graph/ConstantWeightShortestPathFinder.cpp +++ b/arangod/Graph/ConstantWeightShortestPathFinder.cpp @@ -23,15 +23,24 @@ #include "ConstantWeightShortestPathFinder.h" -#include +#include "Aql/ShortestPathBlock.h" +#include "Cluster/ServerState.h" +#include "Utils/OperationCursor.h" +#include "VocBase/EdgeCollectionInfo.h" +#include "VocBase/LogicalCollection.h" +#include "VocBase/ManagedDocumentResult.h" #include "VocBase/Traverser.h" +#include +#include +#include + using namespace arangodb; using namespace arangodb::graph; ConstantWeightShortestPathFinder::ConstantWeightShortestPathFinder( - ExpanderFunction left, ExpanderFunction right) - : _leftNeighborExpander(left), _rightNeighborExpander(right) {} + arangodb::aql::ShortestPathBlock* block) + : _block(block) {} ConstantWeightShortestPathFinder::~ConstantWeightShortestPathFinder() { clearVisited(); @@ -72,7 +81,11 @@ bool ConstantWeightShortestPathFinder::shortestPath( nextClosure.clear(); if (_leftClosure.size() < _rightClosure.size()) { for (arangodb::velocypack::Slice& v : _leftClosure) { - _leftNeighborExpander(v, edges, neighbors); + if (arangodb::ServerState::instance()->isCoordinator()) { + expandVertexCluster(false, v, edges, neighbors); + } else { + expandVertex(false, v, edges, neighbors); + } size_t const neighborsSize = neighbors.size(); TRI_ASSERT(edges.size() == neighborsSize); for (size_t i = 0; i < neighborsSize; ++i) { @@ -112,7 +125,11 @@ bool ConstantWeightShortestPathFinder::shortestPath( nextClosure.clear(); } else { for (arangodb::velocypack::Slice& v : _rightClosure) { - _rightNeighborExpander(v, edges, neighbors); + if (arangodb::ServerState::instance()->isCoordinator()) { + expandVertexCluster(true, v, edges, neighbors); + } else { + expandVertex(true, v, edges, neighbors); + } size_t const neighborsSize = neighbors.size(); TRI_ASSERT(edges.size() == neighborsSize); for (size_t i = 0; i < neighborsSize; ++i) { @@ -155,6 +172,80 @@ bool ConstantWeightShortestPathFinder::shortestPath( return false; } +void ConstantWeightShortestPathFinder::expandVertex( + bool backward, VPackSlice& vertex, std::vector& edges, + std::vector& neighbors) { + TRI_ASSERT(vertex.isString()); + std::string id = vertex.copyString(); + ManagedDocumentResult* mmdr = _block->_mmdr.get(); + std::unique_ptr edgeCursor; + for (auto const& edgeCollection : _block->_collectionInfos) { + TRI_ASSERT(edgeCollection != nullptr); + if (backward) { + edgeCursor = edgeCollection->getReverseEdges(id, mmdr); + } else { + edgeCursor = edgeCollection->getEdges(id, mmdr); + } + + LogicalCollection* collection = edgeCursor->collection(); + auto cb = [&](DocumentIdentifierToken const& element) { + if (collection->readDocument(_block->transaction(), element, *mmdr)) { + VPackSlice edge(mmdr->vpack()); + VPackSlice from = transaction::helpers::extractFromFromDocument(edge); + if (from == vertex) { + VPackSlice to = transaction::helpers::extractToFromDocument(edge); + if (to != vertex) { + edges.emplace_back(edge); + neighbors.emplace_back(to); + } + } else { + edges.emplace_back(edge); + neighbors.emplace_back(from); + } + } + }; + while (edgeCursor->getMore(cb, 1000)) { + } + } +} + +void ConstantWeightShortestPathFinder::expandVertexCluster( + bool backward, VPackSlice& vertex, std::vector& resEdges, + std::vector& neighbors) { + int res = TRI_ERROR_NO_ERROR; + for (auto const& edgeCollection : _block->_collectionInfos) { + VPackBuilder result; + TRI_ASSERT(edgeCollection != nullptr); + if (backward) { + res = edgeCollection->getReverseEdgesCoordinator(vertex, result); + } else { + res = edgeCollection->getEdgesCoordinator(vertex, result); + } + + if (res != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(res); + } + + VPackSlice edges = result.slice().get("edges"); + for (auto const& edge : VPackArrayIterator(edges)) { + VPackSlice from = transaction::helpers::extractFromFromDocument(edge); + if (from == vertex) { + VPackSlice to = transaction::helpers::extractToFromDocument(edge); + if (to != vertex) { + resEdges.emplace_back(edge); + neighbors.emplace_back(to); + } + } else { + resEdges.emplace_back(edge); + neighbors.emplace_back(from); + } + } + // Make sure the data Slices are pointing to is not running out of scope. + // This is not thread-safe! + _block->_coordinatorCache.emplace_back(result.steal()); + } +} + void ConstantWeightShortestPathFinder::clearVisited() { for (auto& it : _leftFound) { delete it.second; diff --git a/arangod/Graph/ConstantWeightShortestPathFinder.h b/arangod/Graph/ConstantWeightShortestPathFinder.h index 091e8b4b13..e4c647bc59 100644 --- a/arangod/Graph/ConstantWeightShortestPathFinder.h +++ b/arangod/Graph/ConstantWeightShortestPathFinder.h @@ -28,6 +28,11 @@ #include "Graph/ShortestPathFinder.h" namespace arangodb { + +namespace aql { +class ShortestPathBlock; +} + namespace velocypack { class Slice; } @@ -68,12 +73,11 @@ class ConstantWeightShortestPathFinder : public ShortestPathFinder { _rightFound; std::deque _rightClosure; - ExpanderFunction _leftNeighborExpander; - ExpanderFunction _rightNeighborExpander; + // TODO Remove Me! + arangodb::aql::ShortestPathBlock* _block; public: - ConstantWeightShortestPathFinder(ExpanderFunction left, - ExpanderFunction right); + ConstantWeightShortestPathFinder(arangodb::aql::ShortestPathBlock* block); ~ConstantWeightShortestPathFinder(); @@ -83,6 +87,14 @@ class ConstantWeightShortestPathFinder : public ShortestPathFinder { std::function const& callback) override; private: + void expandVertex(bool backward, arangodb::velocypack::Slice& vertex, + std::vector& edges, + std::vector& neighbors); + + void expandVertexCluster(bool backward, arangodb::velocypack::Slice& vertex, + std::vector& edges, + std::vector& neighbors); + void clearVisited(); };