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
00113 #undef assert
00114 #define assert MONGO_assert
00115
00116 struct WrappingInt {
00117 WrappingInt() {
00118 x = 0;
00119 }
00120 WrappingInt(unsigned z) : x(z) { }
00121 unsigned x;
00122 operator unsigned() const {
00123 return x;
00124 }
00125
00126
00127 static int diff(unsigned a, unsigned b) {
00128 return a-b;
00129 }
00130 bool operator<=(WrappingInt r) {
00131
00132 int df = (r.x - x);
00133 return df >= 0;
00134 }
00135 bool operator>(WrappingInt r) {
00136 return !(r<=*this);
00137 }
00138 };
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 inline bool startsWith(const char *str, const char *prefix) {
00156 size_t l = strlen(prefix);
00157 if ( strlen(str) < l ) return false;
00158 return strncmp(str, prefix, l) == 0;
00159 }
00160 inline bool startsWith(string s, string p) { return startsWith(s.c_str(), p.c_str()); }
00161
00162 inline bool endsWith(const char *p, const char *suffix) {
00163 size_t a = strlen(p);
00164 size_t b = strlen(suffix);
00165 if ( b > a ) return false;
00166 return strcmp(p + a - b, suffix) == 0;
00167 }
00168
00169 inline unsigned long swapEndian(unsigned long x) {
00170 return
00171 ((x & 0xff) << 24) |
00172 ((x & 0xff00) << 8) |
00173 ((x & 0xff0000) >> 8) |
00174 ((x & 0xff000000) >> 24);
00175 }
00176
00177 #if defined(BOOST_LITTLE_ENDIAN)
00178 inline unsigned long fixEndian(unsigned long x) {
00179 return x;
00180 }
00181 #else
00182 inline unsigned long fixEndian(unsigned long x) {
00183 return swapEndian(x);
00184 }
00185 #endif
00186
00187 #if !defined(_WIN32)
00188 typedef int HANDLE;
00189 inline void strcpy_s(char *dst, unsigned len, const char *src) {
00190 assert( strlen(src) < len );
00191 strcpy(dst, src);
00192 }
00193 #else
00194 typedef void *HANDLE;
00195 #endif
00196
00197
00198
00199
00200
00201
00202 template<class T>
00203 class ThreadLocalValue {
00204 public:
00205 ThreadLocalValue( T def = 0 ) : _default( def ) { }
00206
00207 T get() const {
00208 T * val = _val.get();
00209 if ( val )
00210 return *val;
00211 return _default;
00212 }
00213
00214 void set( const T& i ) {
00215 T *v = _val.get();
00216 if( v ) {
00217 *v = i;
00218 return;
00219 }
00220 v = new T(i);
00221 _val.reset( v );
00222 }
00223
00224 private:
00225 boost::thread_specific_ptr<T> _val;
00226 const T _default;
00227 };
00228
00229 class ProgressMeter : boost::noncopyable {
00230 public:
00231 ProgressMeter( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 ) {
00232 reset( total , secondsBetween , checkInterval );
00233 }
00234
00235 ProgressMeter() {
00236 _active = 0;
00237 }
00238
00239 void reset( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 ) {
00240 _total = total;
00241 _secondsBetween = secondsBetween;
00242 _checkInterval = checkInterval;
00243
00244 _done = 0;
00245 _hits = 0;
00246 _lastTime = (int)time(0);
00247
00248 _active = 1;
00249 }
00250
00251 void finished() {
00252 _active = 0;
00253 }
00254
00255 bool isActive() {
00256 return _active;
00257 }
00258
00262 bool hit( int n = 1 ) {
00263 if ( ! _active ) {
00264 cout << "warning: hit on in-active ProgressMeter" << endl;
00265 return false;
00266 }
00267
00268 _done += n;
00269 _hits++;
00270 if ( _hits % _checkInterval )
00271 return false;
00272
00273 int t = (int) time(0);
00274 if ( t - _lastTime < _secondsBetween )
00275 return false;
00276
00277 if ( _total > 0 ) {
00278 int per = (int)( ( (double)_done * 100.0 ) / (double)_total );
00279 cout << "\t\t" << _done << "/" << _total << "\t" << per << "%" << endl;
00280 }
00281 _lastTime = t;
00282 return true;
00283 }
00284
00285 unsigned long long done() {
00286 return _done;
00287 }
00288
00289 unsigned long long hits() {
00290 return _hits;
00291 }
00292
00293 string toString() const {
00294 if ( ! _active )
00295 return "";
00296 stringstream buf;
00297 buf << _done << "/" << _total << " " << (_done*100)/_total << "%";
00298 return buf.str();
00299 }
00300
00301 bool operator==( const ProgressMeter& other ) const {
00302 return this == &other;
00303 }
00304 private:
00305
00306 bool _active;
00307
00308 unsigned long long _total;
00309 int _secondsBetween;
00310 int _checkInterval;
00311
00312 unsigned long long _done;
00313 unsigned long long _hits;
00314 int _lastTime;
00315 };
00316
00317 class ProgressMeterHolder : boost::noncopyable {
00318 public:
00319 ProgressMeterHolder( ProgressMeter& pm )
00320 : _pm( pm ) {
00321 }
00322
00323 ~ProgressMeterHolder() {
00324 _pm.finished();
00325 }
00326
00327 ProgressMeter* operator->() {
00328 return &_pm;
00329 }
00330
00331 bool hit( int n = 1 ) {
00332 return _pm.hit( n );
00333 }
00334
00335 void finished() {
00336 _pm.finished();
00337 }
00338
00339 bool operator==( const ProgressMeter& other ) {
00340 return _pm == other;
00341 }
00342
00343 private:
00344 ProgressMeter& _pm;
00345 };
00346
00347 class TicketHolder {
00348 public:
00349 TicketHolder( int num ) : _mutex("TicketHolder") {
00350 _outof = num;
00351 _num = num;
00352 }
00353
00354 bool tryAcquire() {
00355 scoped_lock lk( _mutex );
00356 if ( _num <= 0 ) {
00357 if ( _num < 0 ) {
00358 cerr << "DISASTER! in TicketHolder" << endl;
00359 }
00360 return false;
00361 }
00362 _num--;
00363 return true;
00364 }
00365
00366 void release() {
00367 scoped_lock lk( _mutex );
00368 _num++;
00369 }
00370
00371 void resize( int newSize ) {
00372 scoped_lock lk( _mutex );
00373 int used = _outof - _num;
00374 if ( used > newSize ) {
00375 cout << "ERROR: can't resize since we're using (" << used << ") more than newSize(" << newSize << ")" << endl;
00376 return;
00377 }
00378
00379 _outof = newSize;
00380 _num = _outof - used;
00381 }
00382
00383 int available() const {
00384 return _num;
00385 }
00386
00387 int used() const {
00388 return _outof - _num;
00389 }
00390
00391 int outof() const { return _outof; }
00392
00393 private:
00394 int _outof;
00395 int _num;
00396 mongo::mutex _mutex;
00397 };
00398
00399 class TicketHolderReleaser {
00400 public:
00401 TicketHolderReleaser( TicketHolder * holder ) {
00402 _holder = holder;
00403 }
00404
00405 ~TicketHolderReleaser() {
00406 _holder->release();
00407 }
00408 private:
00409 TicketHolder * _holder;
00410 };
00411
00412
00417 class ThreadSafeString {
00418 public:
00419 ThreadSafeString( size_t size=256 )
00420 : _size( 256 ) , _buf( new char[256] ) {
00421 memset( _buf , 0 , _size );
00422 }
00423
00424 ThreadSafeString( const ThreadSafeString& other )
00425 : _size( other._size ) , _buf( new char[_size] ) {
00426 strncpy( _buf , other._buf , _size );
00427 }
00428
00429 ~ThreadSafeString() {
00430 delete[] _buf;
00431 _buf = 0;
00432 }
00433
00434 string toString() const {
00435 string s = _buf;
00436 return s;
00437 }
00438
00439 ThreadSafeString& operator=( const char * str ) {
00440 size_t s = strlen(str);
00441 if ( s >= _size - 2 )
00442 s = _size - 2;
00443 strncpy( _buf , str , s );
00444 _buf[s] = 0;
00445 return *this;
00446 }
00447
00448 bool operator==( const ThreadSafeString& other ) const {
00449 return strcmp( _buf , other._buf ) == 0;
00450 }
00451
00452 bool operator==( const char * str ) const {
00453 return strcmp( _buf , str ) == 0;
00454 }
00455
00456 bool operator!=( const char * str ) const {
00457 return strcmp( _buf , str ) != 0;
00458 }
00459
00460 bool empty() const {
00461 return _buf == 0 || _buf[0] == 0;
00462 }
00463
00464 private:
00465 size_t _size;
00466 char * _buf;
00467 };
00468
00469 ostream& operator<<( ostream &s, const ThreadSafeString &o );
00470
00471 inline bool isNumber( char c ) {
00472 return c >= '0' && c <= '9';
00473 }
00474
00475 inline unsigned stringToNum(const char *str) {
00476 unsigned x = 0;
00477 const char *p = str;
00478 while( 1 ) {
00479 if( !isNumber(*p) ) {
00480 if( *p == 0 && p != str )
00481 break;
00482 throw 0;
00483 }
00484 x = x * 10 + *p++ - '0';
00485 }
00486 return x;
00487 }
00488
00489
00490 inline int lexNumCmp( const char *s1, const char *s2 ) {
00491
00492 while( *s1 && *s2 ) {
00493
00494 bool p1 = ( *s1 == (char)255 );
00495 bool p2 = ( *s2 == (char)255 );
00496
00497 if ( p1 && !p2 )
00498 return 1;
00499 if ( p2 && !p1 )
00500 return -1;
00501
00502 bool n1 = isNumber( *s1 );
00503 bool n2 = isNumber( *s2 );
00504
00505 if ( n1 && n2 ) {
00506
00507 while ( *s1 == '0' ) s1++;
00508 while ( *s2 == '0' ) s2++;
00509
00510 char * e1 = (char*)s1;
00511 char * e2 = (char*)s2;
00512
00513
00514
00515 while ( isNumber (*e1) ) e1++;
00516 while ( isNumber (*e2) ) e2++;
00517
00518 int len1 = (int)(e1-s1);
00519 int len2 = (int)(e2-s2);
00520
00521 int result;
00522
00523 if ( len1 > len2 ) {
00524 return 1;
00525 }
00526 else if ( len2 > len1 ) {
00527 return -1;
00528 }
00529
00530 else if ( (result = strncmp(s1, s2, len1)) != 0 ) {
00531 return result;
00532 }
00533
00534
00535 s1 = e1;
00536 s2 = e2;
00537 continue;
00538 }
00539
00540 if ( n1 )
00541 return 1;
00542
00543 if ( n2 )
00544 return -1;
00545
00546 if ( *s1 > *s2 )
00547 return 1;
00548
00549 if ( *s2 > *s1 )
00550 return -1;
00551
00552 s1++; s2++;
00553 }
00554
00555 if ( *s1 )
00556 return 1;
00557 if ( *s2 )
00558 return -1;
00559 return 0;
00560 }
00561
00568 template <typename T>
00569 struct ptr {
00570
00571 ptr() : _p(NULL) {}
00572
00573
00574 ptr(T* p) : _p(p) {}
00575 template<typename U> ptr(U* p) : _p(p) {}
00576 template<typename U> ptr(const ptr<U>& p) : _p(p) {}
00577 template<typename U> ptr(const boost::shared_ptr<U>& p) : _p(p.get()) {}
00578 template<typename U> ptr(const boost::scoped_ptr<U>& p) : _p(p.get()) {}
00579
00580
00581
00582 ptr& operator= (T* p) { _p = p; return *this; }
00583 template<typename U> ptr& operator= (U* p) { _p = p; return *this; }
00584 template<typename U> ptr& operator= (const ptr<U>& p) { _p = p; return *this; }
00585 template<typename U> ptr& operator= (const boost::shared_ptr<U>& p) { _p = p.get(); return *this; }
00586 template<typename U> ptr& operator= (const boost::scoped_ptr<U>& p) { _p = p.get(); return *this; }
00587
00588
00589
00590 T* operator->() const { return _p; }
00591 T& operator*() const { return *_p; }
00592
00593
00594 operator T* () const { return _p; }
00595
00596 private:
00597 T* _p;
00598 };
00599
00601 using namespace boost;
00602
00603 }