diff --git a/arangod/MMFiles/MMFilesEdgeIndex.cpp b/arangod/MMFiles/MMFilesEdgeIndex.cpp index c588c233b2..78eeab7727 100644 --- a/arangod/MMFiles/MMFilesEdgeIndex.cpp +++ b/arangod/MMFiles/MMFilesEdgeIndex.cpp @@ -118,6 +118,57 @@ bool MMFilesEdgeIndexIterator::next(LocalDocumentIdCallback const& cb, size_t li return true; } +bool MMFilesEdgeIndexIterator::nextDocument(DocumentCallback const& cb, size_t limit) { + _documentIds.clear(); + _documentIds.reserve(limit); + + if (limit == 0 || (_buffer.empty() && !_iterator.valid())) { + // No limit no data, or we are actually done. The last call should have + // returned false + TRI_ASSERT(limit > 0); // Someone called with limit == 0. Api broken + return false; + } + + bool done = false; + while (limit > 0) { + if (_buffer.empty()) { + // We start a new lookup + _posInBuffer = 0; + + VPackSlice tmp = _iterator.value(); + if (tmp.isObject()) { + tmp = tmp.get(StaticStrings::IndexEq); + } + _index->lookupByKey(&_context, &tmp, _buffer, _batchSize); + } else if (_posInBuffer >= _buffer.size()) { + // We have to refill the buffer + _buffer.clear(); + + _posInBuffer = 0; + _index->lookupByKeyContinue(&_context, _lastElement, _buffer, _batchSize); + } + + if (_buffer.empty()) { + _iterator.next(); + _lastElement = MMFilesSimpleIndexElement(); + if (!_iterator.valid()) { + done = true; + break; + } + } else { + _lastElement = _buffer.back(); + // found something + TRI_ASSERT(_posInBuffer < _buffer.size()); + _documentIds.emplace_back(std::make_pair(_buffer[_posInBuffer++].localDocumentId(), nullptr)); + limit--; + } + } + + auto physical = static_cast(_collection->getPhysical()); + physical->readDocumentWithCallback(_trx, _documentIds, cb); + return !done; +} + void MMFilesEdgeIndexIterator::reset() { _posInBuffer = 0; _buffer.clear(); diff --git a/arangod/MMFiles/MMFilesEdgeIndex.h b/arangod/MMFiles/MMFilesEdgeIndex.h index 92c98baba2..aeede634e5 100644 --- a/arangod/MMFiles/MMFilesEdgeIndex.h +++ b/arangod/MMFiles/MMFilesEdgeIndex.h @@ -125,6 +125,7 @@ class MMFilesEdgeIndexIterator final : public IndexIterator { char const* typeName() const override { return "edge-index-iterator"; } bool next(LocalDocumentIdCallback const& cb, size_t limit) override; + bool nextDocument(DocumentCallback const& cb, size_t limit) override; void reset() override; @@ -138,6 +139,7 @@ class MMFilesEdgeIndexIterator final : public IndexIterator { size_t _posInBuffer; size_t _batchSize; MMFilesSimpleIndexElement _lastElement; + std::vector> _documentIds; }; class MMFilesEdgeIndex final : public MMFilesIndex { diff --git a/arangod/MMFiles/MMFilesHashIndex.cpp b/arangod/MMFiles/MMFilesHashIndex.cpp index ee828bbdbc..a5a348c8fd 100644 --- a/arangod/MMFiles/MMFilesHashIndex.cpp +++ b/arangod/MMFiles/MMFilesHashIndex.cpp @@ -249,68 +249,44 @@ bool MMFilesHashIndexIterator::next(LocalDocumentIdCallback const& cb, size_t li return true; } -void MMFilesHashIndexIterator::reset() { - _buffer.clear(); - _posInBuffer = 0; - _lookups.reset(); - _index->lookup(_trx, _lookups.lookup(), _buffer); -} +bool MMFilesHashIndexIterator::nextDocument(DocumentCallback const& cb, size_t limit) { + _documentIds.clear(); + _documentIds.reserve(limit); -MMFilesHashIndexIteratorVPack::MMFilesHashIndexIteratorVPack( - LogicalCollection* collection, transaction::Methods* trx, - MMFilesHashIndex const* index, - std::unique_ptr searchValues) - : IndexIterator(collection, trx, index), - _index(index), - _searchValues(std::move(searchValues)), - _iterator(_searchValues->slice()), - _buffer(), - _posInBuffer(0) { -} - -MMFilesHashIndexIteratorVPack::~MMFilesHashIndexIteratorVPack() { - if (_searchValues != nullptr) { - // return the VPackBuilder to the transaction context - _trx->transactionContextPtr()->returnBuilder(_searchValues.release()); - } -} - -bool MMFilesHashIndexIteratorVPack::next(LocalDocumentIdCallback const& cb, - size_t limit) { + bool done = false; while (limit > 0) { if (_posInBuffer >= _buffer.size()) { - if (!_iterator.valid()) { + if (!_lookups.hasAndGetNext()) { // we're at the end of the lookup values - return false; + done = true; + break; } // We have to refill the buffer _buffer.clear(); _posInBuffer = 0; - int res = TRI_ERROR_NO_ERROR; - _index->lookup(_trx, _iterator.value(), _buffer); - _iterator.next(); - - if (res != TRI_ERROR_NO_ERROR) { - THROW_ARANGO_EXCEPTION(res); - } + _index->lookup(_trx, _lookups.lookup(), _buffer); } if (!_buffer.empty()) { // found something TRI_ASSERT(_posInBuffer < _buffer.size()); - cb(_buffer[_posInBuffer++]->localDocumentId()); + _documentIds.emplace_back(std::make_pair(_buffer[_posInBuffer++]->localDocumentId(), nullptr)); --limit; } } - return true; + + auto physical = static_cast(_collection->getPhysical()); + physical->readDocumentWithCallback(_trx, _documentIds, cb); + return !done; } -void MMFilesHashIndexIteratorVPack::reset() { +void MMFilesHashIndexIterator::reset() { _buffer.clear(); _posInBuffer = 0; - _iterator.reset(); + _lookups.reset(); + _index->lookup(_trx, _lookups.lookup(), _buffer); } /// @brief create the unique array diff --git a/arangod/MMFiles/MMFilesHashIndex.h b/arangod/MMFiles/MMFilesHashIndex.h index fa7351a549..e45fa69ce5 100644 --- a/arangod/MMFiles/MMFilesHashIndex.h +++ b/arangod/MMFiles/MMFilesHashIndex.h @@ -217,6 +217,7 @@ class MMFilesHashIndexIterator final : public IndexIterator { char const* typeName() const override { return "hash-index-iterator"; } bool next(LocalDocumentIdCallback const& cb, size_t limit) override; + bool nextDocument(DocumentCallback const& cb, size_t limit) override; void reset() override; @@ -225,35 +226,11 @@ class MMFilesHashIndexIterator final : public IndexIterator { MMFilesHashIndexLookupBuilder _lookups; std::vector _buffer; size_t _posInBuffer; -}; - -class MMFilesHashIndexIteratorVPack final : public IndexIterator { - public: - /// @brief Construct an MMFilesHashIndexIterator based on VelocyPack - MMFilesHashIndexIteratorVPack( - LogicalCollection* collection, transaction::Methods* trx, - MMFilesHashIndex const* index, - std::unique_ptr searchValues); - - ~MMFilesHashIndexIteratorVPack(); - - char const* typeName() const override { return "hash-index-iterator-vpack"; } - - bool next(LocalDocumentIdCallback const& cb, size_t limit) override; - - void reset() override; - - private: - MMFilesHashIndex const* _index; - std::unique_ptr _searchValues; - arangodb::velocypack::ArrayIterator _iterator; - std::vector _buffer; - size_t _posInBuffer; + std::vector> _documentIds; }; class MMFilesHashIndex final : public MMFilesPathBasedIndex { friend class MMFilesHashIndexIterator; - friend class MMFilesHashIndexIteratorVPack; public: MMFilesHashIndex() = delete; diff --git a/arangod/MMFiles/MMFilesSkiplistIndex.cpp b/arangod/MMFiles/MMFilesSkiplistIndex.cpp index 9e68e24b17..205039bbcc 100644 --- a/arangod/MMFiles/MMFilesSkiplistIndex.cpp +++ b/arangod/MMFiles/MMFilesSkiplistIndex.cpp @@ -32,6 +32,7 @@ #include "Indexes/IndexLookupContext.h" #include "Indexes/IndexResult.h" #include "Indexes/SimpleAttributeEqualityMatcher.h" +#include "MMFiles/MMFilesCollection.h" #include "StorageEngine/PhysicalCollection.h" #include "Transaction/Helpers.h" #include "Transaction/Methods.h" @@ -584,12 +585,52 @@ bool MMFilesSkiplistIterator::next(LocalDocumentIdCallback const& cb, size_t lim } TRI_ASSERT(tmp != nullptr); TRI_ASSERT(tmp->document() != nullptr); + cb(tmp->document()->localDocumentId()); limit--; } return true; } +bool MMFilesSkiplistIterator::nextDocument(DocumentCallback const& cb, size_t limit) { + _documentIds.clear(); + _documentIds.reserve(limit); + + bool done = false; + while (limit > 0) { + if (_cursor == nullptr) { + // We are exhausted already, sorry + done = true; + break; + } + TRI_ASSERT(_currentInterval < _intervals.size()); + auto const& interval = _intervals[_currentInterval]; + Node* tmp = _cursor; + if (_reverse) { + if (_cursor == interval.first) { + forwardCursor(); + } else { + _cursor = _cursor->prevNode(); + } + } else { + if (_cursor == interval.second) { + forwardCursor(); + } else { + _cursor = _cursor->nextNode(); + } + } + TRI_ASSERT(tmp != nullptr); + TRI_ASSERT(tmp->document() != nullptr); + + _documentIds.emplace_back(std::make_pair(tmp->document()->localDocumentId(), nullptr)); + limit--; + } + + auto physical = static_cast(_collection->getPhysical()); + physical->readDocumentWithCallback(_trx, _documentIds, cb); + return !done; +} + void MMFilesSkiplistIterator::forwardCursor() { _currentInterval++; if (_currentInterval < _intervals.size()) { diff --git a/arangod/MMFiles/MMFilesSkiplistIndex.h b/arangod/MMFiles/MMFilesSkiplistIndex.h index 67c3eee774..a06dacffb6 100644 --- a/arangod/MMFiles/MMFilesSkiplistIndex.h +++ b/arangod/MMFiles/MMFilesSkiplistIndex.h @@ -187,6 +187,7 @@ class MMFilesSkiplistIterator final : public IndexIterator { size_t _currentInterval; MMFilesBaseSkiplistLookupBuilder* _builder; + std::vector> _documentIds; std::function @@ -214,6 +215,7 @@ class MMFilesSkiplistIterator final : public IndexIterator { /// @brief Get the next elements in the skiplist bool next(LocalDocumentIdCallback const& cb, size_t limit) override; + bool nextDocument(DocumentCallback const& cb, size_t limit) override; /// @brief Reset the cursor void reset() override;