summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMisha Tyulenev <misha@mongodb.com>2016-11-09 10:38:56 -0500
committerMisha Tyulenev <misha@mongodb.com>2016-11-09 10:46:12 -0500
commit9abe003a4307295f4a3785527ac7ff633383b39a (patch)
treea470f5649776b3232fcca7a96b4f3f460e4643fa
parente20c8f98eb6e060cc6f46ee60a2683ea7043f1a1 (diff)
downloadmongo-9abe003a4307295f4a3785527ac7ff633383b39a.tar.gz
SERVER-26799 do not refresh if RSM is removed from a RSM manager
-rw-r--r--src/mongo/base/error_codes.err1
-rw-r--r--src/mongo/client/replica_set_monitor.cpp14
-rw-r--r--src/mongo/client/replica_set_monitor.h7
-rw-r--r--src/mongo/client/replica_set_monitor_manager.cpp3
4 files changed, 25 insertions, 0 deletions
diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err
index c21b810d481..3eb5740d743 100644
--- a/src/mongo/base/error_codes.err
+++ b/src/mongo/base/error_codes.err
@@ -196,6 +196,7 @@ error_code("BalancerInterrupted", 194)
error_code("ViewPipelineMaxSizeExceeded", 195)
error_code("InvalidIndexSpecificationOption", 197)
error_code("OBSOLETE_ReceivedOpReplyMessage", 198)
+error_code("ReplicaSetMonitorRemoved", 199)
# Non-sequential error codes (for compatibility only)
error_code("SocketException", 9001)
diff --git a/src/mongo/client/replica_set_monitor.cpp b/src/mongo/client/replica_set_monitor.cpp
index d27cd68d162..c64c4280424 100644
--- a/src/mongo/client/replica_set_monitor.cpp
+++ b/src/mongo/client/replica_set_monitor.cpp
@@ -233,6 +233,11 @@ void ReplicaSetMonitor::_refresh(const CallbackArgs& cbArgs) {
{
// reschedule itself
invariant(_executor);
+ if (_isRemovedFromManager.load()) { // already removed so no need to refresh
+ LOG(1) << "Stopping refresh for replica set " << getName() << " because its removed";
+ return;
+ }
+
stdx::lock_guard<stdx::mutex> lk(_mutex);
std::weak_ptr<ReplicaSetMonitor> that(shared_from_this());
auto status = _executor->scheduleWorkAt(_executor->now() + kRefreshPeriod,
@@ -260,6 +265,11 @@ void ReplicaSetMonitor::_refresh(const CallbackArgs& cbArgs) {
StatusWith<HostAndPort> ReplicaSetMonitor::getHostOrRefresh(const ReadPreferenceSetting& criteria,
Milliseconds maxWait) {
+ if (_isRemovedFromManager.load()) {
+ return Status(ErrorCodes::ReplicaSetMonitorRemoved,
+ str::stream() << "ReplicaSetMonitor for set " << getName() << " is removed");
+ }
+
{
// Fast path, for the failure-free case
stdx::lock_guard<stdx::mutex> lk(_state->mutex);
@@ -453,6 +463,10 @@ bool ReplicaSetMonitor::isKnownToHaveGoodPrimary() const {
return false;
}
+void ReplicaSetMonitor::markAsRemoved() {
+ _isRemovedFromManager.store(true);
+}
+
Refresher::Refresher(const SetStatePtr& setState)
: _set(setState), _scan(setState->currentScan), _startedNewScan(false) {
if (_scan)
diff --git a/src/mongo/client/replica_set_monitor.h b/src/mongo/client/replica_set_monitor.h
index e83f41e4556..7b8f602cbce 100644
--- a/src/mongo/client/replica_set_monitor.h
+++ b/src/mongo/client/replica_set_monitor.h
@@ -36,6 +36,7 @@
#include "mongo/base/disallow_copying.h"
#include "mongo/base/string_data.h"
#include "mongo/executor/task_executor.h"
+#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/functional.h"
#include "mongo/util/net/hostandport.h"
#include "mongo/util/time_support.h"
@@ -164,6 +165,11 @@ public:
bool isKnownToHaveGoodPrimary() const;
/**
+ * Marks the instance as removed to exit refresh sooner.
+ */
+ void markAsRemoved();
+
+ /**
* Creates a new ReplicaSetMonitor, if it doesn't already exist.
*/
static std::shared_ptr<ReplicaSetMonitor> createIfNeeded(const std::string& name,
@@ -262,6 +268,7 @@ private:
const SetStatePtr _state;
executor::TaskExecutor* _executor;
+ AtomicBool _isRemovedFromManager{false};
};
diff --git a/src/mongo/client/replica_set_monitor_manager.cpp b/src/mongo/client/replica_set_monitor_manager.cpp
index 555d8174b3f..6a463dbf29e 100644
--- a/src/mongo/client/replica_set_monitor_manager.cpp
+++ b/src/mongo/client/replica_set_monitor_manager.cpp
@@ -124,6 +124,9 @@ void ReplicaSetMonitorManager::removeMonitor(StringData setName) {
stdx::lock_guard<stdx::mutex> lk(_mutex);
ReplicaSetMonitorsMap::const_iterator it = _monitors.find(setName);
if (it != _monitors.end()) {
+ if (auto monitor = it->second.lock()) {
+ monitor->markAsRemoved();
+ }
_monitors.erase(it);
log() << "Removed ReplicaSetMonitor for replica set " << setName;
}