2009-04-24 00:02:51 +02:00
|
|
|
// optime.h - OpTime class
|
|
|
|
|
2009-10-27 20:58:27 +01:00
|
|
|
/* Copyright 2009 10gen Inc.
|
2009-04-24 00:02:51 +02:00
|
|
|
*
|
2009-10-27 20:58:27 +01:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2009-04-24 00:02:51 +02:00
|
|
|
*
|
2009-10-27 20:58:27 +01:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2009-04-24 00:02:51 +02:00
|
|
|
*
|
2009-10-27 20:58:27 +01:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2009-04-24 00:02:51 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2009-10-14 22:29:32 +02:00
|
|
|
#include "../db/concurrency.h"
|
|
|
|
|
2009-04-24 00:02:51 +02:00
|
|
|
namespace mongo {
|
2010-06-04 01:28:31 +02:00
|
|
|
void exitCleanly( ExitCode code );
|
2011-01-04 06:40:41 +01:00
|
|
|
|
2010-03-08 21:55:18 +01:00
|
|
|
struct ClockSkewException : public DBException {
|
2011-01-04 06:40:41 +01:00
|
|
|
ClockSkewException() : DBException( "clock skew exception" , 20001 ) {}
|
2010-03-08 21:55:18 +01:00
|
|
|
};
|
2010-05-11 21:18:07 +02:00
|
|
|
|
2010-06-27 03:31:17 +02:00
|
|
|
/* replsets use RSOpTime.
|
2010-06-01 17:08:27 +02:00
|
|
|
M/S uses OpTime.
|
|
|
|
But this is useable from both.
|
|
|
|
*/
|
|
|
|
typedef unsigned long long ReplTime;
|
|
|
|
|
2010-05-11 21:18:07 +02:00
|
|
|
/* Operation sequence #. A combination of current second plus an ordinal value.
|
|
|
|
*/
|
2009-04-24 00:02:51 +02:00
|
|
|
#pragma pack(4)
|
|
|
|
class OpTime {
|
|
|
|
unsigned i;
|
|
|
|
unsigned secs;
|
|
|
|
static OpTime last;
|
|
|
|
public:
|
2010-03-08 21:55:18 +01:00
|
|
|
static void setLast(const Date_t &date) {
|
|
|
|
last = OpTime(date);
|
|
|
|
}
|
2009-04-24 00:02:51 +02:00
|
|
|
unsigned getSecs() const {
|
|
|
|
return secs;
|
|
|
|
}
|
2009-12-03 23:25:22 +01:00
|
|
|
OpTime(Date_t date) {
|
|
|
|
reinterpret_cast<unsigned long long&>(*this) = date.millis;
|
|
|
|
}
|
2010-06-01 17:08:27 +02:00
|
|
|
OpTime(ReplTime x) {
|
|
|
|
reinterpret_cast<unsigned long long&>(*this) = x;
|
2009-04-24 00:02:51 +02:00
|
|
|
}
|
|
|
|
OpTime(unsigned a, unsigned b) {
|
|
|
|
secs = a;
|
|
|
|
i = b;
|
|
|
|
}
|
|
|
|
OpTime() {
|
|
|
|
secs = 0;
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
static OpTime now() {
|
|
|
|
unsigned t = (unsigned) time(0);
|
2011-01-04 06:40:41 +01:00
|
|
|
if ( t < last.secs ) {
|
2010-03-08 21:55:18 +01:00
|
|
|
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();
|
|
|
|
}
|
2010-03-05 05:14:03 +01:00
|
|
|
t = last.secs;
|
|
|
|
}
|
2009-04-24 00:02:51 +02:00
|
|
|
if ( last.secs == t ) {
|
|
|
|
last.i++;
|
|
|
|
return last;
|
|
|
|
}
|
|
|
|
last = OpTime(t, 1);
|
2011-01-04 06:40:41 +01:00
|
|
|
return last;
|
2009-04-24 00:02:51 +02:00
|
|
|
}
|
2011-01-04 06:40:41 +01:00
|
|
|
|
2009-04-24 00:02:51 +02:00
|
|
|
/* 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
|
|
|
|
better choice for now than say, Number, which is floating point. Note the BinData type
|
2011-01-04 06:40:41 +01:00
|
|
|
is perhaps the cleanest choice, lacking a true unsigned64 datatype, but BinData has 5
|
2009-04-24 00:02:51 +02:00
|
|
|
bytes of overhead.
|
|
|
|
*/
|
|
|
|
unsigned long long asDate() const {
|
2010-07-26 22:25:15 +02:00
|
|
|
return reinterpret_cast<const unsigned long long*>(&i)[0];
|
2009-04-24 00:02:51 +02:00
|
|
|
}
|
2010-06-28 23:29:15 +02:00
|
|
|
long long asLL() const {
|
2010-07-26 22:25:15 +02:00
|
|
|
return reinterpret_cast<const long long*>(&i)[0];
|
2010-06-28 23:29:15 +02:00
|
|
|
}
|
2011-01-04 06:40:41 +01:00
|
|
|
|
2010-06-29 21:52:35 +02:00
|
|
|
bool isNull() const { return secs == 0; }
|
2011-01-04 06:40:41 +01:00
|
|
|
|
2009-04-24 00:02:51 +02:00
|
|
|
string toStringLong() const {
|
|
|
|
char buf[64];
|
|
|
|
time_t_to_String(secs, buf);
|
|
|
|
stringstream ss;
|
2010-08-18 00:23:40 +02:00
|
|
|
ss << time_t_to_String_short(secs) << ' ';
|
2009-04-24 00:02:51 +02:00
|
|
|
ss << hex << secs << ':' << i;
|
|
|
|
return ss.str();
|
|
|
|
}
|
2011-01-04 06:40:41 +01:00
|
|
|
|
2010-07-06 22:11:56 +02:00
|
|
|
string toStringPretty() const {
|
|
|
|
stringstream ss;
|
2010-07-12 14:54:37 +02:00
|
|
|
ss << time_t_to_String_short(secs) << ':' << hex << i;
|
2010-07-06 22:11:56 +02:00
|
|
|
return ss.str();
|
|
|
|
}
|
2011-01-04 06:40:41 +01:00
|
|
|
|
2009-04-24 00:02:51 +02:00
|
|
|
string toString() const {
|
|
|
|
stringstream ss;
|
|
|
|
ss << hex << secs << ':' << i;
|
|
|
|
return ss.str();
|
|
|
|
}
|
2010-07-18 04:11:21 +02:00
|
|
|
|
2009-04-24 00:02:51 +02:00
|
|
|
bool operator==(const OpTime& r) const {
|
|
|
|
return i == r.i && secs == r.secs;
|
|
|
|
}
|
|
|
|
bool operator!=(const OpTime& r) const {
|
|
|
|
return !(*this == r);
|
|
|
|
}
|
|
|
|
bool operator<(const OpTime& r) const {
|
|
|
|
if ( secs != r.secs )
|
|
|
|
return secs < r.secs;
|
|
|
|
return i < r.i;
|
|
|
|
}
|
2011-01-04 06:40:41 +01:00
|
|
|
bool operator<=(const OpTime& r) const {
|
2010-06-27 03:31:17 +02:00
|
|
|
return *this < r || *this == r;
|
|
|
|
}
|
2011-01-04 06:40:41 +01:00
|
|
|
bool operator>(const OpTime& r) const {
|
2010-07-21 21:39:59 +02:00
|
|
|
return !(*this <= r);
|
|
|
|
}
|
2010-08-02 20:03:33 +02:00
|
|
|
bool operator>=(const OpTime& r) const {
|
|
|
|
return !(*this < r);
|
|
|
|
}
|
2009-04-24 00:02:51 +02:00
|
|
|
};
|
|
|
|
#pragma pack()
|
2011-01-04 06:40:41 +01:00
|
|
|
|
2009-04-24 21:15:52 +02:00
|
|
|
} // namespace mongo
|