summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/fsync.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/commands/fsync.cpp')
-rw-r--r--src/mongo/db/commands/fsync.cpp395
1 files changed, 204 insertions, 191 deletions
diff --git a/src/mongo/db/commands/fsync.cpp b/src/mongo/db/commands/fsync.cpp
index aa3b8c9855a..348637d062a 100644
--- a/src/mongo/db/commands/fsync.cpp
+++ b/src/mongo/db/commands/fsync.cpp
@@ -57,232 +57,245 @@
namespace mongo {
- using std::endl;
- using std::string;
- using std::stringstream;
-
- class FSyncLockThread : public BackgroundJob {
- void doRealWork();
- public:
- FSyncLockThread() : BackgroundJob( true ) {}
- virtual ~FSyncLockThread(){}
- virtual string name() const { return "FSyncLockThread"; }
- virtual void run() {
- Client::initThread( "fsyncLockWorker" );
- try {
- doRealWork();
- }
- catch ( std::exception& e ) {
- error() << "FSyncLockThread exception: " << e.what() << endl;
- }
+using std::endl;
+using std::string;
+using std::stringstream;
+
+class FSyncLockThread : public BackgroundJob {
+ void doRealWork();
+
+public:
+ FSyncLockThread() : BackgroundJob(true) {}
+ virtual ~FSyncLockThread() {}
+ virtual string name() const {
+ return "FSyncLockThread";
+ }
+ virtual void run() {
+ Client::initThread("fsyncLockWorker");
+ try {
+ doRealWork();
+ } catch (std::exception& e) {
+ error() << "FSyncLockThread exception: " << e.what() << endl;
}
- };
-
- /* see unlockFsync() for unlocking:
- db.$cmd.sys.unlock.findOne()
- */
- class FSyncCommand : public Command {
- public:
- static const char* url() { return "http://dochub.mongodb.org/core/fsynccommand"; }
- bool locked;
- bool pendingUnlock;
- SimpleMutex m; // protects locked var above
- string err;
-
- stdx::condition_variable_any _threadSync;
- stdx::condition_variable_any _unlockSync;
-
- FSyncCommand() : Command( "fsync" ) { locked=false; pendingUnlock=false; }
- virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual bool slaveOk() const { return true; }
- virtual bool adminOnly() const { return true; }
- virtual void help(stringstream& h) const { h << url(); }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {
- ActionSet actions;
- actions.addAction(ActionType::fsync);
- out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+ }
+};
+
+/* see unlockFsync() for unlocking:
+ db.$cmd.sys.unlock.findOne()
+*/
+class FSyncCommand : public Command {
+public:
+ static const char* url() {
+ return "http://dochub.mongodb.org/core/fsynccommand";
+ }
+ bool locked;
+ bool pendingUnlock;
+ SimpleMutex m; // protects locked var above
+ string err;
+
+ stdx::condition_variable_any _threadSync;
+ stdx::condition_variable_any _unlockSync;
+
+ FSyncCommand() : Command("fsync") {
+ locked = false;
+ pendingUnlock = false;
+ }
+ virtual bool isWriteCommandForConfigServer() const {
+ return false;
+ }
+ virtual bool slaveOk() const {
+ return true;
+ }
+ virtual bool adminOnly() const {
+ return true;
+ }
+ virtual void help(stringstream& h) const {
+ h << url();
+ }
+ virtual void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) {
+ ActionSet actions;
+ actions.addAction(ActionType::fsync);
+ out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
+ }
+ virtual bool run(OperationContext* txn,
+ const string& dbname,
+ BSONObj& cmdObj,
+ int,
+ string& errmsg,
+ BSONObjBuilder& result) {
+ if (txn->lockState()->isLocked()) {
+ errmsg = "fsync: Cannot execute fsync command from contexts that hold a data lock";
+ return false;
}
- virtual bool run(OperationContext* txn,
- const string& dbname,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result) {
-
- if (txn->lockState()->isLocked()) {
- errmsg = "fsync: Cannot execute fsync command from contexts that hold a data lock";
+
+ bool sync =
+ !cmdObj["async"].trueValue(); // async means do an fsync, but return immediately
+ bool lock = cmdObj["lock"].trueValue();
+ log() << "CMD fsync: sync:" << sync << " lock:" << lock << endl;
+ if (lock) {
+ if (!sync) {
+ errmsg = "fsync: sync option must be true when using lock";
return false;
}
- bool sync = !cmdObj["async"].trueValue(); // async means do an fsync, but return immediately
- bool lock = cmdObj["lock"].trueValue();
- log() << "CMD fsync: sync:" << sync << " lock:" << lock << endl;
- if( lock ) {
- if ( ! sync ) {
- errmsg = "fsync: sync option must be true when using lock";
- return false;
- }
-
- stdx::lock_guard<SimpleMutex> lk(m);
- err = "";
-
- (new FSyncLockThread())->go();
- while ( ! locked && err.size() == 0 ) {
- _threadSync.wait( m );
- }
-
- if ( err.size() ){
- errmsg = err;
- return false;
- }
-
- log() << "db is now locked, no writes allowed. db.fsyncUnlock() to unlock" << endl;
- log() << " For more info see " << FSyncCommand::url() << endl;
- result.append("info", "now locked against writes, use db.fsyncUnlock() to unlock");
- result.append("seeAlso", FSyncCommand::url());
+ stdx::lock_guard<SimpleMutex> lk(m);
+ err = "";
+ (new FSyncLockThread())->go();
+ while (!locked && err.size() == 0) {
+ _threadSync.wait(m);
}
- else {
- // the simple fsync command case
- if (sync) {
- // can this be GlobalRead? and if it can, it should be nongreedy.
- ScopedTransaction transaction(txn, MODE_X);
- Lock::GlobalWrite w(txn->lockState());
- getDur().commitNow(txn);
-
- // No WriteUnitOfWork needed, as this does no writes of its own.
- }
-
- // Take a global IS lock to ensure the storage engine is not shutdown
- Lock::GlobalLock global(txn->lockState(), MODE_IS, UINT_MAX);
- StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine();
- result.append( "numFiles" , storageEngine->flushAllFiles( sync ) );
- }
- return 1;
- }
- } fsyncCmd;
- namespace {
- bool unlockFsync();
- } // namespace
+ if (err.size()) {
+ errmsg = err;
+ return false;
+ }
- class FSyncUnlockCommand : public Command {
- public:
+ log() << "db is now locked, no writes allowed. db.fsyncUnlock() to unlock" << endl;
+ log() << " For more info see " << FSyncCommand::url() << endl;
+ result.append("info", "now locked against writes, use db.fsyncUnlock() to unlock");
+ result.append("seeAlso", FSyncCommand::url());
- FSyncUnlockCommand() : Command("fsyncUnlock") {}
+ } else {
+ // the simple fsync command case
+ if (sync) {
+ // can this be GlobalRead? and if it can, it should be nongreedy.
+ ScopedTransaction transaction(txn, MODE_X);
+ Lock::GlobalWrite w(txn->lockState());
+ getDur().commitNow(txn);
- bool isWriteCommandForConfigServer() const override { return false; }
+ // No WriteUnitOfWork needed, as this does no writes of its own.
+ }
- bool slaveOk() const override { return true; }
+ // Take a global IS lock to ensure the storage engine is not shutdown
+ Lock::GlobalLock global(txn->lockState(), MODE_IS, UINT_MAX);
+ StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine();
+ result.append("numFiles", storageEngine->flushAllFiles(sync));
+ }
+ return 1;
+ }
+} fsyncCmd;
- bool adminOnly() const override { return true; }
+namespace {
+bool unlockFsync();
+} // namespace
- Status checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) override {
+class FSyncUnlockCommand : public Command {
+public:
+ FSyncUnlockCommand() : Command("fsyncUnlock") {}
- bool isAuthorized = AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(),
- ActionType::unlock);
+ bool isWriteCommandForConfigServer() const override {
+ return false;
+ }
- return isAuthorized ? Status::OK() : Status(ErrorCodes::Unauthorized, "Unauthorized");
- }
+ bool slaveOk() const override {
+ return true;
+ }
- bool run(OperationContext* txn,
- const std::string& db,
- BSONObj& cmdObj,
- int options,
- std::string& errmsg,
- BSONObjBuilder& result) override {
+ bool adminOnly() const override {
+ return true;
+ }
- log() << "command: unlock requested";
+ Status checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) override {
+ bool isAuthorized = AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
+ ResourcePattern::forClusterResource(), ActionType::unlock);
- if (unlockFsync()) {
- result.append("info", "unlock completed");
- return true;
- }
- else {
- errmsg = "not locked";
- return false;
- }
- }
+ return isAuthorized ? Status::OK() : Status(ErrorCodes::Unauthorized, "Unauthorized");
+ }
- } unlockFsyncCmd;
+ bool run(OperationContext* txn,
+ const std::string& db,
+ BSONObj& cmdObj,
+ int options,
+ std::string& errmsg,
+ BSONObjBuilder& result) override {
+ log() << "command: unlock requested";
- SimpleMutex filesLockedFsync;
+ if (unlockFsync()) {
+ result.append("info", "unlock completed");
+ return true;
+ } else {
+ errmsg = "not locked";
+ return false;
+ }
+ }
- void FSyncLockThread::doRealWork() {
- stdx::lock_guard<SimpleMutex> lkf(filesLockedFsync);
+} unlockFsyncCmd;
- OperationContextImpl txn;
- ScopedTransaction transaction(&txn, MODE_X);
- Lock::GlobalWrite global(txn.lockState()); // No WriteUnitOfWork needed
+SimpleMutex filesLockedFsync;
- stdx::lock_guard<SimpleMutex> lk(fsyncCmd.m);
+void FSyncLockThread::doRealWork() {
+ stdx::lock_guard<SimpleMutex> lkf(filesLockedFsync);
- invariant(!fsyncCmd.locked); // impossible to get here if locked is true
- try {
- getDur().syncDataAndTruncateJournal(&txn);
- }
- catch( std::exception& e ) {
- error() << "error doing syncDataAndTruncateJournal: " << e.what() << endl;
- fsyncCmd.err = e.what();
- fsyncCmd._threadSync.notify_one();
- fsyncCmd.locked = false;
- return;
- }
+ OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_X);
+ Lock::GlobalWrite global(txn.lockState()); // No WriteUnitOfWork needed
- txn.lockState()->downgradeGlobalXtoSForMMAPV1();
+ stdx::lock_guard<SimpleMutex> lk(fsyncCmd.m);
- try {
- StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine();
- storageEngine->flushAllFiles(true);
- }
- catch( std::exception& e ) {
- error() << "error doing flushAll: " << e.what() << endl;
- fsyncCmd.err = e.what();
- fsyncCmd._threadSync.notify_one();
- fsyncCmd.locked = false;
- return;
- }
+ invariant(!fsyncCmd.locked); // impossible to get here if locked is true
+ try {
+ getDur().syncDataAndTruncateJournal(&txn);
+ } catch (std::exception& e) {
+ error() << "error doing syncDataAndTruncateJournal: " << e.what() << endl;
+ fsyncCmd.err = e.what();
+ fsyncCmd._threadSync.notify_one();
+ fsyncCmd.locked = false;
+ return;
+ }
- invariant(!fsyncCmd.locked);
- fsyncCmd.locked = true;
+ txn.lockState()->downgradeGlobalXtoSForMMAPV1();
+ try {
+ StorageEngine* storageEngine = getGlobalServiceContext()->getGlobalStorageEngine();
+ storageEngine->flushAllFiles(true);
+ } catch (std::exception& e) {
+ error() << "error doing flushAll: " << e.what() << endl;
+ fsyncCmd.err = e.what();
fsyncCmd._threadSync.notify_one();
+ fsyncCmd.locked = false;
+ return;
+ }
- while ( ! fsyncCmd.pendingUnlock ) {
- fsyncCmd._unlockSync.wait(fsyncCmd.m);
- }
- fsyncCmd.pendingUnlock = false;
+ invariant(!fsyncCmd.locked);
+ fsyncCmd.locked = true;
- fsyncCmd.locked = false;
- fsyncCmd.err = "unlocked";
+ fsyncCmd._threadSync.notify_one();
- fsyncCmd._unlockSync.notify_one();
+ while (!fsyncCmd.pendingUnlock) {
+ fsyncCmd._unlockSync.wait(fsyncCmd.m);
}
+ fsyncCmd.pendingUnlock = false;
+
+ fsyncCmd.locked = false;
+ fsyncCmd.err = "unlocked";
+
+ fsyncCmd._unlockSync.notify_one();
+}
+
+bool lockedForWriting() {
+ return fsyncCmd.locked;
+}
- bool lockedForWriting() {
- return fsyncCmd.locked;
+namespace {
+// @return true if unlocked
+bool unlockFsync() {
+ stdx::lock_guard<SimpleMutex> lk(fsyncCmd.m);
+ if (!fsyncCmd.locked) {
+ return false;
}
-
- namespace {
- // @return true if unlocked
- bool unlockFsync() {
- stdx::lock_guard<SimpleMutex> lk( fsyncCmd.m );
- if( !fsyncCmd.locked ) {
- return false;
- }
- fsyncCmd.pendingUnlock = true;
- fsyncCmd._unlockSync.notify_one();
- fsyncCmd._threadSync.notify_one();
+ fsyncCmd.pendingUnlock = true;
+ fsyncCmd._unlockSync.notify_one();
+ fsyncCmd._threadSync.notify_one();
- while ( fsyncCmd.locked ) {
- fsyncCmd._unlockSync.wait( fsyncCmd.m );
- }
- return true;
- }
- } // namespace
+ while (fsyncCmd.locked) {
+ fsyncCmd._unlockSync.wait(fsyncCmd.m);
+ }
+ return true;
+}
+} // namespace
}