diff options
Diffstat (limited to 'src/mongo/db/exec/working_set.cpp')
-rw-r--r-- | src/mongo/db/exec/working_set.cpp | 393 |
1 files changed, 196 insertions, 197 deletions
diff --git a/src/mongo/db/exec/working_set.cpp b/src/mongo/db/exec/working_set.cpp index 746ace2f3ca..5e531af346a 100644 --- a/src/mongo/db/exec/working_set.cpp +++ b/src/mongo/db/exec/working_set.cpp @@ -33,248 +33,247 @@ namespace mongo { - using std::string; +using std::string; - WorkingSet::MemberHolder::MemberHolder() : member(NULL) { } - WorkingSet::MemberHolder::~MemberHolder() {} +WorkingSet::MemberHolder::MemberHolder() : member(NULL) {} +WorkingSet::MemberHolder::~MemberHolder() {} - WorkingSet::WorkingSet() : _freeList(INVALID_ID) { } +WorkingSet::WorkingSet() : _freeList(INVALID_ID) {} - WorkingSet::~WorkingSet() { - for (size_t i = 0; i < _data.size(); i++) { - delete _data[i].member; - } +WorkingSet::~WorkingSet() { + for (size_t i = 0; i < _data.size(); i++) { + delete _data[i].member; } - - WorkingSetID WorkingSet::allocate() { - if (_freeList == INVALID_ID) { - // The free list is empty so we need to make a single new WSM to return. This relies on - // vector::resize being amortized O(1) for efficient allocation. Note that the free list - // remains empty until something is returned by a call to free(). - WorkingSetID id = _data.size(); - _data.resize(_data.size() + 1); - _data.back().nextFreeOrSelf = id; - _data.back().member = new WorkingSetMember(); - return id; - } - - // Pop the head off the free list and return it. - WorkingSetID id = _freeList; - _freeList = _data[id].nextFreeOrSelf; - _data[id].nextFreeOrSelf = id; // set to self to mark as in-use +} + +WorkingSetID WorkingSet::allocate() { + if (_freeList == INVALID_ID) { + // The free list is empty so we need to make a single new WSM to return. This relies on + // vector::resize being amortized O(1) for efficient allocation. Note that the free list + // remains empty until something is returned by a call to free(). + WorkingSetID id = _data.size(); + _data.resize(_data.size() + 1); + _data.back().nextFreeOrSelf = id; + _data.back().member = new WorkingSetMember(); return id; } - void WorkingSet::free(const WorkingSetID& i) { - MemberHolder& holder = _data[i]; - verify(i < _data.size()); // ID has been allocated. - verify(holder.nextFreeOrSelf == i); // ID currently in use. - - // Free resources and push this WSM to the head of the freelist. - holder.member->clear(); - holder.nextFreeOrSelf = _freeList; - _freeList = i; - } - - void WorkingSet::flagForReview(const WorkingSetID& i) { - WorkingSetMember* member = get(i); - verify(WorkingSetMember::OWNED_OBJ == member->state); - _flagged.insert(i); + // Pop the head off the free list and return it. + WorkingSetID id = _freeList; + _freeList = _data[id].nextFreeOrSelf; + _data[id].nextFreeOrSelf = id; // set to self to mark as in-use + return id; +} + +void WorkingSet::free(const WorkingSetID& i) { + MemberHolder& holder = _data[i]; + verify(i < _data.size()); // ID has been allocated. + verify(holder.nextFreeOrSelf == i); // ID currently in use. + + // Free resources and push this WSM to the head of the freelist. + holder.member->clear(); + holder.nextFreeOrSelf = _freeList; + _freeList = i; +} + +void WorkingSet::flagForReview(const WorkingSetID& i) { + WorkingSetMember* member = get(i); + verify(WorkingSetMember::OWNED_OBJ == member->state); + _flagged.insert(i); +} + +const unordered_set<WorkingSetID>& WorkingSet::getFlagged() const { + return _flagged; +} + +bool WorkingSet::isFlagged(WorkingSetID id) const { + invariant(id < _data.size()); + return _flagged.end() != _flagged.find(id); +} + +void WorkingSet::clear() { + for (size_t i = 0; i < _data.size(); i++) { + delete _data[i].member; } + _data.clear(); - const unordered_set<WorkingSetID>& WorkingSet::getFlagged() const { - return _flagged; - } - - bool WorkingSet::isFlagged(WorkingSetID id) const { - invariant(id < _data.size()); - return _flagged.end() != _flagged.find(id); - } + // Since working set is now empty, the free list pointer should + // point to nothing. + _freeList = INVALID_ID; - void WorkingSet::clear() { - for (size_t i = 0; i < _data.size(); i++) { - delete _data[i].member; - } - _data.clear(); + _flagged.clear(); +} - // Since working set is now empty, the free list pointer should - // point to nothing. - _freeList = INVALID_ID; +// +// Iteration +// - _flagged.clear(); +WorkingSet::iterator::iterator(WorkingSet* ws, size_t index) : _ws(ws), _index(index) { + // If we're currently not pointing at an allocated member, then we have + // to advance to the first one, unless we're already at the end. + if (_index < _ws->_data.size() && isFree()) { + advance(); } +} - // - // Iteration - // - - WorkingSet::iterator::iterator(WorkingSet* ws, size_t index) - : _ws(ws), - _index(index) { - // If we're currently not pointing at an allocated member, then we have - // to advance to the first one, unless we're already at the end. - if (_index < _ws->_data.size() && isFree()) { - advance(); - } - } +void WorkingSet::iterator::advance() { + // Move forward at least once in the data list. + _index++; - void WorkingSet::iterator::advance() { - // Move forward at least once in the data list. + // While we haven't hit the end and the current member is not in use. (Skips ahead until + // we find the next allocated member.) + while (_index < _ws->_data.size() && isFree()) { _index++; - - // While we haven't hit the end and the current member is not in use. (Skips ahead until - // we find the next allocated member.) - while (_index < _ws->_data.size() && isFree()) { - _index++; - } } +} - bool WorkingSet::iterator::isFree() const { - return _ws->_data[_index].nextFreeOrSelf != _index; - } +bool WorkingSet::iterator::isFree() const { + return _ws->_data[_index].nextFreeOrSelf != _index; +} - void WorkingSet::iterator::free() { - dassert(!isFree()); - _ws->free(_index); - } +void WorkingSet::iterator::free() { + dassert(!isFree()); + _ws->free(_index); +} - void WorkingSet::iterator::operator++() { - dassert(_index < _ws->_data.size()); - advance(); - } +void WorkingSet::iterator::operator++() { + dassert(_index < _ws->_data.size()); + advance(); +} - bool WorkingSet::iterator::operator==(const WorkingSet::iterator& other) const { - return (_index == other._index); - } +bool WorkingSet::iterator::operator==(const WorkingSet::iterator& other) const { + return (_index == other._index); +} - bool WorkingSet::iterator::operator!=(const WorkingSet::iterator& other) const { - return (_index != other._index); - } +bool WorkingSet::iterator::operator!=(const WorkingSet::iterator& other) const { + return (_index != other._index); +} - WorkingSetMember& WorkingSet::iterator::operator*() { - dassert(_index < _ws->_data.size() && !isFree()); - return *_ws->_data[_index].member; - } +WorkingSetMember& WorkingSet::iterator::operator*() { + dassert(_index < _ws->_data.size() && !isFree()); + return *_ws->_data[_index].member; +} - WorkingSetMember* WorkingSet::iterator::operator->() { - dassert(_index < _ws->_data.size() && !isFree()); - return _ws->_data[_index].member; - } +WorkingSetMember* WorkingSet::iterator::operator->() { + dassert(_index < _ws->_data.size() && !isFree()); + return _ws->_data[_index].member; +} - WorkingSet::iterator WorkingSet::begin() { - return WorkingSet::iterator(this, 0); - } +WorkingSet::iterator WorkingSet::begin() { + return WorkingSet::iterator(this, 0); +} - WorkingSet::iterator WorkingSet::end() { - return WorkingSet::iterator(this, _data.size()); - } +WorkingSet::iterator WorkingSet::end() { + return WorkingSet::iterator(this, _data.size()); +} - // - // WorkingSetMember - // +// +// WorkingSetMember +// - WorkingSetMember::WorkingSetMember() : state(WorkingSetMember::INVALID), isSuspicious(false) { } +WorkingSetMember::WorkingSetMember() : state(WorkingSetMember::INVALID), isSuspicious(false) {} - WorkingSetMember::~WorkingSetMember() { } +WorkingSetMember::~WorkingSetMember() {} - void WorkingSetMember::clear() { - for (size_t i = 0; i < WSM_COMPUTED_NUM_TYPES; i++) { - _computed[i].reset(); - } - - keyData.clear(); - obj.reset(); - state = WorkingSetMember::INVALID; - } - - bool WorkingSetMember::hasLoc() const { - return state == LOC_AND_IDX || state == LOC_AND_UNOWNED_OBJ || state == LOC_AND_OWNED_OBJ; +void WorkingSetMember::clear() { + for (size_t i = 0; i < WSM_COMPUTED_NUM_TYPES; i++) { + _computed[i].reset(); } - bool WorkingSetMember::hasObj() const { - return hasOwnedObj() || hasUnownedObj(); + keyData.clear(); + obj.reset(); + state = WorkingSetMember::INVALID; +} + +bool WorkingSetMember::hasLoc() const { + return state == LOC_AND_IDX || state == LOC_AND_UNOWNED_OBJ || state == LOC_AND_OWNED_OBJ; +} + +bool WorkingSetMember::hasObj() const { + return hasOwnedObj() || hasUnownedObj(); +} + +bool WorkingSetMember::hasOwnedObj() const { + return state == OWNED_OBJ || state == LOC_AND_OWNED_OBJ; +} + +bool WorkingSetMember::hasUnownedObj() const { + return state == LOC_AND_UNOWNED_OBJ; +} + +bool WorkingSetMember::hasComputed(const WorkingSetComputedDataType type) const { + return _computed[type].get(); +} + +const WorkingSetComputedData* WorkingSetMember::getComputed( + const WorkingSetComputedDataType type) const { + verify(_computed[type]); + return _computed[type].get(); +} + +void WorkingSetMember::addComputed(WorkingSetComputedData* data) { + verify(!hasComputed(data->type())); + _computed[data->type()].reset(data); +} + +void WorkingSetMember::setFetcher(RecordFetcher* fetcher) { + _fetcher.reset(fetcher); +} + +RecordFetcher* WorkingSetMember::releaseFetcher() { + return _fetcher.release(); +} + +bool WorkingSetMember::hasFetcher() const { + return NULL != _fetcher.get(); +} + +bool WorkingSetMember::getFieldDotted(const string& field, BSONElement* out) const { + // If our state is such that we have an object, use it. + if (hasObj()) { + *out = obj.value().getFieldDotted(field); + return true; } - bool WorkingSetMember::hasOwnedObj() const { - return state == OWNED_OBJ || state == LOC_AND_OWNED_OBJ; - } + // Our state should be such that we have index data/are covered. + for (size_t i = 0; i < keyData.size(); ++i) { + BSONObjIterator keyPatternIt(keyData[i].indexKeyPattern); + BSONObjIterator keyDataIt(keyData[i].keyData); - bool WorkingSetMember::hasUnownedObj() const { - return state == LOC_AND_UNOWNED_OBJ; - } - - bool WorkingSetMember::hasComputed(const WorkingSetComputedDataType type) const { - return _computed[type].get(); - } + while (keyPatternIt.more()) { + BSONElement keyPatternElt = keyPatternIt.next(); + verify(keyDataIt.more()); + BSONElement keyDataElt = keyDataIt.next(); - const WorkingSetComputedData* WorkingSetMember::getComputed(const WorkingSetComputedDataType type) const { - verify(_computed[type]); - return _computed[type].get(); + if (field == keyPatternElt.fieldName()) { + *out = keyDataElt; + return true; + } + } } - void WorkingSetMember::addComputed(WorkingSetComputedData* data) { - verify(!hasComputed(data->type())); - _computed[data->type()].reset(data); - } + return false; +} - void WorkingSetMember::setFetcher(RecordFetcher* fetcher) { - _fetcher.reset(fetcher); - } +size_t WorkingSetMember::getMemUsage() const { + size_t memUsage = 0; - RecordFetcher* WorkingSetMember::releaseFetcher() { - return _fetcher.release(); + if (hasLoc()) { + memUsage += sizeof(RecordId); } - bool WorkingSetMember::hasFetcher() const { - return NULL != _fetcher.get(); + // XXX: Unowned objects count towards current size. + // See SERVER-12579 + if (hasObj()) { + memUsage += obj.value().objsize(); } - bool WorkingSetMember::getFieldDotted(const string& field, BSONElement* out) const { - // If our state is such that we have an object, use it. - if (hasObj()) { - *out = obj.value().getFieldDotted(field); - return true; - } - - // Our state should be such that we have index data/are covered. - for (size_t i = 0; i < keyData.size(); ++i) { - BSONObjIterator keyPatternIt(keyData[i].indexKeyPattern); - BSONObjIterator keyDataIt(keyData[i].keyData); - - while (keyPatternIt.more()) { - BSONElement keyPatternElt = keyPatternIt.next(); - verify(keyDataIt.more()); - BSONElement keyDataElt = keyDataIt.next(); - - if (field == keyPatternElt.fieldName()) { - *out = keyDataElt; - return true; - } - } - } - - return false; + for (size_t i = 0; i < keyData.size(); ++i) { + const IndexKeyDatum& keyDatum = keyData[i]; + memUsage += keyDatum.keyData.objsize(); } - size_t WorkingSetMember::getMemUsage() const { - size_t memUsage = 0; - - if (hasLoc()) { - memUsage += sizeof(RecordId); - } - - // XXX: Unowned objects count towards current size. - // See SERVER-12579 - if (hasObj()) { - memUsage += obj.value().objsize(); - } - - for (size_t i = 0; i < keyData.size(); ++i) { - const IndexKeyDatum& keyDatum = keyData[i]; - memUsage += keyDatum.keyData.objsize(); - } - - return memUsage; - } + return memUsage; +} } // namespace mongo |