From 48f14493a3751483b67144897a44ed3297720f8c Mon Sep 17 00:00:00 2001 From: Eric Milkie Date: Thu, 9 Apr 2015 08:02:20 -0400 Subject: Revert "SERVER-15047 Remove undefined behavior from Timestamp" This reverts commit e87716a9286b6aa6f63a513012e55f6e42f634a2. --- src/mongo/bson/timestamp.h | 128 +++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 74 deletions(-) (limited to 'src/mongo/bson/timestamp.h') diff --git a/src/mongo/bson/timestamp.h b/src/mongo/bson/timestamp.h index c18fb85bb07..b223b5deb50 100644 --- a/src/mongo/bson/timestamp.h +++ b/src/mongo/bson/timestamp.h @@ -27,74 +27,57 @@ #pragma once -#include - -#include "mongo/base/data_cursor.h" #include "mongo/base/data_view.h" -#include "mongo/platform/cstdint.h" #include "mongo/bson/util/builder.h" -#include "mongo/platform/endian.h" #include "mongo/util/assert_util.h" namespace mongo { - class StringData; - /** - * Timestamp: A combination of current second plus an ordinal value, held together in a - * single 64-bit integer, stored in memory as little endian, regardless of local endianness. + /* Timestamp: A combination of current second plus an ordinal value. */ +#pragma pack(4) class Timestamp { - public: - - Timestamp() = default; + unsigned i; // ordinal comes first so we can do a single 64 bit compare on little endian + unsigned secs; + public: + unsigned getSecs() const { + return secs; + } + unsigned getInc() const { + return i; + } - explicit Timestamp(Date_t date) { - _data = endian::nativeToLittle(date.millis); - dassert(static_cast(getSecs()) >= 0); + Timestamp(Date_t date) { + reinterpret_cast(*this) = date.millis; + dassert( (int)secs >= 0 ); } - Timestamp(unsigned secs, unsigned inc) { - DataCursor(reinterpret_cast(&_data)) - .writeLEAndAdvance(inc) - .writeLE(secs); + 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 getSecs() const { - static_assert(sizeof(unsigned) == sizeof(uint32_t), "unsigned must be uint32"); - return ConstDataCursor(reinterpret_cast(&_data)) - .skip() - .readLE(); - } - - unsigned getInc() const { - static_assert(sizeof(unsigned) == sizeof(uint32_t), "unsigned must be uint32"); - return ConstDataCursor(reinterpret_cast(&_data)) - .readLE(); - } - unsigned long long asULL() const { - return endian::littleToNative(_data); + return reinterpret_cast(&i)[0]; } - long long asLL() const { - const unsigned long long val = endian::littleToNative(_data); - return static_cast(val); + return reinterpret_cast(&i)[0]; } - bool isNull() const { - return getSecs() == 0; - } - - // 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; - - // Set the value of this Timestamp to match that of the pointed to bytes. The - // return value points to the first byte not consumed by the read operation. - const void* readFrom(const void* bytes); + bool isNull() const { return secs == 0; } std::string toStringLong() const; @@ -102,35 +85,32 @@ namespace mongo { std::string toString() const; - private: - uint64_t _data = 0; - }; - - inline bool operator==(const Timestamp& lhs, const Timestamp& rhs) { - return (lhs.getInc() == rhs.getInc()) && (lhs.getSecs() == rhs.getSecs()); - } - - inline bool operator!=(const Timestamp& lhs, const Timestamp& rhs) { - return !(lhs == rhs); - } - - inline bool operator<(const Timestamp& lhs, const Timestamp& rhs) { - if ( lhs.getSecs() != rhs.getSecs() ) { - return lhs.getSecs() < rhs.getSecs(); + bool operator==(const Timestamp& r) const { + return i == r.i && secs == r.secs; + } + bool operator!=(const Timestamp& r) const { + return !(*this == r); + } + bool operator<(const Timestamp& r) const { + if ( secs != r.secs ) + return secs < r.secs; + return i < r.i; + } + bool operator<=(const Timestamp& r) const { + return *this < r || *this == r; + } + bool operator>(const Timestamp& r) const { + return !(*this <= r); + } + bool operator>=(const Timestamp& r) const { + return !(*this < r); } - return lhs.getInc() < rhs.getInc(); - } - - inline bool operator<=(const Timestamp& lhs, const Timestamp& rhs) { - return (lhs < rhs) || (lhs == rhs); - } - inline bool operator>(const Timestamp& lhs, const Timestamp& rhs) { - return !(lhs <= rhs); - } + // 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; - inline bool operator>=(const Timestamp& lhs, const Timestamp& rhs) { - return !(lhs < rhs); - } + }; +#pragma pack() } // namespace mongo -- cgit v1.2.1