Compare commits

...

88 Commits

Author SHA1 Message Date
Eliot Horowitz
aef371ecf5 BUMP 1.6.2 2010-09-01 08:50:38 -04:00
Kristina Chodorow
5b66c47327 fix sharding tests 2010-08-31 23:41:17 -04:00
Alberto Lerner
0260ce050b SERVER-1607 more replica set checks before adding shard 2010-08-31 21:21:18 -04:00
Alberto Lerner
3c1fa57776 SERVER-1607 replica set checks before adding a shard 2010-08-31 21:21:06 -04:00
Kristina Chodorow
19a0f996fa tests SERVER-1665 2010-08-31 21:20:58 -04:00
Alberto Lerner
0fda3ce40f SERVER-1607 expose replica set of a ConnectionString 2010-08-31 21:20:16 -04:00
Alberto Lerner
4a9135c3b6 SERVER-1607 isMaster returns the name of the replica set, if appropriate 2010-08-31 21:17:31 -04:00
Eliot Horowitz
0af2db40cf fix test for v1.6 2010-08-31 21:16:07 -04:00
Dwight
f93b0d654f move tests that close the database to slownightly so they dont interfere with other tests running at the same time 2010-08-31 20:18:05 -04:00
Alberto Lerner
9ff3ddc944 SERVER-1611 allow localhost in a replica-set-based shard 2010-08-31 17:38:05 -04:00
Eliot Horowitz
cd47c92322 fix segfault on repl set slave before inited SERVER-1656 1.6 version 2010-08-31 17:36:10 -04:00
Eliot Horowitz
2b869d6dfa no size_t append in 1.6 2010-08-31 17:33:58 -04:00
Dwight
c9feeb823d fix bugs with query yielding 162 2010-08-31 17:28:08 -04:00
Dwight
38da020af0 elim ambiguous call warning/error 2010-08-31 17:27:28 -04:00
dwight
79b5c8023b const is safer 2010-08-31 17:27:14 -04:00
dwight
baa4cb9c04 clientcursor finish last commit 2010-08-31 17:27:04 -04:00
dwight
66befc517c clean up diags clientcursor after changes 2010-08-31 17:26:56 -04:00
dwight
e070747d94 fix an old but serious bug with cursors 162 2010-08-31 17:26:45 -04:00
Eliot Horowitz
921dbd018b major delete issue with multiple dbs 2010-08-31 17:26:42 -04:00
Eliot Horowitz
964b3436ef remove warning when advancing a cursor to the end 2010-08-31 17:25:26 -04:00
Eliot Horowitz
0840daf31a track number of timed out cursors and display in cursorinfo and serverStatus 2010-08-31 17:25:16 -04:00
Dwight
a3dd77e7ec lower risk of collection name collisions 2010-08-31 17:22:30 -04:00
Eliot Horowitz
4a65b51c57 assert when would inf. loop, but probably caused by something else, still looking 2010-08-31 17:21:23 -04:00
Eliot Horowitz
bdfefa42c5 add if debug is on to buildinfo 2010-08-31 17:17:52 -04:00
Eliot Horowitz
625b4c4378 fix docs for pidfilepath SERVER-1706 2010-08-31 17:16:23 -04:00
Eliot Horowitz
4099bc52cc mongo::Query instead of Query for define 2010-08-31 17:15:44 -04:00
Eliot Horowitz
5c6f0dcfbd better debugging for drop errors 2010-08-31 17:15:31 -04:00
Eliot Horowitz
b620e3327e don't log create collection if on replication side SERVER-1707 2010-08-31 11:18:51 -04:00
Kristina Chodorow
92d5eb42af use replica set name for shard id SERVER-1665 2010-08-28 12:01:22 -04:00
Eliot Horowitz
aaae92dedb make web console get query in a thread safe way SERVER-1692 2010-08-26 13:54:32 -04:00
Eliot Horowitz
0e78196fd5 use smuassert instead of uassert SERVER-1661 2010-08-23 13:37:13 -04:00
Eliot Horowitz
6122c120c3 sharded m/r supports scope SERVER-1663 2010-08-23 13:20:50 -04:00
Eliot Horowitz
7b02bf761d fix m/r sort SERVER-1652 2010-08-21 21:24:09 -04:00
Eliot Horowitz
00e9040236 sayPiggyBack for replica set connection SERVER-1647 2010-08-20 14:12:40 -04:00
Eliot Horowitz
f0d0aad23d fix change log 2010-08-20 11:53:19 -04:00
Eliot Horowitz
f6aad0935e remove mechanism to put mongos -> mongod connections in last error id mode 2010-08-19 10:14:01 -04:00
Eliot Horowitz
7093e6e585 1.6.2 prep 2010-08-17 16:02:25 -04:00
Eliot Horowitz
c5f5f9a4f3 stabilize test 2010-08-17 12:28:19 -04:00
Alberto Lerner
19b587d925 Depend less an a time estimate. 2010-08-17 11:49:07 -04:00
Eliot Horowitz
31d81b823d BUMP 1.6.1 2010-08-17 10:04:43 -04:00
Eliot Horowitz
e280c561f1 make sharding/rs test faster 2010-08-17 09:57:17 -04:00
Eliot Horowitz
1a30dad111 turn off test that is different on windows 2010-08-17 09:34:29 -04:00
Eliot Horowitz
3770916e05 SERVER-1626 initial sync bug fix
Conflicts:

	db/repl.cpp
2010-08-16 17:07:08 -04:00
Eliot Horowitz
67159d2583 BackgroundJob::wait bug SERVER-1628
Conflicts:

	util/background.cpp
2010-08-16 17:04:22 -04:00
dwight
81da9cda7f faster 2010-08-16 17:03:38 -04:00
dwight
415c264123 SERVER-1614 2010-08-16 17:02:33 -04:00
Dwight
4454a8a0a0 fix help title 2010-08-16 16:57:23 -04:00
Eliot Horowitz
d1c3edcf33 writeback is ok on slave 2010-08-16 15:48:08 -04:00
Eliot Horowitz
1948efc6a4 cursor paranoia 2010-08-16 14:30:11 -04:00
Eliot Horowitz
c3855123b5 even more migrate debugging 2010-08-16 14:29:59 -04:00
Eliot Horowitz
2976396903 return connection to pool 2010-08-16 14:29:48 -04:00
Eliot Horowitz
aa5d314ae9 compile 2010-08-16 14:29:39 -04:00
Eliot Horowitz
d3b427b96f better transfer error logging 2010-08-16 14:29:29 -04:00
Eliot Horowitz
3de268fcae change error reporting order for robustness 2010-08-16 14:28:53 -04:00
Eliot Horowitz
54239a3676 fix select() timing for os x SERVER-1596 2010-08-16 14:28:12 -04:00
Eliot Horowitz
1d7dfe2868 try to fix select timing on windows SERVER-1596 2010-08-16 14:28:02 -04:00
Eliot Horowitz
f1f53ef3c1 possible chunk matcher fix 2010-08-16 14:27:43 -04:00
Eliot Horowitz
356eeb5a62 make BSONElement::toString 20x faster for double 2010-08-16 14:27:29 -04:00
Eliot Horowitz
2800a96e56 clean up chunk version handling - prep for SERVER-1473 2010-08-16 14:26:12 -04:00
Mathias Stearn
0c8f696e79 be smarter about sleeping 2010-08-16 14:25:59 -04:00
Alberto Lerner
b58d62a194 Bug fix: logChange() does't throw (can be called from destructors 2010-08-16 14:16:58 -04:00
Eliot Horowitz
2ba8ac25f1 CS-112 initial sync problem with traditional replication
Conflicts:

	db/repl.cpp
2010-08-12 16:12:02 -04:00
Mathias Stearn
edb14c522b move log flush code to after errnoWithDescription 2010-08-11 14:43:26 -04:00
Mathias Stearn
af35eebfb6 check return from fwrite SERVER-1578 2010-08-11 14:43:16 -04:00
Mathias Stearn
edffe867a5 distinct should yield even if non-matching. SERVER-1597 2010-08-09 14:45:12 -04:00
Mathias Stearn
0e8ef6bca0 Yield in distinct SERVER-1597 2010-08-09 14:45:03 -04:00
Mathias Stearn
b59584f3dd Support large files in GridFS SERVER-1408 2010-08-09 13:38:43 -04:00
Eliot Horowitz
3cc86177ce fix getMore with sharding+rs in edge case SERVER-1584 2010-08-06 13:25:52 -04:00
Alberto Lerner
dcfab78c4b DistributedLock::unlock() handles partition from config DB 2010-08-05 13:41:01 -04:00
Eliot Horowitz
ba166df412 post 1.6.0 2010-08-05 11:34:06 -04:00
Eliot Horowitz
2c7f164b65 BUMP 1.6.0 2010-08-05 09:32:06 -04:00
Alberto Lerner
53d1c8bbad Bug fix: DefaultDBPort is perfectly valid when transitioning from a non-sharded mongod 2010-08-05 00:16:50 -04:00
Eliot Horowitz
e4fcc800f7 fix serverStatus for replica sets SERVER-1570 2010-08-04 16:03:32 -04:00
Eliot Horowitz
7abf0580ca when restarting repl set don't blow away directories
Conflicts:

	shell/servers.js
2010-08-04 16:00:06 -04:00
Eliot Horowitz
ae1e0804da fix upsert with $atomic SERVER-1568 2010-08-04 15:15:30 -04:00
Mathias Stearn
50b7bbe934 Low-verbosity sharded explain() SERVER-1562 2010-08-04 13:30:47 -04:00
Eliot Horowitz
fd26b536e9 clean up data files after sharding/replset tests 2010-08-04 12:33:13 -04:00
Dwight
6f6aa20e92 trying to fix SERVER-1483 2010-08-04 12:13:38 -04:00
Dwight
55937a8f3e sort members in replSetGetStatus output for easy reading 2010-08-04 12:11:18 -04:00
Richard Kreuter
8947d06986 Remove C++ driver from RPM specfile. 2010-08-04 11:54:00 -04:00
Dwight
8c095b2cb2 make error msgs better 2010-08-04 11:53:56 -04:00
Dwight
2e6aeb0229 extraneous logging 2010-08-04 11:53:52 -04:00
Dwight
cb661f73fd allow a member down during a config change 2010-08-04 11:53:44 -04:00
Eliot Horowitz
63f894763d fix sorting if sort field not included in projection SERVER-1561 2010-08-04 11:53:36 -04:00
Eliot Horowitz
2c3d88336e allow get last errors blocking on w to be killed 2010-08-04 10:20:16 -04:00
Eliot Horowitz
c542dbd78a when access namespace for the first time, prep all connections SERVER-1560 2010-08-04 10:17:17 -04:00
Eliot Horowitz
b5ce278c18 fix type SERVER-1563 2010-08-04 09:39:16 -04:00
Eliot Horowitz
a432ac592e 1.6.0-pre- marker 2010-08-03 22:18:44 -04:00
81 changed files with 981 additions and 351 deletions

View File

@@ -387,16 +387,7 @@ namespace mongo {
}
break;
case NumberDouble:
{
stringstream tmp;
tmp.precision( 16 );
tmp << number();
string n = tmp.str();
s << n;
// indicate this is a double:
if( strchr(n.c_str(), '.') == 0 && strchr(n.c_str(), 'E') == 0 && strchr(n.c_str(), 'N') == 0 )
s << ".0";
}
s.appendDoubleNice( number() );
break;
case NumberLong:
s << _numberLong();

View File

@@ -164,6 +164,7 @@ namespace mongo {
#define SBNUM(val,maxSize,macro) \
int prev = _buf.l; \
int z = sprintf( _buf.grow(maxSize) , macro , (val) ); \
assert( z >= 0 ); \
_buf.l = prev + z; \
return *this;
@@ -197,6 +198,17 @@ namespace mongo {
}
#undef SBNUM
void appendDoubleNice( double x ){
int prev = _buf.l;
char * start = _buf.grow( 32 );
int z = sprintf( start , "%.16g" , x );
assert( z >= 0 );
_buf.l = prev + z;
if( strchr(start, '.') == 0 && strchr(start, 'E') == 0 && strchr(start, 'N') == 0 ){
write( ".0" , 2 );
}
}
void write( const char* buf, int len){
memcpy( _buf.grow( len ) , buf , len );
}

View File

@@ -1063,6 +1063,18 @@ namespace mongo {
return checkMaster()->findOne(a,b,c,d);
}
bool DBClientReplicaSet::isMember( const DBConnector * conn ) const {
if ( conn == this )
return true;
for ( unsigned i=0; i<_conns.size(); i++ )
if ( _conns[i]->isMember( conn ) )
return true;
return false;
}
bool serverAlive( const string &uri ) {
DBClientConnection c( false, 0, 20 ); // potentially the connection to server could fail while we're checking if it's alive - so use timeouts
string err;

View File

@@ -106,10 +106,11 @@ namespace mongo {
_finishInit();
}
ConnectionString( ConnectionType type , const vector<HostAndPort>& servers )
: _type( type ) , _servers( servers ){
_finishInit();
}
// TODO Delete if nobody is using
//ConnectionString( ConnectionType type , const vector<HostAndPort>& servers )
// : _type( type ) , _servers( servers ){
// _finishInit();
//}
ConnectionString( ConnectionType type , const string& s , const string& setName = "" ){
_type = type;
@@ -156,6 +157,14 @@ namespace mongo {
static ConnectionString parse( const string& url , string& errmsg );
string getSetName() const{
return _setName;
}
vector<HostAndPort> getServers() const {
return _servers;
}
private:
ConnectionString(){
@@ -314,7 +323,7 @@ namespace mongo {
/** Typically one uses the QUERY(...) macro to construct a Query object.
Example: QUERY( "age" << 33 << "school" << "UCLA" )
*/
#define QUERY(x) Query( BSON(x) )
#define QUERY(x) mongo::Query( BSON(x) )
/**
interface that handles communication with the db
@@ -329,6 +338,8 @@ namespace mongo {
/* used by QueryOption_Exhaust. To use that your subclass must implement this. */
virtual void recv( Message& m ) { assert(false); }
virtual string getServerAddress() const = 0;
};
/**
@@ -739,8 +750,6 @@ namespace mongo {
*/
virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = false , bool multi = false );
virtual string getServerAddress() const = 0;
virtual bool isFailed() const = 0;
virtual void killCursor( long long cursorID ) = 0;
@@ -758,6 +767,9 @@ namespace mongo {
virtual void say( Message& toSend ) = 0;
virtual ConnectionString::ConnectionType type() const = 0;
/** @return true if conn is either equal to or contained in this connection */
virtual bool isMember( const DBConnector * conn ) const = 0;
}; // DBClientBase
class DBClientReplicaSet;
@@ -892,11 +904,16 @@ namespace mongo {
virtual bool call( Message &toSend, Message &response, bool assertOk = true );
virtual ConnectionString::ConnectionType type() const { return ConnectionString::MASTER; }
virtual bool isMember( const DBConnector * conn ) const { return this == conn; };
virtual void checkResponse( const char *data, int nReturned );
protected:
friend class SyncClusterConnection;
virtual void recv( Message& m );
virtual void sayPiggyBack( Message &toSend );
virtual void checkResponse( const char *data, int nReturned );
};
/** Use this class to connect to a replica set of servers. The class will manage
@@ -987,9 +1004,12 @@ namespace mongo {
virtual ConnectionString::ConnectionType type() const { return ConnectionString::SET; }
virtual bool isMember( const DBConnector * conn ) const;
virtual void checkResponse( const char *data, int nReturned ) { checkMaster()->checkResponse( data , nReturned ); }
protected:
virtual void sayPiggyBack( Message &toSend ) { assert(false); }
virtual void checkResponse( const char *data, int nReturned ) { assert(false); }
virtual void sayPiggyBack( Message &toSend ) { checkMaster()->say( toSend ); }
bool isFailed() const {
return _currentMaster == 0 || _currentMaster->isFailed();

View File

@@ -193,7 +193,7 @@ namespace mongo {
void DBClientCursor::attach( AScopedConnection * conn ){
assert( _scopedHost.size() == 0 );
assert( connector == conn->get() );
assert( conn->get()->isMember( connector ) );
_scopedHost = conn->getHost();
conn->done();
connector = 0;

View File

@@ -109,9 +109,6 @@ namespace mongo {
bool DistributedLock::lock_try( string why , BSONObj * other ){
// check for recrusive
assert( getState() == 0 );
ScopedDbConnection conn( _conn );
BSONObjBuilder queryBuilder;
@@ -136,7 +133,7 @@ namespace mongo {
return false;
}
Date_t elapsed = jsTime() - lastPing["ping"].Date(); // in ms
unsigned long long elapsed = jsTime() - lastPing["ping"].Date(); // in ms
elapsed = elapsed / ( 1000 * 60 ); // convert to minutes
if ( elapsed <= _takeoverMinutes ){
@@ -208,18 +205,33 @@ namespace mongo {
if ( ! gotLock )
return false;
_state.set( 1 );
return true;
}
void DistributedLock::unlock(){
ScopedDbConnection conn( _conn );
conn->update( _ns , _id, BSON( "$set" << BSON( "state" << 0 ) ) );
log(1) << "dist_lock unlock: " << conn->findOne( _ns , _id ) << endl;
conn.done();
const int maxAttempts = 3;
int attempted = 0;
while ( ++attempted <= maxAttempts ) {
try {
ScopedDbConnection conn( _conn );
conn->update( _ns , _id, BSON( "$set" << BSON( "state" << 0 ) ) );
log(1) << "dist_lock unlock: " << conn->findOne( _ns , _id ) << endl;
conn.done();
return;
_state.set( 0 );
} catch ( std::exception& e) {
log( LL_WARNING ) << "dist_lock " << _name << " failed to contact config server in unlock attempt "
<< attempted << ": " << e.what() << endl;
sleepsecs(1 << attempted);
}
}
log( LL_WARNING ) << "dist_lock couldn't consumate unlock request. " << "Lock " << _name
<< " will be taken over after " << _takeoverMinutes << " minutes timeout" << endl;
}
}

View File

@@ -36,14 +36,6 @@ namespace mongo {
*/
DistributedLock( const ConnectionString& conn , const string& name , unsigned takeoverMinutes = 10 );
int getState(){
return _state.get();
}
bool isLocked(){
return _state.get() != 0;
}
bool lock_try( string why , BSONObj * other = 0 );
void unlock();
@@ -54,8 +46,6 @@ namespace mongo {
string _ns;
BSONObj _id;
ThreadLocalValue<int> _state;
};
class dist_lock_try {

View File

@@ -66,7 +66,6 @@ namespace mongo {
}
BSONObj GridFS::storeFile( const char* data , size_t length , const string& remoteName , const string& contentType){
massert( 10279 , "large files not yet implemented", length <= 0xffffffff);
char const * const end = data + length;
OID id;
@@ -127,8 +126,6 @@ namespace mongo {
if (fd != stdin)
fclose( fd );
massert( 10280 , "large files not yet implemented", length <= 0xffffffff);
return insertFile((remoteName.empty() ? fileName : remoteName), id, length, contentType);
}

View File

@@ -328,6 +328,38 @@ namespace mongo {
void ParallelSortClusteredCursor::_finishCons(){
_numServers = _servers.size();
_cursors = 0;
if ( ! _sortKey.isEmpty() && ! _fields.isEmpty() ){
// we need to make sure the sort key is in the project
bool isNegative = false;
BSONObjBuilder b;
{
BSONObjIterator i( _fields );
while ( i.more() ){
BSONElement e = i.next();
b.append( e );
if ( ! e.trueValue() )
isNegative = true;
}
}
{
BSONObjIterator i( _sortKey );
while ( i.more() ){
BSONElement e = i.next();
BSONElement f = _fields.getField( e.fieldName() );
if ( isNegative ){
uassert( 13431 , "have to have sort key in projection and removing it" , f.eoo() );
}
else if ( f.eoo() ){
// add to projection
b.append( e );
}
}
}
_fields = b.obj();
}
}
void ParallelSortClusteredCursor::_init(){

View File

@@ -369,4 +369,16 @@ namespace mongo {
// should never need to do this
assert(0);
}
bool SyncClusterConnection::isMember( const DBConnector * conn ) const {
if ( conn == this )
return true;
for ( unsigned i=0; i<_conns.size(); i++ )
if ( _conns[i]->isMember( conn ) )
return true;
return false;
}
}

View File

@@ -90,6 +90,8 @@ namespace mongo {
virtual ConnectionString::ConnectionType type() const { return ConnectionString::SYNC; }
virtual bool isMember( const DBConnector * conn ) const;
private:
SyncClusterConnection( SyncClusterConnection& prev );
string _toString() const;

View File

@@ -259,6 +259,29 @@ namespace mongo {
}
}
BSONObj CurOp::query( bool threadSafe ) {
if( querySize() == 1 ) {
return _tooBig;
}
if ( ! threadSafe ){
BSONObj o(_queryBuf);
return o;
}
int size = querySize();
int before = checksum( _queryBuf , size );
BSONObj a(_queryBuf);
BSONObj b = a.copy();
int after = checksum( _queryBuf , size );
if ( before == after )
return b;
return BSON( "msg" << "query changed while capturing" );
}
BSONObj CurOp::infoNoauth( int attempt ) {
BSONObjBuilder b;
b.append("opid", _opNum);
@@ -402,7 +425,7 @@ namespace mongo {
tablecell( ss , co.getOp() );
tablecell( ss , co.getNS() );
if ( co.haveQuery() )
tablecell( ss , co.query() );
tablecell( ss , co.query( true ) );
else
tablecell( ss , "" );
tablecell( ss , co.getRemoteString() );

View File

@@ -32,27 +32,37 @@
namespace mongo {
CCById ClientCursor::clientCursorsById;
CCByLoc ClientCursor::byLoc;
boost::recursive_mutex ClientCursor::ccmutex;
typedef multimap<DiskLoc, ClientCursor*> CCByLoc;
unsigned ClientCursor::byLocSize() {
CCById ClientCursor::clientCursorsById;
boost::recursive_mutex ClientCursor::ccmutex;
long long ClientCursor::numberTimedOut = 0;
/*static*/ void ClientCursor::assertNoCursors() {
recursive_scoped_lock lock(ccmutex);
return byLoc.size();
if( clientCursorsById.size() ) {
log() << "ERROR clientcursors exist but should not at this point" << endl;
ClientCursor *cc = clientCursorsById.begin()->second;
log() << "first one: " << cc->cursorid << ' ' << cc->ns << endl;
clientCursorsById.clear();
assert(false);
}
}
void ClientCursor::setLastLoc_inlock(DiskLoc L) {
if ( L == _lastLoc )
return;
CCByLoc& bl = byLoc();
if ( !_lastLoc.isNull() ) {
CCByLoc::iterator i = kv_find(byLoc, _lastLoc, this);
if ( i != byLoc.end() )
byLoc.erase(i);
CCByLoc::iterator i = kv_find(bl, _lastLoc, this);
if ( i != bl.end() )
bl.erase(i);
}
if ( !L.isNull() )
byLoc.insert( make_pair(L, this) );
bl.insert( make_pair(L, this) );
_lastLoc = L;
}
@@ -76,24 +86,52 @@ namespace mongo {
{
recursive_scoped_lock lock(ccmutex);
for ( CCByLoc::iterator i = byLoc.begin(); i != byLoc.end(); ++i ) {
Database *db = cc().database();
assert(db);
assert( str::startsWith(nsPrefix, db->name) );
for( CCById::iterator i = clientCursorsById.begin(); i != clientCursorsById.end(); ++i ) {
ClientCursor *cc = i->second;
if ( strncmp(nsPrefix, cc->ns.c_str(), len) == 0 )
if( cc->_db != db )
continue;
if ( strncmp(nsPrefix, cc->ns.c_str(), len) == 0 ) {
toDelete.push_back(i->second);
}
}
/*
note : we can't iterate byloc because clientcursors may exist with a loc of null in which case
they are not in the map. perhaps they should not exist though in the future? something to
change???
CCByLoc& bl = db->ccByLoc;
for ( CCByLoc::iterator i = bl.begin(); i != bl.end(); ++i ) {
ClientCursor *cc = i->second;
if ( strncmp(nsPrefix, cc->ns.c_str(), len) == 0 ) {
assert( cc->_db == db );
toDelete.push_back(i->second);
}
}*/
for ( vector<ClientCursor*>::iterator i = toDelete.begin(); i != toDelete.end(); ++i )
delete (*i);
}
}
bool ClientCursor::shouldTimeout( unsigned millis ){
_idleAgeMillis += millis;
return _idleAgeMillis > 600000 && _pinValue == 0;
}
/* called every 4 seconds. millis is amount of idle time passed since the last call -- could be zero */
void ClientCursor::idleTimeReport(unsigned millis) {
readlock lk("");
recursive_scoped_lock lock(ccmutex);
for ( CCByLoc::iterator i = byLoc.begin(); i != byLoc.end(); ) {
CCByLoc::iterator j = i;
for ( CCById::iterator i = clientCursorsById.begin(); i != clientCursorsById.end(); ) {
CCById::iterator j = i;
i++;
if( j->second->shouldTimeout( millis ) ){
numberTimedOut++;
log(1) << "killing old cursor " << j->second->cursorid << ' ' << j->second->ns
<< " idle:" << j->second->idleTime() << "ms\n";
delete j->second;
@@ -106,10 +144,12 @@ namespace mongo {
*/
void ClientCursor::informAboutToDeleteBucket(const DiskLoc& b) {
recursive_scoped_lock lock(ccmutex);
RARELY if ( byLoc.size() > 70 ) {
log() << "perf warning: byLoc.size=" << byLoc.size() << " in aboutToDeleteBucket\n";
Database *db = cc().database();
CCByLoc& bl = db->ccByLoc;
RARELY if ( bl.size() > 70 ) {
log() << "perf warning: byLoc.size=" << bl.size() << " in aboutToDeleteBucket\n";
}
for ( CCByLoc::iterator i = byLoc.begin(); i != byLoc.end(); i++ )
for ( CCByLoc::iterator i = bl.begin(); i != bl.end(); i++ )
i->second->c->aboutToDeleteBucket(b);
}
void aboutToDeleteBucket(const DiskLoc& b) {
@@ -120,8 +160,11 @@ namespace mongo {
void ClientCursor::aboutToDelete(const DiskLoc& dl) {
recursive_scoped_lock lock(ccmutex);
CCByLoc::iterator j = byLoc.lower_bound(dl);
CCByLoc::iterator stop = byLoc.upper_bound(dl);
Database *db = cc().database();
assert(db);
CCByLoc& bl = db->ccByLoc;
CCByLoc::iterator j = bl.lower_bound(dl);
CCByLoc::iterator stop = bl.upper_bound(dl);
if ( j == stop )
return;
@@ -139,6 +182,7 @@ namespace mongo {
for ( vector<ClientCursor*>::iterator i = toAdvance.begin(); i != toAdvance.end(); ++i ){
ClientCursor* cc = *i;
wassert(cc->_db == db);
if ( cc->_doingDeletes ) continue;
@@ -157,7 +201,9 @@ namespace mongo {
c->advance();
if ( c->eof() ) {
// advanced to end
// leave ClieneCursor in place so next getMore doesn't fail
// leave ClientCursor in place so next getMore doesn't fail
// still need to mark new location though
cc->updateLocation();
}
else {
wassert( c->refLoc() != dl );
@@ -296,6 +342,13 @@ namespace mongo {
int ctmLast = 0; // so we don't have to do find() which is a little slow very often.
long long ClientCursor::allocCursorId_inlock() {
if( 0 ) {
static long long z;
++z;
cout << "TEMP alloccursorid " << z << endl;
return z;
}
long long x;
int ctm = (int) curTimeMillis();
while ( 1 ) {
@@ -328,7 +381,13 @@ namespace mongo {
}
void ClientCursor::appendStats( BSONObjBuilder& result ){
recursive_scoped_lock lock(ccmutex);
result.appendNumber("totalOpen", (int)clientCursorsById.size() );
result.appendNumber("clientCursors_size", (int) numCursors());
result.appendNumber("timedOut" , (int)numberTimedOut);
}
// QUESTION: Restrict to the namespace from which this command was issued?
// Alternatively, make this command admin-only?
class CmdCursorInfo : public Command {
@@ -339,11 +398,8 @@ namespace mongo {
help << " example: { cursorInfo : 1 }";
}
virtual LockType locktype() const { return NONE; }
bool run(const string&, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ){
recursive_scoped_lock lock(ClientCursor::ccmutex);
result.append("totalOpen", unsigned( ClientCursor::clientCursorsById.size() ) );
result.append("byLocation_size", unsigned( ClientCursor::byLoc.size() ) );
result.append("clientCursors_size", unsigned( ClientCursor::clientCursorsById.size() ) );
bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ){
ClientCursor::appendStats( result );
return true;
}
} cmdCursorInfo;

View File

@@ -45,8 +45,6 @@ namespace mongo {
*/
typedef map<CursorId, ClientCursor*> CCById;
typedef multimap<DiskLoc, ClientCursor*> CCByLoc;
extern BSONObj id_obj;
class ClientCursor {
@@ -64,14 +62,13 @@ namespace mongo {
ElapsedTracker _yieldSometimesTracker;
static CCById clientCursorsById;
static CCByLoc byLoc;
static boost::recursive_mutex ccmutex; // must use this for all statics above!
static CursorId allocCursorId_inlock();
static long long numberTimedOut;
static boost::recursive_mutex ccmutex; // must use this for all statics above!
static CursorId allocCursorId_inlock();
public:
static void assertNoCursors();
/* use this to assure we don't in the background time out cursor while it is under use.
if you are using noTimeout() already, there is no risk anyway.
Further, this mechanism guards against two getMore requests on the same cursor executing
@@ -139,19 +136,23 @@ namespace mongo {
};
/*const*/ CursorId cursorid;
string ns;
shared_ptr<Cursor> c;
const string ns;
const shared_ptr<Cursor> c;
int pos; // # objects into the cursor so far
BSONObj query;
int _queryOptions; // see enum QueryOptions dbclient.h
const int _queryOptions; // see enum QueryOptions dbclient.h
OpTime _slaveReadTill;
Database * const _db;
ClientCursor(int queryOptions, shared_ptr<Cursor>& _c, const string& _ns) :
_idleAgeMillis(0), _pinValue(0),
_doingDeletes(false), _yieldSometimesTracker(128,10),
ns(_ns), c(_c),
pos(0), _queryOptions(queryOptions)
pos(0), _queryOptions(queryOptions),
_db( cc().database() )
{
assert( _db );
assert( str::startsWith(_ns, _db->name) );
if( queryOptions & QueryOption_NoCursorTimeout )
noTimeout();
recursive_scoped_lock lock(ccmutex);
@@ -308,10 +309,7 @@ namespace mongo {
/**
* @param millis amount of idle passed time since last call
*/
bool shouldTimeout( unsigned millis ){
_idleAgeMillis += millis;
return _idleAgeMillis > 600000 && _pinValue == 0;
}
bool shouldTimeout( unsigned millis );
void storeOpForSlave( DiskLoc last );
void updateSlaveLocation( CurOp& curop );
@@ -327,12 +325,18 @@ private:
void noTimeout() {
_pinValue++;
}
multimap<DiskLoc, ClientCursor*>& byLoc() {
return _db->ccByLoc;
}
public:
void setDoingDeletes( bool doingDeletes ){
_doingDeletes = doingDeletes;
}
static void appendStats( BSONObjBuilder& result );
static unsigned byLocSize(); // just for diagnostics
static unsigned numCursors() { return clientCursorsById.size(); }
static void informAboutToDeleteBucket(const DiskLoc& b);
static void aboutToDelete(const DiskLoc& dl);

View File

@@ -45,7 +45,7 @@ namespace mongo {
("bind_ip", po::value<string>(&cmdLine.bind_ip), "comma separated list of ip addresses to listen on - all local ips by default")
("logpath", po::value<string>() , "file to send all output to instead of stdout" )
("logappend" , "append to logpath instead of over-writing" )
("pidfilepath", po::value<string>(), "directory for pidfile (if not set, no pidfile is created)")
("pidfilepath", po::value<string>(), "full path to pidfile (if not set, no pidfile is created)")
#ifndef _WIN32
("fork" , "fork server process" )
#endif

View File

@@ -85,13 +85,7 @@ namespace mongo {
int querySize() const { return *((int *) _queryBuf); }
bool haveQuery() const { return querySize() != 0; }
BSONObj query() {
if( querySize() == 1 ) {
return _tooBig;
}
BSONObj o(_queryBuf);
return o;
}
BSONObj query( bool threadSafe = false);
void ensureStarted(){
if ( _start == 0 )

View File

@@ -22,6 +22,8 @@
namespace mongo {
class ClientCursor;
/**
* Database represents a database database
* Each database database has its own set of files -- dbname.ns, dbname.0, dbname.1, ...
@@ -196,6 +198,9 @@ namespace mongo {
NamespaceIndex namespaceIndex;
int profile; // 0=off.
string profileName; // "alleyinsider.system.profile"
multimap<DiskLoc, ClientCursor*> ccByLoc;
int magic; // used for making sure the object is still loaded in memory
};

View File

@@ -126,6 +126,7 @@ namespace mongo {
assert( sprintf( buf , "w block pass: %lld" , ++passes ) < 30 );
c.curop()->setMessage( buf );
sleepmillis(1);
killCurrentOp.checkForInterrupt();
}
result.appendNumber( "wtime" , t.millis() );
}
@@ -159,32 +160,6 @@ namespace mongo {
}
} cmdGetPrevError;
class CmdSwitchToClientErrors : public Command {
public:
virtual bool requiresAuth() { return false; }
virtual bool logTheOp() {
return false;
}
virtual void help( stringstream& help ) const {
help << "convert to id based errors rather than connection based";
}
virtual bool slaveOk() const {
return true;
}
virtual LockType locktype() const { return NONE; }
CmdSwitchToClientErrors() : Command("switchToClientErrors", false, "switchtoclienterrors") {}
bool run(const string& dbnamne , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
if ( lastError.getID() ){
errmsg = "already in client id mode";
return false;
}
LastError *le = lastError.disableForCommand();
le->overridenById = true;
result << "ok" << 1;
return true;
}
} cmdSwitchToClientErrors;
class CmdDropDatabase : public Command {
public:
virtual bool logTheOp() {
@@ -292,7 +267,6 @@ namespace mongo {
}
bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
long long start = Listener::getElapsedTimeMillis();
BSONObjBuilder timeBuilder(128);
@@ -381,7 +355,13 @@ namespace mongo {
globalFlushCounters.append( bb );
bb.done();
}
{
BSONObjBuilder bb( result.subobjStart( "cursros" ) );
ClientCursor::appendStats( bb );
bb.done();
}
timeBuilder.appendNumber( "after counters" , Listener::getElapsedTimeMillis() - start );
if ( anyReplEnabled() ){
@@ -648,10 +628,10 @@ namespace mongo {
virtual void help( stringstream& help ) const {
help << "create a collection";
}
virtual bool run(const string& dbname , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
virtual bool run(const string& dbname , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
string ns = dbname + '.' + cmdObj.firstElement().valuestr();
string err;
bool ok = userCreateNS(ns.c_str(), cmdObj, err, true);
bool ok = userCreateNS(ns.c_str(), cmdObj, err, ! fromRepl );
if ( !ok && !err.empty() )
errmsg = err;
return ok;
@@ -1450,17 +1430,18 @@ namespace mongo {
BSONElementSet values;
shared_ptr<Cursor> cursor = bestGuessCursor(ns.c_str() , query , BSONObj() );
scoped_ptr<ClientCursor> cc (new ClientCursor(QueryOption_NoCursorTimeout, cursor, ns));
while ( cursor->ok() ){
if ( cursor->matcher() && ! cursor->matcher()->matchesCurrent( cursor.get() ) ){
cursor->advance();
continue;
if ( !cursor->matcher() || cursor->matcher()->matchesCurrent( cursor.get() ) ){
BSONObj o = cursor->current();
o.getFieldsDotted( key, values );
}
BSONObj o = cursor->current();
cursor->advance();
o.getFieldsDotted( key.c_str(), values );
if (!cc->yieldSometimes())
break;
}
BSONArrayBuilder b( result.subarrayStart( "values" ) );

View File

@@ -60,6 +60,13 @@ namespace mongo {
bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ){
result << "version" << versionString << "gitVersion" << gitVersion() << "sysInfo" << sysInfo();
result << "bits" << ( sizeof( int* ) == 4 ? 32 : 64 );
result.appendBool( "debug" ,
#ifdef _DEBUG
true
#else
false
#endif
);
return true;
}
} cmdBuildInfo;

View File

@@ -432,7 +432,7 @@ namespace mongo {
ss << p( a("/", "back", "Home") );
ss << p( "<b>MongoDB List of <a href=\"http://www.mongodb.org/display/DOCS/Commands\">Commands</a></b>\n" );
const map<string, Command*> *m = Command::commandsByBestName();
ss << "S:slave-only N:no-lock R:read-lock W:write-lock A:admin-only<br>\n";
ss << "S:slave-ok R:read-lock W:write-lock A:admin-only<br>\n";
ss << table();
ss << "<tr><th>Command</th><th>Attributes</th><th>Help</th></tr>\n";
for( map<string, Command*>::const_iterator i = m->begin(); i != m->end(); i++ )

View File

@@ -143,6 +143,7 @@ namespace mongo {
}
virtual ConnectionString::ConnectionType type() const { return ConnectionString::MASTER; }
virtual bool isMember( const DBConnector * conn ) const { return this == conn; };
};
extern int lockFile;

View File

@@ -168,9 +168,7 @@ namespace mongo {
}
LastError * LastErrorHolder::startRequest( Message& m , int clientId ) {
if ( clientId == 0 )
clientId = m.header()->id & 0xFFFF0000;
assert( clientId );
setID( clientId );
LastError * le = _get( true );
@@ -179,11 +177,7 @@ namespace mongo {
}
void LastErrorHolder::startRequest( Message& m , LastError * connectionOwned ) {
if ( !connectionOwned->overridenById ) {
prepareErrForNewRequest( m, connectionOwned );
return;
}
startRequest(m);
prepareErrForNewRequest( m, connectionOwned );
}
void LastErrorHolder::disconnect( int clientId ){

View File

@@ -32,7 +32,6 @@ namespace mongo {
long long nObjects;
int nPrev;
bool valid;
bool overridenById;
bool disabled;
void writeback( OID& oid ){
reset( true );
@@ -56,7 +55,6 @@ namespace mongo {
nObjects = nDeleted;
}
LastError() {
overridenById = false;
reset();
}
void reset( bool _valid = false ) {
@@ -127,7 +125,7 @@ namespace mongo {
/** when db receives a message/request, call this */
void startRequest( Message& m , LastError * connectionOwned );
LastError * startRequest( Message& m , int clientId = 0 );
LastError * startRequest( Message& m , int clientId );
void disconnect( int clientId );

View File

@@ -176,11 +176,11 @@ namespace mongo {
{ // query options
if ( cmdObj["query"].type() == Object ){
filter = cmdObj["query"].embeddedObjectUserCheck();
q = filter;
}
if ( cmdObj["sort"].type() == Object )
q.sort( cmdObj["sort"].embeddedObjectUserCheck() );
if ( cmdObj["sort"].type() == Object ){
sort = cmdObj["sort"].embeddedObjectUserCheck();
}
if ( cmdObj["limit"].isNumber() )
limit = cmdObj["limit"].numberLong();
@@ -222,7 +222,7 @@ namespace mongo {
// query options
BSONObj filter;
Query q;
BSONObj sort;
long long limit;
// functions
@@ -444,7 +444,7 @@ namespace mongo {
readlock lock( mr.ns );
Client::Context ctx( mr.ns );
shared_ptr<Cursor> temp = bestGuessCursor( mr.ns.c_str(), mr.filter, BSONObj() );
shared_ptr<Cursor> temp = bestGuessCursor( mr.ns.c_str(), mr.filter, mr.sort );
auto_ptr<ClientCursor> cursor( new ClientCursor( QueryOption_NoCursorTimeout , temp , mr.ns.c_str() ) );
Timer mt;

View File

@@ -637,6 +637,8 @@ namespace mongo {
}
bool legalClientSystemNS( const string& ns , bool write ){
if( ns == "local.system.replset" ) return true;
if ( ns.find( ".system.users" ) != string::npos )
return true;

View File

@@ -728,8 +728,11 @@ namespace mongo {
try {
assert( dropIndexes(d, name.c_str(), "*", errmsg, result, true) );
}
catch( DBException& ) {
uasserted(12503,"drop: dropIndexes for collection failed - consider trying repair");
catch( DBException& e ) {
stringstream ss;
ss << "drop: dropIndexes for collection failed - consider trying repair ";
ss << " cause: " << e.what();
uasserted(12503,ss.str());
}
assert( d->nIndexes == 0 );
}
@@ -1892,7 +1895,10 @@ namespace mongo {
bb.done();
if( nNotClosed )
result.append("nNotClosed", nNotClosed);
else {
ClientCursor::assertNoCursors();
}
return true;
}

View File

@@ -654,11 +654,12 @@ namespace mongo {
if ( !ClientCursor::recoverFromYield( _yieldData ) ) {
_c.reset();
_cc.reset();
_so.reset();
massert( 13338, "cursor dropped during query", false );
// TODO maybe we want to prevent recording the winning plan as well?
}
}
}
}
virtual void next() {
if ( _findingStartCursor.get() ) {
@@ -772,7 +773,8 @@ namespace mongo {
_n = _inMemSort ? _so->size() : _n;
}
else if ( _inMemSort ) {
_so->fill( _buf, _pq.getFields() , _n );
if( _so.get() )
_so->fill( _buf, _pq.getFields() , _n );
}
if ( _pq.hasOption( QueryOption_CursorTailable ) && _pq.getNumToReturn() != 1 )

View File

@@ -290,11 +290,13 @@ namespace mongo {
}
}
else {
result.append("ismaster", replSettings.master || replSettings.slave == 0 ? 1 : 0);
//result.append("msg", "not paired");
result.appendBool("ismaster", _isMaster() );
}
if ( level ){
if ( level && replSet ){
result.append( "info" , "is replica set" );
}
else if ( level ){
BSONObjBuilder sources( result.subarrayStart( "sources" ) );
readlock lk( "local.sources" );
@@ -856,11 +858,13 @@ namespace mongo {
see logOp() comments.
*/
void ReplSource::sync_pullOpLog_applyOperation(BSONObj& op, OpTime *localLogTail) {
log( 6 ) << "processing op: " << op << endl;
if( logLevel >= 6 ) // op.tostring is expensive so doing this check explicitly
log(6) << "processing op: " << op << endl;
// skip no-op
if ( op.getStringField( "op" )[ 0 ] == 'n' )
if( op.getStringField("op")[0] == 'n' )
return;
char clientName[MaxDatabaseLen];
const char *ns = op.getStringField("ns");
nsToDatabase(ns, clientName);
@@ -1301,12 +1305,15 @@ namespace mongo {
1) find most recent op in local log
2) more()?
*/
if ( !oplogReader.more() ) {
bool moreInitialSyncsPending = !addDbNextPass.empty() && n; // we need "&& n" to assure we actually process at least one op to get a sync point recorded in the first place.
if ( moreInitialSyncsPending || !oplogReader.more() ) {
dblock lk;
OpTime nextLastSaved = nextLastSavedLocalTs();
{
dbtemprelease t;
if ( oplogReader.more() ) {
if ( !moreInitialSyncsPending && oplogReader.more() ) {
if ( getInitialSyncCompleted() ) { // if initial sync hasn't completed, break out of loop so we can set to completed or clone more dbs
continue;
}
@@ -1323,6 +1330,8 @@ namespace mongo {
log() << "repl: end sync_pullOpLog syncedTo: " << syncedTo.toStringLong() << endl;
break;
}
else {
}
OCCASIONALLY if( n > 0 && ( n > 100000 || time(0) - saveLast > 60 ) ) {
// periodically note our progress, in case we are doing a lot of work and crash

View File

@@ -171,7 +171,7 @@ namespace mongo {
}
void ReplSetImpl::_getOplogDiagsAsHtml(unsigned server_id, stringstream& ss) const {
Member *m = findById(server_id);
const Member *m = findById(server_id);
if( m == 0 ) {
ss << "Error : can't find a member with id: " << server_id << '\n';
return;
@@ -329,7 +329,7 @@ namespace mongo {
_rsLog.toHTML( s );
}
Member* ReplSetImpl::findById(unsigned id) const {
const Member* ReplSetImpl::findById(unsigned id) const {
if( id == _self->id() ) return _self;
for( Member *m = head(); m; m = m->next() )
if( m->id() == id )
@@ -371,6 +371,7 @@ namespace mongo {
v.push_back(bb.obj());
m = m->next();
}
sort(v.begin(), v.end());
b.append("set", name());
b.appendTimeT("date", time(0));
b.append("myState", box.getState().s);

View File

@@ -26,7 +26,7 @@
namespace mongo {
void checkAllMembersUpForConfigChange(const ReplSetConfig& cfg, bool initial);
void checkMembersUpForConfigChange(const ReplSetConfig& cfg, bool initial);
/* commands in other files:
replSetHeartbeat - health.cpp
@@ -151,9 +151,9 @@ namespace mongo {
return false;
}
checkAllMembersUpForConfigChange(newConfig,false);
checkMembersUpForConfigChange(newConfig,false);
log() << "replSet replSetReconfig all members seem up" << rsLog;
log() << "replSet replSetReconfig [2]" << rsLog;
theReplSet->haveNewConfig(newConfig, true);
ReplSet::startupStatusMsg = "replSetReconfig'd";

View File

@@ -123,6 +123,7 @@ namespace mongo {
void ReplSetImpl::_fillIsMaster(BSONObjBuilder& b) {
const StateBox::SP sp = box.get();
bool isp = sp.state.primary();
b.append("setName", name());
b.append("ismaster", isp);
b.append("secondary", sp.state.secondary());
{
@@ -390,9 +391,9 @@ namespace mongo {
startupStatus = EMPTYCONFIG;
startupStatusMsg = "can't get " + rsConfigNs + " config from self or any seed (EMPTYCONFIG)";
log() << "replSet can't get " << rsConfigNs << " config from self or any seed (EMPTYCONFIG)" << rsLog;
log() << "replSet have you ran replSetInitiate yet?" << rsLog;
log(1) << "replSet have you ran replSetInitiate yet?" << rsLog;
if( _seeds->size() == 0 )
log() << "replSet no seed hosts were specified on the --replSet command line - that might be the issue" << rsLog;
log(1) << "replSet info no seed hosts were specified on the --replSet command line" << rsLog;
}
else {
startupStatus = EMPTYUNREACHABLE;

View File

@@ -305,7 +305,9 @@ namespace mongo {
private:
Member* head() const { return _members.head(); }
Member* findById(unsigned id) const;
public:
const Member* findById(unsigned id) const;
private:
void _getTargets(list<Target>&, int &configVersion);
void getTargets(list<Target>&, int &configVersion);
void startThreads();

View File

@@ -114,7 +114,7 @@ namespace mongo {
mchk(_id >= 0 && _id <= 255);
mchk(priority >= 0 && priority <= 1000);
mchk(votes >= 0 && votes <= 100);
uassert(13419, "replica set config : this version of mongo only supports priorities 0 and 1", priority == 0 || priority == 1);
uassert(13419, "this version of mongod only supports priorities 0 and 1", priority == 0 || priority == 1);
}
/*static*/ bool ReplSetConfig::legalChange(const ReplSetConfig& o, const ReplSetConfig& n, string& errmsg) {
@@ -133,7 +133,7 @@ namespace mongo {
/* TODO : MORE CHECKS HERE */
cout << "TODO : don't allow removal of a node until we handle it at the removed node end." << endl;
log() << "replSet TODO : don't allow removal of a node until we handle it at the removed node end?" << endl;
// we could change its votes to zero perhaps instead as a short term...
return true;
@@ -220,7 +220,7 @@ namespace mongo {
catch(DBException& e) {
log() << "replSet cfg parsing exception for members[" << i << "] " << e.what() << rsLog;
stringstream ss;
ss << "replSet members[" << i << "] bad config object";
ss << "bad config for member[" << i << "] " << e.what();
uassert(13135, ss.str(), false);
}
if( !(ords.count(m._id) == 0 && hosts.count(m.h.toString()) == 0) ) {

View File

@@ -32,10 +32,12 @@ using namespace mongoutils;
namespace mongo {
/* throws
@param initial -
/* called on a reconfig AND on initiate
throws
@param initial true when initiating
*/
void checkAllMembersUpForConfigChange(const ReplSetConfig& cfg, bool initial) {
void checkMembersUpForConfigChange(const ReplSetConfig& cfg, bool initial) {
int failures = 0;
int me = 0;
for( vector<ReplSetConfig::MemberCfg>::const_iterator i = cfg.members.begin(); i != cfg.members.end(); i++ ) {
if( i->h.isSelf() ) {
@@ -45,7 +47,7 @@ namespace mongo {
}
}
}
uassert(13278, "bad config?", me <= 1);
uassert(13278, "bad config - dups?", me <= 1); // dups?
uassert(13279, "can't find self in the replset config", me == 1);
for( vector<ReplSetConfig::MemberCfg>::const_iterator i = cfg.members.begin(); i != cfg.members.end(); i++ ) {
@@ -62,12 +64,11 @@ namespace mongo {
}
}
catch(DBException& e) {
log() << "replSet requestHeartbeat " << i->h.toString() << " : " << e.toString() << rsLog;
log() << "replSet cmufcc requestHeartbeat " << i->h.toString() << " : " << e.toString() << rsLog;
}
catch(...) {
log() << "replSet error exception in requestHeartbeat?" << rsLog;
log() << "replSet cmufcc error exception in requestHeartbeat?" << rsLog;
}
cout << "TEMP hb res cfg change:" << res.toString() << endl;
if( res.getBoolField("mismatch") )
uasserted(13145, "set name does not match the set name host " + i->h.toString() + " expects");
if( *res.getStringField("set") ) {
@@ -83,9 +84,31 @@ namespace mongo {
}
}
if( !ok && !res["rs"].trueValue() ) {
if( !res.isEmpty() )
if( !res.isEmpty() ) {
/* strange. got a response, but not "ok". log it. */
log() << "replSet warning " << i->h.toString() << " replied: " << res.toString() << rsLog;
uasserted(13144, "need members up to initiate/reconfig, not ok: " + i->h.toString());
}
bool allowFailure = false;
failures++;
if( res.isEmpty() && !initial && failures == 1 ) {
/* for now we are only allowing 1 node to be down on a reconfig. this can be made to be a minority
trying to keep change small as release is near.
*/
const Member* m = theReplSet->findById( i->_id );
if( m ) {
// ok, so this was an existing member (wouldn't make sense to add to config a new member that is down)
assert( m->h().toString() == i->h.toString() );
allowFailure = true;
}
}
if( !allowFailure ) {
string msg = string("need members up to initiate, not ok : ") + i->h.toString();
if( !initial )
msg = string("need most members up to reconfigure, not ok : ") + i->h.toString();
uasserted(13144, msg);
}
}
}
if( initial ) {
@@ -175,8 +198,10 @@ namespace mongo {
configObj = cmdObj["replSetInitiate"].Obj();
}
bool parsed = false;
try {
ReplSetConfig newConfig(configObj);
parsed = true;
if( newConfig.version > 1 ) {
errmsg = "can't initiate with a version number greater than 1";
@@ -185,7 +210,7 @@ namespace mongo {
log() << "replSet replSetInitiate config object parses ok, " << newConfig.members.size() << " members specified" << rsLog;
checkAllMembersUpForConfigChange(newConfig, true);
checkMembersUpForConfigChange(newConfig, true);
log() << "replSet replSetInitiate all members seem up" << rsLog;
@@ -199,7 +224,11 @@ namespace mongo {
}
catch( DBException& e ) {
log() << "replSet replSetInitiate exception: " << e.what() << rsLog;
throw;
if( !parsed )
errmsg = string("couldn't parse cfg object ") + e.what();
else
errmsg = string("couldn't initiate : ") + e.what();
return false;
}
return true;

View File

@@ -203,8 +203,8 @@ namespace mongo {
OpTime ts = o["ts"]._opTime();
long long h = o["h"].numberLong();
if( ts != lastOpTimeWritten || h != lastH ) {
log() << "TEMP our last op time written: " << lastOpTimeWritten.toStringPretty() << endl;
log() << "TEMP primary's GTE: " << ts.toStringPretty() << endl;
log(1) << "TEMP our last op time written: " << lastOpTimeWritten.toStringPretty() << endl;
log(1) << "TEMP primary's GTE: " << ts.toStringPretty() << endl;
/*
}*/
@@ -243,7 +243,6 @@ namespace mongo {
}
else {
sethbmsg(str::stream() << "still syncing, not yet to minValid optime " << minvalid.toString());
//log() << "TEMP " << lastOpTimeWritten.toString() << rsLog;
}
/* todo: too stale capability */

View File

@@ -164,7 +164,7 @@ namespace mongo {
if( replSet ) {
/* todo: speed up the secondary case. as written here there are 2 mutex entries, it can be 1. */
if( isMaster() ) return;
notMasterUnless( pq.hasOption(QueryOption_SlaveOk) && theReplSet->isSecondary() );
notMasterUnless( pq.hasOption(QueryOption_SlaveOk) && theReplSet && theReplSet->isSecondary() );
} else {
notMasterUnless(isMaster() || pq.hasOption(QueryOption_SlaveOk) || replSettings.slave == SimpleSlave );
}

View File

@@ -266,8 +266,8 @@ namespace mongo {
ss << "# databases: " << dbHolder.size() << '\n';
if( ClientCursor::byLocSize()>500 )
ss << "Cursors byLoc.size(): " << ClientCursor::byLocSize() << '\n';
if( ClientCursor::numCursors()>500 )
ss << "# Cursors: " << ClientCursor::numCursors() << '\n';
ss << "\nreplication: ";
if( *replInfo )

View File

@@ -88,16 +88,17 @@ namespace mongo {
void _add(BSONObj& k, BSONObj o, DiskLoc* loc) {
if (!loc){
best.insert(make_pair(k,o));
best.insert(make_pair(k.getOwned(),o.getOwned()));
} else {
BSONObjBuilder b;
b.appendElements(o);
b.append("$diskLoc", loc->toBSONObj());
best.insert(make_pair(k, b.obj()));
best.insert(make_pair(k.getOwned(), b.obj().getOwned()));
}
}
void _addIfBetter(BSONObj& k, BSONObj o, BestMap::iterator i, DiskLoc* loc) {
/* todo : we don't correct approxSize here. */
const BSONObj& worstBestKey = i->first;
int c = worstBestKey.woCompare(k, order.pattern);
if ( c > 0 ) {
@@ -124,7 +125,11 @@ namespace mongo {
BSONObj k = order.getKeyFromObject(o);
if ( (int) best.size() < limit ) {
approxSize += k.objsize();
uassert( 10128 , "too much key data for sort() with no index. add an index or specify a smaller limit", approxSize < 1 * 1024 * 1024 );
approxSize += o.objsize();
/* note : adjust when bson return limit adjusts. note this limit should be a bit higher. */
uassert( 10128 , "too much data for sort() with no index. add an index or specify a smaller limit", approxSize < 32 * 1024 * 1024 );
_add(k, o, loc);
return;
}

View File

@@ -527,7 +527,7 @@ namespace mongo {
string field = root + e.fieldName();
FieldCompareResult cmp = compareDottedFieldNames( m->second.m->fieldName , field );
DEBUGUPDATE( "\t\t\t field:" << field << "\t mod:" << m->second.m->fieldName << "\t cmp:" << cmp );
DEBUGUPDATE( "\t\t\t field:" << field << "\t mod:" << m->second.m->fieldName << "\t cmp:" << cmp << "\t short: " << e.fieldName() );
switch ( cmp ){
@@ -550,6 +550,13 @@ namespace mongo {
e = es.next();
m++;
}
else {
// this is a very weird case
// have seen it in production, but can't reproduce
// this assert prevents an inf. loop
// but likely isn't the correct solution
assert(0);
}
continue;
}
case LEFT_BEFORE: // Mod on a field that doesn't exist
@@ -613,6 +620,8 @@ namespace mongo {
BSONObjIteratorSorted i( query );
while ( i.more() ){
BSONElement e = i.next();
if ( e.fieldName()[0] == '$' ) // for $atomic and anything else we add
continue;
if ( e.type() == Object && e.embeddedObject().firstElement().fieldName()[0] == '$' ){
// this means this is a $gt type filter, so don't make part of the new object

View File

@@ -389,6 +389,35 @@ namespace JsobjTests {
}
};
class ToStringNumber {
public:
void run(){
BSONObjBuilder b;
b.append( "a" , (int)4 );
b.append( "b" , (double)5 );
b.append( "c" , (long long)6 );
b.append( "d" , 123.456789123456789123456789123456789 );
b.append( "e" , 123456789.123456789123456789123456789 );
b.append( "f" , 1234567891234567891234.56789123456789 );
b.append( "g" , -123.456 );
BSONObj x = b.obj();
ASSERT_EQUALS( "4", x["a"].toString( false , true ) );
ASSERT_EQUALS( "5.0", x["b"].toString( false , true ) );
ASSERT_EQUALS( "6", x["c"].toString( false , true ) );
ASSERT_EQUALS( "123.4567891234568" , x["d"].toString( false , true ) );
ASSERT_EQUALS( "123456789.1234568" , x["e"].toString( false , true ) );
// ASSERT_EQUALS( "1.234567891234568e+21" , x["f"].toString( false , true ) ); // windows and *nix are different - TODO, work around for test or not bother?
ASSERT_EQUALS( "-123.456" , x["g"].toString( false , true ) );
}
};
class NullString {
public:
void run() {
@@ -1693,6 +1722,7 @@ namespace JsobjTests {
add< BSONObjTests::AppendIntOrLL >();
add< BSONObjTests::AppendNumber >();
add< BSONObjTests::ToStringArray >();
add< BSONObjTests::ToStringNumber >();
add< BSONObjTests::NullString >();
add< BSONObjTests::Validation::BadType >();
add< BSONObjTests::Validation::EooBeforeEnd >();

25
debian/changelog vendored
View File

@@ -1,8 +1,33 @@
mongodb (1.6.2) unstable; urgency=low
* replica_sets some fixes
* sharding some fixes with rs
* full change log http://jira.mongodb.org/browse/SERVER/fixforversion/10187
-- Richard Kreuter <richard@10gen.com> Wed, 1 Sep 2010 16:56:28 -0500
mongodb (1.6.1) unstable; urgency=low
* replica_sets some fixes
* sharding some fixes with rs
* full change log http://jira.mongodb.org/browse/SERVER/fixforversion/10183
-- Richard Kreuter <richard@10gen.com> Tue, 17 Aug 2010 16:56:28 -0500
mongodb (1.6.0) unstable; urgency=low
* sharding stable
* replica_sets stable
-- Richard Kreuter <richard@10gen.com> Thu, 05 Aug 2010 16:56:28 -0500
mongodb (1.5.8) unstable; urgency=low
* sharding lots of changes
* replica_sets lots of changes
-- Richard Kreuter <richard@10gen.com> Tue, 03 Aug 2010 16:56:28 -0500
mongodb (1.5.7) unstable; urgency=low

View File

@@ -3,7 +3,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = MongoDB
PROJECT_NUMBER = 1.5.8
PROJECT_NUMBER = 1.6.2
OUTPUT_DIRECTORY = docs/doxygen
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English

View File

@@ -1,5 +1,5 @@
t = db.getCollection( "foo" );
t = db.getCollection( "foo_basic3" );
t.find( { "a.b" : 1 } ).toArray();

View File

@@ -1,5 +1,5 @@
t = db.getCollection( "foo" );
t = db.getCollection( "foo_basic9" );
t.save( { "foo$bar" : 5 } );

View File

@@ -21,4 +21,10 @@ assert( res.databases && res.databases.length > 0 , "listDatabases 1 " + tojson(
x = db._adminCommand( "ismaster" );
assert( x.ismaster , "ismaster failed: " + tojson( x ) )
before = db.runCommand( "serverStatus" )
sleep( 5000 )
after = db.runCommand( "serverStatus" )
assert.lt( 3 , after.uptimeEstimate , "up1" )
assert.gt( after.uptimeEstimate , before.uptimeEstimate , "up2" )
// TODO: add more tests here

View File

@@ -1,6 +1,6 @@
a = db.getSisterDB( "test_dbnamea" )
b = db.getSisterDB( "test_dbnameA" )
a = db.getSisterDB( "dbcasetest_dbnamea" )
b = db.getSisterDB( "dbcasetest_dbnameA" )
a.dropDatabase();
b.dropDatabase();

31
jstests/delx.js Normal file
View File

@@ -0,0 +1,31 @@
a = db.getSisterDB("delxa" )
b = db.getSisterDB("delxb" )
function setup( mydb ){
mydb.dropDatabase();
for ( i=0; i<100; i++ ){
mydb.foo.insert( { _id : i } );
}
mydb.getLastError();
}
setup( a );
setup( b );
assert.eq( 100 , a.foo.find().itcount() , "A1" )
assert.eq( 100 , b.foo.find().itcount() , "A2" )
x = a.foo.find().sort( { _id : 1 } ).batchSize( 60 )
y = b.foo.find().sort( { _id : 1 } ).batchSize( 60 )
x.next();
y.next();
a.foo.remove( { _id : { $gt : 50 } } );
assert.eq( 51 , a.foo.find().itcount() , "B1" )
assert.eq( 100 , b.foo.find().itcount() , "B2" )
assert.eq( 59 , x.itcount() , "C1" )
assert.eq( 99 , y.itcount() , "C2" ); // this was asserting because ClientCursor byLoc doesn't take db into consideration

View File

@@ -141,6 +141,14 @@ assert.soon( function(){ return am.lotOfIndexes.getIndexes().length == as.lotOfI
assert.eq( am.lotOfIndexes.getIndexes().length , as.lotOfIndexes.getIndexes().length , "lots of indexes b" )
// multi-update with $inc
am.mu1.update( { _id : 1 , $atomic : 1 } , { $inc : { x : 1 } } , true , true )
x = { _id : 1 , x : 1 }
assert.eq( x , am.mu1.findOne() , "mu1" );
assert.soon( function(){ z = as.mu1.findOne(); printjson( z ); return friendlyEqual( x , z ); } , "mu2" )
rt.stop();

View File

@@ -27,7 +27,7 @@ doTest = function( signal ) {
var master = replTest.getMaster();
var config = master.getDB("local").system.replset.findOne();
replTest.stopSet( signal );
replTest.stopSet( signal , true );
replTest.restart(0);
replTest.restart(1);

View File

@@ -0,0 +1,52 @@
// don't start any shards, yet
s = new ShardingTest( "add_shard2", 1, 0, 1, {useHostname : true} );
var conn1 = startMongodTest( 30001 , "add_shard21" , 0 , {useHostname : true} );
var conn2 = startMongodTest( 30002 , "add_shard22" , 0 , {useHostname : true} );
var rs1 = new ReplSetTest( { "name" : "add_shard2_rs1", nodes : 3 , startPort : 31200 } );
rs1.startSet();
rs1.initiate();
var master1 = rs1.getMaster();
var rs2 = new ReplSetTest( { "name" : "add_shard2_rs2", nodes : 3 , startPort : 31203 } );
rs2.startSet();
rs2.initiate();
var master2 = rs2.getMaster();
// step 1. name given
assert(s.admin.runCommand({"addshard" : getHostName()+":30001", "name" : "bar"}).ok, "failed to add shard in step 1");
var shard = s.getDB("config").shards.findOne({"_id" : {"$nin" : ["shard0000"]}});
assert(shard, "shard wasn't found");
assert.eq("bar", shard._id, "shard has incorrect name");
// step 2. replica set
assert(s.admin.runCommand({"addshard" : "add_shard2_rs1/"+getHostName()+":31200"}).ok, "failed to add shard in step 2");
shard = s.getDB("config").shards.findOne({"_id" : {"$nin" : ["shard0000", "bar"]}});
assert(shard, "shard wasn't found");
assert.eq("add_shard2_rs1", shard._id, "t2 name");
// step 3. replica set w/ name given
assert(s.admin.runCommand({"addshard" : "add_shard2_rs2/"+getHostName()+":31203", "name" : "myshard"}).ok,
"failed to add shard in step 4");
shard = s.getDB("config").shards.findOne({"_id" : {"$nin" : ["shard0000", "bar", "add_shard2_rs1"]}});
assert(shard, "shard wasn't found");
assert.eq("myshard", shard._id, "t3 name");
// step 4. no name given
assert(s.admin.runCommand({"addshard" : getHostName()+":30002"}).ok, "failed to add shard in step 4");
shard = s.getDB("config").shards.findOne({"_id" : {"$nin" : ["shard0000", "bar", "add_shard2_rs1", "myshard"]}});
assert(shard, "shard wasn't found");
assert.eq("shard0001", shard._id, "t4 name");
assert.eq(s.getDB("config").shards.count(), 5, "unexpected number of shards");
// step 5. replica set w/ a wrong host
assert(!s.admin.runCommand({"addshard" : "add_shard2_rs2/NonExistingHost:31203"}).ok, "accepted bad hostname in step 5");
// step 6. replica set w/ mixed wrong/right hosts
assert(!s.admin.runCommand({"addshard" : "add_shard2_rs2/"+getHostName()+":31203,foo:9999"}).ok,
"accepted bad hostname in step 6");
s.stop();

View File

@@ -6,8 +6,14 @@ s.adminCommand( { shardcollection : "test.data" , key : { num : 1 } } );
db = s.getDB( "test" );
for ( i=0; i<100; i++ ){
db.data.insert( { _id : i , num : i } );
N = 100
forward = []
backward = []
for ( i=0; i<N; i++ ){
db.data.insert( { _id : i , num : i , x : N - i } )
forward.push( i )
backward.push( ( N - 1 ) - i )
}
db.getLastError();
@@ -23,7 +29,7 @@ assert.eq( temp[0].shard , temp[2].shard , "A2" );
assert.neq( temp[0].shard , temp[1].shard , "A3" );
temp = db.data.find().sort( { num : 1 } ).toArray();
assert.eq( 100 , temp.length , "B1" );
assert.eq( N , temp.length , "B1" );
for ( i=0; i<100; i++ ){
assert.eq( i , temp[i].num , "B2" )
}
@@ -39,6 +45,37 @@ assert.eq( 67 , z.length , "C2" )
print( "a: " + a + " b:" + b + " mongos slow down: " + Math.ceil( 100 * ( ( a - b ) / b ) ) + "%" )
//assert.lt( a , b * 1.3 , "C3 - speed test" );
// -- secondary index sorting
function getSorted( by , want , dir , proj ){
var s = {}
s[by] = dir || 1;
printjson( s )
var cur = db.data.find( {} , proj || {} ).sort( s )
return terse( cur.map( function(z){ return z[want]; } ) );
}
function terse( a ){
var s = "";
for ( var i=0; i<a.length; i++ ){
if ( i > 0 )
s += ",";
s += a[i];
}
return s;
}
forward = terse(forward);
backward = terse(backward);
assert.eq( forward , getSorted( "num" , "num" , 1 ) , "D1" )
assert.eq( backward , getSorted( "num" , "num" , -1 ) , "D2" )
assert.eq( backward , getSorted( "x" , "num" , 1 ) , "D3" )
assert.eq( forward , getSorted( "x" , "num" , -1 ) , "D4" )
assert.eq( backward , getSorted( "x" , "num" , 1 , { num : 1 } ) , "D5" )
assert.eq( forward , getSorted( "x" , "num" , -1 , { num : 1 } ) , "D6" )
s.stop();

View File

@@ -25,4 +25,10 @@ assert( t.findOne( { i : i - 1 } ), "E" );
t.remove( { i : i - 1 } );
assert( db.getLastError().indexOf( "capped" ) >= 0, "F" );
assert( t.validate().valid, "G" );
assert( t.validate().valid, "G" );
/* there is a cursor open here, so this is a convenient place for a quick cursor test. */
db._adminCommand("closeAllDatabases");
//assert( db.serverStatus().cursors.totalOpen == 0, "cursors open and shouldn't be");

View File

@@ -15,7 +15,7 @@ while ( bigString.length < 10000 )
inserted = 0;
num = 0;
while ( inserted < ( 20 * 1024 * 1024 ) ){
db.foo.insert( { _id : num++ , s : bigString } );
db.foo.insert( { _id : num++ , s : bigString , x : Math.random() } );
inserted += bigString.length;
}
@@ -48,6 +48,7 @@ assert.soon( function(){
return d < 5;
} , "balance didn't happen" , 1000 * 60 * 3 , 5000 );
s.config.settings.update( { _id: "balancer" }, { $set : { stopped: true } } , true );
for ( i=0; i<s._rs.length; i++ ){
r = s._rs[i];
@@ -58,4 +59,14 @@ for ( i=0; i<s._rs.length; i++ ){
assert.eq( x.master.md5 , x.slaves[j].md5 , "hashes same for: " + r.url + " slave: " + j );
}
assert.eq( num , db.foo.find().count() , "C1" )
assert.eq( num , db.foo.find().itcount() , "C2" )
assert.eq( num , db.foo.find().sort( { _id : 1 } ).itcount() , "C3" )
assert.eq( num , db.foo.find().sort( { _id : -1 } ).itcount() , "C4" )
db.foo.ensureIndex( { x : 1 } )
assert.eq( num , db.foo.find().sort( { x : 1 } ).itcount() , "C5" )
assert.eq( num , db.foo.find().sort( { x : -1 } ).itcount() , "C6" )
s.stop()

View File

@@ -1,5 +1,5 @@
Name: mongo
Version: 1.5.8
Version: 1.6.2
Release: mongodb_1%{?dist}
Summary: mongo client shell and tools
License: AGPL 3.0
@@ -130,11 +130,6 @@ fi
%attr(0755,mongod,mongod) %dir /var/log/mongo
%attr(0640,mongod,mongod) %config(noreplace) %verify(not md5 size mtime) /var/log/mongo/mongod.log
%files devel
/usr/include/mongo
%{_libdir}/libmongoclient.a
#%{_libdir}/libmongotestfiles.a
%changelog
* Thu Jan 28 2010 Richard M Kreuter <richard@10gen.com>
- Minor fixes.

View File

@@ -265,7 +265,7 @@ namespace mongo {
}
// Save the new key boundaries in the configDB.
_manager->save();
_manager->save( false );
// Log all these changes in the configDB's log. We log a simple split differently than a multi-split.
if ( newChunks.size() == 1) {
@@ -584,7 +584,7 @@ namespace mongo {
_shards.insert(c->getShard());
save_inlock();
save_inlock( true );
log() << "no chunks for:" << ns << " so creating first: " << c->toString() << endl;
}
}
@@ -880,16 +880,18 @@ namespace mongo {
configServer.logChange( "dropCollection" , _ns , BSONObj() );
}
void ChunkManager::save(){
void ChunkManager::save( bool major ){
rwlock lk( _lock , true );
save_inlock();
save_inlock( major );
}
void ChunkManager::save_inlock(){
void ChunkManager::save_inlock( bool major ){
ShardChunkVersion a = getVersion_inlock();
assert( a > 0 || _chunkMap.size() <= 1 );
ShardChunkVersion nextChunkVersion = a.incMajor();
ShardChunkVersion nextChunkVersion = a;
nextChunkVersion.inc( major );
vector<ChunkPtr> toFix;
vector<ShardChunkVersion> newVersions;
@@ -907,7 +909,7 @@ namespace mongo {
_sequenceNumber = ++NextSequenceNumber;
ShardChunkVersion myVersion = nextChunkVersion;
++nextChunkVersion;
nextChunkVersion.incMinor();
toFix.push_back( c );
newVersions.push_back( myVersion );

View File

@@ -269,7 +269,7 @@ namespace mongo {
void getAllShards( set<Shard>& all );
void getShardsForRange(set<Shard>& shards, const BSONObj& min, const BSONObj& max); // [min, max)
void save();
void save( bool major );
string toString() const;
@@ -307,7 +307,7 @@ namespace mongo {
void _reload_inlock();
void _load();
void save_inlock();
void save_inlock( bool major );
ShardChunkVersion getVersion_inlock() const;
void ensureIndex_inlock();

View File

@@ -616,30 +616,44 @@ namespace mongo {
help << "add a new shard to the system";
}
bool run(const string& , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool){
HostAndPort shardAddr( cmdObj.firstElement().valuestrsafe() );
if ( shardAddr.isLocalHost() != grid.allowLocalHost() ){
errmsg = "can't use localhost as a shard since all shards need to communicate. "
"either use all shards and configdbs in localhost or all in actual IPs " ;
log() << "addshard request " << cmdObj << " failed: attempt to mix localhosts and IPs" << endl;
errmsg.clear();
// get replica set component hosts
ConnectionString servers = ConnectionString::parse( cmdObj.firstElement().valuestrsafe() , errmsg );
if ( ! errmsg.empty() ){
log() << "addshard request " << cmdObj << " failed:" << errmsg << endl;
return false;
}
// HostAndPort defaults to a different port; adjust if needed.
if ( shardAddr.port() == CmdLine::DefaultDBPort ){
shardAddr.setPort( CmdLine::ShardServerPort );
// using localhost in server names implies every other process must use locahost addresses too
vector<HostAndPort> serverAddrs = servers.getServers();
for ( size_t i = 0 ; i < serverAddrs.size() ; i++ ){
if ( serverAddrs[i].isLocalHost() != grid.allowLocalHost() ){
errmsg = "can't use localhost as a shard since all shards need to communicate. "
"either use all shards and configdbs in localhost or all in actual IPs " ;
log() << "addshard request " << cmdObj << " failed: attempt to mix localhosts and IPs" << endl;
return false;
}
// it's fine if mongods of a set all use default port
if ( ! serverAddrs[i].hasPort() ){
serverAddrs[i].setPort( CmdLine::ShardServerPort );
}
}
// name is optional; addShard will provide one if needed
string name = "";
if ( cmdObj["name"].type() == String ) {
name = cmdObj["name"].valuestrsafe();
}
// maxSize is the space usage cap in a shard in MBs
long long maxSize = 0;
if ( cmdObj[ ShardFields::maxSize.name() ].isNumber() ){
maxSize = cmdObj[ ShardFields::maxSize.name() ].numberLong();
}
if ( ! grid.addShard( &name , shardAddr.toString() , maxSize , errmsg ) ){
if ( ! grid.addShard( &name , servers , maxSize , errmsg ) ){
log() << "addshard request " << cmdObj << " failed: " << errmsg << endl;
return false;
}

View File

@@ -745,6 +745,7 @@ namespace mongo {
fn == "reduce" ||
fn == "query" ||
fn == "sort" ||
fn == "scope" ||
fn == "verbose" ){
b.append( e );
}

View File

@@ -653,7 +653,13 @@ namespace mongo {
BSONObj msg = BSON( "_id" << id.str() << "server" << getHostNameCached() << "time" << DATENOW <<
"what" << what << "ns" << ns << "details" << detail );
log() << "config change: " << msg << endl;
conn->insert( "config.changelog" , msg );
try {
conn->insert( "config.changelog" , msg );
}
catch ( std::exception& e ){
log() << "not logging config change: " << e.what() << endl;
}
conn.done();
}

View File

@@ -528,7 +528,8 @@ namespace mongo {
log(0) << "_recvChunkStatus : " << res << endl;
if ( ! ok ){
if ( ! ok || res["state"].String() == "fail" ){
log( LL_ERROR ) << "_recvChunkStatus error : " << res << endl;
errmsg = "_recvChunkStatus error";
result.append( "cause" ,res );
return false;
@@ -544,7 +545,7 @@ namespace mongo {
// 5.a
migrateFromStatus._inCriticalSection = true;
ShardChunkVersion myVersion = maxVersion;
++myVersion;
myVersion.incMajor();
{
dblock lk;
@@ -587,7 +588,8 @@ namespace mongo {
if ( ! x.isEmpty() ){
BSONObjBuilder temp2;
++myVersion;
myVersion.incMinor();
temp2.appendTimestamp( "lastmod" , myVersion );
shardingState.setVersion( ns , myVersion );
@@ -685,10 +687,12 @@ namespace mongo {
catch ( std::exception& e ){
state = FAIL;
errmsg = e.what();
log( LL_ERROR ) << "migrate failed: " << e.what() << endl;
}
catch ( ... ){
state = FAIL;
errmsg = "UNKNOWN ERROR";
log( LL_ERROR ) << "migrate failed with unknown exception" << endl;
}
active = false;
}
@@ -739,7 +743,7 @@ namespace mongo {
auto_ptr<DBClientCursor> cursor = conn->query( ns , Query().minKey( min ).maxKey( max ) , /* QueryOption_Exhaust */ 0 );
assert( cursor.get() );
while ( cursor->more() ){
BSONObj o = cursor->next();
BSONObj o = cursor->next().getOwned();
{
writelock lk( ns );
Helpers::upsert( ns , o );
@@ -756,7 +760,11 @@ namespace mongo {
BSONObj res;
if ( ! conn->runCommand( "admin" , BSON( "_transferMods" << 1 ) , res ) ){
state = FAIL;
errmsg = "_transferMods failed: ";
errmsg += res.toString();
log( LL_ERROR ) << "_transferMods failed: " << res << endl;
conn.done();
return;
}
if ( res["size"].number() == 0 )
break;
@@ -775,6 +783,7 @@ namespace mongo {
log() << "_transferMods failed in STEADY state: " << res << endl;
errmsg = res.toString();
state = FAIL;
conn.done();
return;
}
@@ -801,9 +810,10 @@ namespace mongo {
b.append( "from" , from );
b.append( "min" , min );
b.append( "max" , max );
b.append( "state" , stateString() );
if ( state == FAIL )
b.append( "errmsg" , errmsg );
{
BSONObjBuilder bb( b.subobjStart( "counts" ) );
bb.append( "cloned" , numCloned );

View File

@@ -603,7 +603,8 @@ namespace mongo {
BSONObj x = loc.obj().extractFields(_key);
MyMap::const_iterator a = _map.upper_bound( x );
a--;
if ( a != _map.begin() )
a--;
bool good = x.woCompare( a->second.first ) >= 0 && x.woCompare( a->second.second ) < 0;
#if 0

View File

@@ -52,7 +52,7 @@ namespace mongo {
class WriteBackCommand : public Command {
public:
virtual LockType locktype() const { return NONE; }
virtual bool slaveOk() const { return false; }
virtual bool slaveOk() const { return true; }
virtual bool adminOnly() const { return true; }
WriteBackCommand() : Command( "writebacklisten" ){}

View File

@@ -115,41 +115,107 @@ namespace mongo {
_allowLocalShard = allow;
}
bool Grid::addShard( string* name , const string& host , long long maxSize , string& errMsg ){
// name is optional
bool Grid::addShard( string* name , const ConnectionString& servers , long long maxSize , string& errMsg ){
// name can be NULL, so privide a dummy one here to avoid testing it elsewhere
string nameInternal;
if ( ! name ) {
name = &nameInternal;
}
// Check whether the host exists and is operative. In order to be accepted as a new shard, that
// mongod must not have any database name that exists already in any other shards. If that
// test passes, the new shard's databases are going to be entered as non-sharded db's whose
// primary is the newly added shard.
// Check whether the host (or set) exists and run several sanity checks on this request.
// There are two set of sanity checks: making sure adding this particular shard is consistent
// with the replica set state (if it exists) and making sure this shards databases can be
// brought into the grid without conflict.
vector<string> dbNames;
try {
ScopedDbConnection newShardConn( host );
ScopedDbConnection newShardConn( servers );
newShardConn->getLastError();
if ( newShardConn->type() == ConnectionString::SYNC ){
newShardConn.done();
errMsg = "can't use sync cluster as a shard. for replica set, have to use <name>/<server1>,<server2>,...";
errMsg = "can't use sync cluster as a shard. for replica set, have to use <setname>/<server1>,<server2>,...";
return false;
}
// get the shard's local db's listing
BSONObj res;
bool ok = newShardConn->runCommand( "admin" , BSON( "listDatabases" << 1 ) , res );
BSONObj resIsMaster;
bool ok = newShardConn->runCommand( "admin" , BSON( "isMaster" << 1 ) , resIsMaster );
if ( !ok ){
ostringstream ss;
ss << "failed listing " << host << " databases:" << res;
ss << "failed running isMaster: " << resIsMaster;
errMsg = ss.str();
newShardConn.done();
return false;
}
BSONObjIterator i( res["databases"].Obj() );
// if the shard has only one host, make sure it is not part of a replica set
string setName = resIsMaster["setName"].str();
string commandSetName = servers.getSetName();
if ( commandSetName.empty() && ! setName.empty() ){
ostringstream ss;
ss << "host is part of set: " << setName << " use replica set url format <setname>/<server1>,<server2>,....";
errMsg = ss.str();
newShardConn.done();
return false;
}
// if the shard is part of replica set, make sure it is the right one
if ( ! commandSetName.empty() && ( commandSetName != setName ) ){
ostringstream ss;
ss << "host is part of a different set: " << setName;
errMsg = ss.str();
newShardConn.done();
return false;
}
// if the shard is part of a replica set, make sure all the hosts mentioned in 'servers' are part of
// the set. It is fine if not all members of the set are present in 'servers'.
bool foundAll = true;
string offendingHost;
if ( ! commandSetName.empty() ){
set<string> hostSet;
BSONObjIterator iter( resIsMaster["hosts"].Obj() );
while ( iter.more() ){
hostSet.insert( iter.next().String() ); // host:port
}
vector<HostAndPort> hosts = servers.getServers();
for ( size_t i = 0 ; i < hosts.size() ; i++ ){
string host = hosts[i].toString(); // host:port
if ( hostSet.find( host ) == hostSet.end() ){
offendingHost = host;
foundAll = false;
break;
}
}
}
if ( ! foundAll ){
ostringstream ss;
ss << "host " << offendingHost << " does not belong to replica set " << setName;;
errMsg = ss.str();
newShardConn.done();
return false;
}
// shard name defaults to the name of the replica set
if ( name->empty() && ! setName.empty() )
*name = setName;
// In order to be accepted as a new shard, that mongod must not have any database name that exists already
// in any other shards. If that test passes, the new shard's databases are going to be entered as
// non-sharded db's whose primary is the newly added shard.
BSONObj resListDB;
ok = newShardConn->runCommand( "admin" , BSON( "listDatabases" << 1 ) , resListDB );
if ( !ok ){
ostringstream ss;
ss << "failed listing " << servers.toString() << "'s databases:" << resListDB;
errMsg = ss.str();
newShardConn.done();
return false;
}
BSONObjIterator i( resListDB["databases"].Obj() );
while ( i.more() ){
BSONObj dbEntry = i.next().Obj();
const string& dbName = dbEntry["name"].String();
@@ -176,7 +242,7 @@ namespace mongo {
DBConfigPtr config = getDBConfig( *it , false );
if ( config.get() != NULL ){
ostringstream ss;
ss << "trying to add shard " << host << " because local database " << *it;
ss << "trying to add shard " << servers.toString() << " because local database " << *it;
ss << " exists in another " << config->getPrimary().toString();
errMsg = ss.str();
return false;
@@ -192,7 +258,7 @@ namespace mongo {
// build the ConfigDB shard document
BSONObjBuilder b;
b.append( "_id" , *name );
b.append( "host" , host );
b.append( "host" , servers.toString() );
if ( maxSize > 0 ){
b.append( ShardFields::maxSize.name() , maxSize );
}
@@ -201,8 +267,8 @@ namespace mongo {
{
ScopedDbConnection conn( configServer.getPrimary() );
// check whether this host:port is not an already a known shard
BSONObj old = conn->findOne( ShardNS::shard , BSON( "host" << host ) );
// check whether the set of hosts (or single host) is not an already a known shard
BSONObj old = conn->findOne( ShardNS::shard , BSON( "host" << servers.toString() ) );
if ( ! old.isEmpty() ){
errMsg = "host already used";
conn.done();
@@ -228,7 +294,7 @@ namespace mongo {
for ( vector<string>::const_iterator it = dbNames.begin(); it != dbNames.end(); ++it ){
DBConfigPtr config = getDBConfig( *it , true , *name );
if ( ! config ){
log() << "adding shard " << host << " even though could not add database " << *it << endl;
log() << "adding shard " << servers << " even though could not add database " << *it << endl;
}
}

View File

@@ -57,18 +57,17 @@ namespace mongo {
/**
*
* addShard will create a new shard in the grid. It expects a mongod process to be runing
* on the provided address.
* TODO - add the mongod's databases to the grid
* on the provided address. Adding a shard that is a replica set is supported.
*
* @param name is an optional string with the name of the shard. if ommited, grid will
* generate one and update the parameter.
* @param host is the complete address of the machine where the shard will be
* @param servers is the connection string of the shard being added
* @param maxSize is the optional space quota in bytes. Zeros means there's no limitation to
* space usage
* @param errMsg is the error description in case the operation failed.
* @return true if shard was successfully added.
*/
bool addShard( string* name , const string& host , long long maxSize , string& errMsg );
bool addShard( string* name , const ConnectionString& servers , long long maxSize , string& errMsg );
/**
* @return true if the config database knows about a host 'name'

View File

@@ -123,7 +123,8 @@ namespace mongo {
log() << staleConfig.what() << " attempt: " << attempt << endl;
uassert( 10195 , "too many attempts to update config, failing" , attempt < 5 );
ShardConnection::checkMyConnectionVersions( getns() );
sleepsecs( attempt );
if (!staleConfig.justConnection() )
sleepsecs( attempt );
reset( ! staleConfig.justConnection() );
_d.markReset();
process( attempt + 1 );

View File

@@ -63,10 +63,7 @@ namespace mongo {
class ShardingConnectionHook : public DBConnectionHook {
public:
virtual void onCreate( DBClientBase * conn ){
if ( conn->type() != ConnectionString::SYNC )
conn->simpleCommand( "admin" , 0 , "switchtoclienterrors" );
}
virtual void onHandedOut( DBClientBase * conn ){
ClientInfo::get()->addShard( conn->getServerAddress() );
}
@@ -92,10 +89,12 @@ namespace mongo {
r.process();
}
catch ( DBException& e ){
log() << "DBException in process: " << e.what() << endl;
le->raiseError( e.getCode() , e.what() );
m.header()->id = r.id();
log() << "UserException: " << e.what() << endl;
if ( r.expectResponse() ){
BSONObj err = BSON( "$err" << e.what() << "code" << e.getCode() );
replyToQuery( ResultFlag_ErrSet, p , m , err );

View File

@@ -76,6 +76,12 @@ namespace mongo {
Shard s( name , host , maxSize , isDraining );
_lookup[name] = s;
_lookup[host] = s;
// add rs name to lookup (if it exists)
size_t pos;
if ((pos = host.find('/', 0)) != string::npos) {
_lookup[host.substr(0, pos)] = s;
}
}
}
@@ -90,6 +96,13 @@ namespace mongo {
{
scoped_lock lk( _mutex );
map<string,Shard>::iterator i = _lookup.find( ident );
// if normal find didn't find anything, try to find by rs name
size_t pos;
if ( i == _lookup.end() && (pos = ident.find('/', 0)) != string::npos) {
i = _lookup.find( ident.substr(0, pos) );
}
if ( i != _lookup.end() )
return i->second;
}

View File

@@ -26,6 +26,7 @@ namespace mongo {
/**
* holds all the actual db connections for a client to various servers
* 1 pre thread, so don't have to worry about thread safety
*/
class ClientConnections : boost::noncopyable {
public:
@@ -70,7 +71,8 @@ namespace mongo {
_hosts.clear();
}
DBClientBase * get( const string& addr ){
DBClientBase * get( const string& addr , const string& ns ){
_check( ns );
scoped_lock lk( _mutex );
Status* &s = _hosts[addr];
if ( ! s )
@@ -152,9 +154,16 @@ namespace mongo {
}
}
void _check( const string& ns ){
if ( ns.size() == 0 || _seenNS.count( ns ) )
return;
_seenNS.insert( ns );
checkVersions( ns );
}
map<string,Status*> _hosts;
mongo::mutex _mutex;
set<string> _seenNS;
// -----
static thread_specific_ptr<ClientConnections> _perThread;
@@ -188,7 +197,7 @@ namespace mongo {
void ShardConnection::_init(){
assert( _addr.size() );
_conn = ClientConnections::get()->get( _addr );
_conn = ClientConnections::get()->get( _addr , _ns );
_finishedInit = false;
}

View File

@@ -58,11 +58,19 @@ namespace mongo {
}
}
ShardChunkVersion incMajor() const {
return ShardChunkVersion( _major + 1 , 0 );
void inc( bool major ){
if ( major )
incMajor();
else
incMinor();
}
void operator++(){
void incMajor() {
_major++;
_minor = 0;
}
void incMinor() {
_minor++;
}
@@ -79,8 +87,9 @@ namespace mongo {
ss << _major << "|" << _minor;
return ss.str();
}
operator unsigned long long() const { return _combined; }
ShardChunkVersion& operator=( const BSONElement& elem ){
switch ( elem.type() ){
case Timestamp:

View File

@@ -156,7 +156,7 @@ namespace mongo {
JSBool mongo_external_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
Convertor c( cx );
uassert( 10238 , "0 or 1 args to Mongo" , argc <= 1 );
smuassert( cx , "0 or 1 args to Mongo" , argc <= 1 );
string host = "127.0.0.1";
if ( argc > 0 )
@@ -207,9 +207,9 @@ namespace mongo {
};
JSBool mongo_find(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
uassert( 10240 , "mongo_find neesd 6 args" , argc == 6 );
smuassert( cx , "mongo_find needs 6 args" , argc == 6 );
shared_ptr< DBClientWithCommands > * connHolder = (shared_ptr< DBClientWithCommands >*)JS_GetPrivate( cx , obj );
uassert( 10241 , "no connection!" , connHolder && connHolder->get() );
smuassert( cx , "no connection!" , connHolder && connHolder->get() );
DBClientWithCommands *conn = connHolder->get();
Convertor c( cx );

View File

@@ -243,6 +243,20 @@ DBQuery.prototype.explain = function (verbose) {
if (!verbose) {
delete e.allPlans;
delete e.oldPlan;
if (e.shards){
for (var key in e.shards){
var s = e.shards[key];
if(s.length === undefined){
delete s.allPlans;
delete s.oldPlan;
} else {
for (var i=0; i < s.length; i++){
delete s[i].allPlans;
delete s[i].oldPlan;
}
}
}
}
}
return e;
}

View File

@@ -62,6 +62,13 @@ startMongodTest = function (port, dirname, restart, extraOptions ) {
f = startMongodNoReset;
if (!dirname)
dirname = "" + port; // e.g., data/db/27000
var useHostname = false;
if (extraOptions) {
useHostname = extraOptions.useHostname;
delete extraOptions.useHostname;
}
var options =
{
@@ -78,7 +85,7 @@ startMongodTest = function (port, dirname, restart, extraOptions ) {
var conn = f.apply(null, [ options ] );
conn.name = "localhost:" + port;
conn.name = (useHostname ? getHostName() : "localhost") + ":" + port;
return conn;
}
@@ -145,6 +152,10 @@ myPort = function() {
return 27017;
}
/**
* otherParams can be:
* * useHostname to use the hostname (instead of localhost)
*/
ShardingTest = function( testName , numShards , verboseLevel , numMongos , otherParams ){
this._testName = testName;
@@ -155,7 +166,10 @@ ShardingTest = function( testName , numShards , verboseLevel , numMongos , other
if ( otherParams.sync && numShards < 3 )
throw "if you want sync, you need at least 3 servers";
var localhost = "localhost";
var localhost = otherParams.useHostname ? getHostName() : "localhost";
this._alldbpaths = []
if ( otherParams.rs ){
localhost = getHostName();
@@ -165,6 +179,11 @@ ShardingTest = function( testName , numShards , verboseLevel , numMongos , other
var rs = new ReplSetTest( { name : testName + "-rs" + i , nodes : 3 , startPort : 31100 + ( i * 100 ) } );
this._rs[i] = { test : rs , nodes : rs.startSet( { oplogSize:40 } ) , url : rs.getURL() };
rs.initiate();
}
for ( var i=0; i<numShards; i++){
var rs = this._rs[i].test;
rs.getMaster().getDB( "admin" ).foo.save( { x : 1 } )
rs.awaitReplication();
this._connections.push( new Mongo( rs.getURL() ) );
@@ -173,6 +192,7 @@ ShardingTest = function( testName , numShards , verboseLevel , numMongos , other
this._configServers = []
for ( var i=0; i<3; i++ ){
var conn = startMongodTest( 30000 + i , testName + "-config" + i );
this._alldbpaths.push( testName + "-config" + i )
this._configServers.push( conn );
}
@@ -182,17 +202,18 @@ ShardingTest = function( testName , numShards , verboseLevel , numMongos , other
}
else {
for ( var i=0; i<numShards; i++){
var conn = startMongodTest( 30000 + i , testName + i );
var conn = startMongodTest( 30000 + i , testName + i, 0, {useHostname : otherParams.useHostname} );
this._alldbpaths.push( testName +i )
this._connections.push( conn );
}
if ( otherParams.sync ){
this._configDB = "localhost:30000,localhost:30001,localhost:30002";
this._configDB = localhost+":30000,"+localhost+":30001,"+localhost+":30002";
this._configConnection = new Mongo( this._configDB );
this._configConnection.getDB( "config" ).settings.insert( { _id : "chunksize" , value : otherParams.chunksize || 50 } );
}
else {
this._configDB = "localhost:30000";
this._configDB = localhost + ":30000";
this._connections[0].getDB( "config" ).settings.insert( { _id : "chunksize" , value : otherParams.chunksize || 50 } );
}
}
@@ -201,6 +222,7 @@ ShardingTest = function( testName , numShards , verboseLevel , numMongos , other
var startMongosPort = 31000;
for ( var i=0; i<(numMongos||1); i++ ){
var myPort = startMongosPort - i;
print("config: "+this._configDB);
var conn = startMongos( { port : startMongosPort - i , v : verboseLevel || 0 , configdb : this._configDB } );
conn.name = localhost + ":" + myPort;
this._mongos.push( conn );
@@ -316,6 +338,11 @@ ShardingTest.prototype.stop = function(){
this._rs[i].test.stopSet( 15 );
}
}
if ( this._alldbpaths ){
for( i=0; i<this._alldbpaths.length; i++ ){
resetDbpath( "/data/db/" + this._alldbpaths[i] );
}
}
print('*** ' + this._testName + " completed successfully ***");
}
@@ -966,6 +993,8 @@ ReplSetTest = function( opts ){
this.name = opts.name || "testReplSet";
this.host = opts.host || getHostName();
this.numNodes = opts.nodes || 0;
this.useSeedList = opts.useSeedList || false;
this.bridged = opts.bridged || false;
this.ports = [];
@@ -1024,6 +1053,10 @@ ReplSetTest.prototype.getPort = function( n ){
ReplSetTest.prototype.getPath = function( n ){
var p = "/data/db/" + this.name + "-";
p += n.toString();
if ( ! this._alldbpaths )
this._alldbpaths = [ p ];
else
this._alldbpaths.push( p );
return p;
}
@@ -1326,9 +1359,15 @@ ReplSetTest.prototype.stop = function( n , signal ){
return stopMongod( port , signal || 15 );
}
ReplSetTest.prototype.stopSet = function( signal ) {
ReplSetTest.prototype.stopSet = function( signal , forRestart ) {
for(i=0; i < this.ports.length; i++) {
this.stop( i, signal );
}
if ( ! forRestart && this._alldbpaths ){
for( i=0; i<this._alldbpaths.length; i++ ){
resetDbpath( this._alldbpaths[i] );
}
}
print('*** Shut down repl set - test worked ****' )
}

View File

@@ -65,8 +65,7 @@ namespace mongo {
}
bool BackgroundJob::wait(int msMax, unsigned maxsleep) {
assert( state != NotStarted );
unsigned ms = 0;
unsigned ms = 1;
Date_t start = jsTime();
while ( state != Done ) {
sleepmillis(ms);
@@ -84,7 +83,7 @@ namespace mongo {
/* wait for several jobs to finish. */
void BackgroundJob::wait(list<BackgroundJob*>& L, unsigned maxsleep) {
unsigned ms = 0;
unsigned ms = 1;
{
x:
sleepmillis(ms);

View File

@@ -27,13 +27,13 @@ namespace mongo {
typedef boost::function<void()> lam;
/** typical usage is: task::fork( serverPtr ); */
/** typical usage is: task::fork( new Server("threadname") ); */
class Server : public Task {
public:
/** send a message to the port */
void send(lam);
Server(string name) : _name(name) { }
Server(string name) : _name(name), rq(false) { }
virtual ~Server() { }
/** send message but block until function completes */
@@ -42,9 +42,8 @@ namespace mongo {
void requeue() { rq = true; }
protected:
/* this needn't be abstract; i left it that way for now so i remember
to call Client::initThread() when using in mongo... */
virtual void starting() = 0;
/* REMINDER : for use in mongod, you will want to have this call Client::initThread(). */
virtual void starting() { }
private:
virtual bool initClient() { return true; }

View File

@@ -117,7 +117,6 @@ namespace mongo {
void Server::doWork() {
starting();
rq = false;
while( 1 ) {
lam f;
try {
@@ -134,7 +133,10 @@ namespace mongo {
f();
if( rq ) {
rq = false;
send(f);
{
boost::mutex::scoped_lock lk(m);
d.push_back(f);
}
}
} catch(std::exception& e) {
log() << "Server::doWork() exception " << e.what() << endl;
@@ -143,6 +145,27 @@ namespace mongo {
}
}
}
static Server *s;
static void abc(int i) {
cout << "Hello " << i << endl;
s->requeue();
}
class TaskUnitTest : public mongo::UnitTest {
public:
virtual void run() {
lam f = boost::bind(abc, 3);
//f();
s = new Server("unittest");
fork(s);
s->send(f);
sleepsecs(30);
cout <<" done" << endl;
}
}; // not running. taskunittest;
}
}

View File

@@ -74,6 +74,7 @@ namespace mongo {
string host() const { return _host; }
int port() const { return _port >= 0 ? _port : CmdLine::DefaultDBPort; }
bool hasPort() const { return _port >= 0; }
void setPort( int port ) { _port = port; }
private:

View File

@@ -158,15 +158,7 @@ namespace mongo {
static vector<Tee*> * globalTees;
public:
static void logLockless( const StringData& s ){
if ( doneSetup == 1717 ){
fwrite( s.data() , s.size() , 1 , logfile );
fflush( logfile );
}
else {
cout << s.data() << endl;
}
}
inline static void logLockless( const StringData& s );
static void setLogFile(FILE* f){
scoped_lock lk(mutex);
@@ -177,52 +169,9 @@ namespace mongo {
return 1717;
}
void flush(Tee *t = 0) {
// this ensures things are sane
if ( doneSetup == 1717 ) {
string msg = ss.str();
string threadName = getThreadName();
const char * type = logLevelToString(logLevel);
int spaceNeeded = msg.size() + 64 + threadName.size();
int bufSize = 128;
while ( bufSize < spaceNeeded )
bufSize += 128;
BufBuilder b(bufSize);
time_t_to_String( time(0) , b.grow(20) );
if (!threadName.empty()){
b.appendChar( '[' );
b.appendStr( threadName , false );
b.appendChar( ']' );
b.appendChar( ' ' );
}
if ( type[0] ){
b.appendStr( type , false );
b.appendStr( ": " , false );
}
b.appendStr( msg );
string out( b.buf() , b.len() - 1);
scoped_lock lk(mutex);
if( t ) t->write(logLevel,out);
if ( globalTees ){
for ( unsigned i=0; i<globalTees->size(); i++ )
(*globalTees)[i]->write(logLevel,out);
}
#ifndef _WIN32
//syslog( LOG_INFO , "%s" , cc );
#endif
fwrite(out.data(), out.size(), 1, logfile);
fflush(logfile);
}
_init();
}
inline void flush(Tee *t = 0);
Nullstream& setLogLevel(LogLevel l){
inline Nullstream& setLogLevel(LogLevel l){
logLevel = l;
return *this;
}
@@ -416,6 +365,69 @@ namespace mongo {
/** output the error # and error message with prefix.
handy for use as parm in uassert/massert.
*/
string errnoWithPrefix( const char * prefix = 0 );
string errnoWithPrefix( const char * prefix );
void Logstream::logLockless( const StringData& s ){
if ( doneSetup == 1717 ){
if(fwrite(s.data(), s.size(), 1, logfile)){
fflush(logfile);
}else{
int x = errno;
cout << "Failed to write to logfile: " << errnoWithDescription(x) << ": " << out << endl;
}
}
else {
cout << s.data() << endl;
}
}
void Logstream::flush(Tee *t) {
// this ensures things are sane
if ( doneSetup == 1717 ) {
string msg = ss.str();
string threadName = getThreadName();
const char * type = logLevelToString(logLevel);
int spaceNeeded = msg.size() + 64 + threadName.size();
int bufSize = 128;
while ( bufSize < spaceNeeded )
bufSize += 128;
BufBuilder b(bufSize);
time_t_to_String( time(0) , b.grow(20) );
if (!threadName.empty()){
b.appendChar( '[' );
b.appendStr( threadName , false );
b.appendChar( ']' );
b.appendChar( ' ' );
}
if ( type[0] ){
b.appendStr( type , false );
b.appendStr( ": " , false );
}
b.appendStr( msg );
string out( b.buf() , b.len() - 1);
scoped_lock lk(mutex);
if( t ) t->write(logLevel,out);
if ( globalTees ){
for ( unsigned i=0; i<globalTees->size(); i++ )
(*globalTees)[i]->write(logLevel,out);
}
#ifndef _WIN32
//syslog( LOG_INFO , "%s" , cc );
#endif
if(fwrite(out.data(), out.size(), 1, logfile)){
fflush(logfile);
}else{
int x = errno;
cout << "Failed to write to logfile: " << errnoWithDescription(x) << ": " << out << endl;
}
}
_init();
}
} // namespace mongo

View File

@@ -168,7 +168,11 @@ namespace mongo {
const int ret = select(maxfd+1, fds, NULL, NULL, &maxSelectTime);
if (ret == 0){
#if defined(__linux__)
_elapsedTime += ( 10000 - maxSelectTime.tv_usec ) / 1000;
#else
_elapsedTime += 10;
#endif
continue;
}
_elapsedTime += ret; // assume 1ms to grab connection. very rough

View File

@@ -14,7 +14,7 @@ namespace mongo {
// mongo processes version support
//
const char versionString[] = "1.5.9-pre-";
const char versionString[] = "1.6.2";
string mongodVersion() {
stringstream ss;