2008-06-06 15:43:15 +02:00
|
|
|
// goodies.h
|
|
|
|
// miscellaneous junk
|
|
|
|
|
2008-07-20 23:37:33 +02:00
|
|
|
/**
|
|
|
|
* Copyright (C) 2008 10gen Inc.
|
2008-12-29 02:28:49 +01:00
|
|
|
*
|
2008-07-20 23:37:33 +02:00
|
|
|
* 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.
|
2008-12-29 02:28:49 +01:00
|
|
|
*
|
2008-07-20 23:37:33 +02:00
|
|
|
* 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.
|
2008-12-29 02:28:49 +01:00
|
|
|
*
|
2008-07-20 23:37:33 +02:00
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2008-06-06 15:43:15 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../stdafx.h"
|
|
|
|
|
2009-01-14 23:09:51 +01:00
|
|
|
namespace mongo {
|
|
|
|
|
2008-06-06 15:43:15 +02:00
|
|
|
#if !defined(_WIN32)
|
2009-01-14 23:09:51 +01:00
|
|
|
|
|
|
|
} // namespace mongo
|
|
|
|
|
2008-06-06 15:43:15 +02:00
|
|
|
#include <pthread.h>
|
2009-01-14 23:09:51 +01:00
|
|
|
|
|
|
|
namespace mongo {
|
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
inline pthread_t GetCurrentThreadId() {
|
|
|
|
return pthread_self();
|
|
|
|
}
|
2009-01-14 23:09:51 +01:00
|
|
|
|
|
|
|
} // namespace mongo
|
|
|
|
|
2008-06-27 20:35:05 +02:00
|
|
|
#include <execinfo.h>
|
2009-01-14 23:09:51 +01:00
|
|
|
|
|
|
|
namespace mongo {
|
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
/* use "addr2line -CFe <exe>" to parse. */
|
2009-02-02 15:52:14 +01:00
|
|
|
inline void printStackTrace( ostream &o = cout ) {
|
2009-02-06 19:26:12 +01:00
|
|
|
void *b[20];
|
2009-01-15 16:17:11 +01:00
|
|
|
size_t size;
|
|
|
|
char **strings;
|
|
|
|
size_t i;
|
2008-12-29 02:28:49 +01:00
|
|
|
|
2009-02-06 19:26:12 +01:00
|
|
|
size = backtrace(b, 20);
|
2009-01-15 16:17:11 +01:00
|
|
|
strings = backtrace_symbols(b, size);
|
2008-12-29 02:28:49 +01:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
for (i = 0; i < size; i++)
|
2009-02-02 15:52:14 +01:00
|
|
|
o << hex << b[i] << ' ';
|
|
|
|
o << '\n';
|
2009-01-15 16:17:11 +01:00
|
|
|
for (i = 0; i < size; i++)
|
2009-02-02 15:52:14 +01:00
|
|
|
o << ' ' << strings[i] << '\n';
|
2008-06-27 20:35:05 +02:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
free (strings);
|
|
|
|
}
|
2008-06-27 20:35:05 +02:00
|
|
|
#else
|
2009-01-15 16:17:11 +01:00
|
|
|
inline void printStackTrace() { }
|
2008-06-06 15:43:15 +02:00
|
|
|
#endif
|
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
/* set to TRUE if we are exiting */
|
|
|
|
extern bool goingAway;
|
2008-06-06 15:43:15 +02:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
/* find the multimap member which matches a particular key and value.
|
2008-06-08 16:58:19 +02:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
note this can be slow if there are a lot with the same key.
|
|
|
|
*/
|
|
|
|
template<class C,class K,class V> inline typename C::iterator kv_find(C& c, const K& k,const V& v) {
|
|
|
|
pair<typename C::iterator,typename C::iterator> 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;
|
2008-12-29 02:28:49 +01:00
|
|
|
}
|
2009-01-15 16:17:11 +01:00
|
|
|
} catch (...) {
|
2008-12-29 02:28:49 +01:00
|
|
|
}
|
|
|
|
}
|
2008-06-06 15:43:15 +02:00
|
|
|
|
|
|
|
#undef yassert
|
2009-01-14 23:09:51 +01:00
|
|
|
|
|
|
|
} // namespace mongo
|
|
|
|
|
2009-02-20 17:08:22 +01:00
|
|
|
#include <boost/thread/barrier.hpp>
|
2008-06-06 15:43:15 +02:00
|
|
|
#include <boost/thread/thread.hpp>
|
|
|
|
#include <boost/thread/xtime.hpp>
|
2009-01-14 23:09:51 +01:00
|
|
|
|
|
|
|
namespace mongo {
|
|
|
|
|
2008-06-06 15:43:15 +02:00
|
|
|
#undef assert
|
|
|
|
#define assert xassert
|
|
|
|
#define yassert 1
|
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
};
|
2008-06-06 15:43:15 +02:00
|
|
|
|
2009-01-14 23:09:51 +01:00
|
|
|
} // namespace mongo
|
|
|
|
|
2008-06-06 15:43:15 +02:00
|
|
|
#include <ctime>
|
|
|
|
|
2009-01-14 23:09:51 +01:00
|
|
|
namespace mongo {
|
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
inline void time_t_to_String(time_t t, char *buf) {
|
2008-06-06 15:43:15 +02:00
|
|
|
#if defined(_WIN32)
|
2009-01-15 16:17:11 +01:00
|
|
|
ctime_s(buf, 64, &t);
|
2008-06-06 15:43:15 +02:00
|
|
|
#else
|
2009-01-15 16:17:11 +01:00
|
|
|
ctime_r(&t, buf);
|
2008-06-06 15:43:15 +02:00
|
|
|
#endif
|
2009-01-15 16:17:11 +01:00
|
|
|
buf[24] = 0; // don't want the \n
|
|
|
|
}
|
2008-06-06 15:43:15 +02:00
|
|
|
|
2009-01-07 00:57:01 +01:00
|
|
|
#define asctime _asctime_not_threadsafe_
|
|
|
|
#define gmtime _gmtime_not_threadsafe_
|
|
|
|
#define localtime _localtime_not_threadsafe_
|
|
|
|
#define ctime _ctime_is_not_threadsafe_
|
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
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);
|
2009-02-06 19:29:57 +01:00
|
|
|
if( s >= 1000 ) {
|
|
|
|
xt.sec += s/1000;
|
|
|
|
s-=1000;
|
|
|
|
}
|
2009-01-15 16:17:11 +01:00
|
|
|
xt.nsec += s * 1000000;
|
|
|
|
boost::thread::sleep(xt);
|
|
|
|
}
|
2008-06-06 15:43:15 +02:00
|
|
|
// note this wraps
|
2009-01-15 16:17:11 +01:00
|
|
|
inline int tdiff(unsigned told, unsigned tnew) {
|
|
|
|
return WrappingInt::diff(tnew, told);
|
2008-12-29 02:28:49 +01:00
|
|
|
}
|
2009-01-15 16:17:11 +01:00
|
|
|
inline unsigned curTimeMillis() {
|
|
|
|
boost::xtime xt;
|
|
|
|
boost::xtime_get(&xt, boost::TIME_UTC);
|
|
|
|
unsigned t = xt.nsec / 1000000;
|
|
|
|
return (xt.sec & 0xfffff) * 1000 + t;
|
2008-12-29 02:28:49 +01:00
|
|
|
}
|
2009-01-15 16:17:11 +01:00
|
|
|
|
|
|
|
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;
|
2008-12-29 02:28:49 +01:00
|
|
|
}
|
2009-01-15 16:17:11 +01:00
|
|
|
|
|
|
|
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;
|
2008-12-29 02:28:49 +01:00
|
|
|
}
|
2009-01-15 16:17:11 +01:00
|
|
|
|
|
|
|
// 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;
|
2008-12-29 02:28:49 +01:00
|
|
|
}
|
2009-01-15 16:17:11 +01:00
|
|
|
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;
|
|
|
|
};
|
2008-07-31 19:37:32 +02:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
/*
|
2008-07-31 19:37:32 +02:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
class DebugMutex : boost::noncopyable {
|
|
|
|
friend class lock;
|
|
|
|
boost::mutex m;
|
|
|
|
int locked;
|
|
|
|
public:
|
|
|
|
DebugMutex() : locked(0); { }
|
|
|
|
bool isLocked() { return locked; }
|
|
|
|
};
|
2008-07-31 19:37:32 +02:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
*/
|
2008-07-31 19:37:32 +02:00
|
|
|
|
2008-08-02 20:58:15 +02:00
|
|
|
//typedef boostlock lock;
|
2008-09-03 22:43:00 +02:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
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;
|
|
|
|
}
|
2008-09-11 15:15:34 +02:00
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
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;
|
|
|
|
}
|
2008-09-03 22:43:00 +02:00
|
|
|
|
2009-01-14 23:09:51 +01:00
|
|
|
} // namespace mongo
|
|
|
|
|
2008-09-04 16:33:56 +02:00
|
|
|
#include "boost/detail/endian.hpp"
|
|
|
|
|
2009-01-14 23:09:51 +01:00
|
|
|
namespace mongo {
|
|
|
|
|
2009-01-15 16:17:11 +01:00
|
|
|
inline unsigned long swapEndian(unsigned long x) {
|
|
|
|
return
|
|
|
|
((x & 0xff) << 24) |
|
|
|
|
((x & 0xff00) << 8) |
|
|
|
|
((x & 0xff0000) >> 8) |
|
|
|
|
((x & 0xff000000) >> 24);
|
|
|
|
}
|
2008-09-04 16:33:56 +02:00
|
|
|
|
|
|
|
#if defined(BOOST_LITTLE_ENDIAN)
|
2009-01-15 16:17:11 +01:00
|
|
|
inline unsigned long fixEndian(unsigned long x) {
|
|
|
|
return x;
|
|
|
|
}
|
2008-09-04 16:33:56 +02:00
|
|
|
#else
|
2009-01-15 16:17:11 +01:00
|
|
|
inline unsigned long fixEndian(unsigned long x) {
|
|
|
|
return swapEndian(x);
|
|
|
|
}
|
2008-09-04 16:33:56 +02:00
|
|
|
#endif
|
2008-12-01 03:00:54 +01:00
|
|
|
|
2009-01-16 21:13:46 +01:00
|
|
|
// 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;
|
|
|
|
}
|
2009-01-14 23:09:51 +01:00
|
|
|
|
|
|
|
} // namespace mongo
|