diff options
author | Andy Schwerin <schwerin@mongodb.com> | 2015-05-07 16:45:29 -0400 |
---|---|---|
committer | Andy Schwerin <schwerin@mongodb.com> | 2015-05-12 09:57:33 -0400 |
commit | 9aac625685811873ffbc2d3e8d09531eff1ce10e (patch) | |
tree | ecd8dd9fc9d148b196c6ab2aa5e38e5f9e327c54 /src/mongo/bson | |
parent | 21a16d229bdba571f1118a419898b666c666b869 (diff) | |
download | mongo-9aac625685811873ffbc2d3e8d09531eff1ce10e.tar.gz |
SERVER-13874 Make mongo::Milliseconds et al. aliases for equivalent stdx::chrono types.
Also introduces operators for adding stdx::chrono::duration to Date_t,
subtracting two Date_ts to get Milliseconds, and remove the use of
reinterpret_cast from the implementation of BSON Timestamp type.
Diffstat (limited to 'src/mongo/bson')
-rw-r--r-- | src/mongo/bson/bsonelement.cpp | 20 | ||||
-rw-r--r-- | src/mongo/bson/bsonelement.h | 5 | ||||
-rw-r--r-- | src/mongo/bson/bsonobjbuilder.cpp | 13 | ||||
-rw-r--r-- | src/mongo/bson/json.cpp | 12 | ||||
-rw-r--r-- | src/mongo/bson/oid.cpp | 2 | ||||
-rw-r--r-- | src/mongo/bson/oid.h | 2 | ||||
-rw-r--r-- | src/mongo/bson/timestamp.h | 83 |
7 files changed, 73 insertions, 64 deletions
diff --git a/src/mongo/bson/bsonelement.cpp b/src/mongo/bson/bsonelement.cpp index 49f45c44a12..86efd0f7e27 100644 --- a/src/mongo/bson/bsonelement.cpp +++ b/src/mongo/bson/bsonelement.cpp @@ -201,7 +201,7 @@ namespace mongo { s << "\"" << dateToISOStringLocal(date()) << "\""; } else { - s << "{ \"$numberLong\" : \"" << static_cast<long long>(d.millis) << "\" }"; + s << "{ \"$numberLong\" : \"" << d.toMillisSinceEpoch() << "\" }"; } s << " }"; } @@ -221,7 +221,7 @@ namespace mongo { else { // FIXME: This is not parseable by the shell, since it may not fit in a // float - s << d.millis; + s << d.toMillisSinceEpoch(); } } else { @@ -266,10 +266,14 @@ namespace mongo { case bsonTimestamp: if ( format == TenGen ) { - s << "Timestamp( " << ( timestampTime() / 1000 ) << ", " << timestampInc() << " )"; + s << "Timestamp( " + << durationCount<Seconds>(timestampTime().toDurationSinceEpoch()) + << ", " << timestampInc() << " )"; } else { - s << "{ \"$timestamp\" : { \"t\" : " << ( timestampTime() / 1000 ) << ", \"i\" : " << timestampInc() << " } }"; + s << "{ \"$timestamp\" : { \"t\" : " + << durationCount<Seconds>(timestampTime().toDurationSinceEpoch()) + << ", \"i\" : " << timestampInc() << " } }"; } break; @@ -616,7 +620,7 @@ namespace mongo { s << "EOO"; break; case mongo::Date: - s << "new Date(" << (long long) date() << ')'; + s << "new Date(" << date().toMillisSinceEpoch() << ')'; break; case RegEx: { s << "/" << regex() << '/'; @@ -701,7 +705,7 @@ namespace mongo { } break; case bsonTimestamp: - s << "Timestamp " << timestampTime() << "|" << timestampInc(); + s << "Timestamp " << timestampTime().toMillisSinceEpoch() << "|" << timestampInc(); break; default: s << "?type=" << type(); @@ -852,8 +856,8 @@ namespace mongo { case Date: // Signed comparisons for Dates. { - long long a = (long long) l.Date().millis; - long long b = (long long) r.Date().millis; + const Date_t a = l.Date(); + const Date_t b = r.Date(); if( a < b ) return -1; return a == b ? 0 : 1; diff --git a/src/mongo/bson/bsonelement.h b/src/mongo/bson/bsonelement.h index c4fd19c77b4..25d9e895b49 100644 --- a/src/mongo/bson/bsonelement.h +++ b/src/mongo/bson/bsonelement.h @@ -211,7 +211,8 @@ namespace mongo { @see Bool(), trueValue() */ Date_t date() const { - return Date_t(ConstDataView(value()).read<LittleEndian<unsigned long long>>()); + return Date_t::fromMillisSinceEpoch( + ConstDataView(value()).read<LittleEndian<long long>>()); } /** Convert the value to boolean, regardless of its type, in a javascript-like fashion @@ -464,7 +465,7 @@ namespace mongo { Date_t timestampTime() const { unsigned long long t = ConstDataView(value() + 4).read<LittleEndian<unsigned int>>(); - return t * 1000; + return Date_t::fromMillisSinceEpoch(t * 1000); } unsigned int timestampInc() const { return ConstDataView(value()).read<LittleEndian<unsigned int>>(); diff --git a/src/mongo/bson/bsonobjbuilder.cpp b/src/mongo/bson/bsonobjbuilder.cpp index d0fd2665ff3..a9878b28adc 100644 --- a/src/mongo/bson/bsonobjbuilder.cpp +++ b/src/mongo/bson/bsonobjbuilder.cpp @@ -109,7 +109,9 @@ namespace mongo { case String: appendMinForType( fieldName, Object ); return; case Date: - appendDate( fieldName , std::numeric_limits<long long>::max() ); return; + appendDate(fieldName, + Date_t::fromMillisSinceEpoch(std::numeric_limits<long long>::max())); + return; case bsonTimestamp: append( fieldName , Timestamp::max() ); return; case Undefined: // shared with EOO @@ -196,16 +198,9 @@ namespace mongo { } BSONObjBuilder& BSONObjBuilder::appendDate(StringData fieldName, Date_t dt) { - /* easy to pass a time_t to this and get a bad result. thus this warning. */ - if ( kDebugBuild && dt > 0 && dt <= 0xffffffff ) { - static int n; - if( n++ == 0 ) - log() << "DEV WARNING appendDate() called with a tiny (but nonzero) date" << std::endl; - } - _b.appendNum((char) Date); _b.appendStr(fieldName); - _b.appendNum(dt); + _b.appendNum(dt.toMillisSinceEpoch()); return *this; } diff --git a/src/mongo/bson/json.cpp b/src/mongo/bson/json.cpp index 2b13e318e44..3bf5c531cd0 100644 --- a/src/mongo/bson/json.cpp +++ b/src/mongo/bson/json.cpp @@ -471,12 +471,12 @@ namespace mongo { if (!ret.isOK()) { return ret; } - date = numberLong; + date = Date_t::fromMillisSinceEpoch(numberLong); } else { // SERVER-11920: We should use parseNumberFromString here, but that function requires // that we know ahead of time where the number ends, which is not currently the case. - date = static_cast<unsigned long long>(strtoll(_input, &endptr, 10)); + date = Date_t::fromMillisSinceEpoch(strtoll(_input, &endptr, 10)); if (_input == endptr) { return parseError("Date expecting integer milliseconds"); } @@ -487,7 +487,8 @@ namespace mongo { // SERVER-11920: We should use parseNumberFromString here, but that function // requires that we know ahead of time where the number ends, which is not currently // the case. - date = strtoull(_input, &endptr, 10); + date = Date_t::fromMillisSinceEpoch( + static_cast<long long>(strtoull(_input, &endptr, 10))); if (errno == ERANGE) { return parseError("Date milliseconds overflow"); } @@ -753,7 +754,7 @@ namespace mongo { char* endptr; // SERVER-11920: We should use parseNumberFromString here, but that function requires that // we know ahead of time where the number ends, which is not currently the case. - Date_t date = static_cast<unsigned long long>(strtoll(_input, &endptr, 10)); + Date_t date = Date_t::fromMillisSinceEpoch(strtoll(_input, &endptr, 10)); if (_input == endptr) { return parseError("Date expecting integer milliseconds"); } @@ -763,7 +764,8 @@ namespace mongo { errno = 0; // SERVER-11920: We should use parseNumberFromString here, but that function requires // that we know ahead of time where the number ends, which is not currently the case. - date = strtoull(_input, &endptr, 10); + date = Date_t::fromMillisSinceEpoch( + static_cast<long long>(strtoull(_input, &endptr, 10))); if (errno == ERANGE) { return parseError("Date milliseconds overflow"); } diff --git a/src/mongo/bson/oid.cpp b/src/mongo/bson/oid.cpp index 853299d5bfe..e9c6b87eb3a 100644 --- a/src/mongo/bson/oid.cpp +++ b/src/mongo/bson/oid.cpp @@ -151,7 +151,7 @@ namespace { } void OID::init(Date_t date, bool max) { - setTimestamp(uint32_t(date / 1000)); + setTimestamp(uint32_t(date.toMillisSinceEpoch() / 1000)); uint64_t rest = max ? std::numeric_limits<uint64_t>::max() : 0u; std::memcpy(_view().view(kInstanceUniqueOffset), &rest, kInstanceUniqueSize + kIncrementSize); diff --git a/src/mongo/bson/oid.h b/src/mongo/bson/oid.h index df29065bb5e..a4ae3269d5f 100644 --- a/src/mongo/bson/oid.h +++ b/src/mongo/bson/oid.h @@ -140,7 +140,7 @@ namespace mongo { void init( Date_t date, bool max=false ); time_t asTimeT() const; - Date_t asDateT() const { return asTimeT() * 1000LL; } + Date_t asDateT() const { return Date_t::fromMillisSinceEpoch(asTimeT() * 1000LL); } // True iff the OID is not empty bool isSet() const { diff --git a/src/mongo/bson/timestamp.h b/src/mongo/bson/timestamp.h index b223b5deb50..8565cc80847 100644 --- a/src/mongo/bson/timestamp.h +++ b/src/mongo/bson/timestamp.h @@ -30,51 +30,56 @@ #include "mongo/base/data_view.h" #include "mongo/bson/util/builder.h" #include "mongo/util/assert_util.h" +#include "mongo/util/time_support.h" namespace mongo { - /* Timestamp: A combination of current second plus an ordinal value. + /** + * Timestamp: A combination of a count of seconds since the POSIX epoch plus an ordinal value. */ -#pragma pack(4) class Timestamp { - unsigned i; // ordinal comes first so we can do a single 64 bit compare on little endian - unsigned secs; public: + // Maximum Timestamp value. + static Timestamp max(); + + /** + * DEPRECATED Constructor that builds a Timestamp from a Date_t by using the + * high-order 4 bytes of "date" for the "secs" field and the low-order 4 bytes + * for the "i" field. + */ + explicit Timestamp(Date_t date) : Timestamp(date.toULL()) {} + + /** + * DEPRECATED Constructor that builds a Timestamp from a 64-bit unsigned integer by using + * the high-order 4 bytes of "v" for the "secs" field and the low-order 4 bytes for the "i" + * field." + */ + explicit Timestamp(unsigned long long v) : Timestamp(v >> 32, v) {} + + Timestamp(Seconds s, unsigned increment) : Timestamp(s.count(), increment) {} + + Timestamp(unsigned a, unsigned b) : i(b), secs(a) { + dassert(secs <= std::numeric_limits<int>::max()); + } + + Timestamp() : i(0), secs(0) {} + unsigned getSecs() const { return secs; } + unsigned getInc() const { return i; } - Timestamp(Date_t date) { - reinterpret_cast<unsigned long long&>(*this) = date.millis; - dassert( (int)secs >= 0 ); - } - - Timestamp(unsigned a, unsigned b) { - secs = a; - i = b; - dassert( (int)secs >= 0 ); - } - Timestamp( const Timestamp& other ) { - secs = other.secs; - i = other.i; - dassert( (int)secs >= 0 ); - } - Timestamp() { - secs = 0; - i = 0; - } - - // Maximum Timestamp value. - static Timestamp max(); - unsigned long long asULL() const { - return reinterpret_cast<const unsigned long long*>(&i)[0]; + unsigned long long result = secs; + result <<= 32; + result |= i; + return result; } long long asLL() const { - return reinterpret_cast<const long long*>(&i)[0]; + return static_cast<long long>(asULL()); } bool isNull() const { return secs == 0; } @@ -86,31 +91,33 @@ namespace mongo { std::string toString() const; bool operator==(const Timestamp& r) const { - return i == r.i && secs == r.secs; + return tie() == r.tie(); } bool operator!=(const Timestamp& r) const { - return !(*this == r); + return tie() != r.tie(); } bool operator<(const Timestamp& r) const { - if ( secs != r.secs ) - return secs < r.secs; - return i < r.i; + return tie() < r.tie(); } bool operator<=(const Timestamp& r) const { - return *this < r || *this == r; + return tie() <= r.tie(); } bool operator>(const Timestamp& r) const { - return !(*this <= r); + return tie() > r.tie(); } bool operator>=(const Timestamp& r) const { - return !(*this < r); + return tie() >= r.tie(); } // Append the BSON representation of this Timestamp to the given BufBuilder with the given // name. This lives here because Timestamp manages its own serialization format. void append(BufBuilder& builder, const StringData& fieldName) const; + private: + std::tuple<unsigned, unsigned> tie() const { return std::tie(secs, i); } + + unsigned i; // ordinal comes first so we can do a single 64 bit compare on little endian + unsigned secs; }; -#pragma pack() } // namespace mongo |