diff options
author | Dwight <dmerriman@gmail.com> | 2009-10-21 16:00:40 -0400 |
---|---|---|
committer | Dwight <dmerriman@gmail.com> | 2009-10-21 16:00:40 -0400 |
commit | 844d96c19f45fba8c3eb1ed08df95493fc76ec98 (patch) | |
tree | 7ba582877f3ce600cfb1c74ce47638d3967c0d70 /db/namespace.h | |
parent | b2b90b5568d742577cb0acbcf3e9561432bf21cd (diff) | |
download | mongo-844d96c19f45fba8c3eb1ed08df95493fc76ec98.tar.gz |
allow more indexes
do not revert to an earlier db version or you will have problems
Diffstat (limited to 'db/namespace.h')
-rw-r--r-- | db/namespace.h | 146 |
1 files changed, 114 insertions, 32 deletions
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 <MaxIndexes ); - multiKeyIndexBits |= (1 << i); + dassert( i < NIndexesMax ); + multiKeyIndexBits |= (((unsigned long long) 1) << i); } void clearIndexIsMultikey(int i) { - dassert( i < 32 && i <MaxIndexes ); - multiKeyIndexBits &= ~(1 << i); + dassert( i < NIndexesMax ); + multiKeyIndexBits &= ~(((unsigned long long) 1) << i); } - /* you MUST call when adding an index. see pdfile.cpp */ - void addingIndex(const char *thisns, IndexDetails& details); + /* add a new index. does not add to system.indexes etc. - just to NamespaceDetails. + caller must populate returned object. + */ + IndexDetails& addIndex(const char *thisns); void aboutToDeleteAnIndex() { flags &= ~Flag_HaveIdIndex; @@ -368,9 +435,10 @@ namespace mongo { //returns offset in indexes[] int findIndexByName(const char *name) { - for ( int i = 0; i < nIndexes; i++ ) { - if ( strcmp(indexes[i].info.obj().getStringField("name"),name) == 0 ) - return i; + IndexIterator i = ii(); + while( i.more() ) { + if ( strcmp(i.next().info.obj().getStringField("name"),name) == 0 ) + return i.pos()-1; } return -1; } @@ -379,9 +447,10 @@ namespace mongo { generally id is first index, so not that expensive an operation (assuming present). */ int findIdIndex() { - for( int i = 0; i < nIndexes; i++ ) { - if( indexes[i].isIdIndex() ) - return i; + IndexIterator i = ii(); + while( i.more() ) { + if( i.next().isIdIndex() ) + return i.pos()-1; } return -1; } @@ -514,6 +583,7 @@ namespace mongo { */ class NamespaceIndex { friend class NamespaceCursor; + BOOST_STATIC_ASSERT( sizeof(NamespaceDetails::Extra) <= sizeof(NamespaceDetails) ); public: NamespaceIndex(const string &dir, const string &database) : ht( 0 ), @@ -543,6 +613,23 @@ namespace mongo { return ((char *) d) - (char *) ht->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 ) { |