1
0
Fork 0

Moved index API to return DocumentIdentifierTokens which are independent of the underlying storage engine. The agreement is, that the Engine gives a uint64_t sized identifier which allows to fetch any document back again. For MMFiles Engine this identifier is the revision.

This commit is contained in:
Michael Hackstein 2017-01-24 18:19:25 +01:00
parent f1df7ae882
commit 2133b1448c
34 changed files with 237 additions and 158 deletions

View File

@ -42,7 +42,7 @@ CollectionScanner::CollectionScanner(arangodb::Transaction* trx,
CollectionScanner::~CollectionScanner() {}
void CollectionScanner::scan(std::vector<arangodb::IndexLookupResult>& result, size_t batchSize) {
void CollectionScanner::scan(std::vector<arangodb::DocumentIdentifierToken>& result, size_t batchSize) {
result.clear();
if (!_cursor->hasMore()) {

View File

@ -40,7 +40,7 @@ class CollectionScanner {
~CollectionScanner();
void scan(std::vector<IndexLookupResult>& result, size_t batchSize);
void scan(std::vector<DocumentIdentifierToken>& result, size_t batchSize);
void reset();

View File

@ -250,8 +250,7 @@ AqlItemBlock* EnumerateCollectionBlock::getSome(size_t, // atLeast,
// The result is in the first variable of this depth,
// we do not need to do a lookup in getPlanNode()->_registerPlan->varInfo,
// but can just take cur->getNrRegs() as registerId:
TRI_voc_rid_t revisionId = _documents[_position].revisionId();
if (c->readRevision(_trx, *_mmdr, revisionId)) {
if (c->readDocument(_trx, *_mmdr, _documents[_position])) {
uint8_t const* vpack = _mmdr->vpack();
res->setValue(j, static_cast<arangodb::aql::RegisterId>(curRegs), AqlValue(vpack, AqlValueFromManagedDocument()));
}

View File

@ -81,7 +81,7 @@ class EnumerateCollectionBlock : public ExecutionBlock {
CollectionScanner _scanner;
/// @brief document buffer
std::vector<IndexLookupResult> _documents;
std::vector<DocumentIdentifierToken> _documents;
/// @brief iterator over documents
size_t _position;

View File

@ -430,18 +430,17 @@ bool IndexBlock::readIndex(size_t atMost) {
if (hasMultipleIndexes) {
for (auto const& element : _result) {
TRI_voc_rid_t revisionId = element.revisionId();
if (collection->readRevision(_trx, *_mmdr, revisionId)) {
if (collection->readDocument(_trx, *_mmdr, element)) {
uint8_t const* vpack = _mmdr->vpack(); //back();
// uniqueness checks
if (!isLastIndex) {
// insert & check for duplicates in one go
if (_alreadyReturned.emplace(revisionId).second) {
if (_alreadyReturned.emplace(element).second) {
_documents.emplace_back(vpack);
}
} else {
// only check for duplicates
if (_alreadyReturned.find(revisionId) == _alreadyReturned.end()) {
if (_alreadyReturned.find(element) == _alreadyReturned.end()) {
_documents.emplace_back(vpack);
}
}
@ -449,8 +448,7 @@ bool IndexBlock::readIndex(size_t atMost) {
}
} else {
for (auto const& element : _result) {
TRI_voc_rid_t revisionId = element.revisionId();
if (collection->readRevision(_trx, *_mmdr, revisionId)) {
if (collection->readDocument(_trx, *_mmdr, element)) {
uint8_t const* vpack = _mmdr->vpack(); //back();
_documents.emplace_back(vpack);
}

View File

@ -110,7 +110,7 @@ class IndexBlock : public ExecutionBlock {
Collection const* _collection;
/// @brief document result
std::vector<IndexLookupResult> _result;
std::vector<DocumentIdentifierToken> _result;
/// @brief document buffer
std::vector<arangodb::velocypack::Slice> _documents;
@ -149,7 +149,7 @@ class IndexBlock : public ExecutionBlock {
AstNode const* _condition;
/// @brief set of already returned documents. Used to make the result distinct
std::unordered_set<TRI_voc_rid_t> _alreadyReturned;
std::unordered_set<DocumentIdentifierToken> _alreadyReturned;
/// @brief whether or not at least one expression uses v8
bool _hasV8Expression;

View File

@ -70,7 +70,7 @@ struct ConstDistanceExpanderLocal {
bool _isReverse;
/// @brief Local cursor vector
std::vector<IndexLookupResult> _cursor;
std::vector<DocumentIdentifierToken> _cursor;
public:
ConstDistanceExpanderLocal(ShortestPathBlock const* block,
@ -96,10 +96,9 @@ struct ConstDistanceExpanderLocal {
_cursor.clear();
LogicalCollection* collection = edgeCursor->collection();
while (edgeCursor->hasMore()) {
edgeCursor->getMoreMptr(_cursor, UINT64_MAX);
edgeCursor->getMoreMptr(_cursor, 1000);
for (auto const& element : _cursor) {
TRI_voc_rid_t revisionId = element.revisionId();
if (collection->readRevision(_block->transaction(), *mmdr, revisionId)) {
if (collection->readDocument(_block->transaction(), *mmdr, element)) {
VPackSlice edge(mmdr->vpack());
VPackSlice from =
arangodb::Transaction::extractFromFromDocument(edge);
@ -220,7 +219,7 @@ struct EdgeWeightExpanderLocal {
void operator()(VPackSlice const& source,
std::vector<ArangoDBPathFinder::Step*>& result) {
ManagedDocumentResult* mmdr = _block->_mmdr.get();
std::vector<IndexLookupResult> cursor;
std::vector<DocumentIdentifierToken> cursor;
std::unique_ptr<arangodb::OperationCursor> edgeCursor;
std::unordered_map<VPackSlice, size_t> candidates;
for (auto const& edgeCollection : _block->_collectionInfos) {
@ -240,10 +239,9 @@ struct EdgeWeightExpanderLocal {
cursor.clear();
LogicalCollection* collection = edgeCursor->collection();
while (edgeCursor->hasMore()) {
edgeCursor->getMoreMptr(cursor, UINT64_MAX);
edgeCursor->getMoreMptr(cursor, 1000);
for (auto const& element : cursor) {
TRI_voc_rid_t revisionId = element.revisionId();
if (collection->readRevision(_block->transaction(), *mmdr, revisionId)) {
if (collection->readDocument(_block->transaction(), *mmdr, element)) {
VPackSlice edge(mmdr->vpack());
VPackSlice from =
arangodb::Transaction::extractFromFromDocument(edge);

View File

@ -51,16 +51,16 @@ IndexIterator::~IndexIterator() {
}
/// @brief default implementation for next
IndexLookupResult IndexIterator::next() { return IndexLookupResult(); }
DocumentIdentifierToken IndexIterator::next() { return DocumentIdentifierToken(); }
/// @brief default implementation for nextBabies
void IndexIterator::nextBabies(std::vector<IndexLookupResult>& result, size_t batchSize) {
void IndexIterator::nextBabies(std::vector<DocumentIdentifierToken>& result, size_t batchSize) {
result.clear();
if (batchSize > 0) {
while (true) {
IndexLookupResult element = next();
if (!element) {
DocumentIdentifierToken element = next();
if (element == 0) {
return;
}
result.emplace_back(element);
@ -79,7 +79,7 @@ void IndexIterator::reset() {}
void IndexIterator::skip(uint64_t count, uint64_t& skipped) {
// Skip the first count-many entries
// TODO: Can be improved
while (count > 0 && next()) {
while (count > 0 && next() != 0) {
--count;
skipped++;
}
@ -88,16 +88,16 @@ void IndexIterator::skip(uint64_t count, uint64_t& skipped) {
/// @brief Get the next element
/// If one iterator is exhausted, the next one is used.
/// A nullptr indicates that all iterators are exhausted
IndexLookupResult MultiIndexIterator::next() {
DocumentIdentifierToken MultiIndexIterator::next() {
if (_current == nullptr) {
return IndexLookupResult();
return DocumentIdentifierToken();
}
IndexLookupResult next = _current->next();
while (!next) {
DocumentIdentifierToken next = _current->next();
while (next == 0) {
_currentIdx++;
if (_currentIdx >= _iterators.size()) {
_current = nullptr;
return IndexLookupResult();
return DocumentIdentifierToken();
}
_current = _iterators.at(_currentIdx);
next = _current->next();
@ -108,7 +108,7 @@ IndexLookupResult MultiIndexIterator::next() {
/// @brief Get the next limit many elements
/// If one iterator is exhausted, the next one will be used.
/// An empty result vector indicates that all iterators are exhausted
void MultiIndexIterator::nextBabies(std::vector<IndexLookupResult>& result, size_t limit) {
void MultiIndexIterator::nextBabies(std::vector<DocumentIdentifierToken>& result, size_t limit) {
result.clear();
if (_current == nullptr) {

View File

@ -26,7 +26,7 @@
//
// typeName() returns a string descibing the type of the indexIterator
//
// The next() function of the IndexIterator returns IndexLookupResults that are
// The next() function of the IndexIterator returns DocumentIdentifierTokens that are
// created from RevisionIds. If there is nothing more to return a default
// constructed IndesLookupResult is returend.
//
@ -51,6 +51,7 @@
#include "Basics/Common.h"
#include "Cluster/ServerState.h"
#include "Indexes/IndexLookupContext.h"
#include "StorageEngine/StorageEngine.h"
#include "VocBase/ManagedDocumentResult.h"
#include "VocBase/vocbase.h"
@ -59,24 +60,6 @@ class Index;
class LogicalCollection;
class Transaction;
class IndexLookupResult {
public:
constexpr IndexLookupResult() : _revisionId(0) {}
explicit IndexLookupResult(TRI_voc_rid_t revisionId) : _revisionId(revisionId) {}
IndexLookupResult(IndexLookupResult const& other) : _revisionId(other._revisionId) {}
IndexLookupResult& operator=(IndexLookupResult const& other) {
_revisionId = other._revisionId;
return *this;
}
inline operator bool() const { return _revisionId != 0; }
inline TRI_voc_rid_t revisionId() const { return _revisionId; }
private:
TRI_voc_rid_t _revisionId;
};
/// @brief a base class to iterate over the index. An iterator is requested
/// at the index itself
class IndexIterator {
@ -94,9 +77,9 @@ class IndexIterator {
LogicalCollection* collection() const { return _collection; }
arangodb::Transaction* transaction() const { return _trx; }
virtual IndexLookupResult next();
virtual DocumentIdentifierToken next();
virtual void nextBabies(std::vector<IndexLookupResult>&, size_t);
virtual void nextBabies(std::vector<DocumentIdentifierToken>&, size_t);
virtual void reset();
@ -120,9 +103,9 @@ class EmptyIndexIterator final : public IndexIterator {
char const* typeName() const override { return "empty-index-iterator"; }
IndexLookupResult next() override { return IndexLookupResult(); }
DocumentIdentifierToken next() override { return DocumentIdentifierToken(); }
void nextBabies(std::vector<IndexLookupResult>&, size_t) override {}
void nextBabies(std::vector<DocumentIdentifierToken>&, size_t) override {}
void reset() override {}
@ -161,12 +144,12 @@ class MultiIndexIterator final : public IndexIterator {
/// @brief Get the next element
/// If one iterator is exhausted, the next one is used.
/// A nullptr indicates that all iterators are exhausted
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
/// @brief Get at most the next limit many elements
/// If one iterator is exhausted, the next one will be used.
/// An empty result vector indicates that all iterators are exhausted
void nextBabies(std::vector<IndexLookupResult>&, size_t) override;
void nextBabies(std::vector<DocumentIdentifierToken>&, size_t) override;
/// @brief Reset the cursor
/// This will reset ALL internal iterators and start all over again

View File

@ -45,9 +45,9 @@ class IndexLookupContext {
~IndexLookupContext() {}
uint8_t const* lookup(TRI_voc_rid_t revisionId) {
uint8_t const* lookup(DocumentIdentifierToken token) {
try {
if (_collection->readRevision(_trx, *_result, revisionId)) {
if (_collection->readDocument(_trx, *_result, token)) {
return _result->vpack();
}
} catch (...) {

View File

@ -31,6 +31,7 @@
#include "Basics/hashes.h"
#include "Indexes/IndexLookupContext.h"
#include "Indexes/SimpleAttributeEqualityMatcher.h"
#include "MMFiles/MMFilesToken.h"
#include "Utils/CollectionNameResolver.h"
#include "Utils/Transaction.h"
#include "Utils/TransactionContext.h"
@ -126,7 +127,7 @@ MMFilesEdgeIndexIterator::~MMFilesEdgeIndexIterator() {
}
}
IndexLookupResult MMFilesEdgeIndexIterator::next() {
DocumentIdentifierToken MMFilesEdgeIndexIterator::next() {
while (_iterator.valid()) {
if (_buffer.empty()) {
// We start a new lookup
@ -150,17 +151,17 @@ IndexLookupResult MMFilesEdgeIndexIterator::next() {
} else {
_lastElement = _buffer.back();
// found something
return IndexLookupResult(_buffer[_posInBuffer++].revisionId());
return MMFilesToken{_buffer[_posInBuffer++].revisionId()};
}
// found no result. now go to next lookup value in _keys
_iterator.next();
}
return IndexLookupResult();
return MMFilesToken{};
}
void MMFilesEdgeIndexIterator::nextBabies(std::vector<IndexLookupResult>& buffer, size_t limit) {
void MMFilesEdgeIndexIterator::nextBabies(std::vector<DocumentIdentifierToken>& buffer, size_t limit) {
size_t atMost = _batchSize > limit ? limit : _batchSize;
if (atMost == 0) {
@ -187,7 +188,7 @@ void MMFilesEdgeIndexIterator::nextBabies(std::vector<IndexLookupResult>& buffer
}
for (auto& it : _buffer) {
buffer.emplace_back(it.revisionId());
buffer.emplace_back(MMFilesToken(it.revisionId()));
}
if (_buffer.empty()) {
@ -223,28 +224,28 @@ AnyDirectionMMFilesEdgeIndexIterator::AnyDirectionMMFilesEdgeIndexIterator(Logic
_inbound(inboundIterator),
_useInbound(false) {}
IndexLookupResult AnyDirectionMMFilesEdgeIndexIterator::next() {
IndexLookupResult res;
DocumentIdentifierToken AnyDirectionMMFilesEdgeIndexIterator::next() {
DocumentIdentifierToken res;
if (_useInbound) {
do {
res = _inbound->next();
} while (res && _seen.find(res.revisionId()) != _seen.end());
} while (res != 0 && _seen.find(res) != _seen.end());
return res;
}
res = _outbound->next();
if (!res) {
if (res == 0) {
_useInbound = true;
return next();
}
_seen.emplace(res.revisionId());
_seen.emplace(res);
return res;
}
void AnyDirectionMMFilesEdgeIndexIterator::nextBabies(std::vector<IndexLookupResult>& result, size_t limit) {
void AnyDirectionMMFilesEdgeIndexIterator::nextBabies(std::vector<DocumentIdentifierToken>& result, size_t limit) {
result.clear();
for (size_t i = 0; i < limit; ++i) {
IndexLookupResult res = next();
if (!res) {
DocumentIdentifierToken res = next();
if (res == 0) {
return;
}
result.emplace_back(res);

View File

@ -53,9 +53,9 @@ class MMFilesEdgeIndexIterator final : public IndexIterator {
char const* typeName() const override { return "edge-index-iterator"; }
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
void nextBabies(std::vector<IndexLookupResult>&, size_t) override;
void nextBabies(std::vector<DocumentIdentifierToken>&, size_t) override;
void reset() override;
@ -85,16 +85,16 @@ class AnyDirectionMMFilesEdgeIndexIterator final : public IndexIterator {
char const* typeName() const override { return "any-edge-index-iterator"; }
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
void nextBabies(std::vector<IndexLookupResult>&, size_t) override;
void nextBabies(std::vector<DocumentIdentifierToken>&, size_t) override;
void reset() override;
private:
MMFilesEdgeIndexIterator* _outbound;
MMFilesEdgeIndexIterator* _inbound;
std::unordered_set<TRI_voc_rid_t> _seen;
std::unordered_set<DocumentIdentifierToken> _seen;
bool _useInbound;
};

View File

@ -29,6 +29,7 @@
#include "Basics/StringRef.h"
#include "Basics/VelocyPackHelper.h"
#include "Logger/Logger.h"
#include "MMFiles/MMFilesToken.h"
#include "VocBase/transaction.h"
using namespace arangodb;
@ -85,7 +86,7 @@ void MMFilesGeoIndexIterator::evaluateCondition() {
}
}
IndexLookupResult MMFilesGeoIndexIterator::next() {
DocumentIdentifierToken MMFilesGeoIndexIterator::next() {
if (!_cursor) {
createCursor(_lat, _lon);
}
@ -98,14 +99,14 @@ IndexLookupResult MMFilesGeoIndexIterator::next() {
)
{
auto revision = ::MMFilesGeoIndex::toRevision(coords->coordinates[0].data);
return IndexLookupResult{revision};
return MMFilesToken{revision};
}
}
// if there are no more results we return the default constructed IndexLookupResult
return IndexLookupResult{};
return MMFilesToken{};
}
void MMFilesGeoIndexIterator::nextBabies(std::vector<IndexLookupResult>& result, size_t batchSize) {
void MMFilesGeoIndexIterator::nextBabies(std::vector<DocumentIdentifierToken>& result, size_t batchSize) {
if (!_cursor) {
createCursor(_lat, _lon);
@ -135,7 +136,8 @@ void MMFilesGeoIndexIterator::nextBabies(std::vector<IndexLookupResult>& result,
withDistances = true;
maxDistance = _radius;
}
auto coords = std::unique_ptr<GeoCoordinates>(::GeoIndex_ReadCursor(_cursor, static_cast<int>(batchSize), withDistances, maxDistance));
auto coords = std::unique_ptr<GeoCoordinates>(::GeoIndex_ReadCursor(
_cursor, static_cast<int>(batchSize), withDistances, maxDistance));
size_t const length = coords ? coords->length : 0;
@ -197,7 +199,7 @@ void MMFilesGeoIndexIterator::nextBabies(std::vector<IndexLookupResult>& result,
result.reserve(numDocs);
for (size_t i = 0; i < numDocs; ++i) {
result.emplace_back(IndexLookupResult(::MMFilesGeoIndex::toRevision(coords->coordinates[i].data)));
result.emplace_back(MMFilesToken(::MMFilesGeoIndex::toRevision(coords->coordinates[i].data)));
}
}

View File

@ -56,9 +56,9 @@ class MMFilesGeoIndexIterator final : public IndexIterator {
char const* typeName() const override { return "geo-index-iterator"; }
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
void nextBabies(std::vector<IndexLookupResult>&, size_t) override;
void nextBabies(std::vector<DocumentIdentifierToken>&, size_t) override;
void reset() override;

View File

@ -30,6 +30,7 @@
#include "Basics/VelocyPackHelper.h"
#include "Indexes/IndexLookupContext.h"
#include "Indexes/SimpleAttributeEqualityMatcher.h"
#include "MMFiles/MMFilesToken.h"
#include "Utils/TransactionContext.h"
#include "VocBase/LogicalCollection.h"
#include "VocBase/transaction.h"
@ -294,12 +295,12 @@ MMFilesHashIndexIterator::MMFilesHashIndexIterator(LogicalCollection* collection
_index->lookup(_trx, _lookups.lookup(), _buffer);
}
IndexLookupResult MMFilesHashIndexIterator::next() {
DocumentIdentifierToken MMFilesHashIndexIterator::next() {
while (true) {
if (_posInBuffer >= _buffer.size()) {
if (!_lookups.hasAndGetNext()) {
// we're at the end of the lookup values
return IndexLookupResult();
return MMFilesToken{};
}
// We have to refill the buffer
@ -311,12 +312,12 @@ IndexLookupResult MMFilesHashIndexIterator::next() {
if (!_buffer.empty()) {
// found something
return IndexLookupResult(_buffer[_posInBuffer++]->revisionId());
return MMFilesToken{_buffer[_posInBuffer++]->revisionId()};
}
}
}
void MMFilesHashIndexIterator::nextBabies(std::vector<IndexLookupResult>& result, size_t atMost) {
void MMFilesHashIndexIterator::nextBabies(std::vector<DocumentIdentifierToken>& result, size_t atMost) {
result.clear();
if (atMost == 0) {
@ -347,7 +348,7 @@ void MMFilesHashIndexIterator::nextBabies(std::vector<IndexLookupResult>& result
}
for (size_t i = _posInBuffer; i < atMost + _posInBuffer; ++i) {
result.emplace_back(_buffer[i]->revisionId());
result.emplace_back(MMFilesToken{_buffer[i]->revisionId()});
}
_posInBuffer += atMost;
return;
@ -383,12 +384,12 @@ MMFilesHashIndexIteratorVPack::~MMFilesHashIndexIteratorVPack() {
}
}
IndexLookupResult MMFilesHashIndexIteratorVPack::next() {
DocumentIdentifierToken MMFilesHashIndexIteratorVPack::next() {
while (true) {
if (_posInBuffer >= _buffer.size()) {
if (!_iterator.valid()) {
// we're at the end of the lookup values
return IndexLookupResult();
return MMFilesToken{};
}
// We have to refill the buffer
@ -406,7 +407,7 @@ IndexLookupResult MMFilesHashIndexIteratorVPack::next() {
if (!_buffer.empty()) {
// found something
return IndexLookupResult(_buffer[_posInBuffer++]->revisionId());
return MMFilesToken{_buffer[_posInBuffer++]->revisionId()};
}
}
}

View File

@ -90,9 +90,9 @@ class MMFilesHashIndexIterator final : public IndexIterator {
char const* typeName() const override { return "hash-index-iterator"; }
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
void nextBabies(std::vector<IndexLookupResult>&, size_t) override;
void nextBabies(std::vector<DocumentIdentifierToken>&, size_t) override;
void reset() override;
@ -117,7 +117,7 @@ class MMFilesHashIndexIteratorVPack final : public IndexIterator {
char const* typeName() const override { return "hash-index-iterator-vpack"; }
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
void reset() override;

View File

@ -24,6 +24,7 @@
#include "MMFilesIndexElement.h"
#include "Basics/VelocyPackHelper.h"
#include "Indexes/IndexLookupContext.h"
#include "MMFiles/MMFilesToken.h"
using namespace arangodb;
@ -57,7 +58,7 @@ arangodb::velocypack::Slice MMFilesHashIndexElement::slice(IndexLookupContext* c
if (offset == 0) {
return basics::VelocyPackHelper::NullValue();
}
uint8_t const* vpack = context->lookup(_revisionId);
uint8_t const* vpack = context->lookup(MMFilesToken{_revisionId});
if (vpack == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND);
}
@ -133,7 +134,7 @@ arangodb::velocypack::Slice MMFilesSkiplistIndexElement::slice(IndexLookupContex
if (offset == 0) {
return basics::VelocyPackHelper::NullValue();
}
uint8_t const* vpack = context->lookup(_revisionId);
uint8_t const* vpack = context->lookup(MMFilesToken{_revisionId});
if (vpack == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND);
}
@ -149,7 +150,7 @@ uint64_t MMFilesSimpleIndexElement::hash(arangodb::velocypack::Slice const& valu
}
VPackSlice MMFilesSimpleIndexElement::slice(IndexLookupContext* context) const {
uint8_t const* vpack = context->lookup(_revisionId);
uint8_t const* vpack = context->lookup(MMFilesToken{_revisionId});
if (vpack == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND);
}

View File

@ -32,6 +32,7 @@
#include "MMFiles/MMFilesPrimaryIndex.h"
#include "MMFiles/MMFilesPersistentIndexFeature.h"
#include "MMFiles/MMFilesPersistentIndexKeyComparator.h"
#include "MMFiles/MMFilesToken.h"
#include "Utils/Transaction.h"
#include "VocBase/LogicalCollection.h"
@ -137,13 +138,13 @@ void PersistentIndexIterator::reset() {
}
/// @brief Get the next element in the index
IndexLookupResult PersistentIndexIterator::next() {
DocumentIdentifierToken PersistentIndexIterator::next() {
auto comparator = RocksDBFeature::instance()->comparator();
while (true) {
if (!_cursor->Valid()) {
// We are exhausted already, sorry
return IndexLookupResult();
return MMFilesToken{};
}
rocksdb::Slice key = _cursor->key();
@ -154,7 +155,7 @@ IndexLookupResult PersistentIndexIterator::next() {
if (res < 0) {
if (_reverse) {
return IndexLookupResult();
return MMFilesToken{};
} else {
_cursor->Next();
}
@ -164,7 +165,7 @@ IndexLookupResult PersistentIndexIterator::next() {
res = comparator->Compare(key, rocksdb::Slice(_rightEndpoint->data(), _rightEndpoint->size()));
// LOG(TRACE) << "comparing: " << VPackSlice(key.data() + PersistentIndex::keyPrefixSize()).toJson() << " with " << VPackSlice((char const*) _rightEndpoint->data() + PersistentIndex::keyPrefixSize()).toJson() << " - res: " << res;
IndexLookupResult doc;
MMFilesToken doc;
if (res <= 0) {
// get the value for _key, which is the last entry in the key array
@ -179,7 +180,7 @@ IndexLookupResult PersistentIndexIterator::next() {
// use primary index to lookup the document
MMFilesSimpleIndexElement element = _primaryIndex->lookupKey(_trx, keySlice[n - 1]);
if (element) {
doc = IndexLookupResult(element.revisionId());
doc = MMFilesToken{element.revisionId()};
}
}
@ -191,13 +192,13 @@ IndexLookupResult PersistentIndexIterator::next() {
if (res > 0) {
if (!_probe) {
return IndexLookupResult();
return MMFilesToken{};
}
_probe = false;
continue;
}
if (doc) {
if (doc != 0) {
return doc;
}
}

View File

@ -75,7 +75,7 @@ class PersistentIndexIterator final : public IndexIterator {
char const* typeName() const override { return "rocksdb-index-iterator"; }
/// @brief Get the next element in the index
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
/// @brief Reset the cursor
void reset() override;

View File

@ -29,6 +29,7 @@
#include "Basics/tri-strings.h"
#include "Indexes/IndexLookupContext.h"
#include "Indexes/SimpleAttributeEqualityMatcher.h"
#include "MMFiles/MMFilesToken.h"
#include "Utils/Transaction.h"
#include "Utils/TransactionContext.h"
#include "VocBase/LogicalCollection.h"
@ -106,20 +107,20 @@ MMFilesPrimaryIndexIterator::~MMFilesPrimaryIndexIterator() {
}
}
IndexLookupResult MMFilesPrimaryIndexIterator::next() {
DocumentIdentifierToken MMFilesPrimaryIndexIterator::next() {
while (_iterator.valid()) {
MMFilesSimpleIndexElement result = _index->lookupKey(_trx, _iterator.value());
_iterator.next();
if (result) {
// found a result
return IndexLookupResult(result.revisionId());
return MMFilesToken{result.revisionId()};
}
// found no result. now go to next lookup value in _keys
}
return IndexLookupResult();
return MMFilesToken{};
}
void MMFilesPrimaryIndexIterator::reset() { _iterator.reset(); }
@ -132,7 +133,7 @@ AllIndexIterator::AllIndexIterator(LogicalCollection* collection,
bool reverse)
: IndexIterator(collection, trx, mmdr, index), _index(indexImpl), _reverse(reverse), _total(0) {}
IndexLookupResult AllIndexIterator::next() {
DocumentIdentifierToken AllIndexIterator::next() {
MMFilesSimpleIndexElement element;
if (_reverse) {
element = _index->findSequentialReverse(&_context, _position);
@ -140,12 +141,12 @@ IndexLookupResult AllIndexIterator::next() {
element = _index->findSequential(&_context, _position, _total);
}
if (element) {
return IndexLookupResult(element.revisionId());
return MMFilesToken{element.revisionId()};
}
return IndexLookupResult();
return MMFilesToken{};
}
void AllIndexIterator::nextBabies(std::vector<IndexLookupResult>& buffer, size_t limit) {
void AllIndexIterator::nextBabies(std::vector<DocumentIdentifierToken>& buffer, size_t limit) {
size_t atMost = limit;
buffer.clear();
@ -154,9 +155,9 @@ void AllIndexIterator::nextBabies(std::vector<IndexLookupResult>& buffer, size_t
}
while (atMost > 0) {
IndexLookupResult result = next();
DocumentIdentifierToken result = next();
if (!result) {
if (result == 0) {
return;
}
@ -173,12 +174,12 @@ AnyIndexIterator::AnyIndexIterator(LogicalCollection* collection, arangodb::Tran
MMFilesPrimaryIndexImpl const* indexImpl)
: IndexIterator(collection, trx, mmdr, index), _index(indexImpl), _step(0), _total(0) {}
IndexLookupResult AnyIndexIterator::next() {
DocumentIdentifierToken AnyIndexIterator::next() {
MMFilesSimpleIndexElement element = _index->findRandom(&_context, _initial, _position, _step, _total);
if (element) {
return IndexLookupResult(element.revisionId());
return MMFilesToken{element.revisionId()};
}
return IndexLookupResult();
return MMFilesToken{};
}
void AnyIndexIterator::reset() {

View File

@ -54,7 +54,7 @@ class MMFilesPrimaryIndexIterator final : public IndexIterator {
char const* typeName() const override { return "primary-index-iterator"; }
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
void reset() override;
@ -77,9 +77,9 @@ class AllIndexIterator final : public IndexIterator {
char const* typeName() const override { return "all-index-iterator"; }
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
void nextBabies(std::vector<IndexLookupResult>&, size_t) override;
void nextBabies(std::vector<DocumentIdentifierToken>&, size_t) override;
void reset() override;
@ -101,7 +101,7 @@ class AnyIndexIterator final : public IndexIterator {
char const* typeName() const override { return "any-index-iterator"; }
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
void reset() override;

View File

@ -29,6 +29,7 @@
#include "Basics/StaticStrings.h"
#include "Basics/VelocyPackHelper.h"
#include "Indexes/IndexLookupContext.h"
#include "MMFiles/MMFilesToken.h"
#include "Utils/Transaction.h"
#include "VocBase/LogicalCollection.h"
@ -520,10 +521,10 @@ void MMFilesSkiplistIterator::reset() {
}
/// @brief Get the next element in the skiplist
IndexLookupResult MMFilesSkiplistIterator::next() {
DocumentIdentifierToken MMFilesSkiplistIterator::next() {
if (_cursor == nullptr) {
// We are exhausted already, sorry
return IndexLookupResult();
return MMFilesToken{};
}
Node* tmp = _cursor;
if (_reverse) {
@ -541,7 +542,7 @@ IndexLookupResult MMFilesSkiplistIterator::next() {
}
TRI_ASSERT(tmp != nullptr);
TRI_ASSERT(tmp->document() != nullptr);
return IndexLookupResult(tmp->document()->revisionId());
return MMFilesToken{tmp->document()->revisionId()};
}
MMFilesSkiplistIterator2::MMFilesSkiplistIterator2(LogicalCollection* collection, arangodb::Transaction* trx,
@ -602,10 +603,10 @@ void MMFilesSkiplistIterator2::reset() {
}
/// @brief Get the next element in the skiplist
IndexLookupResult MMFilesSkiplistIterator2::next() {
DocumentIdentifierToken MMFilesSkiplistIterator2::next() {
if (_cursor == nullptr) {
// We are exhausted already, sorry
return IndexLookupResult();
return MMFilesToken{};
}
TRI_ASSERT(_currentInterval < _intervals.size());
auto const& interval = _intervals[_currentInterval];
@ -625,7 +626,7 @@ IndexLookupResult MMFilesSkiplistIterator2::next() {
}
TRI_ASSERT(tmp != nullptr);
TRI_ASSERT(tmp->document() != nullptr);
return IndexLookupResult(tmp->document()->revisionId());
return MMFilesToken{tmp->document()->revisionId()};
}
void MMFilesSkiplistIterator2::forwardCursor() {

View File

@ -196,7 +196,7 @@ class MMFilesSkiplistIterator final : public IndexIterator {
char const* typeName() const override { return "skiplist-index-iterator"; }
/// @brief Get the next element in the skiplist
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
/// @brief Reset the cursor
void reset() override;
@ -257,7 +257,7 @@ class MMFilesSkiplistIterator2 final : public IndexIterator {
char const* typeName() const override { return "skiplist-index-iterator2"; }
/// @brief Get the next element in the skiplist
IndexLookupResult next() override;
DocumentIdentifierToken next() override;
/// @brief Reset the cursor
void reset() override;

View File

@ -0,0 +1,46 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 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
////////////////////////////////////////////////////////////////////////////////
#include "StorageEngine/StorageEngine.h"
namespace arangodb {
struct MMFilesToken : public DocumentIdentifierToken {
public:
MMFilesToken() : DocumentIdentifierToken() {}
explicit MMFilesToken(TRI_voc_rid_t revisionId)
: DocumentIdentifierToken(revisionId) {}
MMFilesToken(MMFilesToken const& other)
: DocumentIdentifierToken(other._data) {}
MMFilesToken& operator=(MMFilesToken const& other) {
_data = other._data;
return *this;
}
inline TRI_voc_rid_t revisionId() const {
return static_cast<TRI_voc_rid_t>(_data);
}
};
static_assert(sizeof(MMFilesToken) == sizeof(uint64_t), "invalid MMFilesToken size");
}

View File

@ -91,7 +91,7 @@ bool RestEdgesHandler::getEdgesForVertexList(
THROW_ARANGO_EXCEPTION(cursor->code);
}
std::vector<IndexLookupResult> batch;
std::vector<DocumentIdentifierToken> batch;
ManagedDocumentResult mmdr;
auto collection = trx.documentCollection();
while (cursor->hasMore()) {
@ -99,8 +99,7 @@ bool RestEdgesHandler::getEdgesForVertexList(
scannedIndex += batch.size();
for (auto const& it : batch) {
TRI_voc_rid_t revisionId = it.revisionId();
if (collection->readRevision(&trx, mmdr, revisionId)) {
if (collection->readDocument(&trx, mmdr, it)) {
result.add(VPackSlice(mmdr.vpack()));
}
}
@ -129,7 +128,7 @@ bool RestEdgesHandler::getEdgesForVertex(
THROW_ARANGO_EXCEPTION(cursor->code);
}
std::vector<IndexLookupResult> batch;
std::vector<DocumentIdentifierToken> batch;
ManagedDocumentResult mmdr;
auto collection = trx.documentCollection();
while (cursor->hasMore()) {
@ -137,8 +136,7 @@ bool RestEdgesHandler::getEdgesForVertex(
scannedIndex += batch.size();
for (auto const& it : batch) {
TRI_voc_rid_t revisionId = it.revisionId();
if (collection->readRevision(&trx, mmdr, revisionId)) {
if (collection->readDocument(&trx, mmdr, it)) {
result.add(VPackSlice(mmdr.vpack()));
}
}

View File

@ -37,6 +37,33 @@ namespace arangodb {
class LogicalCollection;
class PhysicalCollection;
// @brief This token is handed out by Indexes and
// is used by StorageEngines to return a document
// Only specializations of this token can be created.
struct DocumentIdentifierToken {
public:
// TODO Replace by Engine::InvalidToken
constexpr DocumentIdentifierToken() : _data(0) {}
~DocumentIdentifierToken() {}
inline bool operator==(DocumentIdentifierToken const& other) const { return _data == other._data; }
inline bool operator==(uint64_t const& other) const { return _data == other; }
inline bool operator!=(DocumentIdentifierToken const& other) const { return !(operator==(other)); }
inline bool operator!=(uint64_t const& other) const { return !(operator==(other)); }
protected:
explicit DocumentIdentifierToken(uint64_t data) : _data(data) {}
public:
uint64_t _data;
};
class StorageEngine : public application_features::ApplicationFeature {
public:
@ -249,4 +276,22 @@ class StorageEngine : public application_features::ApplicationFeature {
}
namespace std {
template <>
struct hash<arangodb::DocumentIdentifierToken> {
inline size_t operator()(arangodb::DocumentIdentifierToken const& token) const noexcept {
return token._data;
}
};
template <>
struct equal_to<arangodb::DocumentIdentifierToken> {
bool operator()(arangodb::DocumentIdentifierToken const& lhs,
arangodb::DocumentIdentifierToken const& rhs) const {
return lhs == rhs;
}
};
}
#endif

View File

@ -47,8 +47,8 @@ void OperationCursor::reset() {
/// NOTE: This will throw on OUT_OF_MEMORY
//////////////////////////////////////////////////////////////////////////////
std::vector<IndexLookupResult> OperationCursor::getMoreMptr(uint64_t batchSize) {
std::vector<IndexLookupResult> res;
std::vector<DocumentIdentifierToken> OperationCursor::getMoreMptr(uint64_t batchSize) {
std::vector<DocumentIdentifierToken> res;
getMoreMptr(res, batchSize);
return res;
}
@ -62,7 +62,7 @@ std::vector<IndexLookupResult> OperationCursor::getMoreMptr(uint64_t batchSize)
/// The caller shall NOT modify it.
//////////////////////////////////////////////////////////////////////////////
void OperationCursor::getMoreMptr(std::vector<IndexLookupResult>& result,
void OperationCursor::getMoreMptr(std::vector<DocumentIdentifierToken>& result,
uint64_t batchSize) {
if (!hasMore()) {
TRI_ASSERT(false);

View File

@ -108,7 +108,7 @@ struct OperationCursor {
/// NOTE: This will throw on OUT_OF_MEMORY
//////////////////////////////////////////////////////////////////////////////
std::vector<IndexLookupResult> getMoreMptr(uint64_t batchSize = 1000);
std::vector<DocumentIdentifierToken> getMoreMptr(uint64_t batchSize = 1000);
//////////////////////////////////////////////////////////////////////////////
/// @brief Get next batchSize many elements. mptr variant
@ -118,7 +118,7 @@ struct OperationCursor {
/// NOTE: The result vector handed in will be cleared.
//////////////////////////////////////////////////////////////////////////////
void getMoreMptr(std::vector<IndexLookupResult>& result, uint64_t batchSize = 1000);
void getMoreMptr(std::vector<DocumentIdentifierToken>& result, uint64_t batchSize = 1000);
//////////////////////////////////////////////////////////////////////////////
/// @brief Skip the next toSkip many elements.

View File

@ -1286,14 +1286,13 @@ OperationResult Transaction::anyLocal(std::string const& collectionName,
{}, &mmdr, skip, limit, 1000, false);
LogicalCollection* collection = cursor->collection();
std::vector<IndexLookupResult> result;
std::vector<DocumentIdentifierToken> result;
while (cursor->hasMore()) {
result.clear();
cursor->getMoreMptr(result);
for (auto const& element : result) {
TRI_voc_rid_t revisionId = element.revisionId();
if (collection->readRevision(this, mmdr, revisionId)) {
if (collection->readDocument(this, mmdr, element)) {
uint8_t const* vpack = mmdr.vpack();
resultBuilder.add(VPackSlice(vpack));
}
@ -2647,14 +2646,13 @@ OperationResult Transaction::allLocal(std::string const& collectionName,
}
LogicalCollection* collection = cursor->collection();
std::vector<IndexLookupResult> result;
std::vector<DocumentIdentifierToken> result;
result.reserve(1000);
while (cursor->hasMore()) {
cursor->getMoreMptr(result, 1000);
for (auto const& element : result) {
TRI_voc_rid_t revisionId = element.revisionId();
if (collection->readRevision(this, mmdr, revisionId)) {
if (collection->readDocument(this, mmdr, element)) {
uint8_t const* vpack = mmdr.vpack();
resultBuilder.addExternal(vpack);
}

View File

@ -254,7 +254,7 @@ static void JS_AllQuery(v8::FunctionCallbackInfo<v8::Value> const& args) {
VPackOptions resultOptions = VPackOptions::Defaults;
resultOptions.customTypeHandler = transactionContext->orderCustomTypeHandler().get();
std::vector<IndexLookupResult> batch;
std::vector<DocumentIdentifierToken> batch;
ManagedDocumentResult mmdr;
VPackBuilder resultBuilder;
resultBuilder.openArray();
@ -262,8 +262,7 @@ static void JS_AllQuery(v8::FunctionCallbackInfo<v8::Value> const& args) {
opCursor->getMoreMptr(batch);
// We only need this one call, limit == batchsize
for (auto const& it : batch) {
TRI_voc_rid_t revisionId = it.revisionId();
if (collection->readRevision(&trx, mmdr, revisionId)) {
if (collection->readDocument(&trx, mmdr, it)) {
resultBuilder.add(VPackSlice(mmdr.vpack()));
}
}

View File

@ -48,6 +48,7 @@
#include "MMFiles/MMFilesPersistentIndex.h"
#include "MMFiles/MMFilesPrimaryIndex.h"
#include "MMFiles/MMFilesSkiplistIndex.h"
#include "MMFiles/MMFilesToken.h"
#include "MMFiles/MMFilesWalMarker.h"
#include "MMFiles/MMFilesWalSlots.h"
#include "StorageEngine/StorageEngine.h"
@ -3766,6 +3767,13 @@ bool LogicalCollection::readRevisionConditional(Transaction* trx,
return false;
}
// TODO ONLY TEMP wrapper
bool LogicalCollection::readDocument(arangodb::Transaction* trx, ManagedDocumentResult& result, DocumentIdentifierToken const& token) {
// TODO This only works for MMFiles Engine. Has to be moved => StorageEngine
auto tkn = static_cast<MMFilesToken const*>(&token);
return readRevision(trx, result, tkn->revisionId());
}
void LogicalCollection::insertRevision(TRI_voc_rid_t revisionId,
uint8_t const* dataptr,
TRI_voc_fid_t fid, bool isInWal) {

View File

@ -25,6 +25,7 @@
#define ARANGOD_VOCBASE_LOGICAL_COLLECTION_H 1
#include "Basics/Common.h"
#include "StorageEngine/StorageEngine.h"
#include "VocBase/PhysicalCollection.h"
#include "VocBase/voc-types.h"
#include "VocBase/vocbase.h"
@ -384,6 +385,7 @@ class LogicalCollection {
bool readRevision(arangodb::Transaction*, ManagedDocumentResult& result, TRI_voc_rid_t revisionId);
bool readRevisionConditional(arangodb::Transaction*, ManagedDocumentResult& result, TRI_voc_rid_t revisionId, TRI_voc_tick_t maxTick, bool excludeWal);
bool readDocument(arangodb::Transaction*, ManagedDocumentResult& result, DocumentIdentifierToken const& token);
void insertRevision(TRI_voc_rid_t revisionId, uint8_t const* dataptr, TRI_voc_fid_t fid, bool isInWal);
void updateRevision(TRI_voc_rid_t revisionId, uint8_t const* dataptr, TRI_voc_fid_t fid, bool isInWal);

View File

@ -78,8 +78,7 @@ bool SingleServerEdgeCursor::next(std::vector<VPackSlice>& result,
_cachePos++;
if (_cachePos < _cache.size()) {
LogicalCollection* collection = _cursors[_currentCursor][_currentSubCursor]->collection();
TRI_voc_rid_t revisionId = _cache[_cachePos].revisionId();
if (collection->readRevision(_trx, *_mmdr, revisionId)) {
if (collection->readDocument(_trx, *_mmdr, _cache[_cachePos])) {
result.emplace_back(_mmdr->vpack());
}
if (_internalCursorMapping != nullptr) {
@ -128,8 +127,7 @@ bool SingleServerEdgeCursor::next(std::vector<VPackSlice>& result,
TRI_ASSERT(_cachePos < _cache.size());
LogicalCollection* collection = cursor->collection();
TRI_voc_rid_t revisionId = _cache[_cachePos].revisionId();
if (collection->readRevision(_trx, *_mmdr, revisionId)) {
if (collection->readDocument(_trx, *_mmdr, _cache[_cachePos])) {
result.emplace_back(_mmdr->vpack());
}
if (_internalCursorMapping != nullptr) {
@ -162,8 +160,7 @@ bool SingleServerEdgeCursor::readAll(std::unordered_set<VPackSlice>& result,
// because the cursor expect's it to be filled.
cursor->getMoreMptr(_cache);
for (auto const& element : _cache) {
TRI_voc_rid_t revisionId = element.revisionId();
if (collection->readRevision(_trx, *_mmdr, revisionId)) {
if (collection->readDocument(_trx, *_mmdr, element)) {
result.emplace(_mmdr->vpack());
}
}

View File

@ -48,7 +48,7 @@ class SingleServerEdgeCursor : public EdgeCursor {
std::vector<std::vector<OperationCursor*>> _cursors;
size_t _currentCursor;
size_t _currentSubCursor;
std::vector<IndexLookupResult> _cache;
std::vector<DocumentIdentifierToken> _cache;
size_t _cachePos;
std::vector<size_t> const* _internalCursorMapping;