diff options
author | Benety Goh <benety@mongodb.com> | 2014-01-22 15:10:11 -0500 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2014-01-24 11:26:47 -0500 |
commit | 2200ec891db98519701ba7192f42a644a405652e (patch) | |
tree | a26ba29e31dddbb10ec7dcbf4848e9bd1dff486d | |
parent | c42f5d873c0a0b6622f04b9b4d0235e6f0ec5f9c (diff) | |
download | mongo-2200ec891db98519701ba7192f42a644a405652e.tar.gz |
SERVER-12426 updated max BSON timestamp to depend on OpTime::max() which is defined as max(int32_t) seconds since epoch.
-rw-r--r-- | src/SConscript.client | 1 | ||||
-rw-r--r-- | src/mongo/bson/bsonobjbuilder_test.cpp | 13 | ||||
-rw-r--r-- | src/mongo/bson/optime.cpp | 7 | ||||
-rw-r--r-- | src/mongo/bson/optime.h | 3 | ||||
-rw-r--r-- | src/mongo/db/jsobj.cpp | 2 | ||||
-rw-r--r-- | src/mongo/dbtests/jstests.cpp | 40 | ||||
-rw-r--r-- | src/mongo/scripting/engine_v8.cpp | 15 | ||||
-rw-r--r-- | src/mongo/scripting/v8_db.cpp | 2 |
8 files changed, 79 insertions, 4 deletions
diff --git a/src/SConscript.client b/src/SConscript.client index 8925163eae4..15530d36e79 100644 --- a/src/SConscript.client +++ b/src/SConscript.client @@ -40,6 +40,7 @@ clientSourceBasic = [ 'mongo/base/string_data.cpp', 'mongo/bson/bson_validate.cpp', 'mongo/bson/oid.cpp', + 'mongo/bson/optime.cpp', 'mongo/bson/util/bson_extract.cpp', 'mongo/buildinfo.cpp', 'mongo/client/auth_helpers.cpp', diff --git a/src/mongo/bson/bsonobjbuilder_test.cpp b/src/mongo/bson/bsonobjbuilder_test.cpp index cd66c792727..f2b44c552f8 100644 --- a/src/mongo/bson/bsonobjbuilder_test.cpp +++ b/src/mongo/bson/bsonobjbuilder_test.cpp @@ -44,6 +44,7 @@ namespace { using mongo::BSONObj; using mongo::BSONObjBuilder; using mongo::BSONType; + using mongo::OpTime; const long long maxEncodableInt = (1 << 30) - 1; const long long minEncodableInt = -maxEncodableInt; @@ -248,4 +249,16 @@ namespace { ASSERT_EQUALS(o1, o2); } + TEST(BSONObjBuilderTest, AppendMaxTimestampOpTimeConversion) { + BSONObjBuilder b; + b.appendMaxForType("a", mongo::Timestamp); + BSONObj o1 = b.obj(); + + BSONElement e = o1.getField("a"); + ASSERT_FALSE(e.eoo()); + + OpTime opTime = e._opTime(); + ASSERT_FALSE(opTime.isNull()); + } + } // unnamed namespace diff --git a/src/mongo/bson/optime.cpp b/src/mongo/bson/optime.cpp index 489932ebe70..6cc01969366 100644 --- a/src/mongo/bson/optime.cpp +++ b/src/mongo/bson/optime.cpp @@ -16,6 +16,7 @@ #include "mongo/bson/optime.h" #include <iostream> +#include <limits> #include <ctime> #include "mongo/bson/inline_decls.h" @@ -73,6 +74,12 @@ namespace mongo { return last; } + OpTime OpTime::max() { + unsigned int t = static_cast<unsigned int>(std::numeric_limits<int32_t>::max()); + unsigned int i = std::numeric_limits<uint32_t>::max(); + return OpTime(t, i); + } + void OpTime::waitForDifferent(unsigned millis){ mutex::scoped_lock lk(m); while (*this == last) { diff --git a/src/mongo/bson/optime.h b/src/mongo/bson/optime.h index c584a62c9de..6d549a38824 100644 --- a/src/mongo/bson/optime.h +++ b/src/mongo/bson/optime.h @@ -92,6 +92,9 @@ namespace mongo { static OpTime getLast(const mongo::mutex::scoped_lock&); + // Maximum OpTime value. + static OpTime max(); + // Waits for global OpTime to be different from *this void waitForDifferent(unsigned millis); diff --git a/src/mongo/db/jsobj.cpp b/src/mongo/db/jsobj.cpp index 1378a9513a8..73ef893f525 100644 --- a/src/mongo/db/jsobj.cpp +++ b/src/mongo/db/jsobj.cpp @@ -1283,7 +1283,7 @@ namespace mongo { case Date: appendDate( fieldName , numeric_limits<long long>::max() ); return; case Timestamp: // TODO integrate with Date SERVER-3304 - appendTimestamp( fieldName , numeric_limits<unsigned long long>::max() ); return; + append( fieldName , OpTime::max() ); return; case Undefined: // shared with EOO appendUndefined( fieldName ); return; diff --git a/src/mongo/dbtests/jstests.cpp b/src/mongo/dbtests/jstests.cpp index 67d77c969b2..0f6d4f1d9af 100644 --- a/src/mongo/dbtests/jstests.cpp +++ b/src/mongo/dbtests/jstests.cpp @@ -31,6 +31,8 @@ #include "mongo/pch.h" +#include <limits> + #include "mongo/base/parse_number.h" #include "mongo/db/instance.h" #include "mongo/db/json.h" @@ -773,6 +775,26 @@ namespace JSTests { } }; + class InvalidTimestamp { + public: + void run() { + auto_ptr<Scope> s( globalScriptEngine->newScope() ); + s->localConnect( "blah" ); + + // Timestamp 't' component cannot exceed max for int32_t. + // Use appendTimestamp(field, Date) to bypass OpTime construction. + BSONObj in; + { + BSONObjBuilder b; + b.appendTimestamp( "a", std::numeric_limits<unsigned long long>::max() ); + in = b.obj(); + } + s->setObject( "a" , in ); + + ASSERT_FALSE( s->exec( "x = tojson( a ); " ,"foo" , false , true , false ) ); + } + }; + class WeirdObjects { public: @@ -1618,6 +1640,22 @@ namespace JSTests { } }; + class TimestampMax : public TestRoundTrip { + virtual BSONObj bson() const { + BSONObjBuilder b; + b.appendMaxForType( "a", mongo::Timestamp ); + BSONObj o = b.obj(); + return o; + } + virtual string json() const { + OpTime opTime = OpTime::max(); + stringstream ss; + ss << "{ \"a\" : Timestamp( " << opTime.getSecs() << ", " << opTime.getInc() + << " ) }"; + return ss.str(); + } + }; + class Regex : public TestRoundTrip { virtual BSONObj bson() const { BSONObjBuilder b; @@ -2039,6 +2077,7 @@ namespace JSTests { add< TypeConservation >(); add< NumberLong >(); add< NumberLong2 >(); + add< InvalidTimestamp >(); add< RenameTest >(); add< WeirdObjects >(); @@ -2095,6 +2134,7 @@ namespace JSTests { add< RoundTripTests::DateNonzero >(); add< RoundTripTests::DateNegative >(); add< RoundTripTests::Timestamp >(); + add< RoundTripTests::TimestampMax >(); add< RoundTripTests::Regex >(); add< RoundTripTests::RegexWithQuotes >(); add< RoundTripTests::UnquotedFieldName >(); diff --git a/src/mongo/scripting/engine_v8.cpp b/src/mongo/scripting/engine_v8.cpp index 938e59a8033..ef0aaf8bcf9 100644 --- a/src/mongo/scripting/engine_v8.cpp +++ b/src/mongo/scripting/engine_v8.cpp @@ -1442,10 +1442,21 @@ namespace mongo { argv[1] = v8::String::New(ss.str().c_str()); return BinDataFT()->GetFunction()->NewInstance(2, argv); } - case mongo::Timestamp: + case mongo::Timestamp: { + v8::TryCatch tryCatch; + argv[0] = v8::Number::New(elem.timestampTime() / 1000); argv[1] = v8::Number::New(elem.timestampInc()); - return TimestampFT()->GetFunction()->NewInstance(2,argv); + + v8::Handle<v8::Value> ret = TimestampFT()->GetFunction()->NewInstance(2,argv); + uassert(17355, str::stream() << "Error converting " << elem.toString(false) + << " in field " << elem.fieldName() + << " to a JS Timestamp object: " + << toSTLString(tryCatch.Exception()), + !tryCatch.HasCaught()); + + return ret; + } case mongo::NumberLong: nativeUnsignedLong = elem.numberLong(); // values above 2^53 are not accurately represented in JS diff --git a/src/mongo/scripting/v8_db.cpp b/src/mongo/scripting/v8_db.cpp index cf32eb502cb..f7f2bce13d4 100644 --- a/src/mongo/scripting/v8_db.cpp +++ b/src/mongo/scripting/v8_db.cpp @@ -743,7 +743,7 @@ namespace mongo { return v8AssertionException("Timestamp increment must be a number"); } int64_t t = args[0]->IntegerValue(); - int64_t largestVal = ((2039LL-1970LL) *365*24*60*60); //seconds between 1970-2038 + int64_t largestVal = int64_t(OpTime::max().getSecs()); if( t > largestVal ) return v8AssertionException( str::stream() << "The first argument must be in seconds; " |