summaryrefslogtreecommitdiff
path: root/src/mongo/bson
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2015-05-07 16:45:29 -0400
committerAndy Schwerin <schwerin@mongodb.com>2015-05-12 09:57:33 -0400
commit9aac625685811873ffbc2d3e8d09531eff1ce10e (patch)
treeecd8dd9fc9d148b196c6ab2aa5e38e5f9e327c54 /src/mongo/bson
parent21a16d229bdba571f1118a419898b666c666b869 (diff)
downloadmongo-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.cpp20
-rw-r--r--src/mongo/bson/bsonelement.h5
-rw-r--r--src/mongo/bson/bsonobjbuilder.cpp13
-rw-r--r--src/mongo/bson/json.cpp12
-rw-r--r--src/mongo/bson/oid.cpp2
-rw-r--r--src/mongo/bson/oid.h2
-rw-r--r--src/mongo/bson/timestamp.h83
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