summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/SConscript.client1
-rw-r--r--src/mongo/bson/bsonobjbuilder_test.cpp13
-rw-r--r--src/mongo/bson/optime.cpp7
-rw-r--r--src/mongo/bson/optime.h3
-rw-r--r--src/mongo/db/jsobj.cpp2
-rw-r--r--src/mongo/dbtests/jstests.cpp40
-rw-r--r--src/mongo/scripting/engine_v8.cpp15
-rw-r--r--src/mongo/scripting/v8_db.cpp2
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; "