diff --git a/db/clientcursor.cpp b/db/clientcursor.cpp index 2de855136c7..4ac5d87ae45 100644 --- a/db/clientcursor.cpp +++ b/db/clientcursor.cpp @@ -103,7 +103,7 @@ namespace mongo { /* must call when a btree bucket going away. note this is potentially slow */ - inline void ClientCursor::informAboutToDeleteBucket(const DiskLoc& b) { + void ClientCursor::informAboutToDeleteBucket(const DiskLoc& b) { recursive_boostlock lock(ccmutex); RARELY if ( byLoc.size() > 70 ) { log() << "perf warning: byLoc.size=" << byLoc.size() << " in aboutToDeleteBucket\n"; diff --git a/db/database.h b/db/database.h index d03dcbc37f5..a09d932daa3 100644 --- a/db/database.h +++ b/db/database.h @@ -153,6 +153,12 @@ namespace mongo { return f; } + Extent* allocExtent( const char *ns, int size, bool capped ) { + Extent *e = DataFileMgr::allocFromFreeList( ns, size, capped ); + if( e ) return e; + return suitableFile( size )->createExtent( ns, size, capped ); + } + MongoDataFile* newestFile() { int n = (int) files.size(); if ( n > 0 ) n--; diff --git a/db/pdfile.cpp b/db/pdfile.cpp index 5e2588648d0..6df2a2475be 100644 --- a/db/pdfile.cpp +++ b/db/pdfile.cpp @@ -99,7 +99,8 @@ namespace mongo { /* todo: do this only when we have allocated space successfully? or we could insert with a { ok: 0 } field and then go back and set to ok : 1 after we are done. */ - if( strstr(ns, ".$freelist") == 0 ) + bool isFreeList = strstr(ns, ".$freelist") != 0; + if( !isFreeList ) addNewNamespaceToCatalog(ns, j.isEmpty() ? 0 : &j); long long size = initialExtentSize(128); @@ -131,16 +132,18 @@ namespace mongo { if ( nExtents > 0 ) { assert( size <= 0x7fffffff ); for ( int i = 0; i < nExtents; ++i ) { - database->suitableFile((int) size)->allocExtent( ns, (int) size, newCapped ); + assert( size <= 0x7fffffff ); + database->allocExtent( ns, (int) size, newCapped ); } } else { while ( size > 0 ) { int max = MongoDataFile::maxSize() - MDFHeader::headerSize(); int desiredExtentSize = (int) (size > max ? max : size); - Extent *e = database->suitableFile( desiredExtentSize )->allocExtent( ns, desiredExtentSize, newCapped ); + Extent *e = database->allocExtent( ns, desiredExtentSize, newCapped ); size -= e->length; } if ( !newCapped ) { + // check if it's time to preallocate a new file, and if so queue that job for a bg thread // ok to call this multiple times database->preallocateAFile(); } @@ -320,7 +323,7 @@ namespace mongo { return e; } - Extent* MongoDataFile::allocExtent(const char *ns, int approxSize, bool capped) { + Extent* DataFileMgr::allocFromFreeList(const char *ns, int approxSize, bool capped) { string s = cc().database()->name + ".$freelist"; NamespaceDetails *f = nsdetails(s.c_str()); if( f ) { @@ -378,7 +381,8 @@ namespace mongo { } } - return createExtent(ns, approxSize, capped); + return 0; + // return createExtent(ns, approxSize, capped); } /*---------------------------------------------------------------------*/ @@ -552,6 +556,24 @@ namespace mongo { } } + void printFreeList() { + string s = cc().database()->name + ".$freelist"; + log() << "dump freelist " << s << '\n'; + NamespaceDetails *freeExtents = nsdetails(s.c_str()); + if( freeExtents == 0 ) { + log() << " freeExtents==0" << endl; + return; + } + DiskLoc a = freeExtents->firstExtent; + while( !a.isNull() ) { + Extent *e = a.ext(); + log() << " " << a.toString() << " len:" << e->length << " prev:" << e->xprev.toString() << '\n'; + a = e->xnext; + } + + log() << " end freelist" << endl; + } + /* drop a collection/namespace */ void dropNS(const string& nsToDrop) { NamespaceDetails* d = nsdetails(nsToDrop.c_str()); @@ -1336,7 +1358,7 @@ namespace mongo { also if this is an addIndex, those checks should happen before this! */ // This creates first file in the database. - cc().database()->newestFile()->allocExtent(ns, initialExtentSize(len)); + cc().database()->newestFile()->createExtent(ns, initialExtentSize(len)); d = nsdetails(ns); if ( !god ) ensureIdIndexForNewNs(ns); @@ -1436,13 +1458,13 @@ namespace mongo { // out of space if ( d->capped == 0 ) { // size capped doesn't grow log(1) << "allocating new extent for " << ns << " padding:" << d->paddingFactor << " lenWHdr: " << lenWHdr << endl; - cc().database()->newestFile()->allocExtent(ns, followupExtentSize(lenWHdr, d->lastExtentSize)); + cc().database()->allocExtent(ns, followupExtentSize(lenWHdr, d->lastExtentSize), false); loc = d->alloc(ns, lenWHdr, extentLoc); if ( loc.isNull() ){ log() << "WARNING: alloc() failed after allocating new extent. lenWHdr: " << lenWHdr << " last extent size:" << d->lastExtentSize << "; trying again\n"; for ( int zzz=0; zzz<10 && lenWHdr > d->lastExtentSize; zzz++ ){ log() << "try #" << zzz << endl; - cc().database()->newestFile()->allocExtent(ns, followupExtentSize(len, d->lastExtentSize)); + cc().database()->allocExtent(ns, followupExtentSize(len, d->lastExtentSize), false); loc = d->alloc(ns, lenWHdr, extentLoc); if ( ! loc.isNull() ) break; diff --git a/db/pdfile.h b/db/pdfile.h index 9c92dc51624..5f108f11204 100644 --- a/db/pdfile.h +++ b/db/pdfile.h @@ -70,11 +70,6 @@ namespace mongo { */ Extent* createExtent(const char *ns, int approxSize, bool capped = false, int loops = 0); - /* see if we can find an extent of the right size in the freelist. if not, - createExtent. - */ - Extent* allocExtent(const char *ns, int approxSize, bool capped = false); - MDFHeader *getHeader() { return header; } @@ -99,6 +94,9 @@ namespace mongo { public: void init(const string& path ); + /* see if we can find an extent of the right size in the freelist. */ + static Extent* allocFromFreeList(const char *ns, int approxSize, bool capped = false); + /** @return DiskLoc where item ends up */ const DiskLoc update( const char *ns, diff --git a/util/file_allocator.h b/util/file_allocator.h index f3765459e51..b53ebc32fe0 100644 --- a/util/file_allocator.h +++ b/util/file_allocator.h @@ -49,6 +49,10 @@ namespace mongo { // May be called if file exists. If file exists, or its allocation has // been requested, size is updated to match existing file size. void requestAllocation( const string &name, long &size ) { + /* Some of the system calls in the file allocator don't work in win, + so no win support - 32 or 64 bit. Plus we don't seem to need preallocation + on windows anyway as we don't have to pre-zero the file there. + */ #if !defined(_WIN32) boostlock lk( pendingMutex_ ); long oldSize = prevSize( name );