diff options
author | Antonin Kral <a.kral@bobek.cz> | 2010-12-10 13:05:34 +0100 |
---|---|---|
committer | Antonin Kral <a.kral@bobek.cz> | 2010-12-10 13:05:34 +0100 |
commit | ed4a804c027562e1bf6a0f45dae7326198c29f8e (patch) | |
tree | 9d04736132d5421497a80619e30d4c2e03e76728 /db | |
parent | e598e7ada36302f35a0da8ae0c63c34b51b6a720 (diff) | |
download | mongodb-ed4a804c027562e1bf6a0f45dae7326198c29f8e.tar.gz |
Imported Upstream version 1.6.5
Diffstat (limited to 'db')
-rw-r--r-- | db/dbcommands.cpp | 2 | ||||
-rw-r--r-- | db/dbhelpers.cpp | 4 | ||||
-rw-r--r-- | db/geo/2d.cpp | 68 | ||||
-rw-r--r-- | db/instance.cpp | 12 | ||||
-rw-r--r-- | db/namespace.cpp | 6 | ||||
-rw-r--r-- | db/query.cpp | 7 | ||||
-rw-r--r-- | db/queryutil.cpp | 25 | ||||
-rw-r--r-- | db/repl.cpp | 2 | ||||
-rw-r--r-- | db/repl/connections.h | 25 | ||||
-rw-r--r-- | db/repl/consensus.cpp | 15 | ||||
-rw-r--r-- | db/repl/health.cpp | 6 | ||||
-rw-r--r-- | db/repl/heartbeat.cpp | 2 | ||||
-rw-r--r-- | db/repl/multicmd.h | 2 | ||||
-rw-r--r-- | db/repl/rs_config.cpp | 34 | ||||
-rw-r--r-- | db/repl/rs_member.h | 6 | ||||
-rw-r--r-- | db/repl/rs_sync.cpp | 9 | ||||
-rw-r--r-- | db/update.cpp | 8 |
17 files changed, 160 insertions, 73 deletions
diff --git a/db/dbcommands.cpp b/db/dbcommands.cpp index 96374d9..7bd7203 100644 --- a/db/dbcommands.cpp +++ b/db/dbcommands.cpp @@ -377,7 +377,7 @@ namespace mongo { } { - BSONObjBuilder bb( result.subobjStart( "cursros" ) ); + BSONObjBuilder bb( result.subobjStart( "cursors" ) ); ClientCursor::appendStats( bb ); bb.done(); } diff --git a/db/dbhelpers.cpp b/db/dbhelpers.cpp index 124deb8..205787e 100644 --- a/db/dbhelpers.cpp +++ b/db/dbhelpers.cpp @@ -301,6 +301,10 @@ namespace mongo { c->checkLocation(); + if ( yield && ! cc->yieldSometimes() ){ + // cursor got finished by someone else, so we're done + break; + } } return num; diff --git a/db/geo/2d.cpp b/db/geo/2d.cpp index 19efafd..60818fc 100644 --- a/db/geo/2d.cpp +++ b/db/geo/2d.cpp @@ -1257,7 +1257,7 @@ namespace mongo { _want._min = Point( _g , _bl ); _want._max = Point( _g , _tr ); - + uassert( 13064 , "need an area > 0 " , _want.area() > 0 ); _state = START; @@ -1268,12 +1268,14 @@ namespace mongo { GEODEBUG( "center : " << center.toString() << "\t" << _prefix ); - { - GeoHash a(0LL,32); - GeoHash b(0LL,32); - b.move(1,1); - _fudge = _g->distance(a,b); - } + { + GeoHash a(0LL,32); + GeoHash b(0LL,32); + b.move(1,1); + _fudge = _g->distance(a,b); + } + + _wantLen = _fudge + std::max((_want._max._x - _want._min._x), (_want._max._y - _want._min._y)); ok(); } @@ -1308,32 +1310,47 @@ namespace mongo { _state = DONE; return; } - - Box cur( _g , _prefix ); - if ( cur._min._x + _fudge < _want._min._x && - cur._min._y + _fudge < _want._min._y && - cur._max._x - _fudge > _want._max._x && - cur._max._y - _fudge > _want._max._y ){ - - _state = DONE; - GeoHash temp = _prefix.commonPrefix( cur._max.hash( _g ) ); - GEODEBUG( "box done : " << cur.toString() << " prefix:" << _prefix << " common:" << temp ); - - if ( temp == _prefix ) - return; - _prefix = temp; - GEODEBUG( "\t one more loop" ); - continue; - } - else { + if (_g->sizeEdge(_prefix) < _wantLen){ _prefix = _prefix.up(); + } else { + for (int i=-1; i<=1; i++){ + for (int j=-1; j<=1; j++){ + + if (i == 0 && j == 0) + continue; // main box + + GeoHash newBox = _prefix; + newBox.move(i, j); + + PREFIXDEBUG(newBox, _g); + + Box cur( _g , newBox ); + if (_want.intersects(cur)){ + // TODO consider splitting into quadrants + getPointsForPrefix(newBox); + } else { + GEODEBUG("skipping box"); + } + } + } + _state = DONE; } + } return; } } + + void getPointsForPrefix(const GeoHash& prefix){ + if ( ! BtreeLocation::initial( *_id , _spec , _min , _max , prefix , _found , this ) ){ + return; + } + + while ( _min.hasPrefix( prefix ) && _min.advance( -1 , _found , this ) ); + while ( _max.hasPrefix( prefix ) && _max.advance( 1 , _found , this ) ); + } virtual bool checkDistance( const GeoHash& h , double& d ){ bool res = _want.inside( Point( _g , h ) , _fudge ); @@ -1346,6 +1363,7 @@ namespace mongo { GeoHash _bl; GeoHash _tr; Box _want; + double _wantLen; int _found; diff --git a/db/instance.cpp b/db/instance.cpp index 9e81464..a6873f2 100644 --- a/db/instance.cpp +++ b/db/instance.cpp @@ -499,6 +499,7 @@ namespace mongo { if( ntoreturn ) ss << " ntoreturn:" << ntoreturn; + time_t start = 0; int pass = 0; bool exhaust = false; QueryResult* msgdata; @@ -511,6 +512,17 @@ namespace mongo { catch ( GetMoreWaitException& ) { exhaust = false; massert(13073, "shutting down", !inShutdown() ); + if( pass == 0 ) { + start = time(0); + } + else { + if( time(0) - start >= 4 ) { + // after about 4 seconds, return. this is a sanity check. pass stops at 1000 normally + // for DEV this helps and also if sleep is highly inaccurate on a platform. we want to + // return occasionally so slave can checkpoint. + pass = 10000; + } + } pass++; DEV sleepmillis(20); diff --git a/db/namespace.cpp b/db/namespace.cpp index de3f4df..8a1ab6f 100644 --- a/db/namespace.cpp +++ b/db/namespace.cpp @@ -564,8 +564,10 @@ namespace mongo { } void renameNamespace( const char *from, const char *to ) { - NamespaceIndex *ni = nsindex( from ); - assert( ni && ni->details( from ) && !ni->details( to ) ); + NamespaceIndex *ni = nsindex( from ); + assert( ni ); + assert( ni->details( from ) ); + assert( ! ni->details( to ) ); // Our namespace and index details will move to a different // memory location. The only references to namespace and diff --git a/db/query.cpp b/db/query.cpp index 5bd7b00..154fd15 100644 --- a/db/query.cpp +++ b/db/query.cpp @@ -320,7 +320,6 @@ namespace mongo { while ( 1 ) { if ( !c->ok() ) { -// log() << "TEMP Tailable : " << c->tailable() << ' ' << (queryOptions & QueryOption_AwaitData) << endl; if ( c->tailable() ) { /* when a tailable cursor hits "EOF", ok() goes false, and current() is null. however advance() can still be retries as a reactivation attempt. when there is new data, it will @@ -787,8 +786,10 @@ namespace mongo { if ( _pq.isExplain()) { _eb.noteScan( _c.get(), _nscanned, _nscannedObjects, _n, scanAndOrderRequired(), _curop.elapsedMillis(), useHints && !_pq.getHint().eoo() ); } else { - _response.appendData( _buf.buf(), _buf.len() ); - _buf.decouple(); + if (_buf.len()) { + _response.appendData( _buf.buf(), _buf.len() ); + _buf.decouple(); + } } if ( stop ) { setStop(); diff --git a/db/queryutil.cpp b/db/queryutil.cpp index 007a1ce..2153046 100644 --- a/db/queryutil.cpp +++ b/db/queryutil.cpp @@ -982,23 +982,16 @@ namespace mongo { BSONElement kk = k.next(); int number = (int) kk.number(); bool forward = ( number >= 0 ? 1 : -1 ) * ( _direction >= 0 ? 1 : -1 ) > 0; - BSONElement e = obj.getField( kk.fieldName() ); - if ( e.eoo() ) { - e = staticNull.firstElement(); - } - if ( e.type() == Array ) { - BSONObjIterator j( e.embeddedObject() ); - bool match = false; - while( j.more() ) { - if ( matchesElement( j.next(), i, forward ) ) { - match = true; - break; - } - } - if ( !match ) { - return false; + BSONElementSet keys; + obj.getFieldsDotted( kk.fieldName(), keys ); + bool match = false; + for( BSONElementSet::const_iterator j = keys.begin(); j != keys.end(); ++j ) { + if ( matchesElement( *j, i, forward ) ) { + match = true; + break; } - } else if ( !matchesElement( e, i, forward ) ) { + } + if ( !match ) { return false; } } diff --git a/db/repl.cpp b/db/repl.cpp index 085ae64..ea0eab9 100644 --- a/db/repl.cpp +++ b/db/repl.cpp @@ -658,6 +658,8 @@ namespace mongo { ReplSource tmp(c->current()); if ( tmp.hostName != cmdLine.source ) { log() << "repl: --source " << cmdLine.source << " != " << tmp.hostName << " from local.sources collection" << endl; + log() << "repl: for instructions on changing this slave's source, see:" << endl; + log() << "http://dochub.mongodb.org/core/masterslave" << endl; log() << "repl: terminating mongod after 30 seconds" << endl; sleepsecs(30); dbexit( EXIT_REPLICATION_ERROR ); diff --git a/db/repl/connections.h b/db/repl/connections.h index 95defe4..cdf2fad 100644 --- a/db/repl/connections.h +++ b/db/repl/connections.h @@ -44,19 +44,36 @@ namespace mongo { /** throws assertions if connect failure etc. */ ScopedConn(string hostport); ~ScopedConn(); - DBClientConnection* operator->(); + + /* If we were to run a query and not exhaust the cursor, future use of the connection would be problematic. + So here what we do is wrapper known safe methods and not allow cursor-style queries at all. This makes + ScopedConn limited in functionality but very safe. More non-cursor wrappers can be added here if needed. + */ + + bool runCommand(const string &dbname, const BSONObj& cmd, BSONObj &info, int options=0) { + return conn()->runCommand(dbname, cmd, info, options); + } + unsigned long long count(const string &ns) { + return conn()->count(ns); + } + BSONObj findOne(const string &ns, const Query& q, const BSONObj *fieldsToReturn = 0, int queryOptions = 0) { + return conn()->findOne(ns, q, fieldsToReturn, queryOptions); + } + private: auto_ptr<scoped_lock> connLock; static mutex mapMutex; struct X { mutex z; DBClientConnection cc; - X() : z("X"), cc(/*reconnect*/true, 0, /*timeout*/10) { + X() : z("X"), cc(/*reconnect*/ true, 0, + /*timeout*/ theReplSet ? theReplSet->config().ho.heartbeatTimeoutMillis/1000.0 : 10.0) { cc._logLevel = 2; } } *x; typedef map<string,ScopedConn::X*> M; static M& _map; + DBClientConnection* conn() { return &x->cc; } }; inline ScopedConn::ScopedConn(string hostport) { @@ -84,8 +101,8 @@ namespace mongo { // conLock releases... } - inline DBClientConnection* ScopedConn::operator->() { + /*inline DBClientConnection* ScopedConn::operator->() { return &x->cc; - } + }*/ } diff --git a/db/repl/consensus.cpp b/db/repl/consensus.cpp index 4044538..1519c26 100644 --- a/db/repl/consensus.cpp +++ b/db/repl/consensus.cpp @@ -134,6 +134,9 @@ namespace mongo { OID round = cmd["round"].OID(); int myver = rs.config().version; + const Member* primary = rs.box.getPrimary(); + const Member* hopeful = rs.findById(whoid); + int vote = 0; if( set != rs.name() ) { log() << "replSet error received an elect request for '" << set << "' but our set name is '" << rs.name() << "'" << rsLog; @@ -147,6 +150,16 @@ namespace mongo { log() << "replSet info got stale version # during election" << rsLog; vote = -10000; } + else if( !hopeful ) { + log() << "couldn't find member with id " << whoid << rsLog; + vote = -10000; + } + else if( primary && primary->hbinfo().opTime > hopeful->hbinfo().opTime ) { + // other members might be aware of more up-to-date nodes + log() << hopeful->fullName() << " is trying to elect itself but " << + primary->fullName() << " is already primary and more up-to-date" << rsLog; + vote = -10000; + } else { try { vote = yea(whoid); @@ -165,7 +178,7 @@ namespace mongo { void ReplSetImpl::_getTargets(list<Target>& L, int& configVersion) { configVersion = config().version; for( Member *m = head(); m; m=m->next() ) - if( m->hbinfo().up() ) + if( m->hbinfo().maybeUp() ) L.push_back( Target(m->fullName()) ); } diff --git a/db/repl/health.cpp b/db/repl/health.cpp index 72396fe..c75221c 100644 --- a/db/repl/health.cpp +++ b/db/repl/health.cpp @@ -19,6 +19,7 @@ #include "health.h" #include "../../util/background.h" #include "../../client/dbclient.h" +#include "../../client/connpool.h" #include "../commands.h" #include "../../util/concurrency/value.h" #include "../../util/concurrency/task.h" @@ -186,7 +187,7 @@ namespace mongo { //const bo fields = BSON( "o" << false << "o2" << false ); const bo fields; - ScopedConn conn(m->fullName()); + ScopedDbConnection conn(m->fullName()); auto_ptr<DBClientCursor> c = conn->query(rsoplog, Query().sort("$natural",1), 20, 0, &fields); if( c.get() == 0 ) { @@ -245,8 +246,6 @@ namespace mongo { ss << _table(); ss << p(time_t_to_String_short(time(0)) + " current time"); - //ss << "</pre>\n"; - if( !otEnd.isNull() ) { ss << "<p>Log length in time: "; unsigned d = otEnd.getSecs() - otFirst.getSecs(); @@ -259,6 +258,7 @@ namespace mongo { ss << "</p>\n"; } + conn.done(); } void ReplSetImpl::_summarizeAsHtml(stringstream& s) const { diff --git a/db/repl/heartbeat.cpp b/db/repl/heartbeat.cpp index 4f28897..b39fad7 100644 --- a/db/repl/heartbeat.cpp +++ b/db/repl/heartbeat.cpp @@ -134,7 +134,7 @@ namespace mongo { assert( theReplSet == 0 || !theReplSet->lockedByMe() ); ScopedConn conn(memberFullName); - return conn->runCommand("admin", cmd, result); + return conn.runCommand("admin", cmd, result, 0); } /* poll every other set member to check its status */ diff --git a/db/repl/multicmd.h b/db/repl/multicmd.h index 61c9b5f..9eb9a17 100644 --- a/db/repl/multicmd.h +++ b/db/repl/multicmd.h @@ -43,7 +43,7 @@ namespace mongo { void run() { try { ScopedConn c(d.toHost); - d.ok = c->runCommand("admin", cmd, d.result); + d.ok = c.runCommand("admin", cmd, d.result); } catch(DBException&) { DEV log() << "dev caught dbexception on multiCommand " << d.toHost << rsLog; diff --git a/db/repl/rs_config.cpp b/db/repl/rs_config.cpp index 85c9a46..371507d 100644 --- a/db/repl/rs_config.cpp +++ b/db/repl/rs_config.cpp @@ -302,9 +302,8 @@ namespace mongo { clear(); int level = 2; DEV level = 0; - //log(0) << "replSet load config from: " << h.toString() << rsLog; - auto_ptr<DBClientCursor> c; + BSONObj cfg; int v = -5; try { if( h.isSelf() ) { @@ -337,13 +336,28 @@ namespace mongo { } v = -4; - ScopedConn conn(h.toString()); - v = -3; - c = conn->query(rsConfigNs); - if( c.get() == 0 ) { - version = v; return; + unsigned long long count = 0; + try { + ScopedConn conn(h.toString()); + v = -3; + cfg = conn.findOne(rsConfigNs, Query()).getOwned(); + count = conn.count(rsConfigNs); + } + catch ( DBException& e) { + if ( !h.isSelf() ) { + throw; + } + + // on startup, socket is not listening yet + DBDirectClient cli; + cfg = cli.findOne( rsConfigNs, Query() ).getOwned(); + count = cli.count(rsConfigNs); } - if( !c->more() ) { + + if( count > 1 ) + uasserted(13109, str::stream() << "multiple rows in " << rsConfigNs << " not supported host: " << h.toString()); + + if( cfg.isEmpty() ) { version = EMPTYCONFIG; return; } @@ -355,9 +369,7 @@ namespace mongo { return; } - BSONObj o = c->nextSafe(); - uassert(13109, "multiple rows in " + rsConfigNs + " not supported", !c->more()); - from(o); + from(cfg); checkRsConfig(); _ok = true; log(level) << "replSet load config ok from " << (h.isSelf() ? "self" : h.toString()) << rsLog; diff --git a/db/repl/rs_member.h b/db/repl/rs_member.h index 6a797b5..099cb22 100644 --- a/db/repl/rs_member.h +++ b/db/repl/rs_member.h @@ -67,7 +67,6 @@ namespace mongo { public: HeartbeatInfo() : _id(0xffffffff),hbstate(MemberState::RS_UNKNOWN),health(-1.0),downSince(0),skew(INT_MIN) { } HeartbeatInfo(unsigned id); - bool up() const { return health > 0; } unsigned id() const { return _id; } MemberState hbstate; double health; @@ -78,6 +77,11 @@ namespace mongo { OpTime opTime; int skew; + bool up() const { return health > 0; } + + /** health is set to -1 on startup. that means we haven't even checked yet. 0 means we checked and it failed. */ + bool maybeUp() const { return health != 0; } + long long timeDown() const; // ms /* true if changed in a way of interest to the repl set manager. */ diff --git a/db/repl/rs_sync.cpp b/db/repl/rs_sync.cpp index 9ea65cf..9de3f60 100644 --- a/db/repl/rs_sync.cpp +++ b/db/repl/rs_sync.cpp @@ -70,7 +70,14 @@ namespace mongo { return false; } - r.query(rsoplog, bo()); + { + BSONObjBuilder q; + q.appendDate("$gte", applyGTE.asDate()); + BSONObjBuilder query; + query.append("ts", q.done()); + BSONObj queryObj = query.done(); + r.query(rsoplog, queryObj); + } assert( r.haveCursor() ); /* we lock outside the loop to avoid the overhead of locking on every operation. server isn't usable yet anyway! */ diff --git a/db/update.cpp b/db/update.cpp index d4a038b..e178e0f 100644 --- a/db/update.cpp +++ b/db/update.cpp @@ -517,10 +517,12 @@ namespace mongo { DEBUGUPDATE( "\t\t createNewFromMods root: " << root ); BSONObjIteratorSorted es( obj ); BSONElement e = es.next(); - + ModStateHolder::iterator m = _mods.lower_bound( root ); - ModStateHolder::iterator mend = _mods.lower_bound( root + '{' ); - + StringBuilder buf(root.size() + 2 ); + buf << root << (char)255; + ModStateHolder::iterator mend = _mods.lower_bound( buf.str() ); + set<string> onedownseen; while ( e.type() && m != mend ){ |