1
0
Fork 0

Removed external expander functions and moved them into the PathFinder implementations.

This commit is contained in:
Michael Hackstein 2017-04-11 11:41:12 +02:00
parent 8df9fe1d21
commit b09dfaa323
4 changed files with 120 additions and 116 deletions

View File

@ -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));
}
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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();
};