diff options
author | Antonin Kral <a.kral@bobek.cz> | 2011-12-15 09:35:47 +0100 |
---|---|---|
committer | Antonin Kral <a.kral@bobek.cz> | 2011-12-15 09:35:47 +0100 |
commit | f0d9a01bccdaeb466c12c92057914bbfef59526c (patch) | |
tree | 7679efa1f0daf7d1d906882a15dc77af6b7aef32 /util | |
parent | 5d342a758c6095b4d30aba0750b54f13b8916f51 (diff) | |
download | mongodb-f0d9a01bccdaeb466c12c92057914bbfef59526c.tar.gz |
Imported Upstream version 2.0.2
Diffstat (limited to 'util')
-rw-r--r-- | util/concurrency/rwlock.h | 2 | ||||
-rw-r--r-- | util/concurrency/spin_lock.cpp | 31 | ||||
-rw-r--r-- | util/concurrency/value.h | 69 | ||||
-rw-r--r-- | util/concurrency/vars.cpp | 2 | ||||
-rw-r--r-- | util/net/httpclient.h | 3 | ||||
-rw-r--r-- | util/net/message_port.cpp | 1 | ||||
-rw-r--r-- | util/net/message_server_port.cpp | 4 | ||||
-rw-r--r-- | util/net/miniwebserver.cpp | 9 | ||||
-rw-r--r-- | util/processinfo_win32.cpp | 17 | ||||
-rw-r--r-- | util/ramlog.cpp | 2 | ||||
-rw-r--r-- | util/version.cpp | 4 |
11 files changed, 125 insertions, 19 deletions
diff --git a/util/concurrency/rwlock.h b/util/concurrency/rwlock.h index d8a11ea..ed5bda0 100644 --- a/util/concurrency/rwlock.h +++ b/util/concurrency/rwlock.h @@ -203,7 +203,7 @@ namespace mongo { DEV mutexDebugger.entering(_name); } void unlock() { - mutexDebugger.leaving(_name); + DEV mutexDebugger.leaving(_name); check( pthread_rwlock_unlock( &_lock ) ); } diff --git a/util/concurrency/spin_lock.cpp b/util/concurrency/spin_lock.cpp index 1811f15..52bd218 100644 --- a/util/concurrency/spin_lock.cpp +++ b/util/concurrency/spin_lock.cpp @@ -45,7 +45,36 @@ namespace mongo { #if defined(_WIN32) EnterCriticalSection(&_cs); #elif defined(__USE_XOPEN2K) - pthread_spin_lock( &_lock ); + + /** + * this is designed to perform close to the default spin lock + * the reason for the mild insanity is to prevent horrible performance + * when contention spikes + * it allows spinlocks to be used in many more places + * which is good because even with this change they are about 8x faster on linux + */ + + if ( pthread_spin_trylock( &_lock ) == 0 ) + return; + + for ( int i=0; i<1000; i++ ) + if ( pthread_spin_trylock( &_lock ) == 0 ) + return; + + for ( int i=0; i<1000; i++ ) { + if ( pthread_spin_trylock( &_lock ) == 0 ) + return; + pthread_yield(); + } + + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 5000000; + + while ( pthread_spin_trylock( &_lock ) != 0 ) { + nanosleep(&t, NULL); + } + #elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) // fast path if (!_locked && !__sync_lock_test_and_set(&_locked, true)) { diff --git a/util/concurrency/value.h b/util/concurrency/value.h index c66977b..897fa95 100644 --- a/util/concurrency/value.h +++ b/util/concurrency/value.h @@ -21,6 +21,7 @@ #pragma once #include "mutex.h" +#include "spin_lock.h" namespace mongo { @@ -36,7 +37,7 @@ namespace mongo { builds at runtime. */ template <typename T, mutex& BY> - class Guarded { + class Guarded : boost::noncopyable { T _val; public: T& ref(const scoped_lock& lk) { @@ -47,29 +48,85 @@ namespace mongo { class DiagStr { string _s; - static mutex m; + mutable SpinLock m; public: DiagStr(const DiagStr& r) : _s(r.get()) { } DiagStr() { } bool empty() const { - mutex::scoped_lock lk(m); + scoped_spinlock lk(m); return _s.empty(); } string get() const { - mutex::scoped_lock lk(m); + scoped_spinlock lk(m); return _s; } void set(const char *s) { - mutex::scoped_lock lk(m); + scoped_spinlock lk(m); _s = s; } void set(const string& s) { - mutex::scoped_lock lk(m); + scoped_spinlock lk(m); _s = s; } operator string() const { return get(); } void operator=(const string& s) { set(s); } + void operator=(const DiagStr& rhs) { + scoped_spinlock lk(m); + _s = rhs.get(); + } }; +#if 0 // not including in 2.0 + + /** Thread safe map. + Be careful not to use this too much or it could make things slow; + if not a hot code path no problem. + + Examples: + + mapsf<int,int> mp; + + int x = mp.get(); + + map<int,int> two; + mp.swap(two); + + { + mapsf<int,int>::ref r(mp); + r[9] = 1; + map<int,int>::iterator i = r.r.begin(); + } + + */ + template< class K, class V > + struct mapsf : boost::noncopyable { + SimpleMutex m; + map<K,V> val; + friend struct ref; + public: + mapsf() : m("mapsf") { } + void swap(map<K,V>& rhs) { + SimpleMutex::scoped_lock lk(m); + val.swap(rhs); + } + // safe as we pass by value: + V get(K k) { + SimpleMutex::scoped_lock lk(m); + map<K,V>::iterator i = val.find(k); + if( i == val.end() ) + return K(); + return i->second; + } + // think about deadlocks when using ref. the other methods + // above will always be safe as they are "leaf" operations. + struct ref { + SimpleMutex::scoped_lock lk; + public: + map<K,V> const &r; + ref(mapsf<K,V> &m) : lk(m.m), r(m.val) { } + V& operator[](const K& k) { return r[k]; } + }; + }; +#endif } diff --git a/util/concurrency/vars.cpp b/util/concurrency/vars.cpp index 213e576..b561ccc 100644 --- a/util/concurrency/vars.cpp +++ b/util/concurrency/vars.cpp @@ -22,8 +22,6 @@ namespace mongo { - mutex DiagStr::m("diags"); - // intentional leak. otherwise destructor orders can be problematic at termination. MutexDebugger &mutexDebugger = *(new MutexDebugger()); diff --git a/util/net/httpclient.h b/util/net/httpclient.h index c3f8c82..126969f 100644 --- a/util/net/httpclient.h +++ b/util/net/httpclient.h @@ -35,7 +35,7 @@ namespace mongo { return _entireResponse; } - const Headers getHeaders() const { + Headers getHeaders() const { return _headers; } @@ -76,4 +76,3 @@ namespace mongo { #endif }; } - diff --git a/util/net/message_port.cpp b/util/net/message_port.cpp index 9abfaf7..29764c3 100644 --- a/util/net/message_port.cpp +++ b/util/net/message_port.cpp @@ -139,6 +139,7 @@ namespace mongo { MessagingPort::MessagingPort( Socket& sock ) : Socket( sock ) , piggyBackData( 0 ) { + ports.insert(this); } void MessagingPort::shutdown() { diff --git a/util/net/message_server_port.cpp b/util/net/message_server_port.cpp index ca0b13d..ac13712 100644 --- a/util/net/message_server_port.cpp +++ b/util/net/message_server_port.cpp @@ -87,6 +87,10 @@ namespace mongo { log() << "ClockSkewException - shutting down" << endl; exitCleanly( EXIT_CLOCK_SKEW ); } + catch ( const DBException& e ) { // must be right above std::exception to avoid catching subclasses + log() << "DBException handling request, closing client connection: " << e << endl; + p->shutdown(); + } catch ( std::exception &e ) { error() << "Uncaught std::exception: " << e.what() << ", terminating" << endl; dbexit( EXIT_UNCAUGHT ); diff --git a/util/net/miniwebserver.cpp b/util/net/miniwebserver.cpp index 0793100..f0b5856 100644 --- a/util/net/miniwebserver.cpp +++ b/util/net/miniwebserver.cpp @@ -166,8 +166,13 @@ namespace mongo { ss << responseMsg; string response = ss.str(); - sock.send( response.c_str(), response.size() , "http response" ); - sock.close(); + try { + sock.send( response.c_str(), response.size() , "http response" ); + sock.close(); + } + catch ( SocketException& e ) { + log(1) << "couldn't send data to http client: " << e << endl; + } } string MiniWebServer::getHeader( const char * req , string wanted ) { diff --git a/util/processinfo_win32.cpp b/util/processinfo_win32.cpp index ec66aec..fdd88d3 100644 --- a/util/processinfo_win32.cpp +++ b/util/processinfo_win32.cpp @@ -19,7 +19,7 @@ #include "processinfo.h" #include <iostream> #include <psapi.h> - +#include "../bson/bsonobjbuilder.h" using namespace std; int getpid() { @@ -57,7 +57,20 @@ namespace mongo { return _wconvertmtos( pmc.WorkingSetSize ); } - void ProcessInfo::getExtraInfo(BSONObjBuilder& info) {} + void ProcessInfo::getExtraInfo(BSONObjBuilder& info) { + MEMORYSTATUSEX mse; + mse.dwLength = sizeof(mse); + PROCESS_MEMORY_COUNTERS pmc; + if( GetProcessMemoryInfo( GetCurrentProcess() , &pmc, sizeof(pmc) ) ) { + info.append("page_faults", static_cast<int>(pmc.PageFaultCount)); + info.append("usagePageFileMB", static_cast<int>(pmc.PagefileUsage / 1024 / 1024)); + } + if( GlobalMemoryStatusEx( &mse ) ) { + info.append("totalPageFileMB", static_cast<int>(mse.ullTotalPageFile / 1024 / 1024)); + info.append("availPageFileMB", static_cast<int>(mse.ullAvailPageFile / 1024 / 1024)); + info.append("ramMB", static_cast<int>(mse.ullTotalPhys / 1024 / 1024)); + } + } bool ProcessInfo::blockCheckSupported() { return false; diff --git a/util/ramlog.cpp b/util/ramlog.cpp index 69ffc17..d7a839a 100644 --- a/util/ramlog.cpp +++ b/util/ramlog.cpp @@ -135,7 +135,7 @@ namespace mongo { assert( strlen(v[i]) > 20 ); int r = repeats(v, i); if( r < 0 ) { - s << color( linkify( clean(v,i).c_str() ) ); + s << color( linkify( clean(v,i).c_str() ) ) << '\n'; } else { stringstream x; diff --git a/util/version.cpp b/util/version.cpp index a6efbd5..c43180c 100644 --- a/util/version.cpp +++ b/util/version.cpp @@ -38,7 +38,7 @@ namespace mongo { * 1.2.3-rc4-pre- * If you really need to do something else you'll need to fix _versionArray() */ - const char versionString[] = "2.0.0"; + const char versionString[] = "2.0.2"; // See unit test for example outputs static BSONArray _versionArray(const char* version){ @@ -168,7 +168,7 @@ namespace mongo { f.open("/proc/self/numa_maps", /*read_only*/true); if ( f.is_open() && ! f.bad() ) { char line[100]; //we only need the first line - f.read(0, line, sizeof(line)); + assert( read(f.fd, line, sizeof(line)) <= 100 ); // just in case... line[98] = ' '; |