00001 // optime.h - OpTime class 00002 00003 /* Copyright 2009 10gen Inc. 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #pragma once 00019 00020 #include "../db/concurrency.h" 00021 00022 namespace mongo { 00023 void exitCleanly( ExitCode code ); 00024 00025 struct ClockSkewException : public DBException { 00026 ClockSkewException() : DBException( "clock skew exception" , 20001 ) {} 00027 }; 00028 00029 /* replsets use RSOpTime. 00030 M/S uses OpTime. 00031 But this is useable from both. 00032 */ 00033 typedef unsigned long long ReplTime; 00034 00035 /* Operation sequence #. A combination of current second plus an ordinal value. 00036 */ 00037 #pragma pack(4) 00038 class OpTime { 00039 unsigned i; 00040 unsigned secs; 00041 static OpTime last; 00042 public: 00043 static void setLast(const Date_t &date) { 00044 last = OpTime(date); 00045 } 00046 unsigned getSecs() const { 00047 return secs; 00048 } 00049 OpTime(Date_t date) { 00050 reinterpret_cast<unsigned long long&>(*this) = date.millis; 00051 } 00052 OpTime(ReplTime x) { 00053 reinterpret_cast<unsigned long long&>(*this) = x; 00054 } 00055 OpTime(unsigned a, unsigned b) { 00056 secs = a; 00057 i = b; 00058 } 00059 OpTime( const OpTime& other ) { 00060 secs = other.secs; 00061 i = other.i; 00062 } 00063 OpTime() { 00064 secs = 0; 00065 i = 0; 00066 } 00067 static OpTime now() { 00068 unsigned t = (unsigned) time(0); 00069 if ( t < last.secs ) { 00070 bool toLog = false; 00071 ONCE toLog = true; 00072 RARELY toLog = true; 00073 if ( last.i & 0x80000000 ) 00074 toLog = true; 00075 if ( toLog ) 00076 log() << "clock skew detected prev: " << last.secs << " now: " << t << " trying to handle..." << endl; 00077 if ( last.i & 0x80000000 ) { 00078 log() << "ERROR Large clock skew detected, shutting down" << endl; 00079 throw ClockSkewException(); 00080 } 00081 t = last.secs; 00082 } 00083 if ( last.secs == t ) { 00084 last.i++; 00085 return last; 00086 } 00087 last = OpTime(t, 1); 00088 return last; 00089 } 00090 00091 /* We store OpTime's in the database as BSON Date datatype -- we needed some sort of 00092 64 bit "container" for these values. While these are not really "Dates", that seems a 00093 better choice for now than say, Number, which is floating point. Note the BinData type 00094 is perhaps the cleanest choice, lacking a true unsigned64 datatype, but BinData has 5 00095 bytes of overhead. 00096 */ 00097 unsigned long long asDate() const { 00098 return reinterpret_cast<const unsigned long long*>(&i)[0]; 00099 } 00100 long long asLL() const { 00101 return reinterpret_cast<const long long*>(&i)[0]; 00102 } 00103 00104 bool isNull() const { return secs == 0; } 00105 00106 string toStringLong() const { 00107 char buf[64]; 00108 time_t_to_String(secs, buf); 00109 stringstream ss; 00110 ss << time_t_to_String_short(secs) << ' '; 00111 ss << hex << secs << ':' << i; 00112 return ss.str(); 00113 } 00114 00115 string toStringPretty() const { 00116 stringstream ss; 00117 ss << time_t_to_String_short(secs) << ':' << hex << i; 00118 return ss.str(); 00119 } 00120 00121 string toString() const { 00122 stringstream ss; 00123 ss << hex << secs << ':' << i; 00124 return ss.str(); 00125 } 00126 00127 bool operator==(const OpTime& r) const { 00128 return i == r.i && secs == r.secs; 00129 } 00130 bool operator!=(const OpTime& r) const { 00131 return !(*this == r); 00132 } 00133 bool operator<(const OpTime& r) const { 00134 if ( secs != r.secs ) 00135 return secs < r.secs; 00136 return i < r.i; 00137 } 00138 bool operator<=(const OpTime& r) const { 00139 return *this < r || *this == r; 00140 } 00141 bool operator>(const OpTime& r) const { 00142 return !(*this <= r); 00143 } 00144 bool operator>=(const OpTime& r) const { 00145 return !(*this < r); 00146 } 00147 }; 00148 #pragma pack() 00149 00150 } // namespace mongo