summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCharlie Swanson <charlie.swanson@mongodb.com>2017-06-12 16:41:54 -0400
committerCharlie Swanson <charlie.swanson@mongodb.com>2017-06-14 11:40:35 -0400
commitad473bb00cddb5e6ec83589fd4a7ebe780d7ca7d (patch)
tree2f45ed27db28e19d9d6a04027988fa1ad6a21504 /src
parentd0b402cb0a01d716cad5a7f759c55cda4a4d5c1f (diff)
downloadmongo-ad473bb00cddb5e6ec83589fd4a7ebe780d7ca7d.tar.gz
SERVER-29207 Add DateTimeSupport to ServiceContext
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/pipeline/SConscript1
-rw-r--r--src/mongo/db/query/SConscript2
-rw-r--r--src/mongo/db/query/datetime/SConscript29
-rw-r--r--src/mongo/db/query/datetime/date_time_support.cpp111
-rw-r--r--src/mongo/db/query/datetime/date_time_support.h98
-rw-r--r--src/mongo/db/query/datetime/init_timezone_data.cpp65
-rw-r--r--src/mongo/db/server_options.h5
-rw-r--r--src/mongo/db/server_options_helpers.cpp9
8 files changed, 318 insertions, 2 deletions
diff --git a/src/mongo/db/pipeline/SConscript b/src/mongo/db/pipeline/SConscript
index 6c1ee4f7772..4f5966dc92e 100644
--- a/src/mongo/db/pipeline/SConscript
+++ b/src/mongo/db/pipeline/SConscript
@@ -178,6 +178,7 @@ env.Library(
'dependencies',
'document_value',
'expression_context',
+ '$BUILD_DIR/mongo/db/query/datetime/date_time_support',
'$BUILD_DIR/mongo/util/summation',
]
)
diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript
index a21ce9d1801..7c42568f7c0 100644
--- a/src/mongo/db/query/SConscript
+++ b/src/mongo/db/query/SConscript
@@ -7,6 +7,7 @@ env = env.Clone()
env.SConscript(
dirs=[
"collation",
+ "datetime",
],
exports=[
'env'
@@ -106,6 +107,7 @@ env.Library(
"$BUILD_DIR/mongo/base",
"$BUILD_DIR/mongo/util/fail_point",
"collation/collator_icu",
+ "datetime/init_timezone_data",
"explain_options",
"query_planner",
"query_request",
diff --git a/src/mongo/db/query/datetime/SConscript b/src/mongo/db/query/datetime/SConscript
new file mode 100644
index 00000000000..84216ac941e
--- /dev/null
+++ b/src/mongo/db/query/datetime/SConscript
@@ -0,0 +1,29 @@
+# -*- mode: python -*-
+
+Import('env')
+
+env = env.Clone()
+
+timeZoneEnv = env.Clone()
+timeZoneEnv.InjectThirdPartyIncludePaths(libraries=['timelib'])
+timeZoneEnv.Library(
+ target='date_time_support',
+ source=[
+ 'date_time_support.cpp'
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/db/service_context',
+ '$BUILD_DIR/third_party/shim_timelib',
+ ]
+)
+
+timeZoneEnv.Library(
+ target='init_timezone_data',
+ source=[
+ 'init_timezone_data.cpp'
+ ],
+ LIBDEPS=[
+ 'date_time_support',
+ '$BUILD_DIR/third_party/shim_timelib',
+ ]
+)
diff --git a/src/mongo/db/query/datetime/date_time_support.cpp b/src/mongo/db/query/datetime/date_time_support.cpp
new file mode 100644
index 00000000000..eb169cff9be
--- /dev/null
+++ b/src/mongo/db/query/datetime/date_time_support.cpp
@@ -0,0 +1,111 @@
+/**
+ * Copyright (C) 2017 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::kDefault
+
+#include "mongo/platform/basic.h"
+
+#include <memory>
+#include <timelib.h>
+
+#include "mongo/db/query/datetime/date_time_support.h"
+
+#include "mongo/base/init.h"
+#include "mongo/db/server_options.h"
+#include "mongo/db/service_context.h"
+#include "mongo/stdx/memory.h"
+#include "mongo/util/assert_util.h"
+#include "mongo/util/duration.h"
+#include "mongo/util/log.h"
+#include "mongo/util/mongoutils/str.h"
+
+namespace mongo {
+
+namespace {
+const auto getDateTimeSupport =
+ ServiceContext::declareDecoration<std::unique_ptr<DateTimeSupport>>();
+} // namespace
+
+const DateTimeSupport* DateTimeSupport::get(ServiceContext* serviceContext) {
+ invariant(getDateTimeSupport(serviceContext));
+ return getDateTimeSupport(serviceContext).get();
+}
+
+void DateTimeSupport::set(ServiceContext* serviceContext,
+ std::unique_ptr<DateTimeSupport> dateTimeSupport) {
+ getDateTimeSupport(serviceContext) = std::move(dateTimeSupport);
+}
+
+DateTimeSupport::DateTimeSupport() {
+ loadTimeZoneInfo({const_cast<timelib_tzdb*>(timelib_builtin_db()), TimeZoneDBDeleter()});
+}
+
+DateTimeSupport::DateTimeSupport(
+ std::unique_ptr<timelib_tzdb, TimeZoneDBDeleter> timeZoneDatabase) {
+ loadTimeZoneInfo(std::move(timeZoneDatabase));
+}
+
+void DateTimeSupport::TimeZoneDBDeleter::operator()(timelib_tzdb* timeZoneDatabase) {
+ if (timeZoneDatabase != timelib_builtin_db()) {
+ timelib_zoneinfo_dtor(timeZoneDatabase);
+ }
+}
+
+DateTimeSupport::~DateTimeSupport() {
+ for (auto&& entry : _timeZones) {
+ timelib_tzinfo_dtor(entry.second);
+ }
+}
+
+void DateTimeSupport::loadTimeZoneInfo(
+ std::unique_ptr<timelib_tzdb, TimeZoneDBDeleter> timeZoneDatabase) {
+ invariant(timeZoneDatabase);
+ _timeZoneDatabase = std::move(timeZoneDatabase);
+ int nTimeZones;
+ auto timezone_identifier_list =
+ timelib_timezone_identifiers_list(_timeZoneDatabase.get(), &nTimeZones);
+ for (int i = 0; i < nTimeZones; ++i) {
+ auto entry = timezone_identifier_list[i];
+ int errorCode = TIMELIB_ERROR_NO_ERROR;
+ auto tzInfo = timelib_parse_tzfile(entry.id, _timeZoneDatabase.get(), &errorCode);
+ if (!tzInfo) {
+ invariant(errorCode != TIMELIB_ERROR_NO_ERROR);
+ fassertFailedWithStatusNoTrace(
+ 40475,
+ {ErrorCodes::FailedToParse,
+ str::stream() << "failed to parse time zone file for time zone identifier \""
+ << entry.id
+ << "\": "
+ << timelib_get_error_message(errorCode)});
+ }
+ invariant(errorCode == TIMELIB_ERROR_NO_ERROR);
+ _timeZones[entry.id] = tzInfo;
+ }
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/query/datetime/date_time_support.h b/src/mongo/db/query/datetime/date_time_support.h
new file mode 100644
index 00000000000..1c4540bbcbe
--- /dev/null
+++ b/src/mongo/db/query/datetime/date_time_support.h
@@ -0,0 +1,98 @@
+/**
+ * Copyright (C) 2017 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/base/disallow_copying.h"
+#include "mongo/util/string_map.h"
+#include "mongo/util/time_support.h"
+
+namespace mongo {
+
+class ServiceContext;
+
+/**
+ * A C++ interface wrapping the third-party timelib library. A single instance of this class can be
+ * accessed via the global service context.
+ */
+class DateTimeSupport {
+ MONGO_DISALLOW_COPYING(DateTimeSupport);
+
+public:
+ /**
+ * A custom-deleter which deletes 'timeZoneDatabase' if it is not the builtin time zone
+ * database, which has static lifetime and should not be freed.
+ */
+ struct TimeZoneDBDeleter {
+ TimeZoneDBDeleter() = default;
+ void operator()(timelib_tzdb* timeZoneDatabase);
+ };
+
+ /**
+ * Creates a DateTimeSupport object with time zone data loaded from timelib's built-in timezone
+ * rules.
+ */
+ DateTimeSupport();
+
+ /**
+ * Creates a DateTimeSupport object using time zone rules given by 'timeZoneDatabase'.
+ */
+ DateTimeSupport(std::unique_ptr<timelib_tzdb, TimeZoneDBDeleter> timeZoneDatabase);
+
+ ~DateTimeSupport();
+
+ /**
+ * Returns the DateTimeSupport object associated with the specified service context. This method
+ * must only be called if a DateTimeSupport has been set on the service context.
+ */
+ static const DateTimeSupport* get(ServiceContext* serviceContext);
+
+ /**
+ * Sets the DateTimeSupport object associated with the specified service context.
+ */
+ static void set(ServiceContext* serviceContext,
+ std::unique_ptr<DateTimeSupport> dateTimeSupport);
+
+private:
+ /**
+ * Populates '_timeZones' with parsed time zone rules for each timezone specified by
+ * 'timeZoneDatabase'.
+ */
+ void loadTimeZoneInfo(std::unique_ptr<timelib_tzdb, TimeZoneDBDeleter> timeZoneDatabase);
+
+ // A map from the time zone name to the struct describing the timezone. These are pre-populated
+ // at startup to avoid reading the source files repeatedly.
+ StringMap<timelib_tzinfo*> _timeZones;
+
+ // The timelib structure which provides timezone information.
+ std::unique_ptr<timelib_tzdb, TimeZoneDBDeleter> _timeZoneDatabase;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/query/datetime/init_timezone_data.cpp b/src/mongo/db/query/datetime/init_timezone_data.cpp
new file mode 100644
index 00000000000..d9c73085239
--- /dev/null
+++ b/src/mongo/db/query/datetime/init_timezone_data.cpp
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2017 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 <timelib.h>
+
+#include "mongo/base/init.h"
+#include "mongo/db/query/datetime/date_time_support.h"
+#include "mongo/db/server_options.h"
+#include "mongo/db/service_context.h"
+#include "mongo/stdx/memory.h"
+#include "mongo/util/mongoutils/str.h"
+
+namespace mongo {
+
+MONGO_INITIALIZER_WITH_PREREQUISITES(
+ LoadTimeZoneDB, ("GlobalLogManager", "SetGlobalEnvironment", "EndStartupOptionStorage"))
+(InitializerContext* context) {
+ auto serviceContext = getGlobalServiceContext();
+ if (!serverGlobalParams.timeZoneInfoPath.empty()) {
+ std::unique_ptr<timelib_tzdb, DateTimeSupport::TimeZoneDBDeleter> timeZoneDatabase(
+ timelib_zoneinfo(const_cast<char*>(serverGlobalParams.timeZoneInfoPath.c_str())),
+ DateTimeSupport::TimeZoneDBDeleter());
+ if (!timeZoneDatabase) {
+ return {ErrorCodes::FailedToParse,
+ str::stream() << "failed to load time zone database from path \""
+ << serverGlobalParams.timeZoneInfoPath
+ << "\""};
+ }
+ DateTimeSupport::set(serviceContext,
+ stdx::make_unique<DateTimeSupport>(std::move(timeZoneDatabase)));
+ } else {
+ // No 'zoneInfo' specified on the command line, fall back to the built-in rules.
+ DateTimeSupport::set(serviceContext, stdx::make_unique<DateTimeSupport>());
+ }
+ return Status::OK();
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/server_options.h b/src/mongo/db/server_options.h
index b1b58670cce..148c96dd0bd 100644
--- a/src/mongo/db/server_options.h
+++ b/src/mongo/db/server_options.h
@@ -76,8 +76,9 @@ struct ServerGlobalParams {
int unixSocketPermissions = DEFAULT_UNIX_PERMS; // permissions for the UNIX domain socket
- std::string keyFile; // Path to keyfile, or empty if none.
- std::string pidFile; // Path to pid file, or empty if none.
+ std::string keyFile; // Path to keyfile, or empty if none.
+ std::string pidFile; // Path to pid file, or empty if none.
+ std::string timeZoneInfoPath; // Path to time zone info directory, or empty if none.
std::string logpath; // Path to log file, if logging to a file; otherwise, empty.
bool logAppend = false; // True if logging to a file in append mode.
diff --git a/src/mongo/db/server_options_helpers.cpp b/src/mongo/db/server_options_helpers.cpp
index 326345cb87d..af2a00f9d86 100644
--- a/src/mongo/db/server_options_helpers.cpp
+++ b/src/mongo/db/server_options_helpers.cpp
@@ -272,6 +272,11 @@ Status addGeneralServerOptions(moe::OptionSection* options) {
moe::String,
"full path to pidfile (if not set, no pidfile is created)");
+ options->addOptionChaining("processManagement.timeZoneInfo",
+ "timeZoneInfo",
+ moe::String,
+ "full path to time zone info directory, e.g. /usr/share/zoneinfo");
+
options
->addOptionChaining(
"security.keyFile", "keyFile", moe::String, "private key for cluster authentication")
@@ -982,6 +987,10 @@ Status storeServerOptions(const moe::Environment& params) {
serverGlobalParams.pidFile = params["processManagement.pidFilePath"].as<string>();
}
+ if (params.count("processManagement.timeZoneInfo")) {
+ serverGlobalParams.timeZoneInfoPath = params["processManagement.timeZoneInfo"].as<string>();
+ }
+
if (params.count("setParameter")) {
std::map<std::string, std::string> parameters =
params["setParameter"].as<std::map<std::string, std::string>>();