diff options
Diffstat (limited to 'util/top.h')
-rw-r--r-- | util/top.h | 183 |
1 files changed, 0 insertions, 183 deletions
diff --git a/util/top.h b/util/top.h deleted file mode 100644 index aaf7c3f..0000000 --- a/util/top.h +++ /dev/null @@ -1,183 +0,0 @@ -// top.h : DB usage monitor. - -/* 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. - */ - -#pragma once - -#include <boost/date_time/posix_time/posix_time.hpp> -#undef assert -#define assert xassert - -namespace mongo { - - /* Records per namespace utilization of the mongod process. - No two functions of this class may be called concurrently. - */ - class Top { - typedef boost::posix_time::ptime T; - typedef boost::posix_time::time_duration D; - typedef boost::tuple< D, int, int, int > UsageData; - public: - Top() : _read(false), _write(false) { } - - /* these are used to record activity: */ - - void clientStart( const char *client ) { - clientStop(); - _currentStart = currentTime(); - _current = client; - } - - /* indicate current request is a read operation. */ - void setRead() { _read = true; } - - void setWrite() { _write = true; } - - void clientStop() { - if ( _currentStart == T() ) - return; - D d = currentTime() - _currentStart; - - { - boostlock L(topMutex); - recordUsage( _current, d ); - } - - _currentStart = T(); - _read = false; - _write = false; - } - - /* these are used to fetch the stats: */ - - struct Usage { - string ns; - D time; - double pct; - int reads, writes, calls; - }; - - static void usage( vector< Usage > &res ) { - boostlock L(topMutex); - - // Populate parent namespaces - UsageMap snapshot; - UsageMap totalUsage; - fillParentNamespaces( snapshot, _snapshot ); - fillParentNamespaces( totalUsage, _totalUsage ); - - multimap< D, string, more > sorted; - for( UsageMap::iterator i = snapshot.begin(); i != snapshot.end(); ++i ) - sorted.insert( make_pair( i->second.get<0>(), i->first ) ); - for( multimap< D, string, more >::iterator i = sorted.begin(); i != sorted.end(); ++i ) { - if ( trivialNs( i->second.c_str() ) ) - continue; - Usage u; - u.ns = i->second; - u.time = totalUsage[ u.ns ].get<0>(); - u.pct = _snapshotDuration != D() ? 100.0 * i->first.ticks() / _snapshotDuration.ticks() : 0; - u.reads = snapshot[ u.ns ].get<1>(); - u.writes = snapshot[ u.ns ].get<2>(); - u.calls = snapshot[ u.ns ].get<3>(); - res.push_back( u ); - } - for( UsageMap::iterator i = totalUsage.begin(); i != totalUsage.end(); ++i ) { - if ( snapshot.count( i->first ) != 0 || trivialNs( i->first.c_str() ) ) - continue; - Usage u; - u.ns = i->first; - u.time = i->second.get<0>(); - u.pct = 0; - u.reads = 0; - u.writes = 0; - u.calls = 0; - res.push_back( u ); - } - } - - static void completeSnapshot() { - boostlock L(topMutex); - - if ( &_snapshot == &_snapshotA ) { - _snapshot = _snapshotB; - _nextSnapshot = _snapshotA; - } else { - _snapshot = _snapshotA; - _nextSnapshot = _snapshotB; - } - _snapshotDuration = currentTime() - _snapshotStart; - _snapshotStart = currentTime(); - _nextSnapshot.clear(); - } - - private: - static boost::mutex topMutex; - static bool trivialNs( const char *ns ) { - const char *ret = strrchr( ns, '.' ); - return ret && ret[ 1 ] == '\0'; - } - typedef map<string,UsageData> UsageMap; // duration, # reads, # writes, # total calls - static T currentTime() { - return boost::posix_time::microsec_clock::universal_time(); - } - void recordUsage( const string &client, D duration ) { - recordUsageForMap( _totalUsage, client, duration ); - recordUsageForMap( _nextSnapshot, client, duration ); - } - void recordUsageForMap( UsageMap &map, const string &client, D duration ) { - UsageData& g = map[client]; - g.get< 0 >() += duration; - if ( _read && !_write ) - g.get< 1 >()++; - else if ( !_read && _write ) - g.get< 2 >()++; - g.get< 3 >()++; - } - static void fillParentNamespaces( UsageMap &to, const UsageMap &from ) { - for( UsageMap::const_iterator i = from.begin(); i != from.end(); ++i ) { - string current = i->first; - size_t dot = current.rfind( "." ); - if ( dot == string::npos || dot != current.length() - 1 ) { - inc( to[ current ], i->second ); - } - while( dot != string::npos ) { - current = current.substr( 0, dot ); - inc( to[ current ], i->second ); - dot = current.rfind( "." ); - } - } - } - static void inc( UsageData &to, const UsageData &from ) { - to.get<0>() += from.get<0>(); - to.get<1>() += from.get<1>(); - to.get<2>() += from.get<2>(); - to.get<3>() += from.get<3>(); - } - struct more { bool operator()( const D &a, const D &b ) { return a > b; } }; - string _current; - T _currentStart; - static T _snapshotStart; - static D _snapshotDuration; - static UsageMap _totalUsage; - static UsageMap _snapshotA; - static UsageMap _snapshotB; - static UsageMap &_snapshot; - static UsageMap &_nextSnapshot; - bool _read; - bool _write; - }; - -} // namespace mongo |