1
0
Fork 0

Adapted traverser implementations to new Path Enumerator for improved pruning

This commit is contained in:
Michael Hackstein 2015-11-27 16:25:02 +01:00
parent d0021131b5
commit a7b7d1ec18
6 changed files with 120 additions and 27 deletions

View File

@ -68,19 +68,26 @@ triagens::basics::Json* ClusterTraversalPath::lastVertexToJson (Transaction*,
// --SECTION-- class ClusterTraverser
// -----------------------------------------------------------------------------
std::string ClusterTraverser::VertexGetter::operator() (std::string const& edgeId,
std::string const& vertexId) {
auto it = _edges->find(edgeId);
bool ClusterTraverser::VertexGetter::operator() (std::string const& edgeId,
std::string const& vertexId,
size_t depth,
std::string& result) {
auto it = _traverser->_edges.find(edgeId);
std::string def = "";
if (it != _edges->end()) {
if (it != _traverser->_edges.end()) {
std::string from = triagens::basics::JsonHelper::getStringValue(it->second, "_from", def);
if (from != vertexId) {
return from;
result = from;
}
std::string to = triagens::basics::JsonHelper::getStringValue(it->second, "_to", def);
return to;
else {
std::string to = triagens::basics::JsonHelper::getStringValue(it->second, "_to", def);
result = to;
}
return true;
}
return def;
TRI_ASSERT(false);
result = def;
return false;
}
void ClusterTraverser::EdgeGetter::operator() (std::string const& startVertex,
@ -157,6 +164,10 @@ void ClusterTraverser::EdgeGetter::operator() (std::string const& startVertex,
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
if (! expVertices.empty() && ! verticesToFetch.empty()) {
// There are some vertices that either do not exist or do not match the filter.
// We have to exclude these from the traversal
}
std::string next = stack.top();
stack.pop();
last = &_continueConst;
@ -188,6 +199,50 @@ void ClusterTraverser::setStartVertex (VertexId& v) {
std::string id = v.toString(_resolver);
_enumerator.reset(new triagens::basics::PathEnumerator<std::string, std::string, size_t> (_edgeGetter, _vertexGetter, id));
_done = false;
auto it = _vertices.find(id);
if (it == _vertices.end()) {
triagens::rest::HttpResponse::HttpResponseCode responseCode;
std::map<std::string, std::string> headers;
std::map<std::string, std::string> resultHeaders;
std::vector<std::string> splitId = triagens::basics::StringUtils::split(id, '/');
TRI_ASSERT(splitId.size() == 2);
std::string vertexResult;
int res = getDocumentOnCoordinator(_dbname,
splitId[0],
splitId[1],
0,
headers,
true,
responseCode,
resultHeaders,
vertexResult);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
if (responseCode == triagens::rest::HttpResponse::HttpResponseCode::NOT_FOUND) {
_vertices.emplace(id, nullptr);
}
else {
_vertices.emplace(id, triagens::basics::JsonHelper::fromString(vertexResult));
}
it = _vertices.find(id);
}
auto exp = _expressions->find(0);
if (exp != _expressions->end() && ! vertexMatchesCondition(it->second, exp->second)) {
// We can stop here. The start vertex does not match condition
_done = true;
}
}
bool ClusterTraverser::vertexMatchesCondition (TRI_json_t* v, std::vector<TraverserExpression*> const& exp) {
for (auto const& e : exp) {
if (! e->isEdgeAccess) {
if (v == nullptr || ! e->matchesCheck(v)) {
return false;
}
}
}
return true;
}
const triagens::arango::traverser::TraversalPath* ClusterTraverser::next () {

View File

@ -54,7 +54,7 @@ namespace triagens {
) : Traverser(opts, expressions),
_edgeCols(edgeCollections),
_dbname(dbname),
_vertexGetter(&_edges),
_vertexGetter(this),
_edgeGetter(this),
_resolver(resolver) {
}
@ -72,6 +72,12 @@ namespace triagens {
private:
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
bool vertexMatchesCondition (TRI_json_t*, std::vector<TraverserExpression*> const&);
// -----------------------------------------------------------------------------
// --SECTION-- private classes
// -----------------------------------------------------------------------------
@ -80,15 +86,15 @@ namespace triagens {
public:
VertexGetter (std::unordered_map<std::string, TRI_json_t*> const* edges)
: _edges(edges) {
VertexGetter (ClusterTraverser* traverser)
: _traverser(traverser) {
}
std::string operator() (std::string const&, std::string const&);
bool operator() (std::string const&, std::string const&, size_t, std::string&);
private:
std::unordered_map<std::string, TRI_json_t*> const* _edges;
ClusterTraverser* _traverser;
};

View File

@ -789,18 +789,21 @@ DepthFirstTraverser::DepthFirstTraverser (
}
void DepthFirstTraverser::_defInternalFunctions () {
_getVertex = [] (EdgeInfo& edge, VertexId& vertex) -> VertexId {
_getVertex = [] (EdgeInfo const& edge, VertexId const& vertex, size_t depth, VertexId& result) -> bool {
auto mptr = edge.mptr;
// TODO fill Statistics
if (strcmp(TRI_EXTRACT_MARKER_FROM_KEY(&mptr), vertex.key) == 0 &&
TRI_EXTRACT_MARKER_FROM_CID(&mptr) == vertex.cid) {
return VertexId(TRI_EXTRACT_MARKER_TO_CID(&mptr), TRI_EXTRACT_MARKER_TO_KEY(&mptr));
result = VertexId(TRI_EXTRACT_MARKER_TO_CID(&mptr), TRI_EXTRACT_MARKER_TO_KEY(&mptr));
}
return VertexId(TRI_EXTRACT_MARKER_FROM_CID(&mptr), TRI_EXTRACT_MARKER_FROM_KEY(&mptr));
else {
result = VertexId(TRI_EXTRACT_MARKER_FROM_CID(&mptr), TRI_EXTRACT_MARKER_FROM_KEY(&mptr));
}
return true;
};
if (_opts.direction == TRI_EDGE_ANY) {
_getEdge = [&] (VertexId& startVertex, std::vector<EdgeInfo>& edges, TRI_doc_mptr_copy_t*& last, size_t& eColIdx, bool& dir) {
_getEdge = [&] (VertexId const& startVertex, std::vector<EdgeInfo>& edges, TRI_doc_mptr_copy_t*& last, size_t& eColIdx, bool& dir) {
std::vector<TRI_doc_mptr_copy_t> tmp;
TRI_ASSERT(eColIdx < _edgeCols.size());
// TODO fill Statistics
@ -864,7 +867,9 @@ void DepthFirstTraverser::_defInternalFunctions () {
return;
}
if (! exp->isEdgeAccess) {
VertexId other = _getVertex(e, startVertex);
VertexId other;
// This always returns true and third parameter is ignored
_getVertex(e, startVertex, 0, other);
auto collection = _trx->trxCollection(other.cid);
if (collection == nullptr) {
int res = TRI_AddCollectionTransaction(_trx->getInternals(),
@ -902,7 +907,7 @@ void DepthFirstTraverser::_defInternalFunctions () {
}
};
} else {
_getEdge = [&] (VertexId& startVertex, std::vector<EdgeInfo>& edges, TRI_doc_mptr_copy_t*& last, size_t& eColIdx, bool& dir) {
_getEdge = [&] (VertexId const& startVertex, std::vector<EdgeInfo>& edges, TRI_doc_mptr_copy_t*& last, size_t& eColIdx, bool& dir) {
std::vector<TRI_doc_mptr_copy_t> tmp;
TRI_ASSERT(eColIdx < _edgeCols.size());
// Do not touch the bool parameter, as long as it is default the first encountered nullptr is final
@ -936,7 +941,9 @@ void DepthFirstTraverser::_defInternalFunctions () {
return;
}
if (! exp->isEdgeAccess) {
VertexId other = _getVertex(e, startVertex);
VertexId other;
// This always returns true, third parameter is ignored
_getVertex(e, startVertex, 0, other);
auto collection = _trx->trxCollection(other.cid);
if (collection == nullptr) {
int res = TRI_AddCollectionTransaction(_trx->getInternals(),

View File

@ -261,15 +261,17 @@ namespace triagens {
/// @brief internal function to extract an edge
////////////////////////////////////////////////////////////////////////////////
std::function<void(VertexId&, std::vector<EdgeInfo>&,
std::function<void(VertexId const&,
std::vector<EdgeInfo>&,
TRI_doc_mptr_copy_t*&,
size_t&, bool&)> _getEdge;
size_t&,
bool&)> _getEdge;
////////////////////////////////////////////////////////////////////////////////
/// @brief internal function to extract vertex information
////////////////////////////////////////////////////////////////////////////////
std::function<VertexId (EdgeInfo&, VertexId&)> _getVertex;
std::function<bool (EdgeInfo const&, VertexId const&, size_t, VertexId&)> _getVertex;
////////////////////////////////////////////////////////////////////////////////
/// @brief a vector containing all required edge collection structures

View File

@ -145,10 +145,7 @@ bool TraverserExpression::recursiveCheck (triagens::aql::AstNode const* node,
/// @brief evalutes if an element matches the given expression
////////////////////////////////////////////////////////////////////////////////
bool TraverserExpression::matchesCheck (TRI_doc_mptr_t& element,
TRI_document_collection_t* collection,
CollectionNameResolver const* resolver) const {
DocumentAccessor accessor(resolver, collection, &element);
bool TraverserExpression::matchesCheck (DocumentAccessor& accessor) const {
recursiveCheck(varAccess, accessor);
triagens::basics::Json result = accessor.toJson();
switch (comparisonType) {
@ -167,4 +164,26 @@ bool TraverserExpression::matchesCheck (TRI_doc_mptr_t& element,
default:
TRI_ASSERT(false);
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief evalutes if an element matches the given expression
////////////////////////////////////////////////////////////////////////////////
bool TraverserExpression::matchesCheck (TRI_json_t* element) const {
DocumentAccessor accessor(element);
return matchesCheck(accessor);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief evalutes if an element matches the given expression
////////////////////////////////////////////////////////////////////////////////
bool TraverserExpression::matchesCheck (TRI_doc_mptr_t& element,
TRI_document_collection_t* collection,
CollectionNameResolver const* resolver) const {
DocumentAccessor accessor(resolver, collection, &element);
return matchesCheck(accessor);
}

View File

@ -132,6 +132,10 @@ namespace triagens {
TRI_document_collection_t* collection,
CollectionNameResolver const* resolver) const;
bool matchesCheck (TRI_json_t* element) const;
bool matchesCheck (DocumentAccessor& accessor) const;
private:
bool recursiveCheck (triagens::aql::AstNode const*,