00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #pragma once
00020
00021 #include "../bson/util/misc.h"
00022 #include "concurrency/mutex.h"
00023
00024 namespace mongo {
00025
00026
00027 string hexdump(const char *data, unsigned len);
00028
00033 unsigned setThreadName(const char * name);
00034 string getThreadName();
00035
00036 template<class T>
00037 inline string ToString(const T& t) {
00038 stringstream s;
00039 s << t;
00040 return s.str();
00041 }
00042
00043 #if !defined(_WIN32) && !defined(NOEXECINFO) && !defined(__freebsd__) && !defined(__openbsd__) && !defined(__sun__)
00044
00045 }
00046
00047 #include <pthread.h>
00048 #include <execinfo.h>
00049
00050 namespace mongo {
00051
00052 inline pthread_t GetCurrentThreadId() {
00053 return pthread_self();
00054 }
00055
00056
00057 inline void printStackTrace( ostream &o = cout ) {
00058 void *b[20];
00059
00060 int size = backtrace(b, 20);
00061 for (int i = 0; i < size; i++)
00062 o << hex << b[i] << dec << ' ';
00063 o << endl;
00064
00065 char **strings;
00066
00067 strings = backtrace_symbols(b, size);
00068 for (int i = 0; i < size; i++)
00069 o << ' ' << strings[i] << '\n';
00070 o.flush();
00071 free (strings);
00072 }
00073 #else
00074 inline void printStackTrace( ostream &o = cout ) { }
00075 #endif
00076
00077 bool isPrime(int n);
00078 int nextPrime(int n);
00079
00080 inline void dumpmemory(const char *data, int len) {
00081 if ( len > 1024 )
00082 len = 1024;
00083 try {
00084 const char *q = data;
00085 const char *p = q;
00086 while ( len > 0 ) {
00087 for ( int i = 0; i < 16; i++ ) {
00088 if ( *p >= 32 && *p <= 126 )
00089 cout << *p;
00090 else
00091 cout << '.';
00092 p++;
00093 }
00094 cout << " ";
00095 p -= 16;
00096 for ( int i = 0; i < 16; i++ )
00097 cout << (unsigned) ((unsigned char)*p++) << ' ';
00098 cout << endl;
00099 len -= 16;
00100 }
00101 }
00102 catch (...) {
00103 }
00104 }
00105
00106
00107 #define MONGO_PRINT(x) cout << #x ": " << (x) << endl
00108 #define PRINT MONGO_PRINT
00109
00110 #define MONGO_PRINTFL cout << __FILE__ ":" << __LINE__ << endl
00111 #define PRINTFL MONGO_PRINTFL
00112 #define MONGO_FLOG log() << __FILE__ ":" << __LINE__ << endl
00113 #define FLOG MONGO_FLOG
00114
00115 #undef assert
00116 #define assert MONGO_assert
00117
00118 inline bool startsWith(const char *str, const char *prefix) {
00119 size_t l = strlen(prefix);
00120 if ( strlen(str) < l ) return false;
00121 return strncmp(str, prefix, l) == 0;
00122 }
00123 inline bool startsWith(string s, string p) { return startsWith(s.c_str(), p.c_str()); }
00124
00125 inline bool endsWith(const char *p, const char *suffix) {
00126 size_t a = strlen(p);
00127 size_t b = strlen(suffix);
00128 if ( b > a ) return false;
00129 return strcmp(p + a - b, suffix) == 0;
00130 }
00131
00132 inline unsigned long swapEndian(unsigned long x) {
00133 return
00134 ((x & 0xff) << 24) |
00135 ((x & 0xff00) << 8) |
00136 ((x & 0xff0000) >> 8) |
00137 ((x & 0xff000000) >> 24);
00138 }
00139
00140 #if defined(BOOST_LITTLE_ENDIAN)
00141 inline unsigned long fixEndian(unsigned long x) {
00142 return x;
00143 }
00144 #else
00145 inline unsigned long fixEndian(unsigned long x) {
00146 return swapEndian(x);
00147 }
00148 #endif
00149
00150 #if !defined(_WIN32)
00151 typedef int HANDLE;
00152 inline void strcpy_s(char *dst, unsigned len, const char *src) {
00153 assert( strlen(src) < len );
00154 strcpy(dst, src);
00155 }
00156 #else
00157 typedef void *HANDLE;
00158 #endif
00159
00160
00161
00162
00163
00164
00165 template<class T>
00166 class ThreadLocalValue {
00167 public:
00168 ThreadLocalValue( T def = 0 ) : _default( def ) { }
00169
00170 T get() const {
00171 T * val = _val.get();
00172 if ( val )
00173 return *val;
00174 return _default;
00175 }
00176
00177 void set( const T& i ) {
00178 T *v = _val.get();
00179 if( v ) {
00180 *v = i;
00181 return;
00182 }
00183 v = new T(i);
00184 _val.reset( v );
00185 }
00186
00187 private:
00188 boost::thread_specific_ptr<T> _val;
00189 const T _default;
00190 };
00191
00192 class ProgressMeter : boost::noncopyable {
00193 public:
00194 ProgressMeter( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 ) {
00195 reset( total , secondsBetween , checkInterval );
00196 }
00197
00198 ProgressMeter() {
00199 _active = 0;
00200 }
00201
00202
00203 void reset( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 ) {
00204 _total = total;
00205 _secondsBetween = secondsBetween;
00206 _checkInterval = checkInterval;
00207
00208 _done = 0;
00209 _hits = 0;
00210 _lastTime = (int)time(0);
00211
00212 _active = 1;
00213 }
00214
00215 void finished() {
00216 _active = 0;
00217 }
00218
00219 bool isActive() {
00220 return _active;
00221 }
00222
00227 bool hit( int n = 1 ) {
00228 if ( ! _active ) {
00229 cout << "warning: hit on in-active ProgressMeter" << endl;
00230 return false;
00231 }
00232
00233 _done += n;
00234 _hits++;
00235 if ( _hits % _checkInterval )
00236 return false;
00237
00238 int t = (int) time(0);
00239 if ( t - _lastTime < _secondsBetween )
00240 return false;
00241
00242 if ( _total > 0 ) {
00243 int per = (int)( ( (double)_done * 100.0 ) / (double)_total );
00244 cout << "\t\t" << _done << "/" << _total << "\t" << per << "%" << endl;
00245 }
00246 _lastTime = t;
00247 return true;
00248 }
00249
00250 void setTotalWhileRunning( unsigned long long total ) {
00251 _total = total;
00252 }
00253
00254 unsigned long long done() const { return _done; }
00255
00256 unsigned long long hits() const { return _hits; }
00257
00258 unsigned long long total() const { return _total; }
00259
00260 string toString() const {
00261 if ( ! _active )
00262 return "";
00263 stringstream buf;
00264 buf << _done << "/" << _total << " " << (_done*100)/_total << "%";
00265 return buf.str();
00266 }
00267
00268 bool operator==( const ProgressMeter& other ) const {
00269 return this == &other;
00270 }
00271 private:
00272
00273 bool _active;
00274
00275 unsigned long long _total;
00276 int _secondsBetween;
00277 int _checkInterval;
00278
00279 unsigned long long _done;
00280 unsigned long long _hits;
00281 int _lastTime;
00282 };
00283
00284
00285
00286
00287
00288 class ProgressMeterHolder : boost::noncopyable {
00289 public:
00290 ProgressMeterHolder( ProgressMeter& pm )
00291 : _pm( pm ) {
00292 }
00293
00294 ~ProgressMeterHolder() {
00295 _pm.finished();
00296 }
00297
00298 ProgressMeter* operator->() {
00299 return &_pm;
00300 }
00301
00302 bool hit( int n = 1 ) {
00303 return _pm.hit( n );
00304 }
00305
00306 void finished() {
00307 _pm.finished();
00308 }
00309
00310 bool operator==( const ProgressMeter& other ) {
00311 return _pm == other;
00312 }
00313
00314 private:
00315 ProgressMeter& _pm;
00316 };
00317
00318 class TicketHolder {
00319 public:
00320 TicketHolder( int num ) : _mutex("TicketHolder") {
00321 _outof = num;
00322 _num = num;
00323 }
00324
00325 bool tryAcquire() {
00326 scoped_lock lk( _mutex );
00327 if ( _num <= 0 ) {
00328 if ( _num < 0 ) {
00329 cerr << "DISASTER! in TicketHolder" << endl;
00330 }
00331 return false;
00332 }
00333 _num--;
00334 return true;
00335 }
00336
00337 void release() {
00338 scoped_lock lk( _mutex );
00339 _num++;
00340 }
00341
00342 void resize( int newSize ) {
00343 scoped_lock lk( _mutex );
00344 int used = _outof - _num;
00345 if ( used > newSize ) {
00346 cout << "ERROR: can't resize since we're using (" << used << ") more than newSize(" << newSize << ")" << endl;
00347 return;
00348 }
00349
00350 _outof = newSize;
00351 _num = _outof - used;
00352 }
00353
00354 int available() const {
00355 return _num;
00356 }
00357
00358 int used() const {
00359 return _outof - _num;
00360 }
00361
00362 int outof() const { return _outof; }
00363
00364 private:
00365 int _outof;
00366 int _num;
00367 mongo::mutex _mutex;
00368 };
00369
00370 class TicketHolderReleaser {
00371 public:
00372 TicketHolderReleaser( TicketHolder * holder ) {
00373 _holder = holder;
00374 }
00375
00376 ~TicketHolderReleaser() {
00377 _holder->release();
00378 }
00379 private:
00380 TicketHolder * _holder;
00381 };
00382
00383
00388 class ThreadSafeString {
00389 public:
00390 ThreadSafeString( size_t size=256 )
00391 : _size( size ) , _buf( new char[size] ) {
00392 memset( _buf , 0 , _size );
00393 }
00394
00395 ThreadSafeString( const ThreadSafeString& other )
00396 : _size( other._size ) , _buf( new char[_size] ) {
00397 strncpy( _buf , other._buf , _size );
00398 }
00399
00400 ~ThreadSafeString() {
00401 delete[] _buf;
00402 _buf = 0;
00403 }
00404
00405 string toString() const {
00406 string s = _buf;
00407 return s;
00408 }
00409
00410 ThreadSafeString& operator=( const char * str ) {
00411 size_t s = strlen(str);
00412 if ( s >= _size - 2 )
00413 s = _size - 2;
00414 strncpy( _buf , str , s );
00415 _buf[s] = 0;
00416 return *this;
00417 }
00418
00419 bool operator==( const ThreadSafeString& other ) const {
00420 return strcmp( _buf , other._buf ) == 0;
00421 }
00422
00423 bool operator==( const char * str ) const {
00424 return strcmp( _buf , str ) == 0;
00425 }
00426
00427 bool operator!=( const char * str ) const {
00428 return strcmp( _buf , str ) != 0;
00429 }
00430
00431 bool empty() const {
00432 return _buf == 0 || _buf[0] == 0;
00433 }
00434
00435 private:
00436 size_t _size;
00437 char * _buf;
00438 };
00439
00440 ostream& operator<<( ostream &s, const ThreadSafeString &o );
00441
00448 template <typename T>
00449 struct ptr {
00450
00451 ptr() : _p(NULL) {}
00452
00453
00454 ptr(T* p) : _p(p) {}
00455 template<typename U> ptr(U* p) : _p(p) {}
00456 template<typename U> ptr(const ptr<U>& p) : _p(p) {}
00457 template<typename U> ptr(const boost::shared_ptr<U>& p) : _p(p.get()) {}
00458 template<typename U> ptr(const boost::scoped_ptr<U>& p) : _p(p.get()) {}
00459
00460
00461
00462 ptr& operator= (T* p) { _p = p; return *this; }
00463 template<typename U> ptr& operator= (U* p) { _p = p; return *this; }
00464 template<typename U> ptr& operator= (const ptr<U>& p) { _p = p; return *this; }
00465 template<typename U> ptr& operator= (const boost::shared_ptr<U>& p) { _p = p.get(); return *this; }
00466 template<typename U> ptr& operator= (const boost::scoped_ptr<U>& p) { _p = p.get(); return *this; }
00467
00468
00469
00470 T* operator->() const { return _p; }
00471 T& operator*() const { return *_p; }
00472
00473
00474 operator T* () const { return _p; }
00475
00476 private:
00477 T* _p;
00478 };
00479
00480
00481
00483 using namespace boost;
00484
00485 }