mirror of https://gitee.com/bigwinds/arangodb
Removed external expander functions and moved them into the PathFinder implementations.
This commit is contained in:
parent
8df9fe1d21
commit
b09dfaa323
|
@ -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<VPackSlice>& resEdges,
|
||||
std::vector<VPackSlice>& neighbors) {
|
||||
TRI_ASSERT(v.isString());
|
||||
std::string id = v.copyString();
|
||||
ManagedDocumentResult* mmdr = _block->_mmdr.get();
|
||||
std::unique_ptr<arangodb::OperationCursor> 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<VPackSlice>& resEdges,
|
||||
std::vector<VPackSlice>& 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -23,15 +23,24 @@
|
|||
|
||||
#include "ConstantWeightShortestPathFinder.h"
|
||||
|
||||
#include <velocypack/Slice.h>
|
||||
#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 <velocypack/Iterator.h>
|
||||
#include <velocypack/Slice.h>
|
||||
#include <velocypack/velocypack-aliases.h>
|
||||
|
||||
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<VPackSlice>& edges,
|
||||
std::vector<VPackSlice>& neighbors) {
|
||||
TRI_ASSERT(vertex.isString());
|
||||
std::string id = vertex.copyString();
|
||||
ManagedDocumentResult* mmdr = _block->_mmdr.get();
|
||||
std::unique_ptr<arangodb::OperationCursor> 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<VPackSlice>& resEdges,
|
||||
std::vector<VPackSlice>& 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;
|
||||
|
|
|
@ -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<arangodb::velocypack::Slice> _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<void()> const& callback) override;
|
||||
|
||||
private:
|
||||
void expandVertex(bool backward, arangodb::velocypack::Slice& vertex,
|
||||
std::vector<arangodb::velocypack::Slice>& edges,
|
||||
std::vector<arangodb::velocypack::Slice>& neighbors);
|
||||
|
||||
void expandVertexCluster(bool backward, arangodb::velocypack::Slice& vertex,
|
||||
std::vector<arangodb::velocypack::Slice>& edges,
|
||||
std::vector<arangodb::velocypack::Slice>& neighbors);
|
||||
|
||||
void clearVisited();
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue