00001
00002
00003
00004 #ifndef IBIS_UTIL_H
00005 #define IBIS_UTIL_H
00006
00007
00008
00009
00010 #if defined(_WIN32) && defined(_MSC_VER) && defined(_DEBUG)
00011 #define _CRTDBG_MAP_ALLOC
00012 #include <stdlib.h>
00013 #include <crtdbg.h>
00014 #else
00015 #include <stdlib.h>
00016 #endif
00017 #include "const.h"
00018
00019 #include <cctype>
00020 #include <cstring>
00021 #include <stdio.h>
00022
00023 #include <sys/stat.h>
00024
00025
00026 #include <fcntl.h>
00027
00028 #include <map>
00029 #include <string>
00030 #include <limits>
00031 #include <sstream>
00032
00033 #include <float.h>
00034 #include <math.h>
00035 #if !defined(unix) && defined(_WIN32)
00036 #include <windows.h>
00037 #include <io.h>
00038 #include <fcntl.h>
00039 int truncate(const char*, uint32_t);
00040 #include <direct.h>
00041 #include <sys/stat.h>
00042 #define rmdir _rmdir
00043
00044 #else
00045 #include <unistd.h>
00046 #endif
00047
00048
00049 #ifndef FASTBIT_MIN_MAP_SIZE
00050 #define FASTBIT_MIN_MAP_SIZE 1048576
00051 #endif
00052
00053 #if ! (defined(HAVE_MMAP) || defined(_MSC_VER))
00054 # if defined(_XOPEN_SOURCE)
00055 # define HAVE_MMAP _XOPEN_SOURCE - 0 >= 500
00056 # elif defined(_POSIX_C_SOURCE)
00057 # define HAVE_MMAP _POSIX_C_SOURCE - 0 >= 0
00058 # else
00059 # define HAVE_MMAP defined(unix)||defined(linux)||defined(__APPLE__)||defined(__CYGWIN__)
00060 # endif
00061 #endif
00062
00063 #if (HAVE_MMAP+0>0) || (defined(_WIN32) && defined(_MSC_VER))
00064 #define HAVE_FILE_MAP 1
00065 #endif
00066
00067 #ifndef DBL_EPSILON
00068 #define DBL_EPSILON 2.2204460492503131e-16
00069 #else
00070
00071 #undef DBL_EPSILON
00072 #define DBL_EPSILON 2.2204460492503131e-16
00073 #endif
00074
00075 #ifndef FASTBIT_FLOAT_NULL
00076 #define FASTBIT_FLOAT_NULL std::numeric_limits<float>::quiet_NaN()
00077 #endif
00078 #ifndef FASTBIT_DOUBLE_NULL
00079 #define FASTBIT_DOUBLE_NULL std::numeric_limits<double>::quiet_NaN()
00080 #endif
00081
00083 #if !defined(HAVE_GCC_ATOMIC32) && defined(WITHOUT_FASTBIT_CONFIG_H)
00084 #if __GNUC__+0 >= 4 && defined(LINUX)
00085 #define HAVE_GCC_ATOMIC32 2
00086 #endif
00087 #endif
00088 #if !defined(HAVE_GCC_ATOMIC64) && defined(WITHOUT_FASTBIT_CONFIG_H)
00089 #if defined(__IA64__) || defined(__x86_64__) || defined(__ppc64__)
00090 #if __GNUC__+0 >= 4 && defined(LINUX)
00091 #define HAVE_GCC_ATOMIC64 2
00092 #endif
00093 #endif
00094 #endif
00095
00097 #if defined(_MSC_VER) && defined(_WIN32)
00098 #ifndef HAVE_WIN_ATOMIC32
00099 #if defined(NTDDI_VERSION) && defined(NTDDI_WIN2K)
00100 #if NTDDI_VERSION >= NTDDI_WIN2K
00101 #define HAVE_WIN_ATOMIC32
00102 #endif
00103 #elif defined(WINVER)
00104 #if WINVER >= 0x0500
00105 #define HAVE_WIN_ATOMIC32
00106 #endif
00107 #endif
00108 #endif
00109 #ifndef HAVE_WIN_ATOMIC64
00110 #if defined(NTDDI_VERSION) && defined(NTDDI_WINVISTA)
00111 #if NTDDI_VERSION >= NTDDI_WINVISTA
00112 #define HAVE_WIN_ATOMIC64
00113 #endif
00114 #elif defined(WINVER)
00115 #if WINVER >= 0x0600
00116 #define HAVE_WIN_ATOMIC64
00117 #endif
00118 #endif
00119 #endif
00120 #endif
00121
00122
00123 #if defined(_MSC_VER) && defined(_WIN32)
00124 #define UnixOpen ::_open
00125 #define UnixClose ::_close
00126 #define UnixRead ::_read
00127 #define UnixWrite ::_write
00128 #define UnixSeek ::_lseek
00129 #define UnixFlush ::_commit
00130 #define UnixSnprintf ::_snprintf
00131 #define UnixStat ::_stat
00132 #define UnixFStat ::_fstat
00133 #define Stat_T struct _stat
00134 #else
00135 #define UnixOpen ::open
00136 #define UnixClose ::close
00137 #define UnixRead ::read
00138 #define UnixWrite ::write
00139 #define UnixSeek ::lseek
00140 #define UnixFlush ::fsync
00141 #define UnixSnprintf ::snprintf
00142 #define UnixStat ::stat
00143 #define UnixFStat ::fstat
00144 #define Stat_T struct stat
00145 #endif
00146
00147
00148 #if defined(O_RDONLY)
00149 #if defined(O_LARGEFILE)
00150 #if defined(O_BINARY)
00151 #define OPEN_READONLY O_RDONLY | O_BINARY | O_LARGEFILE
00152 #else
00153 #define OPEN_READONLY O_RDONLY | O_LARGEFILE
00154 #endif
00155 #elif defined(O_BINARY)
00156 #define OPEN_READONLY O_RDONLY | O_BINARY
00157 #else
00158 #define OPEN_READONLY O_RDONLY
00159 #endif
00160 #elif defined(_O_RDONLY)
00161 #if defined(_O_LARGEFILE)
00162 #define OPEN_READONLY _O_RDONLY | _O_LARGEFILE | _O_BINARY
00163 #else
00164 #define OPEN_READONLY _O_RDONLY | _O_BINARY
00165 #endif
00166 #endif
00167
00168 #if defined(O_WRONLY)
00169 #if defined(O_LARGEFILE)
00170 #if defined(O_BINARY)
00171 #define OPEN_WRITENEW O_WRONLY | O_BINARY | O_CREAT | O_TRUNC | O_LARGEFILE
00172 #else
00173 #define OPEN_WRITENEW O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE
00174 #endif
00175 #elif defined(O_BINARY)
00176 #define OPEN_WRITENEW O_WRONLY | O_BINARY | O_CREAT | O_TRUNC
00177 #else
00178 #define OPEN_WRITENEW O_WRONLY | O_CREAT | O_TRUNC
00179 #endif
00180 #elif defined(_O_WRONLY)
00181 #if defined(_O_LARGEFILE)
00182 #define OPEN_WRITENEW _O_WRONLY|_O_CREAT|_O_TRUNC|_O_LARGEFILE|_O_BINARY
00183 #else
00184 #define OPEN_WRITENEW _O_WRONLY|_O_CREAT|_O_TRUNC|_O_BINARY
00185 #endif
00186 #endif
00187
00188 #if defined(O_WRONLY)
00189 #if defined(O_LARGEFILE)
00190 #if defined(O_BINARY)
00191 #define OPEN_WRITEADD O_WRONLY | O_BINARY | O_CREAT | O_LARGEFILE
00192 #else
00193 #define OPEN_WRITEADD O_WRONLY | O_CREAT| O_LARGEFILE
00194 #endif
00195 #elif defined(O_BINARY)
00196 #define OPEN_WRITEADD O_WRONLY | O_BINARY | O_CREAT
00197 #else
00198 #define OPEN_WRITEADD O_WRONLY | O_CREAT
00199 #endif
00200 #elif defined(_O_WRONLY)
00201 #if defined(_O_LARGEFILE)
00202 #define OPEN_WRITEADD _O_WRONLY | _O_CREAT | _O_LARGEFILE | _O_BINARY
00203 #else
00204 #define OPEN_WRITEADD _O_WRONLY | _O_CREAT | _O_BINARY
00205 #endif
00206 #endif
00207
00208 #if defined(O_RDWR)
00209 #if defined(O_LARGEFILE)
00210 #if defined(O_BINARY)
00211 #define OPEN_READWRITE O_RDWR | O_BINARY | O_CREAT | O_LARGEFILE
00212 #else
00213 #define OPEN_READWRITE O_RDWR | O_CREAT | O_LARGEFILE
00214 #endif
00215 #elif defined(O_BINARY)
00216 #define OPEN_READWRITE O_RDWR | O_BINARY | O_CREAT
00217 #else
00218 #define OPEN_READWRITE O_RDWR | O_CREAT
00219 #endif
00220 #elif defined(_O_RDWR)
00221 #if defined(_O_LARGEFILE)
00222 #define OPEN_READWRITE _O_RDWR | _O_CREAT | _O_LARGEFILE | _O_BINARY
00223 #else
00224 #define OPEN_READWRITE _O_RDWR | _O_CREAT | _O_BINARY
00225 #endif
00226 #endif
00227
00228 #if defined(O_WRONLY)
00229 #if defined(O_LARGEFILE)
00230 #if defined(O_BINARY)
00231 #define OPEN_APPENDONLY O_WRONLY | O_BINARY | O_CREAT | O_APPEND | O_LARGEFILE
00232 #else
00233 #define OPEN_APPENDONLY O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE
00234 #endif
00235 #elif defined(O_BINARY)
00236 #define OPEN_APPENDONLY O_WRONLY | O_BINARY | O_CREAT | O_APPEND
00237 #else
00238 #define OPEN_APPENDONLY O_WRONLY | O_CREAT | O_APPEND
00239 #endif
00240 #elif defined(_O_WRONLY)
00241 #if defined(_O_LARGEFILE)
00242 #define OPEN_APPENDONLY _O_WRONLY | _O_CREAT | _O_APPEND | _O_LARGEFILE | _O_BINARY
00243 #else
00244 #define OPEN_APPENDONLY _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY
00245 #endif
00246 #endif
00247
00248 #if defined(_MSC_VER) && defined(_WIN32)
00249 #define OPEN_FILEMODE _S_IREAD | _S_IWRITE
00250 #elif defined(S_IRGRP) && defined(S_IWGRP) && defined(S_IROTH)
00251 #define OPEN_FILEMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
00252 #else
00253 #define OPEN_FILEMODE S_IRUSR | S_IWUSR
00254 #endif
00255
00256 #if defined(_WIN32) && defined(_MSC_VER)
00257
00258 #ifdef max
00259 #undef max
00260 #endif
00261 #ifdef min
00262 #undef min
00263 #endif
00264 #endif
00265
00266 #ifndef FASTBIT_CS_PATTERN_MATCH
00267
00268
00269
00270 #define FASTBIT_CS_PATTERN_MATCH 1
00271 #endif
00272
00273
00274 #define STRMATCH_META_CSH_ANY '*'
00275 #define STRMATCH_META_CSH_ONE '?'
00276 #define STRMATCH_META_SQL_ANY '%'
00277 #define STRMATCH_META_SQL_ONE '_'
00278 #define STRMATCH_META_ESCAPE '\\'
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 #define LOGGER(v) \
00290 if (false == (v)) ; else ibis::util::logger(0)()
00291
00292
00293 #define IBIS_JOIN_MACRO2(X, Y) X##Y
00294 #define IBIS_JOIN_MACRO(X, Y) IBIS_JOIN_MACRO2(X, Y)
00295 #ifdef __GNUC__
00296 #define IBIS_GUARD_NAME IBIS_JOIN_MACRO(_guard, __LINE__) __attribute__( ( unused ) )
00297 #else
00298 #define IBIS_GUARD_NAME IBIS_JOIN_MACRO(_guard, __LINE__)
00299 #endif
00300 #define IBIS_BLOCK_GUARD \
00301 ibis::util::guard IBIS_GUARD_NAME = ibis::util::makeGuard
00302
00303 namespace std {
00304
00305 template <> struct less< char* > {
00306 bool operator()(const char*x, const char*y) const {
00307 return strcmp(x, y) < 0;
00308 }
00309 };
00310
00311
00312 template <> struct less< const char* > {
00313 bool operator()(const char* x, const char* y) const {
00314 return strcmp(x, y) < 0;
00315 }
00316 };
00317
00318 template <> struct less< ibis::rid_t > {
00319 bool operator()(const ibis::rid_t& x, const ibis::rid_t& y) const {
00320 return (x < y);
00321 }
00322 };
00323
00324 template <> struct less< const ibis::rid_t* > {
00325 bool operator()(const ibis::rid_t* x, const ibis::rid_t* y) const {
00326 return (*x < *y);
00327 }
00328 };
00329 }
00330
00331 namespace ibis {
00334 class resource;
00335 class bitvector;
00336 class column;
00337 class fileManager;
00338 class horometer;
00339 class index;
00340 class roster;
00341 class bitvector64;
00342
00343 class dictionary;
00344 class bundle;
00345 class colValues;
00346
00347 class fromClause;
00348 class whereClause;
00349 class selectClause;
00350
00351
00353 extern FASTBIT_CXX_DLLSPEC partList datasets;
00354
00355 typedef std::vector<colValues*> colList;
00356
00358 FASTBIT_CXX_DLLSPEC ibis::resource& gParameters();
00359
00362 class FASTBIT_CXX_DLLSPEC nameList {
00363 public:
00364 nameList() : cstr(0), buff(0) {};
00365 nameList(const char* str) : cstr(0), buff(0) {select(str);}
00366 ~nameList() {if (cstr) clear();}
00367
00368 bool empty() const {return cstr == 0;}
00369 const char* operator*() const {return cstr;};
00370 uint32_t size() const {return cvec.size();};
00371
00373 void select(const char* str);
00375 void add(const char* str);
00379 uint32_t find(const char* key) const;
00380
00381 const char* operator[](uint32_t i) const {return cvec[i];}
00382 typedef std::vector< const char* >::const_iterator const_iterator;
00383 const_iterator begin() const {return cvec.begin();}
00384 const_iterator end() const {return cvec.end();}
00385
00386 void clear()
00387 {cvec.clear(); delete [] cstr; delete [] buff; buff=0; cstr=0;}
00388
00389 private:
00390 typedef std::vector< const char * > compStore;
00391 char* cstr;
00392 char* buff;
00393 compStore cvec;
00394
00395 nameList(const nameList&);
00396 nameList& operator=(const nameList&);
00397 };
00398
00401 typedef std::map< const char*, part*, lessi > partAssoc;
00402
00404 class bad_alloc : public std::bad_alloc {
00405 public:
00409 bad_alloc(const char *m="unknown") throw() : mesg_(m) {};
00410 virtual ~bad_alloc() throw() {}
00411 virtual const char* what() const throw() {return mesg_;}
00412
00413 private:
00416 const char *mesg_;
00417 };
00418
00420 namespace util {
00422 extern const char* charTable;
00424 extern const short unsigned charIndex[];
00426 extern const char* delimiters;
00428 extern const int log2table[256];
00435 extern FASTBIT_CXX_DLLSPEC pthread_mutex_t envLock;
00436
00438 inline char* trim(char* str);
00440 char* strnewdup(const char* s);
00442 char* strnewdup(const char* s, const uint32_t n);
00444 inline void removeTail(char* str, char tail);
00445 char* getString(const char* buf);
00446 const char* getToken(char*& str, const char* tok_chrs);
00447 int readInt(int64_t& val, const char *&str,
00448 const char* del=ibis::util::delimiters);
00449 int readUInt(uint64_t& val, const char *&str,
00450 const char* del=ibis::util::delimiters);
00451 int readDouble(double& val, const char *&str,
00452 const char* del=ibis::util::delimiters);
00453 FASTBIT_CXX_DLLSPEC int readString(std::string& str, const char*& buf,
00454 const char *delim=0);
00455
00456 int64_t read(int, void*, int64_t);
00457
00460 void removeDir(const char* name, bool leaveDir=false);
00462 int makeDir(const char* dir);
00465 FASTBIT_CXX_DLLSPEC off_t getFileSize(const char* name);
00468 int copy(const char* to, const char* from);
00469
00473 inline void setVerboseLevel(int v) {ibis::gVerbose=v;}
00475 FASTBIT_CXX_DLLSPEC const char* userName();
00477 uint32_t serialNumber();
00478 void uniformFraction(const long unsigned idx,
00479 long unsigned &denominator,
00480 long unsigned &numerator);
00481 inline double rand();
00482
00484 FASTBIT_CXX_DLLSPEC uint32_t checksum(const char* str, uint32_t sz);
00485 inline uint32_t checksum(uint32_t a, uint32_t b);
00486 std::string shortName(const std::string& longname);
00487 std::string randName(const std::string& longname);
00489
00491 void int2string(std::string &str, unsigned val);
00492 void int2string(std::string &str, unsigned v1, unsigned v2);
00493 void int2string(std::string &str, unsigned v1,
00494 unsigned v2, unsigned v3);
00495 void int2string(std::string &str, const std::vector<unsigned>& val);
00496 void encode64(uint64_t, std::string&);
00497 int decode64(uint64_t&, const std::string&);
00498 int decode16(uint64_t&, const char*);
00499 std::string groupby1000(uint64_t);
00501
00504 double incrDouble(const double&);
00505 double decrDouble(const double&);
00506 void eq2range(const double&, double&, double&);
00509 inline double coarsen(const double in, unsigned prec=2);
00512 double compactValue(double left, double right,
00513 double start=0.0);
00514
00517 double compactValue2(double left, double right,
00518 double start=0.0);
00519
00521 void setNaN(double& val);
00522 void setNaN(float& val);
00523
00527 template <typename Tin, typename Tout>
00528 void round_down(const Tin& inval, Tout& outval) {
00529 outval = ((double)std::numeric_limits<Tout>::min() > inval ?
00530 std::numeric_limits<Tout>::min() :
00531 (double)std::numeric_limits<Tout>::max() <= inval ?
00532 std::numeric_limits<Tout>::max() :
00533 static_cast<Tout>(inval));
00534 }
00538 template <typename Tin, typename Tout>
00539 void round_up(const Tin& inval, Tout& outval) {
00540 outval = ((double)std::numeric_limits<Tout>::min() >= inval ?
00541 std::numeric_limits<Tout>::min() :
00542 (double) std::numeric_limits<Tout>::max() < inval ?
00543 std::numeric_limits<Tout>::max() :
00544 static_cast<Tout>(inval) +
00545 ((inval-static_cast<Tin>(static_cast<Tout>(inval))) > 0));
00546 }
00548 template <typename Tin>
00549 void round_up(const Tin& inval, float&);
00551 template <typename Tin>
00552 void round_up(const Tin& inval, double& outval) {
00553 outval = static_cast<double>(inval);
00554 }
00555
00557 inline int log2(uint32_t x) {
00558 register uint32_t xx, xxx;
00559 return (xx = x >> 16)
00560 ? (xxx = xx >> 8) ? 24 + log2table[xxx] : 16 + log2table[xx]
00561 : (xxx = x >> 8) ? 8 + log2table[xxx] : log2table[x];
00562 }
00564 inline int log2(uint64_t x) {
00565 register uint32_t xx;
00566 return (xx = x >> 32)
00567 ? 32 + log2(xx)
00568 : log2(static_cast<uint32_t>(x));
00569 }
00571
00572 FASTBIT_CXX_DLLSPEC void
00573 logMessage(const char* event, const char* fmt, ...);
00574 FASTBIT_CXX_DLLSPEC FILE* getLogFile();
00575 int writeLogFileHeader(FILE *fptr, const char* fname);
00576 FASTBIT_CXX_DLLSPEC void closeLogFile();
00577 FASTBIT_CXX_DLLSPEC int setLogFileName(const char* filename);
00578 FASTBIT_CXX_DLLSPEC const char* getLogFileName();
00579
00583 FASTBIT_CXX_DLLSPEC bool strMatch(const char* str, const char* pat);
00584
00586 const ibis::bitvector64& outerProduct(const ibis::bitvector& a,
00587 const ibis::bitvector& b,
00588 ibis::bitvector64& c);
00591 const ibis::bitvector64& outerProductUpper(const ibis::bitvector& a,
00592 const ibis::bitvector& b,
00593 ibis::bitvector64& c);
00594
00596 long intersect(const std::vector<ibis::bitvector> &bits1,
00597 const std::vector<ibis::bitvector> &bits2,
00598 std::vector<ibis::bitvector> &res);
00600 long intersect(const std::vector<ibis::bitvector> &bits1,
00601 const std::vector<ibis::bitvector> &bits2,
00602 const std::vector<ibis::bitvector> &bits3,
00603 std::vector<ibis::bitvector> &res);
00604 void clear(ibis::array_t<ibis::bitvector*> &bv) throw();
00605 void clear(ibis::partList &pl) throw();
00606 void updateDatasets(void);
00607
00610 inline const char* getVersionString() {
00611 return FASTBIT_STRING;
00612 }
00619 inline int getVersionNumber() {
00620 #ifdef FASTBIT_IBIS_INT_VERSION
00621 return FASTBIT_IBIS_INT_VERSION;
00622 #else
00623 return 1030000;
00624 #endif
00625 }
00626
00628 void getLocalTime(char *str);
00630 void getGMTime(char *str);
00631 void secondsToString(const time_t, char *str);
00632
00633
00634 #if defined(WIN32) && ! defined(__CYGWIN__)
00635 char* getpass_r(const char *prompt, char *buffer, uint32_t buflen);
00636 char* getpass(const char* prompt);
00637 #else
00638 inline char *itoa(int value, char *str, int ) {
00639 sprintf(str,"%d",value);
00640 return str;
00641 }
00642 #endif
00643
00645 template <typename T> inline void
00646 clearVec(std::vector<T*> &v) {
00647 const size_t nv = v.size();
00648 for (size_t j = 0; j < nv; ++j)
00649 delete v[j];
00650 v.clear();
00651 }
00652
00661 class FASTBIT_CXX_DLLSPEC logger {
00662 public:
00664 logger(int blanks=0);
00666 ~logger();
00668 std::ostream& operator()(void) {return mybuffer;}
00669
00670 protected:
00672 std::ostringstream mybuffer;
00673
00674 private:
00675 logger(const logger&);
00676 logger& operator=(const logger&);
00677 };
00678
00681 class ioLock {
00682 public:
00683 ioLock() {
00684 #if defined(PTW32_STATIC_LIB)
00685 if (mutex == PTHREAD_MUTEX_INITIALIZER) {
00686 int ierr = pthread_mutex_init(&mutex, 0);
00687 if (ierr != 0)
00688 throw "ioLock failed to initialize the necessary mutex";
00689 }
00690 #endif
00691 if (0 != pthread_mutex_lock(&mutex))
00692 throw "ioLock failed to obtain a lock";
00693 }
00694 ~ioLock() {
00695 (void) pthread_mutex_unlock(&mutex);
00696 }
00697 private:
00698
00699 static pthread_mutex_t mutex;
00700
00701 ioLock(const ioLock&) {};
00702 ioLock& operator=(const ioLock&);
00703 };
00704
00706 class mutexLock {
00707 public:
00708 mutexLock(pthread_mutex_t* lk, const char* m)
00709 : mesg(m), lock(lk) {
00710 LOGGER(ibis::gVerbose > 10)
00711 << "util::mutexLock -- acquiring lock (" << lock
00712 << ") for " << mesg;
00713 if (0 != pthread_mutex_lock(lock)) {
00714 throw "mutexLock failed to obtain a lock";
00715 }
00716 }
00717 ~mutexLock() {
00718 LOGGER(ibis::gVerbose > 10)
00719 << "util::mutexLock -- releasing lock (" << lock
00720 << ") for " << mesg;
00721 (void) pthread_mutex_unlock(lock);
00722 }
00723
00724 private:
00725 const char *mesg;
00726 pthread_mutex_t *lock;
00727
00728 mutexLock() : mesg(0), lock(0) {};
00729 mutexLock(const mutexLock&);
00730 mutexLock& operator=(const mutexLock&);
00731 };
00732
00736 class quietLock {
00737 public:
00738 quietLock(pthread_mutex_t *lk) : lock(lk) {
00739 if (0 != pthread_mutex_lock(lock))
00740 throw "quietLock failed to obtain a mutex lock";
00741 }
00742 ~quietLock() {
00743 (void) pthread_mutex_unlock(lock);
00744 }
00745
00746 private:
00747 pthread_mutex_t *lock;
00748
00749 quietLock();
00750 quietLock(const quietLock&);
00751 quietLock& operator=(const quietLock&);
00752 };
00753
00755 class readLock {
00756 public:
00757 readLock(pthread_rwlock_t* lk, const char* m)
00758 : mesg(m), lock(lk) {
00759 if (0 != pthread_rwlock_rdlock(lock)) {
00760 throw "readLock failed to obtain a lock";
00761 }
00762 }
00763 ~readLock() {
00764 (void) pthread_rwlock_unlock(lock);
00765 }
00766
00767 private:
00768 const char *mesg;
00769 pthread_rwlock_t *lock;
00770
00771 readLock() : mesg(0), lock(0) {};
00772 readLock(const readLock&);
00773 readLock& operator=(const readLock&);
00774 };
00775
00777 class writeLock {
00778 public:
00779 writeLock(pthread_rwlock_t* lk, const char* m)
00780 : mesg(m), lock(lk) {
00781 if (0 != pthread_rwlock_wrlock(lock)) {
00782 throw "writeLock failed to obtain a lock";
00783 }
00784 }
00785 ~writeLock() {
00786 int ierr = pthread_rwlock_unlock(lock);
00787 if (ierr != 0) {
00788 throw "writeLock failed to release the lock";
00789 }
00790 }
00791
00792 private:
00793 const char *mesg;
00794 pthread_rwlock_t *lock;
00795
00796 writeLock() : mesg(0), lock(0) {};
00797 writeLock(const writeLock&);
00798 writeLock& operator=(const writeLock&);
00799 };
00800
00807 class FASTBIT_CXX_DLLSPEC counter {
00808 public:
00809 ~counter() {
00810 #if defined(HAVE_GCC_ATOMIC32)
00811 #elif defined(HAVE_WIN_ATOMIC32)
00812 #else
00813 (void)pthread_mutex_destroy(&lock_);
00814 #endif
00815 }
00816 counter() : count_(0) {
00817 #if defined(HAVE_GCC_ATOMIC32)
00818 #elif defined(HAVE_WIN_ATOMIC32)
00819 #else
00820 if (0 != pthread_mutex_init(&lock_, 0))
00821 throw ibis::bad_alloc
00822 ("util::counter failed to initialize mutex lock");
00823 #endif
00824 }
00825
00827 uint32_t operator()() {
00828 #if defined(HAVE_GCC_ATOMIC32)
00829 return __sync_fetch_and_add(&count_, 1);
00830 #elif defined(HAVE_WIN_ATOMIC32)
00831 return InterlockedIncrement((volatile long *)&count_)-1;
00832 #else
00833 ibis::util::quietLock lck(&lock_);
00834 uint32_t ret = count_;
00835 ++ count_;
00836 return ret;
00837 #endif
00838 }
00840 void reset() {
00841 #if defined(HAVE_GCC_ATOMIC32)
00842 (void) __sync_fetch_and_sub(&count_, count_);
00843 #elif defined(HAVE_WIN_ATOMIC32)
00844 (void) InterlockedExchange((volatile long *)&count_, 0);
00845 #else
00846 ibis::util::quietLock lck(&lock_);
00847 count_ = 0;
00848 #endif
00849 }
00851 uint32_t value() const {
00852 return count_;
00853 }
00854
00855 private:
00856 #if defined(HAVE_GCC_ATOMIC32)
00857 #elif defined(HAVE_WIN_ATOMIC32)
00858 #else
00859 mutable pthread_mutex_t lock_;
00860 #endif
00861 volatile uint32_t count_;
00862
00864 counter(const counter&);
00866 counter& operator=(const counter&);
00867 };
00868
00883 class FASTBIT_CXX_DLLSPEC sharedInt32 {
00884 public:
00885 sharedInt32() : val_(0) {
00886 #if defined(HAVE_GCC_ATOMIC32)
00887 #elif defined(HAVE_WIN_ATOMIC32)
00888 #else
00889 if (pthread_mutex_init(&mytex, 0) != 0)
00890 throw "pthread_mutex_init failed for sharedInt";
00891 #endif
00892 }
00893
00894 ~sharedInt32() {
00895 #if defined(HAVE_GCC_ATOMIC32)
00896 #elif defined(HAVE_WIN_ATOMIC32)
00897 #else
00898 (void)pthread_mutex_destroy(&mytex);
00899 #endif
00900 }
00901
00903 uint32_t operator()() const {return val_;}
00904
00906 uint32_t operator++() {
00907 #if defined(HAVE_GCC_ATOMIC32)
00908 return __sync_add_and_fetch(&val_, 1);
00909 #elif defined(HAVE_WIN_ATOMIC32)
00910 return InterlockedIncrement((volatile long *)&val_);
00911 #else
00912 ibis::util::quietLock lock(&mytex);
00913 ++ val_;
00914 return val_;
00915 #endif
00916 }
00917
00919 uint32_t operator--() {
00920 #if defined(HAVE_GCC_ATOMIC32)
00921 return __sync_sub_and_fetch(&val_, 1);
00922 #elif defined(HAVE_WIN_ATOMIC32)
00923 return InterlockedDecrement((volatile long *)&val_);
00924 #else
00925 ibis::util::quietLock lock(&mytex);
00926 -- val_;
00927 return val_;
00928 #endif
00929 }
00930
00932 void operator+=(const uint32_t rhs) {
00933 #if defined(HAVE_GCC_ATOMIC32)
00934 (void) __sync_add_and_fetch(&val_, rhs);
00935 #elif defined(HAVE_WIN_ATOMIC32)
00936 (void) InterlockedExchangeAdd((volatile long *)&val_, rhs);
00937 #else
00938 ibis::util::quietLock lock(&mytex);
00939 val_ += rhs;
00940 #endif
00941 }
00942
00944 void operator-=(const uint32_t rhs) {
00945 #if defined(HAVE_GCC_ATOMIC32)
00946 (void) __sync_sub_and_fetch(&val_, rhs);
00947 #elif defined(HAVE_WIN_ATOMIC32)
00948 (void) InterlockedExchangeAdd((volatile long *)&val_,
00949 -(long)rhs);
00950 #else
00951 ibis::util::quietLock lock(&mytex);
00952 val_ -= rhs;
00953 #endif
00954 }
00955
00957 void swap(sharedInt32 &rhs) {
00958 uint32_t tmp = rhs.val_;
00959 rhs.val_ = val_;
00960 val_ = tmp;
00961 }
00962
00963 private:
00964 uint32_t volatile val_;
00965 #if defined(HAVE_GCC_ATOMIC32)
00966 #elif defined(HAVE_WIN_ATOMIC32)
00967 #else
00968 pthread_mutex_t mytex;
00969 #endif
00970
00971 sharedInt32(const sharedInt32&);
00972 sharedInt32& operator=(const sharedInt32&);
00973 };
00974
00981 class sharedInt64 {
00982 public:
00983 sharedInt64() : val_(0) {
00984 #if defined(HAVE_GCC_ATOMIC64)
00985 #elif defined(HAVE_WIN_ATOMIC64)
00986 #else
00987 if (pthread_mutex_init(&mytex, 0) != 0)
00988 throw "pthread_mutex_init failed for sharedInt";
00989 #endif
00990 }
00991
00992 ~sharedInt64() {
00993 #if defined(HAVE_GCC_ATOMIC64)
00994 #elif defined(HAVE_WIN_ATOMIC64)
00995 #else
00996 (void)pthread_mutex_destroy(&mytex);
00997 #endif
00998 }
00999
01001 uint64_t operator()() const {return val_;}
01002
01004 uint64_t operator++() {
01005 #if defined(HAVE_GCC_ATOMIC64)
01006 return __sync_add_and_fetch(&val_, 1);
01007 #elif defined(HAVE_WIN_ATOMIC64)
01008 return InterlockedIncrement64((volatile LONGLONG *)&val_);
01009 #else
01010 ibis::util::quietLock lock(&mytex);
01011 ++ val_;
01012 return val_;
01013 #endif
01014 }
01015
01017 uint64_t operator--() {
01018 #if defined(HAVE_GCC_ATOMIC64)
01019 return __sync_sub_and_fetch(&val_, 1);
01020 #elif defined(HAVE_WIN_ATOMIC64)
01021 return InterlockedDecrement64((volatile LONGLONG *)&val_);
01022 #else
01023 ibis::util::quietLock lock(&mytex);
01024 -- val_;
01025 return val_;
01026 #endif
01027 }
01028
01030 void operator+=(const uint64_t rhs) {
01031 #if defined(HAVE_GCC_ATOMIC64)
01032 (void) __sync_add_and_fetch(&val_, rhs);
01033 #elif defined(HAVE_WIN_ATOMIC64)
01034 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_,
01035 rhs);
01036 #else
01037 ibis::util::quietLock lock(&mytex);
01038 val_ += rhs;
01039 #endif
01040 }
01041
01043 void operator-=(const uint64_t rhs) {
01044 #if defined(HAVE_GCC_ATOMIC64)
01045 (void) __sync_sub_and_fetch(&val_, rhs);
01046 #elif defined(HAVE_WIN_ATOMIC64)
01047 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_,
01048 -(long)rhs);
01049 #else
01050 ibis::util::quietLock lock(&mytex);
01051 val_ -= rhs;
01052 #endif
01053 }
01054
01056 void swap(sharedInt64 &rhs) {
01057 uint64_t tmp = rhs.val_;
01058 rhs.val_ = val_;
01059 val_ = tmp;
01060 }
01061
01062 private:
01063 uint64_t volatile val_;
01064 #if defined(HAVE_GCC_ATOMIC64)
01065 #elif defined(HAVE_WIN_ATOMIC64)
01066 #else
01067 pthread_mutex_t mytex;
01068 #endif
01069
01070 sharedInt64(const sharedInt64&);
01071 sharedInt64& operator=(const sharedInt64&);
01072 };
01073
01083 class timer {
01084 public:
01085 explicit timer(const char* msg, int lvl=1);
01086 ~timer();
01087
01088 private:
01089 ibis::horometer *chrono_;
01090 std::string mesg_;
01091
01092 timer();
01093 timer(const timer&);
01094 timer& operator=(const timer&);
01095 };
01096
01098 template <class T> class refHolder {
01099 public:
01100 refHolder(T& r) : ref_(r) {}
01101 operator T& () const {return ref_;}
01102
01103 private:
01104 T& ref_;
01105
01106 refHolder();
01107 };
01108
01110 template <class T>
01111 inline refHolder<T> ref(T& r) {return refHolder<T>(r);}
01112
01115 class guardBase {
01116 public:
01119 void dismiss() const {done_ = true;}
01120
01121 protected:
01122 mutable volatile bool done_;
01123
01125 ~guardBase() {};
01126 guardBase() : done_(false) {};
01127
01128
01129 guardBase(const guardBase& rhs) : done_(rhs.done_) {
01130 rhs.dismiss();
01131 }
01132
01135 template <typename T>
01136 static void cleanup(T& task) throw () {
01137 try {
01138 if (!task.done_)
01139 task.execute();
01140 }
01141 catch (const std::exception& e) {
01142 LOGGER(ibis::gVerbose > 1)
01143 << " ... caught a std::exception (" << e.what()
01144 << ") in util::gard";
01145 }
01146 catch (const char* s) {
01147 LOGGER(ibis::gVerbose > 1)
01148 << " ... caught a string exception (" << s
01149 << ") in util::guard";
01150 }
01151 catch (...) {
01152 LOGGER(ibis::gVerbose > 1)
01153 << " ... caught a unknown exception in util::guard";
01154 }
01155 task.done_ = true;
01156 }
01157 };
01158
01172 typedef const guardBase& guard;
01173
01176 template <typename F>
01177 class guardImpl0 : public guardBase {
01178 public:
01179 static guardImpl0<F> makeGuard(F f) {
01180 return guardImpl0<F>(f);
01181 }
01182
01184 ~guardImpl0() {cleanup(*this);}
01185
01186 protected:
01187 friend class guardBase;
01188 void execute() {fun_();}
01189
01191 explicit guardImpl0(F f) : fun_(f) {}
01192
01193 private:
01195 F fun_;
01196
01197 guardImpl0();
01198 guardImpl0& operator=(const guardImpl0&);
01199 };
01200
01201 template <typename F>
01202 inline guardImpl0<F> makeGuard(F f) {
01203 return guardImpl0<F>::makeGuard(f);
01204 }
01205
01208 template <typename F, typename A>
01209 class guardImpl1 : public guardBase {
01210 public:
01211 static guardImpl1<F, A> makeGuard(F f, A a) {
01212 return guardImpl1<F, A>(f, a);
01213 }
01214
01216 ~guardImpl1() {cleanup(*this);}
01217
01218 protected:
01219 friend class guardBase;
01220 void execute() {fun_(arg_);}
01221
01223 explicit guardImpl1(F f, A a) : fun_(f), arg_(a) {}
01224
01225 private:
01227 F fun_;
01229 A arg_;
01230
01231 guardImpl1();
01232 guardImpl1& operator=(const guardImpl1&);
01233 };
01234
01235 template <typename F, typename A>
01236 inline guardImpl1<F, A> makeGuard(F f, A a) {
01237 return guardImpl1<F, A>::makeGuard(f, a);
01238 }
01239
01242 template <typename F, typename A1, typename A2>
01243 class guardImpl2 : public guardBase {
01244 public:
01245 static guardImpl2<F, A1, A2> makeGuard(F f, A1 a1, A2 a2) {
01246 return guardImpl2<F, A1, A2>(f, a1, a2);
01247 }
01248
01250 ~guardImpl2() {cleanup(*this);}
01251
01252 protected:
01253 friend class guardBase;
01254 void execute() {fun_(arg1_, arg2_);}
01255
01257 explicit guardImpl2(F f, A1 a1, A2 a2)
01258 : fun_(f), arg1_(a1), arg2_(a2) {}
01259
01260 private:
01262 F fun_;
01264 A1 arg1_;
01266 A2 arg2_;
01267
01268 guardImpl2();
01269
01270 guardImpl2& operator=(const guardImpl2&);
01271 };
01272
01273 template <typename F, typename A1, typename A2>
01274 inline guardImpl2<F, A1, A2> makeGuard(F f, A1 a1, A2 a2) {
01275 return guardImpl2<F, A1, A2>::makeGuard(f, a1, a2);
01276 }
01277
01279 template <class C, typename F>
01280 class guardObj0 : public guardBase {
01281 public:
01282 static guardObj0<C, F> makeGuard(C& o, F f) {
01283 return guardObj0<C, F>(o, f);
01284 }
01285
01287 ~guardObj0() {cleanup(*this);}
01288
01289 protected:
01290 friend class guardBase;
01291 void execute() {(obj_.*fun_)();}
01292
01294 guardObj0(C& o, F f) : obj_(o), fun_(f) {}
01295
01296 private:
01297 C& obj_;
01298 F fun_;
01299
01300 guardObj0();
01301 guardObj0& operator=(const guardObj0&);
01302 };
01303
01304 template <class C, typename F>
01305 inline guardObj0<C, F> objectGuard(C o, F f) {
01306 return guardObj0<C, F>::makeGuard(o, f);
01307 }
01308 }
01309 }
01310
01311 #if defined(WIN32) && ! defined(__CYGWIN__)
01312 char* getpass(const char* prompt);
01313 #endif
01314
01320 inline double ibis::util::rand() {
01321
01322
01323 static uint32_t seed = 1;
01324 static const uint32_t alpha = 69069;
01325 static const double scale = ::pow(0.5, 32);
01326 seed = static_cast<uint32_t>(seed * alpha);
01327 return(scale * seed);
01328 }
01329
01331 inline uint32_t ibis::util::checksum(uint32_t a, uint32_t b) {
01332 uint32_t a0 = (a >> 16);
01333 uint32_t a1 = (a & 0xFFFF);
01334 uint32_t b0 = (b >> 16);
01335 uint32_t b1 = (b & 0xFFFF);
01336 return ((((a0<<2)+a1*3+(b0<<1)+b1) << 16) | ((a0+a1+b0+b1) & 0xFFFF));
01337 }
01338
01346 inline double ibis::util::incrDouble(const double& in) {
01347 #if defined(HAVE_NEXTAFTER)
01348 return nextafter(in, DBL_MAX);
01349 #elif defined(_MSC_VER) && defined(_WIN32)
01350 return _nextafter(in, DBL_MAX);
01351 #else
01352 double tmp = fabs(in) * DBL_EPSILON;
01353 if (tmp > 0.0) tmp += in;
01354 else tmp = in + DBL_MIN;
01355 return tmp;
01356 #endif
01357 }
01358
01361 inline double ibis::util::decrDouble(const double& in) {
01362 #if defined(HAVE_NEXTAFTER)
01363 return nextafter(in, -DBL_MAX);
01364 #elif defined(_MSC_VER) && defined(_WIN32)
01365 return _nextafter(in, -DBL_MAX);
01366 #else
01367 double tmp = fabs(in) * DBL_EPSILON;
01368 if (tmp > 0.0) tmp = in - tmp;
01369 else tmp = in - DBL_MIN;
01370 return tmp;
01371 #endif
01372 }
01373
01378 inline void ibis::util::eq2range(const double& in,
01379 double& left, double& right) {
01380 #if defined(HAVE_NEXTAFTER)
01381 right = nextafter(in, DBL_MAX);
01382 #elif defined(_MSC_VER) && defined(_WIN32)
01383 right = _nextafter(in, DBL_MAX);
01384 #else
01385 double tmp = fabs(in) * DBL_EPSILON;
01386 if (tmp > 0.0) {right = in + tmp;}
01387 else {right = in + DBL_MIN;}
01388 #endif
01389 left = in;
01390 }
01391
01395 template <typename Tin>
01396 inline void ibis::util::round_up(const Tin& inval, float& outval) {
01397
01398 outval = static_cast<float>(inval);
01399 if (static_cast<Tin>(outval) < inval) {
01400
01401
01402 #if defined(HAVE_NEXTAFTER)
01403 outval = nextafterf(static_cast<float>(inval), FLT_MAX);
01404 #else
01405 float tmp = fabsf(outval) * FLT_EPSILON;
01406 if (tmp > 0.0) outval += tmp;
01407 else outval += FLT_MIN;
01408 #endif
01409 }
01410 }
01411
01412
01413 inline void ibis::util::removeTail(char* str, char tail) {
01414 if (str != 0 && *str != 0) {
01415 char *tmp = str;
01416 while (*tmp != 0) ++ tmp;
01417 -- tmp;
01418 while (tmp > str && *tmp == tail) {
01419 *tmp = static_cast<char>(0);
01420 -- tmp;
01421 }
01422 }
01423 }
01424
01425
01426 inline char* ibis::util::trim(char* str) {
01427 char* head = 0;
01428 if (str == 0) return head;
01429 if (*str == 0) return head;
01430
01431 head = str;
01432 while (*head) {
01433 if (std::isspace(*head))
01434 ++ head;
01435 else
01436 break;
01437 }
01438 if (*head == 0)
01439 return head;
01440
01441 for (str = head; *str != 0; ++ str);
01442 -- str;
01443 while (str >= head && std::isspace(*str)) {
01444 *str = static_cast<char>(0);
01445 -- str;
01446 }
01447 return head;
01448 }
01449
01457 inline double ibis::util::coarsen(const double in, unsigned prec) {
01458 double ret;
01459 if (prec > 15) {
01460 ret = in;
01461 }
01462 else if (in == 0.0) {
01463 ret = in;
01464 }
01465 else {
01466 ret = fabs(in);
01467 if (ret < DBL_MIN) {
01468 ret = 0.0;
01469 }
01470 else if (ret < DBL_MAX) {
01471 ret = log10(ret);
01472 if (prec > 0)
01473 -- prec;
01474 const int ixp = static_cast<int>(floor(ret)) -
01475 static_cast<int>(prec);
01476 ret = floor(0.5 + pow(1e1, ret-ixp));
01477 if (ixp > 0)
01478 ret *= pow(1e1, ixp);
01479 else if (ixp < 0)
01480 ret /= pow(1e1, -ixp);
01481 if (in < 0.0)
01482 ret = -ret;
01483 }
01484 else {
01485 ret = in;
01486 }
01487 }
01488 return ret;
01489 }
01490
01492 inline std::ostream& operator<<(std::ostream& out, const ibis::rid_t& rid) {
01493 out << '(' << rid.num.run << ", " << rid.num.event << ')';
01494 return out;
01495 }
01496
01498 inline std::istream& operator>>(std::istream& is, ibis::rid_t& rid) {
01499 char c = 0;
01500 is >> c;
01501 if (c == '(') {
01502 is >> rid.num.run >> c;
01503 if (c == ',')
01504 is >> rid.num.event >> c;
01505 else
01506 rid.num.event = 0;
01507 if (c != ')')
01508 is.clear(std::ios::badbit);
01509 }
01510 else {
01511 is.putback(c);
01512 is >> rid.num.run >> c;
01513 if (c != ',')
01514 is.putback(c);
01515 is >> rid.num.event;
01516 }
01517 return is;
01518 }
01519 #endif // IBIS_UTIL_H