mirror of https://gitee.com/bigwinds/arangodb
Included two Abstract classes for Traversals. Traverser and TraversalPath. Implemented both of them for Single-Server Traversals.
This commit is contained in:
parent
e18e1fa75b
commit
8d0d921ab6
|
@ -126,7 +126,7 @@ BOOST_FIXTURE_TEST_SUITE (PathEnumeratorTest, PathEnumeratorSetup)
|
|||
BOOST_AUTO_TEST_CASE (test_fullPathEnumerator) {
|
||||
int startVertex = 1;
|
||||
PathEnumerator<int, int, int> it(integerEdgeEnumerator, integerVertexEnumerator, startVertex);
|
||||
TraversalPath<int, int, int> path;
|
||||
EnumeratedPath<int, int> path;
|
||||
for (int k = 1; k < 4; k++) {
|
||||
path = it.next();
|
||||
BOOST_CHECK_EQUAL(path.edges.size(), (size_t)1);
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
using namespace triagens::aql;
|
||||
using Json = triagens::basics::Json;
|
||||
using CollectionNameResolver = triagens::arango::CollectionNameResolver;
|
||||
using VertexId = triagens::arango::traverser::VertexId;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief thread-local cache for compiled regexes
|
||||
|
@ -2255,7 +2256,7 @@ AqlValue Functions::Neighbors (triagens::aql::Query* query,
|
|||
triagens::arango::AqlTransaction* trx,
|
||||
FunctionParameters const& parameters) {
|
||||
size_t const n = parameters.size();
|
||||
basics::traverser::NeighborsOptions opts;
|
||||
triagens::arango::traverser::NeighborsOptions opts;
|
||||
|
||||
if (n < 4 || n > 6) {
|
||||
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "NEIGHBORS", (int) 4, (int) 6);
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#include "Aql/ExecutionPlan.h"
|
||||
#include "Aql/TraversalBlock.h"
|
||||
#include "Aql/ExecutionNode.h"
|
||||
#include "Utils/ShapedJsonTransformer.h"
|
||||
#include "Utils/SingleCollectionReadOnlyTransaction.h"
|
||||
#include <iostream> /// TODO: remove me.
|
||||
|
||||
using namespace std;
|
||||
|
@ -39,6 +37,8 @@ using namespace triagens::basics;
|
|||
using namespace triagens::arango;
|
||||
using namespace triagens::aql;
|
||||
|
||||
using VertexId = triagens::arango::traverser::VertexId;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class TraversalBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -53,29 +53,17 @@ TraversalBlock::TraversalBlock (ExecutionEngine* engine,
|
|||
_edgeReg(0),
|
||||
_pathReg(0),
|
||||
_condition((ep->condition()) ? ep->condition()->root(): nullptr),
|
||||
_hasV8Expression(false),
|
||||
_AccessP(Json::Object, 1),
|
||||
_currentJsonPath(Json::Array, 10)
|
||||
{
|
||||
_hasV8Expression(false) {
|
||||
|
||||
basics::traverser::TraverserOptions opts;
|
||||
triagens::arango::traverser::TraverserOptions opts;
|
||||
ep->fillTraversalOptions(opts);
|
||||
std::vector<TRI_document_collection_t*> edgeCollections;
|
||||
auto cids = ep->edgeCids();
|
||||
|
||||
Json theCurrentJsonPath(Json::Array, 10),
|
||||
_currentPath(TRI_UNKNOWN_MEM_ZONE, theCurrentJsonPath.json(), Json::NOFREE);
|
||||
_AccessP = Json(Json::Object, 1)
|
||||
("p", Json(Json::Object, 1)
|
||||
("edges", theCurrentJsonPath)
|
||||
);
|
||||
|
||||
|
||||
|
||||
for (auto const& cid : cids) {
|
||||
edgeCollections.push_back(_trx->documentCollection(cid));
|
||||
}
|
||||
_traverser.reset(new basics::traverser::DepthFirstTraverser(edgeCollections, opts));
|
||||
_traverser.reset(new triagens::arango::traverser::DepthFirstTraverser(edgeCollections, opts));
|
||||
_resolver = new CollectionNameResolver(_trx->vocbase());
|
||||
if (!ep->usesInVariable()) {
|
||||
_vertexId = ep->getStartVertex();
|
||||
|
@ -217,105 +205,9 @@ int TraversalBlock::initializeCursor (AqlItemBlock* items,
|
|||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
Json TraversalBlock::extractVertexJson (
|
||||
VertexId const& v
|
||||
) {
|
||||
auto collection = _trx->trxCollection(v.cid);
|
||||
if (collection == nullptr) {
|
||||
SingleCollectionReadOnlyTransaction intTrx(new StandaloneTransactionContext(), _trx->vocbase(), v.cid);
|
||||
int res = intTrx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
collection = intTrx.trxCollection();
|
||||
TRI_doc_mptr_copy_t mptr;
|
||||
intTrx.read(&mptr, v.key);
|
||||
Json tmp = TRI_ExpandShapedJson(
|
||||
collection->_collection->_collection->getShaper(),
|
||||
_resolver,
|
||||
v.cid,
|
||||
&mptr
|
||||
);
|
||||
intTrx.finish(res);
|
||||
return tmp;
|
||||
}
|
||||
TRI_doc_mptr_copy_t mptr;
|
||||
_trx->readSingle(collection, &mptr, v.key);
|
||||
return TRI_ExpandShapedJson(
|
||||
collection->_collection->_collection->getShaper(),
|
||||
_resolver,
|
||||
v.cid,
|
||||
&mptr
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Json TraversalBlock::extractEdgeJson (
|
||||
EdgeInfo const& e
|
||||
) {
|
||||
auto cid = e.cid;
|
||||
auto collection = _trx->trxCollection(cid);
|
||||
TRI_shaped_json_t shapedJson;
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, &e.mptr);
|
||||
return TRI_ExpandShapedJson(
|
||||
collection->_collection->_collection->getShaper(),
|
||||
_resolver,
|
||||
cid,
|
||||
&e.mptr
|
||||
);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Transform the VertexId to AQLValue object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue TraversalBlock::vertexToAqlValue (
|
||||
VertexId const& v
|
||||
) {
|
||||
// This json is freed by the AqlValue. No unique_ptr here.
|
||||
Json* result = new Json(extractVertexJson(v));
|
||||
return AqlValue(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Transform the EdgeInfo to AQLValue object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue TraversalBlock::edgeToAqlValue (
|
||||
EdgeInfo const& e
|
||||
) {
|
||||
// This json is freed by the AqlValue. No unique_ptr here.
|
||||
Json* result = new Json(extractEdgeJson(e));
|
||||
return AqlValue(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Transform the path to AQLValue object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue TraversalBlock::pathToAqlValue (
|
||||
const TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>& p
|
||||
) {
|
||||
// This json is freed by the AqlValue. No unique_ptr here.
|
||||
Json* path = new Json(Json::Object, 2);
|
||||
Json vertices(Json::Array);
|
||||
for (size_t i = 0; i < p.vertices.size(); ++i) {
|
||||
vertices(extractVertexJson(p.vertices[i]));
|
||||
}
|
||||
Json edges(Json::Array);
|
||||
for (size_t i = 0; i < p.edges.size(); ++i) {
|
||||
edges(extractEdgeJson(p.edges[i]));
|
||||
}
|
||||
(*path)("vertices", vertices)
|
||||
("edges", edges);
|
||||
|
||||
return AqlValue(path);
|
||||
}
|
||||
|
||||
|
||||
bool TraversalBlock::executeExpressions (AqlValue& pathValue) {
|
||||
TRI_ASSERT(_condition != nullptr);
|
||||
return true;
|
||||
|
||||
|
||||
auto& toReplace = _nonConstExpressions[0];
|
||||
|
@ -338,7 +230,7 @@ bool TraversalBlock::executeExpressions (AqlValue& pathValue) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read more paths
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
bool TraversalBlock::morePaths (size_t hint) {
|
||||
freeCaches();
|
||||
_posInPaths = 0;
|
||||
|
@ -349,29 +241,28 @@ bool TraversalBlock::morePaths (size_t hint) {
|
|||
|
||||
for (size_t j = 0; j < hint; ++j) {
|
||||
auto p = _traverser->next();
|
||||
if (p.edges.size() == 0) {
|
||||
if (p == nullptr) {
|
||||
// There are no further paths available.
|
||||
break;
|
||||
}
|
||||
|
||||
_currentJsonPath.add(extractEdgeJson(p.edges.back()));
|
||||
AqlValue pathValue;
|
||||
|
||||
if (usesPathOutput() || (en->condition() != NULL)) {
|
||||
pathValue = pathToAqlValue(p);
|
||||
if (usesPathOutput() || (en->condition() != nullptr)) {
|
||||
pathValue = AqlValue(p->pathToJson(_trx, _resolver));
|
||||
}
|
||||
|
||||
if ((en->condition() != NULL) &&
|
||||
!executeExpressions(pathValue)) {
|
||||
if ((en->condition() != nullptr) &&
|
||||
! executeExpressions(pathValue)) {
|
||||
_traverser->prune();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( usesVertexOutput() ) {
|
||||
_vertices.push_back(vertexToAqlValue(p.vertices.back()));
|
||||
_vertices.emplace_back(p->lastVertexToJson(_trx, _resolver));
|
||||
}
|
||||
if ( usesEdgeOutput() ) {
|
||||
_edges.push_back(edgeToAqlValue(p.edges.back()));
|
||||
_edges.emplace_back(p->lastEdgeToJson(_trx, _resolver));
|
||||
}
|
||||
if ( usesPathOutput() ) {
|
||||
_paths.push_back(pathValue);
|
||||
|
@ -422,7 +313,7 @@ void TraversalBlock::initializePaths (AqlItemBlock const* items) {
|
|||
Json _idJson = input.get("_id");
|
||||
if (_idJson.isString()) {
|
||||
_vertexId = JsonHelper::getStringValue(_idJson.json(), "");
|
||||
VertexId v = triagens::basics::traverser::IdStringToVertexId (
|
||||
VertexId v = triagens::arango::traverser::IdStringToVertexId (
|
||||
_resolver,
|
||||
_vertexId
|
||||
);
|
||||
|
@ -436,7 +327,7 @@ void TraversalBlock::initializePaths (AqlItemBlock const* items) {
|
|||
Json _idJson = vertexJson.get("_id");
|
||||
if (_idJson.isString()) {
|
||||
_vertexId = JsonHelper::getStringValue(_idJson.json(), "");
|
||||
VertexId v = triagens::basics::traverser::IdStringToVertexId (
|
||||
VertexId v = triagens::arango::traverser::IdStringToVertexId (
|
||||
_resolver,
|
||||
_vertexId
|
||||
);
|
||||
|
|
|
@ -113,7 +113,7 @@ namespace triagens {
|
|||
/// @brief Depth first Traverser object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unique_ptr<triagens::basics::traverser::DepthFirstTraverser> _traverser;
|
||||
std::unique_ptr<triagens::arango::traverser::Traverser> _traverser;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief The information to get the starting point. Can either be a constant
|
||||
|
@ -122,7 +122,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
union {
|
||||
VertexId _startId;
|
||||
triagens::arango::traverser::VertexId _startId;
|
||||
size_t _reg;
|
||||
};
|
||||
|
||||
|
@ -282,46 +282,6 @@ namespace triagens {
|
|||
return _pathVar != nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to extract JSON from a vertexId object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
basics::Json extractVertexJson (
|
||||
VertexId const& v
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to extract JSON from a EdgeInfo object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
basics::Json extractEdgeJson (
|
||||
EdgeInfo const& e
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transform a VertexId to AqlValue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue vertexToAqlValue (
|
||||
VertexId const& v
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transform a EdgeInfo to AqlValue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue edgeToAqlValue (
|
||||
EdgeInfo const& e
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief transform the Traversalpath object to AqlValue
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue pathToAqlValue (
|
||||
const basics::TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>& p
|
||||
);
|
||||
|
||||
};
|
||||
} // namespace triagens::aql
|
||||
} // namespace triagens
|
||||
|
|
|
@ -362,7 +362,7 @@ double TraversalNode::estimateCost (size_t& nrItems) const {
|
|||
return depCost + nrItems;
|
||||
}
|
||||
|
||||
void TraversalNode::fillTraversalOptions (basics::traverser::TraverserOptions& opts) const {
|
||||
void TraversalNode::fillTraversalOptions (triagens::arango::traverser::TraverserOptions& opts) const {
|
||||
opts.direction = _direction;
|
||||
opts.minDepth = _minDepth;
|
||||
opts.maxDepth = _maxDepth;
|
||||
|
|
|
@ -267,7 +267,7 @@ namespace triagens {
|
|||
/// with default values.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void fillTraversalOptions (basics::traverser::TraverserOptions& opts) const;
|
||||
void fillTraversalOptions (triagens::arango::traverser::TraverserOptions& opts) const;
|
||||
|
||||
std::vector<TRI_voc_cid_t> const edgeCids () const {
|
||||
return _edgeCids;
|
||||
|
|
|
@ -32,14 +32,16 @@
|
|||
#include "Utils/transactions.h"
|
||||
#include "Utils/V8ResolverGuard.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "Utils/ShapedJsonTransformer.h"
|
||||
#include "Utils/SingleCollectionReadOnlyTransaction.h"
|
||||
#include "VocBase/document-collection.h"
|
||||
#include "VocBase/KeyGenerator.h"
|
||||
#include "VocBase/VocShaper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace triagens::basics;
|
||||
using namespace triagens::basics::traverser;
|
||||
using namespace triagens::arango;
|
||||
using namespace triagens::arango::traverser;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the _from Id out of mptr, we return an RValue reference
|
||||
|
@ -68,7 +70,7 @@ static VertexId ExtractToId (TRI_doc_mptr_copy_t const& ptr) {
|
|||
/// VertexId is in use
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VertexId triagens::basics::traverser::IdStringToVertexId (
|
||||
VertexId triagens::arango::traverser::IdStringToVertexId (
|
||||
CollectionNameResolver const* resolver,
|
||||
string const& vertex
|
||||
) {
|
||||
|
@ -718,6 +720,85 @@ void TRI_RunNeighborsSearch (
|
|||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class SingleServerTraversalPath
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Json* SingleServerTraversalPath::pathToJson (Transaction* trx,
|
||||
CollectionNameResolver* resolver) const {
|
||||
std::unique_ptr<Json> path(new Json(Json::Object, 2));
|
||||
Json vertices(Json::Array);
|
||||
for (size_t i = 0; i < _path.vertices.size(); ++i) {
|
||||
vertices(*vertexToJson(trx, resolver, _path.vertices[i]));
|
||||
}
|
||||
Json edges(Json::Array);
|
||||
for (size_t i = 0; i < _path.edges.size(); ++i) {
|
||||
edges(*edgeToJson(trx, resolver, _path.edges[i]));
|
||||
}
|
||||
(*path)("vertices", vertices)
|
||||
("edges", edges);
|
||||
|
||||
return path.release();
|
||||
}
|
||||
|
||||
|
||||
Json* SingleServerTraversalPath::lastEdgeToJson (Transaction* trx,
|
||||
CollectionNameResolver* resolver) const {
|
||||
return edgeToJson(trx, resolver, _path.edges.back());
|
||||
}
|
||||
|
||||
Json* SingleServerTraversalPath::lastVertexToJson (Transaction* trx,
|
||||
CollectionNameResolver* resolver) const {
|
||||
return vertexToJson(trx, resolver, _path.vertices.back());
|
||||
}
|
||||
|
||||
Json* SingleServerTraversalPath::edgeToJson (Transaction* trx,
|
||||
CollectionNameResolver* resolver,
|
||||
EdgeInfo const& e) const {
|
||||
auto collection = trx->trxCollection(e.cid);
|
||||
TRI_shaped_json_t shapedJson;
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, &e.mptr);
|
||||
return new Json(TRI_ExpandShapedJson(
|
||||
collection->_collection->_collection->getShaper(),
|
||||
resolver,
|
||||
e.cid,
|
||||
&e.mptr
|
||||
));
|
||||
}
|
||||
|
||||
Json* SingleServerTraversalPath::vertexToJson (Transaction* trx,
|
||||
CollectionNameResolver* resolver,
|
||||
VertexId const& v) const {
|
||||
auto collection = trx->trxCollection(v.cid);
|
||||
if (collection == nullptr) {
|
||||
SingleCollectionReadOnlyTransaction intTrx(new StandaloneTransactionContext(), trx->vocbase(), v.cid);
|
||||
int res = intTrx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
collection = intTrx.trxCollection();
|
||||
TRI_doc_mptr_copy_t mptr;
|
||||
intTrx.read(&mptr, v.key);
|
||||
std::unique_ptr<Json> tmp(new Json(TRI_ExpandShapedJson(
|
||||
collection->_collection->_collection->getShaper(),
|
||||
resolver,
|
||||
v.cid,
|
||||
&mptr
|
||||
)));
|
||||
intTrx.finish(res);
|
||||
return tmp.release();
|
||||
}
|
||||
TRI_doc_mptr_copy_t mptr;
|
||||
trx->readSingle(collection, &mptr, v.key);
|
||||
return new Json(TRI_ExpandShapedJson(
|
||||
collection->_collection->_collection->getShaper(),
|
||||
resolver,
|
||||
v.cid,
|
||||
&mptr
|
||||
));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class DepthFirstTraverser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -856,10 +937,9 @@ void DepthFirstTraverser::setStartVertex (VertexId& v) {
|
|||
|
||||
size_t DepthFirstTraverser::skip (size_t amount) {
|
||||
size_t skipped = 0;
|
||||
TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t> p;
|
||||
for (size_t i = 0; i < amount; ++i) {
|
||||
p = next();
|
||||
if (p.edges.size() == 0) {
|
||||
std::unique_ptr<const TraversalPath> p(next());
|
||||
if (p == nullptr) {
|
||||
break;
|
||||
}
|
||||
++skipped;
|
||||
|
@ -871,21 +951,22 @@ bool DepthFirstTraverser::hasMore () {
|
|||
return !_done;
|
||||
}
|
||||
|
||||
const TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>& DepthFirstTraverser::next () {
|
||||
const TraversalPath* DepthFirstTraverser::next () {
|
||||
TRI_ASSERT(!_done);
|
||||
if (_pruneNext) {
|
||||
_pruneNext = false;
|
||||
_enumerator->prune();
|
||||
}
|
||||
TRI_ASSERT(!_pruneNext);
|
||||
const TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>& p = _enumerator->next();
|
||||
size_t countEdges = p.edges.size();
|
||||
const EnumeratedPath<EdgeInfo, VertexId>& path = _enumerator->next();
|
||||
size_t countEdges = path.edges.size();
|
||||
if (countEdges == 0) {
|
||||
_done = true;
|
||||
// Done traversing
|
||||
return p;
|
||||
return nullptr;
|
||||
}
|
||||
if (_opts.shouldPrunePath(p)) {
|
||||
std::unique_ptr<SingleServerTraversalPath> p(new SingleServerTraversalPath(path));
|
||||
if (_opts.shouldPrunePath(p.get())) {
|
||||
_enumerator->prune();
|
||||
return next();
|
||||
}
|
||||
|
@ -895,7 +976,7 @@ const TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>& DepthFirstTraverse
|
|||
if (countEdges < _opts.minDepth) {
|
||||
return next();
|
||||
}
|
||||
return p;
|
||||
return p.release();
|
||||
}
|
||||
|
||||
void DepthFirstTraverser::prune () {
|
||||
|
|
|
@ -35,39 +35,10 @@
|
|||
#include "Utils/ExplicitTransaction.h"
|
||||
#include "VocBase/edge-collection.h"
|
||||
#include "VocBase/ExampleMatcher.h"
|
||||
#include "VocBase/Traverser.h"
|
||||
|
||||
class VocShaper;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Template for a vertex id. Is simply a pair of cid and key
|
||||
/// NOTE: This struct will never free the value asigned to char const* key
|
||||
/// The environment has to make sure that the string it points to is
|
||||
/// not freed as long as this struct is in use!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct VertexId {
|
||||
TRI_voc_cid_t cid;
|
||||
char const* key;
|
||||
|
||||
VertexId ()
|
||||
: cid(0),
|
||||
key("") {
|
||||
}
|
||||
|
||||
VertexId (TRI_voc_cid_t cid, char const* key)
|
||||
: cid(cid),
|
||||
key(key) {
|
||||
}
|
||||
|
||||
bool operator== (const VertexId& other) const {
|
||||
if (cid == other.cid) {
|
||||
return strcmp(key, other.key) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct EdgeInfo {
|
||||
TRI_voc_cid_t cid;
|
||||
TRI_doc_mptr_copy_t mptr;
|
||||
|
@ -78,41 +49,6 @@ struct EdgeInfo {
|
|||
) : cid(pcid), mptr(pmptr) { }
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<VertexId> {
|
||||
public:
|
||||
size_t operator() (VertexId const& s) const {
|
||||
size_t h1 = std::hash<TRI_voc_cid_t>()(s.cid);
|
||||
size_t h2 = TRI_FnvHashString(s.key);
|
||||
return h1 ^ ( h2 << 1 );
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct equal_to<VertexId> {
|
||||
public:
|
||||
bool operator() (VertexId const& s, VertexId const& t) const {
|
||||
return s.cid == t.cid && strcmp(s.key, t.key) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct less<VertexId> {
|
||||
public:
|
||||
bool operator() (const VertexId& lhs, const VertexId& rhs) {
|
||||
if (lhs.cid != rhs.cid) {
|
||||
return lhs.cid < rhs.cid;
|
||||
}
|
||||
return strcmp(lhs.key, rhs.key) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// EdgeId and VertexId are similar here. both have a key and a cid
|
||||
typedef VertexId EdgeId;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Template for information required by vertex filter.
|
||||
/// Contains transaction, barrier and the Matcher Class.
|
||||
|
@ -137,14 +73,17 @@ struct VertexFilterInfo {
|
|||
/// @brief typedef the template instantiation of the PathFinder
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef triagens::basics::PathFinder<VertexId, EdgeId, double>
|
||||
typedef triagens::basics::PathFinder<triagens::arango::traverser::VertexId,
|
||||
triagens::arango::traverser::EdgeId,
|
||||
double>
|
||||
ArangoDBPathFinder;
|
||||
|
||||
typedef triagens::basics::ConstDistanceFinder<VertexId, EdgeId>
|
||||
typedef triagens::basics::ConstDistanceFinder<triagens::arango::traverser::VertexId,
|
||||
triagens::arango::traverser::EdgeId>
|
||||
ArangoDBConstDistancePathFinder;
|
||||
|
||||
namespace triagens {
|
||||
namespace basics {
|
||||
namespace arango {
|
||||
namespace traverser {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -189,7 +128,7 @@ namespace triagens {
|
|||
TRI_voc_cid_t const& cid,
|
||||
std::string& errorMessage);
|
||||
|
||||
void addEdgeFilter (Json const& example,
|
||||
void addEdgeFilter (triagens::basics::Json const& example,
|
||||
VocShaper* shaper,
|
||||
TRI_voc_cid_t const& cid,
|
||||
triagens::arango::CollectionNameResolver const* resolver);
|
||||
|
@ -262,7 +201,7 @@ namespace triagens {
|
|||
struct TraverserOptions {
|
||||
|
||||
private:
|
||||
std::function<bool (const TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>& path)> pruningFunction;
|
||||
std::function<bool (const TraversalPath* path)> pruningFunction;
|
||||
|
||||
public:
|
||||
TRI_edge_direction_e direction;
|
||||
|
@ -282,14 +221,14 @@ namespace triagens {
|
|||
{ };
|
||||
|
||||
void setPruningFunction (
|
||||
std::function<bool (const TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>& path)> callback
|
||||
std::function<bool (const TraversalPath* path)> callback
|
||||
) {
|
||||
pruningFunction = callback;
|
||||
usesPrune = true;
|
||||
}
|
||||
|
||||
bool shouldPrunePath (
|
||||
const TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>& path
|
||||
const TraversalPath* path
|
||||
) {
|
||||
if (!usesPrune) {
|
||||
return false;
|
||||
|
@ -299,10 +238,60 @@ namespace triagens {
|
|||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class SingleServerTraversalPath
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class SingleServerTraversalPath : public TraversalPath {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
public:
|
||||
|
||||
SingleServerTraversalPath (
|
||||
const triagens::basics::EnumeratedPath<EdgeInfo, VertexId>& path
|
||||
) : _path(path) {
|
||||
}
|
||||
|
||||
~SingleServerTraversalPath () {
|
||||
}
|
||||
|
||||
triagens::basics::Json* pathToJson (Transaction*,
|
||||
CollectionNameResolver*) const override;
|
||||
|
||||
triagens::basics::Json* lastEdgeToJson (Transaction*,
|
||||
CollectionNameResolver*) const override;
|
||||
|
||||
triagens::basics::Json* lastVertexToJson (Transaction*,
|
||||
CollectionNameResolver*) const override;
|
||||
|
||||
private:
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
triagens::basics::Json* edgeToJson (Transaction* trx,
|
||||
CollectionNameResolver* resolver,
|
||||
EdgeInfo const& e) const;
|
||||
|
||||
triagens::basics::Json* vertexToJson (Transaction* trx,
|
||||
CollectionNameResolver* resolver,
|
||||
VertexId const& v) const;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
triagens::basics::EnumeratedPath<EdgeInfo, VertexId> _path;
|
||||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class DepthFirstTraverser
|
||||
// -----------------------------------------------------------------------------
|
||||
class DepthFirstTraverser {
|
||||
class DepthFirstTraverser : public Traverser {
|
||||
|
||||
private:
|
||||
|
||||
|
@ -328,7 +317,9 @@ namespace triagens {
|
|||
/// @brief internal cursor to enumerate the paths of a graph
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unique_ptr<PathEnumerator<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>> _enumerator;
|
||||
std::unique_ptr<triagens::basics::PathEnumerator<EdgeInfo,
|
||||
VertexId,
|
||||
TRI_doc_mptr_copy_t>> _enumerator;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief internal function to extract an edge
|
||||
|
@ -375,25 +366,25 @@ namespace triagens {
|
|||
/// @brief Reset the traverser to use another start vertex
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setStartVertex (VertexId& v);
|
||||
void setStartVertex (VertexId& v) override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Skip amount many paths of the graph.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t skip (size_t amount);
|
||||
size_t skip (size_t amount) override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the next possible path in the graph.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const TraversalPath<EdgeInfo, VertexId, TRI_doc_mptr_copy_t>& next ();
|
||||
const TraversalPath* next () override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Prune the current path prefix. Do not evaluate it any further.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void prune ();
|
||||
void prune () override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Simple check if there potentially more paths.
|
||||
|
@ -401,7 +392,7 @@ namespace triagens {
|
|||
/// If it returns false it is guaranteed that there are no more paths.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool hasMore ();
|
||||
bool hasMore () override;
|
||||
|
||||
};
|
||||
|
||||
|
@ -453,12 +444,12 @@ class EdgeCollectionInfo {
|
|||
_weighter(weighter) {
|
||||
}
|
||||
|
||||
EdgeId extractEdgeId (TRI_doc_mptr_copy_t& ptr) {
|
||||
return EdgeId(_edgeCollectionCid, TRI_EXTRACT_MARKER_KEY(&ptr));
|
||||
triagens::arango::traverser::EdgeId extractEdgeId (TRI_doc_mptr_copy_t& ptr) {
|
||||
return triagens::arango::traverser::EdgeId(_edgeCollectionCid, TRI_EXTRACT_MARKER_KEY(&ptr));
|
||||
}
|
||||
|
||||
std::vector<TRI_doc_mptr_copy_t> getEdges (TRI_edge_direction_e direction,
|
||||
VertexId const& vertexId) const {
|
||||
triagens::arango::traverser::VertexId const& vertexId) const {
|
||||
return TRI_LookupEdgesDocumentCollection(_edgeCollection,
|
||||
direction, vertexId.cid, const_cast<char*>(vertexId.key));
|
||||
}
|
||||
|
@ -525,13 +516,13 @@ class VertexCollectionInfo {
|
|||
|
||||
std::unique_ptr<ArangoDBPathFinder::Path> TRI_RunShortestPathSearch (
|
||||
std::vector<EdgeCollectionInfo*>& collectionInfos,
|
||||
triagens::basics::traverser::ShortestPathOptions& opts
|
||||
triagens::arango::traverser::ShortestPathOptions& opts
|
||||
);
|
||||
|
||||
|
||||
std::unique_ptr<ArangoDBConstDistancePathFinder::Path> TRI_RunSimpleShortestPathSearch (
|
||||
std::vector<EdgeCollectionInfo*>& collectionInfos,
|
||||
triagens::basics::traverser::ShortestPathOptions& opts
|
||||
triagens::arango::traverser::ShortestPathOptions& opts
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -539,7 +530,7 @@ std::unique_ptr<ArangoDBConstDistancePathFinder::Path> TRI_RunSimpleShortestPath
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_RunNeighborsSearch (std::vector<EdgeCollectionInfo*>& collectionInfos,
|
||||
triagens::basics::traverser::NeighborsOptions& opts,
|
||||
std::unordered_set<VertexId>& distinct);
|
||||
triagens::arango::traverser::NeighborsOptions& opts,
|
||||
std::unordered_set<triagens::arango::traverser::VertexId>& distinct);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,8 +73,8 @@
|
|||
|
||||
using namespace std;
|
||||
using namespace triagens::basics;
|
||||
using namespace triagens::basics::traverser;
|
||||
using namespace triagens::arango;
|
||||
using namespace triagens::arango::traverser;
|
||||
using namespace triagens::rest;
|
||||
using namespace arangodb;
|
||||
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Traverser
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Michael Hackstein
|
||||
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
|
||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGODB_VOCBASE_TRAVERSER_H
|
||||
#define ARANGODB_VOCBASE_TRAVERSER_H 1
|
||||
|
||||
#include "basics/Traverser.h"
|
||||
|
||||
namespace triagens {
|
||||
namespace arango {
|
||||
namespace traverser {
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- struct VertexId
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Template for a vertex id. Is simply a pair of cid and key
|
||||
/// NOTE: This struct will never free the value asigned to char const* key
|
||||
/// The environment has to make sure that the string it points to is
|
||||
/// not freed as long as this struct is in use!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct VertexId {
|
||||
TRI_voc_cid_t cid;
|
||||
char const* key;
|
||||
|
||||
VertexId ()
|
||||
: cid(0),
|
||||
key("") {
|
||||
}
|
||||
|
||||
VertexId (TRI_voc_cid_t cid, char const* key)
|
||||
: cid(cid),
|
||||
key(key) {
|
||||
}
|
||||
|
||||
bool operator== (const VertexId& other) const {
|
||||
if (cid == other.cid) {
|
||||
return strcmp(key, other.key) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// EdgeId and VertexId are similar here. both have a key and a cid
|
||||
typedef VertexId EdgeId;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class TraversalPath
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class TraversalPath {
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Constructor. This is an abstract only class.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TraversalPath () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds the complete path as Json
|
||||
/// Has the format:
|
||||
/// {
|
||||
/// vertices: [<vertex-as-json>],
|
||||
/// edges: [<edge-as-json>]
|
||||
/// }
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual triagens::basics::Json* pathToJson (Transaction*,
|
||||
CollectionNameResolver*) const = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds only the last edge on the path as Json
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual triagens::basics::Json* lastEdgeToJson (Transaction*,
|
||||
CollectionNameResolver*) const = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Builds only the last vertex as Json
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual triagens::basics::Json* lastVertexToJson (Transaction*,
|
||||
CollectionNameResolver*) const = 0;
|
||||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class Traverser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class Traverser {
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Constructor. This is an abstract only class.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Traverser () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~Traverser () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Reset the traverser to use another start vertex
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void setStartVertex (VertexId& v) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Skip amount many paths of the graph.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual size_t skip (size_t amount) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the next possible path in the graph.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual const TraversalPath* next () = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Prune the current path prefix. Do not evaluate it any further.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void prune () = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Simple check if there potentially more paths.
|
||||
/// It might return true although there are no more paths available.
|
||||
/// If it returns false it is guaranteed that there are no more paths.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual bool hasMore () = 0;
|
||||
|
||||
};
|
||||
|
||||
} // traverser
|
||||
} // arango
|
||||
} // triagens
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- functions for std::containers
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<triagens::arango::traverser::VertexId> {
|
||||
public:
|
||||
size_t operator() (triagens::arango::traverser::VertexId const& s) const {
|
||||
size_t h1 = std::hash<TRI_voc_cid_t>()(s.cid);
|
||||
size_t h2 = TRI_FnvHashString(s.key);
|
||||
return h1 ^ ( h2 << 1 );
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct equal_to<triagens::arango::traverser::VertexId> {
|
||||
public:
|
||||
bool operator() (triagens::arango::traverser::VertexId const& s, triagens::arango::traverser::VertexId const& t) const {
|
||||
return s.cid == t.cid && strcmp(s.key, t.key) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct less<triagens::arango::traverser::VertexId> {
|
||||
public:
|
||||
bool operator() (const triagens::arango::traverser::VertexId& lhs, const triagens::arango::traverser::VertexId& rhs) {
|
||||
if (lhs.cid != rhs.cid) {
|
||||
return lhs.cid < rhs.cid;
|
||||
}
|
||||
return strcmp(lhs.key, rhs.key) < 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1232,14 +1232,14 @@ namespace triagens {
|
|||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- struct TraversalPath
|
||||
// --SECTION-- struct EnumeratedPath
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <typename edgeIdentifier, typename vertexIdentifier, typename edgeItem>
|
||||
struct TraversalPath {
|
||||
template <typename edgeIdentifier, typename vertexIdentifier>
|
||||
struct EnumeratedPath {
|
||||
std::vector<edgeIdentifier> edges;
|
||||
std::vector<vertexIdentifier> vertices;
|
||||
TraversalPath () {}
|
||||
EnumeratedPath () {}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -1262,7 +1262,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief List of the last path is used to
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
TraversalPath<edgeIdentifier, vertexIdentifier, edgeItem> _traversalPath;
|
||||
EnumeratedPath<edgeIdentifier, vertexIdentifier> _enumeratedPath;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief The pointers returned for edge indexes on this path. Used to continue
|
||||
|
@ -1310,11 +1310,11 @@ namespace triagens {
|
|||
vertexIdentifier& startVertex
|
||||
) : _getEdge(getEdge),
|
||||
_getVertex(getVertex) {
|
||||
_traversalPath.vertices.push_back(startVertex);
|
||||
_enumeratedPath.vertices.push_back(startVertex);
|
||||
_lastEdges.push(nullptr);
|
||||
_lastEdgesDir.push(false);
|
||||
_lastEdgesIdx.push(0);
|
||||
TRI_ASSERT(_traversalPath.vertices.size() == 1);
|
||||
TRI_ASSERT(_enumeratedPath.vertices.size() == 1);
|
||||
TRI_ASSERT(_lastEdges.size() == 1);
|
||||
TRI_ASSERT(_lastEdgesDir.size() == 1);
|
||||
};
|
||||
|
@ -1329,32 +1329,32 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the next Path element from the traversal.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const TraversalPath<edgeIdentifier, vertexIdentifier, edgeItem>& next () {
|
||||
const EnumeratedPath<edgeIdentifier, vertexIdentifier>& next () {
|
||||
if (_lastEdges.size() == 0) {
|
||||
_traversalPath.edges.clear();
|
||||
_traversalPath.vertices.clear();
|
||||
return _traversalPath;
|
||||
_enumeratedPath.edges.clear();
|
||||
_enumeratedPath.vertices.clear();
|
||||
return _enumeratedPath;
|
||||
}
|
||||
_getEdge(_traversalPath.vertices.back(), _traversalPath.edges, _lastEdges.top(), _lastEdgesIdx.top(), _lastEdgesDir.top());
|
||||
_getEdge(_enumeratedPath.vertices.back(), _enumeratedPath.edges, _lastEdges.top(), _lastEdgesIdx.top(), _lastEdgesDir.top());
|
||||
if (_lastEdges.top() != nullptr) {
|
||||
// Could continue the path in the next depth.
|
||||
_lastEdges.push(nullptr);
|
||||
_lastEdgesDir.push(false);
|
||||
_lastEdgesIdx.push(0);
|
||||
vertexIdentifier v = _getVertex(_traversalPath.edges.back(), _traversalPath.vertices.back());
|
||||
_traversalPath.vertices.push_back(v);
|
||||
TRI_ASSERT(_traversalPath.vertices.size() == _traversalPath.edges.size() + 1);
|
||||
vertexIdentifier v = _getVertex(_enumeratedPath.edges.back(), _enumeratedPath.vertices.back());
|
||||
_enumeratedPath.vertices.push_back(v);
|
||||
TRI_ASSERT(_enumeratedPath.vertices.size() == _enumeratedPath.edges.size() + 1);
|
||||
} else {
|
||||
if (_traversalPath.edges.size() == 0) {
|
||||
if (_enumeratedPath.edges.size() == 0) {
|
||||
// We are done with enumerating paths
|
||||
_traversalPath.edges.clear();
|
||||
_traversalPath.vertices.clear();
|
||||
_enumeratedPath.edges.clear();
|
||||
_enumeratedPath.vertices.clear();
|
||||
} else {
|
||||
prune();
|
||||
return next();
|
||||
}
|
||||
}
|
||||
return _traversalPath;
|
||||
return _enumeratedPath;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1366,9 +1366,9 @@ namespace triagens {
|
|||
_lastEdges.pop();
|
||||
_lastEdgesDir.pop();
|
||||
_lastEdgesIdx.pop();
|
||||
if (_traversalPath.edges.size() > 0) {
|
||||
_traversalPath.edges.pop_back();
|
||||
_traversalPath.vertices.pop_back();
|
||||
if (_enumeratedPath.edges.size() > 0) {
|
||||
_enumeratedPath.edges.pop_back();
|
||||
_enumeratedPath.vertices.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue