summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSiyuan Zhou <siyuan.zhou@mongodb.com>2018-08-16 18:58:49 -0400
committerSiyuan Zhou <siyuan.zhou@mongodb.com>2018-08-16 18:58:49 -0400
commit5e461534b339c957d2e6dcf16015949a496a1110 (patch)
treec688bcfa73c9b4eacbb42fa778df3ccf7e65c02c /src
parent57be1f7097ceed41b156a826c541aa276f35dd61 (diff)
downloadmongo-5e461534b339c957d2e6dcf16015949a496a1110.tar.gz
Revert "SERVER-34986 Allow connections to override maxConns based on CIDR range"
This reverts commit 1a643ba65b070c167cdfdd5056c7d2ac79dd5371.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/commands/server_status_servers.cpp11
-rw-r--r--src/mongo/db/db.cpp6
-rw-r--r--src/mongo/db/server_options.h4
-rw-r--r--src/mongo/db/server_options_server_helpers.cpp34
-rw-r--r--src/mongo/embedded/service_entry_point_embedded.cpp6
-rw-r--r--src/mongo/embedded/service_entry_point_embedded.h3
-rw-r--r--src/mongo/s/server.cpp6
-rw-r--r--src/mongo/transport/SConscript14
-rw-r--r--src/mongo/transport/max_conns_override_test.cpp84
-rw-r--r--src/mongo/transport/service_entry_point.h35
-rw-r--r--src/mongo/transport/service_entry_point_impl.cpp71
-rw-r--r--src/mongo/transport/service_entry_point_impl.h14
-rw-r--r--src/mongo/transport/service_executor_adaptive.cpp30
-rw-r--r--src/mongo/transport/service_executor_reserved.cpp212
-rw-r--r--src/mongo/transport/service_executor_reserved.h91
-rw-r--r--src/mongo/transport/service_executor_synchronous.cpp5
-rw-r--r--src/mongo/transport/service_state_machine.cpp8
-rw-r--r--src/mongo/transport/service_state_machine.h7
-rw-r--r--src/mongo/transport/service_state_machine_test.cpp8
-rw-r--r--src/mongo/transport/transport_layer_asio_test.cpp14
-rw-r--r--src/mongo/util/net/sockaddr.cpp2
21 files changed, 73 insertions, 592 deletions
diff --git a/src/mongo/db/commands/server_status_servers.cpp b/src/mongo/db/commands/server_status_servers.cpp
index b7a0eca6895..96007301142 100644
--- a/src/mongo/db/commands/server_status_servers.cpp
+++ b/src/mongo/db/commands/server_status_servers.cpp
@@ -62,7 +62,10 @@ public:
auto serviceEntryPoint = opCtx->getServiceContext()->getServiceEntryPoint();
invariant(serviceEntryPoint);
- serviceEntryPoint->appendStats(&bb);
+ auto stats = serviceEntryPoint->sessionStats();
+ bb.append("current", static_cast<int>(stats.numOpenSessions));
+ bb.append("available", static_cast<int>(stats.numAvailableSessions));
+ bb.append("totalCreated", static_cast<int>(stats.numCreatedSessions));
return bb.obj();
}
@@ -80,10 +83,8 @@ public:
networkCounter.append(b);
appendMessageCompressionStats(&b);
auto executor = opCtx->getServiceContext()->getServiceExecutor();
- if (executor) {
- BSONObjBuilder section(b.subobjStart("serviceExecutorTaskStats"));
- executor->appendStats(&section);
- }
+ if (executor)
+ executor->appendStats(&b);
return b.obj();
}
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index 78ffeb1a511..d89eac1424e 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -645,12 +645,6 @@ ExitCode _initAndListen(int listenPort) {
return EXIT_NET_ERROR;
}
- start = serviceContext->getServiceEntryPoint()->start();
- if (!start.isOK()) {
- error() << "Failed to start the service entry point: " << start;
- return EXIT_NET_ERROR;
- }
-
start = serviceContext->getTransportLayer()->start();
if (!start.isOK()) {
error() << "Failed to start the listener: " << start.toString();
diff --git a/src/mongo/db/server_options.h b/src/mongo/db/server_options.h
index 1a3f3a96c3e..25f7a7ccc42 100644
--- a/src/mongo/db/server_options.h
+++ b/src/mongo/db/server_options.h
@@ -30,8 +30,6 @@
#include "mongo/db/jsobj.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/platform/process_id.h"
-#include "mongo/stdx/variant.h"
-#include "mongo/util/net/cidr.h"
namespace mongo {
@@ -81,8 +79,6 @@ struct ServerGlobalParams {
std::string serviceExecutor;
size_t maxConns = DEFAULT_MAX_CONN; // Maximum number of simultaneous open connections.
- std::vector<stdx::variant<CIDR, std::string>> maxConnsOverride;
- int reservedAdminThreads = 0;
int unixSocketPermissions = DEFAULT_UNIX_PERMS; // permissions for the UNIX domain socket
diff --git a/src/mongo/db/server_options_server_helpers.cpp b/src/mongo/db/server_options_server_helpers.cpp
index bae75613bdd..9342ae91302 100644
--- a/src/mongo/db/server_options_server_helpers.cpp
+++ b/src/mongo/db/server_options_server_helpers.cpp
@@ -120,24 +120,6 @@ Status addGeneralServerOptions(moe::OptionSection* options) {
"net.maxIncomingConnections", "maxConns", moe::Int, maxConnInfoBuilder.str().c_str());
options
- ->addOptionChaining(
- "net.maxIncomingConnectionsOverride",
- "",
- moe::StringVector,
- "CIDR ranges that do not count towards the maxIncomingConnections limit")
- .hidden()
- .setSources(moe::SourceYAMLConfig);
-
- options
- ->addOptionChaining(
- "net.reservedAdminThreads",
- "",
- moe::Int,
- "number of worker threads to reserve for admin and internal connections")
- .hidden()
- .setSources(moe::SourceYAMLConfig);
-
- options
->addOptionChaining("net.transportLayer",
"transportLayer",
moe::String,
@@ -601,22 +583,6 @@ Status storeServerOptions(const moe::Environment& params) {
}
}
- if (params.count("net.maxIncomingConnectionsOverride")) {
- auto ranges = params["net.maxIncomingConnectionsOverride"].as<std::vector<std::string>>();
- for (const auto& range : ranges) {
- auto swr = CIDR::parse(range);
- if (!swr.isOK()) {
- serverGlobalParams.maxConnsOverride.push_back(range);
- } else {
- serverGlobalParams.maxConnsOverride.push_back(std::move(swr.getValue()));
- }
- }
- }
-
- if (params.count("net.reservedAdminThreads")) {
- serverGlobalParams.reservedAdminThreads = params["net.reservedAdminThreads"].as<int>();
- }
-
if (params.count("net.wireObjectCheck")) {
serverGlobalParams.objcheck = params["net.wireObjectCheck"].as<bool>();
}
diff --git a/src/mongo/embedded/service_entry_point_embedded.cpp b/src/mongo/embedded/service_entry_point_embedded.cpp
index a1f6acc7382..3efc2848b80 100644
--- a/src/mongo/embedded/service_entry_point_embedded.cpp
+++ b/src/mongo/embedded/service_entry_point_embedded.cpp
@@ -75,15 +75,11 @@ void ServiceEntryPointEmbedded::startSession(transport::SessionHandle session) {
void ServiceEntryPointEmbedded::endAllSessions(transport::Session::TagMask tags) {}
-Status ServiceEntryPointEmbedded::start() {
- UASSERT_NOT_IMPLEMENTED;
-}
-
bool ServiceEntryPointEmbedded::shutdown(Milliseconds timeout) {
UASSERT_NOT_IMPLEMENTED;
}
-void ServiceEntryPointEmbedded::appendStats(BSONObjBuilder*) const {
+ServiceEntryPoint::Stats ServiceEntryPointEmbedded::sessionStats() const {
UASSERT_NOT_IMPLEMENTED;
}
diff --git a/src/mongo/embedded/service_entry_point_embedded.h b/src/mongo/embedded/service_entry_point_embedded.h
index eea4e48b86e..ba6ed39ce6d 100644
--- a/src/mongo/embedded/service_entry_point_embedded.h
+++ b/src/mongo/embedded/service_entry_point_embedded.h
@@ -45,9 +45,8 @@ public:
void startSession(transport::SessionHandle session) override;
void endAllSessions(transport::Session::TagMask tags) override;
- Status start() override;
bool shutdown(Milliseconds timeout) override;
- void appendStats(BSONObjBuilder* bob) const override;
+ Stats sessionStats() const override;
size_t numOpenSessions() const override;
private:
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index 0ac5e2c17e1..0dc64211d36 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -446,12 +446,6 @@ ExitCode runMongosServer(ServiceContext* serviceContext) {
return EXIT_NET_ERROR;
}
- status = serviceContext->getServiceEntryPoint()->start();
- if (!status.isOK()) {
- error() << "Failed to start the service entry point: " << redact(status);
- return EXIT_NET_ERROR;
- }
-
status = serviceContext->getTransportLayer()->start();
if (!status.isOK()) {
error() << "Failed to start the transport layer: " << redact(status);
diff --git a/src/mongo/transport/SConscript b/src/mongo/transport/SConscript
index 4312fc6f05a..2990aede9ea 100644
--- a/src/mongo/transport/SConscript
+++ b/src/mongo/transport/SConscript
@@ -113,7 +113,6 @@ tlEnv.Library(
target='service_executor',
source=[
'service_executor_adaptive.cpp',
- 'service_executor_reserved.cpp',
'service_executor_synchronous.cpp',
'thread_idle_callback.cpp',
],
@@ -174,19 +173,6 @@ env.Library(
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/transport/message_compressor',
- '$BUILD_DIR/mongo/transport/service_executor',
- ],
-)
-
-env.CppUnitTest(
- target='max_conns_override_test',
- source=[
- 'max_conns_override_test.cpp',
- ],
- LIBDEPS=[
- 'service_entry_point',
- 'transport_layer_mock',
- '$BUILD_DIR/mongo/unittest/unittest'
],
)
diff --git a/src/mongo/transport/max_conns_override_test.cpp b/src/mongo/transport/max_conns_override_test.cpp
deleted file mode 100644
index 195a4c030c6..00000000000
--- a/src/mongo/transport/max_conns_override_test.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright 2018 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects
- * for all of the code used other than as permitted herein. If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so. If you do not
- * wish to do so, delete this exception statement from your version. If you
- * delete this exception statement from all source files in the program,
- * then also delete it in the license file.
- */
-
-#include "mongo/transport/mock_session.h"
-#include "mongo/transport/service_entry_point_impl.h"
-#include "mongo/unittest/unittest.h"
-
-namespace mongo {
-namespace {
-
-using ExemptionVector = std::vector<stdx::variant<CIDR, std::string>>;
-
-template <typename T>
-stdx::variant<CIDR, std::string> makeExemption(T exemption) {
- auto swCIDR = CIDR::parse(exemption);
- if (swCIDR.isOK()) {
- return swCIDR.getValue();
- } else {
- return std::string{exemption};
- }
-}
-
-transport::SessionHandle makeIPSession(StringData ip) {
- return transport::MockSession::create(
- HostAndPort(SockAddr(ip, 27017, AF_INET)), HostAndPort(), nullptr);
-}
-
-transport::SessionHandle makeUNIXSession(StringData path) {
- return transport::MockSession::create(HostAndPort(SockAddr(""_sd, -1, AF_UNIX)),
- HostAndPort(SockAddr(path, -1, AF_UNIX)),
- nullptr);
-}
-
-TEST(MaxConnsOverride, NormalCIDR) {
- ExemptionVector cidrOnly{makeExemption("127.0.0.1"), makeExemption("10.0.0.0/24")};
-
- ASSERT_TRUE(shouldOverrideMaxConns(makeIPSession("127.0.0.1"), cidrOnly));
- ASSERT_TRUE(shouldOverrideMaxConns(makeIPSession("10.0.0.35"), cidrOnly));
- ASSERT_FALSE(shouldOverrideMaxConns(makeIPSession("192.168.0.53"), cidrOnly));
-}
-
-TEST(MaxConnsOverride, UNIXPaths) {
- ExemptionVector mixed{makeExemption("127.0.0.1"),
- makeExemption("10.0.0.0/24"),
- makeExemption("/tmp/mongod.sock")};
-
- ASSERT_TRUE(shouldOverrideMaxConns(makeIPSession("127.0.0.1"), mixed));
- ASSERT_TRUE(shouldOverrideMaxConns(makeIPSession("10.0.0.35"), mixed));
- ASSERT_FALSE(shouldOverrideMaxConns(makeIPSession("192.168.0.53"), mixed));
-#ifdef _WIN32
- ASSERT_FALSE(shouldOverrideMaxConns(makeUNIXSession("/tmp/mongod.sock"), mixed));
-#else
- ASSERT_TRUE(shouldOverrideMaxConns(makeUNIXSession("/tmp/mongod.sock"), mixed));
-#endif
- ASSERT_FALSE(shouldOverrideMaxConns(makeUNIXSession("/tmp/other-mongod.sock"), mixed));
-}
-
-
-} // namespace
-} // namespace
diff --git a/src/mongo/transport/service_entry_point.h b/src/mongo/transport/service_entry_point.h
index abb9c225843..e22135bdaf1 100644
--- a/src/mongo/transport/service_entry_point.h
+++ b/src/mongo/transport/service_entry_point.h
@@ -29,7 +29,6 @@
#pragma once
#include "mongo/base/disallow_copying.h"
-#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/db/dbmessage.h"
#include "mongo/transport/session.h"
@@ -46,6 +45,29 @@ class ServiceEntryPoint {
MONGO_DISALLOW_COPYING(ServiceEntryPoint);
public:
+ /**
+ * Stats for sessions open.
+ */
+ struct Stats {
+ /**
+ * Returns the number of sessions currently open.
+ */
+ size_t numOpenSessions = 0;
+
+ /**
+ * Returns the total number of sessions that have ever been created.
+ */
+ size_t numCreatedSessions = 0;
+
+ /**
+ * Returns the number of available sessions we could still open. Only relevant
+ * when we are operating under a transport::Session limit (for example, in the
+ * legacy implementation, we respect a maximum number of connections). If there
+ * is no session limit, returns std::numeric_limits<int>::max().
+ */
+ size_t numAvailableSessions = 0;
+ };
+
virtual ~ServiceEntryPoint() = default;
/**
@@ -59,19 +81,14 @@ public:
virtual void endAllSessions(transport::Session::TagMask tags) = 0;
/**
- * Starts the service entry point
- */
- virtual Status start() = 0;
-
- /**
* Shuts down the service entry point.
*/
virtual bool shutdown(Milliseconds timeout) = 0;
/**
- * Append high-level stats to a BSONObjBuilder for serverStatus
- */
- virtual void appendStats(BSONObjBuilder* bob) const = 0;
+ * Returns high-level stats about current sessions.
+ */
+ virtual Stats sessionStats() const = 0;
/**
* Returns the number of sessions currently open.
diff --git a/src/mongo/transport/service_entry_point_impl.cpp b/src/mongo/transport/service_entry_point_impl.cpp
index 0113d1bdfc2..adbdc48a6ec 100644
--- a/src/mongo/transport/service_entry_point_impl.cpp
+++ b/src/mongo/transport/service_entry_point_impl.cpp
@@ -46,38 +46,6 @@
#endif
namespace mongo {
-
-bool shouldOverrideMaxConns(const transport::SessionHandle& session,
- const std::vector<stdx::variant<CIDR, std::string>>& exemptions) {
- const auto& remoteAddr = session->remote().sockAddr();
- const auto& localAddr = session->local().sockAddr();
- boost::optional<CIDR> remoteCIDR;
-
- if (remoteAddr && remoteAddr->isIP()) {
- remoteCIDR = uassertStatusOK(CIDR::parse(remoteAddr->getAddr()));
- }
- for (const auto& exemption : exemptions) {
- // If this exemption is a CIDR range, then we check that the remote IP is in the
- // CIDR range
- if ((stdx::holds_alternative<CIDR>(exemption)) && (remoteCIDR)) {
- if (stdx::get<CIDR>(exemption).contains(*remoteCIDR)) {
- return true;
- }
-// Otherwise the exemption is a UNIX path and we should check the local path
-// (the remoteAddr == "anonymous unix socket") against the exemption string
-//
-// On Windows we don't check this at all and only CIDR ranges are supported
-#ifndef _WIN32
- } else if ((stdx::holds_alternative<std::string>(exemption)) && (localAddr) &&
- (localAddr->getAddr() == stdx::get<std::string>(exemption))) {
- return true;
-#endif
- }
- }
-
- return false;
-}
-
ServiceEntryPointImpl::ServiceEntryPointImpl(ServiceContext* svcCtx) : _svcCtx(svcCtx) {
const auto supportedMax = [] {
@@ -103,18 +71,6 @@ ServiceEntryPointImpl::ServiceEntryPointImpl(ServiceContext* svcCtx) : _svcCtx(s
}
_maxNumConnections = supportedMax;
-
- if (serverGlobalParams.reservedAdminThreads) {
- _adminInternalPool = std::make_unique<transport::ServiceExecutorReserved>(
- _svcCtx, "admin/internal connections", serverGlobalParams.reservedAdminThreads);
- }
-}
-
-Status ServiceEntryPointImpl::start() {
- if (_adminInternalPool)
- return _adminInternalPool->start();
- else
- return Status::OK();
}
void ServiceEntryPointImpl::startSession(transport::SessionHandle session) {
@@ -133,16 +89,10 @@ void ServiceEntryPointImpl::startSession(transport::SessionHandle session) {
auto transportMode = _svcCtx->getServiceExecutor()->transportMode();
auto ssm = ServiceStateMachine::create(_svcCtx, session, transportMode);
- auto usingMaxConnOverride = false;
{
stdx::lock_guard<decltype(_sessionsMutex)> lk(_sessionsMutex);
connectionCount = _sessions.size() + 1;
- if (connectionCount > _maxNumConnections) {
- usingMaxConnOverride =
- shouldOverrideMaxConns(session, serverGlobalParams.maxConnsOverride);
- }
-
- if (connectionCount <= _maxNumConnections || usingMaxConnOverride) {
+ if (connectionCount <= _maxNumConnections) {
ssmIt = _sessions.emplace(_sessions.begin(), ssm);
_currentConnections.store(connectionCount);
_createdConnections.addAndFetch(1);
@@ -151,13 +101,11 @@ void ServiceEntryPointImpl::startSession(transport::SessionHandle session) {
// Checking if we successfully added a connection above. Separated from the lock so we don't log
// while holding it.
- if (connectionCount > _maxNumConnections && !usingMaxConnOverride) {
+ if (connectionCount > _maxNumConnections) {
if (!quiet) {
log() << "connection refused because too many open connections: " << connectionCount;
}
return;
- } else if (usingMaxConnOverride && _adminInternalPool) {
- ssm->setServiceExecutor(_adminInternalPool.get());
}
if (!quiet) {
@@ -235,18 +183,15 @@ bool ServiceEntryPointImpl::shutdown(Milliseconds timeout) {
return result;
}
-void ServiceEntryPointImpl::appendStats(BSONObjBuilder* bob) const {
+ServiceEntryPoint::Stats ServiceEntryPointImpl::sessionStats() const {
size_t sessionCount = _currentConnections.load();
- bob->append("current", static_cast<int>(sessionCount));
- bob->append("available", static_cast<int>(_maxNumConnections - sessionCount));
- bob->append("totalCreated", static_cast<int>(_createdConnections.load()));
-
- if (_adminInternalPool) {
- BSONObjBuilder section(bob->subobjStart("adminConnections"));
- _adminInternalPool->appendStats(&section);
- }
+ ServiceEntryPoint::Stats ret;
+ ret.numOpenSessions = sessionCount;
+ ret.numCreatedSessions = _createdConnections.load();
+ ret.numAvailableSessions = _maxNumConnections - sessionCount;
+ return ret;
}
} // namespace mongo
diff --git a/src/mongo/transport/service_entry_point_impl.h b/src/mongo/transport/service_entry_point_impl.h
index 6181885c953..6f47ccedccb 100644
--- a/src/mongo/transport/service_entry_point_impl.h
+++ b/src/mongo/transport/service_entry_point_impl.h
@@ -34,11 +34,8 @@
#include "mongo/stdx/condition_variable.h"
#include "mongo/stdx/list.h"
#include "mongo/stdx/mutex.h"
-#include "mongo/stdx/variant.h"
#include "mongo/transport/service_entry_point.h"
-#include "mongo/transport/service_executor_reserved.h"
#include "mongo/transport/service_state_machine.h"
-#include "mongo/util/net/cidr.h"
namespace mongo {
class ServiceContext;
@@ -64,10 +61,9 @@ public:
void endAllSessions(transport::Session::TagMask tags) final;
- Status start() final;
bool shutdown(Milliseconds timeout) final;
- void appendStats(BSONObjBuilder* bob) const final;
+ Stats sessionStats() const final;
size_t numOpenSessions() const final {
return _currentConnections.load();
@@ -87,14 +83,6 @@ private:
size_t _maxNumConnections{DEFAULT_MAX_CONN};
AtomicWord<size_t> _currentConnections{0};
AtomicWord<size_t> _createdConnections{0};
-
- std::unique_ptr<transport::ServiceExecutorReserved> _adminInternalPool;
};
-/*
- * Returns true if a session with remote/local addresses should be exempted from maxConns
- */
-bool shouldOverrideMaxConns(const transport::SessionHandle& session,
- const std::vector<stdx::variant<CIDR, std::string>>& exemptions);
-
} // namespace mongo
diff --git a/src/mongo/transport/service_executor_adaptive.cpp b/src/mongo/transport/service_executor_adaptive.cpp
index 5d928bd0520..d0014485cc4 100644
--- a/src/mongo/transport/service_executor_adaptive.cpp
+++ b/src/mongo/transport/service_executor_adaptive.cpp
@@ -664,19 +664,20 @@ StringData ServiceExecutorAdaptive::_threadStartedByToString(
void ServiceExecutorAdaptive::appendStats(BSONObjBuilder* bob) const {
stdx::unique_lock<stdx::mutex> lk(_threadsMutex);
- *bob << kExecutorLabel << kExecutorName //
- << kTotalQueued << _totalQueued.load() //
- << kTotalExecuted << _totalExecuted.load() //
- << kThreadsInUse << _threadsInUse.load() //
- << kTotalTimeRunningUs //
- << ticksToMicros(_getThreadTimerTotal(ThreadTimer::kRunning, lk), _tickSource) //
- << kTotalTimeExecutingUs //
- << ticksToMicros(_getThreadTimerTotal(ThreadTimer::kExecuting, lk), _tickSource) //
- << kTotalTimeQueuedUs << ticksToMicros(_totalSpentQueued.load(), _tickSource) //
- << kThreadsRunning << _threadsRunning.load() //
- << kThreadsPending << _threadsPending.load();
-
- BSONObjBuilder threadStartReasons(bob->subobjStart(kThreadReasons));
+ BSONObjBuilder section(bob->subobjStart("serviceExecutorTaskStats"));
+ section << kExecutorLabel << kExecutorName //
+ << kTotalQueued << _totalQueued.load() //
+ << kTotalExecuted << _totalExecuted.load() //
+ << kThreadsInUse << _threadsInUse.load() //
+ << kTotalTimeRunningUs //
+ << ticksToMicros(_getThreadTimerTotal(ThreadTimer::kRunning, lk), _tickSource) //
+ << kTotalTimeExecutingUs //
+ << ticksToMicros(_getThreadTimerTotal(ThreadTimer::kExecuting, lk), _tickSource) //
+ << kTotalTimeQueuedUs << ticksToMicros(_totalSpentQueued.load(), _tickSource) //
+ << kThreadsRunning << _threadsRunning.load() //
+ << kThreadsPending << _threadsPending.load();
+
+ BSONObjBuilder threadStartReasons(section.subobjStart(kThreadReasons));
for (size_t i = 0; i < _threadStartCounters.size(); i++) {
threadStartReasons << _threadStartedByToString(static_cast<ThreadCreationReason>(i))
<< _threadStartCounters[i];
@@ -684,7 +685,7 @@ void ServiceExecutorAdaptive::appendStats(BSONObjBuilder* bob) const {
threadStartReasons.doneFast();
- BSONObjBuilder metricsByTask(bob->subobjStart("metricsByTask"));
+ BSONObjBuilder metricsByTask(section.subobjStart("metricsByTask"));
MetricsArray totalMetrics;
_accumulateAllTaskMetrics(&totalMetrics, lk);
lk.unlock();
@@ -702,6 +703,7 @@ void ServiceExecutorAdaptive::appendStats(BSONObjBuilder* bob) const {
subSection.doneFast();
}
metricsByTask.doneFast();
+ section.doneFast();
}
} // namespace transport
diff --git a/src/mongo/transport/service_executor_reserved.cpp b/src/mongo/transport/service_executor_reserved.cpp
deleted file mode 100644
index 7d8e39c5a7d..00000000000
--- a/src/mongo/transport/service_executor_reserved.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
- * Copyright (C) 2018 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kExecutor;
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/transport/service_executor_reserved.h"
-
-#include "mongo/db/server_parameters.h"
-#include "mongo/stdx/thread.h"
-#include "mongo/transport/service_entry_point_utils.h"
-#include "mongo/transport/service_executor_task_names.h"
-#include "mongo/transport/thread_idle_callback.h"
-#include "mongo/util/log.h"
-#include "mongo/util/processinfo.h"
-
-namespace mongo {
-namespace transport {
-namespace {
-
-// Tasks scheduled with MayRecurse may be called recursively if the recursion depth is below this
-// value.
-MONGO_EXPORT_SERVER_PARAMETER(reservedServiceExecutorRecursionLimit, int, 8);
-
-constexpr auto kThreadsRunning = "threadsRunning"_sd;
-constexpr auto kExecutorLabel = "executor"_sd;
-constexpr auto kExecutorName = "reserved"_sd;
-constexpr auto kReadyThreads = "readyThreads"_sd;
-constexpr auto kStartingThreads = "startingThreads"_sd;
-} // namespace
-
-thread_local std::deque<ServiceExecutor::Task> ServiceExecutorReserved::_localWorkQueue = {};
-thread_local int ServiceExecutorReserved::_localRecursionDepth = 0;
-thread_local int64_t ServiceExecutorReserved::_localThreadIdleCounter = 0;
-
-ServiceExecutorReserved::ServiceExecutorReserved(ServiceContext* ctx,
- std::string name,
- size_t reservedThreads)
- : _name(std::move(name)), _reservedThreads(reservedThreads) {}
-
-Status ServiceExecutorReserved::start() {
- {
- stdx::unique_lock<stdx::mutex> lk(_mutex);
- _stillRunning.store(true);
- _numStartingThreads = _reservedThreads;
- }
-
- for (size_t i = 0; i < _reservedThreads; i++) {
- auto status = _startWorker();
- if (!status.isOK()) {
- return status;
- }
- }
-
- return Status::OK();
-}
-
-Status ServiceExecutorReserved::_startWorker() {
- log() << "Starting new worker thread for " << _name << " service executor";
- return launchServiceWorkerThread([this] {
- stdx::unique_lock<stdx::mutex> lk(_mutex);
- _numRunningWorkerThreads.addAndFetch(1);
- auto numRunningGuard = MakeGuard([&] {
- _numRunningWorkerThreads.subtractAndFetch(1);
- _shutdownCondition.notify_one();
- });
-
- _numStartingThreads--;
- _numReadyThreads++;
-
- while (_stillRunning.load()) {
- _threadWakeup.wait(lk, [&] { return (!_stillRunning.load() || !_readyTasks.empty()); });
-
- if (!_stillRunning.loadRelaxed()) {
- break;
- }
-
- if (_readyTasks.empty()) {
- continue;
- }
-
- auto task = std::move(_readyTasks.front());
- _readyTasks.pop_front();
- _numReadyThreads -= 1;
- bool launchReplacement = false;
- if (_numReadyThreads + _numStartingThreads < _reservedThreads) {
- _numStartingThreads++;
- launchReplacement = true;
- }
-
- lk.unlock();
-
- if (launchReplacement) {
- auto threadStartStatus = _startWorker();
- if (!threadStartStatus.isOK()) {
- warning() << "Could not start new reserve worker thread: " << threadStartStatus;
- }
- }
-
- _localWorkQueue.emplace_back(std::move(task));
- while (!_localWorkQueue.empty() && _stillRunning.loadRelaxed()) {
- _localRecursionDepth = 1;
- _localWorkQueue.front()();
- _localWorkQueue.pop_front();
- }
-
- lk.lock();
- if (_numReadyThreads + 1 > _reservedThreads) {
- break;
- } else {
- _numReadyThreads += 1;
- }
- }
-
- LOG(3) << "Exiting worker thread in " << _name << " service executor";
- });
-}
-
-
-Status ServiceExecutorReserved::shutdown(Milliseconds timeout) {
- LOG(3) << "Shutting down reserved executor";
-
- stdx::unique_lock<stdx::mutex> lock(_mutex);
- _stillRunning.store(false);
- _threadWakeup.notify_all();
-
- bool result = _shutdownCondition.wait_for(lock, timeout.toSystemDuration(), [this]() {
- return _numRunningWorkerThreads.load() == 0;
- });
-
- return result
- ? Status::OK()
- : Status(ErrorCodes::Error::ExceededTimeLimit,
- "reserved executor couldn't shutdown all worker threads within time limit.");
-}
-
-Status ServiceExecutorReserved::schedule(Task task,
- ScheduleFlags flags,
- ServiceExecutorTaskName taskName) {
- if (!_stillRunning.load()) {
- return Status{ErrorCodes::ShutdownInProgress, "Executor is not running"};
- }
-
- if (!_localWorkQueue.empty()) {
- /*
- * In perf testing we found that yielding after running a each request produced
- * at 5% performance boost in microbenchmarks if the number of worker threads
- * was greater than the number of available cores.
- */
- if (flags & ScheduleFlags::kMayYieldBeforeSchedule) {
- if ((_localThreadIdleCounter++ & 0xf) == 0) {
- markThreadIdle();
- }
- }
-
- // Execute task directly (recurse) if allowed by the caller as it produced better
- // performance in testing. Try to limit the amount of recursion so we don't blow up the
- // stack, even though this shouldn't happen with this executor that uses blocking network
- // I/O.
- if ((flags & ScheduleFlags::kMayRecurse) &&
- (_localRecursionDepth < reservedServiceExecutorRecursionLimit.loadRelaxed())) {
- ++_localRecursionDepth;
- task();
- } else {
- _localWorkQueue.emplace_back(std::move(task));
- }
- return Status::OK();
- }
-
- stdx::lock_guard<stdx::mutex> lk(_mutex);
- _readyTasks.push_back(std::move(task));
- _threadWakeup.notify_one();
-
- return Status::OK();
-}
-
-void ServiceExecutorReserved::appendStats(BSONObjBuilder* bob) const {
- stdx::lock_guard<stdx::mutex> lk(_mutex);
- *bob << kExecutorLabel << kExecutorName << kThreadsRunning
- << static_cast<int>(_numRunningWorkerThreads.loadRelaxed()) << kReadyThreads
- << static_cast<int>(_numReadyThreads) << kStartingThreads
- << static_cast<int>(_numStartingThreads);
-}
-
-} // namespace transport
-} // namespace mongo
diff --git a/src/mongo/transport/service_executor_reserved.h b/src/mongo/transport/service_executor_reserved.h
deleted file mode 100644
index 235e86e5930..00000000000
--- a/src/mongo/transport/service_executor_reserved.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * Copyright (C) 2018 MongoDB Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the GNU Affero General Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#pragma once
-
-#include <deque>
-
-#include "mongo/base/status.h"
-#include "mongo/platform/atomic_word.h"
-#include "mongo/stdx/condition_variable.h"
-#include "mongo/stdx/mutex.h"
-#include "mongo/transport/service_executor.h"
-#include "mongo/transport/service_executor_task_names.h"
-
-namespace mongo {
-namespace transport {
-
-/**
- * The reserved service executor emulates a thread per connection.
- * Each connection has its own worker thread where jobs get scheduled.
- *
- * The executor will start reservedThreads on start, and create a new thread every time it
- * starts a new thread, ensuring there are always reservedThreads available for work - this
- * means that even when you hit the NPROC ulimit, there will still be threads ready to
- * accept work. When threads exit, they will go back to waiting for work if there are fewer
- * than reservedThreads available.
- */
-class ServiceExecutorReserved final : public ServiceExecutor {
-public:
- explicit ServiceExecutorReserved(ServiceContext* ctx, std::string name, size_t reservedThreads);
-
- Status start() override;
- Status shutdown(Milliseconds timeout) override;
- Status schedule(Task task, ScheduleFlags flags, ServiceExecutorTaskName taskName) override;
-
- Mode transportMode() const override {
- return Mode::kSynchronous;
- }
-
- void appendStats(BSONObjBuilder* bob) const override;
-
-private:
- Status _startWorker();
-
- static thread_local std::deque<Task> _localWorkQueue;
- static thread_local int _localRecursionDepth;
- static thread_local int64_t _localThreadIdleCounter;
-
- AtomicBool _stillRunning{false};
-
- mutable stdx::mutex _mutex;
- stdx::condition_variable _threadWakeup;
- stdx::condition_variable _shutdownCondition;
-
- std::deque<Task> _readyTasks;
-
- AtomicUInt32 _numRunningWorkerThreads{0};
- size_t _numReadyThreads{0};
- size_t _numStartingThreads{0};
-
- const std::string _name;
- const size_t _reservedThreads;
-};
-
-} // namespace transport
-} // namespace mongo
diff --git a/src/mongo/transport/service_executor_synchronous.cpp b/src/mongo/transport/service_executor_synchronous.cpp
index 7b1b6509537..a3bd83a0f06 100644
--- a/src/mongo/transport/service_executor_synchronous.cpp
+++ b/src/mongo/transport/service_executor_synchronous.cpp
@@ -142,8 +142,9 @@ Status ServiceExecutorSynchronous::schedule(Task task,
}
void ServiceExecutorSynchronous::appendStats(BSONObjBuilder* bob) const {
- *bob << kExecutorLabel << kExecutorName << kThreadsRunning
- << static_cast<int>(_numRunningWorkerThreads.loadRelaxed());
+ BSONObjBuilder section(bob->subobjStart("serviceExecutorTaskStats"));
+ section << kExecutorLabel << kExecutorName << kThreadsRunning
+ << static_cast<int>(_numRunningWorkerThreads.loadRelaxed());
}
} // namespace transport
diff --git a/src/mongo/transport/service_state_machine.cpp b/src/mongo/transport/service_state_machine.cpp
index 83eb411c7b6..0ecbfcca6d1 100644
--- a/src/mongo/transport/service_state_machine.cpp
+++ b/src/mongo/transport/service_state_machine.cpp
@@ -226,7 +226,6 @@ ServiceStateMachine::ServiceStateMachine(ServiceContext* svcContext,
_sep{svcContext->getServiceEntryPoint()},
_transportMode(transportMode),
_serviceContext(svcContext),
- _serviceExecutor(_serviceContext->getServiceExecutor()),
_sessionHandle(session),
_threadName{str::stream() << "conn" << _session()->id()},
_dbClient{svcContext->makeClient(_threadName, std::move(session))},
@@ -470,10 +469,6 @@ void ServiceStateMachine::start(Ownership ownershipModel) {
ownershipModel);
}
-void ServiceStateMachine::setServiceExecutor(ServiceExecutor* executor) {
- _serviceExecutor = executor;
-}
-
void ServiceStateMachine::_scheduleNextWithGuard(ThreadGuard guard,
transport::ServiceExecutor::ScheduleFlags flags,
transport::ServiceExecutorTaskName taskName,
@@ -485,7 +480,8 @@ void ServiceStateMachine::_scheduleNextWithGuard(ThreadGuard guard,
ssm->_runNextInGuard(std::move(guard));
};
guard.release();
- Status status = _serviceExecutor->schedule(std::move(func), flags, taskName);
+ Status status =
+ _serviceContext->getServiceExecutor()->schedule(std::move(func), flags, taskName);
if (status.isOK()) {
return;
}
diff --git a/src/mongo/transport/service_state_machine.h b/src/mongo/transport/service_state_machine.h
index ee54eb99cc8..bac5417dd67 100644
--- a/src/mongo/transport/service_state_machine.h
+++ b/src/mongo/transport/service_state_machine.h
@@ -126,12 +126,6 @@ public:
void start(Ownership ownershipModel);
/*
- * Set the executor to be used for the next call to runNext(). This allows switching between
- * thread models after the SSM has started.
- */
- void setServiceExecutor(transport::ServiceExecutor* executor);
-
- /*
* Gets the current state of connection for testing/diagnostic purposes.
*/
State state();
@@ -225,7 +219,6 @@ private:
transport::Mode _transportMode;
ServiceContext* const _serviceContext;
- transport::ServiceExecutor* _serviceExecutor;
transport::SessionHandle _sessionHandle;
const std::string _threadName;
diff --git a/src/mongo/transport/service_state_machine_test.cpp b/src/mongo/transport/service_state_machine_test.cpp
index 6d37d63b165..e29c33627a6 100644
--- a/src/mongo/transport/service_state_machine_test.cpp
+++ b/src/mongo/transport/service_state_machine_test.cpp
@@ -84,15 +84,13 @@ public:
void endAllSessions(transport::Session::TagMask tags) override {}
- Status start() override {
- return Status::OK();
- }
-
bool shutdown(Milliseconds timeout) override {
return true;
}
- void appendStats(BSONObjBuilder*) const override {}
+ Stats sessionStats() const override {
+ return {};
+ }
size_t numOpenSessions() const override {
return 0ULL;
diff --git a/src/mongo/transport/transport_layer_asio_test.cpp b/src/mongo/transport/transport_layer_asio_test.cpp
index abf49b48690..b9ff5580dc4 100644
--- a/src/mongo/transport/transport_layer_asio_test.cpp
+++ b/src/mongo/transport/transport_layer_asio_test.cpp
@@ -63,15 +63,13 @@ public:
old_sessions.clear();
}
- Status start() override {
- return Status::OK();
- }
-
bool shutdown(Milliseconds timeout) override {
return true;
}
- void appendStats(BSONObjBuilder*) const override {}
+ Stats sessionStats() const override {
+ return {};
+ }
size_t numOpenSessions() const override {
stdx::unique_lock<stdx::mutex> lock(_mutex);
@@ -171,12 +169,10 @@ public:
return true;
}
- Status start() override {
- return Status::OK();
+ Stats sessionStats() const override {
+ return {};
}
- void appendStats(BSONObjBuilder*) const override {}
-
size_t numOpenSessions() const override {
return 0;
}
diff --git a/src/mongo/util/net/sockaddr.cpp b/src/mongo/util/net/sockaddr.cpp
index 00470af3ea6..0cf024b6f44 100644
--- a/src/mongo/util/net/sockaddr.cpp
+++ b/src/mongo/util/net/sockaddr.cpp
@@ -133,7 +133,7 @@ SockAddr::SockAddr(StringData target, int port, sa_family_t familyHint)
_hostOrIp = "127.0.0.1";
}
- if (mongoutils::str::contains(_hostOrIp, '/') || familyHint == AF_UNIX) {
+ if (mongoutils::str::contains(_hostOrIp, '/')) {
initUnixDomainSocket(_hostOrIp, port);
return;
}