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
|
/// Will be handed over to the path finder
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
namespace aql {
|
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
|
/// @brief Expander for weighted edges
|
||||||
struct EdgeWeightExpanderLocal {
|
struct EdgeWeightExpanderLocal {
|
||||||
|
@ -354,9 +255,8 @@ ShortestPathBlock::ShortestPathBlock(ExecutionEngine* engine,
|
||||||
EdgeWeightExpanderCluster(this, false),
|
EdgeWeightExpanderCluster(this, false),
|
||||||
EdgeWeightExpanderCluster(this, true), _opts.bidirectional));
|
EdgeWeightExpanderCluster(this, true), _opts.bidirectional));
|
||||||
} else {
|
} else {
|
||||||
_finder.reset(new arangodb::graph::ConstantWeightShortestPathFinder(
|
_finder.reset(
|
||||||
ConstDistanceExpanderCluster(this, false),
|
new arangodb::graph::ConstantWeightShortestPathFinder(this));
|
||||||
ConstDistanceExpanderCluster(this, true)));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_opts.useWeight) {
|
if (_opts.useWeight) {
|
||||||
|
@ -364,9 +264,8 @@ ShortestPathBlock::ShortestPathBlock(ExecutionEngine* engine,
|
||||||
EdgeWeightExpanderLocal(this, false),
|
EdgeWeightExpanderLocal(this, false),
|
||||||
EdgeWeightExpanderLocal(this, true), _opts.bidirectional));
|
EdgeWeightExpanderLocal(this, true), _opts.bidirectional));
|
||||||
} else {
|
} else {
|
||||||
_finder.reset(new arangodb::graph::ConstantWeightShortestPathFinder(
|
_finder.reset(
|
||||||
ConstDistanceExpanderLocal(this, false),
|
new arangodb::graph::ConstantWeightShortestPathFinder(this));
|
||||||
ConstDistanceExpanderLocal(this, true)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ class ManagedDocumentResult;
|
||||||
|
|
||||||
namespace graph {
|
namespace graph {
|
||||||
class ShortestPathFinder;
|
class ShortestPathFinder;
|
||||||
|
class ConstantWeightShortestPathFinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace traverser {
|
namespace traverser {
|
||||||
|
@ -45,11 +46,12 @@ namespace aql {
|
||||||
class ShortestPathNode;
|
class ShortestPathNode;
|
||||||
|
|
||||||
class ShortestPathBlock : public ExecutionBlock {
|
class ShortestPathBlock : public ExecutionBlock {
|
||||||
friend struct ConstDistanceExpanderLocal;
|
|
||||||
friend struct ConstDistanceExpanderCluster;
|
|
||||||
friend struct EdgeWeightExpanderLocal;
|
friend struct EdgeWeightExpanderLocal;
|
||||||
friend struct EdgeWeightExpanderCluster;
|
friend struct EdgeWeightExpanderCluster;
|
||||||
|
|
||||||
|
// TODO ONLY TEMPORARY
|
||||||
|
friend class graph::ConstantWeightShortestPathFinder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShortestPathBlock(ExecutionEngine* engine, ShortestPathNode const* ep);
|
ShortestPathBlock(ExecutionEngine* engine, ShortestPathNode const* ep);
|
||||||
|
|
||||||
|
|
|
@ -23,15 +23,24 @@
|
||||||
|
|
||||||
#include "ConstantWeightShortestPathFinder.h"
|
#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 "VocBase/Traverser.h"
|
||||||
|
|
||||||
|
#include <velocypack/Iterator.h>
|
||||||
|
#include <velocypack/Slice.h>
|
||||||
|
#include <velocypack/velocypack-aliases.h>
|
||||||
|
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::graph;
|
using namespace arangodb::graph;
|
||||||
|
|
||||||
ConstantWeightShortestPathFinder::ConstantWeightShortestPathFinder(
|
ConstantWeightShortestPathFinder::ConstantWeightShortestPathFinder(
|
||||||
ExpanderFunction left, ExpanderFunction right)
|
arangodb::aql::ShortestPathBlock* block)
|
||||||
: _leftNeighborExpander(left), _rightNeighborExpander(right) {}
|
: _block(block) {}
|
||||||
|
|
||||||
ConstantWeightShortestPathFinder::~ConstantWeightShortestPathFinder() {
|
ConstantWeightShortestPathFinder::~ConstantWeightShortestPathFinder() {
|
||||||
clearVisited();
|
clearVisited();
|
||||||
|
@ -72,7 +81,11 @@ bool ConstantWeightShortestPathFinder::shortestPath(
|
||||||
nextClosure.clear();
|
nextClosure.clear();
|
||||||
if (_leftClosure.size() < _rightClosure.size()) {
|
if (_leftClosure.size() < _rightClosure.size()) {
|
||||||
for (arangodb::velocypack::Slice& v : _leftClosure) {
|
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();
|
size_t const neighborsSize = neighbors.size();
|
||||||
TRI_ASSERT(edges.size() == neighborsSize);
|
TRI_ASSERT(edges.size() == neighborsSize);
|
||||||
for (size_t i = 0; i < neighborsSize; ++i) {
|
for (size_t i = 0; i < neighborsSize; ++i) {
|
||||||
|
@ -112,7 +125,11 @@ bool ConstantWeightShortestPathFinder::shortestPath(
|
||||||
nextClosure.clear();
|
nextClosure.clear();
|
||||||
} else {
|
} else {
|
||||||
for (arangodb::velocypack::Slice& v : _rightClosure) {
|
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();
|
size_t const neighborsSize = neighbors.size();
|
||||||
TRI_ASSERT(edges.size() == neighborsSize);
|
TRI_ASSERT(edges.size() == neighborsSize);
|
||||||
for (size_t i = 0; i < neighborsSize; ++i) {
|
for (size_t i = 0; i < neighborsSize; ++i) {
|
||||||
|
@ -155,6 +172,80 @@ bool ConstantWeightShortestPathFinder::shortestPath(
|
||||||
return false;
|
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() {
|
void ConstantWeightShortestPathFinder::clearVisited() {
|
||||||
for (auto& it : _leftFound) {
|
for (auto& it : _leftFound) {
|
||||||
delete it.second;
|
delete it.second;
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
#include "Graph/ShortestPathFinder.h"
|
#include "Graph/ShortestPathFinder.h"
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
|
|
||||||
|
namespace aql {
|
||||||
|
class ShortestPathBlock;
|
||||||
|
}
|
||||||
|
|
||||||
namespace velocypack {
|
namespace velocypack {
|
||||||
class Slice;
|
class Slice;
|
||||||
}
|
}
|
||||||
|
@ -68,12 +73,11 @@ class ConstantWeightShortestPathFinder : public ShortestPathFinder {
|
||||||
_rightFound;
|
_rightFound;
|
||||||
std::deque<arangodb::velocypack::Slice> _rightClosure;
|
std::deque<arangodb::velocypack::Slice> _rightClosure;
|
||||||
|
|
||||||
ExpanderFunction _leftNeighborExpander;
|
// TODO Remove Me!
|
||||||
ExpanderFunction _rightNeighborExpander;
|
arangodb::aql::ShortestPathBlock* _block;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConstantWeightShortestPathFinder(ExpanderFunction left,
|
ConstantWeightShortestPathFinder(arangodb::aql::ShortestPathBlock* block);
|
||||||
ExpanderFunction right);
|
|
||||||
|
|
||||||
~ConstantWeightShortestPathFinder();
|
~ConstantWeightShortestPathFinder();
|
||||||
|
|
||||||
|
@ -83,6 +87,14 @@ class ConstantWeightShortestPathFinder : public ShortestPathFinder {
|
||||||
std::function<void()> const& callback) override;
|
std::function<void()> const& callback) override;
|
||||||
|
|
||||||
private:
|
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();
|
void clearVisited();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue