From f3cfb889da2bb934ae12c87757569df87b392d61 Mon Sep 17 00:00:00 2001 From: dwight Date: Sat, 14 May 2011 20:16:24 -0400 Subject: [PATCH] check we are in writelock on optime::now. also tune it a bit --- SConstruct | 6 +++--- client/mongo_client_lib.cpp | 2 +- db/common.cpp | 26 ++++++++++++++++++++++++++ db/jsobj.cpp | 7 ------- db/oplog.cpp | 7 ++++--- dbtests/jsobjtests.cpp | 7 +++++++ util/optime.h | 25 ++++++++++--------------- 7 files changed, 51 insertions(+), 29 deletions(-) diff --git a/SConstruct b/SConstruct index 3ae4c04dec6..686c71de1ec 100644 --- a/SConstruct +++ b/SConstruct @@ -311,7 +311,7 @@ if has_option( "full" ): # ------ SOURCE FILE SETUP ----------- -commonFiles = Split( "pch.cpp buildinfo.cpp db/common.cpp db/indexkey.cpp db/jsobj.cpp bson/oid.cpp db/json.cpp db/lasterror.cpp db/nonce.cpp db/queryutil.cpp db/querypattern.cpp db/projection.cpp shell/mongo.cpp db/security_key.cpp" ) +commonFiles = Split( "pch.cpp buildinfo.cpp db/indexkey.cpp db/jsobj.cpp bson/oid.cpp db/json.cpp db/lasterror.cpp db/nonce.cpp db/queryutil.cpp db/querypattern.cpp db/projection.cpp shell/mongo.cpp db/security_key.cpp" ) commonFiles += [ "util/background.cpp" , "util/sock.cpp" , "util/util.cpp" , "util/file_allocator.cpp" , "util/message.cpp" , "util/assert_util.cpp" , "util/log.cpp" , "util/ramlog.cpp" , "util/httpclient.cpp" , "util/md5main.cpp" , "util/base64.cpp", "util/concurrency/vars.cpp", "util/concurrency/task.cpp", "util/debug_util.cpp", "util/concurrency/thread_pool.cpp", "util/password.cpp", "util/version.cpp", "util/signal_handlers.cpp", @@ -324,7 +324,7 @@ commonFiles += Split( "client/connpool.cpp client/dbclient.cpp client/dbclient_r coreDbFiles = [ "db/commands.cpp" ] coreServerFiles = [ "util/message_server_port.cpp" , - "client/parallel.cpp" , + "client/parallel.cpp" , "db/common.cpp", "util/miniwebserver.cpp" , "db/dbwebserver.cpp" , "db/matcher.cpp" , "db/dbcommands_generic.cpp" ] @@ -353,7 +353,7 @@ coreServerFiles += processInfoFiles if has_option( "asio" ): coreServerFiles += [ "util/message_server_asio.cpp" ] -# mongod files - also files used in tools +# mongod files - also files used in tools. present in dbtests, but not in mongos and not in client libs. serverOnlyFiles = Split( "db/key.cpp db/btreebuilder.cpp util/logfile.cpp util/alignedbuilder.cpp db/mongommf.cpp db/dur.cpp db/durop.cpp db/dur_writetodatafiles.cpp db/dur_preplogbuffer.cpp db/dur_commitjob.cpp db/dur_recover.cpp db/dur_journal.cpp db/query.cpp db/update.cpp db/introspect.cpp db/btree.cpp db/clientcursor.cpp db/tests.cpp db/repl.cpp db/repl/rs.cpp db/repl/consensus.cpp db/repl/rs_initiate.cpp db/repl/replset_commands.cpp db/repl/manager.cpp db/repl/health.cpp db/repl/heartbeat.cpp db/repl/rs_config.cpp db/repl/rs_rollback.cpp db/repl/rs_sync.cpp db/repl/rs_initialsync.cpp db/oplog.cpp db/repl_block.cpp db/btreecursor.cpp db/cloner.cpp db/namespace.cpp db/cap.cpp db/matcher_covered.cpp db/dbeval.cpp db/restapi.cpp db/dbhelpers.cpp db/instance.cpp db/client.cpp db/database.cpp db/pdfile.cpp db/cursor.cpp db/security_commands.cpp db/security.cpp db/queryoptimizer.cpp db/queryoptimizercursor.cpp db/extsort.cpp db/cmdline.cpp" ) serverOnlyFiles += [ "db/index.cpp" ] + Glob( "db/geo/*.cpp" ) diff --git a/client/mongo_client_lib.cpp b/client/mongo_client_lib.cpp index 72bb66da887..86c27d41d21 100644 --- a/client/mongo_client_lib.cpp +++ b/client/mongo_client_lib.cpp @@ -75,7 +75,7 @@ #include "../db/lasterror.cpp" #include "../db/json.cpp" #include "../db/jsobj.cpp" -#include "../db/common.cpp" +//#include "../db/common.cpp" #include "../db/nonce.cpp" #include "../db/commands.cpp" diff --git a/db/common.cpp b/db/common.cpp index e7bd23ede8a..23bd24c4981 100644 --- a/db/common.cpp +++ b/db/common.cpp @@ -17,6 +17,7 @@ #include "pch.h" #include "concurrency.h" +#include "jsobjmanipulator.h" /** * this just has globals @@ -32,4 +33,29 @@ namespace mongo { _remapPrivateViewRequested = false; } + // OpTime::now() uses dbMutex, thus it is in this file not in the cpp files used by drivers and such + void BSONElementManipulator::initTimestamp() { + massert( 10332 , "Expected CurrentTime type", _element.type() == Timestamp ); + unsigned long long ×tamp = *( reinterpret_cast< unsigned long long* >( value() ) ); + if ( timestamp == 0 ) + timestamp = OpTime::now().asDate(); + } + + NOINLINE_DECL OpTime OpTime::skewed() { + bool toLog = false; + ONCE toLog = true; + RARELY toLog = true; + last.i++; + if ( last.i & 0x80000000 ) + toLog = true; + if ( toLog ) { + log() << "clock skew detected prev: " << last.secs << " now: " << (unsigned) time(0) << endl; + } + if ( last.i & 0x80000000 ) { + log() << "error large clock skew detected, shutting down" << endl; + throw ClockSkewException(); + } + return last; + } + } diff --git a/db/jsobj.cpp b/db/jsobj.cpp index c392a21d603..6a6aff55f31 100644 --- a/db/jsobj.cpp +++ b/db/jsobj.cpp @@ -1232,13 +1232,6 @@ namespace mongo { Labeler::Label NE( "$ne" ); Labeler::Label SIZE( "$size" ); - void BSONElementManipulator::initTimestamp() { - massert( 10332 , "Expected CurrentTime type", _element.type() == Timestamp ); - unsigned long long ×tamp = *( reinterpret_cast< unsigned long long* >( value() ) ); - if ( timestamp == 0 ) - timestamp = OpTime::now().asDate(); - } - void BSONObjBuilder::appendMinForType( const StringData& fieldName , int t ) { switch ( t ) { case MinKey: appendMinKey( fieldName ); return; diff --git a/db/oplog.cpp b/db/oplog.cpp index 8676a88254b..72f9d7dda5b 100644 --- a/db/oplog.cpp +++ b/db/oplog.cpp @@ -24,6 +24,7 @@ #include "repl/rs.h" #include "stats/counters.h" #include "../util/file.h" +#include "../util/unittest.h" #include "queryoptimizer.h" namespace mongo { @@ -506,11 +507,11 @@ namespace mongo { // ------------------------------------- - struct TestOpTime { - TestOpTime() { + struct TestOpTime : public UnitTest { + void run() { OpTime t; for ( int i = 0; i < 10; i++ ) { - OpTime s = OpTime::now(); + OpTime s = OpTime::now_inlock(); assert( s != t ); t = s; } diff --git a/dbtests/jsobjtests.cpp b/dbtests/jsobjtests.cpp index 4020e969019..67301d25e3f 100644 --- a/dbtests/jsobjtests.cpp +++ b/dbtests/jsobjtests.cpp @@ -252,6 +252,13 @@ namespace JsobjTests { class TimestampTest : public Base { public: void run() { + Client *c = currentClient.get(); + if( c == 0 ) { + Client::initThread("pretouchN"); + c = &cc(); + } + writelock lk(""); // for initTimestamp + BSONObjBuilder b; b.appendTimestamp( "a" ); BSONObj o = b.done(); diff --git a/util/optime.h b/util/optime.h index a6c1b7d1e97..917fb372392 100644 --- a/util/optime.h +++ b/util/optime.h @@ -39,6 +39,7 @@ namespace mongo { unsigned i; unsigned secs; static OpTime last; + static OpTime skewed(); public: static void setLast(const Date_t &date) { last = OpTime(date); @@ -67,29 +68,23 @@ namespace mongo { secs = 0; i = 0; } - static OpTime now() { + // it isn't generally safe to not be locked for this. so use now(). some tests use this. + static OpTime now_inlock() { unsigned t = (unsigned) time(0); - if ( t < last.secs ) { - bool toLog = false; - ONCE toLog = true; - RARELY toLog = true; - if ( last.i & 0x80000000 ) - toLog = true; - if ( toLog ) - log() << "clock skew detected prev: " << last.secs << " now: " << t << " trying to handle..." << endl; - if ( last.i & 0x80000000 ) { - log() << "ERROR Large clock skew detected, shutting down" << endl; - throw ClockSkewException(); - } - t = last.secs; - } if ( last.secs == t ) { last.i++; return last; } + if ( t < last.secs ) { + return skewed(); // separate function to keep out of the hot code path + } last = OpTime(t, 1); return last; } + static OpTime now() { + DEV dbMutex.assertWriteLocked(); + return now_inlock(); + } /* We store OpTime's in the database as BSON Date datatype -- we needed some sort of 64 bit "container" for these values. While these are not really "Dates", that seems a