summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorWaley Chen <waleycz@gmail.com>2016-04-15 02:58:33 -0400
committerWaley Chen <waleycz@gmail.com>2016-04-15 02:58:33 -0400
commitc2041cd99ea8ff1aa8bfba2d4bcb3bbd2ea7932c (patch)
tree1a7b9828a9883d470c5f85322371eff738279731 /src/mongo
parent7850673c0303b740ecdd2b8718d8c745e25884b3 (diff)
downloadmongo-c2041cd99ea8ff1aa8bfba2d4bcb3bbd2ea7932c.tar.gz
SERVER-23243 Extract time-keeping from Listener
BackgroundThreadClockSource & FastClockSourceFactory
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/SConscript1
-rw-r--r--src/mongo/db/service_context.cpp8
-rw-r--r--src/mongo/db/service_context.h28
-rw-r--r--src/mongo/util/SConscript22
-rw-r--r--src/mongo/util/background_thread_clock_source.cpp80
-rw-r--r--src/mongo/util/background_thread_clock_source.h73
-rw-r--r--src/mongo/util/background_thread_clock_source_test.cpp67
-rw-r--r--src/mongo/util/fast_clock_source_factory.cpp49
-rw-r--r--src/mongo/util/fast_clock_source_factory.h50
9 files changed, 377 insertions, 1 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index 0b65fb199a5..4dfa9e23441 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -250,6 +250,7 @@ mongodLibDeps = [
"db/repl/storage_interface_impl",
"executor/network_interface_factory",
's/commands/shared_cluster_commands',
+ "util/clock_sources",
"util/ntservice",
]
diff --git a/src/mongo/db/service_context.cpp b/src/mongo/db/service_context.cpp
index 075fafd7360..5bcf655cb93 100644
--- a/src/mongo/db/service_context.cpp
+++ b/src/mongo/db/service_context.cpp
@@ -147,6 +147,10 @@ TickSource* ServiceContext::getTickSource() const {
return _tickSource.get();
}
+ClockSource* ServiceContext::getFastClockSource() const {
+ return _fastClockSource.get();
+}
+
ClockSource* ServiceContext::getPreciseClockSource() const {
return _preciseClockSource.get();
}
@@ -155,6 +159,10 @@ void ServiceContext::setTickSource(std::unique_ptr<TickSource> newSource) {
_tickSource = std::move(newSource);
}
+void ServiceContext::setFastClockSource(std::unique_ptr<ClockSource> newSource) {
+ _fastClockSource = std::move(newSource);
+}
+
void ServiceContext::setPreciseClockSource(std::unique_ptr<ClockSource> newSource) {
_preciseClockSource = std::move(newSource);
}
diff --git a/src/mongo/db/service_context.h b/src/mongo/db/service_context.h
index 4a5b54bb6c7..6bf652eec43 100644
--- a/src/mongo/db/service_context.h
+++ b/src/mongo/db/service_context.h
@@ -35,8 +35,8 @@
#include "mongo/db/storage/storage_engine.h"
#include "mongo/platform/unordered_set.h"
#include "mongo/stdx/functional.h"
-#include "mongo/util/decorable.h"
#include "mongo/util/clock_source.h"
+#include "mongo/util/decorable.h"
#include "mongo/util/tick_source.h"
namespace mongo {
@@ -312,6 +312,16 @@ public:
* Returns the tick/clock source set in this context.
*/
TickSource* getTickSource() const;
+
+ /**
+ * Get a ClockSource implementation that may be less precise than the _preciseClockSource but
+ * may be cheaper to call.
+ */
+ ClockSource* getFastClockSource() const;
+
+ /**
+ * Get a ClockSource implementation that is very precise but may be expensive to call.
+ */
ClockSource* getPreciseClockSource() const;
/**
@@ -321,6 +331,12 @@ public:
void setTickSource(std::unique_ptr<TickSource> newSource);
/**
+ * Call this method with a ClockSource implementation that may be less precise than
+ * the _preciseClockSource but may be cheaper to call.
+ */
+ void setFastClockSource(std::unique_ptr<ClockSource> newSource);
+
+ /**
* Call this method with a ClockSource implementation that is very precise but
* may be expensive to call.
*/
@@ -348,6 +364,16 @@ private:
ClientSet _clients;
std::unique_ptr<TickSource> _tickSource;
+
+ /**
+ * A ClockSource implementation that may be less precise than the _preciseClockSource but
+ * may be cheaper to call.
+ */
+ std::unique_ptr<ClockSource> _fastClockSource;
+
+ /**
+ * A ClockSource implementation that is very precise but may be expensive to call.
+ */
std::unique_ptr<ClockSource> _preciseClockSource;
};
diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript
index 60cf152be60..e03426cfdb3 100644
--- a/src/mongo/util/SConscript
+++ b/src/mongo/util/SConscript
@@ -293,6 +293,28 @@ env.Library(
],
)
+env.Library(
+ target='clock_sources',
+ source=[
+ 'background_thread_clock_source.cpp',
+ 'fast_clock_source_factory.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
+ ],
+)
+
+env.CppUnitTest(
+ target='background_thread_clock_source_test',
+ source=[
+ 'background_thread_clock_source_test.cpp',
+ ],
+ LIBDEPS=[
+ 'clock_source_mock',
+ 'clock_sources',
+ ],
+)
+
if env.TargetOSIs('windows'):
env.CppUnitTest(
target='ntservice_test',
diff --git a/src/mongo/util/background_thread_clock_source.cpp b/src/mongo/util/background_thread_clock_source.cpp
new file mode 100644
index 00000000000..96dececff9c
--- /dev/null
+++ b/src/mongo/util/background_thread_clock_source.cpp
@@ -0,0 +1,80 @@
+/**
+ * Copyright (C) 2016 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/platform/basic.h"
+
+#include "mongo/util/background_thread_clock_source.h"
+
+#include <chrono>
+#include <thread>
+
+#include "mongo/stdx/memory.h"
+#include "mongo/stdx/thread.h"
+#include "mongo/util/time_support.h"
+
+namespace mongo {
+
+BackgroundThreadClockSource::BackgroundThreadClockSource(std::unique_ptr<ClockSource> clockSource,
+ Milliseconds granularity)
+ : _clockSource(std::move(clockSource)), _granularity(granularity), _shutdownTimer(false) {
+ _updateCurrent();
+ _startTimerThread();
+}
+
+BackgroundThreadClockSource::~BackgroundThreadClockSource() {
+ {
+ stdx::unique_lock<stdx::mutex> lock(_mutex);
+ _shutdownTimer = true;
+ _condition.notify_one();
+ }
+
+ _timer.join();
+}
+
+Date_t BackgroundThreadClockSource::now() {
+ return Date_t::fromMillisSinceEpoch(_current.load());
+}
+
+void BackgroundThreadClockSource::_startTimerThread() {
+ // Start the background thread that repeatedly sleeps for the specified duration of milliseconds
+ // and wakes up to store the current time.
+ _timer = stdx::thread([&]() {
+ stdx::unique_lock<stdx::mutex> lock(_mutex);
+ while (!_shutdownTimer) {
+ if (_condition.wait_for(lock, _granularity) == stdx::cv_status::timeout) {
+ _updateCurrent();
+ }
+ }
+ });
+}
+
+void BackgroundThreadClockSource::_updateCurrent() {
+ _current.store(_clockSource->now().toMillisSinceEpoch());
+}
+
+} // namespace mongo
diff --git a/src/mongo/util/background_thread_clock_source.h b/src/mongo/util/background_thread_clock_source.h
new file mode 100644
index 00000000000..eecd75c0f4c
--- /dev/null
+++ b/src/mongo/util/background_thread_clock_source.h
@@ -0,0 +1,73 @@
+/**
+ * Copyright (C) 2016 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 <chrono>
+#include <thread>
+
+#include "mongo/base/disallow_copying.h"
+#include "mongo/platform/atomic_word.h"
+#include "mongo/util/clock_source.h"
+#include "mongo/util/time_support.h"
+#include "mongo/stdx/condition_variable.h"
+#include "mongo/stdx/memory.h"
+#include "mongo/stdx/mutex.h"
+#include "mongo/stdx/thread.h"
+
+namespace mongo {
+
+/**
+ * A clock source that uses a periodic timer to build a low-resolution, fast-to-read clock.
+ * Essentially uses a background thread that repeatedly sleeps for X amount of milliseconds
+ * and wakes up to store the current time.
+ */
+class BackgroundThreadClockSource final : public ClockSource {
+ MONGO_DISALLOW_COPYING(BackgroundThreadClockSource);
+
+public:
+ BackgroundThreadClockSource(std::unique_ptr<ClockSource> clockSource, Milliseconds granularity);
+ ~BackgroundThreadClockSource() override;
+ Date_t now() override;
+
+private:
+ void _startTimerThread();
+ void _updateCurrent();
+
+ const std::unique_ptr<ClockSource> _clockSource;
+ AtomicInt64 _current;
+
+ const Milliseconds _granularity;
+
+ stdx::mutex _mutex;
+ stdx::condition_variable _condition;
+ bool _shutdownTimer;
+ stdx::thread _timer;
+};
+
+} // namespace mongo
diff --git a/src/mongo/util/background_thread_clock_source_test.cpp b/src/mongo/util/background_thread_clock_source_test.cpp
new file mode 100644
index 00000000000..5bd82e4186e
--- /dev/null
+++ b/src/mongo/util/background_thread_clock_source_test.cpp
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 2016 10gen 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/platform/basic.h"
+
+#include "mongo/stdx/memory.h"
+#include "mongo/unittest/unittest.h"
+#include "mongo/util/background_thread_clock_source.h"
+#include "mongo/util/clock_source.h"
+#include "mongo/util/clock_source_mock.h"
+#include "mongo/util/time_support.h"
+
+namespace {
+
+using namespace mongo;
+
+TEST(BackgroundThreadClockSource, CreateAndTerminate) {
+ auto clockSource = stdx::make_unique<ClockSourceMock>();
+ auto btClockSource =
+ stdx::make_unique<BackgroundThreadClockSource>(std::move(clockSource), Milliseconds(1));
+ btClockSource.reset(); // destroys the clock source
+
+ clockSource = stdx::make_unique<ClockSourceMock>();
+ btClockSource =
+ stdx::make_unique<BackgroundThreadClockSource>(std::move(clockSource), Hours(48));
+ btClockSource.reset(); // destroys the clock source
+}
+
+TEST(BackgroundThreadClockSource, TimeKeeping) {
+ auto clockSource = stdx::make_unique<ClockSourceMock>();
+ ClockSourceMock* clockSourceMock = clockSource.get();
+
+ auto btClockSource =
+ stdx::make_unique<BackgroundThreadClockSource>(std::move(clockSource), Milliseconds(1));
+ ASSERT_EQUALS(btClockSource->now(), clockSourceMock->now());
+
+ clockSourceMock->advance(Milliseconds(100));
+ sleepFor(Milliseconds(10)); // give the btClockSource opportunity to read the new time
+ ASSERT_EQUALS(btClockSource->now(), clockSourceMock->now());
+}
+
+} // namespace
diff --git a/src/mongo/util/fast_clock_source_factory.cpp b/src/mongo/util/fast_clock_source_factory.cpp
new file mode 100644
index 00000000000..f0b7da62c09
--- /dev/null
+++ b/src/mongo/util/fast_clock_source_factory.cpp
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2016 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/platform/basic.h"
+
+#include "mongo/util/fast_clock_source_factory.h"
+
+#include <memory>
+
+#include "mongo/stdx/memory.h"
+#include "mongo/util/background_thread_clock_source.h"
+#include "mongo/util/system_clock_source.h"
+
+namespace mongo {
+
+std::unique_ptr<ClockSource> FastClockSourceFactory::create(Milliseconds granularity) {
+ // TODO: Create the fastest to read wall clock available on the system.
+ // For now, assume there is no built-in fast wall clock so instead
+ // create a background-thread-based timer.
+ return stdx::make_unique<BackgroundThreadClockSource>(
+ std::move(stdx::make_unique<SystemClockSource>()), granularity);
+}
+
+} // namespace mongo
diff --git a/src/mongo/util/fast_clock_source_factory.h b/src/mongo/util/fast_clock_source_factory.h
new file mode 100644
index 00000000000..6d6de15d47f
--- /dev/null
+++ b/src/mongo/util/fast_clock_source_factory.h
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2016 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 <memory>
+
+#include "mongo/util/time_support.h"
+
+namespace mongo {
+
+class ClockSource;
+
+// Factory that creates the fastest to read wall clock available on the system.
+class FastClockSourceFactory {
+public:
+ /**
+ * Creates the fastest to read wall clock available on the system.
+ * However, on systems with no built-in fast wall clock,
+ * creates a background-thread-based clock implementation.
+ */
+ static std::unique_ptr<ClockSource> create(Milliseconds granularity);
+};
+
+} // namespace mongo