diff options
Diffstat (limited to 'src/mongo/util')
-rw-r--r-- | src/mongo/util/net/ssl_expiration.cpp | 25 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager.cpp | 2 | ||||
-rw-r--r-- | src/mongo/util/signal_handlers_synchronous.cpp | 2 | ||||
-rw-r--r-- | src/mongo/util/time_support.cpp | 80 | ||||
-rw-r--r-- | src/mongo/util/time_support.h | 104 | ||||
-rw-r--r-- | src/mongo/util/time_support_test.cpp | 10 |
6 files changed, 192 insertions, 31 deletions
diff --git a/src/mongo/util/net/ssl_expiration.cpp b/src/mongo/util/net/ssl_expiration.cpp index 9f1d6ef9676..d05462ce442 100644 --- a/src/mongo/util/net/ssl_expiration.cpp +++ b/src/mongo/util/net/ssl_expiration.cpp @@ -32,14 +32,15 @@ #include <string> #include "mongo/util/log.h" +#include "mongo/util/time_support.h" namespace mongo { - static const unsigned long long dayInMillis = 24 * 60 * 60 * 1000; + static const auto oneDay = stdx::chrono::hours(24); CertificateExpirationMonitor::CertificateExpirationMonitor(Date_t date) : _certExpiration(date) - , _lastCheckTime(Date_t(curTimeMillis64())) { + , _lastCheckTime(Date_t::now()) { } std::string CertificateExpirationMonitor::taskName() const { @@ -47,30 +48,28 @@ namespace mongo { } void CertificateExpirationMonitor::taskDoWork() { - const unsigned long long timeSinceLastCheck = - curTimeMillis64() - _lastCheckTime.millis; + const Milliseconds timeSinceLastCheck = Date_t::now() - _lastCheckTime; - if (timeSinceLastCheck < dayInMillis) + if (timeSinceLastCheck < oneDay) return; - const Date_t now = Date_t(curTimeMillis64()); + const Date_t now = Date_t::now(); _lastCheckTime = now; - if (_certExpiration.millis <= now.millis) { + if (_certExpiration <= now) { // The certificate has expired. warning() << "Server certificate is now invalid. It expired on " - << dateToCtimeString(_certExpiration); + << dateToISOStringUTC(_certExpiration); return; } - const unsigned long long remainingValidMillis = - _certExpiration.millis - now.millis; + const auto remainingValidDuration = _certExpiration - now; - if (remainingValidMillis / dayInMillis <= 30) { + if (remainingValidDuration <= 30 * oneDay) { // The certificate will expire in the next 30 days. warning() << "Server certificate will expire on " - << dateToCtimeString(_certExpiration) << " in " - << (remainingValidMillis / dayInMillis) + << dateToISOStringUTC(_certExpiration) << " in " + << durationCount<stdx::chrono::hours>(remainingValidDuration) / 24 << " days."; } } diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp index 6f9be1a1c03..652807e7e71 100644 --- a/src/mongo/util/net/ssl_manager.cpp +++ b/src/mongo/util/net/ssl_manager.cpp @@ -699,7 +699,7 @@ namespace mongo { "The provided SSL certificate is expired or not yet valid."); } - *serverCertificateExpirationDate = Date_t(notAfterMillis); + *serverCertificateExpirationDate = Date_t::fromMillisSinceEpoch(notAfterMillis); } return true; diff --git a/src/mongo/util/signal_handlers_synchronous.cpp b/src/mongo/util/signal_handlers_synchronous.cpp index e28d2796fd5..e0d69350203 100644 --- a/src/mongo/util/signal_handlers_synchronous.cpp +++ b/src/mongo/util/signal_handlers_synchronous.cpp @@ -114,7 +114,7 @@ namespace { // must hold streamMutex to call void writeMallocFreeStreamToLog() { logger::globalLogDomain()->append( - logger::MessageEventEphemeral(curTimeMillis64(), + logger::MessageEventEphemeral(Date_t::now(), logger::LogSeverity::Severe(), getThreadName(), mallocFreeOStream.str())); diff --git a/src/mongo/util/time_support.cpp b/src/mongo/util/time_support.cpp index 69369582058..a850e7fceac 100644 --- a/src/mongo/util/time_support.cpp +++ b/src/mongo/util/time_support.cpp @@ -41,6 +41,7 @@ #include "mongo/bson/util/builder.h" #include "mongo/platform/cstdint.h" #include "mongo/util/assert_util.h" +#include "mongo/util/mongoutils/str.h" #ifdef _WIN32 #include <boost/date_time/filetime_functions.hpp> @@ -64,12 +65,73 @@ timegm(struct tm *const tmp); namespace mongo { +namespace { + template <typename Stream> Stream& streamPut(Stream& os, Microseconds us) { + return os << us.count() << "\xce\xbcs"; + } + + template <typename Stream> Stream& streamPut(Stream& os, Milliseconds ms) { + return os << ms.count() << "ms"; + } + + template <typename Stream> Stream& streamPut(Stream& os, Seconds s) { + return os << s.count() << 's'; + } +} // namespace + + std::ostream& operator<<(std::ostream& os, Microseconds us) { + return streamPut(os, us); + } + + std::ostream& operator<<(std::ostream& os, Milliseconds ms) { + return streamPut(os, ms); + } + std::ostream& operator<<(std::ostream& os, Seconds s) { + return streamPut(os, s); + } + + template <typename Allocator> + StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Microseconds us) { + return streamPut(os, us); + } + + template <typename Allocator> + StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Milliseconds ms) { + return streamPut(os, ms); + } + + template <typename Allocator> + StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Seconds s) { + return streamPut(os, s); + } + + template StringBuilderImpl<StackAllocator>& operator<<(StringBuilderImpl<StackAllocator>&, + Microseconds); + template StringBuilderImpl<StackAllocator>& operator<<(StringBuilderImpl<StackAllocator>&, + Milliseconds); + template StringBuilderImpl<StackAllocator>& operator<<(StringBuilderImpl<StackAllocator>&, + Seconds); + template StringBuilderImpl<TrivialAllocator>& operator<<(StringBuilderImpl<TrivialAllocator>&, + Microseconds); + template StringBuilderImpl<TrivialAllocator>& operator<<(StringBuilderImpl<TrivialAllocator>&, + Milliseconds); + template StringBuilderImpl<TrivialAllocator>& operator<<(StringBuilderImpl<TrivialAllocator>&, + Seconds); + + Date_t Date_t::max() { + return fromMillisSinceEpoch(std::numeric_limits<long long>::max()); + } + + Date_t Date_t::now() { + return fromMillisSinceEpoch(curTimeMillis64()); + } + bool Date_t::isFormatable() const { if (sizeof(time_t) == sizeof(int32_t)) { - return millis < 2147483647000ULL; // "2038-01-19T03:14:07Z" + return millis < 2147483647000LL; // "2038-01-19T03:14:07Z" } else { - return millis < 32535215999000ULL; // "3000-12-31T23:59:59Z" + return millis < 32535215999000LL; // "3000-12-31T23:59:59Z" } } @@ -690,7 +752,11 @@ namespace { resultMillis += (tzAdjSecs * 1000); - return StatusWith<Date_t>(resultMillis); + if (resultMillis > static_cast<unsigned long long>(std::numeric_limits<long long>::max())) { + return {ErrorCodes::BadValue, + str::stream() << dateString << " is too far in the future"}; + } + return Date_t::fromMillisSinceEpoch(static_cast<long long>(resultMillis)); } #undef MONGO_ISO_DATE_FMT_NO_TZ @@ -976,11 +1042,11 @@ namespace { return ((unsigned long long)tv.tv_sec) * 1000 + tv.tv_usec / 1000; } Date_t jsTime() { - timeval tv; - gettimeofday(&tv, NULL); - unsigned long long t = tv.tv_usec / 1000; - return ((unsigned long long) tv.tv_sec * 1000) + t + getJSTimeVirtualSkew() + getJSTimeVirtualThreadSkew(); + return Date_t::now() + + Milliseconds(getJSTimeVirtualThreadSkew()) + + Milliseconds(getJSTimeVirtualSkew()); } + unsigned long long curTimeMicros64() { timeval tv; gettimeofday(&tv, NULL); diff --git a/src/mongo/util/time_support.h b/src/mongo/util/time_support.h index 81db17cbd76..988453f6c39 100644 --- a/src/mongo/util/time_support.h +++ b/src/mongo/util/time_support.h @@ -37,30 +37,116 @@ #include <boost/version.hpp> #include "mongo/base/status_with.h" +#include "mongo/stdx/chrono.h" namespace mongo { - typedef boost::posix_time::milliseconds Milliseconds; - typedef boost::posix_time::seconds Seconds; + template <typename Allocator> class StringBuilderImpl; + + using Microseconds = stdx::chrono::microseconds; + using Milliseconds = stdx::chrono::milliseconds; + using Seconds = stdx::chrono::seconds; + using Minutes = stdx::chrono::minutes; + using stdx::chrono::duration_cast; void time_t_to_Struct(time_t t, struct tm * buf , bool local = false ); std::string time_t_to_String(time_t t); std::string time_t_to_String_short(time_t t); - struct Date_t { - // TODO: make signed (and look for related TODO's) - unsigned long long millis; + // + // Operators for putting durations to streams. + // + + std::ostream& operator<<(std::ostream& os, Microseconds us); + std::ostream& operator<<(std::ostream& os, Milliseconds ms); + std::ostream& operator<<(std::ostream& os, Seconds s); + + template <typename Allocator> + StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Microseconds us); + + template <typename Allocator> + StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Milliseconds ms); + + template <typename Allocator> + StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, Seconds s); + + /** + * Convenience method for reading the count of a duration with specified units. + * + * Use when logging or comparing to integers, to ensure that you're using + * the units you intend. + * + * E.g., log() << durationCount<Seconds>(some duration) << " seconds"; + */ + template <typename DOut, typename DIn> long long durationCount(DIn d) { + return duration_cast<DOut>(d).count(); + } + + class Date_t { + public: + static Date_t max(); + static Date_t now(); + + static Date_t fromMillisSinceEpoch(long long m) { + return Date_t(m); + } + + template <typename Duration> + static Date_t fromDurationSinceEpoch(Duration d) { + return fromMillisSinceEpoch(durationCount<Milliseconds>(d)); + } + Date_t(): millis(0) {} - Date_t(unsigned long long m): millis(m) {} - operator unsigned long long&() { return millis; } - operator const unsigned long long&() const { return millis; } + void toTm (tm *buf); std::string toString() const; time_t toTimeT() const; int64_t asInt64() const { - return static_cast<int64_t>(millis); + return toMillisSinceEpoch(); } + unsigned long long toULL() const { return static_cast<unsigned long long>(asInt64()); } + Milliseconds toDurationSinceEpoch() const { return Milliseconds(toMillisSinceEpoch()); } + long long toMillisSinceEpoch() const { return static_cast<long long>(millis); } bool isFormatable() const; + + template <typename Duration> + Date_t operator+(Duration d) const { + return { millis + duration_cast<Milliseconds>(d).count() }; + } + + template <typename Duration> + Date_t operator-(Duration d) const { + return *this + (-d); + } + + Milliseconds operator-(Date_t other) const { return Milliseconds(millis - other.millis); } + + bool operator==(Date_t other) const { + return toDurationSinceEpoch() == other.toDurationSinceEpoch(); + } + + bool operator!=(Date_t other) const { return !(*this == other); } + + bool operator<(Date_t other) const { + return toDurationSinceEpoch() < other.toDurationSinceEpoch(); + } + + bool operator>(Date_t other) const { + return toDurationSinceEpoch() > other.toDurationSinceEpoch(); + } + + bool operator<=(Date_t other) const { + return !(*this > other); + } + + bool operator>=(Date_t other) const { + return !(*this < other); + } + + private: + Date_t(long long m): millis(m) {} + + long long millis; }; // uses ISO 8601 dates without trailing Z diff --git a/src/mongo/util/time_support_test.cpp b/src/mongo/util/time_support_test.cpp index 0580584c62e..dc367e61647 100644 --- a/src/mongo/util/time_support_test.cpp +++ b/src/mongo/util/time_support_test.cpp @@ -813,5 +813,15 @@ namespace { } } + TEST(TimeFormatting, DurationFormatting) { + ASSERT_EQUALS("52\xce\xbcs", static_cast<std::string>(str::stream() << Microseconds(52))); + ASSERT_EQUALS("52ms", static_cast<std::string>(str::stream() << Milliseconds(52))); + ASSERT_EQUALS("52s", static_cast<std::string>(str::stream() << Seconds(52))); + + std::ostringstream os; + os << Milliseconds(52) << Microseconds(52) << Seconds(52); + ASSERT_EQUALS("52ms52\xce\xbcs52s", os.str()); + } + } // namespace } // namespace mongo |