diff options
author | Spencer T Brody <spencer@10gen.com> | 2012-09-28 16:01:07 -0400 |
---|---|---|
committer | Eric Milkie <milkie@10gen.com> | 2012-10-02 17:42:26 -0400 |
commit | c301b78471e055b8426a27910d9ce514defa67d6 (patch) | |
tree | 810e4f876792b24d248ef9969cdf169e79e2e1b2 | |
parent | 5eb79913ff0ceb6fbf782d8a1ec965ae95880fb4 (diff) | |
download | mongo-c301b78471e055b8426a27910d9ce514defa67d6.tar.gz |
SERVER-7182 Call getLastError on the correct database in mongorestore
-rw-r--r-- | jstests/tool/restorewithauth.js | 44 | ||||
-rw-r--r-- | src/mongo/client/dbclient.cpp | 20 | ||||
-rw-r--r-- | src/mongo/client/dbclientinterface.h | 14 | ||||
-rw-r--r-- | src/mongo/client/syncclusterconnection.cpp | 10 | ||||
-rw-r--r-- | src/mongo/client/syncclusterconnection.h | 5 | ||||
-rw-r--r-- | src/mongo/tools/restore.cpp | 8 |
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) { |