summaryrefslogtreecommitdiff
path: root/db
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2010-12-10 13:05:34 +0100
committerAntonin Kral <a.kral@bobek.cz>2010-12-10 13:05:34 +0100
commited4a804c027562e1bf6a0f45dae7326198c29f8e (patch)
tree9d04736132d5421497a80619e30d4c2e03e76728 /db
parente598e7ada36302f35a0da8ae0c63c34b51b6a720 (diff)
downloadmongodb-ed4a804c027562e1bf6a0f45dae7326198c29f8e.tar.gz
Imported Upstream version 1.6.5
Diffstat (limited to 'db')
-rw-r--r--db/dbcommands.cpp2
-rw-r--r--db/dbhelpers.cpp4
-rw-r--r--db/geo/2d.cpp68
-rw-r--r--db/instance.cpp12
-rw-r--r--db/namespace.cpp6
-rw-r--r--db/query.cpp7
-rw-r--r--db/queryutil.cpp25
-rw-r--r--db/repl.cpp2
-rw-r--r--db/repl/connections.h25
-rw-r--r--db/repl/consensus.cpp15
-rw-r--r--db/repl/health.cpp6
-rw-r--r--db/repl/heartbeat.cpp2
-rw-r--r--db/repl/multicmd.h2
-rw-r--r--db/repl/rs_config.cpp34
-rw-r--r--db/repl/rs_member.h6
-rw-r--r--db/repl/rs_sync.cpp9
-rw-r--r--db/update.cpp8
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 ){