summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2013-12-24 18:44:18 -0500
committerEliot Horowitz <eliot@10gen.com>2013-12-30 00:41:27 -0500
commit7de1f17148231074cdf74177dcbf8e8fc534949b (patch)
tree886e7008704a2152fa47354e513ba9cb4cf0969a /src
parent29e691a91c72b28ef50faddc7ef6f24523788aee (diff)
downloadmongo-7de1f17148231074cdf74177dcbf8e8fc534949b.tar.gz
SERVER-12213: bulk of index refactor, making catalog/record store come via catalog - js tests work
Diffstat (limited to 'src')
-rw-r--r--src/mongo/SConscript2
-rw-r--r--src/mongo/db/cap.cpp1
-rw-r--r--src/mongo/db/catalog/index_catalog.cpp53
-rw-r--r--src/mongo/db/catalog/index_catalog.h11
-rw-r--r--src/mongo/db/catalog/index_create.cpp24
-rw-r--r--src/mongo/db/catalog/index_create.h5
-rw-r--r--src/mongo/db/clientcursor.h4
-rw-r--r--src/mongo/db/commands/distinct.cpp1
-rw-r--r--src/mongo/db/commands/group.cpp2
-rw-r--r--src/mongo/db/commands/mr.cpp1
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp2
-rw-r--r--src/mongo/db/database.cpp1
-rw-r--r--src/mongo/db/dbcommands.cpp1
-rw-r--r--src/mongo/db/dbhelpers.cpp43
-rw-r--r--src/mongo/db/dbhelpers.h8
-rw-r--r--src/mongo/db/exec/2dcommon.cpp2
-rw-r--r--src/mongo/db/exec/2dcommon.h6
-rw-r--r--src/mongo/db/exec/index_scan.h6
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp3
-rw-r--r--src/mongo/db/index/2d_access_method.cpp16
-rw-r--r--src/mongo/db/index/2d_access_method.h8
-rw-r--r--src/mongo/db/index/btree_access_method.cpp87
-rw-r--r--src/mongo/db/index/btree_access_method.h5
-rw-r--r--src/mongo/db/index/btree_access_method_internal.h14
-rw-r--r--src/mongo/db/index/btree_based_builder.cpp42
-rw-r--r--src/mongo/db/index/btree_based_builder.h25
-rw-r--r--src/mongo/db/index/btree_index_cursor.cpp81
-rw-r--r--src/mongo/db/index/btree_index_cursor.h6
-rw-r--r--src/mongo/db/index/btree_interface.cpp188
-rw-r--r--src/mongo/db/index/btree_interface.h52
-rw-r--r--src/mongo/db/index/fts_access_method.cpp6
-rw-r--r--src/mongo/db/index/fts_access_method.h6
-rw-r--r--src/mongo/db/index/hash_access_method.cpp8
-rw-r--r--src/mongo/db/index/hash_access_method.h4
-rw-r--r--src/mongo/db/index/haystack_access_method.cpp8
-rw-r--r--src/mongo/db/index/haystack_access_method.h4
-rw-r--r--src/mongo/db/index/index_access_method.h2
-rw-r--r--src/mongo/db/index/index_descriptor.h2
-rw-r--r--src/mongo/db/index/s2_access_method.cpp10
-rw-r--r--src/mongo/db/index/s2_access_method.h4
-rw-r--r--src/mongo/db/index_builder.cpp2
-rw-r--r--src/mongo/db/instance.cpp1
-rw-r--r--src/mongo/db/ops/count.cpp2
-rw-r--r--src/mongo/db/ops/delete.cpp2
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp2
-rw-r--r--src/mongo/db/query/idhack_runner.cpp17
-rw-r--r--src/mongo/db/query/internal_plans.h2
-rw-r--r--src/mongo/db/query/multi_plan_runner.cpp3
-rw-r--r--src/mongo/db/query/stage_builder.cpp3
-rw-r--r--src/mongo/db/repl/master_slave.cpp1
-rw-r--r--src/mongo/db/repl/oplog.cpp3
-rw-r--r--src/mongo/db/repl/oplogreader.h2
-rw-r--r--src/mongo/db/repl/rs.h2
-rw-r--r--src/mongo/db/repl/rs_rollback.cpp1
-rw-r--r--src/mongo/db/repl/rs_sync.cpp1
-rw-r--r--src/mongo/db/repl/sync.cpp1
-rw-r--r--src/mongo/db/structure/btree/btree.cpp387
-rw-r--r--src/mongo/db/structure/btree/btree.h147
-rw-r--r--src/mongo/db/structure/btree/btreebuilder.cpp47
-rw-r--r--src/mongo/db/structure/btree/btreebuilder.h18
-rw-r--r--src/mongo/db/structure/btree/state-inl.h (renamed from src/mongo/db/query_runner.h)26
-rw-r--r--src/mongo/db/structure/btree/state.cpp (renamed from src/mongo/db/query_runner.cpp)42
-rw-r--r--src/mongo/db/structure/btree/state.h102
-rw-r--r--src/mongo/db/structure/collection.cpp1
-rw-r--r--src/mongo/db/structure/record_store.cpp14
-rw-r--r--src/mongo/db/structure/record_store.h2
-rw-r--r--src/mongo/dbtests/query_multi_plan_runner.cpp1
-rw-r--r--src/mongo/dbtests/query_single_solution_runner.cpp1
-rw-r--r--src/mongo/dbtests/query_stage_merge_sort.cpp1
-rw-r--r--src/mongo/dbtests/query_stage_sort.cpp1
-rw-r--r--src/mongo/dbtests/query_stage_tests.cpp1
-rw-r--r--src/mongo/s/d_split.cpp1
72 files changed, 957 insertions, 634 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index 40357793259..8e62128f3e0 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -536,6 +536,7 @@ serverOnlyFiles = [ "db/curop.cpp",
"db/introspect.cpp",
"db/structure/btree/btree.cpp",
"db/structure/btree/btree_stats.cpp",
+ "db/structure/btree/state.cpp",
"db/clientcursor.cpp",
"db/tests.cpp",
"db/range_deleter_db_env.cpp",
@@ -606,7 +607,6 @@ serverOnlyFiles = [ "db/curop.cpp",
"db/ops/delete.cpp",
"db/ops/insert.cpp",
"db/ops/update.cpp",
- "db/query_runner.cpp",
"db/dbcommands.cpp",
"db/compact.cpp",
"db/dbcommands_admin.cpp",
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 );
diff --git a/src/mongo/dbtests/query_multi_plan_runner.cpp b/src/mongo/dbtests/query_multi_plan_runner.cpp
index 62787291dde..e1367e3ecdb 100644
--- a/src/mongo/dbtests/query_multi_plan_runner.cpp
+++ b/src/mongo/dbtests/query_multi_plan_runner.cpp
@@ -26,6 +26,7 @@
* then also delete it in the license file.
*/
+#include "mongo/db/database.h"
#include "mongo/db/exec/collection_scan.h"
#include "mongo/db/exec/fetch.h"
#include "mongo/db/exec/index_scan.h"
diff --git a/src/mongo/dbtests/query_single_solution_runner.cpp b/src/mongo/dbtests/query_single_solution_runner.cpp
index 994a3a3b65f..5890d5d9b55 100644
--- a/src/mongo/dbtests/query_single_solution_runner.cpp
+++ b/src/mongo/dbtests/query_single_solution_runner.cpp
@@ -27,6 +27,7 @@
*/
#include "mongo/db/clientcursor.h"
+#include "mongo/db/database.h"
#include "mongo/db/exec/collection_scan.h"
#include "mongo/db/exec/fetch.h"
#include "mongo/db/exec/index_scan.h"
diff --git a/src/mongo/dbtests/query_stage_merge_sort.cpp b/src/mongo/dbtests/query_stage_merge_sort.cpp
index a329431e1ef..6b3c5166f2e 100644
--- a/src/mongo/dbtests/query_stage_merge_sort.cpp
+++ b/src/mongo/dbtests/query_stage_merge_sort.cpp
@@ -27,6 +27,7 @@
*/
#include "mongo/client/dbclientcursor.h"
+#include "mongo/db/database.h"
#include "mongo/db/exec/fetch.h"
#include "mongo/db/exec/index_scan.h"
#include "mongo/db/exec/plan_stage.h"
diff --git a/src/mongo/dbtests/query_stage_sort.cpp b/src/mongo/dbtests/query_stage_sort.cpp
index 19953d7da8f..3320b7ed2cd 100644
--- a/src/mongo/dbtests/query_stage_sort.cpp
+++ b/src/mongo/dbtests/query_stage_sort.cpp
@@ -27,6 +27,7 @@
*/
#include "mongo/client/dbclientcursor.h"
+#include "mongo/db/database.h"
#include "mongo/db/exec/fetch.h"
#include "mongo/db/exec/mock_stage.h"
#include "mongo/db/exec/plan_stage.h"
diff --git a/src/mongo/dbtests/query_stage_tests.cpp b/src/mongo/dbtests/query_stage_tests.cpp
index fc8fcfda526..7dfd675a0b1 100644
--- a/src/mongo/dbtests/query_stage_tests.cpp
+++ b/src/mongo/dbtests/query_stage_tests.cpp
@@ -27,6 +27,7 @@
*/
#include "mongo/client/dbclientcursor.h"
+#include "mongo/db/database.h"
#include "mongo/db/exec/index_scan.h"
#include "mongo/db/exec/plan_stage.h"
#include "mongo/db/instance.h"
diff --git a/src/mongo/s/d_split.cpp b/src/mongo/s/d_split.cpp
index 3ddc198dc88..727bce6119f 100644
--- a/src/mongo/s/d_split.cpp
+++ b/src/mongo/s/d_split.cpp
@@ -44,6 +44,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands.h"
+#include "mongo/db/dbhelpers.h"
#include "mongo/db/index_legacy.h"
#include "mongo/db/instance.h"
#include "mongo/db/jsobj.h"