summaryrefslogtreecommitdiff
path: root/db/dbcommands.cpp
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
committerAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
commit5d342a758c6095b4d30aba0750b54f13b8916f51 (patch)
tree762e9aa84781f5e3b96db2c02d356c29cf0217c0 /db/dbcommands.cpp
parentcbe2d992e9cd1ea66af9fa91df006106775d3073 (diff)
downloadmongodb-5d342a758c6095b4d30aba0750b54f13b8916f51.tar.gz
Imported Upstream version 2.0.0
Diffstat (limited to 'db/dbcommands.cpp')
-rw-r--r--db/dbcommands.cpp495
1 files changed, 273 insertions, 222 deletions
diff --git a/db/dbcommands.cpp b/db/dbcommands.cpp
index 59dd78c..31f4b7f 100644
--- a/db/dbcommands.cpp
+++ b/db/dbcommands.cpp
@@ -15,8 +15,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/* SHARDING:
+ I believe this file is for mongod only.
+ See s/commnands_public.cpp for mongos.
+*/
+
#include "pch.h"
-#include "query.h"
+#include "ops/query.h"
#include "pdfile.h"
#include "jsobj.h"
#include "../bson/util/builder.h"
@@ -26,10 +31,11 @@
#include "../util/lruishmap.h"
#include "../util/md5.hpp"
#include "../util/processinfo.h"
+#include "../util/ramlog.h"
#include "json.h"
#include "repl.h"
#include "repl_block.h"
-#include "replpair.h"
+#include "replutil.h"
#include "commands.h"
#include "db.h"
#include "instance.h"
@@ -45,7 +51,21 @@
namespace mongo {
- extern int otherTraceLevel;
+ namespace dur {
+ void setAgeOutJournalFiles(bool rotate);
+ }
+ /** @return true if fields found */
+ bool setParmsMongodSpecific(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ BSONElement e = cmdObj["ageOutJournalFiles"];
+ if( !e.eoo() ) {
+ bool r = e.trueValue();
+ log() << "ageOutJournalFiles " << r << endl;
+ dur::setAgeOutJournalFiles(r);
+ return true;
+ }
+ return false;
+ }
+
void flushDiagLog();
/* reset any errors so that getlasterror comes back clean.
@@ -68,7 +88,7 @@ namespace mongo {
help << "reset error state (used with getpreverror)";
}
CmdResetError() : Command("resetError", false, "reseterror") {}
- bool run(const string& db, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool run(const string& db, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
LastError *le = lastError.get();
assert( le );
le->reset();
@@ -99,7 +119,7 @@ namespace mongo {
<< " { w:n } - await replication to n servers (including self) before returning\n"
<< " { wtimeout:m} - timeout for w in m milliseconds";
}
- bool run(const string& dbname, BSONObj& _cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool run(const string& dbname, BSONObj& _cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
LastError *le = lastError.disableForCommand();
bool err = false;
@@ -112,7 +132,7 @@ namespace mongo {
Client& c = cc();
c.appendLastOp( result );
- result.appendNumber( "connectionId" , c.getConnectionId() );
+ result.appendNumber( "connectionId" , c.getConnectionId() ); // for sharding; also useful in general for debugging
BSONObj cmdObj = _cmdObj;
{
@@ -139,7 +159,7 @@ namespace mongo {
else if ( cmdObj["fsync"].trueValue() ) {
Timer t;
if( !getDur().awaitCommit() ) {
- // if get here, not running with --dur
+ // if get here, not running with --journal
log() << "fsync from getlasterror" << endl;
result.append( "fsyncFiles" , MemoryMappedFile::flushAll( true ) );
}
@@ -156,12 +176,10 @@ namespace mongo {
}
BSONElement e = cmdObj["w"];
- if ( e.isNumber() ) {
+ if ( e.ok() ) {
int timeout = cmdObj["wtimeout"].numberInt();
Timer t;
- int w = e.numberInt();
-
long long passes = 0;
char buf[32];
while ( 1 ) {
@@ -171,7 +189,7 @@ namespace mongo {
if ( anyReplEnabled() ) {
result.append( "wnote" , "no write has been done on this connection" );
}
- else if ( w <= 1 ) {
+ else if ( e.isNumber() && e.numberInt() <= 1 ) {
// don't do anything
// w=1 and no repl, so this is fine
}
@@ -185,8 +203,9 @@ namespace mongo {
}
// check this first for w=0 or w=1
- if ( opReplicatedEnough( op, w ) )
+ if ( opReplicatedEnough( op, e ) ) {
break;
+ }
// if replication isn't enabled (e.g., config servers)
if ( ! anyReplEnabled() ) {
@@ -230,7 +249,7 @@ namespace mongo {
return true;
}
CmdGetPrevError() : Command("getPrevError", false, "getpreverror") {}
- bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
LastError *le = lastError.disableForCommand();
le->appendSelf( result );
if ( le->valid )
@@ -241,6 +260,65 @@ namespace mongo {
}
} cmdGetPrevError;
+ CmdShutdown cmdShutdown;
+
+ void CmdShutdown::help( stringstream& help ) const {
+ help << "shutdown the database. must be ran against admin db and "
+ << "either (1) ran from localhost or (2) authenticated. If "
+ << "this is a primary in a replica set and there is no member "
+ << "within 10 seconds of its optime, it will not shutdown "
+ << "without force : true. You can also specify timeoutSecs : "
+ << "N to wait N seconds for other members to catch up.";
+ }
+
+ bool CmdShutdown::run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool force = cmdObj.hasField("force") && cmdObj["force"].trueValue();
+
+ if (!force && theReplSet && theReplSet->isPrimary()) {
+ long long timeout, now, start;
+ timeout = now = start = curTimeMicros64()/1000000;
+ if (cmdObj.hasField("timeoutSecs")) {
+ timeout += cmdObj["timeoutSecs"].numberLong();
+ }
+
+ OpTime lastOp = theReplSet->lastOpTimeWritten;
+ OpTime closest = theReplSet->lastOtherOpTime();
+ long long int diff = lastOp.getSecs() - closest.getSecs();
+ while (now <= timeout && (diff < 0 || diff > 10)) {
+ sleepsecs(1);
+ now++;
+
+ lastOp = theReplSet->lastOpTimeWritten;
+ closest = theReplSet->lastOtherOpTime();
+ diff = lastOp.getSecs() - closest.getSecs();
+ }
+
+ if (diff < 0 || diff > 10) {
+ errmsg = "no secondaries within 10 seconds of my optime";
+ result.append("closest", closest.getSecs());
+ result.append("difference", diff);
+ return false;
+ }
+
+ // step down
+ theReplSet->stepDown(120);
+
+ log() << "waiting for secondaries to catch up" << endl;
+
+ lastOp = theReplSet->lastOpTimeWritten;
+ while (lastOp != closest && now - start < 60) {
+ closest = theReplSet->lastOtherOpTime();
+
+ now++;
+ sleepsecs(1);
+ }
+
+ // regardless of whether they caught up, we'll shut down
+ }
+
+ return shutdownHelper();
+ }
+
class CmdDropDatabase : public Command {
public:
virtual bool logTheOp() {
@@ -254,7 +332,7 @@ namespace mongo {
}
virtual LockType locktype() const { return WRITE; }
CmdDropDatabase() : Command("dropDatabase") {}
- bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
BSONElement e = cmdObj.firstElement();
log() << "dropDatabase " << dbname << endl;
int p = (int) e.number();
@@ -274,17 +352,20 @@ namespace mongo {
virtual bool slaveOk() const {
return true;
}
+ virtual bool maintenanceMode() const { return true; }
virtual void help( stringstream& help ) const {
help << "repair database. also compacts. note: slow.";
}
virtual LockType locktype() const { return WRITE; }
CmdRepairDatabase() : Command("repairDatabase") {}
- bool run(const string& dbname , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
BSONElement e = cmdObj.firstElement();
log() << "repairDatabase " << dbname << endl;
int p = (int) e.number();
- if ( p != 1 )
+ if ( p != 1 ) {
+ errmsg = "bad option";
return false;
+ }
e = cmdObj.getField( "preserveClonedFilesOnFailure" );
bool preserveClonedFilesOnFailure = e.isBoolean() && e.boolean();
e = cmdObj.getField( "backupOriginalFiles" );
@@ -311,7 +392,7 @@ namespace mongo {
}
virtual LockType locktype() const { return WRITE; }
CmdProfile() : Command("profile") {}
- bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
BSONElement e = cmdObj.firstElement();
result.append("was", cc().database()->profile);
result.append("slowms", cmdLine.slowMS );
@@ -348,7 +429,7 @@ namespace mongo {
help << "returns lots of administrative server statistics";
}
- bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
long long start = Listener::getElapsedTimeMillis();
BSONObjBuilder timeBuilder(128);
@@ -407,9 +488,11 @@ namespace mongo {
t.append("bits", ( sizeof(int*) == 4 ? 32 : 64 ) );
ProcessInfo p;
+ int v = 0;
if ( p.supported() ) {
t.appendNumber( "resident" , p.getResidentSize() );
- t.appendNumber( "virtual" , p.getVirtualMemorySize() );
+ v = p.getVirtualMemorySize();
+ t.appendNumber( "virtual" , v );
t.appendBool( "supported" , true );
}
else {
@@ -419,7 +502,18 @@ namespace mongo {
timeBuilder.appendNumber( "middle of mem" , Listener::getElapsedTimeMillis() - start );
- t.appendNumber( "mapped" , MemoryMappedFile::totalMappedLength() / ( 1024 * 1024 ) );
+ int m = (int) (MemoryMappedFile::totalMappedLength() / ( 1024 * 1024 ));
+ t.appendNumber( "mapped" , m );
+
+ if ( cmdLine.dur ) {
+ m *= 2;
+ t.appendNumber( "mappedWithJournal" , m );
+ }
+
+ if( v - m > 5000 ) {
+ t.append("note", "virtual minus mapped is large. could indicate a memory leak");
+ log() << "warning: virtual size (" << v << "MB) - mapped size (" << m << "MB) is large. could indicate a memory leak" << endl;
+ }
t.done();
@@ -504,9 +598,27 @@ namespace mongo {
result.append("dur", dur::stats.asObj());
}
+ timeBuilder.appendNumber( "after dur" , Listener::getElapsedTimeMillis() - start );
+
+ {
+ RamLog* rl = RamLog::get( "warnings" );
+ verify(15880, rl);
+
+ if (rl->lastWrite() >= time(0)-(10*60)){ // only show warnings from last 10 minutes
+ vector<const char*> lines;
+ rl->get( lines );
+
+ BSONArrayBuilder arr( result.subarrayStart( "warnings" ) );
+ for ( unsigned i=std::max(0,(int)lines.size()-10); i<lines.size(); i++ )
+ arr.append( lines[i] );
+ arr.done();
+ }
+ }
+
if ( ! authed )
result.append( "note" , "run against admin for more info" );
-
+
+ timeBuilder.appendNumber( "at end" , Listener::getElapsedTimeMillis() - start );
if ( Listener::getElapsedTimeMillis() - start > 1000 ) {
BSONObj t = timeBuilder.obj();
log() << "serverStatus was very slow: " << t << endl;
@@ -526,7 +638,7 @@ namespace mongo {
virtual void help( stringstream& help ) const { help << "internal"; }
virtual LockType locktype() const { return NONE; }
CmdGetOpTime() : Command("getoptime") { }
- bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
writelock l( "" );
result.appendDate("optime", OpTime::now().asDate());
return true;
@@ -555,7 +667,7 @@ namespace mongo {
}
void help(stringstream& h) const { h << "http://www.mongodb.org/display/DOCS/Monitoring+and+Diagnostics#MonitoringandDiagnostics-DatabaseRecord%2FReplay"; }
virtual LockType locktype() const { return WRITE; }
- bool run(const string& dbname , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
+ bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
int was = _diaglog.setLevel( cmdObj.firstElement().numberInt() );
flushDiagLog();
if ( !cmdLine.quiet )
@@ -678,7 +790,7 @@ namespace mongo {
}
virtual void help( stringstream& help ) const { help << "drop a collection\n{drop : <collectionName>}"; }
virtual LockType locktype() const { return WRITE; }
- virtual bool run(const string& dbname , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
+ virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
string nsToDrop = dbname + '.' + cmdObj.firstElement().valuestr();
NamespaceDetails *d = nsdetails(nsToDrop.c_str());
if ( !cmdLine.quiet )
@@ -702,7 +814,7 @@ namespace mongo {
return false;
}
virtual bool slaveOk() const {
- // ok on --slave setups, not ok for nonmaster of a repl pair (unless override)
+ // ok on --slave setups
return replSettings.slave == SimpleSlave;
}
virtual bool slaveOverrideOk() {
@@ -712,7 +824,7 @@ namespace mongo {
return false;
}
virtual void help( stringstream& help ) const { help << "count objects in collection"; }
- virtual bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
+ virtual bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
string ns = dbname + '.' + cmdObj.firstElement().valuestr();
string err;
long long n = runCount(ns.c_str(), cmdObj, err);
@@ -748,11 +860,14 @@ namespace mongo {
}
virtual LockType locktype() const { return WRITE; }
virtual void help( stringstream& help ) const {
- help << "create a collection";
+ help << "create a collection explicitly\n"
+ "{ create: <ns>[, capped: <bool>, size: <collSizeInBytes>, max: <nDocs>] }";
}
- virtual bool run(const string& dbname , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ uassert(15888, "must pass name of collection to create", cmdObj.firstElement().valuestrsafe()[0] != '\0');
string ns = dbname + '.' + cmdObj.firstElement().valuestr();
string err;
+ uassert(14832, "specify size:<n> when capped is true", !cmdObj["capped"].trueValue() || cmdObj["size"].isNumber() || cmdObj.hasField("$nExtents"));
bool ok = userCreateNS(ns.c_str(), cmdObj, err, ! fromRepl );
if ( !ok && !err.empty() )
errmsg = err;
@@ -774,7 +889,7 @@ namespace mongo {
help << "drop indexes for a collection";
}
CmdDropIndexes() : Command("dropIndexes", false, "deleteIndexes") { }
- bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& anObjBuilder, bool /*fromRepl*/) {
+ bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& anObjBuilder, bool /*fromRepl*/) {
BSONElement e = jsobj.firstElement();
string toDeleteNs = dbname + '.' + e.valuestr();
NamespaceDetails *d = nsdetails(toDeleteNs.c_str());
@@ -819,7 +934,7 @@ namespace mongo {
help << "re-index a collection";
}
CmdReIndex() : Command("reIndex") { }
- bool run(const string& dbname , BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) {
+ bool run(const string& dbname , BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) {
static DBDirectClient db;
BSONElement e = jsobj.firstElement();
@@ -837,7 +952,7 @@ namespace mongo {
auto_ptr<DBClientCursor> i = db.getIndexes( toDeleteNs );
BSONObjBuilder b;
while ( i->more() ) {
- BSONObj o = i->next().getOwned();
+ BSONObj o = i->next().removeField("v").getOwned();
b.append( BSONObjBuilder::numStr( all.size() ) , o );
all.push_back( o );
}
@@ -851,21 +966,9 @@ namespace mongo {
for ( list<BSONObj>::iterator i=all.begin(); i!=all.end(); i++ ) {
BSONObj o = *i;
- if ( o.getIntField("v") > 0 ) {
- BSONObjBuilder b;
- BSONObjIterator i( o );
- while ( i.more() ) {
- BSONElement e = i.next();
- if ( str::equals( e.fieldName() , "v" ) )
- continue;
- b.append( e );
- }
- o = b.obj();
- }
theDataFileMgr.insertWithObjMod( Namespace( toDeleteNs.c_str() ).getSisterNS( "system.indexes" ).c_str() , o , true );
}
- result.append( "ok" , 1 );
result.append( "nIndexes" , (int)all.size() );
result.appendArray( "indexes" , b.obj() );
return true;
@@ -883,10 +986,10 @@ namespace mongo {
virtual bool adminOnly() const {
return true;
}
- virtual LockType locktype() const { return READ; }
+ virtual LockType locktype() const { return NONE; }
virtual void help( stringstream& help ) const { help << "list databases on this server"; }
CmdListDatabases() : Command("listDatabases" , true ) {}
- bool run(const string& dbname , BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) {
+ bool run(const string& dbname , BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) {
vector< string > dbNames;
getDatabaseNames( dbNames );
vector< BSONObj > dbInfos;
@@ -895,12 +998,18 @@ namespace mongo {
boost::intmax_t totalSize = 0;
for ( vector< string >::iterator i = dbNames.begin(); i != dbNames.end(); ++i ) {
BSONObjBuilder b;
- b.append( "name", i->c_str() );
+ b.append( "name", *i );
+
boost::intmax_t size = dbSize( i->c_str() );
b.append( "sizeOnDisk", (double) size );
- Client::Context ctx( *i );
- b.appendBool( "empty", ctx.db()->isEmpty() );
totalSize += size;
+
+ {
+ readlock lk( *i );
+ Client::Context ctx( *i );
+ b.appendBool( "empty", ctx.db()->isEmpty() );
+ }
+
dbInfos.push_back( b.obj() );
seen.insert( i->c_str() );
@@ -908,7 +1017,11 @@ namespace mongo {
// TODO: erh 1/1/2010 I think this is broken where path != dbpath ??
set<string> allShortNames;
- dbHolder.getAllShortNames( allShortNames );
+ {
+ readlock lk;
+ dbHolder.getAllShortNames( allShortNames );
+ }
+
for ( set<string>::iterator i = allShortNames.begin(); i != allShortNames.end(); i++ ) {
string name = *i;
@@ -916,9 +1029,14 @@ namespace mongo {
continue;
BSONObjBuilder b;
- b << "name" << name << "sizeOnDisk" << double( 1 );
- Client::Context ctx( name );
- b.appendBool( "empty", ctx.db()->isEmpty() );
+ b.append( "name" , name );
+ b.append( "sizeOnDisk" , (double)1.0 );
+
+ {
+ readlock lk( name );
+ Client::Context ctx( name );
+ b.appendBool( "empty", ctx.db()->isEmpty() );
+ }
dbInfos.push_back( b.obj() );
}
@@ -940,7 +1058,7 @@ namespace mongo {
virtual LockType locktype() const { return WRITE; }
CmdCloseAllDatabases() : Command( "closeAllDatabases" ) {}
- bool run(const string& dbname , BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) {
+ bool run(const string& dbname , BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) {
bool ok;
try {
ok = dbHolder.closeAll( dbpath , result, false );
@@ -967,7 +1085,7 @@ namespace mongo {
help << " example: { filemd5 : ObjectId(aaaaaaa) , root : \"fs\" }";
}
virtual LockType locktype() const { return READ; }
- bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
string ns = dbname;
ns += ".";
{
@@ -986,7 +1104,7 @@ namespace mongo {
BSONObj sort = BSON( "files_id" << 1 << "n" << 1 );
shared_ptr<Cursor> cursor = bestGuessCursor(ns.c_str(), query, sort);
- scoped_ptr<ClientCursor> cc (new ClientCursor(QueryOption_NoCursorTimeout, cursor, ns.c_str()));
+ auto_ptr<ClientCursor> cc (new ClientCursor(QueryOption_NoCursorTimeout, cursor, ns.c_str()));
int n = 0;
while ( cursor->ok() ) {
@@ -1000,37 +1118,31 @@ namespace mongo {
BSONObj obj = cursor->current();
cursor->advance();
- ClientCursor::YieldLock yield (cc);
- try {
-
- BSONElement ne = obj["n"];
- assert(ne.isNumber());
- int myn = ne.numberInt();
- if ( n != myn ) {
- log() << "should have chunk: " << n << " have:" << myn << endl;
-
- DBDirectClient client;
- Query q(query);
- q.sort(sort);
- auto_ptr<DBClientCursor> c = client.query(ns, q);
- while(c->more())
- PRINT(c->nextSafe());
+ BSONElement ne = obj["n"];
+ assert(ne.isNumber());
+ int myn = ne.numberInt();
+ if ( n != myn ) {
+ log() << "should have chunk: " << n << " have:" << myn << endl;
+ dumpChunks( ns , query , sort );
+ uassert( 10040 , "chunks out of order" , n == myn );
+ }
- uassert( 10040 , "chunks out of order" , n == myn );
- }
+ int len;
+ const char * data = obj["data"].binDataClean( len );
- int len;
- const char * data = obj["data"].binDataClean( len );
+ ClientCursor::YieldLock yield (cc.get());
+ try {
md5_append( &st , (const md5_byte_t*)(data) , len );
-
n++;
}
catch (...) {
- yield.relock(); // needed before yield goes out of scope
+ if ( ! yield.stillOk() ) // relocks
+ cc.release();
throw;
}
if ( ! yield.stillOk() ) {
+ cc.release();
uasserted(13281, "File deleted during filemd5 command");
}
}
@@ -1041,6 +1153,15 @@ namespace mongo {
result.append( "md5" , digestToString( d ) );
return true;
}
+
+ void dumpChunks( const string& ns , const BSONObj& query , const BSONObj& sort ) {
+ DBDirectClient client;
+ Query q(query);
+ q.sort(sort);
+ auto_ptr<DBClientCursor> c = client.query(ns, q);
+ while(c->more())
+ PRINT(c->nextSafe());
+ }
} cmdFileMD5;
static IndexDetails *cmdIndexDetailsForRange( const char *ns, string &errmsg, BSONObj &min, BSONObj &max, BSONObj &keyPattern ) {
@@ -1063,7 +1184,7 @@ namespace mongo {
"\nkeyPattern, min, and max parameters are optional."
"\nnote: This command may take a while to run";
}
- bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
Timer timer;
string ns = jsobj.firstElement().String();
@@ -1103,7 +1224,7 @@ namespace mongo {
if ( idx == 0 )
return false;
- c.reset( new BtreeCursor( d, d->idxNo(*idx), *idx, min, max, false, 1 ) );
+ c.reset( BtreeCursor::make( d, d->idxNo(*idx), *idx, min, max, false, 1 ) );
}
long long avgObjSize = d->stats.datasize / d->stats.nrecords;
@@ -1178,9 +1299,10 @@ namespace mongo {
virtual bool slaveOk() const { return true; }
virtual LockType locktype() const { return READ; }
virtual void help( stringstream &help ) const {
- help << "{ collStats:\"blog.posts\" , scale : 1 } scale divides sizes e.g. for KB use 1024";
+ help << "{ collStats:\"blog.posts\" , scale : 1 } scale divides sizes e.g. for KB use 1024\n"
+ " avgObjSize - in bytes";
}
- bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
string ns = dbname + "." + jsobj.firstElement().valuestr();
Client::Context cx( ns );
@@ -1199,7 +1321,6 @@ namespace mongo {
errmsg = "scale has to be > 0";
return false;
}
-
}
else if ( jsobj["scale"].trueValue() ) {
errmsg = "scale has to be a number > 0";
@@ -1246,9 +1367,24 @@ namespace mongo {
virtual bool slaveOk() const { return true; }
virtual LockType locktype() const { return READ; }
virtual void help( stringstream &help ) const {
- help << " example: { dbStats:1 } ";
+ help <<
+ "Get stats on a database. Not instantaneous. Slower for databases with large .ns files.\n" <<
+ "Example: { dbStats:1, scale:1 }";
}
- bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ int scale = 1;
+ if ( jsobj["scale"].isNumber() ) {
+ scale = jsobj["scale"].numberInt();
+ if ( scale <= 0 ) {
+ errmsg = "scale has to be > 0";
+ return false;
+ }
+ }
+ else if ( jsobj["scale"].trueValue() ) {
+ errmsg = "scale has to be a number > 0";
+ return false;
+ }
+
list<string> collections;
Database* d = cc().database();
if ( d )
@@ -1288,12 +1424,14 @@ namespace mongo {
result.appendNumber( "collections" , ncollections );
result.appendNumber( "objects" , objects );
result.append ( "avgObjSize" , objects == 0 ? 0 : double(size) / double(objects) );
- result.appendNumber( "dataSize" , size );
- result.appendNumber( "storageSize" , storageSize);
+ result.appendNumber( "dataSize" , size / scale );
+ result.appendNumber( "storageSize" , storageSize / scale);
result.appendNumber( "numExtents" , numExtents );
result.appendNumber( "indexes" , indexes );
- result.appendNumber( "indexSize" , indexSize );
- result.appendNumber( "fileSize" , d->fileSize() );
+ result.appendNumber( "indexSize" , indexSize / scale );
+ result.appendNumber( "fileSize" , d->fileSize() / scale );
+ if( d )
+ result.appendNumber( "nsSizeMB", (int) d->namespaceIndex.fileLength() / 1024 / 1024 );
return true;
}
@@ -1308,7 +1446,7 @@ namespace mongo {
virtual void help( stringstream &help ) const {
help << "{ cloneCollectionAsCapped:<fromName>, toCollection:<toName>, size:<sizeInBytes> }";
}
- bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
string from = jsobj.getStringField( "cloneCollectionAsCapped" );
string to = jsobj.getStringField( "toCollection" );
long long size = (long long)jsobj.getField( "size" ).number();
@@ -1350,6 +1488,7 @@ namespace mongo {
while( c->more() ) {
BSONObj obj = c->next();
theDataFileMgr.insertAndLog( toNs.c_str(), obj, true );
+ getDur().commitIfNeeded();
}
return true;
@@ -1369,7 +1508,7 @@ namespace mongo {
virtual void help( stringstream &help ) const {
help << "{ convertToCapped:<fromCollectionName>, size:<sizeInBytes> }";
}
- bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
BackgroundOperation::assertNoBgOpInProgForDb(dbname.c_str());
string from = jsobj.getStringField( "convertToCapped" );
@@ -1411,116 +1550,6 @@ namespace mongo {
}
} cmdConvertToCapped;
- /* Find and Modify an object returning either the old (default) or new value*/
- class CmdFindAndModify : public Command {
- public:
- virtual void help( stringstream &help ) const {
- help <<
- "{ findAndModify: \"collection\", query: {processed:false}, update: {$set: {processed:true}}, new: true}\n"
- "{ findAndModify: \"collection\", query: {processed:false}, remove: true, sort: {priority:-1}}\n"
- "Either update or remove is required, all other fields have default values.\n"
- "Output is in the \"value\" field\n";
- }
-
- CmdFindAndModify() : Command("findAndModify", false, "findandmodify") { }
- virtual bool logTheOp() {
- return false; // the modification will be logged directly
- }
- virtual bool slaveOk() const {
- return false;
- }
- virtual LockType locktype() const { return WRITE; }
- virtual bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
- static DBDirectClient db;
-
- string ns = dbname + '.' + cmdObj.firstElement().valuestr();
-
- BSONObj origQuery = cmdObj.getObjectField("query"); // defaults to {}
- Query q (origQuery);
- BSONElement sort = cmdObj["sort"];
- if (!sort.eoo())
- q.sort(sort.embeddedObjectUserCheck());
-
- bool upsert = cmdObj["upsert"].trueValue();
-
- BSONObj fieldsHolder (cmdObj.getObjectField("fields"));
- const BSONObj* fields = (fieldsHolder.isEmpty() ? NULL : &fieldsHolder);
-
- BSONObj out = db.findOne(ns, q, fields);
- if (out.isEmpty()) {
- if (!upsert) {
- errmsg = "No matching object found";
- return false;
- }
-
- BSONElement update = cmdObj["update"];
- uassert(13329, "upsert mode requires update field", !update.eoo());
- uassert(13330, "upsert mode requires query field", !origQuery.isEmpty());
- db.update(ns, origQuery, update.embeddedObjectUserCheck(), true);
-
- BSONObj gle = db.getLastErrorDetailed();
- if (gle["err"].type() == String) {
- errmsg = gle["err"].String();
- return false;
- }
-
- if (cmdObj["new"].trueValue()) {
- BSONElement _id = gle["upserted"];
- if (_id.eoo())
- _id = origQuery["_id"];
-
- out = db.findOne(ns, QUERY("_id" << _id), fields);
- }
-
- }
- else {
-
- if (cmdObj["remove"].trueValue()) {
- uassert(12515, "can't remove and update", cmdObj["update"].eoo());
- db.remove(ns, QUERY("_id" << out["_id"]), 1);
-
- }
- else { // update
-
- BSONElement queryId = origQuery["_id"];
- if (queryId.eoo() || getGtLtOp(queryId) != BSONObj::Equality) {
- // need to include original query for $ positional operator
-
- BSONObjBuilder b;
- b.append(out["_id"]);
- BSONObjIterator it(origQuery);
- while (it.more()) {
- BSONElement e = it.next();
- if (strcmp(e.fieldName(), "_id"))
- b.append(e);
- }
- q = Query(b.obj());
- }
-
- if (q.isComplex()) // update doesn't work with complex queries
- q = Query(q.getFilter().getOwned());
-
- BSONElement update = cmdObj["update"];
- uassert(12516, "must specify remove or update", !update.eoo());
- db.update(ns, q, update.embeddedObjectUserCheck());
-
- BSONObj gle = db.getLastErrorDetailed();
- if (gle["err"].type() == String) {
- errmsg = gle["err"].String();
- return false;
- }
-
- if (cmdObj["new"].trueValue())
- out = db.findOne(ns, QUERY("_id" << out["_id"]), fields);
- }
- }
-
- result.append("value", out);
-
- return true;
- }
- } cmdFindAndModify;
-
/* Returns client's uri */
class CmdWhatsMyUri : public Command {
public:
@@ -1535,7 +1564,7 @@ namespace mongo {
virtual void help( stringstream &help ) const {
help << "{whatsmyuri:1}";
}
- virtual bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
+ virtual bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
BSONObj info = cc().curop()->infoNoauth();
result << "you" << info[ "client" ];
return true;
@@ -1550,7 +1579,7 @@ namespace mongo {
return true;
}
virtual bool slaveOk() const {
- return false;
+ return true;
}
virtual LockType locktype() const { return WRITE; }
virtual bool requiresAuth() {
@@ -1559,7 +1588,7 @@ namespace mongo {
virtual void help( stringstream &help ) const {
help << "internal. for testing only.";
}
- virtual bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
+ virtual bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
string coll = cmdObj[ "godinsert" ].valuestrsafe();
uassert( 13049, "godinsert must specify a collection", !coll.empty() );
string ns = dbname + "." + coll;
@@ -1574,7 +1603,7 @@ namespace mongo {
DBHashCmd() : Command( "dbHash", false, "dbhash" ) {}
virtual bool slaveOk() const { return true; }
virtual LockType locktype() const { return READ; }
- virtual bool run(const string& dbname , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
+ virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
list<string> colls;
Database* db = cc().database();
if ( db )
@@ -1611,7 +1640,7 @@ namespace mongo {
int idNum = nsd->findIdIndex();
if ( idNum >= 0 ) {
- cursor.reset( new BtreeCursor( nsd , idNum , nsd->idx( idNum ) , BSONObj() , BSONObj() , false , 1 ) );
+ cursor.reset( BtreeCursor::make( nsd , idNum , nsd->idx( idNum ) , BSONObj() , BSONObj() , false , 1 ) );
}
else if ( c.find( ".system." ) != string::npos ) {
continue;
@@ -1620,9 +1649,8 @@ namespace mongo {
cursor = findTableScan( c.c_str() , BSONObj() );
}
else {
- bb.done();
- errmsg = (string)"can't find _id index for: " + c;
- return 0;
+ log() << "can't find _id index for: " << c << endl;
+ continue;
}
md5_state_t st;
@@ -1665,16 +1693,13 @@ namespace mongo {
virtual bool slaveOk() const { return true; }
virtual void help( stringstream& help ) const {
help << "internal testing command. Makes db block (in a read lock) for 100 seconds\n";
- help << "w:true write lock";
+ help << "w:true write lock. secs:<seconds>";
}
CmdSleep() : Command("sleep") { }
- bool run(const string& ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
-
-
+ bool run(const string& ns, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
int secs = 100;
if ( cmdObj["secs"].isNumber() )
secs = cmdObj["secs"].numberInt();
-
if( cmdObj.getBoolField("w") ) {
writelock lk("");
sleepsecs(secs);
@@ -1683,7 +1708,6 @@ namespace mongo {
readlock lk("");
sleepsecs(secs);
}
-
return true;
}
} cmdSleep;
@@ -1695,7 +1719,7 @@ namespace mongo {
virtual bool slaveOk() const { return false; }
virtual LockType locktype() const { return WRITE; }
virtual bool requiresAuth() { return true; }
- virtual bool run(const string& dbname , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
+ virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
string coll = cmdObj[ "captrunc" ].valuestrsafe();
uassert( 13416, "captrunc must specify a collection", !coll.empty() );
string ns = dbname + "." + coll;
@@ -1722,7 +1746,7 @@ namespace mongo {
virtual bool slaveOk() const { return false; }
virtual LockType locktype() const { return WRITE; }
virtual bool requiresAuth() { return true; }
- virtual bool run(const string& dbname , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
+ virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
string coll = cmdObj[ "emptycapped" ].valuestrsafe();
uassert( 13428, "emptycapped must specify a collection", !coll.empty() );
string ns = dbname + "." + coll;
@@ -1787,13 +1811,31 @@ namespace mongo {
if ( c->adminOnly() )
log( 2 ) << "command: " << cmdObj << endl;
+ if (c->maintenanceMode() && theReplSet && theReplSet->isSecondary()) {
+ theReplSet->setMaintenanceMode(true);
+ }
+
if ( c->locktype() == Command::NONE ) {
// we also trust that this won't crash
+
+ if ( c->requiresAuth() ) {
+ // test that the user at least as read permissions
+ if ( ! client.getAuthenticationInfo()->isAuthorizedReads( dbname ) ) {
+ result.append( "errmsg" , "need to login" );
+ return false;
+ }
+ }
+
client.curop()->ensureStarted();
string errmsg;
- int ok = c->run( dbname , cmdObj , errmsg , result , fromRepl );
+ int ok = c->run( dbname , cmdObj , queryOptions, errmsg , result , fromRepl );
if ( ! ok )
result.append( "errmsg" , errmsg );
+
+ if (c->maintenanceMode() && theReplSet) {
+ theReplSet->setMaintenanceMode(false);
+ }
+
return ok;
}
@@ -1807,11 +1849,13 @@ namespace mongo {
client.curop()->ensureStarted();
Client::Context ctx( dbname , dbpath , &lk , c->requiresAuth() );
+ bool retval = true;
+
try {
string errmsg;
- if ( ! c->run(dbname, cmdObj, errmsg, result, fromRepl ) ) {
+ if ( ! c->run(dbname, cmdObj, queryOptions, errmsg, result, fromRepl ) ) {
result.append( "errmsg" , errmsg );
- return false;
+ retval = false;
}
}
catch ( DBException& e ) {
@@ -1819,14 +1863,18 @@ namespace mongo {
ss << "exception: " << e.what();
result.append( "errmsg" , ss.str() );
result.append( "code" , e.getCode() );
- return false;
+ retval = false;
}
- if ( c->logTheOp() && ! fromRepl ) {
+ if ( retval && c->logTheOp() && ! fromRepl ) {
logOp("c", cmdns, cmdObj);
}
- return true;
+ if (c->maintenanceMode() && theReplSet) {
+ theReplSet->setMaintenanceMode(false);
+ }
+
+ return retval;
}
@@ -1850,7 +1898,10 @@ namespace mongo {
BSONObj jsobj;
{
BSONElement e = _cmdobj.firstElement();
- if ( e.type() == Object && string("query") == e.fieldName() ) {
+ if ( e.type() == Object && (e.fieldName()[0] == '$'
+ ? str::equals("query", e.fieldName()+1)
+ : str::equals("query", e.fieldName())))
+ {
jsobj = e.embeddedObject();
}
else {