Repository: mesos Updated Branches: refs/heads/master 9987b4652 -> d0300e1a4
Added stream manipulators for the Time object. Adds some manipulator classes which allows formatting Time objects to ostreams. Review: https://reviews.apache.org/r/34703 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/2dc9f5e4 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/2dc9f5e4 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/2dc9f5e4 Branch: refs/heads/master Commit: 2dc9f5e4e21d7c7d361b3b23b82e000152fef700 Parents: 9987b46 Author: Alexander Rojas <[email protected]> Authored: Thu Jul 9 17:25:51 2015 +0200 Committer: Till Toenshoff <[email protected]> Committed: Thu Jul 9 17:28:06 2015 +0200 ---------------------------------------------------------------------- 3rdparty/libprocess/Makefile.am | 1 + 3rdparty/libprocess/include/process/time.hpp | 68 +++++++------ 3rdparty/libprocess/src/tests/time_tests.cpp | 52 ++++++++++ 3rdparty/libprocess/src/time.cpp | 114 ++++++++++++++++++++++ 4 files changed, 205 insertions(+), 30 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/2dc9f5e4/3rdparty/libprocess/Makefile.am ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/Makefile.am b/3rdparty/libprocess/Makefile.am index 358893c..71e15f0 100644 --- a/3rdparty/libprocess/Makefile.am +++ b/3rdparty/libprocess/Makefile.am @@ -52,6 +52,7 @@ libprocess_la_SOURCES = \ src/reap.cpp \ src/socket.cpp \ src/subprocess.cpp \ + src/time.cpp \ src/timeseries.cpp if ENABLE_LIBEVENT http://git-wip-us.apache.org/repos/asf/mesos/blob/2dc9f5e4/3rdparty/libprocess/include/process/time.hpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/include/process/time.hpp b/3rdparty/libprocess/include/process/time.hpp index c5ab2a3..6a57b7b 100644 --- a/3rdparty/libprocess/include/process/time.hpp +++ b/3rdparty/libprocess/include/process/time.hpp @@ -1,12 +1,8 @@ #ifndef __PROCESS_TIME_HPP__ #define __PROCESS_TIME_HPP__ -#include <time.h> - #include <iomanip> -#include <glog/logging.h> - #include <stout/duration.hpp> namespace process { @@ -80,39 +76,51 @@ inline Time Time::epoch() { return Time(Duration::zero()); } inline Time Time::max() { return Time(Duration::max()); } -// Outputs the time in RFC 3339 Format. -inline std::ostream& operator << (std::ostream& stream, const Time& time) +// Stream manipulator class which serializes Time objects in RFC 1123 +// format (Also known as HTTP Date format). +// The serialization is independent from the locale and ready to be +// used in HTTP Headers. +// Example: Wed, 15 Nov 1995 04:58:08 GMT +// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html +// section 14.18. +// See https://www.ietf.org/rfc/rfc1123.txt section 5.2.14 +class RFC1123 { - // Round down the secs to use it with strftime and then append the - // fraction part. - long secs = static_cast<long>(time.secs()); - char date[64]; - - // The RFC 3339 Format. - tm tm_; - if (gmtime_r(&secs, &tm_) == NULL) { - PLOG(ERROR) - << "Failed to convert the 'time' to a tm struct using gmtime_r()"; - return stream; - } +public: + explicit RFC1123(const Time& _time) : time(_time) {} - strftime(date, 64, "%Y-%m-%d %H:%M:%S", &tm_); - stream << date; +private: + friend std::ostream& operator << (std::ostream& out, const RFC1123& format); - // Append the fraction part in nanoseconds. - int64_t nsecs = (time.duration() - Seconds(secs)).ns(); + const Time time; +}; - if (nsecs != 0) { - char prev = stream.fill(); - // 9 digits for nanosecond level precision. - stream << "." << std::setfill('0') << std::setw(9) << nsecs; +std::ostream& operator << (std::ostream& out, const RFC1123& formatter); + + +// Stream manipulator class which serializes Time objects in RFC 3339 +// format. +// Example: 1996-12-19T16:39:57-08:00,234 +class RFC3339 +{ +public: + explicit RFC3339(const Time& _time) : time(_time) {} + +private: + friend std::ostream& operator << (std::ostream& out, const RFC3339& format); + + const Time time; +}; - // Return the stream to original formatting state. - stream.fill(prev); - } - stream << "+00:00"; +std::ostream& operator << (std::ostream& out, const RFC3339& formatter); + + +// Outputs the time in RFC 3339 Format. +inline std::ostream& operator << (std::ostream& stream, const Time& time) +{ + stream << RFC3339(time); return stream; } http://git-wip-us.apache.org/repos/asf/mesos/blob/2dc9f5e4/3rdparty/libprocess/src/tests/time_tests.cpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/src/tests/time_tests.cpp b/3rdparty/libprocess/src/tests/time_tests.cpp index be31418..9e1d176 100644 --- a/3rdparty/libprocess/src/tests/time_tests.cpp +++ b/3rdparty/libprocess/src/tests/time_tests.cpp @@ -37,6 +37,58 @@ TEST(TimeTest, Now) } +// Tests stream manipulator which formats Time object into RFC 1123 +// (HTTP Date) format. +TEST(TimeTest, RFC1123Output) +{ + EXPECT_EQ( + "Thu, 01 Jan 1970 00:00:00 GMT", + stringify(RFC1123(Time::epoch()))); + + EXPECT_EQ( + "Thu, 02 Mar 1989 00:00:00 GMT", + stringify(RFC1123(Time::epoch() + Weeks(1000)))); + + EXPECT_EQ( + "Thu, 02 Mar 1989 00:00:00 GMT", + stringify(RFC1123(Time::epoch() + Weeks(1000) + Nanoseconds(1)))); + + EXPECT_EQ( + "Thu, 02 Mar 1989 00:00:01 GMT", + stringify(RFC1123(Time::epoch() + Weeks(1000) + Seconds(1)))); + + EXPECT_EQ( + "Fri, 11 Apr 2262 23:47:16 GMT", + stringify(RFC1123(Time::max()))); +} + + +// Tests stream manipulator which formats Time object into RFC 3339 +// format. +TEST(TimeTest, RFC3339Output) +{ + EXPECT_EQ( + "1970-01-01 00:00:00+00:00", + stringify(RFC3339(Time::epoch()))); + + EXPECT_EQ( + "1989-03-02 00:00:00+00:00", + stringify(RFC3339(Time::epoch() + Weeks(1000)))); + + EXPECT_EQ( + "1989-03-02 00:00:00.000000001+00:00", + stringify(RFC3339(Time::epoch() + Weeks(1000) + Nanoseconds(1)))); + + EXPECT_EQ( + "1989-03-02 00:00:00.000001000+00:00", + stringify(RFC3339(Time::epoch() + Weeks(1000) + Microseconds(1)))); + + EXPECT_EQ( + "2262-04-11 23:47:16.854775807+00:00", + stringify(RFC3339(Time::max()))); +} + + TEST(TimeTest, Output) { EXPECT_EQ("1989-03-02 00:00:00+00:00", http://git-wip-us.apache.org/repos/asf/mesos/blob/2dc9f5e4/3rdparty/libprocess/src/time.cpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/src/time.cpp b/3rdparty/libprocess/src/time.cpp new file mode 100644 index 0000000..87f1f36 --- /dev/null +++ b/3rdparty/libprocess/src/time.cpp @@ -0,0 +1,114 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include <time.h> + +#include <glog/logging.h> + +#include <process/time.hpp> + +namespace process { + +std::ostream& operator << (std::ostream& out, const RFC1123& formatter) +{ + time_t secs = static_cast<time_t>(formatter.time.secs()); + + tm timeInfo = {}; + if (gmtime_r(&secs, &timeInfo) == NULL) { + PLOG(ERROR) + << "Failed to convert from 'time_t' to a 'tm' struct using gmtime_r()"; + return out; + } + + static const char* WEEK_DAYS[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + + static const char* MONTHS[] = { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + }; + + char buffer[64] = {}; + + // 'strftime' cannot be used since it depends on the locale, which + // is not useful when using the RFC 1123 format in HTTP Headers. + if (snprintf( + buffer, + sizeof(buffer), + "%s, %02d %s %d %02d:%02d:%02d GMT", + WEEK_DAYS[timeInfo.tm_wday], + timeInfo.tm_mday, + MONTHS[timeInfo.tm_mon], + timeInfo.tm_year + 1900, + timeInfo.tm_hour, + timeInfo.tm_min, + timeInfo.tm_sec) < 0) { + LOG(ERROR) + << "Failed to format the 'time' to a string using snprintf"; + return out; + } + + out << buffer; + + return out; +} + + +std::ostream& operator << (std::ostream& out, const RFC3339& formatter) +{ + // Round down the secs to use it with strftime and then append the + // fraction part. + time_t secs = static_cast<time_t>(formatter.time.secs()); + + // The RFC 3339 Format. + tm timeInfo = {}; + if (gmtime_r(&secs, &timeInfo) == NULL) { + PLOG(ERROR) + << "Failed to convert from 'time_t' to a 'tm' struct using gmtime_r()"; + return out; + } + + char buffer[64] = {}; + + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &timeInfo); + out << buffer; + + // Append the fraction part in nanoseconds. + int64_t nanoSeconds = (formatter.time.duration() - Seconds(secs)).ns(); + if (nanoSeconds != 0) { + char prev = out.fill(); + + // 9 digits for nanosecond level precision. + out << "." << std::setfill('0') << std::setw(9) << nanoSeconds; + + // Return the stream to original formatting state. + out.fill(prev); + } + + out << "+00:00"; + return out; +} + +} // namespace process {
