From 00b9a481e421ee720a6b4274012dc14e244aa5e2 Mon Sep 17 00:00:00 2001 From: Mathias Stearn Date: Tue, 13 May 2014 15:00:52 -0400 Subject: SERVER-4740 Don't use unsigned for time deltas Leads to weird bugs when time goes backwards. This commit doesn't resolve SERVER-4740 (Use monotonic clock sources for Timer) but lessens the impact of using a non-monotonic clock. --- src/mongo/db/catalog/collection_cursor_cache.cpp | 8 ++++---- src/mongo/db/catalog/collection_cursor_cache.h | 4 ++-- src/mongo/db/clientcursor.cpp | 4 ++-- src/mongo/db/clientcursor.h | 8 ++++---- src/mongo/db/curop.h | 10 +++++----- src/mongo/db/storage/mmap_v1/dur_stats.h | 10 +++++----- src/mongo/db/storage/mmap_v1/dur_writetodatafiles.cpp | 2 +- src/mongo/dbtests/perftests.cpp | 4 ++-- src/mongo/dbtests/querytests.cpp | 3 ++- src/mongo/scripting/bench.h | 4 ++-- src/mongo/util/timer-generic-inl.h | 2 +- src/mongo/util/timer-posixclock-inl.h | 8 ++++---- src/mongo/util/timer-win32-inl.h | 2 +- src/mongo/util/timer.cpp | 6 +++--- src/mongo/util/timer.h | 18 +++++++++--------- 15 files changed, 47 insertions(+), 46 deletions(-) (limited to 'src/mongo') diff --git a/src/mongo/db/catalog/collection_cursor_cache.cpp b/src/mongo/db/catalog/collection_cursor_cache.cpp index 4ff28aa3a71..926baf7a137 100644 --- a/src/mongo/db/catalog/collection_cursor_cache.cpp +++ b/src/mongo/db/catalog/collection_cursor_cache.cpp @@ -102,7 +102,7 @@ namespace mongo { void appendStats( BSONObjBuilder& builder ); - std::size_t timeoutCursors( unsigned millisSinceLastCall ); + std::size_t timeoutCursors( int millisSinceLastCall ); int64_t nextSeed(); @@ -204,7 +204,7 @@ namespace mongo { return collection->cursorCache()->eraseCursor( id, checkAuth ); } - std::size_t GlobalCursorIdCache::timeoutCursors( unsigned millisSinceLastCall ) { + std::size_t GlobalCursorIdCache::timeoutCursors( int millisSinceLastCall ) { vector todo; { SimpleMutex::scoped_lock lk( _mutex ); @@ -235,7 +235,7 @@ namespace mongo { // --- - std::size_t CollectionCursorCache::timeoutCursorsGlobal( unsigned millisSinceLastCall ) { + std::size_t CollectionCursorCache::timeoutCursorsGlobal( int millisSinceLastCall ) { return _globalCursorIdCache.timeoutCursors( millisSinceLastCall ); } @@ -365,7 +365,7 @@ namespace mongo { } } - std::size_t CollectionCursorCache::timeoutCursors( unsigned millisSinceLastCall ) { + std::size_t CollectionCursorCache::timeoutCursors( int millisSinceLastCall ) { SimpleMutex::scoped_lock lk( _mutex ); vector toDelete; diff --git a/src/mongo/db/catalog/collection_cursor_cache.h b/src/mongo/db/catalog/collection_cursor_cache.h index 284d303391f..bc057def73f 100644 --- a/src/mongo/db/catalog/collection_cursor_cache.h +++ b/src/mongo/db/catalog/collection_cursor_cache.h @@ -72,7 +72,7 @@ namespace mongo { * note: must have a readlock on the collection * @return number timed out */ - std::size_t timeoutCursors( unsigned millisSinceLastCall ); + std::size_t timeoutCursors( int millisSinceLastCall ); // ----------------- @@ -117,7 +117,7 @@ namespace mongo { /** * @return number timed out */ - static std::size_t timeoutCursorsGlobal( unsigned millisSinceLastCall ); + static std::size_t timeoutCursorsGlobal( int millisSinceLastCall ); private: CursorId _allocateCursorId_inlock(); diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp index 5fa3654bfa8..628c4e110b7 100644 --- a/src/mongo/db/clientcursor.cpp +++ b/src/mongo/db/clientcursor.cpp @@ -152,12 +152,12 @@ namespace mongo { // Timing and timeouts // - bool ClientCursor::shouldTimeout(unsigned millis) { + bool ClientCursor::shouldTimeout(int millis) { _idleAgeMillis += millis; return _idleAgeMillis > 600000 && _pinValue == 0; } - void ClientCursor::setIdleTime( unsigned millis ) { + void ClientCursor::setIdleTime( int millis ) { _idleAgeMillis = millis; } diff --git a/src/mongo/db/clientcursor.h b/src/mongo/db/clientcursor.h index ca8aa95ca23..ae6640fa39f 100644 --- a/src/mongo/db/clientcursor.h +++ b/src/mongo/db/clientcursor.h @@ -89,9 +89,9 @@ namespace mongo { * @param millis amount of idle passed time since last call * note called outside of locks (other than ccmutex) so care must be exercised */ - bool shouldTimeout( unsigned millis ); - void setIdleTime( unsigned millis ); - unsigned idleTime() const { return _idleAgeMillis; } + bool shouldTimeout( int millis ); + void setIdleTime( int millis ); + int idleTime() const { return _idleAgeMillis; } uint64_t getLeftoverMaxTimeMicros() const { return _leftoverMaxTimeMicros; } void setLeftoverMaxTimeMicros( uint64_t leftoverMaxTimeMicros ) { @@ -184,7 +184,7 @@ namespace mongo { OpTime _slaveReadTill; // How long has the cursor been idle? - unsigned _idleAgeMillis; + int _idleAgeMillis; // TODO: Document. uint64_t _leftoverMaxTimeMicros; diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h index 9459b482bca..fa90d2322d9 100644 --- a/src/mongo/db/curop.h +++ b/src/mongo/db/curop.h @@ -255,7 +255,7 @@ namespace mongo { void ensureStarted(); bool isStarted() const { return _start > 0; } - unsigned long long startTime() { // micros + long long startTime() { // micros ensureStarted(); return _start; } @@ -264,12 +264,12 @@ namespace mongo { _end = curTimeMicros64(); } - unsigned long long totalTimeMicros() { + long long totalTimeMicros() { massert( 12601 , "CurOp not marked done yet" , ! _active ); return _end - startTime(); } int totalTimeMillis() { return (int) (totalTimeMicros() / 1000); } - unsigned long long elapsedMicros() { + long long elapsedMicros() { return curTimeMicros64() - startTime(); } int elapsedMillis() { @@ -326,8 +326,8 @@ namespace mongo { Client * _client; CurOp * _wrapped; Command * _command; - unsigned long long _start; - unsigned long long _end; + long long _start; + long long _end; bool _active; bool _suppressFromCurop; // unless $all is set int _op; diff --git a/src/mongo/db/storage/mmap_v1/dur_stats.h b/src/mongo/db/storage/mmap_v1/dur_stats.h index d97c48d5a39..2a0c98e544c 100644 --- a/src/mongo/db/storage/mmap_v1/dur_stats.h +++ b/src/mongo/db/storage/mmap_v1/dur_stats.h @@ -51,10 +51,10 @@ namespace mongo { unsigned long long _uncompressedBytes; unsigned long long _writeToDataFilesBytes; - unsigned long long _prepLogBufferMicros; - unsigned long long _writeToJournalMicros; - unsigned long long _writeToDataFilesMicros; - unsigned long long _remapPrivateViewMicros; + long long _prepLogBufferMicros; + long long _writeToJournalMicros; + long long _writeToDataFilesMicros; + long long _remapPrivateViewMicros; // undesirable to be in write lock for the group commit (it can be done in a read lock), so good if we // have visibility when this happens. can happen for a couple reasons @@ -63,7 +63,7 @@ namespace mongo { // - data being written faster than the normal group commit interval unsigned _commitsInWriteLock; - unsigned _dtMillis; + int _dtMillis; }; S *curr; private: diff --git a/src/mongo/db/storage/mmap_v1/dur_writetodatafiles.cpp b/src/mongo/db/storage/mmap_v1/dur_writetodatafiles.cpp index 02b2bf5bb44..1fbb80c2253 100644 --- a/src/mongo/db/storage/mmap_v1/dur_writetodatafiles.cpp +++ b/src/mongo/db/storage/mmap_v1/dur_writetodatafiles.cpp @@ -104,7 +104,7 @@ namespace mongo { #endif Timer t; WRITETODATAFILES_Impl1(h, uncompressed); - unsigned long long m = t.micros(); + long long m = t.micros(); stats.curr->_writeToDataFilesMicros += m; LOG(2) << "journal WRITETODATAFILES " << m / 1000.0 << "ms" << endl; } diff --git a/src/mongo/dbtests/perftests.cpp b/src/mongo/dbtests/perftests.cpp index 749d40b39f5..b88269aff90 100644 --- a/src/mongo/dbtests/perftests.cpp +++ b/src/mongo/dbtests/perftests.cpp @@ -196,7 +196,7 @@ namespace PerfTests { public: virtual unsigned batchSize() { return 50; } - void say(unsigned long long n, int us, string s) { + void say(unsigned long long n, long long us, string s) { unsigned long long rps = (n*1000*1000)/(us > 0 ? us : 1); cout << "stats " << setw(42) << left << s << ' ' << right << setw(9) << rps << ' ' << right << setw(5) << us/1000 << "ms "; if( showDurStats() ) @@ -316,7 +316,7 @@ namespace PerfTests { for( i = 0; i < Batch; i++ ) timed(); n += i; - } while( t.micros() < (unsigned) hlm * 1000 ); + } while( t.micros() < (hlm * 1000) ); } client().getLastError(); // block until all ops are finished diff --git a/src/mongo/dbtests/querytests.cpp b/src/mongo/dbtests/querytests.cpp index ff062057250..0f834d1d50c 100644 --- a/src/mongo/dbtests/querytests.cpp +++ b/src/mongo/dbtests/querytests.cpp @@ -1242,7 +1242,8 @@ namespace QueryTests { ASSERT( ! Helpers::findById( ctx.ctx().db(), ns() , BSON( "_id" << 200 ) , res ) ); - unsigned long long slow , fast; + long long slow; + long long fast; int n = 10000; DEV n = 1000; diff --git a/src/mongo/scripting/bench.h b/src/mongo/scripting/bench.h index fb78380dcd6..83f674896bb 100644 --- a/src/mongo/scripting/bench.h +++ b/src/mongo/scripting/bench.h @@ -151,7 +151,7 @@ namespace mongo { /** * Count one instance of the event, which took "timeMicros" microseconds. */ - void countOne(unsigned long long timeMicros) { + void countOne(long long timeMicros) { ++_numEvents; _totalTimeMicros += timeMicros; } @@ -168,7 +168,7 @@ namespace mongo { private: unsigned long long _numEvents; - unsigned long long _totalTimeMicros; + long long _totalTimeMicros; }; /** diff --git a/src/mongo/util/timer-generic-inl.h b/src/mongo/util/timer-generic-inl.h index 67672d206e2..c0b07c563d7 100644 --- a/src/mongo/util/timer-generic-inl.h +++ b/src/mongo/util/timer-generic-inl.h @@ -44,6 +44,6 @@ namespace mongo { - unsigned long long Timer::now() const { return curTimeMicros64(); } + long long Timer::now() const { return curTimeMicros64(); } } // namespace mongo diff --git a/src/mongo/util/timer-posixclock-inl.h b/src/mongo/util/timer-posixclock-inl.h index b0aeddedf01..a171c25ab0d 100644 --- a/src/mongo/util/timer-posixclock-inl.h +++ b/src/mongo/util/timer-posixclock-inl.h @@ -41,17 +41,17 @@ namespace mongo { - unsigned long long Timer::now() const { + long long Timer::now() const { timespec the_time; - unsigned long long result; + long long result; fassert(16160, !clock_gettime(CLOCK_MONOTONIC, &the_time)); // Safe for 292 years after the clock epoch, even if we switch to a signed time value. On // Linux, the monotonic clock's epoch is the UNIX epoch. - result = static_cast(the_time.tv_sec); + result = static_cast(the_time.tv_sec); result *= nanosPerSecond; - result += static_cast(the_time.tv_nsec); + result += static_cast(the_time.tv_nsec); return result; } diff --git a/src/mongo/util/timer-win32-inl.h b/src/mongo/util/timer-win32-inl.h index b78f6389be0..dedf77ca385 100644 --- a/src/mongo/util/timer-win32-inl.h +++ b/src/mongo/util/timer-win32-inl.h @@ -45,7 +45,7 @@ namespace mongo { - unsigned long long Timer::now() const { + long long Timer::now() const { LARGE_INTEGER i; fassert(16161, QueryPerformanceCounter(&i)); return i.QuadPart; diff --git a/src/mongo/util/timer.cpp b/src/mongo/util/timer.cpp index c5cddc96cd7..597c4e15aa5 100644 --- a/src/mongo/util/timer.cpp +++ b/src/mongo/util/timer.cpp @@ -34,7 +34,7 @@ namespace mongo { // default value of 1 so that during startup initialization if referenced no division by zero - unsigned long long Timer::_countsPerSecond = 1; + long long Timer::_countsPerSecond = 1; namespace { @@ -59,11 +59,11 @@ namespace mongo { // Make sure that the current time relative to the (unspecified) epoch isn't already too // big to represent as a 64-bit count of nanoseconds. - unsigned long long maxSecs = std::numeric_limits::max() / + long long maxSecs = std::numeric_limits::max() / Timer::nanosPerSecond; timespec the_time; fassert(16162, !clock_gettime(CLOCK_MONOTONIC, &the_time)); - fassert(16163, static_cast(the_time.tv_sec) < maxSecs); + fassert(16163, static_cast(the_time.tv_sec) < maxSecs); } #elif defined(MONGO_TIMER_IMPL_GENERIC) diff --git a/src/mongo/util/timer.h b/src/mongo/util/timer.h index 161bc98ecb9..0d5a5e97ebc 100644 --- a/src/mongo/util/timer.h +++ b/src/mongo/util/timer.h @@ -46,9 +46,9 @@ namespace mongo { */ class MONGO_CLIENT_API Timer /*copyable*/ { public: - static const unsigned long long millisPerSecond = 1000; - static const unsigned long long microsPerSecond = 1000 * millisPerSecond; - static const unsigned long long nanosPerSecond = 1000 * microsPerSecond; + static const long long millisPerSecond = 1000; + static const long long microsPerSecond = 1000 * millisPerSecond; + static const long long nanosPerSecond = 1000 * microsPerSecond; Timer() { reset(); } int seconds() const { return (int)(micros() / 1000000); } @@ -60,15 +60,15 @@ namespace mongo { * @return time in milliseconds. */ inline int millisReset() { - unsigned long long nextNow = now(); - unsigned long long deltaMicros = + const long long nextNow = now(); + const long long deltaMicros = ((nextNow - _old) * microsPerSecond) / _countsPerSecond; _old = nextNow; return static_cast(deltaMicros / 1000); } - inline unsigned long long micros() const { + inline long long micros() const { return ((now() - _old) * microsPerSecond) / _countsPerSecond; } @@ -82,12 +82,12 @@ namespace mongo { * This value is initialized at program startup, and never changed after. * It should be treated as private. */ - static unsigned long long _countsPerSecond; + static long long _countsPerSecond; private: - inline unsigned long long now() const; + inline long long now() const; - unsigned long long _old; + long long _old; }; } // namespace mongo -- cgit v1.2.1