[Pkg-mongodb-maintainers] [pkg-mongodb] 209/394: Imported Upstream version 2.0.6

Apollon Oikonomopoulos apoikos at moszumanska.debian.org
Wed Sep 21 13:58:55 UTC 2016


This is an automated email from the git hooks/post-receive script.

apoikos pushed a commit to branch master
in repository pkg-mongodb.

commit 3703a282eca7e79e91f4bd651b1b861b76dc6c68
Author: Antonin Kral <a.kral at bobek.cz>
Date:   Tue Jun 5 19:50:34 2012 +0200

    Imported Upstream version 2.0.6
---
 SConstruct                                  | 10 ++--
 bson/util/builder.h                         | 49 +++++++++-------
 client/dbclient_rs.cpp                      | 27 +++++++--
 client/dbclient_rs.h                        |  5 +-
 db/cloner.cpp                               |  6 +-
 db/compact.cpp                              |  5 ++
 db/dbwebserver.cpp                          | 11 ++--
 db/queryoptimizer.cpp                       | 51 +++++++++++------
 db/queryoptimizer.h                         |  1 +
 db/repl.cpp                                 |  2 +-
 db/repl/rs_initialsync.cpp                  | 45 +++++++++++----
 db/security_common.h                        |  4 +-
 doxygenConfig                               |  2 +-
 jstests/queryoptimizer7.js                  | 24 ++++++++
 jstests/queryoptimizera.js                  | 87 +++++++++++++++++++++++++++++
 jstests/replsets/replset7.js                | 46 +++++++++++++++
 jstests/replsets/slavedelay3.js             | 38 +++++++++++++
 jstests/slowNightly/sharding_passthrough.js |  2 +-
 rpm/mongo.spec                              |  2 +-
 s/d_migrate.cpp                             | 57 +++++++++++++------
 s/d_state.cpp                               |  9 +++
 shell/utils.js                              |  3 +-
 third_party/js-1.7/jsprf.c                  |  2 +
 util/net/sock.cpp                           | 26 ++++-----
 util/version.cpp                            |  2 +-
 25 files changed, 408 insertions(+), 108 deletions(-)

diff --git a/SConstruct b/SConstruct
index 3d40050..88ea3f8 100644
--- a/SConstruct
+++ b/SConstruct
@@ -713,11 +713,11 @@ if nix:
     env.Append( LIBS=[] )
 
     #make scons colorgcc friendly
-    env['ENV']['HOME'] = os.environ['HOME']
-    try:
-        env['ENV']['TERM'] = os.environ['TERM']
-    except KeyError:
-        pass
+    for key in ('HOME', 'TERM'):
+        try:
+            env['ENV'][key] = os.environ[key]
+        except KeyError:
+            pass
 
     if linux and has_option( "sharedclient" ):
         env.Append( LINKFLAGS=" -Wl,--as-needed -Wl,-zdefs " )
diff --git a/bson/util/builder.h b/bson/util/builder.h
index f189f58..a5c71a8 100644
--- a/bson/util/builder.h
+++ b/bson/util/builder.h
@@ -17,6 +17,7 @@
 
 #pragma once
 
+#include <cfloat>
 #include <string>
 #include <string.h>
 #include <stdio.h>
@@ -36,7 +37,7 @@ namespace mongo {
     const int BSONObjMaxUserSize = 16 * 1024 * 1024;
 
     /*
-       Sometimeswe we need objects slightly larger - an object in the replication local.oplog
+       Sometimes we need objects slightly larger - an object in the replication local.oplog
        is slightly larger than a user object for example.
     */
     const int BSONObjMaxInternalSize = BSONObjMaxUserSize + ( 16 * 1024 );
@@ -230,42 +231,51 @@ namespace mongo {
         void decouple(); // not allowed. not implemented.
     };
 
+    namespace {
 #if defined(_WIN32)
-#pragma warning( push )
-// warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
-#pragma warning( disable : 4996 )
+        int (*mongo_snprintf)(char *str, size_t size, const char *format, ...) = &sprintf_s;
+#else
+        int (*mongo_snprintf)(char *str, size_t size, const char *format, ...) = &snprintf;
 #endif
+    }
 
     /** stringstream deals with locale so this is a lot faster than std::stringstream for UTF8 */
     class StringBuilder {
     public:
+        static const size_t MONGO_DBL_SIZE = 3 + DBL_MANT_DIG - DBL_MIN_EXP;
+        static const size_t MONGO_S32_SIZE = 12;
+        static const size_t MONGO_U32_SIZE = 11;
+        static const size_t MONGO_S64_SIZE = 23;
+        static const size_t MONGO_U64_SIZE = 22;
+        static const size_t MONGO_S16_SIZE = 7;
+
         StringBuilder( int initsize=256 )
             : _buf( initsize ) {
         }
 
         StringBuilder& operator<<( double x ) {
-            return SBNUM( x , 25 , "%g" );
+            return SBNUM( x , MONGO_DBL_SIZE , "%g" );
         }
         StringBuilder& operator<<( int x ) {
-            return SBNUM( x , 11 , "%d" );
+            return SBNUM( x , MONGO_S32_SIZE , "%d" );
         }
         StringBuilder& operator<<( unsigned x ) {
-            return SBNUM( x , 11 , "%u" );
+            return SBNUM( x , MONGO_U32_SIZE , "%u" );
         }
         StringBuilder& operator<<( long x ) {
-            return SBNUM( x , 22 , "%ld" );
+            return SBNUM( x , MONGO_S64_SIZE , "%ld" );
         }
         StringBuilder& operator<<( unsigned long x ) {
-            return SBNUM( x , 22 , "%lu" );
+            return SBNUM( x , MONGO_U64_SIZE , "%lu" );
         }
         StringBuilder& operator<<( long long x ) {
-            return SBNUM( x , 22 , "%lld" );
+            return SBNUM( x , MONGO_S64_SIZE , "%lld" );
         }
         StringBuilder& operator<<( unsigned long long x ) {
-            return SBNUM( x , 22 , "%llu" );
+            return SBNUM( x , MONGO_U64_SIZE , "%llu" );
         }
         StringBuilder& operator<<( short x ) {
-            return SBNUM( x , 8 , "%hd" );
+            return SBNUM( x , MONGO_S16_SIZE , "%hd" );
         }
         StringBuilder& operator<<( char c ) {
             _buf.grow( 1 )[0] = c;
@@ -273,10 +283,12 @@ namespace mongo {
         }
 
         void appendDoubleNice( double x ) {
-            int prev = _buf.l;
-            char * start = _buf.grow( 32 );
-            int z = sprintf( start , "%.16g" , x );
+            const int prev = _buf.l;
+            const int maxSize = 32; 
+            char * start = _buf.grow( maxSize );
+            int z = mongo_snprintf( start , maxSize , "%.16g" , x );
             assert( z >= 0 );
+            assert( z < maxSize );
             _buf.l = prev + z;
             if( strchr(start, '.') == 0 && strchr(start, 'E') == 0 && strchr(start, 'N') == 0 ) {
                 write( ".0" , 2 );
@@ -308,15 +320,12 @@ namespace mongo {
         template <typename T>
         StringBuilder& SBNUM(T val,int maxSize,const char *macro)  {
             int prev = _buf.l;
-            int z = sprintf( _buf.grow(maxSize) , macro , (val) );
+            int z = mongo_snprintf( _buf.grow(maxSize) , maxSize , macro , (val) );
             assert( z >= 0 );
+            assert( z < maxSize );
             _buf.l = prev + z;
             return *this;
         }
     };
 
-#if defined(_WIN32)
-#pragma warning( pop )
-#endif
-
 } // namespace mongo
diff --git a/client/dbclient_rs.cpp b/client/dbclient_rs.cpp
index 4a8112b..c792656 100644
--- a/client/dbclient_rs.cpp
+++ b/client/dbclient_rs.cpp
@@ -303,12 +303,29 @@ namespace mongo {
         }
     }
 
-    void ReplicaSetMonitor::_checkStatus(DBClientConnection *conn) {
+    void ReplicaSetMonitor::_checkStatus( const string& hostAddr ) {
         BSONObj status;
 
-        if (!conn->runCommand("admin", BSON("replSetGetStatus" << 1), status) ||
-                !status.hasField("members") ||
-                status["members"].type() != Array) {
+        /* replSetGetStatus requires admin auth so use a connection from the pool,
+         * which are authenticated with the keyFile credentials.
+         */
+        ScopedDbConnection authenticatedConn( hostAddr );
+
+        if ( !authenticatedConn->runCommand( "admin", BSON( "replSetGetStatus" << 1 ), status )) {
+            LOG(1) << "dbclient_rs replSetGetStatus failed" << endl;
+            authenticatedConn.done(); // connection worked properly, but we got an error from server
+            return;
+        }
+
+        // Make sure we return when finished
+        authenticatedConn.done();
+
+        if( !status.hasField("members") ) { 
+            log() << "dbclient_rs error expected members field in replSetGetStatus result" << endl;
+            return;
+        }
+        if( status["members"].type() != Array) {
+            log() << "dbclient_rs error expected members field in replSetGetStatus result to be an array" << endl;
             return;
         }
 
@@ -523,7 +540,7 @@ namespace mongo {
             }
             
             _checkHosts( b.arr(), changed);
-            _checkStatus( conn );
+            _checkStatus( conn->getServerAddress() );
 
         }
         catch ( std::exception& e ) {
diff --git a/client/dbclient_rs.h b/client/dbclient_rs.h
index bf91f09..318b3cf 100644
--- a/client/dbclient_rs.h
+++ b/client/dbclient_rs.h
@@ -120,7 +120,7 @@ namespace mongo {
          * Use replSetGetStatus command to make sure hosts in host list are up
          * and readable.  Sets Node::ok appropriately.
          */
-        void _checkStatus(DBClientConnection *conn);
+        void _checkStatus( const string& hostAddr );
 
         /**
          * Add array of hosts to host list. Doesn't do anything if hosts are
@@ -181,9 +181,8 @@ namespace mongo {
         string _name;
         struct Node {
             Node( const HostAndPort& a , DBClientConnection* c ) 
-                : addr( a ) , conn(c) , ok(true) , 
+                : addr( a ) , conn(c) , ok( c != NULL ),
                   ismaster(false), secondary( false ) , hidden( false ) , pingTimeMillis(0) {
-                ok = conn.get() == NULL;
             }
 
             bool okForSecondaryQueries() const {
diff --git a/db/cloner.cpp b/db/cloner.cpp
index 26c2f74..6d5b095 100644
--- a/db/cloner.cpp
+++ b/db/cloner.cpp
@@ -169,7 +169,8 @@ namespace mongo {
                     getDur().commitIfNeeded();
                 }
                 catch( UserException& e ) {
-                    log() << "warning: exception cloning object in " << from_collection << ' ' << e.what() << " obj:" << js.toString() << '\n';
+                    error() << "error: exception cloning object in " << from_collection << ' ' << e.what() << " obj:" << js.toString() << '\n';
+                    throw;
                 }
 
                 RARELY if ( time( 0 ) - saveLast > 60 ) {
@@ -238,7 +239,8 @@ namespace mongo {
                     getDur().commitIfNeeded();
                 }
                 catch( UserException& e ) {
-                    log() << "warning: exception cloning object in " << from_collection << ' ' << e.what() << " obj:" << js.toString() << '\n';
+                    error() << "error: exception cloning object in " << from_collection << ' ' << e.what() << " obj:" << js.toString() << '\n';
+                    throw;
                 }
             }
         }
diff --git a/db/compact.cpp b/db/compact.cpp
index c6e5f77..c100006 100644
--- a/db/compact.cpp
+++ b/db/compact.cpp
@@ -180,6 +180,11 @@ namespace mongo {
             d->deletedList[i].writing().Null();
         }
 
+
+
+        // Start over from scratch with our extent sizing and growth
+        d->lastExtentSize=0;
+
         // before dropping indexes, at least make sure we can allocate one extent!
         uassert(14025, "compact error no space available to allocate", !allocateSpaceForANewRecord(ns, d, Record::HeaderSize+1, false).isNull());
 
diff --git a/db/dbwebserver.cpp b/db/dbwebserver.cpp
index 78c09c0..eb19ba3 100644
--- a/db/dbwebserver.cpp
+++ b/db/dbwebserver.cpp
@@ -79,11 +79,10 @@ namespace mongo {
         }
 
         bool allowed( const char * rq , vector<string>& headers, const SockAddr &from ) {
-            if ( from.isLocalHost() )
-                return true;
-
-            if ( ! _webUsers->haveAdminUsers() )
+            if ( from.isLocalHost() || !_webUsers->haveAdminUsers() ) {
+                cmdAuthenticate.authenticate( "admin", "RestUser", false );
                 return true;
+            }
 
             string auth = getHeader( rq , "Authorization" );
 
@@ -118,8 +117,10 @@ namespace mongo {
                     r << ha2;
                     string r1 = md5simpledigest( r.str() );
 
-                    if ( r1 == parms["response"] )
+                    if ( r1 == parms["response"] ) {
+                        cmdAuthenticate.authenticate( "admin", user["user"].str(), user[ "readOnly" ].isBoolean() && user[ "readOnly" ].boolean() );
                         return true;
+                    }
                 }
             }
 
diff --git a/db/queryoptimizer.cpp b/db/queryoptimizer.cpp
index 71ca657..8ec4cb4 100644
--- a/db/queryoptimizer.cpp
+++ b/db/queryoptimizer.cpp
@@ -214,22 +214,6 @@ doneCheckOrder:
         if ( willScanTable() ) {
             if ( _frs.nNontrivialRanges() ) {
                 checkTableScanAllowed( _frs.ns() );
-                
-                // if we are doing a table scan on _id
-                // and its a capped collection
-                // we disallow as its a common user error
-                // .system. and local collections are exempt
-                if ( _d && _d->capped && _frs.range( "_id" ).nontrivial() ) {
-                    if ( cc().isSyncThread() ||
-                         str::contains( _frs.ns() , ".system." ) || 
-                         str::startsWith( _frs.ns() , "local." ) ) {
-                        // ok
-                    }
-                    else {
-                        warning() << "_id query on capped collection without an _id index, performance will be poor collection: " << _frs.ns() << endl;
-                        //uassert( 14820, str::stream() << "doing _id query on a capped collection without an index is not allowed: " << _frs.ns() ,
-                    }
-                }
             }
             return findTableScan( _frs.ns(), _order, startLoc );
         }
@@ -486,12 +470,14 @@ doneCheckOrder:
                     _usingPrerecordedPlan = true;
                     _mayRecordPlan = false;
                     _plans.push_back( p );
+                    warnOnCappedIdTableScan();
                     return;
                 }
             }
         }
 
         addOtherPlans( false );
+        warnOnCappedIdTableScan();
     }
 
     void QueryPlanSet::addOtherPlans( bool checkFirst ) {
@@ -633,6 +619,31 @@ doneCheckOrder:
         }
         return _plans[0];
     }
+    
+    void QueryPlanSet::warnOnCappedIdTableScan() const {
+        // if we are doing a table scan on _id
+        // and it's a capped collection
+        // we warn as it's a common user error
+        // .system. and local collections are exempt
+        const char *ns = _frsp->ns();
+        NamespaceDetails *d = nsdetails( ns );
+        if ( d &&
+            d->capped &&
+            nPlans() == 1 &&
+            firstPlan()->willScanTable() &&
+            firstPlan()->multikeyFrs().range( "_id" ).nontrivial() ) {
+            if ( cc().isSyncThread() ||
+                str::contains( ns , ".system." ) ||
+                str::startsWith( ns , "local." ) ) {
+                // ok
+            }
+            else {
+                warning()
+                << "unindexed _id query on capped collection, "
+                << "performance will be poor collection: " << ns << endl;
+            }
+        }
+    }
 
     QueryPlanSet::Runner::Runner( QueryPlanSet &plans, QueryOp &op ) :
         _op( op ),
@@ -1247,8 +1258,12 @@ doneCheckOrder:
     void QueryUtilIndexed::clearIndexesForPatterns( const FieldRangeSetPair &frsp, const BSONObj &order ) {
         SimpleMutex::scoped_lock lk(NamespaceDetailsTransient::_qcMutex);
         NamespaceDetailsTransient& nsd = NamespaceDetailsTransient::get_inlock( frsp.ns() );
-        nsd.registerIndexForPattern( frsp._singleKey.pattern( order ), BSONObj(), 0 );
-        nsd.registerIndexForPattern( frsp._multiKey.pattern( order ), BSONObj(), 0 );
+        if ( frsp._singleKey.matchPossible() ) {
+            nsd.registerIndexForPattern( frsp._singleKey.pattern( order ), BSONObj(), 0 );
+        }
+        if ( frsp._multiKey.matchPossible() ) {
+            nsd.registerIndexForPattern( frsp._multiKey.pattern( order ), BSONObj(), 0 );
+        }
     }
     
     pair< BSONObj, long long > QueryUtilIndexed::bestIndexForPatterns( const FieldRangeSetPair &frsp, const BSONObj &order ) {
diff --git a/db/queryoptimizer.h b/db/queryoptimizer.h
index fea6c0b..78d169d 100644
--- a/db/queryoptimizer.h
+++ b/db/queryoptimizer.h
@@ -314,6 +314,7 @@ namespace mongo {
         }
         void init();
         void addHint( IndexDetails &id );
+        void warnOnCappedIdTableScan() const;
         class Runner {
         public:
             Runner( QueryPlanSet &plans, QueryOp &op );
diff --git a/db/repl.cpp b/db/repl.cpp
index 5edf0c2..8dcdd13 100644
--- a/db/repl.cpp
+++ b/db/repl.cpp
@@ -1115,7 +1115,7 @@ namespace mongo {
 
     bool OplogReader::commonConnect(const string& hostName) {
         if( conn() == 0 ) {
-            _conn = shared_ptr<DBClientConnection>(new DBClientConnection( false, 0, 0 /* tcp timeout */));
+            _conn = shared_ptr<DBClientConnection>(new DBClientConnection( false, 0, 60*10 /* tcp timeout */));
             string errmsg;
             ReplInfo r("trying to connect to sync source");
             if ( !_conn->connect(hostName.c_str(), errmsg) ||
diff --git a/db/repl/rs_initialsync.cpp b/db/repl/rs_initialsync.cpp
index 112d739..7065487 100644
--- a/db/repl/rs_initialsync.cpp
+++ b/db/repl/rs_initialsync.cpp
@@ -43,18 +43,24 @@ namespace mongo {
     }
 
     void ReplSetImpl::syncDoInitialSync() {
+        const static int maxFailedAttempts = 3;
         createOplog();
-
-        while( 1 ) {
+        int failedAttempts = 0;
+        while ( failedAttempts < maxFailedAttempts ) {
             try {
                 _syncDoInitialSync();
                 break;
             }
             catch(DBException& e) {
-                sethbmsg("initial sync exception " + e.toString(), 0);
+                failedAttempts++;
+                str::stream msg;
+                msg << "initial sync exception: ";
+                msg << e.toString() << " " << (maxFailedAttempts - failedAttempts) << " attempts remaining" ;
+                sethbmsg(msg, 0);
                 sleepsecs(30);
             }
         }
+        if ( failedAttempts >= maxFailedAttempts ) ::abort();
     }
 
     /* todo : progress metering to sethbmsg. */
@@ -80,7 +86,7 @@ namespace mongo {
     }
 
     const Member* ReplSetImpl::getMemberToSyncTo() {
-        Member *closest = 0;
+
         bool buildIndexes = true;
 
         // wait for 2N pings before choosing a sync target
@@ -95,16 +101,31 @@ namespace mongo {
             buildIndexes = myConfig().buildIndexes;
         }
 
+        Member *closest = 0;
+
         // find the member with the lowest ping time that has more data than me
-        for (Member *m = _members.head(); m; m = m->next()) {
-            if (m->hbinfo().up() &&
-                // make sure members with buildIndexes sync from other members w/indexes
-                (!buildIndexes || (buildIndexes && m->config().buildIndexes)) &&
-                (m->state() == MemberState::RS_PRIMARY ||
-                 (m->state() == MemberState::RS_SECONDARY && m->hbinfo().opTime > lastOpTimeWritten)) &&
-                (!closest || m->hbinfo().ping < closest->hbinfo().ping)) {
-                closest = m;
+
+        // Make two attempts.  The first attempt, we ignore those nodes with
+        // slave delay higher than our own.  The second attempt includes such
+        // nodes, in case those are the only ones we can reach.
+        for (int attempts = 0; attempts < 2; ++attempts) {
+            for (Member *m = _members.head(); m; m = m->next()) {
+                if (m->hbinfo().up() &&
+                    // make sure members with buildIndexes sync from other members w/indexes
+                    (!buildIndexes || (buildIndexes && m->config().buildIndexes)) &&
+                    (m->state() == MemberState::RS_PRIMARY ||
+                     (m->state() == MemberState::RS_SECONDARY && 
+                      m->hbinfo().opTime > lastOpTimeWritten)) &&
+                    (!closest || m->hbinfo().ping < closest->hbinfo().ping)) {
+
+                    if ( attempts == 0 && 
+                         myConfig().slaveDelay < m->config().slaveDelay ) {
+                        break; // skip this one in the first attempt
+                    }
+                    closest = m;
+                }
             }
+            if (closest) break; // no need for second attempt
         }
 
         {
diff --git a/db/security_common.h b/db/security_common.h
index c9a3e3a..80a7450 100644
--- a/db/security_common.h
+++ b/db/security_common.h
@@ -61,10 +61,12 @@ namespace mongo {
         virtual void help(stringstream& ss) const { ss << "internal"; }
         CmdAuthenticate() : Command("authenticate") {}
         bool run(const string& dbname , BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result, bool fromRepl);
+        void authenticate(const string& dbname, const string& user, const bool readOnly);
     private:
         bool getUserObj(const string& dbname, const string& user, BSONObj& userObj, string& pwd);
-        void authenticate(const string& dbname, const string& user, const bool readOnly);
     };
+    
+    extern CmdAuthenticate cmdAuthenticate;
 
     class CmdLogout : public Command {
     public:
diff --git a/doxygenConfig b/doxygenConfig
index afe9177..0be602d 100644
--- a/doxygenConfig
+++ b/doxygenConfig
@@ -3,7 +3,7 @@
 #---------------------------------------------------------------------------
 DOXYFILE_ENCODING      = UTF-8
 PROJECT_NAME           = MongoDB
-PROJECT_NUMBER         = 2.0.5
+PROJECT_NUMBER         = 2.0.6
 OUTPUT_DIRECTORY       = docs/doxygen
 CREATE_SUBDIRS         = NO
 OUTPUT_LANGUAGE        = English
diff --git a/jstests/queryoptimizer7.js b/jstests/queryoptimizer7.js
new file mode 100644
index 0000000..c4ff75b
--- /dev/null
+++ b/jstests/queryoptimizer7.js
@@ -0,0 +1,24 @@
+// Test query retry with a query that is non multikey unusable and unsatisfiable.  SERVER-5581
+
+t = db.jstests_queryoptimizer7;
+t.drop();
+
+t.ensureIndex( { a:1 } );
+t.ensureIndex( { b:1 } );
+
+for( i = 0; i < 25; ++i ) {
+    t.save( { a:0, b:'' } ); // a:0 documents have small b strings.
+}
+big = new Array( 1000000 ).toString();
+for( i = 0; i < 50; ++i ) {
+    t.save( { a:[1,3], b:big } ); // a:[1,3] documents have very large b strings.
+}
+
+// Record the a:1 index for the query pattern for { a: { $lt:1 } }, { b:1 }.
+assert.eq( 'BtreeCursor a_1', t.find( { a:{ $lt:1 } } ).sort( { b:1 } ).explain().cursor );
+
+// The multikey query pattern for this query will match that of the previous query.
+// The a:1 index will be retried for this query but fail because an in memory sort must
+// be performed on a larger data set.  Because the query { a:{ $lt:2, $gt:2 } } is
+// unsatisfiable, no attempt will be made to clear its query pattern.
+assert.lt( -1, t.find( { a:{ $lt:2, $gt:2 } } ).sort( { b:1 } ).itcount() );
diff --git a/jstests/queryoptimizera.js b/jstests/queryoptimizera.js
new file mode 100644
index 0000000..48d7ccf
--- /dev/null
+++ b/jstests/queryoptimizera.js
@@ -0,0 +1,87 @@
+// Check that a warning message about doing a capped collection scan for a query with an _id
+// constraint is printed at appropriate times.  SERVER-5353
+
+function numWarnings() {
+    logs = db.adminCommand( { getLog:"global" } ).log
+    ret = 0;
+    logs.forEach( function( x ) {
+                 if ( x.match( warningMatchRegexp ) ) {
+                 ++ret;
+                 }
+                 } );
+    return ret;
+}
+
+collectionNameIndex = 0;
+
+// Generate a collection name not already present in the log.
+do {
+    testCollectionName = 'jstests_queryoptimizera__' + collectionNameIndex++;
+    warningMatchString = 'unindexed _id query on capped collection.*collection: test.' +
+        testCollectionName;
+    warningMatchRegexp = new RegExp( warningMatchString );    
+    
+} while( numWarnings() > 0 );
+
+t = db[ testCollectionName ];
+t.drop();
+
+notCappedCollectionName = testCollectionName + '_notCapped';
+
+notCapped = db[ notCappedCollectionName ];
+notCapped.drop();
+
+db.createCollection( testCollectionName, { capped:true, size:1000 } );
+db.createCollection( notCappedCollectionName, { autoIndexId:false } );
+
+t.insert( {} );
+notCapped.insert( {} );
+
+oldNumWarnings = 0;
+
+function assertNoNewWarnings() {
+    assert.eq( oldNumWarnings, numWarnings() );
+}
+
+function assertNewWarning() {
+    ++oldNumWarnings;
+    assert.eq( oldNumWarnings, numWarnings() );
+}
+
+// Simple _id query without an _id index.
+t.find( { _id:0 } ).itcount();
+assertNewWarning();
+
+// Simple _id query without an _id index, on a non capped collection.
+notCapped.find( { _id:0 } ).itcount();
+assertNoNewWarnings();
+
+// A multi field query, including _id.
+t.find( { _id:0, a:0 } ).itcount();
+assertNewWarning();
+
+// An unsatisfiable query.
+t.find( { _id:0, a:{$in:[]} } ).itcount();
+assertNoNewWarnings();
+
+// An hinted query.
+t.find( { _id:0 } ).hint( { $natural:1 } ).itcount();
+assertNoNewWarnings();
+
+// Retry a multi field query.
+t.find( { _id:0, a:0 } ).itcount();
+assertNewWarning();
+
+// Warnings should not be printed when an index is added on _id.
+t.ensureIndex( { _id:1 } );
+
+t.find( { _id:0 } ).itcount();
+assertNoNewWarnings();
+
+t.find( { _id:0, a:0 } ).itcount();
+assertNoNewWarnings();
+
+t.find( { _id:0, a:0 } ).itcount();
+assertNoNewWarnings();
+
+t.drop(); // cleanup
diff --git a/jstests/replsets/replset7.js b/jstests/replsets/replset7.js
new file mode 100644
index 0000000..f29c1fb
--- /dev/null
+++ b/jstests/replsets/replset7.js
@@ -0,0 +1,46 @@
+
+// test for SERVER-5040 - if documents move forward during an initial sync.
+
+var rt = new ReplSetTest( { name : "replset7tests" , nodes: 1 } );
+
+var nodes = rt.startSet();
+rt.initiate();
+var master = rt.getMaster();
+
+var md = master.getDB( 'd' );
+var mdc = md[ 'c' ];
+
+// prep the data
+var doccount = 100000;
+for( i = 0; i < doccount; ++i ) {
+    mdc.insert( { _id:i, x:i } );
+}
+md.getLastError();
+
+mdc.ensureIndex( { x : 1 }, { unique: true } );
+md.getLastError();
+
+// add a secondary
+var slave = rt.add();
+rt.reInitiate();
+print ("initiation complete!");
+var sc = slave.getDB( 'd' )[ 'c' ];
+slave.setSlaveOk();
+
+// Wait for slave to start cloning.
+//assert.soon( function() { c = sc.find( { _id:1, x:1 } ); print( c ); return c > 0; } );
+
+
+// Move all documents to the end by growing it
+for (i = 0; i < doccount; ++i) {
+    mdc.remove( { _id:i, x:i } );
+    mdc.insert( { _id:doccount+i, x:i, bigstring: "ayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayayay" } );
+    md.getLastError();
+}
+
+// Wait for replication to catch up.
+rt.awaitSecondaryNodes();
+
+// Do we have an index?
+assert.eq (1, slave.getDB( 'd' )['system.indexes']
+           .find({"v" : 1,"key" : {"x" : 1},"unique" : true,"ns" : "d.c","name" : "x_1"}).count());
diff --git a/jstests/replsets/slavedelay3.js b/jstests/replsets/slavedelay3.js
new file mode 100644
index 0000000..e89fe96
--- /dev/null
+++ b/jstests/replsets/slavedelay3.js
@@ -0,0 +1,38 @@
+load("jstests/replsets/rslib.js");
+
+var name = 'slavedelay3';
+var replTest = new ReplSetTest({ name: name, nodes: 3 });
+var nodes = replTest.startSet();
+var config = replTest.getReplSetConfig();
+// ensure member 0 is primary
+config.members[0].priority = 2;
+config.members[1].priority = 0;
+config.members[1].slaveDelay = 5;
+
+replTest.initiate(config);
+replTest.awaitReplication();
+replTest.bridge();
+
+
+var master = replTest.getMaster().getDB(name);
+ var slaveConns = replTest.liveNodes.slaves;
+ var slave = [];
+ for (var i in slaveConns) {
+     var d = slaveConns[i].getDB(name);
+     d.getMongo().setSlaveOk();
+     slave.push(d);
+ }
+
+waitForAllMembers(master);
+
+
+
+replTest.partition(0,2);
+replTest.awaitReplication();
+
+master.foo.insert({x:1});
+
+// make sure the record still appears in the remote slave
+assert.soon( function() { return slave[1].foo.findOne() != null; } );
+
+replTest.stopSet();
\ No newline at end of file
diff --git a/jstests/slowNightly/sharding_passthrough.js b/jstests/slowNightly/sharding_passthrough.js
index d81df68..fa1f7bc 100644
--- a/jstests/slowNightly/sharding_passthrough.js
+++ b/jstests/slowNightly/sharding_passthrough.js
@@ -72,7 +72,7 @@ files.forEach(
 	    return;
 	}
 	// These aren't supposed to get run under sharding:
-	if (/[\/\\](dbadmin|error1|fsync|fsync2|geo.*|indexh|remove5|update4|notablescan|compact.*|check_shard_index|bench_test.*|mr_replaceIntoDB)\.js$/.test(x.name)) {
+	if (/[\/\\](dbadmin|error1|fsync|fsync2|geo.*|indexh|remove5|update4|notablescan|compact.*|check_shard_index|bench_test.*|mr_replaceIntoDB|queryoptimizera)\.js$/.test(x.name)) {
 	    print(" >>>>>>>>>>>>>>> skipping test that would fail under sharding " + x.name)	    
 	    return;
 	}
diff --git a/rpm/mongo.spec b/rpm/mongo.spec
index 260274c..5745ab5 100644
--- a/rpm/mongo.spec
+++ b/rpm/mongo.spec
@@ -1,5 +1,5 @@
 Name: mongo
-Version: 2.0.5
+Version: 2.0.6
 Release: mongodb_1%{?dist}
 Summary: mongo client shell and tools
 License: AGPL 3.0
diff --git a/s/d_migrate.cpp b/s/d_migrate.cpp
index 731761f..918dd86 100644
--- a/s/d_migrate.cpp
+++ b/s/d_migrate.cpp
@@ -482,32 +482,53 @@ namespace mongo {
             
             while ( 1 ) {
                 bool filledBuffer = false;
-                
-                readlock l( _ns );
-                Client::Context ctx( _ns );
-                scoped_spinlock lk( _trackerLocks );
-                set<DiskLoc>::iterator i = _cloneLocs.begin();
-                for ( ; i!=_cloneLocs.end(); ++i ) {
-                    if (tracker.ping()) // should I yield?
-                        break;
 
-                    DiskLoc dl = *i;
-                    BSONObj o = dl.obj();
+                auto_ptr<RWLockRecursive::Shared> fileLock;
+                Record* recordToTouch = NULL;
 
-                    // use the builder size instead of accumulating 'o's size so that we take into consideration
-                    // the overhead of BSONArray indices
-                    if ( a.len() + o.objsize() + 1024 > BSONObjMaxUserSize ) {
-                        filledBuffer = true; // break out of outer while loop
-                        break;
-                    }
+                {
+                    readlock rlk(_ns);
+                    Client::Context ctx( _ns ); // ReadContext?
+                    scoped_spinlock lk( _trackerLocks );
+                    set<DiskLoc>::iterator i = _cloneLocs.begin();
+                    for ( ; i!=_cloneLocs.end(); ++i ) {
+                        if (tracker.ping()) // should I yield?
+                            break;
 
-                    a.append( o );
-                }
+                        DiskLoc dl = *i;
+                        Record* r = dl.rec();
+                        if ( ! r->likelyInPhysicalMemory() ) {
+                            fileLock.reset( new RWLockRecursive::Shared( MongoFile::mmmutex) );
+                            recordToTouch = r;
+                            break;
+                        }
+
+                        BSONObj o = dl.obj();
+
+                        // use the builder size instead of accumulating 'o's size so that we take into consideration
+                        // the overhead of BSONArray indices
+                        if ( a.len() + o.objsize() + 1024 > BSONObjMaxUserSize ) {
+                            filledBuffer = true; // break out of outer while loop
+                            break;
+                        }
+
+                        a.append( o );
+                    }
 
                 _cloneLocs.erase( _cloneLocs.begin() , i );
 
                 if ( _cloneLocs.empty() || filledBuffer )
                     break;
+                }
+                if ( recordToTouch ) {
+                    // its safe to touch here because we have a LockMongoFilesShared
+                    // we can't do where we get the lock because we would have to unlock the main readlock and tne _trackerLocks
+                    // simpler to handle this out there
+                    recordToTouch->touch();
+                    recordToTouch = NULL;
+                }
+
+
             }
 
             result.appendArray( "objects" , a.arr() );
diff --git a/s/d_state.cpp b/s/d_state.cpp
index 638d8c1..ef933a0 100644
--- a/s/d_state.cpp
+++ b/s/d_state.cpp
@@ -614,6 +614,15 @@ namespace mongo {
             }
 
             if ( globalVersion == 0 && ! authoritative ) {
+                // Needed b/c when the last chunk is moved off a shard, the version gets reset to zero, which
+                // should require a reload.
+                // TODO: Maybe a more elegant way of doing this
+                while ( shardingState.inCriticalMigrateSection() ) {
+                    dbtemprelease r;
+                    sleepmillis(2);
+                    OCCASIONALLY log() << "waiting till out of critical section for version reset" << endl;
+                }
+
                 // need authoritative for first look
                 result.append( "ns" , ns );
                 result.appendBool( "need_authoritative" , true );
diff --git a/shell/utils.js b/shell/utils.js
index 7d7a23b..4e20603 100644
--- a/shell/utils.js
+++ b/shell/utils.js
@@ -739,7 +739,8 @@ if ( typeof _threadInject != "undefined" ){
                                    "jstests/notablescan.js",
                                    "jstests/drop2.js",
                                    "jstests/dropdb_race.js",
-                                   "jstests/bench_test1.js"] );
+                                   "jstests/bench_test1.js",
+                                   "jstests/queryoptimizera.js"] );
         
         // some tests can't be run in parallel with each other
         var serialTestsArr = [ "jstests/fsync.js",
diff --git a/third_party/js-1.7/jsprf.c b/third_party/js-1.7/jsprf.c
index 416c16c..6735520 100644
--- a/third_party/js-1.7/jsprf.c
+++ b/third_party/js-1.7/jsprf.c
@@ -58,6 +58,8 @@
 */
 #ifdef HAVE_VA_COPY
 #define VARARGS_ASSIGN(foo, bar)        VA_COPY(foo,bar)
+#elif defined(va_copy)
+#define VARARGS_ASSIGN(foo, bar)        va_copy(foo,bar)
 #elif defined(HAVE_VA_LIST_AS_ARRAY)
 #define VARARGS_ASSIGN(foo, bar)        foo[0] = bar[0]
 #else
diff --git a/util/net/sock.cpp b/util/net/sock.cpp
index ac565c3..a032e50 100644
--- a/util/net/sock.cpp
+++ b/util/net/sock.cpp
@@ -52,10 +52,18 @@ namespace mongo {
         tv.tv_usec = (int)((long long)(secs*1000*1000) % (1000*1000));
         bool report = logLevel > 3; // solaris doesn't provide these
         DEV report = true;
-        bool ok = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv) ) == 0;
-        if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << endl;
-        ok = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, sizeof(tv) ) == 0;
-        DEV if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << endl;
+#if defined(_WIN32)
+        tv.tv_sec *= 1000; // Windows timeout is a DWORD, in milliseconds.
+        int status = setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv.tv_sec, sizeof(DWORD) ) == 0;
+        if( report && (status == SOCKET_ERROR) ) log() << "unable to set SO_RCVTIMEO" << endl;
+        status = setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv.tv_sec, sizeof(DWORD) ) == 0;
+        DEV if( report && (status == SOCKET_ERROR) ) log() << "unable to set SO_SNDTIMEO" << endl;
+#else
+        bool ok = setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv) ) == 0;
+        if( report && !ok ) log() << "unable to set SO_RCVTIMEO" << endl;
+        ok = setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, sizeof(tv) ) == 0;
+        DEV if( report && !ok ) log() << "unable to set SO_SNDTIMEO" << endl;
+#endif
     }
 
 #if defined(_WIN32)
@@ -755,15 +763,7 @@ namespace mongo {
     }
 
     void Socket::setTimeout( double secs ) {
-        struct timeval tv;
-        tv.tv_sec = (int)secs;
-        tv.tv_usec = (int)((long long)(secs*1000*1000) % (1000*1000));
-        bool report = logLevel > 3; // solaris doesn't provide these
-        DEV report = true;
-        bool ok = setsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv) ) == 0;
-        if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << endl;
-        ok = setsockopt(_fd, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, sizeof(tv) ) == 0;
-        DEV if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << endl;
+        setSockTimeouts( _fd, secs );
     }
 
 #if defined(_WIN32)
diff --git a/util/version.cpp b/util/version.cpp
index 8b08ff4..03ff548 100644
--- a/util/version.cpp
+++ b/util/version.cpp
@@ -38,7 +38,7 @@ namespace mongo {
      *      1.2.3-rc4-pre-
      * If you really need to do something else you'll need to fix _versionArray()
      */
-    const char versionString[] = "2.0.5";
+    const char versionString[] = "2.0.6";
 
     // See unit test for example outputs
     static BSONArray _versionArray(const char* version){

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mongodb/pkg-mongodb.git



More information about the Pkg-mongodb-maintainers mailing list