summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/working_set.cpp
diff options
context:
space:
mode:
authorApollon Oikonomopoulos <apoikos@debian.org>2016-01-14 00:10:06 +0200
committerApollon Oikonomopoulos <apollon@skroutz.gr>2016-01-14 00:10:06 +0200
commit374e1947abcd3e127a2a613aff73ecffdb9199ea (patch)
treed83973c3c9802450acd5b5e86fe0d4e8e60a3a1b /src/mongo/db/exec/working_set.cpp
parent65585c90b12d6523bea75a2aebaae2a2fdf9e641 (diff)
Imported Upstream version 2.6.11upstream/2.6.11
Diffstat (limited to 'src/mongo/db/exec/working_set.cpp')
-rw-r--r--src/mongo/db/exec/working_set.cpp183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/mongo/db/exec/working_set.cpp b/src/mongo/db/exec/working_set.cpp
new file mode 100644
index 00000000000..ec9eaca2453
--- /dev/null
+++ b/src/mongo/db/exec/working_set.cpp
@@ -0,0 +1,183 @@
+/**
+ * Copyright (C) 2013 10gen Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/db/exec/working_set.h"
+
+#include "mongo/db/index/index_descriptor.h"
+
+namespace mongo {
+
+ WorkingSet::MemberHolder::MemberHolder() : member(NULL) { }
+ WorkingSet::MemberHolder::~MemberHolder() {}
+
+ WorkingSet::WorkingSet() : _freeList(INVALID_ID) { }
+
+ 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
+ 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);
+ }
+
+ WorkingSetMember::WorkingSetMember() : state(WorkingSetMember::INVALID) { }
+
+ WorkingSetMember::~WorkingSetMember() { }
+
+ void WorkingSetMember::clear() {
+ for (size_t i = 0; i < WSM_COMPUTED_NUM_TYPES; i++) {
+ _computed[i].reset();
+ }
+
+ keyData.clear();
+ obj = BSONObj();
+ state = WorkingSetMember::INVALID;
+ }
+
+ bool WorkingSetMember::hasLoc() const {
+ return state == LOC_AND_IDX || state == LOC_AND_UNOWNED_OBJ;
+ }
+
+ bool WorkingSetMember::hasObj() const {
+ return hasOwnedObj() || hasUnownedObj();
+ }
+
+ bool WorkingSetMember::hasOwnedObj() const {
+ return state == OWNED_OBJ;
+ }
+
+ bool WorkingSetMember::hasUnownedObj() const {
+ return state == LOC_AND_UNOWNED_OBJ;
+ }
+
+ bool WorkingSetMember::hasComputed(const WorkingSetComputedDataType type) const {
+ return _computed[type];
+ }
+
+ 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);
+ }
+
+ 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.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;
+ }
+
+ size_t WorkingSetMember::getMemUsage() const {
+ size_t memUsage = 0;
+
+ if (hasLoc()) {
+ memUsage += sizeof(DiskLoc);
+ }
+
+ // XXX: Unowned objects count towards current size.
+ // See SERVER-12579
+ if (hasObj()) {
+ memUsage += obj.objsize();
+ }
+
+ for (size_t i = 0; i < keyData.size(); ++i) {
+ const IndexKeyDatum& keyDatum = keyData[i];
+ memUsage += keyDatum.keyData.objsize();
+ }
+
+ return memUsage;
+ }
+
+} // namespace mongo