From 844d96c19f45fba8c3eb1ed08df95493fc76ec98 Mon Sep 17 00:00:00 2001 From: Dwight Date: Wed, 21 Oct 2009 16:00:40 -0400 Subject: [PATCH] allow more indexes do not revert to an earlier db version or you will have problems --- db/dbcommands.cpp | 34 +++++--- db/dbhelpers.cpp | 11 ++- db/namespace.cpp | 46 +++++++--- db/namespace.h | 146 +++++++++++++++++++++++++------- db/pdfile.cpp | 55 ++++++------ db/pdfile.h | 1 - db/query.cpp | 2 +- db/queryoptimizer.cpp | 31 ++++--- db/repl.cpp | 4 +- dbtests/cursortests.cpp | 6 +- dbtests/queryoptimizertests.cpp | 4 +- debian/rules | 0 jstests/index_many.js | 33 ++++++++ 13 files changed, 267 insertions(+), 106 deletions(-) mode change 100755 => 100644 debian/rules create mode 100644 jstests/index_many.js diff --git a/db/dbcommands.cpp b/db/dbcommands.cpp index 21325e618ec..6d89570a19c 100644 --- a/db/dbcommands.cpp +++ b/db/dbcommands.cpp @@ -179,9 +179,11 @@ namespace mongo { int idxn = 0; try { ss << " nIndexes:" << d->nIndexes << endl; - for ( ; idxn < d->nIndexes; idxn++ ) { - ss << " " << d->indexes[idxn].indexNamespace() << " keys:" << - d->indexes[idxn].head.btree()->fullValidate(d->indexes[idxn].head, d->indexes[idxn].keyPattern()) << endl; + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) { + IndexDetails& id = i.next(); + ss << " " << id.indexNamespace() << " keys:" << + id.head.btree()->fullValidate(id.head, id.keyPattern()) << endl; } } catch (...) { @@ -549,10 +551,11 @@ namespace mongo { } } cmdoplogging; - unsigned removeBit(unsigned b, int x) { - unsigned tmp = b; + // remove bit from a bit array - actually remove its slot, not a clear + unsigned long long removeBit(unsigned long long b, int x) { + unsigned long long tmp = b; return - (tmp & ((1 << x)-1)) | + (tmp & ((((unsigned long long) 1) << x)-1)) | ((tmp >> (x+1)) << x); } @@ -563,6 +566,9 @@ namespace mongo { assert( removeBit(2, 1) == 0 ); assert( removeBit(255, 1) == 127 ); assert( removeBit(21, 2) == 9 ); + assert( removeBit(0x8000000000000000, 63) == 0 ); + assert( removeBit(0x8000000000000001, 63) == 1 ); + assert( removeBit(0x8000000000000001, 0) == 0x4000000000000000 ); } } dbc_unittest; @@ -580,17 +586,17 @@ namespace mongo { IndexDetails *idIndex = 0; if( d->nIndexes ) { for ( int i = 0; i < d->nIndexes; i++ ) { - if ( !mayDeleteIdIndex && d->indexes[i].isIdIndex() ) { - idIndex = &d->indexes[i]; + if ( !mayDeleteIdIndex && d->idx(i).isIdIndex() ) { + idIndex = &d->idx(i); } else { - d->indexes[i].kill_idx(); + d->idx(i).kill_idx(); } } d->nIndexes = 0; } if ( idIndex ) { - d->indexes[ 0 ] = *idIndex; - d->nIndexes = 1; + d->addIndex(ns) = *idIndex; + wassert( d->nIndexes == 1 ); } /* assuming here that id index is not multikey: */ d->multiKeyIndexBits = 0; @@ -607,16 +613,16 @@ namespace mongo { call, otherwise, on recreate, the old one would be reused, and its IndexDetails::info ptr would be bad info. */ - IndexDetails *id = &d->indexes[x]; + IndexDetails *id = &d->idx(x); if ( !mayDeleteIdIndex && id->isIdIndex() ) { errmsg = "may not delete _id index"; return false; } - d->indexes[x].kill_idx(); + id->kill_idx(); d->multiKeyIndexBits = removeBit(d->multiKeyIndexBits, x); d->nIndexes--; for ( int i = x; i < d->nIndexes; i++ ) - d->indexes[i] = d->indexes[i+1]; + d->idx(i) = d->idx(i+1); } else { log() << "deleteIndexes: " << name << " not found" << endl; errmsg = "index not found"; diff --git a/db/dbhelpers.cpp b/db/dbhelpers.cpp index 76a71dc8509..1956c4bd560 100644 --- a/db/dbhelpers.cpp +++ b/db/dbhelpers.cpp @@ -30,12 +30,15 @@ namespace mongo { if( d == 0 ) return; - for( int i = 0; i < d->nIndexes; i++ ) { - if( d->indexes[i].keyPattern().woCompare(keyPattern) == 0 ) - return; + { + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) { + if( i.next().keyPattern().woCompare(keyPattern) == 0 ) + return; + } } - if( d->nIndexes >= MaxIndexes ) { + if( d->nIndexes >= NamespaceDetails::NIndexesMax ) { problem() << "Helper::ensureIndex fails, MaxIndexes exceeded " << ns << '\n'; return; } diff --git a/db/namespace.cpp b/db/namespace.cpp index 1fa04eee73d..3dff7cc1108 100644 --- a/db/namespace.cpp +++ b/db/namespace.cpp @@ -507,23 +507,40 @@ namespace mongo { } /* you MUST call when adding an index. see pdfile.cpp */ - void NamespaceDetails::addingIndex(const char *thisns, IndexDetails& details) { + IndexDetails& NamespaceDetails::addIndex(const char *thisns) { assert( nsdetails(thisns) == this ); - assert( &details == &indexes[nIndexes] ); + + if( nIndexes == NIndexesBase && extraOffset == 0 ) { + nsindex(thisns)->allocExtra(thisns); + } + + IndexDetails& id = idx(nIndexes); nIndexes++; NamespaceDetailsTransient::get(thisns).addedIndex(); + return id; + } + + // must be called when renaming a NS to fix up extra + void NamespaceDetails::copyingFrom(const char *thisns, NamespaceDetails *src) { + if( extraOffset ) { + extraOffset = 0; // so allocExtra() doesn't assert. + Extra *e = nsindex(thisns)->allocExtra(thisns); + memcpy(e, src->extra(), sizeof(Extra)); + } } /* returns index of the first index in which the field is present. -1 if not present. (aug08 - this method not currently used) */ int NamespaceDetails::fieldIsIndexed(const char *fieldName) { + massert("not implemented", false); + /* for ( int i = 0; i < nIndexes; i++ ) { IndexDetails& idx = indexes[i]; BSONObj idxKey = idx.info.obj().getObjectField("key"); // e.g., { ts : -1 } if ( !idxKey.findElement(fieldName).eoo() ) return i; - } + }*/ return -1; } @@ -569,11 +586,9 @@ namespace mongo { void NamespaceDetailsTransient::computeIndexKeys() { allIndexKeys.clear(); NamespaceDetails *d = nsdetails(ns.c_str()); - for ( int i = 0; i < d->nIndexes; i++ ) { - // set fields; - d->indexes[i].keyPattern().getFieldNames(allIndexKeys); - // allIndexKeys.insert(fields.begin(),fields.end()); - } + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) + i.next().keyPattern().getFieldNames(allIndexKeys); } void NamespaceDetailsTransient::startLog( int logSizeMb ) { @@ -646,11 +661,20 @@ namespace mongo { // transient (including query cache) so clear these. ClientCursor::invalidate( from ); NamespaceDetailsTransient::drop( from ); - + NamespaceDetails *details = ni->details( from ); ni->add_ns( to, *details ); + NamespaceDetails *todetails = ni->details( to ); + try { + todetails->copyingFrom(to, details); // fixes extraOffset + } + catch( DBException& ) { + // could end up here if .ns is full - if so try to clean up / roll back a little + ni->kill_ns(to); + throw; + } ni->kill_ns( from ); - details = ni->details( to ); + details = todetails; BSONObj oldSpec; char database[MaxClientLen]; @@ -690,7 +714,7 @@ namespace mongo { BSONObj newIndexSpec = newIndexSpecB.done(); DiskLoc newIndexSpecLoc = theDataFileMgr.insert( s.c_str(), newIndexSpec.objdata(), newIndexSpec.objsize(), true, BSONElement(), false ); int indexI = details->findIndexByName( oldIndexSpec.getStringField( "name" ) ); - IndexDetails &indexDetails = details->indexes[ indexI ]; + IndexDetails &indexDetails = details->idx(indexI); string oldIndexNs = indexDetails.indexNamespace(); indexDetails.info = newIndexSpecLoc; string newIndexNs = indexDetails.indexNamespace(); diff --git a/db/namespace.h b/db/namespace.h index e3def0b733b..3eaaecbec3b 100644 --- a/db/namespace.h +++ b/db/namespace.h @@ -94,6 +94,7 @@ namespace mongo { return *this; } + /* for more than 10 indexes -- see NamespaceDetails::Extra */ string extraName() { string s = string(buf) + "$extra"; massert("ns name too long", s.size() < MaxNsLen); @@ -151,7 +152,7 @@ namespace mongo { /* Maximum # of indexes per collection. We need to raise this limit at some point. (Backward datafile compatibility is main issue with changing.) */ - const int MaxIndexes = 10; +// const int MaxIndexes = 10; /* Details about a particular index. There is one of these effectively for each object in system.namespaces (although this also includes the head pointer, which is not in that @@ -262,7 +263,28 @@ namespace mongo { /* this is the "header" for a collection that has all its details. in the .ns file. */ class NamespaceDetails { + friend class NamespaceIndex; + enum { NIndexesExtra = 30, + NIndexesBase = 10 + }; + struct Extra { + // note we could use this field for more chaining later, so don't waste it: + unsigned long long reserved1; + IndexDetails details[NIndexesExtra]; + unsigned reserved2; + unsigned reserved3; + }; + Extra* extra() { + assert( extraOffset ); + return (Extra *) (((char *) this) + extraOffset); + } public: + void copyingFrom(const char *thisns, NamespaceDetails *src); // must be called when renaming a NS to fix up extra + + enum { NIndexesMax = 40 }; + + BOOST_STATIC_ASSERT( NIndexesMax == NIndexesBase + NIndexesExtra ); + NamespaceDetails( const DiskLoc &loc, bool _capped ) { /* be sure to initialize new fields here -- doesn't default to zeroes the way we use it */ firstExtent = lastExtent = capExtent = loc; @@ -283,6 +305,8 @@ namespace mongo { dataFileVersion = 0; indexFileVersion = 0; multiKeyIndexBits = 0; + reservedA = 0; + extraOffset = 0; memset(reserved, 0, sizeof(reserved)); } DiskLoc firstExtent; @@ -292,7 +316,9 @@ namespace mongo { long long nrecords; int lastExtentSize; int nIndexes; - IndexDetails indexes[MaxIndexes]; + private: + IndexDetails _indexes[NIndexesBase]; + public: int capped; int max; // max # of objects for a capped table. double paddingFactor; // 1.0 = no padding. @@ -306,21 +332,60 @@ namespace mongo { unsigned short dataFileVersion; unsigned short indexFileVersion; - unsigned multiKeyIndexBits; - - char reserved[100]; + unsigned long long multiKeyIndexBits; + private: + unsigned long long reservedA; + long long extraOffset; // where the $extra info is located (bytes relative to this) + public: + char reserved[80]; enum NamespaceFlags { Flag_HaveIdIndex = 1 << 0, // set when we have _id index (ONLY if ensureIdIndex was called -- 0 if that has never been called) Flag_CappedDisallowDelete = 1 << 1 // set when deletes not allowed during capped table allocation. }; + IndexDetails& idx(int idxNo) { + if( idxNo < NIndexesBase ) + return _indexes[idxNo]; + return extra()->details[idxNo-NIndexesBase]; + } + + class IndexIterator { + friend class NamespaceDetails; + int i; + int n; + NamespaceDetails *d; + Extra *e; + IndexIterator(NamespaceDetails *_d) { + d = _d; + i = 0; + n = d->nIndexes; + if( n > NIndexesBase ) + e = d->extra(); + } + public: + int pos() { return i; } // note this is the next one to come + bool more() { return i < n; } + IndexDetails& next() { + int k = i; + i++; + return k < NIndexesBase ? d->_indexes[k] : + e->details[k-10]; + } + }; + + IndexIterator ii() { + return IndexIterator(this); + } + /* hackish - find our index # in the indexes array */ int idxNo(IndexDetails& idx) { - for( int i = 0; i < nIndexes; i++ ) - if( &indexes[i] == &idx ) - return i; + IndexIterator i = ii(); + while( i.more() ) { + if( &i.next() == &idx ) + return i.pos()-1; + } massert("E12000 idxNo fails", false); return -1; } @@ -329,20 +394,22 @@ namespace mongo { for a single document. see multikey in wiki. for these, we have to do some dedup object on queries. */ - bool isMultikey(int i) { - return (multiKeyIndexBits & (1 << i)) != 0; + bool isMultikey(int i) { + return (multiKeyIndexBits & (((unsigned long long) 1) << i)) != 0; } void setIndexIsMultikey(int i) { - dassert( i < 32 && i nodes; } + /* extra space for indexes when more than 10 */ + NamespaceDetails::Extra* allocExtra(const char *ns) { + Namespace n(ns); + Namespace extra(n.extraName().c_str()); // throws userexception if ns name too long + NamespaceDetails *d = details(ns); + massert( "allocExtra: base ns missing?", d ); + assert( d->extraOffset == 0 ); + massert( "allocExtra: extra already exists", ht->get(extra) == 0 ); + NamespaceDetails::Extra temp; + memset(&temp, 0, sizeof(temp)); + uassert( "allocExtra: too many namespaces/collections", ht->put(extra, (NamespaceDetails&) temp)); + NamespaceDetails::Extra *e = (NamespaceDetails::Extra *) ht->get(extra); + d->extraOffset = ((char *) e) - ((char *) d); + assert( d->extra() == e ); + return e; + } + NamespaceDetails* details(const char *ns) { if ( !ht ) return 0; @@ -559,18 +646,13 @@ namespace mongo { Namespace n(ns); ht->kill(n); - // todo catch assert if name too long (that is ok if no extra) - // Namespace extra(n.extraName().c_str()); - // ht->kill(extra); + try { + Namespace extra(n.extraName().c_str()); + ht->kill(extra); + } + catch(DBException&) { } } - /* void drop_ns(const char *ns) { - if ( !ht ) - return; - Namespace n(ns); - ht->drop(n); - }*/ - bool find(const char *ns, DiskLoc& loc) { NamespaceDetails *l = details(ns); if ( l ) { diff --git a/db/pdfile.cpp b/db/pdfile.cpp index 1f2140d29a6..23f3c4508a7 100644 --- a/db/pdfile.cpp +++ b/db/pdfile.cpp @@ -795,8 +795,9 @@ namespace mongo { void unindexRecord(NamespaceDetails *d, Record *todelete, const DiskLoc& dl, bool noWarn = false) { if ( d->nIndexes == 0 ) return; BSONObj obj(todelete); - for ( int i = 0; i < d->nIndexes; i++ ) { - _unindexRecord(d->indexes[i], obj, dl, !noWarn); + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) { + _unindexRecord(i.next(), obj, dl, !noWarn); } } @@ -900,23 +901,26 @@ namespace mongo { inline void getIndexChanges(vector& v, NamespaceDetails& d, BSONObj newObj, BSONObj oldObj) { v.resize(d.nIndexes); - for ( int i = 0; i < d.nIndexes; i++ ) { - IndexDetails& idx = d.indexes[i]; + NamespaceDetails::IndexIterator i = d.ii(); + while( i.more() ) { + int j = i.pos(); + IndexDetails& idx = i.next(); BSONObj idxKey = idx.info.obj().getObjectField("key"); // eg { ts : 1 } - IndexChanges& ch = v[i]; + IndexChanges& ch = v[j]; idx.getKeysFromObject(oldObj, ch.oldkeys); idx.getKeysFromObject(newObj, ch.newkeys); if( ch.newkeys.size() > 1 ) - d.setIndexIsMultikey(i); + d.setIndexIsMultikey(j); setDifference(ch.oldkeys, ch.newkeys, ch.removed); setDifference(ch.newkeys, ch.oldkeys, ch.added); } } inline void dupCheck(vector& v, NamespaceDetails& d) { - for ( int i = 0; i < d.nIndexes; i++ ) { - IndexDetails& idx = d.indexes[i]; - v[i].dupCheck(idx); + NamespaceDetails::IndexIterator i = d.ii(); + while( i.more() ) { + int j = i.pos(); + v[j].dupCheck(i.next()); } } @@ -973,7 +977,7 @@ namespace mongo { /* have any index keys changed? */ if( d->nIndexes ) { for ( int x = 0; x < d->nIndexes; x++ ) { - IndexDetails& idx = d->indexes[x]; + IndexDetails& idx = d->idx(x); for ( unsigned i = 0; i < changes[x].removed.size(); i++ ) { try { idx.head.btree()->unindex(idx.head, idx, *changes[x].removed[i], dl); @@ -1021,7 +1025,7 @@ namespace mongo { /* add keys to indexes for a new record */ inline void _indexRecord(NamespaceDetails *d, int idxNo, BSONObj& obj, DiskLoc newRecordLoc, bool dupsAllowed) { - IndexDetails& idx = d->indexes[idxNo]; + IndexDetails& idx = d->idx(idxNo); BSONObjSetDefaultOrder keys; idx.getKeysFromObject(obj, keys); BSONObj order = idx.keyPattern(); @@ -1219,7 +1223,7 @@ namespace mongo { /*UNIQUE*/ for ( int i = 0; i < d->nIndexes; i++ ) { try { - bool unique = d->indexes[i].unique(); + bool unique = d->idx(i).unique(); _indexRecord(d, i, obj, newRecordLoc, /*dupsAllowed*/!unique); } catch( DBException& ) { @@ -1229,7 +1233,7 @@ namespace mongo { */ for( int j = 0; j <= i; j++ ) { try { - _unindexRecord(d->indexes[j], obj, newRecordLoc, false); + _unindexRecord(d->idx(j), obj, newRecordLoc, false); } catch(...) { log(3) << "unindex fails on rollback after unique failure\n"; @@ -1249,10 +1253,14 @@ namespace mongo { d->flags |= NamespaceDetails::Flag_HaveIdIndex; - for( int i = 0; i < d->nIndexes; ++i ) - if ( d->indexes[ i ].isIdIndex() ) - return; - + { + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) { + if( i.next().isIdIndex() ) + return; + } + } + string system_indexes = cc().database()->name + ".system.indexes"; BSONObjBuilder b; @@ -1382,17 +1390,17 @@ namespace mongo { log() << "info: creating collection " << tabletoidxns << " on add index\n"; assert( tableToIndex ); } - if ( tableToIndex->nIndexes >= MaxIndexes ) { + if ( tableToIndex->findIndexByName(name) >= 0 ) { + // index already exists. + return DiskLoc(); + } + if ( tableToIndex->nIndexes >= NamespaceDetails::NIndexesMax ) { stringstream ss; ss << "add index fails, too many indexes for " << tabletoidxns << " key:" << key.toString(); string s = ss.str(); log() << s << '\n'; uasserted(s); } - if ( tableToIndex->findIndexByName(name) >= 0 ) { - //out() << "INFO: index:" << name << " already exists for:" << tabletoidxns << endl; - return DiskLoc(); - } if ( !god && IndexDetails::isIdIndexPattern( key ) ) { ensureHaveIdIndex( tabletoidxns.c_str() ); return DiskLoc(); @@ -1492,9 +1500,8 @@ namespace mongo { if ( tableToIndex ) { int idxNo = tableToIndex->nIndexes; - IndexDetails& idx = tableToIndex->indexes[idxNo]; + IndexDetails& idx = tableToIndex->addIndex(tabletoidxns.c_str()); // clear transient info caches so they refresh; increments nIndexes idx.info = loc; - tableToIndex->addingIndex(tabletoidxns.c_str(), idx); // clear transient info caches so they refresh; increments nIndexes try { buildIndex(tabletoidxns, tableToIndex, idx, idxNo); } catch( DBException& ) { diff --git a/db/pdfile.h b/db/pdfile.h index aec3c53168d..827ab7f9ad1 100644 --- a/db/pdfile.h +++ b/db/pdfile.h @@ -418,7 +418,6 @@ namespace mongo { return &database->namespaceIndex; } - inline NamespaceDetails* nsdetails(const char *ns) { // if this faults, did you set the current db first? (DBContext + dblock) return nsindex(ns)->details(ns); diff --git a/db/query.cpp b/db/query.cpp index 2dde05bbcf0..82a6b9e6f61 100644 --- a/db/query.cpp +++ b/db/query.cpp @@ -749,7 +749,7 @@ namespace mongo { in the query optimizer please fix this then! */ BSONObjBuilder b; - b.append("$hint", d->indexes[i].indexName()); + b.append("$hint", d->idx(i).indexName()); snapshotHint = b.obj(); hint = snapshotHint.firstElement(); } diff --git a/db/queryoptimizer.cpp b/db/queryoptimizer.cpp index aed2fd47d9e..9b2a1a646fa 100644 --- a/db/queryoptimizer.cpp +++ b/db/queryoptimizer.cpp @@ -67,7 +67,7 @@ namespace mongo { } if( idxNo >= 0 ) { - index_ = &d->indexes[idxNo]; + index_ = &d->idx(idxNo); } else { // full table scan case if ( order_.isEmpty() || !strcmp( order_.firstElement().fieldName(), "$natural" ) ) @@ -257,8 +257,9 @@ namespace mongo { mayRecordPlan_ = false; if( hint.type() == String ) { string hintstr = hint.valuestr(); - for (int i = 0; i < d->nIndexes; i++ ) { - IndexDetails& ii = d->indexes[i]; + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) { + IndexDetails& ii = i.next(); if ( ii.indexName() == hintstr ) { addHint( ii ); return; @@ -274,8 +275,9 @@ namespace mongo { plans_.push_back( PlanPtr( new QueryPlan( d, -1, fbs_, order_ ) ) ); return; } - for (int i = 0; i < d->nIndexes; i++ ) { - IndexDetails& ii = d->indexes[i]; + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) { + IndexDetails& ii = i.next(); if( ii.keyPattern().woCompare(hintobj) == 0 ) { addHint( ii ); return; @@ -305,10 +307,13 @@ namespace mongo { plans_.push_back( PlanPtr( new QueryPlan( d, -1, fbs_, order_ ) ) ); return; } - for (int i = 0; i < d->nIndexes; i++ ) { - IndexDetails& ii = d->indexes[i]; + + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) { + int j = i.pos(); + IndexDetails& ii = i.next(); if( ii.keyPattern().woCompare(bestIndex) == 0 ) { - plans_.push_back( PlanPtr( new QueryPlan( d, i, fbs_, order_ ) ) ); + plans_.push_back( PlanPtr( new QueryPlan( d, j, fbs_, order_ ) ) ); return; } } @@ -560,8 +565,9 @@ namespace mongo { return 0; } if ( keyPattern.isEmpty() ) { - for (int i = 0; i < d->nIndexes; i++ ) { - IndexDetails& ii = d->indexes[i]; + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) { + IndexDetails& ii = i.next(); if ( indexWorks( ii.keyPattern(), min.isEmpty() ? max : min, ret.first, ret.second ) ) { id = ⅈ keyPattern = ii.keyPattern(); @@ -574,8 +580,9 @@ namespace mongo { errmsg = "requested keyPattern does not match specified keys"; return 0; } - for (int i = 0; i < d->nIndexes; i++ ) { - IndexDetails& ii = d->indexes[i]; + NamespaceDetails::IndexIterator i = d->ii(); + while( i.more() ) { + IndexDetails& ii = i.next(); if( ii.keyPattern().woCompare(keyPattern) == 0 ) { id = ⅈ break; diff --git a/db/repl.cpp b/db/repl.cpp index 92de5f02a50..3ba2fb4d7be 100644 --- a/db/repl.cpp +++ b/db/repl.cpp @@ -1659,8 +1659,8 @@ namespace mongo { } } - log() << "******" << endl; - log() << "creating oplog size : " << (int)( sz / ( 1024 * 1024 ) ) << "mb" << endl; + log() << "******\n"; + log() << "creating oplog size : " << (int)( sz / ( 1024 * 1024 ) ) << "mb\n"; log() << "******" << endl; b.append("size", sz); diff --git a/dbtests/cursortests.cpp b/dbtests/cursortests.cpp index 633532e5ad1..bee0491b876 100644 --- a/dbtests/cursortests.cpp +++ b/dbtests/cursortests.cpp @@ -125,7 +125,7 @@ namespace CursorTests { b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 1 ), BSON( "" << 2 ) ) ); b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 4 ), BSON( "" << 6 ) ) ); setClient( ns ); - BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->indexes[ 1 ], b, 1 ); + BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->idx(1), b, 1 ); ASSERT_EQUALS( "BtreeCursor a_1 multi", c.toString() ); double expected[] = { 1, 2, 4, 5, 6 }; for( int i = 0; i < 5; ++i ) { @@ -155,7 +155,7 @@ namespace CursorTests { b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 40 ), BSON( "" << 60 ) ) ); b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 109 ), BSON( "" << 200 ) ) ); setClient( ns ); - BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->indexes[ 1 ], b, 1 ); + BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->idx(1), b, 1 ); ASSERT_EQUALS( "BtreeCursor a_1 multi", c.toString() ); double expected[] = { 0, 1, 2, 109 }; for( int i = 0; i < 4; ++i ) { @@ -182,7 +182,7 @@ namespace CursorTests { b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 6 ), BSON( "" << 4 ) ) ); b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 2 ), BSON( "" << 1 ) ) ); setClient( ns ); - BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->indexes[ 1 ], b, -1 ); + BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->idx(1), b, -1 ); ASSERT_EQUALS( "BtreeCursor a_1 reverse multi", c.toString() ); double expected[] = { 6, 5, 4, 2, 1 }; for( int i = 0; i < 5; ++i ) { diff --git a/dbtests/queryoptimizertests.cpp b/dbtests/queryoptimizertests.cpp index 39dc16992ea..1d00a715ec9 100644 --- a/dbtests/queryoptimizertests.cpp +++ b/dbtests/queryoptimizertests.cpp @@ -324,8 +324,8 @@ namespace QueryOptimizerTests { client_.ensureIndex( ns(), key, false, name.c_str() ); NamespaceDetails *d = nsd(); for( int i = 0; i < d->nIndexes; ++i ) { - if ( d->indexes[ i ].indexName() == name || ( d->indexes[ i ].isIdIndex() && IndexDetails::isIdIndexPattern( key ) ) ) - return &d->indexes[ i ]; + if ( d->idx(i).indexName() == name || ( d->idx(i).isIdIndex() && IndexDetails::isIdIndexPattern( key ) ) ) + return &d->idx(i); } assert( false ); return 0; diff --git a/debian/rules b/debian/rules old mode 100755 new mode 100644 diff --git a/jstests/index_many.js b/jstests/index_many.js new file mode 100644 index 00000000000..7bce774fd87 --- /dev/null +++ b/jstests/index_many.js @@ -0,0 +1,33 @@ +t = db.many; + +t.drop(); +db.bar.drop(); + +t.save({x:9}); +t.save({x:19}); + +x = 2; +while( x < 60 ) { + patt={}; + patt[x] = 1; + if( x == 20 ) + patt = { x : 1 }; + t.ensureIndex(patt); + x++; +} + +// print( tojson(db.getLastErrorObj()) ); + +// 40 is the limit currently + +// print( t.getIndexes().length == 40, "40" ); + +assert( t.getIndexes().length == 40, "40" ); + +assert( t.find({x:9}).length() == 1, "b" ) ; + +t.renameCollection( "bar" ); + +assert( t.find({x:9}).length() == 0, "c" ) ; + +assert( db.bar.find({x:9}).length() == 1, "d" ) ;