diff options
Diffstat (limited to 'src/mongo/bson/optime.cpp')
| -rw-r--r-- | src/mongo/bson/optime.cpp | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/mongo/bson/optime.cpp b/src/mongo/bson/optime.cpp new file mode 100644 index 00000000000..6cc01969366 --- /dev/null +++ b/src/mongo/bson/optime.cpp @@ -0,0 +1,105 @@ +/* Copyright 2009 10gen Inc. + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +#include "mongo/bson/optime.h" + +#include <iostream> +#include <limits> +#include <ctime> + +#include "mongo/bson/inline_decls.h" +#include "mongo/util/debug_util.h" +#include "mongo/util/log.h" +#include "mongo/util/startup_test.h" + +namespace mongo { + + OpTime OpTime::last(0, 0); + boost::condition OpTime::notifier; + mongo::mutex OpTime::m("optime"); + + 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) + << std::endl; + } + if ( last.i & 0x80000000 ) { + log() << "error large clock skew detected, shutting down" << std::endl; + throw ClockSkewException(); + } + return last; + } + + /*static*/ OpTime OpTime::_now() { + OpTime result; + unsigned t = (unsigned) time(0); + if ( last.secs == t ) { + last.i++; + result = last; + } + else if ( t < last.secs ) { + result = skewed(); // separate function to keep out of the hot code path + } + else { + last = OpTime(t, 1); + result = last; + } + notifier.notify_all(); + return last; + } + + OpTime OpTime::now(const mongo::mutex::scoped_lock&) { + return _now(); + } + + OpTime OpTime::getLast(const mongo::mutex::scoped_lock&) { + 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) { + if (!notifier.timed_wait(lk.boost(), boost::posix_time::milliseconds(millis))) + return; // timed out + } + } + + struct TestOpTime : public StartupTest { + void run() { + OpTime t; + for ( int i = 0; i < 10; i++ ) { + OpTime s = OpTime::_now(); + verify( s != t ); + t = s; + } + OpTime q = t; + verify( q == t ); + verify( !(q != t) ); + } + } testoptime; + +} |
