8000 Traversal Bugfix by markuspf · Pull Request #11310 · arangodb/arangodb · GitHub
[go: up one dir, main page]

Skip to content

Traversal Bugfix #11310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions arangod/Aql/TraversalExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,14 @@ std::vector<std::pair<Variable const*, RegisterId>> const& TraversalExecutorInfo
}

TraversalExecutor::TraversalExecutor(Fetcher& fetcher, Infos& infos)
: _infos(infos), _inputRow{CreateInvalidInputRowHint{}}, _traverser(infos.traverser()) {}
: _infos(infos), _inputRow{CreateInvalidInputRowHint{}}, _traverser(infos.traverser()) {

// reset the traverser, so that no residual state is left in it. This is
// important because the TraversalExecutor is sometimes reconstructed (in place)
// with the same TraversalExecutorInfos as before. Those infos contain the traverser
// which might contain state from a previous run.
_traverser.done();
}

TraversalExecutor::~TraversalExecutor() {
auto opts = _traverser.options();
Expand All @@ -169,14 +176,7 @@ std::pair<ExecutionState, Result> TraversalExecutor::shutdown(int errorCode) {
return {ExecutionState::DONE, TRI_ERROR_NO_ERROR};
}

std::pair<ExecutionState, TraversalStats> TraversalExecutor::produceRows(OutputAqlItemRow& output) {
// TODO: Remove me!
TRI_ASSERT(false);
return {ExecutionState::DONE, TraversalStats{}};
}

auto TraversalExecutor::doOutput(OutputAqlItemRow& output) -> void {
// TODO check whether _traverser.hasMore is obsolete here
while (!output.isFull() && _traverser.hasMore() && _traverser.next()) {
TRI_ASSERT(_inputRow.isInitialized());

Expand Down Expand Up @@ -212,6 +212,7 @@ auto TraversalExecutor::doSkip(AqlCall& call) -> size_t {
auto skip = size_t{0};

while (call.shouldSkip() && _traverser.hasMore() && _traverser.next()) {
TRI_ASSERT(_inputRow.isInitialized());
skip++;
call.didSkip(1);
}
Expand Down
8 changes: 0 additions & 8 deletions arangod/Aql/TraversalExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,6 @@ class TraversalExecutor {
*/
std::pair<ExecutionState, Result> shutdown(int errorCode);

/**
* @brief produce the next Row of Aql Values.
*
* @return ExecutionState, and if successful exactly one new Row of AqlItems.
*/
[[nodiscard]] auto produceRows(OutputAqlItemRow& output)
-> std::pair<ExecutionState, Stats>;

[[nodiscard]] auto produceRows(AqlItemBlockInputRange& input, OutputAqlItemRow& output)
-> std::tuple<ExecutorState, Stats, AqlCall>;
[[nodiscard]] auto skipRowsRange(AqlItemBlockInputRange& input, AqlCall& call)
Expand Down
32 changes: 15 additions & 17 deletions arangod/Graph/PathEnumerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,24 @@ using Traverser = arangodb::traverser::Traverser;
using TraverserOptions = arangodb::traverser::TraverserOptions;

PathEnumerator::PathEnumerator(Traverser* traverser, TraverserOptions* opts)
: _traverser(traverser),
_isFirst(true),
_opts(opts),
_httpRequests(0) {}
: _traverser(traverser), _isFirst(true), _opts(opts), _httpRequests(0) {}

PathEnumerator::~PathEnumerator() = default;

void PathEnumerator::setStartVertex(arangodb::velocypack::StringRef startVertex) {
_enumeratedPath.edges.clear();
_enumeratedPath.vertices.clear();
_isFirst = true;
_isFirst = true;
_httpRequests = 0;

_enumeratedPath.vertices.push_back(startVertex);
TRI_ASSERT(_enumeratedPath.vertices.size() == 1);
}

bool PathEnumerator::keepEdge(arangodb::graph::EdgeDocumentToken& eid,
arangodb::velocypack::Slice edge,
arangodb::velocypack::StringRef sourceVertex, size_t depth,
size_t cursorId) {
arangodb::velocypack::StringRef sourceVertex,
size_t depth, size_t cursorId) {
if (_opts->hasEdgeFilter(depth, cursorId)) {
VPackSlice e = edge;
if (edge.isString()) {
Expand All @@ -73,7 +70,8 @@ bool PathEnumerator::keepEdge(arangodb::graph::EdgeDocumentToken& eid,
return _opts->destinationCollectionAllowed(edge, sourceVertex);
}

graph::EdgeCursor* PathEnumerator::getCursor(arangodb::velocypack::StringRef nextVertex, uint64_t currentDepth) {
graph::EdgeCursor* PathEnumerator::getCursor(arangodb::velocypack::StringRef nextVertex,
uint64_t currentDepth) {
if (currentDepth >= _cursors.size()) {
_cursors.emplace_back(_opts->buildCursor(currentDepth));
}
Expand All @@ -83,15 +81,14 @@ graph::EdgeCursor* PathEnumerator::getCursor(arangodb::velocypack::StringRef nex
}

DepthFirstEnumerator::DepthFirstEnumerator(Traverser* traverser, TraverserOptions* opts)
: PathEnumerator(traverser, opts),
_activeCursors(0),
_pruneNext(false) {}
: PathEnumerator(traverser, opts), _activeCursors(0), _pruneNext(false) {}

DepthFirstEnumerator::~DepthFirstEnumerator() = default;

void DepthFirstEnumerator::setStartVertex(arangodb::velocypack::StringRef startVertex) {
PathEnumerator::setStartVertex(startVertex);

_activeCursors = 0;
_pruneNext = false;
}

Expand All @@ -114,7 +111,9 @@ bool DepthFirstEnumerator::next() {
if (_enumeratedPath.edges.size() < _opts->maxDepth && !_pruneNext) {
// We are not done with this path, so
// we reserve the cursor for next depth
graph::EdgeCursor* cursor = getCursor(arangodb::velocypack::StringRef(_enumeratedPath.vertices.back()), _enumeratedPath.edges.size());
graph::EdgeCursor* cursor =
getCursor(arangodb::velocypack::StringRef(_enumeratedPath.vertices.back()),
_enumeratedPath.edges.size());
incHttpRequests(cursor->httpRequests());
++_activeCursors;
} else {
Expand All @@ -131,7 +130,7 @@ bool DepthFirstEnumerator::next() {
auto callback = [&](graph::EdgeDocumentToken&& eid, VPackSlice const& edge, size_t cursorId) {
if (!keepEdge(eid, edge,
arangodb::velocypack::StringRef(_enumeratedPath.vertices.back()),
_enumeratedPath.edges.size(), cursorId)) {
_enumeratedPath.edges.size(), cursorId)) {
return;
}

Expand Down Expand Up @@ -257,13 +256,13 @@ bool DepthFirstEnumerator::shouldPrune() {
if (!_opts->usesPrune()) {
return false;
}

transaction::BuilderLeaser pathBuilder(_opts->trx());
// evaluator->evaluate() might access these, so they have to live long
// enough
aql::AqlValue vertex, edge;
aql::AqlValueGuard vertexGuard{vertex, true}, edgeGuard{edge, true};

aql::PruneExpressionEvaluator* evaluator = _opts->getPruneEvaluator();
TRI_ASSERT(evaluator != nullptr);

Expand All @@ -281,4 +280,3 @@ bool DepthFirstEnumerator::shouldPrune() {
}
return evaluator->evaluate();
}

18 changes: 9 additions & 9 deletions arangod/Graph/PathEnumerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class PathEnumerator {
//////////////////////////////////////////////////////////////////////////////

EnumeratedPath _enumeratedPath;

//////////////////////////////////////////////////////////////////////////////
/// @brief Number of HTTP requests made
//////////////////////////////////////////////////////////////////////////////
Expand All @@ -96,7 +96,7 @@ class PathEnumerator {
PathEnumerator(Traverser* traverser, TraverserOptions* opts);

virtual ~PathEnumerator();

/// @brief set start vertex and reset
/// note that the caller *must* guarantee that the string data pointed to by
/// startVertex remains valid even after the call to reset()!!
Expand All @@ -113,19 +113,19 @@ class PathEnumerator {
virtual aql::AqlValue lastVertexToAqlValue() = 0;
virtual aql::AqlValue lastEdgeToAqlValue() = 0;
virtual aql::AqlValue pathToAqlValue(arangodb::velocypack::Builder&) = 0;

/// @brief return number of HTTP requests made, and reset it to 0
size_t getAndResetHttpRequests() {
size_t getAndResetHttpRequests() {
size_t value = _httpRequests;
_httpRequests = 0;
return value;
}

void incHttpRequests(size_t requests) { _httpRequests += requests; }

protected:
graph::EdgeCursor* getCursor(arangodb::velocypack::StringRef nextVertex, uint64_t currentDepth);

/// @brief The vector of EdgeCursors to walk through.
std::vector<std::unique_ptr<graph::EdgeCursor>> _cursors;
};
Expand All @@ -144,7 +144,7 @@ class DepthFirstEnumerator final : public PathEnumerator {
DepthFirstEnumerator(Traverser* traverser, TraverserOptions* opts);

~DepthFirstEnumerator();

/// @brief set start vertex and reset
void setStartVertex(arangodb::velocypack::StringRef startVertex) override;

Expand All @@ -159,7 +159,7 @@ class DepthFirstEnumerator final : public PathEnumerator {

private:
bool shouldPrune();

velocypack::Slice pathToSlice(arangodb::velocypack::Builder& result);
};
} // namespace traverser
Expand Down
Loading
0