// goodies.h // miscellaneous junk /** * Copyright (C) 2008 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #pragma once #include "../stdafx.h" namespace mongo { #if !defined(_WIN32) } // namespace mongo #include namespace mongo { inline pthread_t GetCurrentThreadId() { return pthread_self(); } } // namespace mongo #include namespace mongo { /* use "addr2line -CFe " to parse. */ inline void printStackTrace( ostream &o = cout ) { void *b[20]; size_t size; char **strings; size_t i; size = backtrace(b, 20); strings = backtrace_symbols(b, size); for (i = 0; i < size; i++) o << hex << b[i] << dec << ' '; o << '\n'; for (i = 0; i < size; i++) o << ' ' << strings[i] << '\n'; free (strings); } #else inline void printStackTrace() { } #endif /* set to TRUE if we are exiting */ extern bool goingAway; /* find the multimap member which matches a particular key and value. note this can be slow if there are a lot with the same key. */ template inline typename C::iterator kv_find(C& c, const K& k,const V& v) { pair p = c.equal_range(k); for ( typename C::iterator it=p.first; it!=p.second; ++it) if ( it->second == v ) return it; return c.end(); } bool isPrime(int n); int nextPrime(int n); inline void dumpmemory(const char *data, int len) { if ( len > 1024 ) len = 1024; try { const char *q = data; const char *p = q; while ( len > 0 ) { for ( int i = 0; i < 16; i++ ) { if ( *p >= 32 && *p <= 126 ) cout << *p; else cout << '.'; p++; } cout << " "; p -= 16; for ( int i = 0; i < 16; i++ ) cout << (unsigned) ((unsigned char)*p++) << ' '; cout << endl; len -= 16; } } catch (...) { } } #undef yassert } // namespace mongo #include #include #include namespace mongo { #undef assert #define assert xassert #define yassert 1 struct WrappingInt { WrappingInt() { x = 0; } WrappingInt(unsigned z) : x(z) { } unsigned x; operator unsigned() const { return x; } WrappingInt& operator++() { x++; return *this; } static int diff(unsigned a, unsigned b) { return a-b; } bool operator<=(WrappingInt r) { // platform dependent int df = (r.x - x); return df >= 0; } bool operator>(WrappingInt r) { return !(r<=*this); } }; } // namespace mongo #include namespace mongo { inline void time_t_to_String(time_t t, char *buf) { #if defined(_WIN32) ctime_s(buf, 64, &t); #else ctime_r(&t, buf); #endif buf[24] = 0; // don't want the \n } #define asctime _asctime_not_threadsafe_ #define gmtime _gmtime_not_threadsafe_ #define localtime _localtime_not_threadsafe_ #define ctime _ctime_is_not_threadsafe_ inline void sleepsecs(int s) { boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC); xt.sec += s; boost::thread::sleep(xt); } inline void sleepmillis(int s) { boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC); xt.sec += ( s / 1000 ); xt.nsec += ( s % 1000 ) * 1000000; if ( xt.nsec >= 1000000000 ) { xt.nsec -= 1000000000; xt.sec++; } boost::thread::sleep(xt); } // note this wraps inline int tdiff(unsigned told, unsigned tnew) { return WrappingInt::diff(tnew, told); } inline unsigned curTimeMillis() { boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC); unsigned t = xt.nsec / 1000000; return (xt.sec & 0xfffff) * 1000 + t; } inline unsigned long long jsTime() { boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC); unsigned long long t = xt.nsec / 1000000; return ((unsigned long long) xt.sec * 1000) + t; } inline unsigned long long curTimeMicros64() { boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC); unsigned long long t = xt.nsec / 1000; return (((unsigned long long) xt.sec) * 1000000) + t; } // measures up to 1024 seconds. or, 512 seconds with tdiff that is... inline unsigned curTimeMicros() { boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC); unsigned t = xt.nsec / 1000; unsigned secs = xt.sec % 1024; return secs*1000000 + t; } using namespace boost; typedef boost::mutex::scoped_lock boostlock; // simple scoped timer class Timer { public: Timer() { reset(); } int millis() { return micros() / 1000; } int micros() { unsigned n = curTimeMicros(); return tdiff(old, n); } int micros(unsigned& n) { // returns cur time in addition to timer result n = curTimeMicros(); return tdiff(old, n); } void reset() { old = curTimeMicros(); } private: unsigned old; }; /* class DebugMutex : boost::noncopyable { friend class lock; boost::mutex m; int locked; public: DebugMutex() : locked(0); { } bool isLocked() { return locked; } }; */ //typedef boostlock lock; inline bool startsWith(const char *str, const char *prefix) { unsigned l = strlen(prefix); if ( strlen(str) < l ) return false; return strncmp(str, prefix, l) == 0; } inline bool endsWith(const char *p, const char *suffix) { int a = strlen(p); int b = strlen(suffix); if ( b > a ) return false; return strcmp(p + a - b, suffix) == 0; } } // namespace mongo #include "boost/detail/endian.hpp" namespace mongo { inline unsigned long swapEndian(unsigned long x) { return ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24); } #if defined(BOOST_LITTLE_ENDIAN) inline unsigned long fixEndian(unsigned long x) { return x; } #else inline unsigned long fixEndian(unsigned long x) { return swapEndian(x); } #endif // Like strlen, but only scans up to n bytes. // Returns -1 if no '0' found. inline int strnlen( const char *s, int n ) { for( int i = 0; i < n; ++i ) if ( !s[ i ] ) return i; return -1; } } // namespace mongo