diff options
author | Eliot Horowitz <eliot@10gen.com> | 2013-12-24 18:44:18 -0500 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2013-12-30 00:41:27 -0500 |
commit | 7de1f17148231074cdf74177dcbf8e8fc534949b (patch) | |
tree | 886e7008704a2152fa47354e513ba9cb4cf0969a /src/mongo/db | |
parent | 29e691a91c72b28ef50faddc7ef6f24523788aee (diff) | |
download | mongo-7de1f17148231074cdf74177dcbf8e8fc534949b.tar.gz |
SERVER-12213: bulk of index refactor, making catalog/record store come via catalog - js tests work
Diffstat (limited to 'src/mongo/db')
65 files changed, 950 insertions, 633 deletions
diff --git a/src/mongo/db/cap.cpp b/src/mongo/db/cap.cpp index 559f83feb9b..9b8866b9e86 100644 --- a/src/mongo/db/cap.cpp +++ b/src/mongo/db/cap.cpp @@ -36,6 +36,7 @@ #include "mongo/db/clientcursor.h" #include "mongo/db/db.h" +#include "mongo/db/dbhelpers.h" #include "mongo/db/json.h" #include "mongo/db/pdfile.h" #include "mongo/db/structure/collection.h" diff --git a/src/mongo/db/catalog/index_catalog.cpp b/src/mongo/db/catalog/index_catalog.cpp index 9cef731e750..7dff462fd07 100644 --- a/src/mongo/db/catalog/index_catalog.cpp +++ b/src/mongo/db/catalog/index_catalog.cpp @@ -36,6 +36,7 @@ #include "mongo/db/background.h" #include "mongo/db/catalog/index_create.h" #include "mongo/db/clientcursor.h" +#include "mongo/db/curop.h" #include "mongo/db/field_ref.h" #include "mongo/db/index_legacy.h" #include "mongo/db/index/2d_access_method.h" @@ -239,7 +240,8 @@ namespace mongo { scoped_ptr<IndexDescriptor> desc( new IndexDescriptor( _collection, idxNo, id, id->info.obj().getOwned() ) ); - buildAnIndex( _collection, desc.get(), mayInterrupt ); + auto_ptr<BtreeInMemoryState> btreeState( createInMemory( desc.get() ) ); + buildAnIndex( _collection, btreeState.get(), mayInterrupt ); indexBuildBlock.success(); // in case we got any access methods or something like that @@ -774,7 +776,7 @@ namespace mongo { return Status::OK(); } - void IndexCatalog::markMultikey( IndexDescriptor* idx, bool isMultikey ) { + void IndexCatalog::markMultikey( const IndexDescriptor* idx, bool isMultikey ) { if ( _details->setIndexIsMultikey( idx->_indexNumber, isMultikey ) ) _collection->infoCache()->clearQueryCache(); } @@ -851,7 +853,7 @@ namespace mongo { return _descriptorCache[idxNo]; } - IndexAccessMethod* IndexCatalog::getBtreeIndex( IndexDescriptor* desc ) { + IndexAccessMethod* IndexCatalog::getBtreeIndex( const IndexDescriptor* desc ) { _checkMagic(); int idxNo = desc->getIndexNumber(); @@ -859,12 +861,12 @@ namespace mongo { return _forcedBtreeAccessMethodCache[idxNo]; } - BtreeAccessMethod* newlyCreated = new BtreeAccessMethod( desc ); + BtreeAccessMethod* newlyCreated = new BtreeAccessMethod( createInMemory( desc ) ); _forcedBtreeAccessMethodCache[idxNo] = newlyCreated; return newlyCreated; } - BtreeBasedAccessMethod* IndexCatalog::getBtreeBasedIndex( IndexDescriptor* desc ) { + BtreeBasedAccessMethod* IndexCatalog::getBtreeBasedIndex( const IndexDescriptor* desc ) { string type = _getAccessMethodName(desc->keyPattern()); @@ -884,7 +886,7 @@ namespace mongo { } - IndexAccessMethod* IndexCatalog::getIndex( IndexDescriptor* desc ) { + IndexAccessMethod* IndexCatalog::getIndex( const IndexDescriptor* desc ) { _checkMagic(); int idxNo = desc->getIndexNumber(); @@ -892,27 +894,29 @@ namespace mongo { return _accessMethodCache[idxNo]; } + auto_ptr<BtreeInMemoryState> state( createInMemory( desc ) ); + IndexAccessMethod* newlyCreated = 0; string type = _getAccessMethodName(desc->keyPattern()); if (IndexNames::HASHED == type) { - newlyCreated = new HashAccessMethod(desc); + newlyCreated = new HashAccessMethod( state.release() ); } else if (IndexNames::GEO_2DSPHERE == type) { - newlyCreated = new S2AccessMethod(desc); + newlyCreated = new S2AccessMethod( state.release() ); } else if (IndexNames::TEXT == type) { - newlyCreated = new FTSAccessMethod(desc); + newlyCreated = new FTSAccessMethod( state.release() ); } else if (IndexNames::GEO_HAYSTACK == type) { - newlyCreated = new HaystackAccessMethod(desc); + newlyCreated = new HaystackAccessMethod( state.release() ); } else if ("" == type) { - newlyCreated = new BtreeAccessMethod(desc); + newlyCreated = new BtreeAccessMethod( state.release() ); } else if (IndexNames::GEO_2D == type) { - newlyCreated = new TwoDAccessMethod(desc); + newlyCreated = new TwoDAccessMethod( state.release() ); } else { log() << "Can't find index for keypattern " << desc->keyPattern(); @@ -925,6 +929,29 @@ namespace mongo { return newlyCreated; } + BtreeInMemoryState* IndexCatalog::createInMemory( const IndexDescriptor* descriptor ) { + int idxNo = _details->findIndexByName( descriptor->indexName(), true ); + verify( idxNo >= 0 ); + + Database* db = _collection->_database; + NamespaceDetails* nsd = db->namespaceIndex().details( descriptor->indexNamespace() ); + if ( !nsd ) { + // have to create! + db->namespaceIndex().add_ns( descriptor->indexNamespace(), DiskLoc(), false ); + nsd = db->namespaceIndex().details( descriptor->indexNamespace() ); + db->_addNamespaceToCatalog( descriptor->indexNamespace(), NULL ); + verify(nsd); + } + + RecordStore* rs = new RecordStore( descriptor->indexNamespace() ); + rs->init( nsd, _collection->getExtentManager(), false ); + + return new BtreeInMemoryState( _collection, + descriptor, + rs, + &_details->idx( idxNo ) ); + } + // --------------------------- Status IndexCatalog::_indexRecord( int idxNo, const BSONObj& obj, const DiskLoc &loc ) { @@ -936,7 +963,7 @@ namespace mongo { InsertDeleteOptions options; options.logIfError = false; options.dupsAllowed = - ignoreUniqueIndex( desc->getOnDisk() ) || + ignoreUniqueIndex( desc ) || ( !KeyPattern::isIdKeyPattern(desc->keyPattern()) && !desc->unique() ); int64_t inserted; diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h index 7bb27412fa8..6398fdc87dc 100644 --- a/src/mongo/db/catalog/index_catalog.h +++ b/src/mongo/db/catalog/index_catalog.h @@ -40,6 +40,7 @@ namespace mongo { class Collection; class NamespaceDetails; + class BtreeInMemoryState; class IndexDescriptor; class IndexDetails; class IndexAccessMethod; @@ -95,11 +96,11 @@ namespace mongo { IndexDescriptor* getDescriptor( int idxNo ); // never returns NULL - IndexAccessMethod* getIndex( IndexDescriptor* desc ); + IndexAccessMethod* getIndex( const IndexDescriptor* desc ); - BtreeBasedAccessMethod* getBtreeBasedIndex( IndexDescriptor* desc ); + BtreeBasedAccessMethod* getBtreeBasedIndex( const IndexDescriptor* desc ); - IndexAccessMethod* getBtreeIndex( IndexDescriptor* desc ); + IndexAccessMethod* getBtreeIndex( const IndexDescriptor* desc ); class IndexIterator { public: @@ -149,7 +150,7 @@ namespace mongo { */ BSONObj prepOneUnfinishedIndex(); - void markMultikey( IndexDescriptor* idx, bool isMultikey = true ); + void markMultikey( const IndexDescriptor* idx, bool isMultikey = true ); // --- these probably become private? @@ -202,6 +203,8 @@ namespace mongo { private: + BtreeInMemoryState* createInMemory( const IndexDescriptor* descriptor ); + void _deleteCacheEntry( unsigned i ); void _fixDescriptorCacheNumbers(); diff --git a/src/mongo/db/catalog/index_create.cpp b/src/mongo/db/catalog/index_create.cpp index 0df55d7e3ab..4c71ee681e7 100644 --- a/src/mongo/db/catalog/index_create.cpp +++ b/src/mongo/db/catalog/index_create.cpp @@ -54,7 +54,7 @@ namespace mongo { /** * Add the provided (obj, dl) pair to the provided index. */ - static void addKeysToIndex( Collection* collection, IndexDescriptor* desc, + static void addKeysToIndex( Collection* collection, const IndexDescriptor* desc, const BSONObj& obj, const DiskLoc &recordLoc ) { verify( desc ); @@ -81,11 +81,11 @@ namespace mongo { : BackgroundOperation(ns) { } - unsigned long long go( Collection* collection, IndexDescriptor* idx ); + unsigned long long go( Collection* collection, BtreeInMemoryState* idx ); private: unsigned long long addExistingToIndex( Collection* collection, - IndexDescriptor* idx ); + const IndexDescriptor* idx ); void prep(const StringData& ns ) { Lock::assertWriteLocked(ns); @@ -102,7 +102,8 @@ namespace mongo { }; - unsigned long long BackgroundIndexBuildJob::go( Collection* collection, IndexDescriptor* idx) { + unsigned long long BackgroundIndexBuildJob::go( Collection* collection, + BtreeInMemoryState* btreeState) { string ns = collection->ns().ns(); @@ -113,8 +114,9 @@ namespace mongo { prep( ns ); try { - idx->getOnDisk().head.writing() = BtreeBasedBuilder::makeEmptyIndex( idx->getOnDisk() ); - unsigned long long n = addExistingToIndex( collection, idx ); + //idx->getOnDisk().head.writing() = BtreeBasedBuilder::makeEmptyIndex( idx->getOnDisk() ); + btreeState->setHead( BtreeBasedBuilder::makeEmptyIndex( btreeState ) ); + unsigned long long n = addExistingToIndex( collection, btreeState->descriptor() ); // idx may point at an invalid index entry at this point done( ns ); return n; @@ -126,7 +128,7 @@ namespace mongo { } unsigned long long BackgroundIndexBuildJob::addExistingToIndex( Collection* collection, - IndexDescriptor* idx ) { + const IndexDescriptor* idx ) { string ns = collection->ns().ns(); // our copy for sanity @@ -225,11 +227,13 @@ namespace mongo { // throws DBException void buildAnIndex( Collection* collection, - IndexDescriptor* idx, + BtreeInMemoryState* btreeState, bool mayInterrupt ) { string ns = collection->ns().ns(); // our copy + const IndexDescriptor* idx = btreeState->descriptor(); + const BSONObj& idxInfo = idx->infoObj(); MONGO_TLOG(0) << "build index on: " << ns @@ -243,12 +247,12 @@ namespace mongo { verify( Lock::isWriteLocked( ns ) ); if( inDBRepair || !idxInfo["background"].trueValue() ) { - n = BtreeBasedBuilder::fastBuildIndex( collection, idx, mayInterrupt ); + n = BtreeBasedBuilder::fastBuildIndex( collection, btreeState, mayInterrupt ); verify( !idx->getHead().isNull() ); } else { BackgroundIndexBuildJob j( ns ); - n = j.go( collection, idx ); + n = j.go( collection, btreeState ); } MONGO_TLOG(0) << "build index done. scanned " << n << " total records. " << t.millis() / 1000.0 << " secs" << endl; diff --git a/src/mongo/db/catalog/index_create.h b/src/mongo/db/catalog/index_create.h index f28034ac18c..6abe7e07484 100644 --- a/src/mongo/db/catalog/index_create.h +++ b/src/mongo/db/catalog/index_create.h @@ -33,14 +33,15 @@ #include <string> namespace mongo { + + class BtreeInMemoryState; class Collection; - class IndexDescriptor; // Build an index in the foreground // If background is false, uses fast index builder // If background is true, uses background index builder; blocks until done. void buildAnIndex( Collection* collection, - IndexDescriptor* idx, + BtreeInMemoryState* btreeState, bool mayInterrupt ); } // namespace mongo diff --git a/src/mongo/db/clientcursor.h b/src/mongo/db/clientcursor.h index 6d106bd6c85..9eb6d07e86c 100644 --- a/src/mongo/db/clientcursor.h +++ b/src/mongo/db/clientcursor.h @@ -33,7 +33,6 @@ #include <boost/thread/recursive_mutex.hpp> #include "mongo/db/diskloc.h" -#include "mongo/db/dbhelpers.h" #include "mongo/db/jsobj.h" #include "mongo/db/keypattern.h" #include "mongo/db/matcher.h" @@ -48,6 +47,9 @@ namespace mongo { typedef boost::recursive_mutex::scoped_lock recursive_scoped_lock; class ClientCursor; + class CurOp; + class Database; + class NamespaceDetails; class ParsedQuery; typedef long long CursorId; /* passed to the client so it can send back on getMore */ diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp index b83f362fcf6..bcf73803ea4 100644 --- a/src/mongo/db/commands/distinct.cpp +++ b/src/mongo/db/commands/distinct.cpp @@ -39,6 +39,7 @@ #include "mongo/db/instance.h" #include "mongo/db/jsobj.h" #include "mongo/db/kill_current_op.h" +#include "mongo/db/pdfile.h" #include "mongo/db/query/get_runner.h" #include "mongo/db/query/query_planner_common.h" #include "mongo/db/query/type_explain.h" diff --git a/src/mongo/db/commands/group.cpp b/src/mongo/db/commands/group.cpp index eaf6ef7e210..2e7473f035b 100644 --- a/src/mongo/db/commands/group.cpp +++ b/src/mongo/db/commands/group.cpp @@ -39,8 +39,10 @@ #include "mongo/db/client_basic.h" #include "mongo/db/clientcursor.h" #include "mongo/db/commands.h" +#include "mongo/db/database.h" #include "mongo/db/instance.h" #include "mongo/db/query/get_runner.h" +#include "mongo/db/structure/collection.h" #include "mongo/scripting/engine.h" namespace mongo { diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp index e28af212b0d..cb6e5f2c793 100644 --- a/src/mongo/db/commands/mr.cpp +++ b/src/mongo/db/commands/mr.cpp @@ -39,6 +39,7 @@ #include "mongo/db/clientcursor.h" #include "mongo/db/commands.h" #include "mongo/db/db.h" +#include "mongo/db/dbhelpers.h" #include "mongo/db/instance.h" #include "mongo/db/kill_current_op.h" #include "mongo/db/matcher.h" diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp index 24e52a38ac9..7f625b0ef12 100644 --- a/src/mongo/db/commands/pipeline_command.cpp +++ b/src/mongo/db/commands/pipeline_command.cpp @@ -33,6 +33,8 @@ #include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/privilege.h" +#include "mongo/db/client.h" +#include "mongo/db/curop.h" #include "mongo/db/commands.h" #include "mongo/db/interrupt_status_mongod.h" #include "mongo/db/pipeline/accumulator.h" diff --git a/src/mongo/db/database.cpp b/src/mongo/db/database.cpp index 6a9ae273fce..c6db2fd5d4c 100644 --- a/src/mongo/db/database.cpp +++ b/src/mongo/db/database.cpp @@ -40,6 +40,7 @@ #include "mongo/db/background.h" #include "mongo/db/clientcursor.h" #include "mongo/db/database_holder.h" +#include "mongo/db/dbhelpers.h" #include "mongo/db/storage/index_details.h" #include "mongo/db/instance.h" #include "mongo/db/introspect.h" diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp index eabfc96c62d..a58feef41a2 100644 --- a/src/mongo/db/dbcommands.cpp +++ b/src/mongo/db/dbcommands.cpp @@ -50,6 +50,7 @@ #include "mongo/db/commands/server_status.h" #include "mongo/db/commands/shutdown.h" #include "mongo/db/db.h" +#include "mongo/db/dbhelpers.h" #include "mongo/db/dur_stats.h" #include "mongo/db/index_builder.h" #include "mongo/db/instance.h" diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp index d6750f53d85..1e07ee167cb 100644 --- a/src/mongo/db/dbhelpers.cpp +++ b/src/mongo/db/dbhelpers.cpp @@ -39,13 +39,13 @@ #include "mongo/client/dbclientinterface.h" #include "mongo/db/db.h" #include "mongo/db/json.h" +#include "mongo/db/index/btree_access_method.h" #include "mongo/db/ops/delete.h" #include "mongo/db/ops/update.h" #include "mongo/db/ops/update_lifecycle_impl.h" #include "mongo/db/ops/update_request.h" #include "mongo/db/ops/update_result.h" #include "mongo/db/pagefault.h" -#include "mongo/db/query_runner.h" #include "mongo/db/query/get_runner.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/query/query_planner.h" @@ -114,40 +114,43 @@ namespace mongo { } bool Helpers::findById(Client& c, const char *ns, BSONObj query, BSONObj& result , - bool * nsFound , bool * indexFound ) { + bool* nsFound , bool* indexFound ) { Lock::assertAtLeastReadLocked(ns); Database *database = c.database(); verify( database ); - NamespaceDetails *d = database->namespaceIndex().details(ns); - if ( ! d ) + + Collection* collection = database->getCollection( ns ); + if ( !collection ) { return false; + } + if ( nsFound ) - *nsFound = 1; + *nsFound = true; + + IndexCatalog* catalog = collection->getIndexCatalog(); + const IndexDescriptor* desc = catalog->findIdIndex(); - int idxNo = d->findIdIndex(); - if ( idxNo < 0 ) + if ( !desc ) return false; + if ( indexFound ) *indexFound = 1; - IndexDetails& i = d->idx( idxNo ); - - BSONObj key = i.getKeyFromQuery( query ); - - DiskLoc loc = QueryRunner::fastFindSingle(i, key); + BtreeBasedAccessMethod* accessMethod = catalog->getBtreeBasedIndex( desc ); + DiskLoc loc = accessMethod->findSingle( query["_id"].wrap() ); if ( loc.isNull() ) return false; - result = loc.obj(); + result = collection->docFor( loc ); return true; } - DiskLoc Helpers::findById(NamespaceDetails *d, BSONObj idquery) { - verify(d); - int idxNo = d->findIdIndex(); - uassert(13430, "no _id index", idxNo>=0); - IndexDetails& i = d->idx( idxNo ); - BSONObj key = i.getKeyFromQuery( idquery ); - return QueryRunner::fastFindSingle(i, key); + DiskLoc Helpers::findById(Collection* collection, const BSONObj& idquery) { + verify(collection); + IndexCatalog* catalog = collection->getIndexCatalog(); + const IndexDescriptor* desc = catalog->findIdIndex(); + uassert(13430, "no _id index", desc); + BtreeBasedAccessMethod* accessMethod = catalog->getBtreeBasedIndex( desc ); + return accessMethod->findSingle( idquery["_id"].wrap() ); } vector<BSONObj> Helpers::findAll( const string& ns , const BSONObj& query ) { diff --git a/src/mongo/db/dbhelpers.h b/src/mongo/db/dbhelpers.h index 58bb1881796..ce7b85f3968 100644 --- a/src/mongo/db/dbhelpers.h +++ b/src/mongo/db/dbhelpers.h @@ -40,6 +40,7 @@ namespace mongo { extern const BSONObj reverseNaturalObj; // {"$natural": -1 } + class Collection; class Cursor; /** @@ -90,9 +91,10 @@ namespace mongo { static bool findById(Client&, const char *ns, BSONObj query, BSONObj& result , bool * nsFound = 0 , bool * indexFound = 0 ); - /* uasserts if no _id index. - @return null loc if not found */ - static DiskLoc findById(NamespaceDetails *d, BSONObj query); + /* TODO: should this move into Collection? + * uasserts if no _id index. + * @return null loc if not found */ + static DiskLoc findById(Collection* collection, const BSONObj& query); /** Get/put the first (or last) object from a collection. Generally only useful if the collection only ever has a single object -- which is a "singleton collection". diff --git a/src/mongo/db/exec/2dcommon.cpp b/src/mongo/db/exec/2dcommon.cpp index 2f09e060916..9492cb8fc51 100644 --- a/src/mongo/db/exec/2dcommon.cpp +++ b/src/mongo/db/exec/2dcommon.cpp @@ -224,7 +224,7 @@ namespace twod_exec { // The only time these may be equal is when we actually equal the location // itself, otherwise our expanding algorithm will fail. // static - bool BtreeLocation::initial(IndexDescriptor* descriptor, const TwoDIndexingParams& params, + bool BtreeLocation::initial(const IndexDescriptor* descriptor, const TwoDIndexingParams& params, BtreeLocation& min, BtreeLocation& max, GeoHash start) { verify(descriptor); diff --git a/src/mongo/db/exec/2dcommon.h b/src/mongo/db/exec/2dcommon.h index b475aa3adae..b12548c0d87 100644 --- a/src/mongo/db/exec/2dcommon.h +++ b/src/mongo/db/exec/2dcommon.h @@ -131,8 +131,8 @@ namespace twod_exec { // Returns the min and max keys which bound a particular location. // The only time these may be equal is when we actually equal the location // itself, otherwise our expanding algorithm will fail. - static bool initial(IndexDescriptor* descriptor, const TwoDIndexingParams& params, - BtreeLocation& min, BtreeLocation& max, GeoHash start); + static bool initial(const IndexDescriptor* descriptor, const TwoDIndexingParams& params, + BtreeLocation& min, BtreeLocation& max, GeoHash start); }; // @@ -268,7 +268,7 @@ namespace twod_exec { shared_ptr<GeoHash> _expPrefix; mutable vector<GeoHash> _expPrefixes; - IndexDescriptor* _descriptor; + const IndexDescriptor* _descriptor; shared_ptr<GeoHashConverter> _converter; TwoDIndexingParams _params; }; diff --git a/src/mongo/db/exec/index_scan.h b/src/mongo/db/exec/index_scan.h index 0848da1b46e..4d476fff1e8 100644 --- a/src/mongo/db/exec/index_scan.h +++ b/src/mongo/db/exec/index_scan.h @@ -53,7 +53,7 @@ namespace mongo { maxScan(0), addKeyMetadata(false) { } - IndexDescriptor* descriptor; + const IndexDescriptor* descriptor; IndexBounds bounds; @@ -103,9 +103,9 @@ namespace mongo { WorkingSet* _workingSet; // Index access. - IndexAccessMethod* _iam; // owned by Collection -> IndexCatalog + const IndexAccessMethod* _iam; // owned by Collection -> IndexCatalog scoped_ptr<IndexCursor> _indexCursor; - IndexDescriptor* _descriptor; // owned by Collection -> IndexCatalog + const IndexDescriptor* _descriptor; // owned by Collection -> IndexCatalog // Have we hit the end of the index scan? bool _hitEnd; diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp index f5f74cfcc51..fdd7f4bcc5a 100644 --- a/src/mongo/db/exec/stagedebug_cmd.cpp +++ b/src/mongo/db/exec/stagedebug_cmd.cpp @@ -359,7 +359,8 @@ namespace mongo { uassert(17194, "Expected exactly one text index", idxMatches.size() == 1); IndexDescriptor* index = collection->getIndexCatalog()->getDescriptor(idxMatches[0]); - auto_ptr<FTSAccessMethod> fam(new FTSAccessMethod(index)); + FTSAccessMethod* fam = + reinterpret_cast<FTSAccessMethod*>( collection->getIndexCatalog()->getIndex( index ) ); TextStageParams params(fam->getSpec()); params.ns = ns; params.index = index; diff --git a/src/mongo/db/index/2d_access_method.cpp b/src/mongo/db/index/2d_access_method.cpp index c9fe4b8bab2..0c33e54dd88 100644 --- a/src/mongo/db/index/2d_access_method.cpp +++ b/src/mongo/db/index/2d_access_method.cpp @@ -39,14 +39,16 @@ namespace mongo { - static double configValueWithDefault(IndexDescriptor *desc, const string& name, double def) { + static double configValueWithDefault(const IndexDescriptor *desc, const string& name, double def) { BSONElement e = desc->getInfoElement(name); if (e.isNumber()) { return e.numberDouble(); } return def; } - TwoDAccessMethod::TwoDAccessMethod(IndexDescriptor* descriptor) - : BtreeBasedAccessMethod(descriptor) { + TwoDAccessMethod::TwoDAccessMethod(BtreeInMemoryState* btreeState) + : BtreeBasedAccessMethod(btreeState) { + + const IndexDescriptor* descriptor = btreeState->descriptor(); BSONObjIterator i(descriptor->keyPattern()); while (i.more()) { @@ -65,13 +67,13 @@ namespace mongo { } uassert(16802, "no geo field specified", _params.geo.size()); - double bits = configValueWithDefault(_descriptor, "bits", 26); // for lat/long, ~ 1ft + double bits = configValueWithDefault(descriptor, "bits", 26); // for lat/long, ~ 1ft uassert(16803, "bits in geo index must be between 1 and 32", bits > 0 && bits <= 32); GeoHashConverter::Parameters params; params.bits = static_cast<unsigned>(bits); - params.max = configValueWithDefault(_descriptor, "max", 180.0); - params.min = configValueWithDefault(_descriptor, "min", -180.0); + params.max = configValueWithDefault(descriptor, "max", 180.0); + params.min = configValueWithDefault(descriptor, "min", -180.0); double numBuckets = (1024 * 1024 * 1024 * 4.0); params.scaling = numBuckets / (params.max - params.min); @@ -189,7 +191,7 @@ namespace mongo { } } - Status TwoDAccessMethod::newCursor(IndexCursor** out) { + Status TwoDAccessMethod::newCursor(IndexCursor** out) const { return Status(ErrorCodes::IllegalOperation, "Unimplemented seek called on S2"); } diff --git a/src/mongo/db/index/2d_access_method.h b/src/mongo/db/index/2d_access_method.h index e7eb48797cd..83efe2a6b30 100644 --- a/src/mongo/db/index/2d_access_method.h +++ b/src/mongo/db/index/2d_access_method.h @@ -32,6 +32,7 @@ #include "mongo/db/index/2d_common.h" #include "mongo/db/index/btree_access_method_internal.h" #include "mongo/db/jsobj.h" +#include "mongo/db/structure/btree/state.h" namespace mongo { @@ -67,12 +68,11 @@ namespace mongo { public: using BtreeBasedAccessMethod::_descriptor; using BtreeBasedAccessMethod::_interface; - using BtreeBasedAccessMethod::_ordering; - TwoDAccessMethod(IndexDescriptor* descriptor); + TwoDAccessMethod(BtreeInMemoryState* btreeState); virtual ~TwoDAccessMethod() { } - virtual Status newCursor(IndexCursor** out); + virtual Status newCursor(IndexCursor** out) const; private: friend class TwoDIndexCursor; @@ -97,7 +97,7 @@ namespace mongo { friend class twod_internal::TwoDGeoNearRunner; BtreeInterface* getInterface() { return _interface; } - IndexDescriptor* getDescriptor() { return _descriptor; } + const IndexDescriptor* getDescriptor() { return _descriptor; } TwoDIndexingParams& getParams() { return _params; } // This really gets the 'locs' from the provided obj. diff --git a/src/mongo/db/index/btree_access_method.cpp b/src/mongo/db/index/btree_access_method.cpp index b9c76d9ec17..37cd69ca3d0 100644 --- a/src/mongo/db/index/btree_access_method.cpp +++ b/src/mongo/db/index/btree_access_method.cpp @@ -37,14 +37,15 @@ #include "mongo/db/keypattern.h" #include "mongo/db/pdfile.h" #include "mongo/db/pdfile_private.h" +#include "mongo/db/structure/btree/state-inl.h" namespace mongo { - BtreeBasedAccessMethod::BtreeBasedAccessMethod(IndexDescriptor *descriptor) - : _descriptor(descriptor), _ordering(Ordering::make(_descriptor->keyPattern())) { + BtreeBasedAccessMethod::BtreeBasedAccessMethod(BtreeInMemoryState* btreeState) + : _btreeState(btreeState), _descriptor(btreeState->descriptor()) { - verify(0 == descriptor->version() || 1 == descriptor->version()); - _interface = BtreeInterface::interfaces[descriptor->version()]; + 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 @@ -61,8 +62,12 @@ namespace mongo { for (BSONObjSet::const_iterator i = keys.begin(); i != keys.end(); ++i) { try { - _interface->bt_insert(_descriptor->getHead(), loc, *i, _ordering, - options.dupsAllowed, _descriptor->getOnDisk(), true); + _interface->bt_insert(_btreeState.get(), + _btreeState->head(), + loc, + *i, + options.dupsAllowed, + true); ++*numInserted; } catch (AssertionException& e) { if (10287 == e.getCode() && _descriptor->isBackgroundIndex()) { @@ -86,7 +91,7 @@ namespace mongo { } if (*numInserted > 1) { - _descriptor->setMultikey(); + _btreeState->setMultikey(); } return ret; @@ -96,7 +101,10 @@ namespace mongo { bool ret = false; try { - ret = _interface->unindex(_descriptor->getHead(), _descriptor->getOnDisk(), key, loc); + ret = _interface->unindex(_btreeState.get(), + _btreeState->head(), + key, + loc); } catch (AssertionException& e) { problem() << "Assertion failure: _unindex failed " << _descriptor->indexNamespace() << endl; @@ -160,15 +168,37 @@ namespace mongo { int unusedPos; bool unusedFound; DiskLoc unusedDiskLoc; - _interface->locate(_descriptor->getOnDisk(), _descriptor->getHead(), *i, _ordering, - unusedPos, unusedFound, unusedDiskLoc, 1); + _interface->locate(_btreeState.get(), + _descriptor->getHead(), + *i, + unusedPos, + unusedFound, + unusedDiskLoc, + 1); } return Status::OK(); } + DiskLoc BtreeBasedAccessMethod::findSingle( const BSONObj& key ) { + if ( 0 == _descriptor->version() ) { + return _btreeState->getHeadBucket<V0>()->findSingle( _btreeState.get(), + _btreeState->head(), + key ); + } + if ( 1 == _descriptor->version() ) { + return _btreeState->getHeadBucket<V1>()->findSingle( _btreeState.get(), + _btreeState->head(), + key ); + } + verify( 0 ); + } + + Status BtreeBasedAccessMethod::validate(int64_t* numKeys) { - *numKeys = _interface->fullValidate(_descriptor->getHead(), _descriptor->keyPattern()); + *numKeys = _interface->fullValidate(_btreeState.get(), + _descriptor->getHead(), + _descriptor->keyPattern()); return Status::OK(); } @@ -193,12 +223,13 @@ namespace mongo { if (checkForDups) { for (vector<BSONObj*>::iterator i = data->added.begin(); i != data->added.end(); i++) { - if (_interface->wouldCreateDup(_descriptor->getOnDisk(), _descriptor->getHead(), - **i, _ordering, record)) { + if (_interface->wouldCreateDup(_btreeState.get(), + _btreeState->head(), + **i, record)) { status->_isValid = false; return Status(ErrorCodes::DuplicateKey, - _interface->dupKeyError(_descriptor->getHead(), - _descriptor->getOnDisk(), + _interface->dupKeyError(_btreeState.get(), + _btreeState->head(), **i)); } } @@ -218,16 +249,22 @@ namespace mongo { static_cast<BtreeBasedPrivateUpdateData*>(ticket._indexSpecificUpdateData.get()); if (data->oldKeys.size() + data->added.size() - data->removed.size() > 1) { - _descriptor->setMultikey(); + _btreeState->setMultikey(); } for (size_t i = 0; i < data->added.size(); ++i) { - _interface->bt_insert(_descriptor->getHead(), data->loc, *data->added[i], _ordering, - data->dupsAllowed, _descriptor->getOnDisk(), true); + _interface->bt_insert(_btreeState.get(), + _btreeState->head(), + data->loc, + *data->added[i], + data->dupsAllowed, + true); } for (size_t i = 0; i < data->removed.size(); ++i) { - _interface->unindex(_descriptor->getHead(), _descriptor->getOnDisk(), *data->removed[i], + _interface->unindex(_btreeState.get(), + _btreeState->head(), + *data->removed[i], data->loc); } @@ -237,8 +274,8 @@ namespace mongo { } // Standard Btree implementation below. - BtreeAccessMethod::BtreeAccessMethod(IndexDescriptor* descriptor) - : BtreeBasedAccessMethod(descriptor) { + BtreeAccessMethod::BtreeAccessMethod(BtreeInMemoryState* btreeState) + : BtreeBasedAccessMethod(btreeState) { // The key generation wants these values. vector<const char*> fieldNames; @@ -251,10 +288,10 @@ namespace mongo { fixed.push_back(BSONElement()); } - if (0 == descriptor->version()) { + if (0 == _descriptor->version()) { _keyGenerator.reset(new BtreeKeyGeneratorV0(fieldNames, fixed, _descriptor->isSparse())); - } else if (1 == descriptor->version()) { + } else if (1 == _descriptor->version()) { _keyGenerator.reset(new BtreeKeyGeneratorV1(fieldNames, fixed, _descriptor->isSparse())); } else { @@ -266,8 +303,8 @@ namespace mongo { _keyGenerator->getKeys(obj, keys); } - Status BtreeAccessMethod::newCursor(IndexCursor** out) { - *out = new BtreeIndexCursor(_descriptor, _ordering, _interface); + Status BtreeAccessMethod::newCursor(IndexCursor** out) const { + *out = new BtreeIndexCursor(_btreeState.get(), _interface); return Status::OK(); } diff --git a/src/mongo/db/index/btree_access_method.h b/src/mongo/db/index/btree_access_method.h index 149c34c3a46..09028615350 100644 --- a/src/mongo/db/index/btree_access_method.h +++ b/src/mongo/db/index/btree_access_method.h @@ -53,12 +53,11 @@ namespace mongo { // superclass and subclasses (like this) can use them. using BtreeBasedAccessMethod::_descriptor; using BtreeBasedAccessMethod::_interface; - using BtreeBasedAccessMethod::_ordering; - BtreeAccessMethod(IndexDescriptor* descriptor); + BtreeAccessMethod(BtreeInMemoryState* btreeState ); virtual ~BtreeAccessMethod() { } - virtual Status newCursor(IndexCursor** out); + virtual Status newCursor(IndexCursor** out) const; private: virtual void getKeys(const BSONObj& obj, BSONObjSet* keys); diff --git a/src/mongo/db/index/btree_access_method_internal.h b/src/mongo/db/index/btree_access_method_internal.h index 610aeea9fcb..234ef1d21e0 100644 --- a/src/mongo/db/index/btree_access_method_internal.h +++ b/src/mongo/db/index/btree_access_method_internal.h @@ -30,12 +30,14 @@ #include <vector> +#include "mongo/base/disallow_copying.h" #include "mongo/db/diskloc.h" #include "mongo/db/jsobj.h" #include "mongo/db/index/btree_interface.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/index/index_cursor.h" #include "mongo/db/index/index_descriptor.h" +#include "mongo/db/structure/btree/state.h" namespace mongo { @@ -48,8 +50,10 @@ namespace mongo { * 3. override getKeys. */ class BtreeBasedAccessMethod : public IndexAccessMethod { + MONGO_DISALLOW_COPYING( BtreeBasedAccessMethod ); public: - BtreeBasedAccessMethod(IndexDescriptor *descriptor); + BtreeBasedAccessMethod( BtreeInMemoryState* btreeState ); + virtual ~BtreeBasedAccessMethod() { } virtual Status insert(const BSONObj& obj, @@ -70,12 +74,14 @@ namespace mongo { virtual Status update(const UpdateTicket& ticket, int64_t* numUpdated); - virtual Status newCursor(IndexCursor **out) = 0; + virtual Status newCursor(IndexCursor **out) const = 0; virtual Status touch(const BSONObj& obj); virtual Status validate(int64_t* numKeys); + virtual DiskLoc findSingle( const BSONObj& key ); + protected: // Friends who need getKeys. friend class BtreeBasedBuilder; @@ -85,8 +91,8 @@ namespace mongo { virtual void getKeys(const BSONObj &obj, BSONObjSet *keys) = 0; - IndexDescriptor* _descriptor; - Ordering _ordering; + scoped_ptr<BtreeInMemoryState> _btreeState; // OWNED HERE + const IndexDescriptor* _descriptor; // There are 2 types of Btree disk formats. We put them both behind one interface. BtreeInterface* _interface; diff --git a/src/mongo/db/index/btree_based_builder.cpp b/src/mongo/db/index/btree_based_builder.cpp index cb5a2c92967..57abfda90ef 100644 --- a/src/mongo/db/index/btree_based_builder.cpp +++ b/src/mongo/db/index/btree_based_builder.cpp @@ -75,7 +75,7 @@ namespace mongo { template< class V > void buildBottomUpPhases2And3( bool dupsAllowed, - IndexDescriptor* idx, + BtreeInMemoryState* btreeState, BSONObjExternalSorter& sorter, bool dropDups, set<DiskLoc>& dupsToDrop, @@ -84,7 +84,7 @@ namespace mongo { ProgressMeterHolder& pm, Timer& t, bool mayInterrupt ) { - BtreeBuilder<V> btBuilder(dupsAllowed, idx->getOnDisk()); + BtreeBuilder<V> btBuilder(dupsAllowed, btreeState); BSONObj keyLast; auto_ptr<BSONObjExternalSorter::Iterator> i = sorter.iterator(); // verifies that pm and op refer to the same ProgressMeter @@ -136,8 +136,8 @@ namespace mongo { } } - DiskLoc BtreeBasedBuilder::makeEmptyIndex(const IndexDetails& idx) { - if (0 == idx.version()) { + DiskLoc BtreeBasedBuilder::makeEmptyIndex(BtreeInMemoryState* idx) { + if (0 == idx->descriptor()->version()) { return BtreeBucket<V0>::addBucket(idx); } else { return BtreeBucket<V1>::addBucket(idx); @@ -155,7 +155,7 @@ namespace mongo { } void BtreeBasedBuilder::addKeysToPhaseOne(Collection* collection, - IndexDescriptor* idx, + const IndexDescriptor* idx, const BSONObj& order, SortPhaseOne* phaseOne, ProgressMeter* progressMeter, @@ -189,19 +189,25 @@ namespace mongo { } uint64_t BtreeBasedBuilder::fastBuildIndex( Collection* collection, - IndexDescriptor* idx, + BtreeInMemoryState* btreeState, bool mayInterrupt ) { CurOp * op = cc().curop(); - Timer t; - MONGO_TLOG(1) << "fastBuildIndex " << collection->ns() << ' ' << idx->toString() << endl; + const IndexDescriptor* descriptor = btreeState->descriptor(); + + MONGO_TLOG(1) << "fastBuildIndex " << collection->ns() << ' ' << descriptor->toString(); - bool dupsAllowed = !idx->unique() || ignoreUniqueIndex(idx->getOnDisk()); - bool dropDups = idx->dropDups() || inDBRepair; - BSONObj order = idx->keyPattern(); + bool dupsAllowed = !descriptor->unique() || ignoreUniqueIndex(descriptor); + bool dropDups = descriptor->dropDups() || inDBRepair; + BSONObj order = descriptor->keyPattern(); - getDur().writingDiskLoc(idx->getOnDisk().head).Null(); + { + DiskLoc myNull; + myNull.Null(); + btreeState->setHead( myNull ); + //getDur().writingDiskLoc(idx->getOnDisk().head).Null(); + } if ( logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(2) ) ) printMemInfo( "before index start" ); @@ -212,13 +218,13 @@ namespace mongo { collection->numRecords(), 10)); SortPhaseOne phase1; - addKeysToPhaseOne(collection, idx, order, &phase1, pm.get(), mayInterrupt ); + addKeysToPhaseOne(collection, descriptor, order, &phase1, pm.get(), mayInterrupt ); pm.finished(); BSONObjExternalSorter& sorter = *(phase1.sorter); if( phase1.multi ) { - collection->getIndexCatalog()->markMultikey( idx ); + btreeState->setMultikey(); } if ( logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(2) ) ) @@ -233,9 +239,9 @@ namespace mongo { set<DiskLoc> dupsToDrop; /* build index --- */ - if( idx->version() == 0 ) + if( descriptor->version() == 0 ) buildBottomUpPhases2And3<V0>(dupsAllowed, - idx, + btreeState, sorter, dropDups, dupsToDrop, @@ -244,9 +250,9 @@ namespace mongo { pm, t, mayInterrupt); - else if( idx->version() == 1 ) + else if( descriptor->version() == 1 ) buildBottomUpPhases2And3<V1>(dupsAllowed, - idx, + btreeState, sorter, dropDups, dupsToDrop, diff --git a/src/mongo/db/index/btree_based_builder.h b/src/mongo/db/index/btree_based_builder.h index 50510a33417..e003d2b9518 100644 --- a/src/mongo/db/index/btree_based_builder.h +++ b/src/mongo/db/index/btree_based_builder.h @@ -44,6 +44,7 @@ namespace mongo { class Collection; class BSONObjExternalSorter; + class BtreeInMemoryState; class ExternalSortComparison; class IndexDescriptor; class IndexDetails; @@ -57,10 +58,14 @@ namespace mongo { /** * Want to build an index? Call this. Throws DBException. */ - static uint64_t fastBuildIndex(Collection* collection, IndexDescriptor* descriptor, + static uint64_t fastBuildIndex(Collection* collection, + BtreeInMemoryState* descriptor, bool mayInterrupt); - static DiskLoc makeEmptyIndex(const IndexDetails& idx); - static ExternalSortComparison* getComparison(int version, const BSONObj& keyPattern); + + static DiskLoc makeEmptyIndex(BtreeInMemoryState* idx); + + static ExternalSortComparison* getComparison(int version, + const BSONObj& keyPattern); private: friend class IndexUpdateTests::AddKeysToPhaseOne; @@ -69,18 +74,22 @@ namespace mongo { friend class IndexUpdateTests::InterruptDoDropDups; - static void addKeysToPhaseOne(Collection* collection, IndexDescriptor* idx, - const BSONObj& order, SortPhaseOne* phaseOne, - ProgressMeter* progressMeter, bool mayInterrupt ); + static void addKeysToPhaseOne(Collection* collection, + const IndexDescriptor* idx, + const BSONObj& order, + SortPhaseOne* phaseOne, + ProgressMeter* progressMeter, + bool mayInterrupt ); - static void doDropDups(Collection* collection, const set<DiskLoc>& dupsToDrop, + static void doDropDups(Collection* collection, + const set<DiskLoc>& dupsToDrop, bool mayInterrupt ); }; // Exposed for testing purposes. template< class V > void buildBottomUpPhases2And3( bool dupsAllowed, - IndexDescriptor* idx, + BtreeInMemoryState* btreeState, BSONObjExternalSorter& sorter, bool dropDups, set<DiskLoc>& dupsToDrop, diff --git a/src/mongo/db/index/btree_index_cursor.cpp b/src/mongo/db/index/btree_index_cursor.cpp index fda428b0dda..19cf283e081 100644 --- a/src/mongo/db/index/btree_index_cursor.cpp +++ b/src/mongo/db/index/btree_index_cursor.cpp @@ -43,10 +43,10 @@ namespace mongo { SimpleMutex BtreeIndexCursor::_activeCursorsMutex("active_btree_index_cursors"); // Go forward by default. - BtreeIndexCursor::BtreeIndexCursor(IndexDescriptor *descriptor, Ordering ordering, + BtreeIndexCursor::BtreeIndexCursor(const BtreeInMemoryState* btreeState, BtreeInterface *interface) - : _direction(1), _descriptor(descriptor), _ordering(ordering), _interface(interface), - _bucket(descriptor->getHead()), _keyOffset(0) { + : _direction(1), _btreeState(btreeState), _interface(interface), + _bucket(btreeState->head()), _keyOffset(0) { SimpleMutex::scoped_lock lock(_activeCursorsMutex); _activeCursors.insert(this); @@ -90,15 +90,13 @@ namespace mongo { // Unused out parameter. bool found; - _bucket = _interface->locate( - _descriptor->getOnDisk(), - _descriptor->getHead(), - position, - _ordering, - _keyOffset, - found, - 1 == _direction ? minDiskLoc : maxDiskLoc, - _direction); + _bucket = _interface->locate( _btreeState, + _btreeState->head(), + position, + _keyOffset, + found, + 1 == _direction ? minDiskLoc : maxDiskLoc, + _direction); skipUnusedKeys(); @@ -111,20 +109,18 @@ namespace mongo { // Bucket is modified by customLocate. Seeks start @ the root, so we set _bucket to the // root here. - _bucket = _descriptor->getHead(); + _bucket = _btreeState->head(); _keyOffset = 0; - _interface->customLocate( - _bucket, - _keyOffset, - _emptyObj, - 0, - false, - position, - inclusive, - _ordering, - (int)_direction, - ignored); + _interface->customLocate(_btreeState, + _bucket, + _keyOffset, + _emptyObj, + 0, false, + position, + inclusive, + (int)_direction, + ignored); skipUnusedKeys(); @@ -134,16 +130,15 @@ namespace mongo { Status BtreeIndexCursor::skip(const BSONObj &keyBegin, int keyBeginLen, bool afterKey, const vector<const BSONElement*>& keyEnd, const vector<bool>& keyEndInclusive) { - _interface->advanceTo( - _bucket, - _keyOffset, - keyBegin, - keyBeginLen, - afterKey, - keyEnd, - keyEndInclusive, - _ordering, - (int)_direction); + _interface->advanceTo(_btreeState, + _bucket, + _keyOffset, + keyBegin, + keyBeginLen, + afterKey, + keyEnd, + keyEndInclusive, + (int)_direction); skipUnusedKeys(); return Status::OK(); @@ -206,15 +201,13 @@ namespace mongo { bool found; // Why don't we just call seek? Because we want to pass _savedLoc. - _bucket = _interface->locate( - _descriptor->getOnDisk(), - _descriptor->getHead(), - _savedKey, - _ordering, - _keyOffset, - found, - _savedLoc, - _direction); + _bucket = _interface->locate(_btreeState, + _btreeState->head(), + _savedKey, + _keyOffset, + found, + _savedLoc, + _direction); skipUnusedKeys(); @@ -256,7 +249,7 @@ namespace mongo { // Move to the next/prev. key. Used by normal getNext and also skipping unused keys. void BtreeIndexCursor::advance(const char* caller) { - _bucket = _interface->advance(_bucket, _keyOffset, _direction, caller); + _bucket = _interface->advance(_btreeState, _bucket, _keyOffset, _direction, caller); } } // namespace mongo diff --git a/src/mongo/db/index/btree_index_cursor.h b/src/mongo/db/index/btree_index_cursor.h index efbfb6d6998..c1fc45181d3 100644 --- a/src/mongo/db/index/btree_index_cursor.h +++ b/src/mongo/db/index/btree_index_cursor.h @@ -36,6 +36,7 @@ #include "mongo/db/index/btree_interface.h" #include "mongo/db/index/index_cursor.h" #include "mongo/db/index/index_descriptor.h" +#include "mongo/db/structure/btree/state.h" namespace mongo { @@ -85,7 +86,7 @@ namespace mongo { static SimpleMutex _activeCursorsMutex; // Go forward by default. - BtreeIndexCursor(IndexDescriptor *descriptor, Ordering ordering, BtreeInterface *interface); + BtreeIndexCursor(const BtreeInMemoryState* btreeState, BtreeInterface *interface); void skipUnusedKeys(); @@ -101,8 +102,7 @@ namespace mongo { BSONObj _emptyObj; int _direction; - IndexDescriptor* _descriptor; - Ordering _ordering; + const BtreeInMemoryState* _btreeState; // not-owned BtreeInterface* _interface; // What are we looking at RIGHT NOW? We look at a bucket. diff --git a/src/mongo/db/index/btree_interface.cpp b/src/mongo/db/index/btree_interface.cpp index 548537e43fa..448a6abf9f2 100644 --- a/src/mongo/db/index/btree_interface.cpp +++ b/src/mongo/db/index/btree_interface.cpp @@ -1,32 +1,34 @@ /** -* 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. -*/ + * 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/structure/btree/btree.h" +#include "mongo/db/structure/btree/state.h" +#include "mongo/db/structure/btree/state-inl.h" #include "mongo/db/index/btree_interface.h" #include "mongo/db/pdfile.h" @@ -39,105 +41,97 @@ namespace mongo { virtual ~BtreeInterfaceImpl() { } - virtual int bt_insert(const DiskLoc thisLoc, + virtual int bt_insert(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, const DiskLoc recordLoc, const BSONObj& key, - const Ordering &order, - bool dupsAllowed, - IndexDetails& idx, - bool toplevel) const { + bool dupsallowed, + bool toplevel) { // FYI: toplevel has a default value of true in btree.h - return thisLoc.btree<Version>()->bt_insert( - thisLoc, - recordLoc, - key, - order, - dupsAllowed, - idx, - toplevel); + return btreeState->getBucket<Version>(thisLoc)->bt_insert(btreeState, + thisLoc, + recordLoc, + key, + dupsallowed, + toplevel); } - virtual bool unindex(const DiskLoc thisLoc, - IndexDetails& id, + virtual bool unindex(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, const BSONObj& key, - const DiskLoc recordLoc) const { - return thisLoc.btree<Version>()->unindex(thisLoc, id, key, recordLoc); + const DiskLoc recordLoc) { + return btreeState->getBucket<Version>(thisLoc)->unindex(btreeState, + thisLoc, + key, + recordLoc); } - virtual DiskLoc locate(const IndexDetails& idx, + virtual DiskLoc locate(const BtreeInMemoryState* btreeState, const DiskLoc& thisLoc, const BSONObj& key, - const Ordering& order, int& pos, bool& found, const DiskLoc& recordLoc, int direction) const { // FYI: direction has a default of 1 - return thisLoc.btree<Version>()->locate( - idx, - thisLoc, - key, - order, - pos, - found, - recordLoc, - direction); + return btreeState->getBucket<Version>(thisLoc)->locate(btreeState, + thisLoc, + key, + pos, + found, + recordLoc, + direction); } - virtual bool wouldCreateDup(const IndexDetails& idx, + virtual bool wouldCreateDup(const BtreeInMemoryState* btreeState, const DiskLoc& thisLoc, const BSONObj& key, - const Ordering& order, const DiskLoc& self) const { typename Version::KeyOwned ownedVersion(key); - return thisLoc.btree<Version>()->wouldCreateDup( - idx, - thisLoc, - ownedVersion, - order, - self); + return btreeState->getBucket<Version>(thisLoc)->wouldCreateDup(btreeState, + thisLoc, + ownedVersion, + self); } - virtual void customLocate(DiskLoc& locInOut, + virtual void customLocate(const BtreeInMemoryState* btreeState, + DiskLoc& locInOut, int& keyOfs, const BSONObj& keyBegin, int keyBeginLen, bool afterVersion, const vector<const BSONElement*>& keyEnd, const vector<bool>& keyEndInclusive, - const Ordering& order, int direction, - pair<DiskLoc, int>& bestParent) { - locInOut.btree<Version>()->customLocate( - locInOut, - keyOfs, - keyBegin, - keyBeginLen, - afterVersion, - keyEnd, - keyEndInclusive, - order, - direction, - bestParent); + pair<DiskLoc, int>& bestParent) const { + return BtreeBucket<Version>::customLocate(btreeState, + locInOut, + keyOfs, + keyBegin, + keyBeginLen, afterVersion, + keyEnd, + keyEndInclusive, + direction, + bestParent); } - virtual void advanceTo(DiskLoc &thisLoc, + virtual void advanceTo(const BtreeInMemoryState* btreeState, + DiskLoc &thisLoc, int &keyOfs, const BSONObj &keyBegin, int keyBeginLen, bool afterVersion, const vector<const BSONElement*>& keyEnd, const vector<bool>& keyEndInclusive, - const Ordering& order, int direction) const { - thisLoc.btree<Version>()->advanceTo( - thisLoc, - keyOfs, - keyBegin, - keyBeginLen, - afterVersion, - keyEnd, - keyEndInclusive, - order, - direction); + int direction) const { + return btreeState->getBucket<Version>(thisLoc)->advanceTo(btreeState, + thisLoc, + keyOfs, + keyBegin, + keyBeginLen, + afterVersion, + keyEnd, + keyEndInclusive, + direction); } @@ -182,21 +176,26 @@ namespace mongo { } } - virtual string dupKeyError(DiskLoc bucket, const IndexDetails &idx, + virtual string dupKeyError(const BtreeInMemoryState* btreeState, + DiskLoc bucket, const BSONObj& keyObj) const { typename Version::KeyOwned key(keyObj); - return bucket.btree<Version>()->dupKeyError(idx, key); + return btreeState->getBucket<Version>( bucket )->dupKeyError(btreeState->descriptor(), + key); } - virtual DiskLoc advance(const DiskLoc& thisLoc, + virtual DiskLoc advance(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, int& keyOfs, int direction, const char* caller) const { - return thisLoc.btree<Version>()->advance(thisLoc, keyOfs, direction, caller); + return btreeState->getBucket<Version>(thisLoc)->advance(thisLoc, keyOfs, direction, caller); } - virtual long long fullValidate(const DiskLoc& thisLoc, const BSONObj& keyPattern) { - return thisLoc.btree<Version>()->fullValidate(thisLoc, keyPattern); + virtual long long fullValidate(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const BSONObj& keyPattern) { + return btreeState->getBucket<Version>(thisLoc)->fullValidate(thisLoc, keyPattern); } }; @@ -205,3 +204,4 @@ namespace mongo { BtreeInterface* BtreeInterface::interfaces[] = { &interface_v0, &interface_v1 }; } // namespace mongo + diff --git a/src/mongo/db/index/btree_interface.h b/src/mongo/db/index/btree_interface.h index 5af0cea2f25..9c468929920 100644 --- a/src/mongo/db/index/btree_interface.h +++ b/src/mongo/db/index/btree_interface.h @@ -28,12 +28,13 @@ #pragma once -#include "mongo/db/structure/btree/btree.h" #include "mongo/db/diskloc.h" #include "mongo/db/jsobj.h" namespace mongo { + class BtreeInMemoryState; + /** * We have two Btree on-disk formats which support identical operations. We hide this as much * as possible by having one implementation of this interface per format. @@ -50,63 +51,64 @@ namespace mongo { // was deleted. Calling code needs to be able to recognize this and possibly ignore it. static const int deletedBucketCode = 16738; - virtual int bt_insert(const DiskLoc thisLoc, + virtual int bt_insert(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, const DiskLoc recordLoc, const BSONObj& key, - const Ordering &order, - bool dupsAllowed, - IndexDetails& idx, - bool toplevel = true) const = 0; + bool dupsallowed, + bool toplevel = true) = 0; - virtual bool unindex(const DiskLoc thisLoc, - IndexDetails& id, + virtual bool unindex(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, const BSONObj& key, - const DiskLoc recordLoc) const = 0; + const DiskLoc recordLoc) = 0; - virtual DiskLoc locate(const IndexDetails& idx, + virtual DiskLoc locate(const BtreeInMemoryState* btreeState, const DiskLoc& thisLoc, const BSONObj& key, - const Ordering& order, - int& pos, - bool& found, - const DiskLoc& recordLoc, + int& pos, // out + bool& found, // out + const DiskLoc& recordLoc, // out int direction = 1) const = 0; - virtual bool wouldCreateDup(const IndexDetails& idx, + virtual bool wouldCreateDup(const BtreeInMemoryState* btreeState, const DiskLoc& thisLoc, const BSONObj& key, - const Ordering& order, const DiskLoc& self) const = 0; - virtual void customLocate(DiskLoc& locInOut, + virtual void customLocate(const BtreeInMemoryState* btreeState, + DiskLoc& locInOut, int& keyOfs, const BSONObj& keyBegin, int keyBeginLen, bool afterKey, const vector<const BSONElement*>& keyEnd, const vector<bool>& keyEndInclusive, - const Ordering& order, int direction, - pair<DiskLoc, int>& bestParent) = 0 ; + pair<DiskLoc, int>& bestParent) const = 0 ; - virtual void advanceTo(DiskLoc &thisLoc, + virtual void advanceTo(const BtreeInMemoryState* btreeState, + DiskLoc &thisLoc, int &keyOfs, const BSONObj &keyBegin, int keyBeginLen, bool afterKey, const vector<const BSONElement*>& keyEnd, const vector<bool>& keyEndInclusive, - const Ordering& order, int direction) const = 0; + int direction) const = 0; - virtual string dupKeyError(DiskLoc bucket, - const IndexDetails &idx, + virtual string dupKeyError(const BtreeInMemoryState* btreeState, + DiskLoc bucket, const BSONObj& keyObj) const =0; - virtual DiskLoc advance(const DiskLoc& thisLoc, + virtual DiskLoc advance(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, int& keyOfs, int direction, const char* caller) const = 0; - virtual long long fullValidate(const DiskLoc& thisLoc, const BSONObj& keyPattern) = 0; + virtual long long fullValidate(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const BSONObj& keyPattern) = 0; /** * These methods are here so that the BtreeCursor doesn't need to do any templating for the diff --git a/src/mongo/db/index/fts_access_method.cpp b/src/mongo/db/index/fts_access_method.cpp index e8a26644caa..766c1a6789a 100644 --- a/src/mongo/db/index/fts_access_method.cpp +++ b/src/mongo/db/index/fts_access_method.cpp @@ -31,14 +31,14 @@ namespace mongo { - FTSAccessMethod::FTSAccessMethod(IndexDescriptor* descriptor) - : BtreeBasedAccessMethod(descriptor), _ftsSpec(descriptor->infoObj()) { } + FTSAccessMethod::FTSAccessMethod(BtreeInMemoryState* btreeState) + : BtreeBasedAccessMethod(btreeState), _ftsSpec(btreeState->descriptor()->infoObj()) { } void FTSAccessMethod::getKeys(const BSONObj& obj, BSONObjSet* keys) { fts::FTSIndexFormat::getKeys(_ftsSpec, obj, keys); } - Status FTSAccessMethod::newCursor(IndexCursor** out) { + Status FTSAccessMethod::newCursor(IndexCursor** out) const { return Status::OK(); } diff --git a/src/mongo/db/index/fts_access_method.h b/src/mongo/db/index/fts_access_method.h index 95e841c8a1b..721b5f33b83 100644 --- a/src/mongo/db/index/fts_access_method.h +++ b/src/mongo/db/index/fts_access_method.h @@ -38,13 +38,13 @@ namespace mongo { class FTSAccessMethod : public BtreeBasedAccessMethod { public: - FTSAccessMethod(IndexDescriptor* descriptor); + FTSAccessMethod(BtreeInMemoryState* btreeState ); virtual ~FTSAccessMethod() { } // Not implemented: - virtual Status newCursor(IndexCursor** out); + virtual Status newCursor(IndexCursor** out) const; - fts::FTSSpec& getSpec() { return _ftsSpec; } + const fts::FTSSpec& getSpec() const { return _ftsSpec; } private: // Implemented: diff --git a/src/mongo/db/index/hash_access_method.cpp b/src/mongo/db/index/hash_access_method.cpp index ed8ac39defa..2752b061f74 100644 --- a/src/mongo/db/index/hash_access_method.cpp +++ b/src/mongo/db/index/hash_access_method.cpp @@ -37,8 +37,10 @@ namespace mongo { return BSONElementHasher::hash64(e, seed); } - HashAccessMethod::HashAccessMethod(IndexDescriptor* descriptor) - : BtreeBasedAccessMethod(descriptor) { + HashAccessMethod::HashAccessMethod(BtreeInMemoryState* btreeState) + : BtreeBasedAccessMethod(btreeState) { + + const IndexDescriptor* descriptor = btreeState->descriptor(); const string HASHED_INDEX_TYPE_IDENTIFIER = "hashed"; @@ -76,7 +78,7 @@ namespace mongo { _hashedField = firstElt.fieldName(); } - Status HashAccessMethod::newCursor(IndexCursor** out) { + Status HashAccessMethod::newCursor(IndexCursor** out) const { return Status(ErrorCodes::IllegalOperation, "Unimplemented seek called on hash"); } diff --git a/src/mongo/db/index/hash_access_method.h b/src/mongo/db/index/hash_access_method.h index 118c97a20f0..a93fa6a3964 100644 --- a/src/mongo/db/index/hash_access_method.h +++ b/src/mongo/db/index/hash_access_method.h @@ -45,10 +45,10 @@ namespace mongo { public: using BtreeBasedAccessMethod::_descriptor; - HashAccessMethod(IndexDescriptor* descriptor); + HashAccessMethod(BtreeInMemoryState* btreeState); virtual ~HashAccessMethod() { } - virtual Status newCursor(IndexCursor** out); + virtual Status newCursor(IndexCursor** out) const; // This is a NO-OP. virtual Status setOptions(const CursorOptions& options) { diff --git a/src/mongo/db/index/haystack_access_method.cpp b/src/mongo/db/index/haystack_access_method.cpp index 2678494ee2e..592a94f87c5 100644 --- a/src/mongo/db/index/haystack_access_method.cpp +++ b/src/mongo/db/index/haystack_access_method.cpp @@ -39,8 +39,10 @@ namespace mongo { static const string GEOSEARCHNAME = "geoHaystack"; - HaystackAccessMethod::HaystackAccessMethod(IndexDescriptor* descriptor) - : BtreeBasedAccessMethod(descriptor) { + HaystackAccessMethod::HaystackAccessMethod(BtreeInMemoryState* btreeState) + : BtreeBasedAccessMethod(btreeState) { + + const IndexDescriptor* descriptor = btreeState->descriptor(); BSONElement e = descriptor->getInfoElement("bucketSize"); uassert(16777, "need bucketSize", e.isNumber()); @@ -135,7 +137,7 @@ namespace mongo { keys->insert(buf.obj()); } - Status HaystackAccessMethod::newCursor(IndexCursor** out) { + Status HaystackAccessMethod::newCursor(IndexCursor** out) const { return Status(ErrorCodes::IllegalOperation, "Unimplemented seek called on Haystack"); } diff --git a/src/mongo/db/index/haystack_access_method.h b/src/mongo/db/index/haystack_access_method.h index 17a42cf7bb1..37c5d1a1270 100644 --- a/src/mongo/db/index/haystack_access_method.h +++ b/src/mongo/db/index/haystack_access_method.h @@ -55,11 +55,11 @@ namespace mongo { public: using BtreeBasedAccessMethod::_descriptor; - HaystackAccessMethod(IndexDescriptor* descriptor); + HaystackAccessMethod(BtreeInMemoryState* btreeState); virtual ~HaystackAccessMethod() { } // Not implemented. - virtual Status newCursor(IndexCursor** out); + virtual Status newCursor(IndexCursor** out) const; protected: friend class GeoHaystackSearchCommand; diff --git a/src/mongo/db/index/index_access_method.h b/src/mongo/db/index/index_access_method.h index 7f076751156..303b09d9ed2 100644 --- a/src/mongo/db/index/index_access_method.h +++ b/src/mongo/db/index/index_access_method.h @@ -108,7 +108,7 @@ namespace mongo { * Fills in '*out' with an IndexCursor. Return a status indicating success or reason of * failure. If the latter, '*out' contains NULL. See index_cursor.h for IndexCursor usage. */ - virtual Status newCursor(IndexCursor **out) = 0; + virtual Status newCursor(IndexCursor **out) const = 0; /** * Try to page-in the pages that contain the keys generated from 'obj'. diff --git a/src/mongo/db/index/index_descriptor.h b/src/mongo/db/index/index_descriptor.h index b91f6ea4c24..81e164c9a4f 100644 --- a/src/mongo/db/index/index_descriptor.h +++ b/src/mongo/db/index/index_descriptor.h @@ -148,7 +148,7 @@ namespace mongo { // Allow access to arbitrary fields in the per-index info object. Some indices stash // index-specific data there. - BSONElement getInfoElement(const string& name) { return _infoObj[name]; } + BSONElement getInfoElement(const string& name) const { return _infoObj[name]; } // // "Internals" of accessing the index, used by IndexAccessMethod(s). diff --git a/src/mongo/db/index/s2_access_method.cpp b/src/mongo/db/index/s2_access_method.cpp index b1a05012c62..11ceb4566ab 100644 --- a/src/mongo/db/index/s2_access_method.cpp +++ b/src/mongo/db/index/s2_access_method.cpp @@ -38,14 +38,16 @@ #include "mongo/db/jsobj.h" namespace mongo { - static int configValueWithDefault(IndexDescriptor *desc, const string& name, int def) { + static int configValueWithDefault(const IndexDescriptor *desc, const string& name, int def) { BSONElement e = desc->getInfoElement(name); if (e.isNumber()) { return e.numberInt(); } return def; } - S2AccessMethod::S2AccessMethod(IndexDescriptor *descriptor) - : BtreeBasedAccessMethod(descriptor) { + S2AccessMethod::S2AccessMethod(BtreeInMemoryState* btreeState) + : BtreeBasedAccessMethod(btreeState) { + + const IndexDescriptor* descriptor = btreeState->descriptor(); // Set up basic params. _params.maxKeysPerInsert = 200; @@ -83,7 +85,7 @@ namespace mongo { geoFields >= 1); } - Status S2AccessMethod::newCursor(IndexCursor** out) { + Status S2AccessMethod::newCursor(IndexCursor** out) const { return Status(ErrorCodes::IllegalOperation, "Unimplemented seek called on S2"); } diff --git a/src/mongo/db/index/s2_access_method.h b/src/mongo/db/index/s2_access_method.h index 3b661174cb9..5736d4cb8ce 100644 --- a/src/mongo/db/index/s2_access_method.h +++ b/src/mongo/db/index/s2_access_method.h @@ -43,10 +43,10 @@ namespace mongo { public: using BtreeBasedAccessMethod::_descriptor; - S2AccessMethod(IndexDescriptor* descriptor); + S2AccessMethod(BtreeInMemoryState* btreeState); virtual ~S2AccessMethod() { } - virtual Status newCursor(IndexCursor** out); + virtual Status newCursor(IndexCursor** out) const; private: friend class Geo2dFindNearCmd; diff --git a/src/mongo/db/index_builder.cpp b/src/mongo/db/index_builder.cpp index 571bb3048ee..f0fcc4b4739 100644 --- a/src/mongo/db/index_builder.cpp +++ b/src/mongo/db/index_builder.cpp @@ -29,6 +29,8 @@ #include "mongo/db/index_builder.h" #include "mongo/db/client.h" +#include "mongo/db/curop.h" +#include "mongo/db/database.h" #include "mongo/db/kill_current_op.h" #include "mongo/db/repl/rs.h" #include "mongo/util/mongoutils/str.h" diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp index 99421877a95..d214e0c0b96 100644 --- a/src/mongo/db/instance.cpp +++ b/src/mongo/db/instance.cpp @@ -50,6 +50,7 @@ #include "mongo/db/commands/fsync.h" #include "mongo/db/d_concurrency.h" #include "mongo/db/db.h" +#include "mongo/db/dbhelpers.h" #include "mongo/db/dbmessage.h" #include "mongo/db/dur_commitjob.h" #include "mongo/db/dur_journal.h" diff --git a/src/mongo/db/ops/count.cpp b/src/mongo/db/ops/count.cpp index 56f762d7516..b82cbcf5dd7 100644 --- a/src/mongo/db/ops/count.cpp +++ b/src/mongo/db/ops/count.cpp @@ -30,7 +30,9 @@ #include "mongo/db/ops/count.h" +#include "mongo/db/client.h" #include "mongo/db/clientcursor.h" +#include "mongo/db/pdfile.h" #include "mongo/db/query/get_runner.h" namespace mongo { diff --git a/src/mongo/db/ops/delete.cpp b/src/mongo/db/ops/delete.cpp index f664bdd8389..cb74a25b0d9 100644 --- a/src/mongo/db/ops/delete.cpp +++ b/src/mongo/db/ops/delete.cpp @@ -28,7 +28,9 @@ #include "mongo/db/ops/delete.h" +#include "mongo/db/client.h" #include "mongo/db/clientcursor.h" +#include "mongo/db/database.h" #include "mongo/db/namespace_details.h" #include "mongo/db/query/get_runner.h" #include "mongo/db/query/query_planner_common.h" diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp index 11c3f503151..2685c4826e3 100644 --- a/src/mongo/db/pipeline/pipeline_d.cpp +++ b/src/mongo/db/pipeline/pipeline_d.cpp @@ -32,13 +32,13 @@ #include "mongo/client/dbclientinterface.h" #include "mongo/db/instance.h" +#include "mongo/db/pdfile.h" #include "mongo/db/pipeline/document_source.h" #include "mongo/db/pipeline/pipeline.h" #include "mongo/db/query/get_runner.h" #include "mongo/db/query/query_planner.h" #include "mongo/s/d_logic.h" - namespace mongo { namespace { diff --git a/src/mongo/db/query/idhack_runner.cpp b/src/mongo/db/query/idhack_runner.cpp index b63fdae6bff..8f36336a687 100644 --- a/src/mongo/db/query/idhack_runner.cpp +++ b/src/mongo/db/query/idhack_runner.cpp @@ -32,8 +32,10 @@ #include "mongo/db/catalog/index_catalog.h" #include "mongo/db/diskloc.h" #include "mongo/db/exec/projection_exec.h" +#include "mongo/db/index/btree_access_method.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/jsobj.h" +#include "mongo/db/pdfile.h" #include "mongo/db/query/canonical_query.h" #include "mongo/db/query/type_explain.h" #include "mongo/db/query/plan_executor.h" @@ -58,23 +60,18 @@ namespace mongo { IndexCatalog* catalog = _collection->getIndexCatalog(); // Find the index we use. - IndexDescriptor* idDesc = catalog->findIdIndex(); + const IndexDescriptor* idDesc = catalog->findIdIndex(); if (NULL == idDesc) { _done = true; return Runner::RUNNER_EOF; } - // Create the key that we need to perform a lookup. - IndexDetails& id = idDesc->getOnDisk(); - BSONObj key = id.getKeyFromQuery(_query->getQueryObj()); + BtreeBasedAccessMethod* accessMethod = catalog->getBtreeBasedIndex( idDesc ); + + BSONObj key = _query->getQueryObj()["_id"].wrap(); // Look up the key by going directly to the Btree. - DiskLoc loc; - if (0 == id.version()) { - loc = id.head.btree<V0>()->findSingle(id, id.head, key); - } else { - loc = id.head.btree<V1>()->findSingle(id, id.head, key); - } + DiskLoc loc = accessMethod->findSingle( key ); _done = true; diff --git a/src/mongo/db/query/internal_plans.h b/src/mongo/db/query/internal_plans.h index c3c6397a44f..fe96e1a9930 100644 --- a/src/mongo/db/query/internal_plans.h +++ b/src/mongo/db/query/internal_plans.h @@ -86,7 +86,7 @@ namespace mongo { /** * Return an index scan. Caller owns returned pointer. */ - static Runner* indexScan(IndexDescriptor* descriptor, + static Runner* indexScan(const IndexDescriptor* descriptor, const BSONObj& startKey, const BSONObj& endKey, bool endKeyInclusive, Direction direction = FORWARD, int options = 0) { diff --git a/src/mongo/db/query/multi_plan_runner.cpp b/src/mongo/db/query/multi_plan_runner.cpp index fba46c98707..7f20c359634 100644 --- a/src/mongo/db/query/multi_plan_runner.cpp +++ b/src/mongo/db/query/multi_plan_runner.cpp @@ -28,10 +28,13 @@ #include "mongo/db/query/multi_plan_runner.h" +#include "mongo/db/client.h" +#include "mongo/db/database.h" #include "mongo/db/diskloc.h" #include "mongo/db/jsobj.h" #include "mongo/db/exec/plan_stage.h" #include "mongo/db/exec/working_set_common.h" +#include "mongo/db/pdfile.h" #include "mongo/db/query/canonical_query.h" #include "mongo/db/query/explain_plan.h" #include "mongo/db/query/plan_cache.h" diff --git a/src/mongo/db/query/stage_builder.cpp b/src/mongo/db/query/stage_builder.cpp index 764008d80a9..7042b7398ed 100644 --- a/src/mongo/db/query/stage_builder.cpp +++ b/src/mongo/db/query/stage_builder.cpp @@ -218,7 +218,8 @@ namespace mongo { return NULL; } IndexDescriptor* index = collection->getIndexCatalog()->getDescriptor(idxMatches[0]); - auto_ptr<FTSAccessMethod> fam(new FTSAccessMethod(index)); + const FTSAccessMethod* fam = + reinterpret_cast<FTSAccessMethod*>( collection->getIndexCatalog()->getIndex( index ) ); TextStageParams params(fam->getSpec()); params.ns = qsol.ns; diff --git a/src/mongo/db/repl/master_slave.cpp b/src/mongo/db/repl/master_slave.cpp index 1a251b76bab..78b5cc8195c 100644 --- a/src/mongo/db/repl/master_slave.cpp +++ b/src/mongo/db/repl/master_slave.cpp @@ -45,6 +45,7 @@ #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/cloner.h" #include "mongo/db/commands.h" +#include "mongo/db/dbhelpers.h" #include "mongo/db/instance.h" #include "mongo/db/ops/update.h" #include "mongo/db/query/internal_plans.h" diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 66b1fdf767c..a75e752fcc6 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -41,6 +41,7 @@ #include "mongo/db/auth/privilege.h" #include "mongo/db/commands.h" #include "mongo/db/commands/dbhash.h" +#include "mongo/db/dbhelpers.h" #include "mongo/db/index_builder.h" #include "mongo/db/instance.h" #include "mongo/db/namespace_string.h" @@ -599,7 +600,7 @@ namespace mongo { // thus this is not ideal. else { if (nsd == NULL || - (nsd->findIdIndex() >= 0 && Helpers::findById(nsd, updateCriteria).isNull()) || + (nsd->findIdIndex() >= 0 && Helpers::findById(collection, updateCriteria).isNull()) || // capped collections won't have an _id index (nsd->findIdIndex() < 0 && Helpers::findOne(ns, updateCriteria, false).isNull())) { failedUpdate = true; diff --git a/src/mongo/db/repl/oplogreader.h b/src/mongo/db/repl/oplogreader.h index cdde20baa3e..40979dc2538 100644 --- a/src/mongo/db/repl/oplogreader.h +++ b/src/mongo/db/repl/oplogreader.h @@ -33,10 +33,10 @@ #include "mongo/client/constants.h" #include "mongo/client/dbclientcursor.h" -#include "mongo/db/dbhelpers.h" namespace mongo { + extern const BSONObj reverseNaturalObj; // { $natural : -1 } /** * Authenticates conn using the server's cluster-membership credentials. * diff --git a/src/mongo/db/repl/rs.h b/src/mongo/db/repl/rs.h index 16b387a536b..88cdbe25e4c 100644 --- a/src/mongo/db/repl/rs.h +++ b/src/mongo/db/repl/rs.h @@ -738,7 +738,7 @@ namespace mongo { _hbinfo.health = 1.0; } - inline bool ignoreUniqueIndex(IndexDescriptor* idx) { + inline bool ignoreUniqueIndex(const IndexDescriptor* idx) { if (!idx->unique()) { return false; } diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp index 8017c965b53..e7ae16da52e 100644 --- a/src/mongo/db/repl/rs_rollback.cpp +++ b/src/mongo/db/repl/rs_rollback.cpp @@ -33,6 +33,7 @@ #include "mongo/db/auth/authorization_manager_global.h" #include "mongo/db/client.h" #include "mongo/db/cloner.h" +#include "mongo/db/dbhelpers.h" #include "mongo/db/ops/update.h" #include "mongo/db/ops/update_request.h" #include "mongo/db/ops/update_lifecycle_impl.h" diff --git a/src/mongo/db/repl/rs_sync.cpp b/src/mongo/db/repl/rs_sync.cpp index 89c6f4e8c52..c1f4be4e45b 100644 --- a/src/mongo/db/repl/rs_sync.cpp +++ b/src/mongo/db/repl/rs_sync.cpp @@ -35,6 +35,7 @@ #include "third_party/murmurhash3/MurmurHash3.h" #include "mongo/db/client.h" +#include "mongo/db/curop.h" #include "mongo/db/commands/fsync.h" #include "mongo/db/d_concurrency.h" #include "mongo/db/namespace_string.h" diff --git a/src/mongo/db/repl/sync.cpp b/src/mongo/db/repl/sync.cpp index 9c9e081f2b4..bc2c4445706 100644 --- a/src/mongo/db/repl/sync.cpp +++ b/src/mongo/db/repl/sync.cpp @@ -34,6 +34,7 @@ #include "mongo/db/client.h" #include "mongo/db/diskloc.h" #include "mongo/db/namespace_details.h" +#include "mongo/db/pdfile.h" #include "mongo/db/repl/oplogreader.h" #include "mongo/db/structure/collection.h" #include "mongo/util/assert_util.h" diff --git a/src/mongo/db/structure/btree/btree.cpp b/src/mongo/db/structure/btree/btree.cpp index 04e52aa6376..e279a92d5cc 100644 --- a/src/mongo/db/structure/btree/btree.cpp +++ b/src/mongo/db/structure/btree/btree.cpp @@ -34,6 +34,7 @@ #include "mongo/db/structure/btree/btree_stats.h" #include "mongo/db/structure/btree/btreebuilder.h" +#include "mongo/db/structure/btree/state-inl.h" #include "mongo/db/client.h" #include "mongo/db/clientcursor.h" #include "mongo/db/curop-inl.h" @@ -688,10 +689,12 @@ namespace mongo { } template< class V > - bool BtreeBucket<V>::exists(const IndexDetails& idx, const DiskLoc &thisLoc, const Key& key, const Ordering& order) const { + bool BtreeBucket<V>::exists(const BtreeInMemoryState* btreeState, + const DiskLoc &thisLoc, + const Key& key ) const { int pos; bool found; - DiskLoc b = locate(idx, thisLoc, key, order, pos, found, minDiskLoc); + DiskLoc b = locate(btreeState, thisLoc, key, pos, found, minDiskLoc); // skip unused keys while ( 1 ) { @@ -707,17 +710,17 @@ namespace mongo { } template< class V > - bool BtreeBucket<V>::wouldCreateDup( - const IndexDetails& idx, const DiskLoc &thisLoc, - const Key& key, const Ordering& order, - const DiskLoc &self) const { + bool BtreeBucket<V>::wouldCreateDup(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const Key& key, + const DiskLoc& self) const { int pos; bool found; - DiskLoc b = locate(idx, thisLoc, key, order, pos, found, minDiskLoc); + DiskLoc b = locate(btreeState, thisLoc, key, pos, found, minDiskLoc); while ( !b.isNull() ) { // we skip unused keys - const BtreeBucket *bucket = b.btree<V>(); + const BtreeBucket *bucket = btreeState->getBucket<V>( b ); const _KeyNode& kn = bucket->k(pos); if ( kn.isUsed() ) { if( bucket->keyAt(pos).woEqual(key) ) @@ -731,10 +734,10 @@ namespace mongo { } template< class V > - string BtreeBucket<V>::dupKeyError( const IndexDetails& idx , const Key& key ) { + string BtreeBucket<V>::dupKeyError( const IndexDescriptor* idx , const Key& key ) { stringstream ss; ss << "E11000 duplicate key error "; - ss << "index: " << idx.indexNamespace() << " "; + ss << "index: " << idx->indexNamespace() << " "; ss << "dup key: " << key.toString(); return ss.str(); } @@ -756,8 +759,11 @@ namespace mongo { bool guessIncreasing = false; template< class V > - bool BtreeBucket<V>::find(const IndexDetails& idx, const Key& key, const DiskLoc &rl, - const Ordering &order, int& pos, bool assertIfDup) const { + bool BtreeBucket<V>::find(const BtreeInMemoryState* btreeState, + const Key& key, + const DiskLoc &rl, + int& pos, + bool assertIfDup) const { Loc recordLoc; recordLoc = rl; globalIndexCounters->btree( reinterpret_cast<const char*>(this) ); @@ -772,7 +778,7 @@ namespace mongo { } while ( l <= h ) { KeyNode M = this->keyNode(m); - int x = key.woCompare(M.key, order); + int x = key.woCompare(M.key, btreeState->ordering()); if ( x == 0 ) { if( assertIfDup ) { if( k(m).isUnused() ) { @@ -781,9 +787,10 @@ namespace mongo { // coding effort in here to make this particularly fast if( !dupsChecked ) { dupsChecked = true; - if( idx.head.btree<V>()->exists(idx, idx.head, key, order) ) { - if( idx.head.btree<V>()->wouldCreateDup(idx, idx.head, key, order, recordLoc) ) - uasserted( ASSERT_ID_DUPKEY , dupKeyError( idx , key ) ); + DiskLoc head = btreeState->head(); + if( head.btree<V>()->exists(btreeState, head, key) ) { + if( head.btree<V>()->wouldCreateDup(btreeState, head, key, recordLoc) ) + uasserted( ASSERT_ID_DUPKEY , dupKeyError( btreeState->descriptor(), key ) ); else alreadyInIndex(); } @@ -792,7 +799,7 @@ namespace mongo { else { if( M.recordLoc == recordLoc ) alreadyInIndex(); - uasserted( ASSERT_ID_DUPKEY , dupKeyError( idx , key ) ); + uasserted( ASSERT_ID_DUPKEY, dupKeyError( btreeState->descriptor(), key ) ); } } @@ -816,9 +823,9 @@ namespace mongo { pos = l; if ( pos != this->n ) { Key keyatpos = keyNode(pos).key; - wassert( key.woCompare(keyatpos, order) <= 0 ); + wassert( key.woCompare(keyatpos, btreeState->ordering()) <= 0 ); if ( pos > 0 ) { - if( !( keyNode(pos-1).key.woCompare(key, order) <= 0 ) ) { + if( !( keyNode(pos-1).key.woCompare(key, btreeState->ordering()) <= 0 ) ) { DEV { log() << key.toString() << endl; log() << keyNode(pos-1).key.toString() << endl; @@ -832,7 +839,7 @@ namespace mongo { } template< class V > - void BtreeBucket<V>::delBucket(const DiskLoc thisLoc, const IndexDetails& id) { + void BtreeBucket<V>::delBucket(BtreeInMemoryState* btreeState, const DiskLoc thisLoc ) { BtreeIndexCursor::aboutToDeleteBucket(thisLoc); verify( !isHead() ); @@ -840,28 +847,23 @@ namespace mongo { const BtreeBucket *p = ll.btree<V>(); int parentIdx = indexInParent( thisLoc ); p->childForPos( parentIdx ).writing().Null(); - deallocBucket( thisLoc, id ); + deallocBucket( btreeState, thisLoc ); } template< class V > - void BtreeBucket<V>::deallocBucket(const DiskLoc thisLoc, const IndexDetails &id) { -#if 0 - // as a temporary defensive measure, we zap the whole bucket, AND don't truly delete - // it (meaning it is ineligible for reuse). - memset(this, 0, Size()); -#else + void BtreeBucket<V>::deallocBucket(BtreeInMemoryState* btreeState, const DiskLoc thisLoc ) { // Mark the bucket as deallocated, see SERVER-4575. this->n = this->INVALID_N_SENTINEL; // defensive: this->parent.Null(); - string ns = id.indexNamespace(); + string ns = btreeState->descriptor()->indexNamespace(); theDataFileMgr._deleteRecord(nsdetails(ns), ns.c_str(), thisLoc.rec(), thisLoc); -#endif } /** note: may delete the entire bucket! this invalid upon return sometimes. */ template< class V > - void BtreeBucket<V>::delKeyAtPos( const DiskLoc thisLoc, IndexDetails& id, int p, const Ordering &order) { + void BtreeBucket<V>::delKeyAtPos(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, int p ) { verify(this->n>0); DiskLoc left = this->childForPos(p); @@ -872,25 +874,25 @@ namespace mongo { // we don't delete the top bucket ever } else { - if ( !mayBalanceWithNeighbors( thisLoc, id, order ) ) { + if ( !mayBalanceWithNeighbors( btreeState, thisLoc ) ) { // An empty bucket is only allowed as a transient state. If // there are no neighbors to balance with, we delete ourself. // This condition is only expected in legacy btrees. - delBucket(thisLoc, id); + delBucket(btreeState, thisLoc); } } return; } - deleteInternalKey( thisLoc, p, id, order ); + deleteInternalKey( btreeState, thisLoc, p ); return; } if ( left.isNull() ) { this->_delKeyAtPos(p); - mayBalanceWithNeighbors( thisLoc, id, order ); + mayBalanceWithNeighbors( btreeState, thisLoc ); } else { - deleteInternalKey( thisLoc, p, id, order ); + deleteInternalKey( btreeState, thisLoc, p ); } } @@ -922,7 +924,9 @@ namespace mongo { * expected to mark a key as unused when handling a legacy btree. */ template< class V > - void BtreeBucket<V>::deleteInternalKey( const DiskLoc thisLoc, int keypos, IndexDetails &id, const Ordering &order ) { + void BtreeBucket<V>::deleteInternalKey(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + int keypos ) { DiskLoc lchild = this->childForPos( keypos ); DiskLoc rchild = this->childForPos( keypos + 1 ); verify( !lchild.isNull() || !rchild.isNull() ); @@ -944,8 +948,9 @@ namespace mongo { // Because advanceLoc is a descendant of thisLoc, updating thisLoc will // not affect packing or keys of advanceLoc and kn will be stable // during the following setInternalKey() - setInternalKey( thisLoc, keypos, kn.recordLoc, kn.key, order, this->childForPos( keypos ), this->childForPos( keypos + 1 ), id ); - advanceLoc.btreemod<V>()->delKeyAtPos( advanceLoc, id, advanceKeyOfs, order ); + setInternalKey( btreeState, thisLoc, keypos, kn.recordLoc, kn.key, + this->childForPos( keypos ), this->childForPos( keypos + 1 ) ); + advanceLoc.btreemod<V>()->delKeyAtPos( btreeState, advanceLoc, advanceKeyOfs ); } //#define BTREE(loc) (static_cast<DiskLoc>(loc).btree<V>()) @@ -954,11 +959,12 @@ namespace mongo { #define BTREEMOD(loc) (loc.template btreemod<V>()) template< class V > - void BtreeBucket<V>::replaceWithNextChild( const DiskLoc thisLoc, IndexDetails &id ) { + void BtreeBucket<V>::replaceWithNextChild( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc ) { verify( this->n == 0 && !this->nextChild.isNull() ); if ( this->parent.isNull() ) { - verify( id.head == thisLoc ); - id.head.writing() = this->nextChild; + verify( btreeState->head() == thisLoc ); + btreeState->setHead( this->nextChild ); } else { DiskLoc ll = this->parent; @@ -966,7 +972,7 @@ namespace mongo { } BTREE(this->nextChild)->parent.writing() = this->parent; BtreeIndexCursor::aboutToDeleteBucket(thisLoc); - deallocBucket( thisLoc, id ); + deallocBucket( btreeState, thisLoc ); } template< class V > @@ -1039,29 +1045,32 @@ namespace mongo { } template< class V > - void BtreeBucket<V>::doMergeChildren( const DiskLoc thisLoc, int leftIndex, IndexDetails &id, const Ordering &order ) { + void BtreeBucket<V>::doMergeChildren( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + int leftIndex ) { DiskLoc leftNodeLoc = this->childForPos( leftIndex ); DiskLoc rightNodeLoc = this->childForPos( leftIndex + 1 ); BtreeBucket *l = leftNodeLoc.btreemod<V>(); BtreeBucket *r = rightNodeLoc.btreemod<V>(); int pos = 0; - l->_packReadyForMod( order, pos ); - r->_packReadyForMod( order, pos ); // pack r in case there are droppable keys + l->_packReadyForMod( btreeState->ordering(), pos ); + r->_packReadyForMod( btreeState->ordering(), pos ); // pack r in case there are droppable keys // We know the additional keys below will fit in l because canMergeChildren() // must be true. int oldLNum = l->n; { + // left child's right child becomes old parent key's left child KeyNode kn = keyNode( leftIndex ); - l->pushBack( kn.recordLoc, kn.key, order, l->nextChild ); // left child's right child becomes old parent key's left child + l->pushBack( kn.recordLoc, kn.key, btreeState->ordering(), l->nextChild ); } for( int i = 0; i < r->n; ++i ) { KeyNode kn = r->keyNode( i ); - l->pushBack( kn.recordLoc, kn.key, order, kn.prevChildBucket ); + l->pushBack( kn.recordLoc, kn.key, btreeState->ordering(), kn.prevChildBucket ); } l->nextChild = r->nextChild; l->fixParentPtrs( leftNodeLoc, oldLNum ); - r->delBucket( rightNodeLoc, id ); + r->delBucket( btreeState, rightNodeLoc ); this->childForPos( leftIndex + 1 ) = leftNodeLoc; this->childForPos( leftIndex ) = DiskLoc(); this->_delKeyAtPos( leftIndex, true ); @@ -1069,11 +1078,11 @@ namespace mongo { // will trash this and thisLoc // TODO To ensure all leaves are of equal height, we should ensure // this is only called on the root. - replaceWithNextChild( thisLoc, id ); + replaceWithNextChild( btreeState, thisLoc ); } else { // balance recursively - maybe we should do this even when n == 0? - mayBalanceWithNeighbors( thisLoc, id, order ); + mayBalanceWithNeighbors( btreeState, thisLoc ); } } @@ -1101,21 +1110,23 @@ namespace mongo { } template< class V > - bool BtreeBucket<V>::tryBalanceChildren( const DiskLoc thisLoc, int leftIndex, IndexDetails &id, const Ordering &order ) const { + bool BtreeBucket<V>::tryBalanceChildren( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + int leftIndex ) const { // If we can merge, then we must merge rather than balance to preserve // bucket utilization constraints. if ( canMergeChildren( thisLoc, leftIndex ) ) { return false; } - thisLoc.btreemod<V>()->doBalanceChildren( thisLoc, leftIndex, id, order ); + thisLoc.btreemod<V>()->doBalanceChildren( btreeState, thisLoc, leftIndex ); return true; } template< class V > - void BtreeBucket<V>::doBalanceLeftToRight( const DiskLoc thisLoc, int leftIndex, int split, - BtreeBucket *l, const DiskLoc lchild, - BtreeBucket *r, const DiskLoc rchild, - IndexDetails &id, const Ordering &order ) { + void BtreeBucket<V>::doBalanceLeftToRight( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, int leftIndex, int split, + BtreeBucket *l, const DiskLoc lchild, + BtreeBucket *r, const DiskLoc rchild ) { // TODO maybe do some audits the same way pushBack() does? // As a precondition, rchild + the old separator are <= half a body size, // and lchild is at most completely full. Based on the value of split, @@ -1138,31 +1149,32 @@ namespace mongo { // Because lchild is a descendant of thisLoc, updating thisLoc will // not affect packing or keys of lchild and kn will be stable // during the following setInternalKey() - setInternalKey( thisLoc, leftIndex, kn.recordLoc, kn.key, order, lchild, rchild, id ); + setInternalKey( btreeState, thisLoc, leftIndex, kn.recordLoc, kn.key, lchild, rchild ); } int zeropos = 0; // lchild and rchild cannot be merged, so there must be >0 (actually more) // keys to the left of split. - l->truncateTo( split, order, zeropos ); + l->truncateTo( split, btreeState->ordering(), zeropos ); } template< class V > - void BtreeBucket<V>::doBalanceRightToLeft( const DiskLoc thisLoc, int leftIndex, int split, - BtreeBucket *l, const DiskLoc lchild, - BtreeBucket *r, const DiskLoc rchild, - IndexDetails &id, const Ordering &order ) { + void BtreeBucket<V>::doBalanceRightToLeft( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, int leftIndex, int split, + BtreeBucket *l, const DiskLoc lchild, + BtreeBucket *r, const DiskLoc rchild ) { // As a precondition, lchild + the old separator are <= half a body size, // and rchild is at most completely full. Based on the value of split, // lchild will get less than half of the total bytes which is at most 75% // of a full body. So lchild will have room for the following keys: int lN = l->n; { + // left child's right child becomes old parent key's left child KeyNode kn = keyNode( leftIndex ); - l->pushBack( kn.recordLoc, kn.key, order, l->nextChild ); // left child's right child becomes old parent key's left child + l->pushBack( kn.recordLoc, kn.key, btreeState->ordering(), l->nextChild ); } for( int i = 0; i < split - lN - 1; ++i ) { KeyNode kn = r->keyNode( i ); - l->pushBack( kn.recordLoc, kn.key, order, kn.prevChildBucket ); + l->pushBack( kn.recordLoc, kn.key, btreeState->ordering(), kn.prevChildBucket ); } { KeyNode kn = r->keyNode( split - lN - 1 ); @@ -1171,39 +1183,42 @@ namespace mongo { l->fixParentPtrs( lchild, lN + 1, l->n ); // Because rchild is a descendant of thisLoc, updating thisLoc will // not affect packing or keys of rchild and kn will be stable - // during the following setInternalKey() - setInternalKey( thisLoc, leftIndex, kn.recordLoc, kn.key, order, lchild, rchild, id ); + // during the following setInternalKey() + setInternalKey( btreeState, thisLoc, leftIndex, kn.recordLoc, kn.key, lchild, rchild ); } int zeropos = 0; // lchild and rchild cannot be merged, so there must be >0 (actually more) // keys to the right of split. - r->dropFront( split - lN, order, zeropos ); + r->dropFront( split - lN, btreeState->ordering(), zeropos ); } template< class V > - void BtreeBucket<V>::doBalanceChildren( const DiskLoc thisLoc, int leftIndex, IndexDetails &id, const Ordering &order ) { + void BtreeBucket<V>::doBalanceChildren( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + int leftIndex ) { DiskLoc lchild = this->childForPos( leftIndex ); DiskLoc rchild = this->childForPos( leftIndex + 1 ); int zeropos = 0; BtreeBucket *l = lchild.btreemod<V>(); - l->_packReadyForMod( order, zeropos ); + l->_packReadyForMod( btreeState->ordering(), zeropos ); BtreeBucket *r = rchild.btreemod<V>(); - r->_packReadyForMod( order, zeropos ); + r->_packReadyForMod( btreeState->ordering(), zeropos ); int split = rebalancedSeparatorPos( thisLoc, leftIndex ); // By definition, if we are below the low water mark and cannot merge // then we must actively balance. verify( split != l->n ); if ( split < l->n ) { - doBalanceLeftToRight( thisLoc, leftIndex, split, l, lchild, r, rchild, id, order ); + doBalanceLeftToRight( btreeState, thisLoc, leftIndex, split, l, lchild, r, rchild ); } else { - doBalanceRightToLeft( thisLoc, leftIndex, split, l, lchild, r, rchild, id, order ); + doBalanceRightToLeft( btreeState, thisLoc, leftIndex, split, l, lchild, r, rchild ); } } template< class V > - bool BtreeBucket<V>::mayBalanceWithNeighbors( const DiskLoc thisLoc, IndexDetails &id, const Ordering &order ) const { + bool BtreeBucket<V>::mayBalanceWithNeighbors(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc ) { if ( this->parent.isNull() ) { // we are root, there are no neighbors return false; } @@ -1223,21 +1238,21 @@ namespace mongo { // to preserve btree bucket utilization constraints since that's a more // heavy duty operation (especially if we must re-split later). if ( mayBalanceRight && - p->tryBalanceChildren( this->parent, parentIdx, id, order ) ) { + p->tryBalanceChildren( btreeState, this->parent, parentIdx) ) { return true; } if ( mayBalanceLeft && - p->tryBalanceChildren( this->parent, parentIdx - 1, id, order ) ) { + p->tryBalanceChildren( btreeState, this->parent, parentIdx - 1 ) ) { return true; } BtreeBucket *pm = BTREEMOD(this->parent); if ( mayBalanceRight ) { - pm->doMergeChildren( this->parent, parentIdx, id, order ); + pm->doMergeChildren( btreeState, this->parent, parentIdx ); return true; } else if ( mayBalanceLeft ) { - pm->doMergeChildren( this->parent, parentIdx - 1, id, order ); + pm->doMergeChildren( btreeState, this->parent, parentIdx - 1 ); return true; } @@ -1246,13 +1261,15 @@ namespace mongo { /** remove a key from the index */ template< class V > - bool BtreeBucket<V>::unindex(const DiskLoc thisLoc, IndexDetails& id, const BSONObj& key, const DiskLoc recordLoc ) const { + bool BtreeBucket<V>::unindex(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + const BSONObj& key, + const DiskLoc recordLoc) const { int pos; bool found; - const Ordering ord = Ordering::make(id.keyPattern()); - DiskLoc loc = locate(id, thisLoc, key, ord, pos, found, recordLoc, 1); + DiskLoc loc = locate(btreeState, thisLoc, key, pos, found, recordLoc, 1); if ( found ) { - loc.btreemod<V>()->delKeyAtPos(loc, id, pos, ord); + loc.btreemod<V>()->delKeyAtPos(btreeState, loc, pos); return true; } return false; @@ -1283,9 +1300,13 @@ namespace mongo { } template< class V > - void BtreeBucket<V>::setInternalKey( const DiskLoc thisLoc, int keypos, - const DiskLoc recordLoc, const Key &key, const Ordering &order, - const DiskLoc lchild, const DiskLoc rchild, IndexDetails &idx ) { + void BtreeBucket<V>::setInternalKey( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + int keypos, + const DiskLoc recordLoc, + const Key &key, + const DiskLoc lchild, + const DiskLoc rchild ) { this->childForPos( keypos ).Null(); // This may leave the bucket empty (n == 0) which is ok only as a @@ -1300,7 +1321,7 @@ namespace mongo { // Just set temporarily - required to pass validation in insertHere() this->childForPos( keypos ) = lchild; - insertHere( thisLoc, keypos, recordLoc, key, order, lchild, rchild, idx ); + insertHere(btreeState, thisLoc, keypos, recordLoc, key, lchild, rchild ); } /** @@ -1313,16 +1334,17 @@ namespace mongo { * the optimized write intent code in basicInsert(). */ template< class V > - void BtreeBucket<V>::insertHere( const DiskLoc thisLoc, int keypos, - const DiskLoc recordLoc, const Key& key, const Ordering& order, - const DiskLoc lchild, const DiskLoc rchild, IndexDetails& idx) const { + void BtreeBucket<V>::insertHere( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, int keypos, + const DiskLoc recordLoc, const Key& key, + const DiskLoc lchild, const DiskLoc rchild ) const { if ( insert_debug ) out() << " " << thisLoc.toString() << ".insertHere " << key.toString() << '/' << recordLoc.toString() << ' ' << lchild.toString() << ' ' << rchild.toString() << " keypos:" << keypos << endl; - if ( !this->basicInsert(thisLoc, keypos, recordLoc, key, order) ) { + if ( !this->basicInsert(thisLoc, keypos, recordLoc, key, btreeState->ordering()) ) { // If basicInsert() fails, the bucket will be packed as required by split(). - thisLoc.btreemod<V>()->split(thisLoc, keypos, recordLoc, key, order, lchild, rchild, idx); + thisLoc.btreemod<V>()->split(btreeState, thisLoc, keypos, recordLoc, key, lchild, rchild ); return; } @@ -1332,7 +1354,7 @@ namespace mongo { if ( keypos+1 == this->n ) { // last key if ( this->nextChild != lchild ) { out() << "ERROR nextChild != lchild" << endl; - out() << " thisLoc: " << thisLoc.toString() << ' ' << idx.indexNamespace() << endl; + out() << " thisLoc: " << thisLoc.toString() << ' ' << btreeState->descriptor()->indexNamespace() << endl; out() << " keyPos: " << keypos << " n:" << this->n << endl; out() << " nextChild: " << this->nextChild.toString() << " lchild: " << lchild.toString() << endl; out() << " recordLoc: " << recordLoc.toString() << " rchild: " << rchild.toString() << endl; @@ -1350,7 +1372,7 @@ namespace mongo { kn->prevChildBucket = lchild; if ( k(keypos+1).prevChildBucket != lchild ) { out() << "ERROR k(keypos+1).prevChildBucket != lchild" << endl; - out() << " thisLoc: " << thisLoc.toString() << ' ' << idx.indexNamespace() << endl; + out() << " thisLoc: " << thisLoc.toString() << ' ' << btreeState->descriptor()->indexNamespace() << endl; out() << " keyPos: " << keypos << " n:" << this->n << endl; out() << " k(keypos+1).pcb: " << k(keypos+1).prevChildBucket.toString() << " lchild: " << lchild.toString() << endl; out() << " recordLoc: " << recordLoc.toString() << " rchild: " << rchild.toString() << endl; @@ -1368,23 +1390,26 @@ namespace mongo { } template< class V > - void BtreeBucket<V>::split(const DiskLoc thisLoc, int keypos, const DiskLoc recordLoc, const Key& key, const Ordering& order, const DiskLoc lchild, const DiskLoc rchild, IndexDetails& idx) { + void BtreeBucket<V>::split(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, int keypos, + const DiskLoc recordLoc, const Key& key, + const DiskLoc lchild, const DiskLoc rchild) { this->assertWritable(); if ( split_debug ) out() << " " << thisLoc.toString() << ".split" << endl; int split = this->splitPos( keypos ); - DiskLoc rLoc = addBucket(idx); + DiskLoc rLoc = addBucket(btreeState); BtreeBucket *r = rLoc.btreemod<V>(); if ( split_debug ) out() << " split:" << split << ' ' << keyNode(split).key.toString() << " n:" << this->n << endl; for ( int i = split+1; i < this->n; i++ ) { KeyNode kn = keyNode(i); - r->pushBack(kn.recordLoc, kn.key, order, kn.prevChildBucket); + r->pushBack(kn.recordLoc, kn.key, btreeState->ordering(), kn.prevChildBucket); } r->nextChild = this->nextChild; - r->assertValid( order ); + r->assertValid( btreeState->ordering() ); if ( split_debug ) out() << " new rLoc:" << rLoc.toString() << endl; @@ -1401,16 +1426,17 @@ namespace mongo { // Because thisLoc is a descendant of parent, updating parent will // not affect packing or keys of thisLoc and splitkey will be stable // during the following: - + // promote splitkey to a parent this->node if ( this->parent.isNull() ) { // make a new parent if we were the root - DiskLoc L = addBucket(idx); + DiskLoc L = addBucket(btreeState); BtreeBucket *p = L.btreemod<V>(); - p->pushBack(splitkey.recordLoc, splitkey.key, order, thisLoc); + p->pushBack(splitkey.recordLoc, splitkey.key, btreeState->ordering(), thisLoc); p->nextChild = rLoc; - p->assertValid( order ); - this->parent = idx.head.writing() = L; + p->assertValid( btreeState->ordering() ); + this->parent = L; + btreeState->setHead( L ); if ( split_debug ) out() << " we were root, making new root:" << hex << this->parent.getOfs() << dec << endl; rLoc.btree<V>()->parent.writing() = this->parent; @@ -1420,25 +1446,25 @@ namespace mongo { rLoc.btree<V>()->parent.writing() = this->parent; if ( split_debug ) out() << " promoting splitkey key " << splitkey.key.toString() << endl; - BTREE(this->parent)->_insert(this->parent, splitkey.recordLoc, splitkey.key, order, /*dupsallowed*/true, thisLoc, rLoc, idx); + BTREE(this->parent)->_insert(btreeState, this->parent, splitkey.recordLoc, splitkey.key, /*dupsallowed*/true, thisLoc, rLoc ); } } int newpos = keypos; // note this may trash splitkey.key. thus we had to promote it before finishing up here. - this->truncateTo(split, order, newpos); + this->truncateTo(split, btreeState->ordering(), newpos); // add our this->new key, there is room this->now { if ( keypos <= split ) { if ( split_debug ) out() << " keypos<split, insertHere() the new key" << endl; - insertHere(thisLoc, newpos, recordLoc, key, order, lchild, rchild, idx); + insertHere(btreeState, thisLoc, newpos, recordLoc, key, lchild, rchild ); } else { int kp = keypos-split-1; verify(kp>=0); - BTREE(rLoc)->insertHere(rLoc, kp, recordLoc, key, order, lchild, rchild, idx); + BTREE(rLoc)->insertHere(btreeState, rLoc, kp, recordLoc, key, lchild, rchild ); } } @@ -1448,8 +1474,8 @@ namespace mongo { /** start a new index off, empty */ template< class V > - DiskLoc BtreeBucket<V>::addBucket(const IndexDetails& id) { - string ns = id.indexNamespace(); + DiskLoc BtreeBucket<V>::addBucket(BtreeInMemoryState* btreeState) { + string ns = btreeState->descriptor()->indexNamespace(); DiskLoc loc = theDataFileMgr.insert(ns.c_str(), 0, V::BucketSize, false, true); BtreeBucket *b = BTREEMOD(loc); b->init(); @@ -1515,15 +1541,27 @@ namespace mongo { } template< class V > - DiskLoc BtreeBucket<V>::locate(const IndexDetails& idx, const DiskLoc& thisLoc, const BSONObj& key, const Ordering &order, int& pos, bool& found, const DiskLoc &recordLoc, int direction) const { + DiskLoc BtreeBucket<V>::locate(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const BSONObj& key, + int& pos, + bool& found, + const DiskLoc& recordLoc, + int direction) const { KeyOwned k(key); - return locate(idx, thisLoc, k, order, pos, found, recordLoc, direction); + return locate(btreeState, thisLoc, k, pos, found, recordLoc, direction); } template< class V > - DiskLoc BtreeBucket<V>::locate(const IndexDetails& idx, const DiskLoc& thisLoc, const Key& key, const Ordering &order, int& pos, bool& found, const DiskLoc &recordLoc, int direction) const { + DiskLoc BtreeBucket<V>::locate(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const Key& key, + int& pos, + bool& found, + const DiskLoc& recordLoc, + int direction) const { int p; - found = find(idx, key, recordLoc, order, p, /*assertIfDup*/ false); + found = find(btreeState, key, recordLoc, p, /*assertIfDup*/ false); if ( found ) { pos = p; return thisLoc; @@ -1532,7 +1570,7 @@ namespace mongo { DiskLoc child = this->childForPos(p); if ( !child.isNull() ) { - DiskLoc l = BTREE(child)->locate(idx, child, key, order, pos, found, recordLoc, direction); + DiskLoc l = BTREE(child)->locate(btreeState, child, key, pos, found, recordLoc, direction); if ( !l.isNull() ) return l; } @@ -1585,7 +1623,18 @@ namespace mongo { * All the direction checks below allowed me to refactor the code, but possibly separate forward and reverse implementations would be more efficient */ template< class V > - void BtreeBucket<V>::advanceTo(DiskLoc &thisLoc, int &keyOfs, const BSONObj &keyBegin, int keyBeginLen, bool afterKey, const vector< const BSONElement * > &keyEnd, const vector< bool > &keyEndInclusive, const Ordering &order, int direction ) const { + void BtreeBucket<V>::advanceTo(const BtreeInMemoryState* btreeState, + DiskLoc &thisLoc, + int &keyOfs, + const BSONObj &keyBegin, + int keyBeginLen, + bool afterKey, + const vector<const BSONElement*>& keyEnd, + const vector<bool>& keyEndInclusive, + int direction) const { + + const Ordering& order = btreeState->ordering(); + int l,h; bool dontGoUp; if ( direction > 0 ) { @@ -1621,7 +1670,7 @@ namespace mongo { } } } - customLocate( thisLoc, keyOfs, keyBegin, keyBeginLen, afterKey, keyEnd, keyEndInclusive, order, direction, bestParent ); + customLocate(btreeState, thisLoc, keyOfs, keyBegin, keyBeginLen, afterKey, keyEnd, keyEndInclusive, direction, bestParent ); } /** @param thisLoc in/out param. perhaps thisLoc isn't the best name given that. @@ -1636,9 +1685,17 @@ namespace mongo { as advanceTo. */ template< class V > - void BtreeBucket<V>::customLocate(DiskLoc &locInOut, int &keyOfs, const BSONObj &keyBegin, int keyBeginLen, bool afterKey, - const vector< const BSONElement * > &keyEnd, const vector< bool > &keyEndInclusive, - const Ordering &order, int direction, pair< DiskLoc, int > &bestParent ) { + void BtreeBucket<V>::customLocate(const BtreeInMemoryState* btreeState, + DiskLoc& locInOut, + int& keyOfs, + const BSONObj& keyBegin, + int keyBeginLen, bool afterKey, + const vector<const BSONElement*>& keyEnd, + const vector<bool>& keyEndInclusive, + int direction, + pair<DiskLoc, int>& bestParent) { + const Ordering& order = btreeState->ordering(); + dassert( direction == 1 || direction == -1 ); const BtreeBucket<V> *bucket = BTREE(locInOut); if ( bucket->n == 0 ) { @@ -1711,13 +1768,14 @@ namespace mongo { /** @thisLoc disk location of *this */ template< class V > - int BtreeBucket<V>::_insert(const DiskLoc thisLoc, const DiskLoc recordLoc, - const Key& key, const Ordering &order, bool dupsAllowed, - const DiskLoc lChild, const DiskLoc rChild, IndexDetails& idx) const { + int BtreeBucket<V>::_insert(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, const DiskLoc recordLoc, + const Key& key, bool dupsAllowed, + const DiskLoc lChild, const DiskLoc rChild ) const { if ( key.dataSize() > getKeyMax() ) { string msg = str::stream() << "ERROR: key too large len:" << key.dataSize() << " max:" << getKeyMax() << ' ' << key.dataSize() - << ' ' << idx.indexNamespace(); + << ' ' << btreeState->descriptor()->indexNamespace(); problem() << msg << endl; if ( isMaster( NULL ) ) { uasserted( 17281, msg ); @@ -1726,7 +1784,7 @@ namespace mongo { verify( key.dataSize() > 0 ); int pos; - bool found = find(idx, key, recordLoc, order, pos, !dupsAllowed); + bool found = find(btreeState, key, recordLoc, pos, !dupsAllowed); if ( insert_debug ) { out() << " " << thisLoc.toString() << '.' << "_insert " << key.toString() << '/' << recordLoc.toString() << @@ -1746,7 +1804,7 @@ namespace mongo { DEV { log() << "_insert(): key already exists in index (ok for background:true)\n"; - log() << " " << idx.indexNamespace() << " thisLoc:" << thisLoc.toString() << '\n'; + log() << " " << btreeState->descriptor()->indexNamespace() << " thisLoc:" << thisLoc.toString() << '\n'; log() << " " << key.toString() << '\n'; log() << " " << "recordLoc:" << recordLoc.toString() << " pos:" << pos << endl; log() << " old l r: " << this->childForPos(pos).toString() << ' ' << this->childForPos(pos+1).toString() << endl; @@ -1765,11 +1823,11 @@ namespace mongo { // is called currently. if ( child.isNull() || !rChild.isNull() ) { // A new key will be inserted at the same tree height as an adjacent existing key. - insertHere(thisLoc, pos, recordLoc, key, order, lChild, rChild, idx); + insertHere(btreeState, thisLoc, pos, recordLoc, key, lChild, rChild); return 0; } - return child.btree<V>()->_insert(child, recordLoc, key, order, dupsAllowed, /*lchild*/DiskLoc(), /*rchild*/DiskLoc(), idx); + return child.btree<V>()->_insert(btreeState, child, recordLoc, key, dupsAllowed, /*lchild*/DiskLoc(), /*rchild*/DiskLoc() ); } template< class V > @@ -1792,19 +1850,21 @@ namespace mongo { /** todo: meaning of return code unclear clean up */ template< class V > - int BtreeBucket<V>::bt_insert(const DiskLoc thisLoc, const DiskLoc recordLoc, - const BSONObj& _key, const Ordering &order, bool dupsAllowed, - IndexDetails& idx, bool toplevel) const - { - guessIncreasing = _key.firstElementType() == jstOID && idx.isIdIndex(); - KeyOwned key(_key); + int BtreeBucket<V>::bt_insert(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + const DiskLoc recordLoc, + const BSONObj& keyBson, + bool dupsAllowed, + bool toplevel) const { + guessIncreasing = keyBson.firstElementType() == jstOID && btreeState->descriptor()->isIdIndex(); + KeyOwned key(keyBson); dassert(toplevel); if ( toplevel ) { if ( key.dataSize() > getKeyMax() ) { string msg = str::stream() << "Btree::insert: key too large to index, failing " - << idx.indexNamespace() << ' ' << key.dataSize() << ' ' - << key.toString(); + << btreeState->descriptor()->indexNamespace() << ' ' + << key.dataSize() << ' ' << key.toString(); problem() << msg << endl; if ( isMaster( NULL ) ) { uasserted( 17280, msg ); @@ -1814,10 +1874,10 @@ namespace mongo { int x; try { - x = _insert(thisLoc, recordLoc, key, order, dupsAllowed, DiskLoc(), DiskLoc(), idx); - this->assertValid( order ); + x = _insert(btreeState, thisLoc, recordLoc, key, dupsAllowed, DiskLoc(), DiskLoc() ); + this->assertValid( btreeState->ordering() ); } - catch( ... ) { + catch( ... ) { guessIncreasing = false; throw; } @@ -1836,13 +1896,14 @@ namespace mongo { } template< class V > - DiskLoc BtreeBucket<V>::findSingle( const IndexDetails& indexdetails , const DiskLoc& thisLoc, const BSONObj& key ) const { + DiskLoc BtreeBucket<V>::findSingle( const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const BSONObj& key ) const { int pos; bool found; - // TODO: is it really ok here that the order is a default? + // TODO: is it really ok here that the order is a default? // for findById() use, yes. for checkNoIndexConflicts, no? - Ordering o = Ordering::make(BSONObj()); - DiskLoc bucket = locate( indexdetails , indexdetails.head , key , o , pos , found , minDiskLoc ); + DiskLoc bucket = locate( btreeState, btreeState->head(), key, pos, found, minDiskLoc ); if ( bucket.isNull() ) return bucket; @@ -1857,54 +1918,11 @@ namespace mongo { b = bucket.btree<V>(); } KeyNode kn = b->keyNode( pos ); - if ( KeyOwned(key).woCompare( kn.key, o ) != 0 ) + if ( KeyOwned(key).woCompare( kn.key, btreeState->ordering() ) != 0 ) return DiskLoc(); return kn.recordLoc; } - template< class V > - void BtreeBucket<V>::a_test(IndexDetails& id) { - BtreeBucket *b = id.head.btreemod<V>(); - - // record locs for testing - DiskLoc A(1, 20); - DiskLoc B(1, 30); - DiskLoc C(1, 40); - - DiskLoc rl; - BSONObj key = fromjson("{x:9}"); - BSONObj orderObj = fromjson("{}"); - Ordering order = Ordering::make(orderObj); - - b->bt_insert(id.head, A, key, order, true, id); - A.GETOFS() += 2; - b->bt_insert(id.head, A, key, order, true, id); - A.GETOFS() += 2; - b->bt_insert(id.head, A, key, order, true, id); - A.GETOFS() += 2; - b->bt_insert(id.head, A, key, order, true, id); - A.GETOFS() += 2; - verify( b->k(0).isUsed() ); -// b->k(0).setUnused(); - b->k(1).setUnused(); - b->k(2).setUnused(); - b->k(3).setUnused(); - - b->dumpTree(id.head, orderObj); - - /* b->bt_insert(id.head, B, key, order, false, id); - b->k(1).setUnused(); - b->dumpTree(id.head, order); - b->bt_insert(id.head, A, key, order, false, id); - b->dumpTree(id.head, order); - */ - - // this should assert. does it? (it might "accidentally" though, not asserting proves a problem, asserting proves nothing) - b->bt_insert(id.head, C, key, order, false, id); - - // b->dumpTree(id.head, order); - } - template class BucketBasics<V0>; template class BucketBasics<V1>; template class BtreeBucket<V0>; @@ -1935,3 +1953,4 @@ namespace mongo { } } btunittest; } + diff --git a/src/mongo/db/structure/btree/btree.h b/src/mongo/db/structure/btree/btree.h index 953b24072e8..825824199f5 100644 --- a/src/mongo/db/structure/btree/btree.h +++ b/src/mongo/db/structure/btree/btree.h @@ -39,6 +39,9 @@ namespace mongo { + class BtreeInMemoryState; + class IndexDescriptor; + /** * Our btree implementation generally follows the standard btree algorithm, * which is described in many places. The nodes of our btree are referred to @@ -666,17 +669,17 @@ namespace mongo { * likewise below in bt_insert() etc. */ private: - bool exists(const IndexDetails& idx, const DiskLoc &thisLoc, const Key& key, const Ordering& order) const; + bool exists(const BtreeInMemoryState* btreeState, const DiskLoc &thisLoc, const Key& key ) const; public: /** * @param self - Don't complain about ourself already being in the index case. * @return true = There is a duplicate used key. */ - bool wouldCreateDup( - const IndexDetails& idx, const DiskLoc &thisLoc, - const Key& key, const Ordering& order, - const DiskLoc &self) const; + bool wouldCreateDup(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const Key& key, + const DiskLoc& self) const; /** * Preconditions: none @@ -684,7 +687,7 @@ namespace mongo { * and init()-ed. This bucket is suitable to for use as a new root * or any other new node in the tree. */ - static DiskLoc addBucket(const IndexDetails&); + static DiskLoc addBucket(BtreeInMemoryState* btreeState); /** * Preconditions: none @@ -693,7 +696,7 @@ namespace mongo { * deallocated from pdfile storage. * - The memory at thisLoc is invalidated, and 'this' is invalidated. */ - void deallocBucket(const DiskLoc thisLoc, const IndexDetails &id); + void deallocBucket(BtreeInMemoryState* btreeState, const DiskLoc thisLoc ); /** * Preconditions: @@ -709,10 +712,12 @@ namespace mongo { * and @return 0. The root of the btree may be changed, so * 'this'/thisLoc may no longer be the root upon return. */ - int bt_insert(const DiskLoc thisLoc, const DiskLoc recordLoc, - const BSONObj& key, const Ordering &order, bool dupsAllowed, - IndexDetails& idx, bool toplevel = true) const; - + int bt_insert(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + const DiskLoc recordLoc, + const BSONObj& key, + bool dupsallowed, + bool toplevel) const; /** * Preconditions: * - 'key' has a valid schema for this index, and may have objsize() > KeyMax. @@ -722,7 +727,10 @@ namespace mongo { * invalidate 'this' / thisLoc and change the head. * - If key / recordLoc are not in the btree, @return false and do nothing. */ - bool unindex(const DiskLoc thisLoc, IndexDetails& id, const BSONObj& key, const DiskLoc recordLoc) const; + bool unindex(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + const BSONObj& key, + const DiskLoc recordLoc) const; /** * locate may return an "unused" key that is just a marker. so be careful. @@ -731,10 +739,21 @@ namespace mongo { * @found - returns true if exact match found. note you can get back a position * result even if found is false. */ - DiskLoc locate(const IndexDetails &idx , const DiskLoc& thisLoc, const BSONObj& key, const Ordering &order, - int& pos, bool& found, const DiskLoc &recordLoc, int direction=1) const; - DiskLoc locate(const IndexDetails &idx , const DiskLoc& thisLoc, const Key& key, const Ordering &order, - int& pos, bool& found, const DiskLoc &recordLoc, int direction=1) const; + DiskLoc locate(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const BSONObj& key, + int& pos, + bool& found, + const DiskLoc& recordLoc, + int direction=1) const; + + DiskLoc locate(const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const Key& key, + int& pos, + bool& found, + const DiskLoc& recordLoc, + int direction=1) const; /** * find the first instance of the key @@ -743,7 +762,9 @@ namespace mongo { * findSingle code. * @return the record location of the first match */ - DiskLoc findSingle( const IndexDetails &indexdetails , const DiskLoc& thisLoc, const BSONObj& key ) const; + DiskLoc findSingle( const BtreeInMemoryState* btreeState, + const DiskLoc& thisLoc, + const BSONObj& key ) const; /** * Advance to next or previous key in the index. @@ -752,10 +773,26 @@ namespace mongo { DiskLoc advance(const DiskLoc& thisLoc, int& keyOfs, int direction, const char *caller) const; /** Advance in specified direction to the specified key */ - void advanceTo(DiskLoc &thisLoc, int &keyOfs, const BSONObj &keyBegin, int keyBeginLen, bool afterKey, const vector< const BSONElement * > &keyEnd, const vector< bool > &keyEndInclusive, const Ordering &order, int direction ) const; + void advanceTo(const BtreeInMemoryState* btreeState, + DiskLoc &thisLoc, + int &keyOfs, + const BSONObj &keyBegin, + int keyBeginLen, + bool afterKey, + const vector<const BSONElement*>& keyEnd, + const vector<bool>& keyEndInclusive, + int direction) const; /** Locate a key with fields comprised of a combination of keyBegin fields and keyEnd fields. */ - static void customLocate(DiskLoc &locInOut, int &keyOfs, const BSONObj &keyBegin, int keyBeginLen, bool afterKey, const vector< const BSONElement * > &keyEnd, const vector< bool > &keyEndInclusive, const Ordering &order, int direction, pair< DiskLoc, int > &bestParent ) ; + static void customLocate(const BtreeInMemoryState* btreeState, + DiskLoc& locInOut, + int& keyOfs, + const BSONObj& keyBegin, + int keyBeginLen, bool afterVersion, + const vector<const BSONElement*>& keyEnd, + const vector<bool>& keyEndInclusive, + int direction, + pair<DiskLoc, int>& bestParent); /** @return head of the btree by traversing from current bucket. */ const DiskLoc getHead(const DiskLoc& thisLoc) const; @@ -763,8 +800,6 @@ namespace mongo { /** get tree shape */ void shape(stringstream&) const; - static void a_test(IndexDetails&); - static int getKeyMax(); protected: @@ -788,7 +823,7 @@ namespace mongo { * - This bucket is deallocated from pdfile storage. * - 'this' and thisLoc are invalidated. */ - void delBucket(const DiskLoc thisLoc, const IndexDetails&); + void delBucket(BtreeInMemoryState* btreeState, const DiskLoc thisLoc ); /** * Preconditions: 0 <= p < n @@ -797,7 +832,9 @@ namespace mongo { * - 'this' and thisLoc may be invalidated. * - The tree head may change. */ - void delKeyAtPos(const DiskLoc thisLoc, IndexDetails& id, int p, const Ordering &order); + void delKeyAtPos(BtreeInMemoryState* btreeSate, + const DiskLoc thisLoc, + int p ); /** * Preconditions: @@ -809,7 +846,7 @@ namespace mongo { * or merge with them and return true. Also, 'this' and thisLoc may * be invalidated and the tree head may change. */ - bool mayBalanceWithNeighbors(const DiskLoc thisLoc, IndexDetails &id, const Ordering &order) const; + bool mayBalanceWithNeighbors(BtreeInMemoryState* btreeState, const DiskLoc thisLoc); /** * Preconditions: @@ -822,7 +859,7 @@ namespace mongo { * - Otherwise, balance keys between the leftIndex child and the * leftIndex + 1 child, return true, and possibly change the tree head. */ - bool tryBalanceChildren( const DiskLoc thisLoc, int leftIndex, IndexDetails &id, const Ordering &order ) const; + bool tryBalanceChildren(BtreeInMemoryState* btreeState, const DiskLoc thisLoc, int leftIndex) const; /** * Preconditions: @@ -833,7 +870,7 @@ namespace mongo { * child such that neither child has fewer than lowWaterMark bytes. * The tree head may change. */ - void doBalanceChildren( const DiskLoc thisLoc, int leftIndex, IndexDetails &id, const Ordering &order ); + void doBalanceChildren( BtreeInMemoryState* btreeState, const DiskLoc thisLoc, int leftIndex ); /** * Preconditions: @@ -847,10 +884,10 @@ namespace mongo { * The previous key in thisLoc at index leftIndex and all keys with * indexes greater than split in lchild are moved to rchild. */ - void doBalanceLeftToRight( const DiskLoc thisLoc, int leftIndex, int split, + void doBalanceLeftToRight( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, int leftIndex, int split, BtreeBucket<V> *l, const DiskLoc lchild, - BtreeBucket<V> *r, const DiskLoc rchild, - IndexDetails &id, const Ordering &order ); + BtreeBucket<V> *r, const DiskLoc rchild ); /** * Preconditions: * - All preconditions of doBalanceChildren @@ -863,11 +900,11 @@ namespace mongo { * head. The previous key in thisLoc at index leftIndex and all keys * with indexes less than split - l->n - 1 in rchild are moved to * lchild. - */ - void doBalanceRightToLeft( const DiskLoc thisLoc, int leftIndex, int split, + */ + void doBalanceRightToLeft( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, int leftIndex, int split, BtreeBucket<V> *l, const DiskLoc lchild, - BtreeBucket<V> *r, const DiskLoc rchild, - IndexDetails &id, const Ordering &order ); + BtreeBucket<V> *r, const DiskLoc rchild ); /** * Preconditions: @@ -878,7 +915,7 @@ namespace mongo { * - The tree may be updated recursively, resulting in 'this' and * thisLoc being invalidated and the tree head being changed. */ - void doMergeChildren( const DiskLoc thisLoc, int leftIndex, IndexDetails &id, const Ordering &order); + void doMergeChildren(BtreeInMemoryState* btreeState,const DiskLoc thisLoc, int leftIndex ); /** * Preconditions: @@ -889,7 +926,7 @@ namespace mongo { * to them are updated, and the tree head may change. * - nextChild replaces thisLoc in the btree structure. */ - void replaceWithNextChild( const DiskLoc thisLoc, IndexDetails &id ); + void replaceWithNextChild( BtreeInMemoryState* btreeState, const DiskLoc thisLoc ); /** * @return true iff the leftIndex and leftIndex + 1 children both exist, @@ -936,9 +973,10 @@ namespace mongo { * into one of the split buckets, and lchild/rchild set appropriately. * Splitting may occur recursively, possibly changing the tree head. */ - void split(const DiskLoc thisLoc, int keypos, + void split(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, int keypos, const DiskLoc recordLoc, const Key& key, - const Ordering& order, const DiskLoc lchild, const DiskLoc rchild, IndexDetails& idx); + const DiskLoc lchild, const DiskLoc rchild); /** * Preconditions: @@ -956,16 +994,23 @@ namespace mongo { * This function will always modify thisLoc, but it's marked const because * it commonly relies on the specialized writ]e intent mechanism of basicInsert(). */ - void insertHere(const DiskLoc thisLoc, int keypos, - const DiskLoc recordLoc, const Key& key, const Ordering &order, - const DiskLoc lchild, const DiskLoc rchild, IndexDetails &idx) const; + void insertHere(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, int keypos, + const DiskLoc recordLoc, const Key& key, + const DiskLoc lchild, const DiskLoc rchild ) const; /** bt_insert() is basically just a wrapper around this. */ - int _insert(const DiskLoc thisLoc, const DiskLoc recordLoc, - const Key& key, const Ordering &order, bool dupsAllowed, - const DiskLoc lChild, const DiskLoc rChild, IndexDetails &idx) const; + int _insert(BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, const DiskLoc recordLoc, + const Key& key, bool dupsallowed, + const DiskLoc lChild, const DiskLoc rChild ) const; + + bool find(const BtreeInMemoryState* btreeState, + const Key& key, + const DiskLoc &recordLoc, + int& pos, + bool assertIfDup) const; - bool find(const IndexDetails& idx, const Key& key, const DiskLoc &recordLoc, const Ordering &order, int& pos, bool assertIfDup) const; static bool customFind( int l, int h, const BSONObj &keyBegin, int keyBeginLen, bool afterKey, const vector< const BSONElement * > &keyEnd, const vector< bool > &keyEndInclusive, const Ordering &order, int direction, DiskLoc &thisLoc, int &keyOfs, pair< DiskLoc, int > &bestParent ) ; static void findLargestKey(const DiskLoc& thisLoc, DiskLoc& largestLoc, int& largestKey); static int customBSONCmp( const BSONObj &l, const BSONObj &rBegin, int rBeginLen, bool rSup, const vector< const BSONElement * > &rEnd, const vector< bool > &rEndInclusive, const Ordering &o, int direction ); @@ -987,9 +1032,13 @@ namespace mongo { * head. * - childForPos( keypos ) will be orphaned. */ - void setInternalKey( const DiskLoc thisLoc, int keypos, - const DiskLoc recordLoc, const Key &key, const Ordering &order, - const DiskLoc lchild, const DiskLoc rchild, IndexDetails &idx); + void setInternalKey( BtreeInMemoryState* btreeState, + const DiskLoc thisLoc, + int keypos, + const DiskLoc recordLoc, + const Key &key, + const DiskLoc lchild, + const DiskLoc rchild ); /** * Preconditions: @@ -1004,10 +1053,10 @@ namespace mongo { * - If the key cannot be replaced, it will be marked as unused. This * is only expected in legacy btrees. */ - void deleteInternalKey( const DiskLoc thisLoc, int keypos, IndexDetails &id, const Ordering &order ); + void deleteInternalKey( BtreeInMemoryState* btreeState, const DiskLoc thisLoc, int keypos ); public: /** simply builds and returns a dup key error message string */ - static string dupKeyError( const IndexDetails& idx , const Key& key ); + static string dupKeyError( const IndexDescriptor* idx , const Key& key ); }; #pragma pack() diff --git a/src/mongo/db/structure/btree/btreebuilder.cpp b/src/mongo/db/structure/btree/btreebuilder.cpp index aaccaf89b35..c1378d4a8ae 100644 --- a/src/mongo/db/structure/btree/btreebuilder.cpp +++ b/src/mongo/db/structure/btree/btreebuilder.cpp @@ -32,7 +32,6 @@ #include "mongo/db/structure/btree/btreebuilder.h" -#include "mongo/db/structure/btree/btree.h" #include "mongo/db/client.h" #include "mongo/db/clientcursor.h" #include "mongo/db/curop-inl.h" @@ -44,26 +43,26 @@ #include "mongo/db/pdfile.h" #include "mongo/db/repl/is_master.h" #include "mongo/db/stats/counters.h" +#include "mongo/db/structure/btree/btree.h" +#include "mongo/db/structure/btree/state.h" namespace mongo { /* --- BtreeBuilder --- */ template<class V> - BtreeBuilder<V>::BtreeBuilder(bool _dupsAllowed, IndexDetails& _idx) : - dupsAllowed(_dupsAllowed), - idx(_idx), - n(0), - order( idx.keyPattern() ), - ordering( Ordering::make(idx.keyPattern()) ) { - first = cur = BtreeBucket<V>::addBucket(idx); + BtreeBuilder<V>::BtreeBuilder(bool dupsAllowed, BtreeInMemoryState* btreeState ): + _dupsAllowed(dupsAllowed), + _btreeState(btreeState), + _numAdded(0) { + first = cur = BtreeBucket<V>::addBucket(btreeState); b = cur.btreemod<V>(); committed = false; } template<class V> void BtreeBuilder<V>::newBucket() { - DiskLoc L = BtreeBucket<V>::addBucket(idx); + DiskLoc L = BtreeBucket<V>::addBucket(_btreeState); b->setTempNext(L); cur = L; b = cur.btreemod<V>(); @@ -78,11 +77,10 @@ namespace mongo { template<class V> void BtreeBuilder<V>::addKey(BSONObj& _key, DiskLoc loc) { - auto_ptr< KeyOwned > key( new KeyOwned(_key) ); if ( key->dataSize() > BtreeBucket<V>::KeyMax ) { string msg = str::stream() << "Btree::insert: key too large to index, failing " - << idx.indexNamespace() + << _btreeState->descriptor()->indexNamespace() << ' ' << key->dataSize() << ' ' << key->toString(); problem() << msg << endl; if ( isMaster( NULL ) ) { @@ -91,24 +89,25 @@ namespace mongo { return; } - if( !dupsAllowed ) { - if( n > 0 ) { - int cmp = keyLast->woCompare(*key, ordering); + if( !_dupsAllowed ) { + if( _numAdded > 0 ) { + int cmp = keyLast->woCompare(*key, _btreeState->ordering()); massert( 10288 , "bad key order in BtreeBuilder - server internal error", cmp <= 0 ); if( cmp == 0 ) { //if( !dupsAllowed ) - uasserted( ASSERT_ID_DUPKEY , BtreeBucket<V>::dupKeyError( idx , *keyLast ) ); + uasserted( ASSERT_ID_DUPKEY, BtreeBucket<V>::dupKeyError( _btreeState->descriptor(), + *keyLast ) ); } } } - if ( ! b->_pushBack(loc, *key, ordering, DiskLoc()) ) { + if ( ! b->_pushBack(loc, *key, _btreeState->ordering(), DiskLoc()) ) { // bucket was full newBucket(); - b->pushBack(loc, *key, ordering, DiskLoc()); + b->pushBack(loc, *key, _btreeState->ordering(), DiskLoc()); } keyLast = key; - n++; + _numAdded++; mayCommitProgressDurably(); } @@ -118,12 +117,12 @@ namespace mongo { while( 1 ) { if( loc.btree<V>()->tempNext().isNull() ) { // only 1 bucket at this level. we are done. - getDur().writingDiskLoc(idx.head) = loc; + _btreeState->setHead( loc ); break; } levels++; - DiskLoc upLoc = BtreeBucket<V>::addBucket(idx); + DiskLoc upLoc = BtreeBucket<V>::addBucket(_btreeState); DiskLoc upStart = upLoc; BtreeBucket<V> *up = upLoc.btreemod<V>(); @@ -143,13 +142,13 @@ namespace mongo { bool keepX = ( x->n != 0 ); DiskLoc keepLoc = keepX ? xloc : x->nextChild; - if ( ! up->_pushBack(r, k, ordering, keepLoc) ) { + if ( ! up->_pushBack(r, k, _btreeState->ordering(), keepLoc) ) { // current bucket full - DiskLoc n = BtreeBucket<V>::addBucket(idx); + DiskLoc n = BtreeBucket<V>::addBucket(_btreeState); up->setTempNext(n); upLoc = n; up = upLoc.btreemod<V>(); - up->pushBack(r, k, ordering, keepLoc); + up->pushBack(r, k, _btreeState->ordering(), keepLoc); } DiskLoc nextLoc = x->tempNext(); // get next in chain at current level @@ -162,7 +161,7 @@ namespace mongo { ll.btreemod<V>()->parent = upLoc; //(x->nextChild.btreemod<V>())->parent = upLoc; } - x->deallocBucket( xloc, idx ); + x->deallocBucket( _btreeState, xloc ); } xloc = nextLoc; } diff --git a/src/mongo/db/structure/btree/btreebuilder.h b/src/mongo/db/structure/btree/btreebuilder.h index 7124d7428e2..c98ef59a6e7 100644 --- a/src/mongo/db/structure/btree/btreebuilder.h +++ b/src/mongo/db/structure/btree/btreebuilder.h @@ -32,6 +32,8 @@ namespace mongo { + class BtreeInMemoryState; + /** * build btree from the bottom up */ @@ -39,15 +41,15 @@ namespace mongo { class BtreeBuilder { typedef typename V::KeyOwned KeyOwned; typedef typename V::Key Key; - - bool dupsAllowed; - IndexDetails& idx; + + bool _dupsAllowed; + BtreeInMemoryState* _btreeState; /** Number of keys added to btree. */ - unsigned long long n; + unsigned long long _numAdded; + /** Last key passed to addKey(). */ auto_ptr< typename V::KeyOwned > keyLast; - BSONObj order; - Ordering ordering; + /** true iff commit() completed successfully. */ bool committed; @@ -59,7 +61,7 @@ namespace mongo { void mayCommitProgressDurably(); public: - BtreeBuilder(bool _dupsAllowed, IndexDetails& _idx); + BtreeBuilder(bool dupsAllowed, BtreeInMemoryState* idx); /** * Preconditions: 'key' is > or >= last key passed to this function (depends on _dupsAllowed) @@ -73,7 +75,7 @@ namespace mongo { */ void commit(bool mayInterrupt); - unsigned long long getn() { return n; } + unsigned long long getn() { return _numAdded; } }; } diff --git a/src/mongo/db/query_runner.h b/src/mongo/db/structure/btree/state-inl.h index 1301e279638..4a3271c1bb6 100644 --- a/src/mongo/db/query_runner.h +++ b/src/mongo/db/structure/btree/state-inl.h @@ -1,5 +1,7 @@ +// state-inl.h + /** -* Copyright (C) 2013 10gen Inc. +* Copyright (C) 2008 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, @@ -26,18 +28,18 @@ * it in the license file. */ -#pragma once - -#include "mongo/db/diskloc.h" +#include "mongo/db/memconcept.h" +#include "mongo/db/pdfile.h" // XXX-ERH :( +#include "mongo/db/structure/btree/state.h" +#include "mongo/db/structure/record_store.h" namespace mongo { - class BSONObj; - class IndexDetails; - - class QueryRunner { - public: - static DiskLoc fastFindSingle(const IndexDetails &indexdetails, const BSONObj& key); - }; + template< class V > + const BtreeBucket<V>* BtreeInMemoryState::getBucket( const DiskLoc& loc ) const { + Record* record = _recordStore->recordFor( loc ); + memconcept::is(record, memconcept::concept::btreebucket, "", 8192); + return reinterpret_cast<const BtreeBucket<V>*>( record->data() ); + } -} // namespace mongo +} diff --git a/src/mongo/db/query_runner.cpp b/src/mongo/db/structure/btree/state.cpp index 38fd7f2ba2f..a869293d332 100644 --- a/src/mongo/db/query_runner.cpp +++ b/src/mongo/db/structure/btree/state.cpp @@ -1,5 +1,7 @@ +// state.cpp + /** -* Copyright (C) 2013 10gen Inc. +* Copyright (C) 2008 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, @@ -26,24 +28,34 @@ * it in the license file. */ -#include "mongo/db/query_runner.h" +#include "mongo/db/structure/btree/state.h" -#include "mongo/db/structure/btree/btree.h" -#include "mongo/db/storage/index_details.h" -#include "mongo/db/jsobj.h" +#include "mongo/db/index/index_descriptor.h" #include "mongo/db/pdfile.h" +#include "mongo/db/storage/extent_manager.h" +#include "mongo/db/structure/record_store.h" namespace mongo { - // static - DiskLoc QueryRunner::fastFindSingle(const IndexDetails &indexdetails, const BSONObj& key) { - const int version = indexdetails.version(); - if (0 == version) { - return indexdetails.head.btree<V0>()->findSingle(indexdetails, indexdetails.head, key); - } else { - verify(1 == version); - return indexdetails.head.btree<V1>()->findSingle(indexdetails, indexdetails.head, key); - } + BtreeInMemoryState::BtreeInMemoryState( Collection* collection, + const IndexDescriptor* descriptor, + RecordStore* recordStore, + IndexDetails* details ) + : _collection( collection ), + _descriptor( descriptor ), + _recordStore( recordStore ), + _indexDetails( details ), + _ordering( Ordering::make( descriptor->keyPattern() ) ) { + } + + const DiskLoc& BtreeInMemoryState::head() const { return _indexDetails->head; } + + void BtreeInMemoryState::setHead( DiskLoc newHead ) { + _indexDetails->head.writing() = newHead; + } + + void BtreeInMemoryState::setMultikey() { + _collection->getIndexCatalog()->markMultikey( _descriptor, true ); } -} // namespace mongo +} diff --git a/src/mongo/db/structure/btree/state.h b/src/mongo/db/structure/btree/state.h new file mode 100644 index 00000000000..23410933b40 --- /dev/null +++ b/src/mongo/db/structure/btree/state.h @@ -0,0 +1,102 @@ +// state.h + +/** +* Copyright (C) 2008 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. +*/ + +#pragma once + +#include "mongo/base/disallow_copying.h" +#include "mongo/db/diskloc.h" +#include "mongo/db/jsobj.h" +#include "mongo/bson/ordering.h" + +namespace mongo { + + class Collection; + class IndexDetails; + class IndexDescriptor; + class NamesapceDetails; + class RecordStore; + + /** + * This class is maybe temporary, and terribly named + * its goal is to keep the state and data structure associated with a btree in one place + * previously, the btree code called back out of its world through globals, which is bad + * the goal here is to make the btree at least a sane visitorish pattern + * so this is passed to each method, and it can be operated on + * long term, the containmenent should be flipped + */ + class BtreeInMemoryState { + MONGO_DISALLOW_COPYING( BtreeInMemoryState ); + public: + BtreeInMemoryState( Collection* collection, + const IndexDescriptor* descriptor, + RecordStore* recordStore, + IndexDetails* details ); + + const Collection* collection() const { return _collection; } + + const IndexDescriptor* descriptor() const { return _descriptor; } + const Ordering& ordering() const { return _ordering; } + + RecordStore* recordStore() { return _recordStore.get(); } + const RecordStore* recordStore() const { return _recordStore.get(); } + + // ---- + + const DiskLoc& head() const; + + void setHead( DiskLoc newHead ); + + void setMultikey(); + + // ------------ + + + template< class V > + const BtreeBucket<V>* getHeadBucket() const { return getBucket<V>( head() ); } + + template< class V > + const BtreeBucket<V>* getBucket( const DiskLoc& loc ) const; + + private: + // the collection this index is over, not storage for the index + Collection* _collection; // not-owned here + + const IndexDescriptor* _descriptor; // not-owned here + + // the record store for this index (where its buckets go) + scoped_ptr<RecordStore> _recordStore; // OWNED HERE + + IndexDetails* _indexDetails; // TODO: remove + + Ordering _ordering; + + }; + +} diff --git a/src/mongo/db/structure/collection.cpp b/src/mongo/db/structure/collection.cpp index daf2ce6c193..cfb95662cc3 100644 --- a/src/mongo/db/structure/collection.cpp +++ b/src/mongo/db/structure/collection.cpp @@ -33,6 +33,7 @@ #include "mongo/base/counter.h" #include "mongo/db/clientcursor.h" #include "mongo/db/commands/server_status.h" +#include "mongo/db/curop.h" #include "mongo/db/database.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/namespace_details.h" diff --git a/src/mongo/db/structure/record_store.cpp b/src/mongo/db/structure/record_store.cpp index 1c80db620a7..8ab11035e77 100644 --- a/src/mongo/db/structure/record_store.cpp +++ b/src/mongo/db/structure/record_store.cpp @@ -52,6 +52,10 @@ namespace mongo { _isSystemIndexes = isSystemIndexes; } + Record* RecordStore::recordFor( const DiskLoc& loc ) const { + return _extentManager->recordFor( loc ); + } + StatusWith<DiskLoc> RecordStore::insertRecord( const DocWriter* doc, int quotaMax ) { int lenWHdr = _details->getRecordAllocationSize( doc->documentSize() + Record::HeaderSize ); @@ -59,7 +63,7 @@ namespace mongo { if ( !loc.isOK() ) return loc; - Record *r = _extentManager->recordFor( loc.getValue() ); + Record *r = recordFor( loc.getValue() ); fassert( 17319, r->lengthWithHeaders() >= lenWHdr ); r = reinterpret_cast<Record*>( getDur().writingPtr(r, lenWHdr) ); @@ -81,7 +85,7 @@ namespace mongo { if ( !loc.isOK() ) return loc; - Record *r = _extentManager->recordFor( loc.getValue() ); + Record *r = recordFor( loc.getValue() ); fassert( 17210, r->lengthWithHeaders() >= lenWHdr ); // copy the data @@ -140,19 +144,19 @@ namespace mongo { void RecordStore::deleteRecord( const DiskLoc& dl ) { - Record* todelete = _extentManager->recordFor( dl ); + Record* todelete = recordFor( dl ); /* remove ourself from the record next/prev chain */ { if ( todelete->prevOfs() != DiskLoc::NullOfs ) { DiskLoc prev = _extentManager->getPrevRecordInExtent( dl ); - Record* prevRecord = _extentManager->recordFor( prev ); + Record* prevRecord = recordFor( prev ); getDur().writingInt( prevRecord->nextOfs() ) = todelete->nextOfs(); } if ( todelete->nextOfs() != DiskLoc::NullOfs ) { DiskLoc next = _extentManager->getNextRecord( dl ); - Record* nextRecord = _extentManager->recordFor( next ); + Record* nextRecord = recordFor( next ); getDur().writingInt( nextRecord->prevOfs() ) = todelete->prevOfs(); } } diff --git a/src/mongo/db/structure/record_store.h b/src/mongo/db/structure/record_store.h index ddaf7aa221c..3ebc5afa9e1 100644 --- a/src/mongo/db/structure/record_store.h +++ b/src/mongo/db/structure/record_store.h @@ -48,6 +48,8 @@ namespace mongo { ExtentManager* em, bool isSystemIndexes ); + Record* recordFor( const DiskLoc& loc ) const; + void deleteRecord( const DiskLoc& dl ); StatusWith<DiskLoc> insertRecord( const char* data, int len, int quotaMax ); |