diff options
author | Charlie Swanson <charlie.swanson@mongodb.com> | 2017-06-12 16:41:54 -0400 |
---|---|---|
committer | Charlie Swanson <charlie.swanson@mongodb.com> | 2017-06-14 11:40:35 -0400 |
commit | ad473bb00cddb5e6ec83589fd4a7ebe780d7ca7d (patch) | |
tree | 2f45ed27db28e19d9d6a04027988fa1ad6a21504 /src | |
parent | d0b402cb0a01d716cad5a7f759c55cda4a4d5c1f (diff) | |
download | mongo-ad473bb00cddb5e6ec83589fd4a7ebe780d7ca7d.tar.gz |
SERVER-29207 Add DateTimeSupport to ServiceContext
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/pipeline/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/query/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/db/query/datetime/SConscript | 29 | ||||
-rw-r--r-- | src/mongo/db/query/datetime/date_time_support.cpp | 111 | ||||
-rw-r--r-- | src/mongo/db/query/datetime/date_time_support.h | 98 | ||||
-rw-r--r-- | src/mongo/db/query/datetime/init_timezone_data.cpp | 65 | ||||
-rw-r--r-- | src/mongo/db/server_options.h | 5 | ||||
-rw-r--r-- | src/mongo/db/server_options_helpers.cpp | 9 |
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>>(); |