From 8d913e98e8058c6322975a858f884a769735bb43 Mon Sep 17 00:00:00 2001
From: Antonin Kral <a.kral@bobek.cz>
Date: Thu, 7 Apr 2011 07:35:46 +0200
Subject: Imported Upstream version 1.8.1

---
 db/cap.cpp            |   1 +
 db/db.cpp             |  29 +++++++++--
 db/dbhelpers.cpp      |   1 +
 db/dur_commitjob.cpp  |   6 ++-
 db/lasterror.cpp      | 134 +++++---------------------------------------------
 db/lasterror.h        |  19 ++-----
 db/pdfile.cpp         |   8 ++-
 db/query.cpp          |  34 ++++++++-----
 db/repl/rs_config.cpp |   6 +--
 db/update.cpp         |   5 +-
 10 files changed, 79 insertions(+), 164 deletions(-)

(limited to 'db')

diff --git a/db/cap.cpp b/db/cap.cpp
index 198bd54..260b311 100644
--- a/db/cap.cpp
+++ b/db/cap.cpp
@@ -319,6 +319,7 @@ namespace mongo {
                 // 'end' has been found and removed, so break.
                 break;
             }
+            getDur().commitIfNeeded();
             // 'curr' will point to the newest document in the collection.
             DiskLoc curr = theCapExtent()->lastRecord;
             assert( !curr.isNull() );
diff --git a/db/db.cpp b/db/db.cpp
index 548ac14..97869c5 100644
--- a/db/db.cpp
+++ b/db/db.cpp
@@ -808,7 +808,7 @@ int main(int argc, char* argv[]) {
             cmdLine.durOptions = params["durOptions"].as<int>();
         }
         if (params.count("journalOptions")) {
-            cmdLine.durOptions = params["durOptions"].as<int>();
+            cmdLine.durOptions = params["journalOptions"].as<int>();
         }
         if (params.count("objcheck")) {
             objcheck = true;
@@ -1116,6 +1116,19 @@ namespace mongo {
         dbexit( EXIT_ABRUPT );
     }
 
+    void abruptQuitWithAddrSignal( int signal, siginfo_t *siginfo, void * ) {
+        ostringstream oss;
+        oss << "Invalid";
+        if ( signal == SIGSEGV || signal == SIGBUS ) {
+            oss << " access";
+        } else {
+            oss << " operation";   
+        }
+        oss << " at address: " << siginfo->si_addr << endl;
+        rawOut( oss.str() );
+        abruptQuit( signal );   
+    }
+        
     sigset_t asyncSignals;
     // The above signals will be processed by this thread only, in order to
     // ensure the db and log mutexes aren't held.
@@ -1138,10 +1151,18 @@ namespace mongo {
     void setupSignals_ignoreHelper( int signal ) {}
 
     void setupSignals( bool inFork ) {
-        assert( signal(SIGSEGV, abruptQuit) != SIG_ERR );
-        assert( signal(SIGFPE, abruptQuit) != SIG_ERR );
+        struct sigaction addrSignals;
+        memset( &addrSignals, 0, sizeof( struct sigaction ) );
+        addrSignals.sa_sigaction = abruptQuitWithAddrSignal;
+        sigemptyset( &addrSignals.sa_mask );
+        addrSignals.sa_flags = SA_SIGINFO;
+       
+        assert( sigaction(SIGSEGV, &addrSignals, 0) == 0 );
+        assert( sigaction(SIGBUS, &addrSignals, 0) == 0 );
+        assert( sigaction(SIGILL, &addrSignals, 0) == 0 );
+        assert( sigaction(SIGFPE, &addrSignals, 0) == 0 );
+        
         assert( signal(SIGABRT, abruptQuit) != SIG_ERR );
-        assert( signal(SIGBUS, abruptQuit) != SIG_ERR );
         assert( signal(SIGQUIT, abruptQuit) != SIG_ERR );
         assert( signal(SIGPIPE, pipeSigHandler) != SIG_ERR );
 
diff --git a/db/dbhelpers.cpp b/db/dbhelpers.cpp
index 75db430..3079aad 100644
--- a/db/dbhelpers.cpp
+++ b/db/dbhelpers.cpp
@@ -85,6 +85,7 @@ namespace mongo {
             }
         }
         virtual long long nscanned() {
+            // We don't support yielding, so will always have c_.
             assert( c_.get() );
             return c_->nscanned();
         }
diff --git a/db/dur_commitjob.cpp b/db/dur_commitjob.cpp
index aed38e8..2d57ffd 100644
--- a/db/dur_commitjob.cpp
+++ b/db/dur_commitjob.cpp
@@ -183,7 +183,7 @@ namespace mongo {
                 // remember intent. we will journal it in a bit
                 _wi.insertWriteIntent(p, len);
                 wassert( _wi._writes.size() <  2000000 );
-                assert(  _wi._writes.size() < 20000000 );
+                //assert(  _wi._writes.size() < 20000000 );
 
                 {
                     // a bit over conservative in counting pagebytes used
@@ -200,7 +200,9 @@ namespace mongo {
                                 log() << "debug nsincecommitifneeded:" << _nSinceCommitIfNeededCall << " bytes:" << _bytes << endl;
                         }
 #endif
-                        uassert(13623, "DR102 too much data written uncommitted", _bytes < UncommittedBytesLimit * 3);
+                        if ( _bytes >= UncommittedBytesLimit * 3 ) {
+                            wassert( ! "DR102 too much data written uncommitted" );
+                        }
                     }
                 }
             }
diff --git a/db/lasterror.cpp b/db/lasterror.cpp
index ba52111..4643aa9 100644
--- a/db/lasterror.cpp
+++ b/db/lasterror.cpp
@@ -28,7 +28,6 @@ namespace mongo {
 
     LastError LastError::noError;
     LastErrorHolder lastError;
-    mongo::mutex LastErrorHolder::_idsmutex("LastErrorHolder");
 
     bool isShell = false;
     void raiseError(int code , const char *msg) {
@@ -79,22 +78,9 @@ namespace mongo {
     }
 
     LastErrorHolder::~LastErrorHolder() {
-        for ( IDMap::iterator i = _ids.begin(); i != _ids.end(); ++i ) {
-            delete i->second.lerr;
-            i->second.lerr = 0;
-        }
-        _ids.clear();
     }
 
 
-    void LastErrorHolder::setID( int id ) {
-        _id.set( id );
-    }
-
-    int LastErrorHolder::getID() {
-        return _id.get();
-    }
-
     LastError * LastErrorHolder::disableForCommand() {
         LastError *le = _get();
         assert( le );
@@ -111,77 +97,31 @@ namespace mongo {
     }
 
     LastError * LastErrorHolder::_get( bool create ) {
-        int id = _id.get();
-        if ( id == 0 ) {
-            LastError * le = _tl.get();
-            if ( ! le && create ) {
-                le = new LastError();
-                _tl.reset( le );
-            }
-            return le;
-        }
-
-        scoped_lock lock(_idsmutex);
-        map<int,Status>::iterator i = _ids.find( id );
-        if ( i == _ids.end() ) {
-            if ( ! create )
-                return 0;
-
-            LastError * le = new LastError();
-            Status s;
-            s.time = time(0);
-            s.lerr = le;
-            _ids[id] = s;
-            return le;
+        LastError * le = _tl.get();
+        if ( ! le && create ) {
+            le = new LastError();
+            _tl.reset( le );
         }
-
-        Status &status = i->second;
-        status.time = time(0);
-        return status.lerr;
-    }
-
-    void LastErrorHolder::remove( int id ) {
-        scoped_lock lock(_idsmutex);
-        map<int,Status>::iterator i = _ids.find( id );
-        if ( i == _ids.end() )
-            return;
-
-        delete i->second.lerr;
-        _ids.erase( i );
+        return le;
     }
 
     void LastErrorHolder::release() {
-        int id = _id.get();
-        if ( id == 0 ) {
-            _tl.release();
-            return;
-        }
-
-        remove( id );
+        _tl.release();
     }
 
     /** ok to call more than once. */
     void LastErrorHolder::initThread() {
-        if( _tl.get() ) return;
-        assert( _id.get() == 0 );
-        _tl.reset( new LastError() );
+        if( ! _tl.get() ) 
+            _tl.reset( new LastError() );
     }
 
     void LastErrorHolder::reset( LastError * le ) {
-        int id = _id.get();
-        if ( id == 0 ) {
-            _tl.reset( le );
-            return;
-        }
-
-        scoped_lock lock(_idsmutex);
-        Status & status = _ids[id];
-        status.time = time(0);
-        status.lerr = le;
+        _tl.reset( le );
     }
 
     void prepareErrForNewRequest( Message &m, LastError * err ) {
         // a killCursors message shouldn't affect last error
+        assert( err );
         if ( m.operation() == dbKillCursors ) {
             err->disabled = true;
         }
@@ -191,60 +131,10 @@ namespace mongo {
         }
     }
 
-    LastError * LastErrorHolder::startRequest( Message& m , int clientId ) {
-        assert( clientId );
-        setID( clientId );
-
-        LastError * le = _get( true );
+    LastError * LastErrorHolder::startRequest( Message& m , LastError * le ) {
+        assert( le );
         prepareErrForNewRequest( m, le );
         return le;
     }
 
-    void LastErrorHolder::startRequest( Message& m , LastError * connectionOwned ) {
-        prepareErrForNewRequest( m, connectionOwned );
-    }
-
-    void LastErrorHolder::disconnect( int clientId ) {
-        if ( clientId )
-            remove(clientId);
-    }
-
-    struct LastErrorHolderTest : public UnitTest {
-    public:
-
-        void test( int i ) {
-            _tl.set( i );
-            assert( _tl.get() == i );
-        }
-
-        void tlmaptest() {
-            test( 1 );
-            test( 12123123 );
-            test( -123123 );
-            test( numeric_limits<int>::min() );
-            test( numeric_limits<int>::max() );
-        }
-
-        void run() {
-            tlmaptest();
-
-            LastError * a = new LastError();
-            LastError * b = new LastError();
-
-            LastErrorHolder holder;
-            holder.reset( a );
-            assert( a == holder.get() );
-            holder.setID( 1 );
-            assert( 0 == holder.get() );
-            holder.reset( b );
-            assert( b == holder.get() );
-            holder.setID( 0 );
-            assert( a == holder.get() );
-
-            holder.remove( 1 );
-        }
-
-        ThreadLocalValue<int> _tl;
-    } lastErrorHolderTest;
-
 } // namespace mongo
diff --git a/db/lasterror.h b/db/lasterror.h
index c77ec74..86250e4 100644
--- a/db/lasterror.h
+++ b/db/lasterror.h
@@ -100,14 +100,14 @@ namespace mongo {
 
     extern class LastErrorHolder {
     public:
-        LastErrorHolder() : _id( 0 ) {}
+        LastErrorHolder(){}
         ~LastErrorHolder();
 
         LastError * get( bool create = false );
         LastError * getSafe() {
             LastError * le = get(false);
             if ( ! le ) {
-                log( LL_ERROR ) << " no LastError!  id: " << getID() << endl;
+                error() << " no LastError!" << endl;
                 assert( le );
             }
             return le;
@@ -120,18 +120,12 @@ namespace mongo {
         /** ok to call more than once. */
         void initThread();
 
-        /**
-         * id of 0 means should use thread local management
-         */
-        void setID( int id );
         int getID();
-
-        void remove( int id );
+        
         void release();
 
         /** when db receives a message/request, call this */
-        void startRequest( Message& m , LastError * connectionOwned );
-        LastError * startRequest( Message& m , int clientId );
+        LastError * startRequest( Message& m , LastError * connectionOwned );
 
         void disconnect( int clientId );
 
@@ -139,17 +133,12 @@ namespace mongo {
         // disable causes get() to return 0.
         LastError *disableForCommand(); // only call once per command invocation!
     private:
-        ThreadLocalValue<int> _id;
         boost::thread_specific_ptr<LastError> _tl;
 
         struct Status {
             time_t time;
             LastError *lerr;
         };
-        typedef map<int,Status> IDMap;
-
-        static mongo::mutex _idsmutex;
-        IDMap _ids;
     } lastError;
 
     void raiseError(int code , const char *msg);
diff --git a/db/pdfile.cpp b/db/pdfile.cpp
index 20a7423..663ae05 100644
--- a/db/pdfile.cpp
+++ b/db/pdfile.cpp
@@ -1198,8 +1198,10 @@ namespace mongo {
 
         log(1) << "\t fastBuildIndex dupsToDrop:" << dupsToDrop.size() << endl;
 
-        for( list<DiskLoc>::iterator i = dupsToDrop.begin(); i != dupsToDrop.end(); i++ )
+        for( list<DiskLoc>::iterator i = dupsToDrop.begin(); i != dupsToDrop.end(); i++ ){
             theDataFileMgr.deleteRecord( ns, i->rec(), *i, false, true );
+            getDur().commitIfNeeded();
+        }
 
         return n;
     }
@@ -1254,6 +1256,8 @@ namespace mongo {
                 n++;
                 progress.hit();
 
+                getDur().commitIfNeeded();
+
                 if ( n % 128 == 0 && !cc->yield() ) {
                     cc.release();
                     uasserted(12584, "cursor gone during bg index");
@@ -1287,7 +1291,7 @@ namespace mongo {
             prep(ns.c_str(), d);
             assert( idxNo == d->nIndexes );
             try {
-                idx.head = BtreeBucket::addBucket(idx);
+                idx.head.writing() = BtreeBucket::addBucket(idx);
                 n = addExistingToIndex(ns.c_str(), d, idx, idxNo);
             }
             catch(...) {
diff --git a/db/query.cpp b/db/query.cpp
index df09fce..7f23ac8 100644
--- a/db/query.cpp
+++ b/db/query.cpp
@@ -76,8 +76,7 @@ namespace mongo {
             }
         }
         virtual long long nscanned() {
-            assert( c_.get() );
-            return c_->nscanned();
+            return c_.get() ? c_->nscanned() : _nscanned;
         }
         virtual void next() {
             if ( !c_->ok() ) {
@@ -416,6 +415,7 @@ namespace mongo {
             _ns(ns), _capped(false), _count(), _myCount(),
             _skip( spec["skip"].numberLong() ),
             _limit( spec["limit"].numberLong() ),
+            _nscanned(),
             _bc() {
         }
 
@@ -430,19 +430,22 @@ namespace mongo {
         }
 
         virtual long long nscanned() {
-            assert( _c.get() );
-            return _c->nscanned();
+            return _c.get() ? _c->nscanned() : _nscanned;
         }
 
         virtual bool prepareToYield() {
-            if ( ! _cc ) {
+            if ( _c && !_cc ) {
                 _cc.reset( new ClientCursor( QueryOption_NoCursorTimeout , _c , _ns.c_str() ) );
             }
-            return _cc->prepareToYield( _yieldData );
+            if ( _cc ) {
+	            return _cc->prepareToYield( _yieldData );
+            }
+            // no active cursor - ok to yield
+            return true;
         }
 
         virtual void recoverFromYield() {
-            if ( !ClientCursor::recoverFromYield( _yieldData ) ) {
+            if ( _cc && !ClientCursor::recoverFromYield( _yieldData ) ) {
                 _c.reset();
                 _cc.reset();
 
@@ -461,6 +464,7 @@ namespace mongo {
                 return;
             }
 
+            _nscanned = _c->nscanned();
             if ( _bc ) {
                 if ( _firstMatch.isEmpty() ) {
                     _firstMatch = _bc->currKeyNode().key.copy();
@@ -523,6 +527,7 @@ namespace mongo {
         long long _myCount;
         long long _skip;
         long long _limit;
+        long long _nscanned;
         shared_ptr<Cursor> _c;
         BSONObj _query;
         BtreeCursor * _bc;
@@ -698,11 +703,15 @@ namespace mongo {
                 return _findingStartCursor->prepareToYield();
             }
             else {
-                if ( ! _cc ) {
+                if ( _c && !_cc ) {
                     _cc.reset( new ClientCursor( QueryOption_NoCursorTimeout , _c , _pq.ns() ) );
                 }
-                return _cc->prepareToYield( _yieldData );
+                if ( _cc ) {
+	                return _cc->prepareToYield( _yieldData );
+                }
             }
+            // no active cursor - ok to yield
+            return true;
         }
 
         virtual void recoverFromYield() {
@@ -711,7 +720,7 @@ namespace mongo {
             if ( _findingStartCursor.get() ) {
                 _findingStartCursor->recoverFromYield();
             }
-            else if ( ! ClientCursor::recoverFromYield( _yieldData ) ) {
+            else if ( _cc && !ClientCursor::recoverFromYield( _yieldData ) ) {
                 _c.reset();
                 _cc.reset();
                 _so.reset();
@@ -732,8 +741,7 @@ namespace mongo {
             if ( _findingStartCursor.get() ) {
                 return 0; // should only be one query plan, so value doesn't really matter.
             }
-            assert( _c.get() );
-            return _c->nscanned();
+            return _c.get() ? _c->nscanned() : _nscanned;
         }
 
         virtual void next() {
@@ -850,6 +858,7 @@ namespace mongo {
 
         // this plan won, so set data for response broadly
         void finish( bool stop ) {
+            massert( 13638, "client cursor dropped during explain query yield", !_pq.isExplain() || _c.get() );
 
             if ( _pq.isExplain() ) {
                 _n = _inMemSort ? _so->size() : _n;
@@ -871,7 +880,6 @@ namespace mongo {
             }
 
             if ( _pq.isExplain() ) {
-                massert( 13638, "client cursor dropped during explain query yield", _c.get() );
                 _eb.noteScan( _c.get(), _nscanned, _nscannedObjects, _n, scanAndOrderRequired(),
                               _curop.elapsedMillis(), useHints && !_pq.getHint().eoo(), _nYields ,
                               _nChunkSkips, _keyFieldsOnly.get() > 0 );
diff --git a/db/repl/rs_config.cpp b/db/repl/rs_config.cpp
index 5998f51..2341fe9 100644
--- a/db/repl/rs_config.cpp
+++ b/db/repl/rs_config.cpp
@@ -314,12 +314,12 @@ namespace mongo {
                 }
                 if( m.h.isLocalHost() )
                     localhosts++;
-                m.arbiterOnly = mobj.getBoolField("arbiterOnly");
+                m.arbiterOnly = mobj["arbiterOnly"].trueValue();
                 m.slaveDelay = mobj["slaveDelay"].numberInt();
                 if( mobj.hasElement("hidden") )
-                    m.hidden = mobj.getBoolField("hidden");
+                    m.hidden = mobj["hidden"].trueValue();
                 if( mobj.hasElement("buildIndexes") )
-                    m.buildIndexes = mobj.getBoolField("buildIndexes");
+                    m.buildIndexes = mobj["buildIndexes"].trueValue();
                 if( mobj.hasElement("priority") )
                     m.priority = mobj["priority"].Number();
                 if( mobj.hasElement("votes") )
diff --git a/db/update.cpp b/db/update.cpp
index 7de9bb1..e79d3d5 100644
--- a/db/update.cpp
+++ b/db/update.cpp
@@ -913,15 +913,14 @@ namespace mongo {
             }
         }
         virtual long long nscanned() {
-            assert( _c.get() );
-            return _c->nscanned();
+            return _c.get() ? _c->nscanned() : _nscanned;
         }
         virtual void next() {
             if ( ! _c->ok() ) {
                 setComplete();
                 return;
             }
-            _nscanned++;
+            _nscanned = _c->nscanned();
             if ( matcher()->matches(_c->currKey(), _c->currLoc(), &_details ) ) {
                 setComplete();
                 return;
-- 
cgit v1.2.3