summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Hernandez <scotthernandez@gmail.com>2016-10-09 17:31:10 -0400
committerScott Hernandez <scotthernandez@gmail.com>2016-10-14 08:54:44 -0400
commitb7f18484664221d7211a32469c2508dfbe3372a0 (patch)
tree59139194fcc463cb4bb6c5a81dca363ea9514e43
parent91a22832b42c814909feeb6dc18f9f098fdd7313 (diff)
downloadmongo-b7f18484664221d7211a32469c2508dfbe3372a0.tar.gz
SERVER-26544: Keep DatabaseCloner active until after the completion callback
-rw-r--r--src/mongo/db/repl/databases_cloner.cpp56
-rw-r--r--src/mongo/db/repl/databases_cloner.h13
2 files changed, 38 insertions, 31 deletions
diff --git a/src/mongo/db/repl/databases_cloner.cpp b/src/mongo/db/repl/databases_cloner.cpp
index 0527a82dfd0..4a4e013de0e 100644
--- a/src/mongo/db/repl/databases_cloner.cpp
+++ b/src/mongo/db/repl/databases_cloner.cpp
@@ -194,8 +194,7 @@ Status DatabasesCloner::startup() {
RemoteCommandRetryScheduler::kAllRetriableErrors));
auto s = _listDBsScheduler->startup();
if (!s.isOK()) {
- _setStatus_inlock(s);
- _failed_inlock(lk);
+ _fail_inlock(&lk, s);
}
return _status;
@@ -215,8 +214,7 @@ void DatabasesCloner::_onListDatabaseFinish(const CommandCallbackArgs& cbd) {
UniqueLock lk(_mutex);
if (!respStatus.isOK()) {
LOG(1) << "listDatabases failed: " << respStatus;
- _setStatus_inlock(respStatus);
- _failed_inlock(lk);
+ _fail_inlock(&lk, respStatus);
return;
}
@@ -300,11 +298,9 @@ void DatabasesCloner::_onListDatabaseFinish(const CommandCallbackArgs& cbd) {
if (_databaseCloners.size() == 0) {
if (_status.isOK()) {
- _active = false;
- lk.unlock();
- _finishFn(_status);
+ _succeed_inlock(&lk);
} else {
- _failed_inlock(lk);
+ _fail_inlock(&lk, _status);
}
}
}
@@ -324,8 +320,7 @@ void DatabasesCloner::_onEachDBCloneFinish(const Status& status, const std::stri
if (!status.isOK()) {
warning() << "database '" << name << "' (" << (_stats.databasesCloned + 1) << " of "
<< _databaseCloners.size() << ") clone failed due to " << status.toString();
- _setStatus_inlock(status);
- _failed_inlock(lk);
+ _fail_inlock(&lk, status);
return;
}
@@ -345,8 +340,7 @@ void DatabasesCloner::_onEachDBCloneFinish(const Status& status, const std::stri
}
if (!adminStatus.isOK()) {
LOG(1) << "Validation failed on 'admin' db due to " << adminStatus;
- _setStatus_inlock(adminStatus);
- _failed_inlock(lk);
+ _fail_inlock(&lk, adminStatus);
return;
}
}
@@ -354,11 +348,7 @@ void DatabasesCloner::_onEachDBCloneFinish(const Status& status, const std::stri
_stats.databasesCloned++;
if (_stats.databasesCloned == _databaseCloners.size()) {
- _active = false;
- // All cloners are done, trigger event.
- LOG(2) << "All database clones finished, calling _finishFn.";
- lk.unlock();
- _finishFn(_status);
+ _succeed_inlock(&lk);
return;
}
@@ -369,25 +359,41 @@ void DatabasesCloner::_onEachDBCloneFinish(const Status& status, const std::stri
warning() << "failed to schedule database '" << name << "' ("
<< (_stats.databasesCloned + 1) << " of " << _databaseCloners.size()
<< ") due to " << startStatus.toString();
- _setStatus_inlock(startStatus);
- _failed_inlock(lk);
+ _fail_inlock(&lk, startStatus);
return;
}
}
-void DatabasesCloner::_failed_inlock(UniqueLock& lk) {
- LOG(3) << "DatabasesCloner::_failed_inlock";
+void DatabasesCloner::_fail_inlock(UniqueLock* lk, Status status) {
+ LOG(3) << "DatabasesCloner::_fail_inlock called";
if (!_active) {
return;
}
- _active = false;
+ _setStatus_inlock(status);
// TODO: shutdown outstanding work, like any cloners active
auto finish = _finishFn;
- lk.unlock();
+ lk->unlock();
+
+ LOG(3) << "DatabasesCloner - calling _finishFn with status: " << _status;
+ finish(status);
+
+ lk->lock();
+ _active = false;
+}
- LOG(3) << "calling _finishFn with status: " << _status;
- _finishFn(_status);
+void DatabasesCloner::_succeed_inlock(UniqueLock* lk) {
+ LOG(3) << "DatabasesCloner::_succeed_inlock called";
+ const auto status = Status::OK();
+ _setStatus_inlock(status);
+ auto finish = _finishFn;
+ lk->unlock();
+
+ LOG(3) << "DatabasesCloner - calling _finishFn with status OK";
+ finish(status);
+
+ lk->lock();
+ _active = false;
}
void DatabasesCloner::_setStatus_inlock(Status s) {
diff --git a/src/mongo/db/repl/databases_cloner.h b/src/mongo/db/repl/databases_cloner.h
index 14d815f9e1a..99748af768f 100644
--- a/src/mongo/db/repl/databases_cloner.h
+++ b/src/mongo/db/repl/databases_cloner.h
@@ -120,10 +120,11 @@ private:
*/
void _setStatus_inlock(Status s);
- /**
- * Will fail the cloner, unlock and call the completion function.
- */
- void _failed_inlock(UniqueLock& lk);
+ /** Will fail the cloner, call the completion function, and become inactive. */
+ void _fail_inlock(UniqueLock* lk, Status s);
+
+ /** Will call the completion function, and become inactive. */
+ void _succeed_inlock(UniqueLock* lk);
/** Called each time a database clone is finished */
void _onEachDBCloneFinish(const Status& status, const std::string& name);
@@ -144,8 +145,8 @@ private:
Status _status{ErrorCodes::NotYetInitialized, ""}; // (M) If it is not OK, we stop everything.
executor::TaskExecutor* _exec; // (R) executor to schedule things with
OldThreadPool* _dbWorkThreadPool; // (R) db worker thread pool for collection cloning.
- HostAndPort _source; // (R) The source to use, until we get an error
- bool _active = false; // (M) false until we start
+ const HostAndPort _source; // (R) The source to use.
+ bool _active = false; // (M) false until we start, and true until finished.
CollectionCloner::ScheduleDbWorkFn _scheduleDbWorkFn; // (M)
const IncludeDbFilterFn _includeDbFn; // (R) function which decides which dbs are cloned.