diff options
-rw-r--r-- | src/mongo/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_catalog.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/index/2d_access_method.h | 2 | ||||
-rw-r--r-- | src/mongo/db/index/btree_access_method.cpp | 235 | ||||
-rw-r--r-- | src/mongo/db/index/btree_access_method.h | 2 | ||||
-rw-r--r-- | src/mongo/db/index/btree_based_access_method.cpp | 278 | ||||
-rw-r--r-- | src/mongo/db/index/btree_based_access_method.h (renamed from src/mongo/db/index/btree_access_method_internal.h) | 0 | ||||
-rw-r--r-- | src/mongo/db/index/fts_access_method.h | 2 | ||||
-rw-r--r-- | src/mongo/db/index/hash_access_method.h | 2 | ||||
-rw-r--r-- | src/mongo/db/index/haystack_access_method.h | 2 | ||||
-rw-r--r-- | src/mongo/db/index/s2_access_method.h | 2 |
11 files changed, 286 insertions, 242 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 8c49a22b21e..7e2731a591f 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -567,6 +567,7 @@ serverOnlyFiles = [ "db/curop.cpp", "db/index_legacy.cpp", "db/index/2d_access_method.cpp", "db/index/btree_access_method.cpp", + "db/index/btree_based_access_method.cpp", "db/index/btree_based_builder.cpp", "db/index/btree_index_cursor.cpp", "db/index/btree_interface.cpp", diff --git a/src/mongo/db/catalog/index_catalog.cpp b/src/mongo/db/catalog/index_catalog.cpp index 943cee3cc9b..6e75820d287 100644 --- a/src/mongo/db/catalog/index_catalog.cpp +++ b/src/mongo/db/catalog/index_catalog.cpp @@ -41,7 +41,7 @@ #include "mongo/db/index_legacy.h" #include "mongo/db/index/2d_access_method.h" #include "mongo/db/index/btree_access_method.h" -#include "mongo/db/index/btree_access_method_internal.h" +#include "mongo/db/index/btree_based_access_method.h" #include "mongo/db/index/fts_access_method.h" #include "mongo/db/index/hash_access_method.h" #include "mongo/db/index/haystack_access_method.h" diff --git a/src/mongo/db/index/2d_access_method.h b/src/mongo/db/index/2d_access_method.h index 782162da8b0..9b0a5f60f01 100644 --- a/src/mongo/db/index/2d_access_method.h +++ b/src/mongo/db/index/2d_access_method.h @@ -30,7 +30,7 @@ #include "mongo/base/status.h" #include "mongo/db/index/2d_common.h" -#include "mongo/db/index/btree_access_method_internal.h" +#include "mongo/db/index/btree_based_access_method.h" #include "mongo/db/jsobj.h" namespace mongo { diff --git a/src/mongo/db/index/btree_access_method.cpp b/src/mongo/db/index/btree_access_method.cpp index d73ae59e321..24c7ac12810 100644 --- a/src/mongo/db/index/btree_access_method.cpp +++ b/src/mongo/db/index/btree_access_method.cpp @@ -40,241 +40,6 @@ namespace mongo { - BtreeBasedAccessMethod::BtreeBasedAccessMethod(IndexCatalogEntry* btreeState) - : _btreeState(btreeState), _descriptor(btreeState->descriptor()) { - - verify(0 == _descriptor->version() || 1 == _descriptor->version()); - _interface = BtreeInterface::interfaces[_descriptor->version()]; - } - - // Find the keys for obj, put them in the tree pointing to loc - Status BtreeBasedAccessMethod::insert(const BSONObj& obj, const DiskLoc& loc, - const InsertDeleteOptions& options, int64_t* numInserted) { - - *numInserted = 0; - - BSONObjSet keys; - // Delegate to the subclass. - getKeys(obj, &keys); - - Status ret = Status::OK(); - - for (BSONObjSet::const_iterator i = keys.begin(); i != keys.end(); ++i) { - try { - _interface->bt_insert(_btreeState, - _btreeState->head(), - loc, - *i, - options.dupsAllowed, - true); - ++*numInserted; - } catch (AssertionException& e) { - if (10287 == e.getCode() && !_btreeState->isReady()) { - // This is the duplicate key exception. We ignore it for some reason in BG - // indexing. - DEV log() << "info: key already in index during bg indexing (ok)\n"; - } else if (!options.dupsAllowed) { - // Assuming it's a duplicate key exception. Clean up any inserted keys. - for (BSONObjSet::const_iterator j = keys.begin(); j != i; ++j) { - removeOneKey(*j, loc); - } - *numInserted = 0; - return Status(ErrorCodes::DuplicateKey, e.what(), e.getCode()); - } else { - problem() << " caught assertion addKeysToIndex " - << _descriptor->indexNamespace() - << obj["_id"] << endl; - ret = Status(ErrorCodes::InternalError, e.what(), e.getCode()); - } - } - } - - if (*numInserted > 1) { - _btreeState->setMultikey(); - } - - return ret; - } - - bool BtreeBasedAccessMethod::removeOneKey(const BSONObj& key, const DiskLoc& loc) { - bool ret = false; - - try { - ret = _interface->unindex(_btreeState, - _btreeState->head(), - key, - loc); - } catch (AssertionException& e) { - problem() << "Assertion failure: _unindex failed " - << _descriptor->indexNamespace() << endl; - out() << "Assertion failure: _unindex failed: " << e.what() << '\n'; - out() << " obj:" << loc.obj().toString() << '\n'; - out() << " key:" << key.toString() << '\n'; - out() << " dl:" << loc.toString() << endl; - logContext(); - } - - return ret; - } - - // Remove the provided doc from the index. - Status BtreeBasedAccessMethod::remove(const BSONObj &obj, const DiskLoc& loc, - const InsertDeleteOptions &options, int64_t* numDeleted) { - - BSONObjSet keys; - getKeys(obj, &keys); - *numDeleted = 0; - - for (BSONObjSet::const_iterator i = keys.begin(); i != keys.end(); ++i) { - bool thisKeyOK = removeOneKey(*i, loc); - - if (thisKeyOK) { - ++*numDeleted; - } else if (options.logIfError) { - log() << "unindex failed (key too big?) " << _descriptor->indexNamespace() - << " key: " << *i << " " << loc.obj()["_id"] << endl; - } - } - - return Status::OK(); - } - - // Return keys in l that are not in r. - // Lifted basically verbatim from elsewhere. - static void setDifference(const BSONObjSet &l, const BSONObjSet &r, vector<BSONObj*> *diff) { - // l and r must use the same ordering spec. - verify(l.key_comp().order() == r.key_comp().order()); - BSONObjSet::const_iterator i = l.begin(); - BSONObjSet::const_iterator j = r.begin(); - while ( 1 ) { - if ( i == l.end() ) - break; - while ( j != r.end() && j->woCompare( *i ) < 0 ) - j++; - if ( j == r.end() || i->woCompare(*j) != 0 ) { - const BSONObj *jo = &*i; - diff->push_back( (BSONObj *) jo ); - } - i++; - } - } - - Status BtreeBasedAccessMethod::touch(const BSONObj& obj) { - BSONObjSet keys; - getKeys(obj, &keys); - - for (BSONObjSet::const_iterator i = keys.begin(); i != keys.end(); ++i) { - int unusedPos; - bool unusedFound; - DiskLoc unusedDiskLoc; - _interface->locate(_btreeState, - _btreeState->head(), - *i, - unusedPos, - unusedFound, - unusedDiskLoc, - 1); - } - - return Status::OK(); - } - - DiskLoc BtreeBasedAccessMethod::findSingle( const BSONObj& key ) { - DiskLoc head = _btreeState->head(); - Record* record = _btreeState->recordStore()->recordFor( head ); - - if ( 0 == _descriptor->version() ) { - return BtreeBucket<V0>::asVersion( record )->findSingle( _btreeState, - _btreeState->head(), - key ); - } - if ( 1 == _descriptor->version() ) { - return BtreeBucket<V1>::asVersion( record )->findSingle( _btreeState, - _btreeState->head(), - key ); - } - verify( 0 ); - } - - - Status BtreeBasedAccessMethod::validate(int64_t* numKeys) { - *numKeys = _interface->fullValidate(_btreeState, - _btreeState->head(), - _descriptor->keyPattern()); - return Status::OK(); - } - - Status BtreeBasedAccessMethod::validateUpdate( - const BSONObj &from, const BSONObj &to, const DiskLoc &record, - const InsertDeleteOptions &options, UpdateTicket* status) { - - BtreeBasedPrivateUpdateData *data = new BtreeBasedPrivateUpdateData(); - status->_indexSpecificUpdateData.reset(data); - - getKeys(from, &data->oldKeys); - getKeys(to, &data->newKeys); - data->loc = record; - data->dupsAllowed = options.dupsAllowed; - - setDifference(data->oldKeys, data->newKeys, &data->removed); - setDifference(data->newKeys, data->oldKeys, &data->added); - - bool checkForDups = !data->added.empty() - && (KeyPattern::isIdKeyPattern(_descriptor->keyPattern()) || _descriptor->unique()) - && !options.dupsAllowed; - - if (checkForDups) { - for (vector<BSONObj*>::iterator i = data->added.begin(); i != data->added.end(); i++) { - if (_interface->wouldCreateDup(_btreeState, - _btreeState->head(), - **i, record)) { - status->_isValid = false; - return Status(ErrorCodes::DuplicateKey, - _interface->dupKeyError(_btreeState, - _btreeState->head(), - **i)); - } - } - } - - status->_isValid = true; - - return Status::OK(); - } - - Status BtreeBasedAccessMethod::update(const UpdateTicket& ticket, int64_t* numUpdated) { - if (!ticket._isValid) { - return Status(ErrorCodes::InternalError, "Invalid updateticket in update"); - } - - BtreeBasedPrivateUpdateData* data = - static_cast<BtreeBasedPrivateUpdateData*>(ticket._indexSpecificUpdateData.get()); - - if (data->oldKeys.size() + data->added.size() - data->removed.size() > 1) { - _btreeState->setMultikey(); - } - - for (size_t i = 0; i < data->added.size(); ++i) { - _interface->bt_insert(_btreeState, - _btreeState->head(), - data->loc, - *data->added[i], - data->dupsAllowed, - true); - } - - for (size_t i = 0; i < data->removed.size(); ++i) { - _interface->unindex(_btreeState, - _btreeState->head(), - *data->removed[i], - data->loc); - } - - *numUpdated = data->added.size(); - - return Status::OK(); - } - // Standard Btree implementation below. BtreeAccessMethod::BtreeAccessMethod(IndexCatalogEntry* btreeState) : BtreeBasedAccessMethod(btreeState) { diff --git a/src/mongo/db/index/btree_access_method.h b/src/mongo/db/index/btree_access_method.h index d6c80a7f215..0c3914d97b5 100644 --- a/src/mongo/db/index/btree_access_method.h +++ b/src/mongo/db/index/btree_access_method.h @@ -34,7 +34,7 @@ #include "mongo/db/structure/btree/btree.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/index/btree_key_generator.h" -#include "mongo/db/index/btree_access_method_internal.h" +#include "mongo/db/index/btree_based_access_method.h" #include "mongo/db/jsobj.h" namespace mongo { diff --git a/src/mongo/db/index/btree_based_access_method.cpp b/src/mongo/db/index/btree_based_access_method.cpp new file mode 100644 index 00000000000..8af96bbadbf --- /dev/null +++ b/src/mongo/db/index/btree_based_access_method.cpp @@ -0,0 +1,278 @@ +/** +* 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/index/btree_access_method.h" + +#include <vector> + +#include "mongo/base/status.h" +#include "mongo/db/index/btree_index_cursor.h" +#include "mongo/db/index/btree_interface.h" +#include "mongo/db/jsobj.h" +#include "mongo/db/keypattern.h" +#include "mongo/db/pdfile.h" +#include "mongo/db/pdfile_private.h" + +namespace mongo { + + BtreeBasedAccessMethod::BtreeBasedAccessMethod(IndexCatalogEntry* btreeState) + : _btreeState(btreeState), _descriptor(btreeState->descriptor()) { + + verify(0 == _descriptor->version() || 1 == _descriptor->version()); + _interface = BtreeInterface::interfaces[_descriptor->version()]; + } + + // Find the keys for obj, put them in the tree pointing to loc + Status BtreeBasedAccessMethod::insert(const BSONObj& obj, const DiskLoc& loc, + const InsertDeleteOptions& options, int64_t* numInserted) { + + *numInserted = 0; + + BSONObjSet keys; + // Delegate to the subclass. + getKeys(obj, &keys); + + Status ret = Status::OK(); + + for (BSONObjSet::const_iterator i = keys.begin(); i != keys.end(); ++i) { + try { + _interface->bt_insert(_btreeState, + _btreeState->head(), + loc, + *i, + options.dupsAllowed, + true); + ++*numInserted; + } catch (AssertionException& e) { + if (10287 == e.getCode() && !_btreeState->isReady()) { + // This is the duplicate key exception. We ignore it for some reason in BG + // indexing. + DEV log() << "info: key already in index during bg indexing (ok)\n"; + } else if (!options.dupsAllowed) { + // Assuming it's a duplicate key exception. Clean up any inserted keys. + for (BSONObjSet::const_iterator j = keys.begin(); j != i; ++j) { + removeOneKey(*j, loc); + } + *numInserted = 0; + return Status(ErrorCodes::DuplicateKey, e.what(), e.getCode()); + } else { + problem() << " caught assertion addKeysToIndex " + << _descriptor->indexNamespace() + << obj["_id"] << endl; + ret = Status(ErrorCodes::InternalError, e.what(), e.getCode()); + } + } + } + + if (*numInserted > 1) { + _btreeState->setMultikey(); + } + + return ret; + } + + bool BtreeBasedAccessMethod::removeOneKey(const BSONObj& key, const DiskLoc& loc) { + bool ret = false; + + try { + ret = _interface->unindex(_btreeState, + _btreeState->head(), + key, + loc); + } catch (AssertionException& e) { + problem() << "Assertion failure: _unindex failed " + << _descriptor->indexNamespace() << endl; + out() << "Assertion failure: _unindex failed: " << e.what() << '\n'; + out() << " obj:" << loc.obj().toString() << '\n'; + out() << " key:" << key.toString() << '\n'; + out() << " dl:" << loc.toString() << endl; + logContext(); + } + + return ret; + } + + // Remove the provided doc from the index. + Status BtreeBasedAccessMethod::remove(const BSONObj &obj, const DiskLoc& loc, + const InsertDeleteOptions &options, int64_t* numDeleted) { + + BSONObjSet keys; + getKeys(obj, &keys); + *numDeleted = 0; + + for (BSONObjSet::const_iterator i = keys.begin(); i != keys.end(); ++i) { + bool thisKeyOK = removeOneKey(*i, loc); + + if (thisKeyOK) { + ++*numDeleted; + } else if (options.logIfError) { + log() << "unindex failed (key too big?) " << _descriptor->indexNamespace() + << " key: " << *i << " " << loc.obj()["_id"] << endl; + } + } + + return Status::OK(); + } + + // Return keys in l that are not in r. + // Lifted basically verbatim from elsewhere. + static void setDifference(const BSONObjSet &l, const BSONObjSet &r, vector<BSONObj*> *diff) { + // l and r must use the same ordering spec. + verify(l.key_comp().order() == r.key_comp().order()); + BSONObjSet::const_iterator i = l.begin(); + BSONObjSet::const_iterator j = r.begin(); + while ( 1 ) { + if ( i == l.end() ) + break; + while ( j != r.end() && j->woCompare( *i ) < 0 ) + j++; + if ( j == r.end() || i->woCompare(*j) != 0 ) { + const BSONObj *jo = &*i; + diff->push_back( (BSONObj *) jo ); + } + i++; + } + } + + Status BtreeBasedAccessMethod::touch(const BSONObj& obj) { + BSONObjSet keys; + getKeys(obj, &keys); + + for (BSONObjSet::const_iterator i = keys.begin(); i != keys.end(); ++i) { + int unusedPos; + bool unusedFound; + DiskLoc unusedDiskLoc; + _interface->locate(_btreeState, + _btreeState->head(), + *i, + unusedPos, + unusedFound, + unusedDiskLoc, + 1); + } + + return Status::OK(); + } + + DiskLoc BtreeBasedAccessMethod::findSingle( const BSONObj& key ) { + DiskLoc head = _btreeState->head(); + Record* record = _btreeState->recordStore()->recordFor( head ); + + if ( 0 == _descriptor->version() ) { + return BtreeBucket<V0>::asVersion( record )->findSingle( _btreeState, + _btreeState->head(), + key ); + } + if ( 1 == _descriptor->version() ) { + return BtreeBucket<V1>::asVersion( record )->findSingle( _btreeState, + _btreeState->head(), + key ); + } + verify( 0 ); + } + + + Status BtreeBasedAccessMethod::validate(int64_t* numKeys) { + *numKeys = _interface->fullValidate(_btreeState, + _btreeState->head(), + _descriptor->keyPattern()); + return Status::OK(); + } + + Status BtreeBasedAccessMethod::validateUpdate( + const BSONObj &from, const BSONObj &to, const DiskLoc &record, + const InsertDeleteOptions &options, UpdateTicket* status) { + + BtreeBasedPrivateUpdateData *data = new BtreeBasedPrivateUpdateData(); + status->_indexSpecificUpdateData.reset(data); + + getKeys(from, &data->oldKeys); + getKeys(to, &data->newKeys); + data->loc = record; + data->dupsAllowed = options.dupsAllowed; + + setDifference(data->oldKeys, data->newKeys, &data->removed); + setDifference(data->newKeys, data->oldKeys, &data->added); + + bool checkForDups = !data->added.empty() + && (KeyPattern::isIdKeyPattern(_descriptor->keyPattern()) || _descriptor->unique()) + && !options.dupsAllowed; + + if (checkForDups) { + for (vector<BSONObj*>::iterator i = data->added.begin(); i != data->added.end(); i++) { + if (_interface->wouldCreateDup(_btreeState, + _btreeState->head(), + **i, record)) { + status->_isValid = false; + return Status(ErrorCodes::DuplicateKey, + _interface->dupKeyError(_btreeState, + _btreeState->head(), + **i)); + } + } + } + + status->_isValid = true; + + return Status::OK(); + } + + Status BtreeBasedAccessMethod::update(const UpdateTicket& ticket, int64_t* numUpdated) { + if (!ticket._isValid) { + return Status(ErrorCodes::InternalError, "Invalid updateticket in update"); + } + + BtreeBasedPrivateUpdateData* data = + static_cast<BtreeBasedPrivateUpdateData*>(ticket._indexSpecificUpdateData.get()); + + if (data->oldKeys.size() + data->added.size() - data->removed.size() > 1) { + _btreeState->setMultikey(); + } + + for (size_t i = 0; i < data->added.size(); ++i) { + _interface->bt_insert(_btreeState, + _btreeState->head(), + data->loc, + *data->added[i], + data->dupsAllowed, + true); + } + + for (size_t i = 0; i < data->removed.size(); ++i) { + _interface->unindex(_btreeState, + _btreeState->head(), + *data->removed[i], + data->loc); + } + + *numUpdated = data->added.size(); + + return Status::OK(); + } + +} // namespace mongo diff --git a/src/mongo/db/index/btree_access_method_internal.h b/src/mongo/db/index/btree_based_access_method.h index 320c1de8944..320c1de8944 100644 --- a/src/mongo/db/index/btree_access_method_internal.h +++ b/src/mongo/db/index/btree_based_access_method.h diff --git a/src/mongo/db/index/fts_access_method.h b/src/mongo/db/index/fts_access_method.h index eceff2ae3b9..47dc8a98405 100644 --- a/src/mongo/db/index/fts_access_method.h +++ b/src/mongo/db/index/fts_access_method.h @@ -30,7 +30,7 @@ #include "mongo/base/status.h" #include "mongo/db/fts/fts_spec.h" -#include "mongo/db/index/btree_access_method_internal.h" +#include "mongo/db/index/btree_based_access_method.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/jsobj.h" diff --git a/src/mongo/db/index/hash_access_method.h b/src/mongo/db/index/hash_access_method.h index 3fdff0e2b7d..cb49b9e0b8b 100644 --- a/src/mongo/db/index/hash_access_method.h +++ b/src/mongo/db/index/hash_access_method.h @@ -33,7 +33,7 @@ #include "mongo/base/status.h" #include "mongo/db/hasher.h" // For HashSeed. #include "mongo/db/index/index_descriptor.h" -#include "mongo/db/index/btree_access_method_internal.h" +#include "mongo/db/index/btree_based_access_method.h" #include "mongo/db/jsobj.h" namespace mongo { diff --git a/src/mongo/db/index/haystack_access_method.h b/src/mongo/db/index/haystack_access_method.h index e24e10f7df9..1b07dce048e 100644 --- a/src/mongo/db/index/haystack_access_method.h +++ b/src/mongo/db/index/haystack_access_method.h @@ -29,7 +29,7 @@ #pragma once #include "mongo/base/status.h" -#include "mongo/db/index/btree_access_method_internal.h" +#include "mongo/db/index/btree_based_access_method.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/jsobj.h" diff --git a/src/mongo/db/index/s2_access_method.h b/src/mongo/db/index/s2_access_method.h index 66c091f3e90..33e7cf1647b 100644 --- a/src/mongo/db/index/s2_access_method.h +++ b/src/mongo/db/index/s2_access_method.h @@ -30,7 +30,7 @@ #include "mongo/base/status.h" #include "mongo/db/geo/s2common.h" -#include "mongo/db/index/btree_access_method_internal.h" +#include "mongo/db/index/btree_based_access_method.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/jsobj.h" |