diff options
Diffstat (limited to 'src/mongo/db/storage/in_memory')
-rw-r--r-- | src/mongo/db/storage/in_memory/in_memory_record_store.cpp | 353 | ||||
-rw-r--r-- | src/mongo/db/storage/in_memory/in_memory_record_store.h | 77 |
2 files changed, 157 insertions, 273 deletions
diff --git a/src/mongo/db/storage/in_memory/in_memory_record_store.cpp b/src/mongo/db/storage/in_memory/in_memory_record_store.cpp index 841888cb051..92deaf82810 100644 --- a/src/mongo/db/storage/in_memory/in_memory_record_store.cpp +++ b/src/mongo/db/storage/in_memory/in_memory_record_store.cpp @@ -36,12 +36,14 @@ #include <boost/shared_ptr.hpp> #include "mongo/db/jsobj.h" +#include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" #include "mongo/db/storage/oplog_hack.h" #include "mongo/db/storage/recovery_unit.h" +#include "mongo/stdx/memory.h" #include "mongo/util/log.h" -#include "mongo/db/namespace_string.h" #include "mongo/util/mongoutils/str.h" +#include "mongo/util/unowned_ptr.h" namespace mongo { @@ -109,6 +111,152 @@ namespace mongo { Records _records; }; + class InMemoryRecordStore::Cursor final : public RecordCursor { + public: + Cursor(OperationContext* txn, const InMemoryRecordStore& rs) + : _txn(txn) + , _records(rs._data->records) + , _isCapped(rs.isCapped()) + {} + + boost::optional<Record> next() final { + if (_needFirstSeek) { + _needFirstSeek = false; + _it = _records.begin(); + } + else if (!_lastMoveWasRestore && _it != _records.end()) { + ++_it; + } + _lastMoveWasRestore = false; + + if (_it == _records.end()) return {}; + return {{_it->first, _it->second.toRecordData()}}; + } + + boost::optional<Record> seekExact(const RecordId& id) final { + _lastMoveWasRestore = false; + _needFirstSeek = false; + _it = _records.find(id); + if (_it == _records.end()) return {}; + return {{_it->first, _it->second.toRecordData()}}; + } + + void savePositioned() final { + _txn = nullptr; + if (!_needFirstSeek && !_lastMoveWasRestore) + _savedId = _it == _records.end() ? RecordId() : _it->first; + } + + void saveUnpositioned() final { + _txn = nullptr; + _savedId = RecordId(); + } + + bool restore(OperationContext* txn) final { + _txn = txn; + if (_savedId.isNull()) { + _it = _records.end(); + return true; + } + + _it = _records.lower_bound(_savedId); + _lastMoveWasRestore = _it == _records.end() || _it->first != _savedId; + + // Capped iterators die on invalidation rather than advancing. + return !(_isCapped && _lastMoveWasRestore); + } + + private: + unowned_ptr<OperationContext> _txn; + Records::const_iterator _it; + bool _needFirstSeek = true; + bool _lastMoveWasRestore = false; + RecordId _savedId; // Location to restore() to. Null means EOF. + + const InMemoryRecordStore::Records& _records; + const bool _isCapped; + }; + + class InMemoryRecordStore::ReverseCursor final : public RecordCursor { + public: + ReverseCursor(OperationContext* txn, const InMemoryRecordStore& rs) + : _txn(txn) + , _records(rs._data->records) + , _isCapped(rs.isCapped()) + {} + + boost::optional<Record> next() final { + if (_needFirstSeek) { + _needFirstSeek = false; + _it = _records.rbegin(); + } + else if (!_lastMoveWasRestore && _it != _records.rend()) { + ++_it; + } + _lastMoveWasRestore = false; + + if (_it == _records.rend()) return {}; + return {{_it->first, _it->second.toRecordData()}}; + } + + boost::optional<Record> seekExact(const RecordId& id) final { + _lastMoveWasRestore = false; + _needFirstSeek = false; + + auto forwardIt = _records.find(id); + if (forwardIt == _records.end()) { + _it = _records.rend(); + return {}; + } + + // The reverse_iterator will point to the preceding element, so increment the base + // iterator to make it point past the found element. + ++forwardIt; + _it = Records::const_reverse_iterator(forwardIt); + dassert(_it != _records.rend()); + dassert(_it->first == id); + return {{_it->first, _it->second.toRecordData()}}; + } + + void savePositioned() final { + _txn = nullptr; + if (!_needFirstSeek && !_lastMoveWasRestore) + _savedId = _it == _records.rend() ? RecordId() : _it->first; + } + + void saveUnpositioned() final { + _txn = nullptr; + _savedId = RecordId(); + } + + bool restore(OperationContext* txn) final { + _txn = txn; + if (_savedId.isNull()) { + _it = _records.rend(); + return true; + } + + // Note: upper_bound returns the first entry > _savedId and reverse_iterators + // dereference to the element before their base iterator. This combine to make this + // dereference to the first element <= _savedId which is what we want here. + _it = Records::const_reverse_iterator(_records.upper_bound(_savedId)); + _lastMoveWasRestore = _it == _records.rend() || _it->first != _savedId; + + // Capped iterators die on invalidation rather than advancing. + return !(_isCapped && _lastMoveWasRestore); + } + + private: + unowned_ptr<OperationContext> _txn; + Records::const_reverse_iterator _it; + bool _needFirstSeek = true; + bool _lastMoveWasRestore = false; + RecordId _savedId; // Location to restore() to. Null means EOF. + const InMemoryRecordStore::Records& _records; + const bool _isCapped; + }; + + // // RecordStore // @@ -369,30 +517,11 @@ namespace mongo { return Status::OK(); } - RecordIterator* InMemoryRecordStore::getIterator( - OperationContext* txn, - const RecordId& start, - const CollectionScanParams::Direction& dir) const { + std::unique_ptr<RecordCursor> InMemoryRecordStore::getCursor(OperationContext* txn, + bool forward) const { - if (dir == CollectionScanParams::FORWARD) { - return new InMemoryRecordIterator(txn, _data->records, *this, start, false); - } - else { - return new InMemoryRecordReverseIterator(txn, _data->records, *this, start); - } - } - - RecordIterator* InMemoryRecordStore::getIteratorForRepair(OperationContext* txn) const { - // TODO maybe make different from InMemoryRecordIterator - return new InMemoryRecordIterator(txn, _data->records, *this); - } - - std::vector<RecordIterator*> InMemoryRecordStore::getManyIterators( - OperationContext* txn) const { - std::vector<RecordIterator*> out; - // TODO maybe find a way to return multiple iterators. - out.push_back(new InMemoryRecordIterator(txn, _data->records, *this)); - return out; + if (forward) return stdx::make_unique<Cursor>(txn, *this); + return stdx::make_unique<ReverseCursor>(txn, *this); } Status InMemoryRecordStore::truncate(OperationContext* txn) { @@ -498,180 +627,4 @@ namespace mongo { return it->first; } - // - // Forward Iterator - // - - InMemoryRecordIterator::InMemoryRecordIterator(OperationContext* txn, - const InMemoryRecordStore::Records& records, - const InMemoryRecordStore& rs, - RecordId start, - bool tailable) - : _txn(txn), - _tailable(tailable), - _lastLoc(RecordId::min()), - _killedByInvalidate(false), - _records(records), - _rs(rs) { - if (start.isNull()) { - _it = _records.begin(); - } - else { - _it = _records.find(start); - invariant(_it != _records.end()); - } - } - - bool InMemoryRecordIterator::isEOF() { - return _it == _records.end(); - } - - RecordId InMemoryRecordIterator::curr() { - if (isEOF()) - return RecordId(); - return _it->first; - } - - RecordId InMemoryRecordIterator::getNext() { - if (isEOF()) { - if (!_tailable) - return RecordId(); - - if (_records.empty()) - return RecordId(); - - invariant(!_killedByInvalidate); - - // recover to last returned record - invariant(!_lastLoc.isNull()); - _it = _records.find(_lastLoc); - invariant(_it != _records.end()); - - if (++_it == _records.end()) - return RecordId(); - } - - const RecordId out = _it->first; - ++_it; - if (_tailable && _it == _records.end()) - _lastLoc = out; - return out; - } - - void InMemoryRecordIterator::invalidate(const RecordId& loc) { - if (_rs.isCapped()) { - // Capped iterators die on invalidation rather than advancing. - if (isEOF()) { - if (_lastLoc == loc) { - _killedByInvalidate = true; - } - } - else if (_it->first == loc) { - _killedByInvalidate = true; - } - - return; - } - - if (_it != _records.end() && _it->first == loc) - ++_it; - } - - void InMemoryRecordIterator::saveState() { - } - - bool InMemoryRecordIterator::restoreState(OperationContext* txn) { - _txn = txn; - return !_killedByInvalidate; - } - - RecordData InMemoryRecordIterator::dataFor(const RecordId& loc) const { - return _rs.dataFor(_txn, loc); - } - - // - // Reverse Iterator - // - - InMemoryRecordReverseIterator::InMemoryRecordReverseIterator( - OperationContext* txn, - const InMemoryRecordStore::Records& records, - const InMemoryRecordStore& rs, - RecordId start) : _txn(txn), - _killedByInvalidate(false), - _records(records), - _rs(rs) { - - if (start.isNull()) { - _it = _records.rbegin(); - } - else { - // The reverse iterator will point to the preceding element, so we - // increment the base iterator to make it point past the found element - InMemoryRecordStore::Records::const_iterator baseIt(++_records.find(start)); - _it = InMemoryRecordStore::Records::const_reverse_iterator(baseIt); - invariant(_it != _records.rend()); - } - } - - bool InMemoryRecordReverseIterator::isEOF() { - return _it == _records.rend(); - } - - RecordId InMemoryRecordReverseIterator::curr() { - if (isEOF()) - return RecordId(); - return _it->first; - } - - RecordId InMemoryRecordReverseIterator::getNext() { - if (isEOF()) - return RecordId(); - - const RecordId out = _it->first; - ++_it; - return out; - } - - void InMemoryRecordReverseIterator::invalidate(const RecordId& loc) { - if (_killedByInvalidate) - return; - - if (_savedLoc == loc) { - if (_rs.isCapped()) { - // Capped iterators die on invalidation rather than advancing. - _killedByInvalidate = true; - return; - } - - restoreState(_txn); - invariant(_it->first == _savedLoc); - ++_it; - saveState(); - } - } - - void InMemoryRecordReverseIterator::saveState() { - if (isEOF()) { - _savedLoc = RecordId(); - } - else { - _savedLoc = _it->first; - } - } - - bool InMemoryRecordReverseIterator::restoreState(OperationContext* txn) { - if (_savedLoc.isNull()) { - _it = _records.rend(); - } - else { - _it = InMemoryRecordStore::Records::const_reverse_iterator(++_records.find(_savedLoc)); - } - return !_killedByInvalidate; - } - - RecordData InMemoryRecordReverseIterator::dataFor(const RecordId& loc) const { - return _rs.dataFor(_txn, loc); - } - } // namespace mongo diff --git a/src/mongo/db/storage/in_memory/in_memory_record_store.h b/src/mongo/db/storage/in_memory/in_memory_record_store.h index 239c4f7bb09..e091d75c4a1 100644 --- a/src/mongo/db/storage/in_memory/in_memory_record_store.h +++ b/src/mongo/db/storage/in_memory/in_memory_record_store.h @@ -39,8 +39,6 @@ namespace mongo { - class InMemoryRecordIterator; - /** * A RecordStore that stores all data in-memory. * @@ -87,13 +85,7 @@ namespace mongo { const char* damageSource, const mutablebson::DamageVector& damages ); - virtual RecordIterator* getIterator( OperationContext* txn, - const RecordId& start, - const CollectionScanParams::Direction& dir) const; - - virtual RecordIterator* getIteratorForRepair( OperationContext* txn ) const; - - virtual std::vector<RecordIterator*> getManyIterators( OperationContext* txn ) const; + std::unique_ptr<RecordCursor> getCursor(OperationContext* txn, bool forward) const final; virtual Status truncate( OperationContext* txn ); @@ -166,6 +158,9 @@ namespace mongo { class RemoveChange; class TruncateChange; + class Cursor; + class ReverseCursor; + StatusWith<RecordId> extractAndCheckLocForOplog(const char* data, int len) const; RecordId allocateLoc(); @@ -191,68 +186,4 @@ namespace mongo { Data* const _data; }; - class InMemoryRecordIterator : public RecordIterator { - public: - InMemoryRecordIterator(OperationContext* txn, - const InMemoryRecordStore::Records& records, - const InMemoryRecordStore& rs, - RecordId start = RecordId(), - bool tailable = false); - - virtual bool isEOF(); - - virtual RecordId curr(); - - virtual RecordId getNext(); - - virtual void invalidate(const RecordId& dl); - - virtual void saveState(); - - virtual bool restoreState(OperationContext* txn); - - virtual RecordData dataFor( const RecordId& loc ) const; - - private: - OperationContext* _txn; // not owned - InMemoryRecordStore::Records::const_iterator _it; - bool _tailable; - RecordId _lastLoc; // only for restarting tailable - bool _killedByInvalidate; - - const InMemoryRecordStore::Records& _records; - const InMemoryRecordStore& _rs; - }; - - class InMemoryRecordReverseIterator : public RecordIterator { - public: - InMemoryRecordReverseIterator(OperationContext* txn, - const InMemoryRecordStore::Records& records, - const InMemoryRecordStore& rs, - RecordId start = RecordId()); - - virtual bool isEOF(); - - virtual RecordId curr(); - - virtual RecordId getNext(); - - virtual void invalidate(const RecordId& dl); - - virtual void saveState(); - - virtual bool restoreState(OperationContext* txn); - - virtual RecordData dataFor( const RecordId& loc ) const; - - private: - OperationContext* _txn; // not owned - InMemoryRecordStore::Records::const_reverse_iterator _it; - bool _killedByInvalidate; - RecordId _savedLoc; // isNull if saved at EOF - - const InMemoryRecordStore::Records& _records; - const InMemoryRecordStore& _rs; - }; - } // namespace mongo |