diff options
author | Aaron <aaron@10gen.com> | 2010-03-08 12:55:18 -0800 |
---|---|---|
committer | Aaron <aaron@10gen.com> | 2010-03-09 10:00:18 -0800 |
commit | 447c9df927ded60e696086e98c1ca6a15b207756 (patch) | |
tree | 98b2ccc573da23b56cd8cbde729f128f15033bd2 | |
parent | 063f651c6bcaa321ad2cb9bc534b724ce60aef6a (diff) | |
download | mongo-447c9df927ded60e696086e98c1ca6a15b207756.tar.gz |
SERVER-705 check for negative effects of large clock skews, seed last optime using oplog
-rw-r--r-- | db/db.cpp | 8 | ||||
-rw-r--r-- | db/db.h | 2 | ||||
-rw-r--r-- | db/instance.cpp | 3 | ||||
-rw-r--r-- | db/repl.cpp | 8 | ||||
-rw-r--r-- | stdafx.h | 1 | ||||
-rw-r--r-- | util/optime.h | 21 |
6 files changed, 37 insertions, 6 deletions
diff --git a/db/db.cpp b/db/db.cpp index f8f1d10bcfd..489287d2773 100644 --- a/db/db.cpp +++ b/db/db.cpp @@ -943,13 +943,13 @@ namespace mongo { #undef out - void exitCleanly() { + void exitCleanly( ExitCode code ) { goingAway = true; killCurrentOp = 1; { dblock lk; log() << "now exiting" << endl; - dbexit( EXIT_KILL ); + dbexit( code ); } } @@ -995,7 +995,7 @@ namespace mongo { int x; sigwait( &asyncSignals, &x ); log() << "got kill or ctrl c signal " << x << " (" << strsignal( x ) << "), will terminate after current cmd ends" << endl; - exitCleanly(); + exitCleanly( EXIT_KILL ); } void setupSignals() { @@ -1018,7 +1018,7 @@ namespace mongo { #else void ctrlCTerminate() { log() << "got kill or ctrl c signal, will terminate after current cmd ends" << endl; - exitCleanly(); + exitCleanly( EXIT_KILL ); } BOOL CtrlHandler( DWORD fdwCtrlType ) { @@ -129,6 +129,8 @@ namespace mongo { } }; + void exitCleanly( ExitCode code ); + } // namespace mongo #include "dbinfo.h" diff --git a/db/instance.cpp b/db/instance.cpp index 6b83ba4a0ad..83cf0be4271 100644 --- a/db/instance.cpp +++ b/db/instance.cpp @@ -262,6 +262,9 @@ namespace mongo { ss << " exception " + e.toString(); log = true; } + catch ( ClockSkewException &e ) { + exitCleanly( EXIT_CLOCK_SKEW ); + } } else if ( op == dbKillCursors ) { OPREAD; diff --git a/db/repl.cpp b/db/repl.cpp index 331dd12fbcf..d6778f116fe 100644 --- a/db/repl.cpp +++ b/db/repl.cpp @@ -1644,8 +1644,14 @@ namespace mongo { const char * ns = "local.oplog.$main"; setClient(ns); - if ( nsdetails( ns ) ) + if ( nsdetails( ns ) ) { + DBDirectClient c; + BSONObj lastOp = c.findOne( ns, Query().sort( BSON( "$natural" << -1 ) ) ); + if ( !lastOp.isEmpty() ) { + OpTime::setLast( lastOp[ "ts" ].date() ); + } return; + } /* create an oplog collection, if it doesn't yet exist. */ BSONObjBuilder b; @@ -53,6 +53,7 @@ namespace mongo { EXIT_OOM_MALLOC = 42 , EXIT_OOM_REALLOC = 43 , EXIT_FS = 45 , + EXIT_CLOCK_SKEW = 47 , EXIT_POSSIBLE_CORRUPTION = 60 , // this means we detected a possible corruption situation, like a buf overflow EXIT_UNCAUGHT = 100 , // top level exception that wasn't caught EXIT_TEST = 101 , diff --git a/util/optime.h b/util/optime.h index 4e523a6409c..de4465e2bbe 100644 --- a/util/optime.h +++ b/util/optime.h @@ -20,15 +20,24 @@ #include "../db/concurrency.h" namespace mongo { + void exitCleanly( int code ); /* Operation sequence #. A combination of current second plus an ordinal value. */ + struct ClockSkewException : public DBException { + virtual const char* what() const throw() { return "clock skew exception"; } + virtual int getCode(){ return 20001; } + }; + #pragma pack(4) class OpTime { unsigned i; unsigned secs; static OpTime last; public: + static void setLast(const Date_t &date) { + last = OpTime(date); + } unsigned getSecs() const { return secs; } @@ -47,7 +56,17 @@ namespace mongo { unsigned t = (unsigned) time(0); // DEV assertInWriteLock(); if ( t < last.secs ){ - log() << "clock skew detected prev: " << last.secs << " now: " << t << " trying to handle..." << endl; + 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 ) { |