summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2011-12-15 09:35:47 +0100
committerAntonin Kral <a.kral@bobek.cz>2011-12-15 09:35:47 +0100
commitf0d9a01bccdaeb466c12c92057914bbfef59526c (patch)
tree7679efa1f0daf7d1d906882a15dc77af6b7aef32 /util
parent5d342a758c6095b4d30aba0750b54f13b8916f51 (diff)
downloadmongodb-f0d9a01bccdaeb466c12c92057914bbfef59526c.tar.gz
Imported Upstream version 2.0.2
Diffstat (limited to 'util')
-rw-r--r--util/concurrency/rwlock.h2
-rw-r--r--util/concurrency/spin_lock.cpp31
-rw-r--r--util/concurrency/value.h69
-rw-r--r--util/concurrency/vars.cpp2
-rw-r--r--util/net/httpclient.h3
-rw-r--r--util/net/message_port.cpp1
-rw-r--r--util/net/message_server_port.cpp4
-rw-r--r--util/net/miniwebserver.cpp9
-rw-r--r--util/processinfo_win32.cpp17
-rw-r--r--util/ramlog.cpp2
-rw-r--r--util/version.cpp4
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] = ' ';