summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2010-11-03 18:23:01 -0400
committerEliot Horowitz <eliot@10gen.com>2010-11-03 18:57:19 -0400
commit2dce387d96b7edf2e920bf235fa5f6ec5422c063 (patch)
tree6b4a108648e586130f1e91f5aaeaf430a7dac4b7 /tools
parent891198796fd078b2e0943d2e7e7d7d9ebb95b762 (diff)
downloadmongo-2dce387d96b7edf2e920bf235fa5f6ec5422c063.tar.gz
mongostat cleaning and towards discover for sharding SERVER-2038
Diffstat (limited to 'tools')
-rw-r--r--tools/stat.cpp160
1 files changed, 127 insertions, 33 deletions
diff --git a/tools/stat.cpp b/tools/stat.cpp
index af49ff71cf2..780aef19798 100644
--- a/tools/stat.cpp
+++ b/tools/stat.cpp
@@ -244,6 +244,11 @@ namespace mongo {
_append( result , "repl" , 4 , ss.str() );
}
+ else if ( b["shardCursorType"].type() == Object ){
+ // is a mongos
+ // TODO: should have a better check
+ _append( result , "repl" , 4 , "RTR" );
+ }
{
struct tm t;
@@ -367,12 +372,14 @@ namespace mongo {
scoped_ptr<boost::thread> thr;
mongo::mutex lock;
-
+
BSONObj prev;
BSONObj now;
time_t lastUpdate;
+ vector<BSONObj> shards;
string error;
+ bool mongos;
};
static void serverThread( shared_ptr<ServerState> state ){
@@ -382,8 +389,10 @@ namespace mongo {
string errmsg;
if ( ! conn.connect( state->host , errmsg ) )
state->error = errmsg;
+
+ long long cycleNumber = 0;
- while ( 1 ){
+ while ( ++cycleNumber ){
try {
BSONObj out;
if ( conn.simpleCommand( "admin" , &out , "serverStatus" ) ){
@@ -399,6 +408,18 @@ namespace mongo {
state->lastUpdate = time(0);
}
+ if ( out["shardCursorType"].type() == Object ){
+ state->mongos = true;
+ if ( cycleNumber % 10 == 1 ){
+ auto_ptr<DBClientCursor> c = conn.query( "config.shards" , BSONObj() );
+ vector<BSONObj> shards;
+ while ( c->more() ){
+ shards.push_back( c->next().getOwned() );
+ }
+ scoped_lock lk( state->lock );
+ state->shards = shards;
+ }
+ }
}
catch ( std::exception& e ){
scoped_lock lk( state->lock );
@@ -430,7 +451,10 @@ namespace mongo {
state->thr.reset( new boost::thread( boost::bind( serverThread , state ) ) );
return true;
}
-
+
+ /**
+ * @param hosts [ "a.foo.com" , "b.foo.com" ]
+ */
bool _addAll( StateMap& threads , const BSONObj& hosts ){
BSONObjIterator i( hosts );
bool added = false;
@@ -441,10 +465,47 @@ namespace mongo {
return added;
}
+ bool _discover( StateMap& threads , const string& host , const shared_ptr<ServerState>& ss ){
+
+ BSONObj info = ss->now;
+
+ bool found = false;
+
+ if ( info["repl"].isABSONObj() ){
+ BSONObj x = info["repl"].Obj();
+ if ( x["hosts"].isABSONObj() )
+ if ( _addAll( threads , x["hosts"].Obj() ) )
+ found = true;
+ if ( x["passives"].isABSONObj() )
+ if ( _addAll( threads , x["passives"].Obj() ) )
+ found = true;
+ }
+
+ if ( ss->mongos ){
+ for ( unsigned i=0; i<ss->shards.size(); i++ ){
+ BSONObj x = ss->shards[i];
+
+ string errmsg;
+ ConnectionString cs = ConnectionString::parse( x["host"].String() , errmsg );
+ if ( errmsg.size() ){
+ cerr << errmsg << endl;
+ continue;
+ }
+
+ vector<HostAndPort> v = cs.getServers();
+ for ( unsigned i=0; i<v.size(); i++ ){
+ if ( _add( threads , v[i].toString() ) )
+ found = true;
+ }
+ }
+ }
+
+ return found;
+ }
+
int runMany(){
StateMap threads;
- unsigned longestHost = 0;
{
string orig = getParam( "host" );
@@ -453,58 +514,72 @@ namespace mongo {
StringSplitter ss( orig.c_str() , "," );
while ( ss.more() ){
string host = ss.next();
- if ( host.size() > longestHost )
- longestHost = host.size();
-
_add( threads , host );
}
}
sleepsecs(1);
-
+
int row = 0;
bool discover = hasParam( "discover" );
while ( 1 ){
sleepsecs( _sleep );
- cout << endl;
- int x = 0;
+ // collect data
+ vector<Row> rows;
for ( map<string,shared_ptr<ServerState> >::iterator i=threads.begin(); i!=threads.end(); ++i ){
scoped_lock lk( i->second->lock );
-
+
if ( i->second->error.size() ){
- cout << setw( longestHost ) << i->first << "\t";
- cout << i->second->error << endl;
+ rows.push_back( Row( i->first , i->second->error ) );
}
else if ( i->second->prev.isEmpty() || i->second->now.isEmpty() ){
- cout << setw( longestHost ) << i->first << "\t";
- cout << "no data" << endl;
+ rows.push_back( Row( i->first ) );
}
else {
BSONObj out = doRow( i->second->prev , i->second->now );
-
- if ( x++ == 0 && row++ % 5 == 0 ){
- cout << setw( longestHost ) << "" << "\t";
- printHeaders( out );
- }
-
- cout << setw( longestHost ) << i->first << "\t";
- printData( out );
+ rows.push_back( Row( i->first , out ) );
}
-
+
if ( discover && ! i->second->now.isEmpty() ){
- if ( i->second->now["repl"].isABSONObj() ){
- BSONObj x = i->second->now["repl"].Obj();
- if ( x["hosts"].isABSONObj() )
- if ( _addAll( threads , x["hosts"].Obj() ) )
- break;
- if ( x["passives"].isABSONObj() )
- if ( _addAll( threads , x["passives"].Obj() ) )
- break;
- }
+ if ( _discover( threads , i->first , i->second ) )
+ break;
}
}
+
+ // compute some stats
+ unsigned longestHost = 0;
+ BSONObj biggest;
+ for ( unsigned i=0; i<rows.size(); i++ ){
+ if ( rows[i].host.size() > longestHost )
+ longestHost = rows[i].host.size();
+ if ( rows[i].data.nFields() > biggest.nFields() )
+ biggest = rows[i].data;
+ }
+
+
+ // display data
+
+ cout << endl;
+
+ // header
+ if ( row++ % 5 == 0 && ! biggest.isEmpty() ){
+ cout << setw( longestHost ) << "" << "\t";
+ printHeaders( biggest );
+ }
+
+ // rows
+ for ( unsigned i=0; i<rows.size(); i++ ){
+ cout << setw( longestHost ) << rows[i].host << "\t";
+ if ( rows[i].err.size() )
+ cout << rows[i].err << endl;
+ else if ( rows[i].data.isEmpty() )
+ cout << "no data" << endl;
+ else
+ printData( rows[i].data );
+ }
+
}
return 0;
@@ -514,6 +589,25 @@ namespace mongo {
bool _http;
bool _many;
bool _all;
+
+ struct Row {
+ Row( string h , string e ){
+ host = h;
+ err = e;
+ }
+
+ Row( string h ){
+ host = h;
+ }
+
+ Row( string h , BSONObj d ){
+ host = h;
+ data = d;
+ }
+ string host;
+ string err;
+ BSONObj data;
+ };
};
}