1
0
Fork 0

Replaced OperationCursor by shared_ptrs every where and removed the slice function from it. Instead it returns a shared ptr on a OperationResult on getMore

This commit is contained in:
Michael Hackstein 2016-03-17 18:49:20 +01:00
parent f0b860cc72
commit 401f55ae37
17 changed files with 449 additions and 322 deletions

View File

@ -33,23 +33,26 @@ CollectionScanner::CollectionScanner(arangodb::AqlTransaction* trx,
(readRandom ? Transaction::CursorType::ANY
: Transaction::CursorType::ALL),
"", VPackSlice(), 0, UINT64_MAX, 1000, false)) {
TRI_ASSERT(_cursor.successful());
TRI_ASSERT(_cursor->successful());
}
CollectionScanner::~CollectionScanner() {}
VPackSlice CollectionScanner::scan(size_t batchSize) {
if (!_cursor.hasMore()) {
if (!_cursor->hasMore()) {
return arangodb::basics::VelocyPackHelper::EmptyArrayValue();
}
_cursor.getMore(batchSize, true);
return _cursor.slice();
_cursor->getMore(_currentBatch, batchSize, true);
if (_currentBatch->failed()) {
return arangodb::basics::VelocyPackHelper::EmptyArrayValue();
}
return _currentBatch->slice();
}
int CollectionScanner::forward(size_t batchSize, uint64_t& skipped) {
return _cursor.skip(batchSize, skipped);
return _cursor->skip(batchSize, skipped);
}
void CollectionScanner::reset() {
_cursor.reset();
_cursor->reset();
}

View File

@ -51,7 +51,8 @@ class CollectionScanner {
int forward(size_t, uint64_t&);
private:
OperationCursor _cursor;
std::shared_ptr<OperationCursor> _cursor;
std::shared_ptr<OperationResult> _currentBatch;
};
}
}

View File

@ -530,16 +530,20 @@ static void RequestEdges(VPackSlice const& vertexSlice,
VPackBuilder searchValueBuilder;
EdgeIndex::buildSearchValue(direction, vertexId, searchValueBuilder);
VPackSlice search = searchValueBuilder.slice();
OperationCursor cursor = trx->indexScan(
std::shared_ptr<OperationCursor> cursor = trx->indexScan(
collectionName, arangodb::Transaction::CursorType::INDEX, indexId,
search, 0, UINT64_MAX, 1000, false);
if (cursor.failed()) {
THROW_ARANGO_EXCEPTION(cursor.code);
if (cursor->failed()) {
THROW_ARANGO_EXCEPTION(cursor->code);
}
while (cursor.hasMore()) {
cursor.getMore();
VPackSlice edges = cursor.slice();
auto opRes = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
while (cursor->hasMore()) {
cursor->getMore(opRes);
if (opRes->failed()) {
THROW_ARANGO_EXCEPTION(opRes->code);
}
VPackSlice edges = opRes->slice();
TRI_ASSERT(edges.isArray());
if (includeVertices) {
for (auto const& edge : VPackArrayIterator(edges)) {

View File

@ -309,25 +309,23 @@ bool IndexBlock::initIndexes() {
/// @brief create an OperationCursor object
////////////////////////////////////////////////////////////////////////////////
std::unique_ptr<arangodb::OperationCursor> IndexBlock::createCursor() {
std::shared_ptr<arangodb::OperationCursor> IndexBlock::createCursor() {
IndexNode const* node = static_cast<IndexNode const*>(getPlanNode());
auto outVariable = node->outVariable();
auto ast = node->_plan->getAst();
if (_condition == nullptr) {
return std::make_unique<arangodb::OperationCursor>(
ast->query()->trx()->indexScanForCondition(
_collection->getName(), _indexes[_currentIndex], ast, nullptr,
outVariable, UINT64_MAX, TRI_DEFAULT_BATCH_SIZE, node->_reverse));
return ast->query()->trx()->indexScanForCondition(
_collection->getName(), _indexes[_currentIndex], ast, nullptr,
outVariable, UINT64_MAX, TRI_DEFAULT_BATCH_SIZE, node->_reverse);
}
TRI_ASSERT(_indexes.size() == _condition->numMembers());
return std::make_unique<arangodb::OperationCursor>(
ast->query()->trx()->indexScanForCondition(
return ast->query()->trx()->indexScanForCondition(
_collection->getName(), _indexes[_currentIndex], ast,
_condition->getMember(_currentIndex), outVariable, UINT64_MAX,
TRI_DEFAULT_BATCH_SIZE, node->_reverse));
TRI_DEFAULT_BATCH_SIZE, node->_reverse);
}
////////////////////////////////////////////////////////////////////////////////
@ -379,48 +377,43 @@ bool IndexBlock::readIndex(size_t atMost) {
bool isReverse = (static_cast<IndexNode const*>(getPlanNode()))->_reverse;
bool isLastIndex = (_currentIndex == lastIndexNr && !isReverse) ||
(_currentIndex == 0 && isReverse);
try {
while (_cursor != nullptr) {
if (!_cursor->hasMore()) {
startNextCursor();
continue;
}
int res = _cursor->getMore(atMost, true);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
VPackSlice slice = _cursor->slice();
TRI_ASSERT(slice.isArray());
size_t length = static_cast<size_t>(slice.length());
auto result = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
while (_cursor != nullptr) {
if (!_cursor->hasMore()) {
startNextCursor();
continue;
}
_cursor->getMore(result, atMost, true);
if (result->failed()) {
THROW_ARANGO_EXCEPTION(result->code);
}
VPackSlice slice = result->slice();
TRI_ASSERT(slice.isArray());
size_t length = static_cast<size_t>(slice.length());
if (length == 0) {
startNextCursor();
continue;
}
if (length == 0) {
startNextCursor();
continue;
}
_engine->_stats.scannedIndex += length;
_engine->_stats.scannedIndex += length;
TRI_IF_FAILURE("IndexBlock::readIndex") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
TRI_IF_FAILURE("IndexBlock::readIndex") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
for (auto const& doc : VPackArrayIterator(slice)) {
std::string key =
arangodb::basics::VelocyPackHelper::getStringValue(doc, "_key", "");
if (_alreadyReturned.find(key) == _alreadyReturned.end()) {
if (!isLastIndex) {
_alreadyReturned.emplace(key);
}
_documents.emplace_back(doc);
for (auto const& doc : VPackArrayIterator(slice)) {
std::string key =
arangodb::basics::VelocyPackHelper::getStringValue(doc, "_key", "");
if (_alreadyReturned.find(key) == _alreadyReturned.end()) {
if (!isLastIndex) {
_alreadyReturned.emplace(key);
}
_documents.emplace_back(doc);
}
// Leave the loop here, we can only exhaust one cursor at a time, otherwise slices are lost
break;
}
} catch (...) {
if (_cursor != nullptr) {
_cursor.release();
}
// Leave the loop here, we can only exhaust one cursor at a time, otherwise slices are lost
break;
}
_posInDocs = 0;
return (!_documents.empty());

View File

@ -86,7 +86,7 @@ class IndexBlock : public ExecutionBlock {
/// @brief create an iterator object
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<arangodb::OperationCursor> createCursor();
std::shared_ptr<arangodb::OperationCursor> createCursor();
//////////////////////////////////////////////////////////////////////////////
/// @brief Forwards _cursor to the next available index
@ -182,7 +182,7 @@ class IndexBlock : public ExecutionBlock {
/// necessarily all at once.
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<arangodb::OperationCursor> _cursor;
std::shared_ptr<arangodb::OperationCursor> _cursor;
//////////////////////////////////////////////////////////////////////////////
/// @brief _condition: holds the complete condition this Block can serve for

View File

@ -48,7 +48,7 @@ TraversalBlock::TraversalBlock(ExecutionEngine* engine, TraversalNode const* ep)
_resolver(nullptr),
_expressions(ep->expressions()),
_hasV8Expression(false) {
arangodb::traverser::TraverserOptions opts;
arangodb::traverser::TraverserOptions opts(_trx);
ep->fillTraversalOptions(opts);
auto ast = ep->_plan->getAst();
@ -98,7 +98,7 @@ TraversalBlock::TraversalBlock(ExecutionEngine* engine, TraversalNode const* ep)
_trx->orderDitch(cid);
}
_traverser.reset(new arangodb::traverser::DepthFirstTraverser(
edgeCollections, opts, _resolver, _trx, _expressions));
edgeCollections, opts, _trx, _expressions));
}
if (!ep->usesInVariable()) {
_vertexId = ep->getStartVertex();
@ -261,7 +261,6 @@ bool TraversalBlock::morePaths(size_t hint) {
_engine->_stats.filtered += _traverser->getAndResetFilteredPaths();
return false;
}
auto en = static_cast<TraversalNode const*>(getPlanNode());
VPackBuilder tmp;
for (size_t j = 0; j < hint; ++j) {

View File

@ -110,7 +110,6 @@ class ClusterTraverser : public Traverser {
CollectionNameResolver const* _resolver;
#warning INITIALIZE
arangodb::velocypack::Builder _builder;
#warning INITIALIZE

View File

@ -22,6 +22,8 @@
////////////////////////////////////////////////////////////////////////////////
#include "OperationCursor.h"
#include "OperationResult.h"
#include "Basics/Exceptions.h"
#include "Logger/Logger.h"
#include "VocBase/MasterPointer.h"
@ -36,55 +38,63 @@ void OperationCursor::reset() {
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Get next default batchSize many elements.
/// @brief Get next batchSize many elements.
/// Defaults to _batchSize
/// Check hasMore()==true before using this
/// NOTE: This will throw on OUT_OF_MEMORY
//////////////////////////////////////////////////////////////////////////////
int OperationCursor::getMore() {
return getMore(_batchSize);
std::shared_ptr<OperationResult> OperationCursor::getMore(uint64_t batchSize,
bool useExternals) {
auto res = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
getMore(res, batchSize, useExternals);
return res;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Get next batchSize many elements.
/// Check hasMore()==true before using this
/// If useExternals is set to true all elements in the vpack are
/// externals. Otherwise they are inlined.
/// NOTE: This will throw on OUT_OF_MEMORY
//////////////////////////////////////////////////////////////////////////////
int OperationCursor::getMore(uint64_t batchSize, bool useExternals) {
void OperationCursor::getMore(std::shared_ptr<OperationResult>& opRes,
uint64_t batchSize, bool useExternals) {
if (opRes == nullptr) {
// Create a valid pointer if none is given
auto tmp = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
opRes.swap(tmp);
}
// This may throw out of memory
if (!hasMore()) {
TRI_ASSERT(false);
// You requested more even if you should have checked it before.
return TRI_ERROR_FORBIDDEN;
opRes->code = TRI_ERROR_FORBIDDEN;
}
if (batchSize == UINT64_MAX) {
batchSize = _batchSize;
}
VPackBuilder builder(buffer);
VPackArrayBuilder guard(&builder);
TRI_doc_mptr_t* mptr = nullptr;
// TODO: Improve this for baby awareness
while (batchSize > 0 && _limit > 0 && (mptr = _indexIterator->next()) != nullptr) {
--batchSize;
--_limit;
VPackBuilder builder(opRes->buffer);
builder.clear();
try {
VPackArrayBuilder guard(&builder);
TRI_doc_mptr_t* mptr = nullptr;
// TODO: Improve this for baby awareness
while (batchSize > 0 && _limit > 0 && (mptr = _indexIterator->next()) != nullptr) {
--batchSize;
--_limit;
#if 0
if (useExternals) {
builder.add(VPackValue(mptr->vpack(), VPackValueType::External));
} else {
if (useExternals) {
builder.add(VPackValue(mptr->vpack(), VPackValueType::External));
} else {
#endif
builder.add(VPackSlice(mptr->vpack()));
builder.add(VPackSlice(mptr->vpack()));
#if 0
}
}
#endif
}
if (batchSize > 0 || _limit == 0) {
// Iterator empty, there is no more
_hasMore = false;
}
opRes->code = TRI_ERROR_NO_ERROR;
} catch (arangodb::basics::Exception const& e) {
opRes->code = e.code();
}
if (batchSize > 0 || _limit == 0) {
// Iterator empty, there is no more
_hasMore = false;
}
return TRI_ERROR_NO_ERROR;
}
//////////////////////////////////////////////////////////////////////////////

View File

@ -38,8 +38,13 @@ namespace arangodb {
// FORWARD declaration
class IndexIterator;
struct OperationResult;
struct OperationCursor : public OperationResult {
struct OperationCursor {
public:
int code;
std::shared_ptr<VPackCustomTypeHandler> customTypeHandler;
private:
@ -50,34 +55,21 @@ struct OperationCursor : public OperationResult {
uint64_t const _batchSize;
public:
explicit OperationCursor(int code)
: OperationResult(code), _hasMore(false), _limit(0), _originalLimit(0), _batchSize(1000) {
}
OperationCursor(int code, std::string const& message)
: OperationResult(code, message), _hasMore(false), _limit(0), _originalLimit(0), _batchSize(1000) {
}
OperationCursor(std::shared_ptr<VPackBuffer<uint8_t>> buffer,
std::shared_ptr<VPackCustomTypeHandler> handler,
std::string const& message,
int code,
bool wasSynchronous)
: OperationResult(buffer, handler, message, code, wasSynchronous),
explicit OperationCursor(int code)
: code(code),
customTypeHandler(),
_hasMore(false),
_limit(0),
_originalLimit(0),
_batchSize(1000) {
}
_batchSize(1000) {}
OperationCursor(std::shared_ptr<VPackCustomTypeHandler> handler, IndexIterator* iterator,
uint64_t limit, uint64_t batchSize)
: OperationResult(std::make_shared<VPackBuffer<uint8_t>>(), handler, "",
TRI_ERROR_NO_ERROR, false),
OperationCursor(std::shared_ptr<VPackCustomTypeHandler> handler,
IndexIterator* iterator, uint64_t limit, uint64_t batchSize)
: code(TRI_ERROR_NO_ERROR),
customTypeHandler(handler),
_indexIterator(iterator),
_hasMore(true),
_limit(limit), // _limit is modified later on
_limit(limit), // _limit is modified later on
_originalLimit(limit),
_batchSize(batchSize) {
if (_indexIterator == nullptr) {
@ -96,6 +88,14 @@ struct OperationCursor : public OperationResult {
return _hasMore;
}
bool successful() const {
return code == TRI_ERROR_NO_ERROR;
}
bool failed() const {
return !successful();
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Reset the cursor
//////////////////////////////////////////////////////////////////////////////
@ -104,19 +104,23 @@ struct OperationCursor : public OperationResult {
//////////////////////////////////////////////////////////////////////////////
/// @brief Get next batchSize many elements.
/// Defaults to _batchSize
/// Check hasMore()==true before using this
/// NOTE: This will throw on OUT_OF_MEMORY
//////////////////////////////////////////////////////////////////////////////
int getMore(uint64_t, bool useExternals = false);
std::shared_ptr<OperationResult> getMore(uint64_t batchSize = UINT64_MAX,
bool useExternals = false);
//////////////////////////////////////////////////////////////////////////////
/// @brief Get next default batchSize many elements.
/// @brief Get next batchSize many elements.
/// Defaults to _batchSize
/// Check hasMore()==true before using this
/// NOTE: This will throw on OUT_OF_MEMORY
//////////////////////////////////////////////////////////////////////////////
int getMore();
void getMore(std::shared_ptr<OperationResult>&, uint64_t batchSize = UINT64_MAX,
bool useExternals = false);
//////////////////////////////////////////////////////////////////////////////
/// @brief Skip the next toSkip many elements.
@ -126,6 +130,7 @@ struct OperationCursor : public OperationResult {
//////////////////////////////////////////////////////////////////////////////
int skip(uint64_t, uint64_t&);
};
}

View File

@ -766,17 +766,20 @@ OperationResult Transaction::anyLocal(std::string const& collectionName,
VPackBuilder resultBuilder;
resultBuilder.openArray();
OperationCursor cursor = indexScan(collectionName, Transaction::CursorType::ANY, "", {}, skip, limit, 1000, false);
while (cursor.hasMore()) {
int res = cursor.getMore();
std::shared_ptr<OperationCursor> cursor =
indexScan(collectionName, Transaction::CursorType::ANY, "", {}, skip,
limit, 1000, false);
if (res != TRI_ERROR_NO_ERROR) {
return OperationResult(res);
auto result = std::make_shared<OperationResult>();
while (cursor->hasMore()) {
cursor->getMore(result);
if (result->failed()) {
return OperationResult(result->code);
}
VPackSlice docs = cursor.slice();
VPackSlice docs = result->slice();
VPackArrayIterator it(docs);
while (it.valid()) {
resultBuilder.add(it.value());
@ -789,7 +792,7 @@ OperationResult Transaction::anyLocal(std::string const& collectionName,
res = unlock(trxCollection(cid), TRI_TRANSACTION_READ);
if (res != TRI_ERROR_NO_ERROR) {
return OperationCursor(res);
return OperationResult(res);
}
return OperationResult(resultBuilder.steal(),
@ -845,6 +848,23 @@ std::string Transaction::collectionName(TRI_voc_cid_t cid) {
return resolver()->getCollectionName(cid);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief return the edge index handle of collection
//////////////////////////////////////////////////////////////////////////////
std::string Transaction::edgeIndexHandle(std::string const& collectionName) {
if (!isEdgeCollection(collectionName)) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_TYPE_INVALID);
}
std::vector<Index*> indexes = indexesForCollection(collectionName);
for (auto idx : indexes) {
if (idx->type() == Index::TRI_IDX_TYPE_EDGE_INDEX) {
return arangodb::basics::StringUtils::itoa(idx->id());
}
}
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_TYPE_INVALID);
}
//////////////////////////////////////////////////////////////////////////////
/// @brief Iterate over all elements of the collection.
//////////////////////////////////////////////////////////////////////////////
@ -1668,18 +1688,21 @@ OperationResult Transaction::allKeysLocal(std::string const& collectionName,
VPackBuilder resultBuilder;
resultBuilder.add(VPackValue(VPackValueType::Object));
resultBuilder.add("documents", VPackValue(VPackValueType::Array));
OperationCursor cursor = indexScan(collectionName, Transaction::CursorType::ALL, "", {}, 0, UINT64_MAX, 1000, false);
while (cursor.hasMore()) {
int res = cursor.getMore();
std::shared_ptr<OperationCursor> cursor =
indexScan(collectionName, Transaction::CursorType::ALL, "", {}, 0,
UINT64_MAX, 1000, false);
if (res != TRI_ERROR_NO_ERROR) {
return OperationResult(res);
auto result = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
while (cursor->hasMore()) {
cursor->getMore(result);
if (result->failed()) {
return OperationResult(result->code);
}
std::string value;
VPackSlice docs = cursor.slice();
VPackSlice docs = result->slice();
VPackArrayIterator it(docs);
while (it.valid()) {
value.assign(prefix);
@ -1695,7 +1718,7 @@ OperationResult Transaction::allKeysLocal(std::string const& collectionName,
res = unlock(trxCollection(cid), TRI_TRANSACTION_READ);
if (res != TRI_ERROR_NO_ERROR) {
return OperationCursor(res);
return OperationResult(res);
}
return OperationResult(resultBuilder.steal(),
@ -1754,17 +1777,20 @@ OperationResult Transaction::allLocal(std::string const& collectionName,
VPackBuilder resultBuilder;
resultBuilder.openArray();
OperationCursor cursor = indexScan(collectionName, Transaction::CursorType::ALL, "", {}, skip, limit, 1000, false);
while (cursor.hasMore()) {
int res = cursor.getMore();
std::shared_ptr<OperationCursor> cursor =
indexScan(collectionName, Transaction::CursorType::ALL, "", {}, skip,
limit, 1000, false);
if (res != TRI_ERROR_NO_ERROR) {
return OperationResult(res);
auto result = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
while (cursor->hasMore()) {
cursor->getMore(result);
if (result->failed()) {
return OperationResult(result->code);
}
VPackSlice docs = cursor.slice();
VPackSlice docs = result->slice();
VPackArrayIterator it(docs);
while (it.valid()) {
resultBuilder.add(it.value());
@ -1777,7 +1803,7 @@ OperationResult Transaction::allLocal(std::string const& collectionName,
res = unlock(trxCollection(cid), TRI_TRANSACTION_READ);
if (res != TRI_ERROR_NO_ERROR) {
return OperationCursor(res);
return OperationResult(res);
}
return OperationResult(resultBuilder.steal(),
@ -1864,7 +1890,7 @@ OperationResult Transaction::truncateLocal(std::string const& collectionName,
res = unlock(trxCollection(cid), TRI_TRANSACTION_WRITE);
if (res != TRI_ERROR_NO_ERROR) {
return OperationCursor(res);
return OperationResult(res);
}
return OperationResult(TRI_ERROR_NO_ERROR);
@ -2095,7 +2121,7 @@ std::pair<bool, bool> Transaction::getIndexForSortCondition(
/// calling this method
//////////////////////////////////////////////////////////////////////////////
OperationCursor Transaction::indexScanForCondition(
std::shared_ptr<OperationCursor> Transaction::indexScanForCondition(
std::string const& collectionName, std::string const& indexId,
arangodb::aql::Ast* ast, arangodb::aql::AstNode const* condition,
arangodb::aql::Variable const* var, uint64_t limit, uint64_t batchSize,
@ -2111,7 +2137,7 @@ OperationCursor Transaction::indexScanForCondition(
if (limit == 0) {
// nothing to do
return OperationCursor(TRI_ERROR_NO_ERROR);
return std::make_shared<OperationCursor>(TRI_ERROR_NO_ERROR);
}
// Now collect the Iterator
@ -2121,11 +2147,12 @@ OperationCursor Transaction::indexScanForCondition(
if (iterator == nullptr) {
// We could not create an ITERATOR and it did not throw an error itself
return OperationCursor(TRI_ERROR_OUT_OF_MEMORY);
return std::make_shared<OperationCursor>(TRI_ERROR_OUT_OF_MEMORY);
}
return OperationCursor(transactionContext()->orderCustomTypeHandler(),
iterator.release(), limit, batchSize);
return std::make_shared<OperationCursor>(
transactionContext()->orderCustomTypeHandler(), iterator.release(), limit,
batchSize);
}
//////////////////////////////////////////////////////////////////////////////
@ -2171,11 +2198,10 @@ arangodb::Index* Transaction::getIndexByIdentifier(
/// calling this method
//////////////////////////////////////////////////////////////////////////////
OperationCursor Transaction::indexScan(
std::shared_ptr<OperationCursor> Transaction::indexScan(
std::string const& collectionName, CursorType cursorType,
std::string const& indexId, VPackSlice const search,
uint64_t skip, uint64_t limit, uint64_t batchSize, bool reverse) {
std::string const& indexId, VPackSlice const search, uint64_t skip,
uint64_t limit, uint64_t batchSize, bool reverse) {
#warning TODO Who checks if indexId is valid and is used for this collection?
// For now we assume indexId is the iid part of the index.
@ -2187,12 +2213,12 @@ OperationCursor Transaction::indexScan(
TRI_voc_cid_t cid = resolver()->getCollectionIdLocal(collectionName);
if (cid == 0) {
return OperationCursor(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
return std::make_shared<OperationCursor>(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
}
if (limit == 0) {
// nothing to do
return OperationCursor(TRI_ERROR_NO_ERROR);
return std::make_shared<OperationCursor>(TRI_ERROR_NO_ERROR);
}
TRI_document_collection_t* document = documentCollection(trxCollection(cid));
@ -2267,14 +2293,15 @@ OperationCursor Transaction::indexScan(
}
if (iterator == nullptr) {
// We could not create an ITERATOR and it did not throw an error itself
return OperationCursor(TRI_ERROR_OUT_OF_MEMORY);
return std::make_shared<OperationCursor>(TRI_ERROR_OUT_OF_MEMORY);
}
uint64_t unused = 0;
iterator->skip(skip, unused);
return OperationCursor(transactionContext()->orderCustomTypeHandler(),
iterator.release(), limit, batchSize);
return std::make_shared<OperationCursor>(
transactionContext()->orderCustomTypeHandler(), iterator.release(), limit,
batchSize);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -307,6 +307,12 @@ class Transaction {
std::string collectionName(TRI_voc_cid_t cid);
//////////////////////////////////////////////////////////////////////////////
/// @brief return the edge index handle of collection
//////////////////////////////////////////////////////////////////////////////
std::string edgeIndexHandle(std::string const&);
//////////////////////////////////////////////////////////////////////////////
/// @brief Iterate over all elements of the collection.
//////////////////////////////////////////////////////////////////////////////
@ -439,12 +445,10 @@ class Transaction {
/// calling this method
//////////////////////////////////////////////////////////////////////////////
OperationCursor indexScanForCondition(std::string const& collectionName,
std::string const& indexId,
arangodb::aql::Ast*,
arangodb::aql::AstNode const*,
arangodb::aql::Variable const*,
uint64_t, uint64_t, bool);
std::shared_ptr<OperationCursor> indexScanForCondition(
std::string const& collectionName, std::string const& indexId,
arangodb::aql::Ast*, arangodb::aql::AstNode const*,
arangodb::aql::Variable const*, uint64_t, uint64_t, bool);
//////////////////////////////////////////////////////////////////////////////
/// @brief factory for OperationCursor objects
@ -452,14 +456,12 @@ class Transaction {
/// calling this method
//////////////////////////////////////////////////////////////////////////////
OperationCursor indexScan(std::string const& collectionName,
CursorType cursorType,
std::string const& indexId,
VPackSlice const search,
uint64_t skip,
uint64_t limit,
uint64_t batchSize,
bool reverse);
std::shared_ptr<OperationCursor> indexScan(std::string const& collectionName,
CursorType cursorType,
std::string const& indexId,
VPackSlice const search,
uint64_t skip, uint64_t limit,
uint64_t batchSize, bool reverse);
//////////////////////////////////////////////////////////////////////////////
/// @brief test if a collection is already locked

View File

@ -92,9 +92,8 @@ EdgeCollectionInfo::EdgeCollectionInfo(arangodb::Transaction* trx,
/// @brief Get edges for the given direction and start vertex.
////////////////////////////////////////////////////////////////////////////////
OperationCursor EdgeCollectionInfo::getEdges(TRI_edge_direction_e direction,
std::string const& vertexId) {
std::shared_ptr<OperationCursor> EdgeCollectionInfo::getEdges(
TRI_edge_direction_e direction, std::string const& vertexId) {
_searchBuilder.clear();
EdgeIndex::buildSearchValue(direction, vertexId, _searchBuilder);
return _trx->indexScan(_collectionName,
@ -187,12 +186,13 @@ class MultiCollectionEdgeExpander {
}
};
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
auto opRes = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
while (edgeCursor->hasMore()) {
edgeCursor->getMore(opRes);
if (opRes->failed()) {
THROW_ARANGO_EXCEPTION(opRes->code);
}
VPackSlice edges = edgeCursor.slice();
VPackSlice edges = opRes->slice();
for (auto const& edge : VPackArrayIterator(edges)) {
if (!_isAllowed(edge)) {
@ -255,12 +255,13 @@ class SimpleEdgeExpander {
};
auto edgeCursor = _edgeCollection->getEdges(_direction, source);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
auto opRes = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
while (edgeCursor->hasMore()) {
edgeCursor->getMore(opRes);
if (opRes->failed()) {
THROW_ARANGO_EXCEPTION(opRes->code);
}
VPackSlice edges = edgeCursor.slice();
VPackSlice edges = opRes->slice();
for (auto const& edge : VPackArrayIterator(edges)) {
std::string const from = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
std::string const to = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
@ -516,13 +517,14 @@ TRI_RunSimpleShortestPathSearch(
std::vector<std::string>& neighbors) {
for (auto const& edgeCollection : collectionInfos) {
TRI_ASSERT(edgeCollection != nullptr);
OperationCursor edgeCursor = edgeCollection->getEdges(forward, v);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
std::shared_ptr<OperationCursor> edgeCursor = edgeCollection->getEdges(forward, v);
auto opRes = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
while (edgeCursor->hasMore()) {
edgeCursor->getMore(opRes);
if (opRes->failed()) {
THROW_ARANGO_EXCEPTION(opRes->code);
}
VPackSlice edges = edgeCursor.slice();
VPackSlice edges = opRes->slice();
for (auto const& edge : VPackArrayIterator(edges)) {
std::string edgeId = trx->extractIdString(edge);
@ -545,15 +547,16 @@ TRI_RunSimpleShortestPathSearch(
auto bwExpander =
[&collectionInfos, backward, trx](std::string const& v, std::vector<std::string>& res_edges,
std::vector<std::string>& neighbors) {
auto opRes = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
for (auto const& edgeCollection : collectionInfos) {
TRI_ASSERT(edgeCollection != nullptr);
OperationCursor edgeCursor = edgeCollection->getEdges(backward, v);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
std::shared_ptr<OperationCursor> edgeCursor = edgeCollection->getEdges(backward, v);
while (edgeCursor->hasMore()) {
edgeCursor->getMore(opRes);
if (opRes->failed()) {
THROW_ARANGO_EXCEPTION(opRes->code);
}
VPackSlice edges = edgeCursor.slice();
VPackSlice edges = opRes->slice();
for (auto const& edge : VPackArrayIterator(edges)) {
std::string edgeId = trx->extractIdString(edge);
@ -593,17 +596,18 @@ static void InboundNeighbors(std::vector<EdgeCollectionInfo*>& collectionInfos,
TRI_edge_direction_e dir = TRI_EDGE_IN;
std::unordered_set<std::string> nextDepth;
auto opRes = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
for (auto const& col : collectionInfos) {
TRI_ASSERT(col != nullptr);
for (auto const& start : startVertices) {
auto edgeCursor = col->getEdges(dir, start);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
while (edgeCursor->hasMore()) {
edgeCursor->getMore(opRes);
if (opRes->failed()) {
THROW_ARANGO_EXCEPTION(opRes->code);
}
VPackSlice edges = edgeCursor.slice();
VPackSlice edges = opRes->slice();
for (auto const& edge : VPackArrayIterator(edges)) {
if (opts.matchesEdge(edge)) {
std::string v = edge.get(TRI_VOC_ATTRIBUTE_FROM).copyString();
@ -644,18 +648,19 @@ static void OutboundNeighbors(std::vector<EdgeCollectionInfo*>& collectionInfos,
uint64_t depth = 1) {
TRI_edge_direction_e dir = TRI_EDGE_OUT;
std::unordered_set<std::string> nextDepth;
auto opRes = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
for (auto const& col : collectionInfos) {
TRI_ASSERT(col != nullptr);
for (auto const& start : startVertices) {
auto edgeCursor = col->getEdges(dir, start);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
while (edgeCursor->hasMore()) {
edgeCursor->getMore(opRes);
if (opRes->failed()) {
THROW_ARANGO_EXCEPTION(opRes->code);
}
VPackSlice edges = edgeCursor.slice();
VPackSlice edges = opRes->slice();
for (auto const& edge : VPackArrayIterator(edges)) {
if (opts.matchesEdge(edge)) {
std::string v = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
@ -697,18 +702,19 @@ static void AnyNeighbors(std::vector<EdgeCollectionInfo*>& collectionInfos,
TRI_edge_direction_e dir = TRI_EDGE_ANY;
std::unordered_set<std::string> nextDepth;
auto opRes = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
for (auto const& col : collectionInfos) {
TRI_ASSERT(col != nullptr);
for (auto const& start : startVertices) {
auto edgeCursor = col->getEdges(dir, start);
while (edgeCursor.hasMore()) {
int res = edgeCursor.getMore();
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
while (edgeCursor->hasMore()) {
edgeCursor->getMore(opRes);
if (opRes->failed()) {
THROW_ARANGO_EXCEPTION(opRes->code);
}
VPackSlice edges = edgeCursor.slice();
VPackSlice edges = opRes->slice();
for (auto const& edge : VPackArrayIterator(edges)) {
if (opts.matchesEdge(edge)) {
std::string v = edge.get(TRI_VOC_ATTRIBUTE_TO).copyString();
@ -815,11 +821,11 @@ void SingleServerTraversalPath::lastVertexToVelocyPack(Transaction* trx, VPackBu
DepthFirstTraverser::DepthFirstTraverser(
std::vector<TRI_document_collection_t*> const& edgeCollections,
TraverserOptions& opts, CollectionNameResolver* resolver, Transaction* trx,
TraverserOptions& opts, Transaction* trx,
std::unordered_map<size_t, std::vector<TraverserExpression*>> const*
expressions)
: Traverser(opts, expressions),
_edgeGetter(this, opts, resolver, trx),
_edgeGetter(this, opts, trx),
_edgeCols(edgeCollections),
_trx(trx) {
_defInternalFunctions();
@ -941,7 +947,7 @@ void DepthFirstTraverser::setStartVertex(
}
}
}
_enumerator.reset(new PathEnumerator<std::string, std::string, TRI_doc_mptr_t>(
_enumerator.reset(new PathEnumerator<std::string, std::string, VPackValueLength>(
_edgeGetter, _getVertex, v));
_done = false;
}
@ -971,90 +977,95 @@ TraversalPath* DepthFirstTraverser::next() {
return p.release();
}
EdgeIndex* DepthFirstTraverser::EdgeGetter::getEdgeIndex(
std::string const& eColName,
TRI_voc_cid_t& cid) {
auto it = _indexCache.find(eColName);
if (it == _indexCache.end()) {
cid = _resolver->getCollectionIdLocal(eColName);
TRI_document_collection_t* documentCollection = _trx->documentCollection(cid);
arangodb::EdgeIndex* edgeIndex = documentCollection->edgeIndex();
_indexCache.emplace(eColName, std::make_pair(cid, edgeIndex));
return edgeIndex;
bool DepthFirstTraverser::EdgeGetter::nextCursor(std::string const& startVertex,
size_t& eColIdx,
VPackValueLength*& last) {
while (true) {
std::string eColName;
std::string indexHandle;
if (last != nullptr) {
// The cursor is empty clean up
last = nullptr;
_posInCursor.pop();
_cursors.pop();
_results.pop();
}
if (!_opts.getCollectionAndSearchValue(eColIdx, startVertex, eColName, indexHandle,
_builder)) {
// If we get here there are no valid edges at all
return false;
}
std::shared_ptr<OperationCursor> cursor = _trx->indexScan(
eColName, arangodb::Transaction::CursorType::INDEX, indexHandle,
_builder.slice(), 0, UINT64_MAX, TRI_DEFAULT_BATCH_SIZE, false);
if (cursor->failed()) {
// Some error, ignore and go to next
eColIdx++;
continue;
}
TRI_ASSERT(_posInCursor.size() == _cursors.size());
_cursors.push(cursor);
_results.emplace(std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR));
return true;
}
}
cid = it->second.first;
return it->second.second;
void DepthFirstTraverser::EdgeGetter::nextEdge(
std::string const& startVertex, size_t& eColIdx, VPackValueLength*& last,
std::vector<std::string>& edges) {
auto cursor = _cursors.top();
auto opRes = _results.top();
if (last == nullptr) {
_posInCursor.push(0);
last = &_posInCursor.top();
} else {
++(*last);
}
while (true) {
VPackSlice edge = opRes->slice();
if (!edge.isArray() || edge.length() <= *last) {
if (cursor->hasMore()) {
// Fetch next and try again
cursor->getMore(opRes);
*last = 0;
continue;
}
eColIdx++;
if (!nextCursor(startVertex, eColIdx, last)) {
// No further edges.
TRI_ASSERT(last == nullptr);
TRI_ASSERT(_cursors.size() == _posInCursor.size());
TRI_ASSERT(_cursors.size() == _results.size());
return;
}
// There is a new Cursor on top of the stack, try it
*last = 0;
continue;
}
edge = edge.at(*last);
if (!_traverser->edgeMatchesConditions(edge, edges.size())) {
++_traverser->_filteredPaths;
(*last)++;
continue;
}
std::string id = _trx->extractIdString(edge);
VPackBuilder tmpBuilder = VPackBuilder::clone(edge);
_traverser->_edges.emplace(id, tmpBuilder.steal());
edges.emplace_back(id);
return;
}
}
void DepthFirstTraverser::EdgeGetter::operator()(
std::string const& startVertex,
std::vector<std::string>& edges, TRI_doc_mptr_t*& last, size_t& eColIdx,
std::vector<std::string>& edges, VPackValueLength*& last, size_t& eColIdx,
bool& dir) {
#warning use new EdgeIndex VPACK lookup here.
// builderSearchValue(dir, startVertex, builder);
// trx->indexScan();
/*
std::string eColName;
TRI_edge_direction_e direction;
while (true) {
if (!_opts.getCollection(eColIdx, eColName, direction)) {
// We are done traversing.
if (last == nullptr) {
eColIdx = 0;
if (!nextCursor(startVertex, eColIdx, last)) {
// We were not able to find any edge
return;
}
TRI_voc_cid_t cid;
arangodb::EdgeIndex* edgeIndex = getEdgeIndex(eColName, cid);
std::vector<TRI_doc_mptr_t> tmp;
if (direction == TRI_EDGE_ANY) {
TRI_edge_direction_e currentDir = dir ? TRI_EDGE_OUT : TRI_EDGE_IN;
TRI_edge_index_iterator_t it(currentDir, startVertex);
edgeIndex->lookup(_trx, &it, tmp, last, 1);
if (last == nullptr) {
// Could not find next edge.
// Change direction and increase collectionId
if (dir) {
++eColIdx;
}
dir = !dir;
continue;
}
}
else {
TRI_edge_index_iterator_t it(direction, startVertex);
edgeIndex->lookup(_trx, &it, tmp, last, 1);
if (last == nullptr) {
// Could not find next edge.
// Set direction to false and continue with next collection
dir = false;
++eColIdx;
continue;
}
}
// If we get here we have found the next edge.
// Now validate expression checks
++_traverser->_readDocuments;
// sth is stored in tmp. Now push it on edges
TRI_ASSERT(tmp.size() == 1);
if (!_traverser->edgeMatchesConditions(tmp.back(), eColIdx, edges.size())) {
// Retry with the next element
continue;
}
EdgeInfo e(cid, tmp.back());
VPackSlice other;
// This always returns true and third parameter is ignored
_traverser->_getVertex(e, startVertex, 0, other);
if (!_traverser->vertexMatchesConditions(other, edges.size() + 1)) {
// Retry with the next element
continue;
}
auto search = std::find(edges.begin(), edges.end(), e);
if (search != edges.end()) {
// The edge is included twice. Go on with the next
continue;
}
edges.push_back(e);
return;
}
*/
nextEdge(startVertex, eColIdx, last, edges);
}

View File

@ -191,35 +191,35 @@ class DepthFirstTraverser : public Traverser {
public:
EdgeGetter(DepthFirstTraverser* traverser,
TraverserOptions const& opts,
CollectionNameResolver* resolver, Transaction* trx)
: _traverser(traverser), _resolver(resolver), _opts(opts), _trx(trx) {}
Transaction* trx)
: _traverser(traverser), _opts(opts), _trx(trx) {}
//////////////////////////////////////////////////////////////////////////////
/// @brief Function to fill the list of edges properly.
//////////////////////////////////////////////////////////////////////////////
void operator()(std::string const&, std::vector<std::string>&,
TRI_doc_mptr_t*&, size_t&, bool&);
arangodb::velocypack::ValueLength*&, size_t&, bool&);
private:
//////////////////////////////////////////////////////////////////////////////
/// @brief Get an edge index for the given collection by name
/// @brief Get the next valid cursor
//////////////////////////////////////////////////////////////////////////////
EdgeIndex* getEdgeIndex(std::string const&, TRI_voc_cid_t&);
bool nextCursor(std::string const&, size_t&,
arangodb::velocypack::ValueLength*&);
//////////////////////////////////////////////////////////////////////////////
/// @brief Collection name resolver
/// @brief Get the next edge
//////////////////////////////////////////////////////////////////////////////
void nextEdge(std::string const&, size_t&,
arangodb::velocypack::ValueLength*&,
std::vector<std::string>&);
DepthFirstTraverser* _traverser;
//////////////////////////////////////////////////////////////////////////////
/// @brief Collection name resolver
//////////////////////////////////////////////////////////////////////////////
CollectionNameResolver* _resolver;
//////////////////////////////////////////////////////////////////////////////
/// @brief Cache for indexes. Maps collectionName to Index
//////////////////////////////////////////////////////////////////////////////
@ -237,15 +237,41 @@ class DepthFirstTraverser : public Traverser {
/// @brief Pointer to active transaction
/// All Edge Collections have to be properly locked before traversing!
//////////////////////////////////////////////////////////////////////////////
Transaction* _trx;
//////////////////////////////////////////////////////////////////////////////
/// @brief Stack of all active cursors
//////////////////////////////////////////////////////////////////////////////
std::stack<std::shared_ptr<OperationCursor>> _cursors;
//////////////////////////////////////////////////////////////////////////////
/// @brief Stack of all active cursor batches
//////////////////////////////////////////////////////////////////////////////
std::stack<std::shared_ptr<OperationResult>> _results;
//////////////////////////////////////////////////////////////////////////////
/// @brief Stack of positions in the cursors
//////////////////////////////////////////////////////////////////////////////
std::stack<arangodb::velocypack::ValueLength> _posInCursor;
//////////////////////////////////////////////////////////////////////////////
/// @brief velocyPack builder to create temporary search values
//////////////////////////////////////////////////////////////////////////////
arangodb::velocypack::Builder _builder;
};
//////////////////////////////////////////////////////////////////////////////
/// @brief internal cursor to enumerate the paths of a graph
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<arangodb::basics::PathEnumerator<std::string, std::string,
TRI_doc_mptr_t>> _enumerator;
std::unique_ptr<arangodb::basics::PathEnumerator<
std::string, std::string, arangodb::velocypack::ValueLength>> _enumerator;
//////////////////////////////////////////////////////////////////////////////
/// @brief internal getter to extract an edge
@ -280,6 +306,14 @@ class DepthFirstTraverser : public Traverser {
std::shared_ptr<arangodb::velocypack::Buffer<uint8_t>>>
_vertices;
//////////////////////////////////////////////////////////////////////////////
/// @brief Cache for edge documents
//////////////////////////////////////////////////////////////////////////////
std::unordered_map<std::string,
std::shared_ptr<arangodb::velocypack::Buffer<uint8_t>>>
_edges;
//////////////////////////////////////////////////////////////////////////////
/// @brief Shared builder to create temporary objects like search values
//////////////////////////////////////////////////////////////////////////////
@ -302,7 +336,7 @@ class DepthFirstTraverser : public Traverser {
public:
DepthFirstTraverser(
std::vector<TRI_document_collection_t*> const&, TraverserOptions&,
CollectionNameResolver*, Transaction*,
Transaction*,
std::unordered_map<size_t, std::vector<TraverserExpression*>> const*);
//////////////////////////////////////////////////////////////////////////////
@ -376,8 +410,8 @@ class EdgeCollectionInfo {
/// @brief Get edges for the given direction and start vertex.
////////////////////////////////////////////////////////////////////////////////
arangodb::OperationCursor getEdges(TRI_edge_direction_e direction,
std::string const&);
std::shared_ptr<arangodb::OperationCursor> getEdges(
TRI_edge_direction_e direction, std::string const&);
double weightEdge(arangodb::velocypack::Slice const);

View File

@ -195,10 +195,12 @@ static void JS_AllQuery(v8::FunctionCallbackInfo<v8::Value> const& args) {
std::string collectionName(collection->_name);
// We directly read the entire cursor. so batchsize == limit
OperationCursor opCursor = trx.indexScan(collectionName, Transaction::CursorType::ALL, "", {}, skip, limit, limit, false);
std::shared_ptr<OperationCursor> opCursor =
trx.indexScan(collectionName, Transaction::CursorType::ALL, "", {}, skip,
limit, limit, false);
if (opCursor.failed()) {
TRI_V8_THROW_EXCEPTION(opCursor.code);
if (opCursor->failed()) {
TRI_V8_THROW_EXCEPTION(opCursor->code);
}
OperationResult countResult = trx.count(collectionName);
@ -215,19 +217,20 @@ static void JS_AllQuery(v8::FunctionCallbackInfo<v8::Value> const& args) {
VPackSlice count = countResult.slice();
TRI_ASSERT(count.isNumber());
if (!opCursor.hasMore()) {
if (!opCursor->hasMore()) {
// OUT OF MEMORY. initial hasMore should return true even if index is empty
TRI_V8_THROW_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
// copy default options
VPackOptions resultOptions = VPackOptions::Defaults;
resultOptions.customTypeHandler = opCursor.customTypeHandler.get();
resultOptions.customTypeHandler = opCursor->customTypeHandler.get();
opCursor.getMore();
auto batch = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
opCursor->getMore(batch);
// We only need this one call, limit == batchsize
VPackSlice docs = opCursor.slice();
VPackSlice docs = batch->slice();
TRI_ASSERT(docs.isArray());
// setup result
v8::Handle<v8::Object> result = v8::Object::New(isolate);

View File

@ -1721,7 +1721,6 @@ static v8::Handle<v8::Value> VertexIdToData(
OperationResult opRes = trx->document(parts[0], builder.slice(), options);
if (opRes.failed()) {
LOG(INFO) << opRes.code;
v8::EscapableHandleScope scope(isolate);
return scope.Escape<v8::Value>(v8::Null(isolate));
}

View File

@ -24,6 +24,7 @@
#include "Traverser.h"
#include "Basics/VelocyPackHelper.h"
#include "Basics/json-utilities.h"
#include "Indexes/EdgeIndex.h"
#include "VocBase/KeyGenerator.h"
using TraverserExpression = arangodb::traverser::TraverserExpression;
@ -60,6 +61,9 @@ void arangodb::traverser::TraverserOptions::setCollections(
TRI_ASSERT(!colls.empty());
_collections = colls;
_directions.emplace_back(dir);
for (auto const& it : colls) {
_indexHandles.emplace_back(_trx->edgeIndexHandle(it));
}
}
void arangodb::traverser::TraverserOptions::setCollections(
@ -72,6 +76,9 @@ void arangodb::traverser::TraverserOptions::setCollections(
TRI_ASSERT(colls.size() == dirs.size());
_collections = colls;
_directions = dirs;
for (auto const& it : colls) {
_indexHandles.emplace_back(_trx->edgeIndexHandle(it));
}
}
size_t arangodb::traverser::TraverserOptions::collectionCount () const {
@ -90,6 +97,29 @@ bool arangodb::traverser::TraverserOptions::getCollection(
dir = _directions.at(index);
}
name = _collections.at(index);
// arangodb::EdgeIndex::buildSearchValue(direction, eColName, _builder);
return true;
}
bool arangodb::traverser::TraverserOptions::getCollectionAndSearchValue(
size_t index, std::string const& vertexId, std::string& name,
std::string& indexHandle, VPackBuilder& builder) {
if (index >= _collections.size()) {
// No more collections stop now
return false;
}
TRI_edge_direction_e dir;
if (_directions.size() == 1) {
dir = _directions.at(0);
} else {
dir = _directions.at(index);
}
name = _collections.at(index);
indexHandle = _indexHandles.at(index);
_builder.clear();
arangodb::EdgeIndex::buildSearchValue(dir, name, _builder);
return true;
}

View File

@ -189,17 +189,19 @@ class TraversalPath {
};
struct TraverserOptions {
private:
arangodb::Transaction* _trx;
std::vector<std::string> _collections;
std::vector<TRI_edge_direction_e> _directions;
std::vector<std::string> _indexHandles;
arangodb::velocypack::Builder _builder;
public:
uint64_t minDepth;
uint64_t maxDepth;
TraverserOptions() : minDepth(1), maxDepth(1) {}
TraverserOptions(arangodb::Transaction* trx) : _trx(trx), minDepth(1), maxDepth(1) {}
void setCollections(std::vector<std::string> const&, TRI_edge_direction_e);
void setCollections(std::vector<std::string> const&, std::vector<TRI_edge_direction_e> const&);
@ -207,6 +209,10 @@ struct TraverserOptions {
size_t collectionCount() const;
bool getCollection(size_t const, std::string&, TRI_edge_direction_e&) const;
bool getCollectionAndSearchValue(size_t, std::string const&, std::string&,
std::string&,
arangodb::velocypack::Builder&);
};
class Traverser {
@ -215,11 +221,12 @@ class Traverser {
/// @brief Constructor. This is an abstract only class.
//////////////////////////////////////////////////////////////////////////////
Traverser()
Traverser(arangodb::Transaction* trx)
: _readDocuments(0),
_filteredPaths(0),
_pruneNext(false),
_done(true),
_opts(trx),
_expressions(nullptr) {}
//////////////////////////////////////////////////////////////////////////////