diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/assert_util.cpp | 1 | ||||
-rw-r--r-- | util/concurrency/spin_lock.h | 10 | ||||
-rw-r--r-- | util/concurrency/value.h | 35 | ||||
-rw-r--r-- | util/concurrency/vars.cpp | 2 | ||||
-rw-r--r-- | util/message.cpp | 45 | ||||
-rw-r--r-- | util/ramlog.h | 3 | ||||
-rw-r--r-- | util/sock.h | 4 | ||||
-rw-r--r-- | util/version.cpp | 42 |
8 files changed, 97 insertions, 45 deletions
diff --git a/util/assert_util.cpp b/util/assert_util.cpp index 47be5e9..8280d8b 100644 --- a/util/assert_util.cpp +++ b/util/assert_util.cpp @@ -91,6 +91,7 @@ namespace mongo { void uasserted(int msgid, const char *msg) { assertionCount.condrollover( ++assertionCount.user ); + LOG(1) << "User Assertion: " << msgid << ":" << msg << endl; raiseError(msgid,msg); throw UserException(msgid, msg); } diff --git a/util/concurrency/spin_lock.h b/util/concurrency/spin_lock.h index d5360f7..02a8797 100644 --- a/util/concurrency/spin_lock.h +++ b/util/concurrency/spin_lock.h @@ -49,6 +49,16 @@ namespace mongo { SpinLock(SpinLock&); SpinLock& operator=(SpinLock&); }; + + struct scoped_spinlock { + scoped_spinlock( SpinLock& l ) : _l(l){ + _l.lock(); + } + ~scoped_spinlock() { + _l.unlock(); + } + SpinLock& _l; + }; } // namespace mongo diff --git a/util/concurrency/value.h b/util/concurrency/value.h index 08d5306..0a0ef85 100644 --- a/util/concurrency/value.h +++ b/util/concurrency/value.h @@ -60,28 +60,31 @@ namespace mongo { }; }; - /** this string COULD be mangled but with the double buffering, assuming writes - are infrequent, it's unlikely. thus, this is reasonable for lockless setting of - diagnostic strings, where their content isn't critical. - */ class DiagStr { - char buf1[256]; - char buf2[256]; - char *p; + string _s; + static mutex m; public: - DiagStr() { - memset(buf1, 0, 256); - memset(buf2, 0, 256); - p = buf1; + DiagStr(const DiagStr& r) : _s(r.get()) { } + DiagStr() { } + bool empty() const { + mutex::scoped_lock lk(m); + return _s.empty(); + } + string get() const { + mutex::scoped_lock lk(m); + return _s; } - - const char * get() const { return p; } void set(const char *s) { - char *q = (p==buf1) ? buf2 : buf1; - strncpy(q, s, 255); - p = q; + mutex::scoped_lock lk(m); + _s = s; + } + void set(const string& s) { + mutex::scoped_lock lk(m); + _s = s; } + operator string() const { return get(); } + void operator=(const string& s) { set(s); } }; } diff --git a/util/concurrency/vars.cpp b/util/concurrency/vars.cpp index 3d057a4..19b58eb 100644 --- a/util/concurrency/vars.cpp +++ b/util/concurrency/vars.cpp @@ -22,6 +22,8 @@ namespace mongo { + mutex DiagStr::m("diags"); + mongo::mutex _atomicMutex("_atomicMutex"); // intentional leak. otherwise destructor orders can be problematic at termination. diff --git a/util/message.cpp b/util/message.cpp index 916aa34..bcb1772 100644 --- a/util/message.cpp +++ b/util/message.cpp @@ -359,7 +359,7 @@ namespace mongo { ConnectBG(int sock, SockAddr farEnd) : _sock(sock), _farEnd(farEnd) { } void run() { _res = ::connect(_sock, _farEnd.raw(), _farEnd.addressSize); } - string name() const { return ""; /* too short lived to need to name */ } + string name() const { return "ConnectBG"; } int inError() const { return _res; } private: @@ -628,12 +628,20 @@ again: unsigned retries = 0; while( len > 0 ) { int ret = ::recv( sock , buf , len , portRecvFlags ); - if ( ret == 0 ) { + if ( ret > 0 ) { + if ( len <= 4 && ret != len ) + log(_logLevel) << "MessagingPort recv() got " << ret << " bytes wanted len=" << len << endl; + assert( ret <= len ); + len -= ret; + buf += ret; + } + else if ( ret == 0 ) { log(3) << "MessagingPort recv() conn closed? " << farEnd.toString() << endl; throw SocketException( SocketException::CLOSED ); } - if ( ret < 0 ) { + else { /* ret < 0 */ int e = errno; + #if defined(EINTR) && !defined(_WIN32) if( e == EINTR ) { if( ++retries == 1 ) { @@ -642,29 +650,18 @@ again: } } #endif - if ( e != EAGAIN || _timeout == 0 ) { - SocketException::Type t = SocketException::RECV_ERROR; -#if defined(_WINDOWS) - if( e == WSAETIMEDOUT ) t = SocketException::RECV_TIMEOUT; -#else - /* todo: what is the error code on an SO_RCVTIMEO on linux? EGAIN? EWOULDBLOCK? */ + if ( ( e == EAGAIN +#ifdef _WINDOWS + || e == WSAETIMEDOUT #endif - log(_logLevel) << "MessagingPort recv() " << errnoWithDescription(e) << " " << farEnd.toString() <<endl; - throw SocketException(t); - } - else { - if ( !serverAlive( farEnd.toString() ) ) { - log(_logLevel) << "MessagingPort recv() remote dead " << farEnd.toString() << endl; - throw SocketException( SocketException::RECV_ERROR ); - } + ) && _timeout > 0 ) { + // this is a timeout + log(_logLevel) << "MessagingPort recv() timeout " << farEnd.toString() <<endl; + throw SocketException(SocketException::RECV_TIMEOUT); } - } - else { - if ( len <= 4 && ret != len ) - log(_logLevel) << "MessagingPort recv() got " << ret << " bytes wanted len=" << len << endl; - assert( ret <= len ); - len -= ret; - buf += ret; + + log(_logLevel) << "MessagingPort recv() " << errnoWithDescription(e) << " " << farEnd.toString() <<endl; + throw SocketException(SocketException::RECV_ERROR); } } } diff --git a/util/ramlog.h b/util/ramlog.h index fc588e6..b2f3aa0 100644 --- a/util/ramlog.h +++ b/util/ramlog.h @@ -108,7 +108,6 @@ namespace mongo { vector<const char*> v; get( v ); - bool first = true; s << "<pre>\n"; for( int i = 0; i < (int)v.size(); i++ ) { assert( strlen(v[i]) > 20 ); @@ -126,7 +125,7 @@ namespace mongo { stringstream r; if( nr == 1 ) r << "repeat last line"; else r << "repeats last " << nr << " lines; ends " << string(v[last]+4,0,15); - first = false; s << html::a("", r.str(), clean(v,i,x.str())); + s << html::a("", r.str(), clean(v,i,x.str())); } else s << x.str(); s << '\n'; diff --git a/util/sock.h b/util/sock.h index 84690fe..54dfb49 100644 --- a/util/sock.h +++ b/util/sock.h @@ -199,7 +199,7 @@ namespace mongo { case AF_INET6: return memcmp(as<sockaddr_in6>().sin6_addr.s6_addr, r.as<sockaddr_in6>().sin6_addr.s6_addr, sizeof(in6_addr)) == 0; case AF_UNIX: return strcmp(as<sockaddr_un>().sun_path, r.as<sockaddr_un>().sun_path) == 0; case AF_UNSPEC: return true; // assume all unspecified addresses are the same - default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); + default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); return false; } } bool operator!=(const SockAddr& r) const { @@ -221,7 +221,7 @@ namespace mongo { case AF_INET6: return memcmp(as<sockaddr_in6>().sin6_addr.s6_addr, r.as<sockaddr_in6>().sin6_addr.s6_addr, sizeof(in6_addr)) < 0; case AF_UNIX: return strcmp(as<sockaddr_un>().sun_path, r.as<sockaddr_un>().sun_path) < 0; case AF_UNSPEC: return false; - default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); + default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); return false; } } diff --git a/util/version.cpp b/util/version.cpp index f57e256..78a31be 100644 --- a/util/version.cpp +++ b/util/version.cpp @@ -23,10 +23,11 @@ #include <string> #include "unittest.h" #include "version.h" +#include "file.h" namespace mongo { - const char versionString[] = "1.8.1"; + const char versionString[] = "1.8.2"; string mongodVersion() { stringstream ss; @@ -94,6 +95,45 @@ namespace mongo { cout << "** WARNING: You are running in OpenVZ. This is known to be broken!!!" << endl; warned = true; } + + if (boost::filesystem::exists("/sys/devices/system/node/node1")){ + // We are on a box with a NUMA enabled kernel and more than 1 numa node (they start at node0) + // Now we look at the first line of /proc/self/numa_maps + // + // Bad example: + // $ cat /proc/self/numa_maps + // 00400000 default file=/bin/cat mapped=6 N4=6 + // + // Good example: + // $ numactl --interleave=all cat /proc/self/numa_maps + // 00400000 interleave:0-7 file=/bin/cat mapped=6 N4=6 + + File f; + 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)); + + // just in case... + line[98] = ' '; + line[99] = '\0'; + + // skip over pointer + const char* space = strchr(line, ' '); + + if ( ! space ) { + cout << "** WARNING: cannot parse numa_maps" << endl; + warned = true; + } + else if ( ! startsWith(space+1, "interleave") ) { + cout << endl; + cout << "** WARNING: You are running on a NUMA machine." << endl; + cout << "** We suggest launching mongod like this to avoid performance problems:" << endl; + cout << "** numactl --interleave=all mongod [other options]" << endl; + warned = true; + } + } + } #endif if (warned) |