summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@10gen.com>2012-09-28 16:01:07 -0400
committerEric Milkie <milkie@10gen.com>2012-10-02 17:42:26 -0400
commitc301b78471e055b8426a27910d9ce514defa67d6 (patch)
tree810e4f876792b24d248ef9969cdf169e79e2e1b2
parent5eb79913ff0ceb6fbf782d8a1ec965ae95880fb4 (diff)
downloadmongo-c301b78471e055b8426a27910d9ce514defa67d6.tar.gz
SERVER-7182 Call getLastError on the correct database in mongorestore
-rw-r--r--jstests/tool/restorewithauth.js44
-rw-r--r--src/mongo/client/dbclient.cpp20
-rw-r--r--src/mongo/client/dbclientinterface.h14
-rw-r--r--src/mongo/client/syncclusterconnection.cpp10
-rw-r--r--src/mongo/client/syncclusterconnection.h5
-rw-r--r--src/mongo/tools/restore.cpp8
6 files changed, 85 insertions, 16 deletions
diff --git a/jstests/tool/restorewithauth.js b/jstests/tool/restorewithauth.js
index 685301bdd94..15439c4fc03 100644
--- a/jstests/tool/restorewithauth.js
+++ b/jstests/tool/restorewithauth.js
@@ -23,22 +23,25 @@ var conn = startMongod( "--port", port, "--dbpath", "/data/db/" + baseName, "--n
var foo = conn.getDB( "foo" );
for( var i = 0; i < 4; i++ ) {
foo["bar"].save( { "x": i } );
+ foo["baz"].save({"x": i});
}
// make sure the collection exists
assert.eq( foo.system.namespaces.count({name: "foo.bar"}), 1 )
//make sure it has no index except _id
-assert.eq( foo.system.indexes.count(), 1 )
+assert.eq(foo.system.indexes.count(), 2);
+
+foo.bar.createIndex({x:1});
+assert.eq(foo.system.indexes.count(), 3);
// get data dump
var dumpdir = "/data/db/restorewithauth-dump1/";
resetDbpath( dumpdir );
-x = runMongoProgram( "mongodump", "--db", "foo", "-h", "127.0.0.1:"+port, "--collection", "bar",
- "--out", dumpdir );
+x = runMongoProgram("mongodump", "--db", "foo", "-h", "127.0.0.1:"+port, "--out", dumpdir);
-// now drop the collection
-foo.bar.drop();
+// now drop the db
+foo.dropDatabase();
// stop mongod
stopMongod( port );
@@ -55,22 +58,45 @@ admin.auth( "admin" , "admin" );
var foo = conn.getDB( "foo" )
// make sure no collection with the same name exists
-assert.eq( foo.system.namespaces.count( {name: "foo.bar"}), 0 )
+assert.eq(foo.system.namespaces.count( {name: "foo.bar"}), 0);
+assert.eq(foo.system.namespaces.count( {name: "foo.baz"}), 0);
// now try to restore dump
x = runMongoProgram( "mongorestore", "-h", "127.0.0.1:" + port, "--dir" , dumpdir, "-vvvvv" );
// make sure that the collection isn't restored
-assert.eq( foo.system.namespaces.count({name: "foo.bar"}), 0 )
+assert.eq(foo.system.namespaces.count({name: "foo.bar"}), 0);
+assert.eq(foo.system.namespaces.count({name: "foo.baz"}), 0);
// now try to restore dump with correct credentials
x = runMongoProgram( "mongorestore", "-h", "127.0.0.1:" + port, "-d", "foo", "-u", "admin", "-p",
"admin", "--dir", dumpdir + "foo/", "-vvvvv");
// make sure that the collection was restored
-assert.eq( foo.system.namespaces.count({name: "foo.bar"}), 1 )
+assert.eq(foo.system.namespaces.count({name: "foo.bar"}), 1);
+assert.eq(foo.system.namespaces.count({name: "foo.baz"}), 1);
// make sure the collection has 4 documents
-assert.eq( foo.bar.count(), 4 )
+assert.eq(foo.bar.count(), 4);
+assert.eq(foo.baz.count(), 4);
+
+foo.dropDatabase();
+
+// make sure that the collection is empty
+assert.eq(foo.system.namespaces.count({name: "foo.bar"}), 0);
+assert.eq(foo.system.namespaces.count({name: "foo.baz"}), 0);
+
+foo.addUser('user', 'password');
+
+// now try to restore dump with foo database credentials
+x = runMongoProgram("mongorestore", "-h", "127.0.0.1:" + port, "-d", "foo", "-u", "user", "-p",
+ "password", "--dir", dumpdir + "foo/", "-vvvvv");
+
+// make sure that the collection was restored
+assert.eq(foo.system.namespaces.count({name: "foo.bar"}), 1);
+assert.eq(foo.system.namespaces.count({name: "foo.baz"}), 1);
+assert.eq(foo.bar.count(), 4);
+assert.eq(foo.baz.count(), 4);
+assert.eq(foo.system.indexes.count(), 4); // _id on foo, _id on bar, x on foo, _id on system.users
stopMongod( port );
diff --git a/src/mongo/client/dbclient.cpp b/src/mongo/client/dbclient.cpp
index 5af4c623982..cb021da8d2d 100644
--- a/src/mongo/client/dbclient.cpp
+++ b/src/mongo/client/dbclient.cpp
@@ -389,6 +389,14 @@ namespace mongo {
}
BSONObj DBClientWithCommands::getLastErrorDetailed(bool fsync, bool j, int w, int wtimeout) {
+ return getLastErrorDetailed("admin", fsync, j, w, wtimeout);
+ }
+
+ BSONObj DBClientWithCommands::getLastErrorDetailed(const std::string& db,
+ bool fsync,
+ bool j,
+ int w,
+ int wtimeout) {
BSONObj info;
BSONObjBuilder b;
b.append( "getlasterror", 1 );
@@ -407,13 +415,21 @@ namespace mongo {
if ( wtimeout > 0 )
b.append( "wtimeout", wtimeout );
- runCommand("admin", b.obj(), info);
+ runCommand(db, b.obj(), info);
return info;
}
string DBClientWithCommands::getLastError(bool fsync, bool j, int w, int wtimeout) {
- BSONObj info = getLastErrorDetailed(fsync, j, w, wtimeout);
+ return getLastError("admin", fsync, j, w, wtimeout);
+ }
+
+ string DBClientWithCommands::getLastError(const std::string& db,
+ bool fsync,
+ bool j,
+ int w,
+ int wtimeout) {
+ BSONObj info = getLastErrorDetailed(db, fsync, j, w, wtimeout);
return getLastErrorString( info );
}
diff --git a/src/mongo/client/dbclientinterface.h b/src/mongo/client/dbclientinterface.h
index 75dba2afcfc..64ab61d6650 100644
--- a/src/mongo/client/dbclientinterface.h
+++ b/src/mongo/client/dbclientinterface.h
@@ -631,16 +631,30 @@ namespace mongo {
bool createCollection(const string &ns, long long size = 0, bool capped = false, int max = 0, BSONObj *info = 0);
/** Get error result from the last write operation (insert/update/delete) on this connection.
+ db doesn't change the command's behavior - it is just for auth checks.
@return error message text, or empty string if no error.
*/
+ string getLastError(const std::string& db,
+ bool fsync = false,
+ bool j = false,
+ int w = 0,
+ int wtimeout = 0);
+ // Same as above but defaults to using admin DB
string getLastError(bool fsync = false, bool j = false, int w = 0, int wtimeout = 0);
/** Get error result from the last write operation (insert/update/delete) on this connection.
+ db doesn't change the command's behavior - it is just for auth checks.
@return full error object.
If "w" is -1, wait for propagation to majority of nodes.
If "wtimeout" is 0, the operation will block indefinitely if needed.
*/
+ virtual BSONObj getLastErrorDetailed(const std::string& db,
+ bool fsync = false,
+ bool j = false,
+ int w = 0,
+ int wtimeout = 0);
+ // Same as above but defaults to using admin DB
virtual BSONObj getLastErrorDetailed(bool fsync = false, bool j = false, int w = 0, int wtimeout = 0);
/** Can be called with the returned value from getLastErrorDetailed to extract an error string.
diff --git a/src/mongo/client/syncclusterconnection.cpp b/src/mongo/client/syncclusterconnection.cpp
index d09c4be3d02..c5fe6fa83fc 100644
--- a/src/mongo/client/syncclusterconnection.cpp
+++ b/src/mongo/client/syncclusterconnection.cpp
@@ -141,9 +141,17 @@ namespace mongo {
}
BSONObj SyncClusterConnection::getLastErrorDetailed(bool fsync, bool j, int w, int wtimeout) {
+ getLastErrorDetailed("admin", fsync, j, w, wtimeout);
+ }
+
+ BSONObj SyncClusterConnection::getLastErrorDetailed(const std::string& db,
+ bool fsync,
+ bool j,
+ int w,
+ int wtimeout) {
if ( _lastErrors.size() )
return _lastErrors[0];
- return DBClientBase::getLastErrorDetailed(fsync,j,w,wtimeout);
+ return DBClientBase::getLastErrorDetailed(db,fsync,j,w,wtimeout);
}
void SyncClusterConnection::_connect( string host ) {
diff --git a/src/mongo/client/syncclusterconnection.h b/src/mongo/client/syncclusterconnection.h
index 3907f7e50a0..b1d7439e020 100644
--- a/src/mongo/client/syncclusterconnection.h
+++ b/src/mongo/client/syncclusterconnection.h
@@ -91,6 +91,11 @@ namespace mongo {
virtual bool isFailed() const { return false; }
virtual string toString() { return _toString(); }
+ virtual BSONObj getLastErrorDetailed(const std::string& db,
+ bool fsync=false,
+ bool j=false,
+ int w=0,
+ int wtimeout=0);
virtual BSONObj getLastErrorDetailed(bool fsync=false, bool j=false, int w=0, int wtimeout=0);
virtual bool callRead( Message& toSend , Message& response );
diff --git a/src/mongo/tools/restore.cpp b/src/mongo/tools/restore.cpp
index d7779e6a3a7..fd39a9e60e0 100644
--- a/src/mongo/tools/restore.cpp
+++ b/src/mongo/tools/restore.cpp
@@ -159,7 +159,7 @@ public:
drillDown(root, _db != "", _coll != "", true);
// should this happen for oplog replay as well?
- conn().getLastError();
+ conn().getLastError(_db == "" ? "admin" : _db);
if (doOplog) {
log() << "\t Replaying oplog" << endl;
@@ -353,7 +353,7 @@ public:
// wait for ops to propagate to "w" nodes (doesn't warn if w used without replset)
if ( _w > 1 ) {
- conn().getLastError(false, false, _w);
+ conn().getLastError(db, false, false, _w);
}
}
else if ( endsWith( _curns.c_str() , ".system.indexes" )) {
@@ -370,7 +370,7 @@ public:
// wait for insert to propagate to "w" nodes (doesn't warn if w used without replset)
if ( _w > 1 ) {
- conn().getLastErrorDetailed(false, false, _w);
+ conn().getLastErrorDetailed(_curdb, false, false, _w);
}
}
}
@@ -478,7 +478,7 @@ private:
conn().insert( _curdb + ".system.indexes" , o );
// We're stricter about errors for indexes than for regular data
- BSONObj err = conn().getLastErrorDetailed(false, false, _w);
+ BSONObj err = conn().getLastErrorDetailed(_curdb, false, false, _w);
if ( ! ( err["err"].isNull() ) ) {
if (err["err"].String() == "norepl" && _w > 1) {