Go to the documentation of this file.00001
00002
00003
00004
00005 #ifndef IBIS_FILEMANAGER_H
00006 #define IBIS_FILEMANAGER_H
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "util.h"
00016
00017 #include <set>
00018 #include <map>
00019 #include <math.h>
00020
00024 class FASTBIT_CXX_DLLSPEC ibis::fileManager {
00025 public:
00026
00030 enum ACCESS_PREFERENCE {
00031 MMAP_LARGE_FILES,
00032 PREFER_READ,
00033 PREFER_MMAP
00034 };
00035
00036 template<typename T>
00037 int getFile(const char* name, array_t<T>& arr,
00038 ACCESS_PREFERENCE pref=MMAP_LARGE_FILES);
00039 template<typename T>
00040 int tryGetFile(const char* name, array_t<T>& arr,
00041 ACCESS_PREFERENCE pref=MMAP_LARGE_FILES);
00042
00044 void printStatus(std::ostream& out) const;
00046 void flushFile(const char* name);
00048 void flushDir(const char* name);
00050 void clear();
00051
00053 static fileManager& instance();
00055 static time_t iBeat() {return hbeat++;}
00057 const double& pageCount() const {return page_count;}
00059 static uint32_t pageSize() {return pagesize;}
00060 inline void recordPages(off_t start, off_t stop);
00061 static inline void increaseUse(size_t inc, const char* evt);
00062 static inline void decreaseUse(size_t dec, const char* evt);
00064 void signalMemoryAvailable() const;
00065
00067 class cleaner {
00068 public:
00069 virtual void operator()() const = 0;
00070 virtual ~cleaner() {};
00071 };
00072 void addCleaner(const cleaner* cl);
00073 void removeCleaner(const cleaner* cl);
00074
00075 class roFile;
00076 class storage;
00077 #if defined(HAVE_FILE_MAP)
00078 class rofSegment;
00079 #endif
00080 friend class roFile;
00081 friend class storage;
00082 int getFile(const char* name, storage** st,
00083 ACCESS_PREFERENCE pref=MMAP_LARGE_FILES);
00084 int tryGetFile(const char* name, storage** st,
00085 ACCESS_PREFERENCE pref=MMAP_LARGE_FILES);
00086 static storage* getFileSegment(const char* name, const int fdes,
00087 const off_t b, const off_t e);
00088
00090 inline void gainReadAccess(const char* mesg) const;
00092 inline void releaseAccess(const char* mesg) const;
00095 class readLock {
00096 public:
00097 readLock(const char* m) : mesg(m) {
00098 ibis::fileManager::instance().gainReadAccess(m);
00099 }
00100 ~readLock() {
00101 ibis::fileManager::instance().releaseAccess(mesg);
00102 }
00103 private:
00104 const char* mesg;
00105 };
00106
00108 static uint64_t currentCacheSize() {return maxBytes;}
00110 static int adjustCacheSize(uint64_t);
00112 static uint64_t bytesInUse() {return ibis::fileManager::totalBytes();}
00114 static uint64_t bytesFree();
00115
00119 template <typename T>
00120 class buffer {
00121 public:
00123 buffer(size_t sz=0);
00125 ~buffer();
00126
00128 T& operator[](size_t i) {return buf[i];}
00130 const T& operator[](size_t i) const {return buf[i];}
00132 T* address() const {return buf;}
00134 size_t size() const {return nbuf;}
00136 size_t resize(size_t sz=0);
00138 void swap(buffer<T>& other) throw () {
00139 T* btmp = buf;
00140 buf = other.buf;
00141 other.buf = btmp;
00142 size_t ntmp = nbuf;
00143 nbuf = other.nbuf;
00144 other.nbuf = ntmp;
00145 }
00146
00147 private:
00148 T* buf;
00149 size_t nbuf;
00150
00151 buffer(const buffer<T>&);
00152 buffer<T>& operator=(const buffer<T>&);
00153 };
00154
00155 protected:
00156 fileManager();
00157 ~fileManager();
00158
00159 void recordFile(roFile*);
00160
00161
00163 static ibis::util::sharedInt64 totalBytes;
00165 static uint64_t maxBytes;
00167 static unsigned int maxOpenFiles;
00168
00169
00170 fileManager(const fileManager& rhs);
00171 fileManager& operator=(const fileManager& rhs);
00172
00173 private:
00174 typedef std::map< const char*, roFile*,
00175 std::less< const char* > > fileList;
00176 typedef std::set< const cleaner* > cleanerList;
00177 typedef std::set< const char*, std::less< const char* > > nameList;
00178 fileList mapped;
00179 fileList incore;
00180 nameList reading;
00181 cleanerList cleaners;
00183 double page_count;
00185 uint32_t minMapSize;
00187 uint32_t nwaiting;
00189 pthread_cond_t readCond;
00190
00191 mutable pthread_rwlock_t lock;
00192 mutable pthread_mutex_t mutex;
00193 mutable pthread_cond_t cond;
00194
00195 static time_t hbeat;
00197 static uint32_t pagesize;
00198
00199 int unload(size_t size);
00200 void invokeCleaners() const;
00201 inline void gainWriteAccess(const char* m) const;
00202
00203 class writeLock;
00204 class softWriteLock;
00205 friend class writeLock;
00206 friend class softWriteLock;
00207 };
00208
00219 class FASTBIT_CXX_DLLSPEC ibis::fileManager::storage {
00220 public:
00221 storage();
00222 explicit storage(size_t n);
00223 virtual ~storage() {clear();}
00224
00225 storage(const char* fname, const off_t begin, const off_t end);
00226 storage(const int fdes, const off_t begin, const off_t end);
00227 storage(const char* begin, const char* end);
00228 storage(const storage& rhs);
00229 storage& operator=(const storage& rhs);
00230 void copy(const storage& rhs);
00231
00234 const char* filename() const {return name;}
00235
00237 bool empty() const {return (m_begin == 0 || m_begin >= m_end);}
00239 size_t size() const {
00240 return (m_begin!=0 && m_begin<m_end ? m_end-m_begin : 0);}
00242 size_t bytes() const {
00243 return (m_begin!=0 && m_begin<m_end ? m_end-m_begin : 0);}
00246 void enlarge(size_t nelm=0);
00247
00249 char* begin() {return m_begin;}
00251 const char* end() const {return m_end;}
00253 const char* begin() const {return m_begin;}
00255 char operator[](size_t i) const {return m_begin[i];}
00256
00257 virtual void beginUse();
00258 virtual void endUse();
00260 unsigned inUse() const {return nref();}
00262 unsigned pastUse() const {return nacc;}
00263
00265 virtual bool isFileMap() const {return false;}
00266
00267 virtual void printStatus(std::ostream& out) const;
00268 off_t read(const char* fname, const off_t begin, const off_t end);
00269 off_t read(const int fdes, const off_t begin, const off_t end);
00270 void write(const char* file) const;
00271
00272 inline void swap(storage& rhs) throw ();
00273
00274
00275
00276
00277
00278
00279
00280 protected:
00281 char* name;
00282 char* m_begin;
00283 char* m_end;
00284 unsigned nacc;
00285
00286 ibis::util::sharedInt32 nref;
00287
00288 virtual void clear();
00289 };
00290
00299 class FASTBIT_CXX_DLLSPEC ibis::fileManager::roFile
00300 : public ibis::fileManager::storage {
00301 public:
00302 virtual ~roFile() {clear();}
00303
00304
00305 virtual void beginUse();
00306 virtual void endUse();
00307
00308 virtual bool isFileMap() const {return (mapped != 0);}
00309
00310
00311 virtual void printStatus(std::ostream& out) const;
00312 void read(const char* file);
00313 #if defined(HAVE_FILE_MAP)
00314 void mapFile(const char* file);
00315 #endif
00316
00317
00318
00319
00320
00321
00322
00323 protected:
00324 roFile();
00325
00326 void doRead(const char* file);
00327
00328 void doRead(const char* file, off_t b, off_t e);
00329 #if defined(HAVE_FILE_MAP)
00330 void doMap(const char* file, off_t b, off_t e, int opt=0);
00331 #endif
00332
00336 float score() const {
00337 float sc = FLT_MAX;
00338 time_t now = time(0);
00339 if (opened >= now) {
00340 sc = static_cast<float>(1e-4 * size() + nacc);
00341 }
00342 else if (lastUse >= now) {
00343 sc = static_cast<float>(sqrt(5e-6*size()) + nacc +
00344 (now - opened));
00345 }
00346 else {
00347 sc = static_cast<float>((sqrt(1e-6*size() + now - opened) +
00348 (static_cast<double>(nacc) /
00349 (now - opened))) / (now - lastUse));
00350 }
00351 return sc;
00352 }
00353
00354 friend class ibis::fileManager;
00355 virtual void clear();
00356
00357 void printBody(std::ostream& out) const;
00358
00359 private:
00360 time_t opened;
00361 time_t lastUse;
00362 unsigned mapped;
00363
00364 #if defined(_WIN32) && defined(_MSC_VER)
00365 HANDLE fdescriptor;
00366 HANDLE fmap;
00367 LPVOID map_begin;
00368 #elif (HAVE_MMAP+0 > 0)
00369 int fdescriptor;
00370 size_t fsize;
00371 void *map_begin;
00372 #endif
00373
00374
00375 roFile(const roFile&);
00376 roFile& operator=(const roFile&);
00377 };
00378
00379 #if defined(HAVE_FILE_MAP)
00380
00381
00382
00383 class FASTBIT_CXX_DLLSPEC ibis::fileManager::rofSegment
00384 : public ibis::fileManager::roFile {
00385 public:
00386 rofSegment(const char *fn, off_t b, off_t e);
00387 virtual ~rofSegment() {};
00388 virtual void printStatus(std::ostream& out) const;
00389
00390 private:
00391 rofSegment();
00392 rofSegment(const rofSegment&);
00393 rofSegment& operator=(const rofSegment&);
00394
00395 std::string filename_;
00396 off_t begin_, end_;
00397 };
00398 #endif
00399
00401 class ibis::fileManager::writeLock {
00402 public:
00403 writeLock(const char* m) : mesg(m)
00404 {ibis::fileManager::instance().gainWriteAccess(mesg);}
00405 ~writeLock() {ibis::fileManager::instance().releaseAccess(mesg);}
00406 private:
00407 const char* mesg;
00408
00409 writeLock(const writeLock&);
00410 writeLock& operator=(const writeLock&);
00411 };
00412
00414 class ibis::fileManager::softWriteLock {
00415 public:
00416 softWriteLock(const char* m);
00417 ~softWriteLock();
00420 bool isLocked() const {return(locked_==0);}
00421
00422 private:
00423 const char* mesg;
00424 const int locked_;
00425
00426 softWriteLock(const softWriteLock&);
00427 softWriteLock& operator=(const softWriteLock&);
00428 };
00429
00430 inline uint64_t ibis::fileManager::bytesFree() {
00431 if (maxBytes == 0)
00432 ibis::fileManager::instance();
00433 return (maxBytes > ibis::fileManager::totalBytes() ?
00434 maxBytes - ibis::fileManager::totalBytes() : 0);
00435 }
00436
00437 inline void ibis::fileManager::releaseAccess(const char* mesg) const {
00438 int ierr = pthread_rwlock_unlock(&lock);
00439 if (0 == ierr) {
00440 LOGGER(ibis::gVerbose > 9)
00441 << "fileManager::releaseAccess on "
00442 << static_cast<const void*>(&lock) << " for " << mesg;
00443 }
00444 else {
00445 LOGGER(ibis::gVerbose >= 0)
00446 << "Warning -- fileManager::releaseAccess on "
00447 << static_cast<const void*>(&lock) << " for " << mesg
00448 << " failed with the error code " << ierr << " -- "
00449 << strerror(ierr);
00450 }
00451 }
00452
00453 inline void ibis::fileManager::gainReadAccess(const char* mesg) const {
00454 int ierr = pthread_rwlock_rdlock(&lock);
00455 if (0 == ierr) {
00456 LOGGER(ibis::gVerbose > 9)
00457 << "fileManager::gainReadAccess on "
00458 << static_cast<const void*>(&lock) << " for " << mesg;
00459 }
00460 else {
00461 LOGGER(ibis::gVerbose >= 0)
00462 << "Warning -- fileManager::gainReadAccess on "
00463 << static_cast<const void*>(&lock) << " for " << mesg
00464 << " failed with the error code " << ierr << " -- "
00465 << strerror(ierr);
00466 }
00467 }
00468
00469 inline void ibis::fileManager::gainWriteAccess(const char* mesg) const {
00470 int ierr = pthread_rwlock_wrlock(&lock);
00471 if (0 == ierr) {
00472 LOGGER(ibis::gVerbose > 9)
00473 << "fileManager::gainWriteAccess on "
00474 << static_cast<const void*>(&lock) << " for " << mesg;
00475 }
00476 else {
00477 LOGGER(ibis::gVerbose >= 0)
00478 << "Warning -- fileManager::gainWriteAccess on "
00479 << static_cast<const void*>(&lock) << " for " << mesg
00480 << " failed with the error code " << ierr << " -- "
00481 << strerror(ierr);
00482 }
00483 }
00484
00488 inline void ibis::fileManager::recordPages(off_t start, off_t stop) {
00489 if (start < stop) {
00490 start -= (start % pagesize);
00491 if (stop % pagesize)
00492 stop += pagesize - stop % pagesize;
00493 page_count += static_cast<double>((stop - start) / pagesize);
00494 }
00495 }
00496
00497 inline void
00498 ibis::fileManager::increaseUse(size_t inc, const char* evt) {
00499 ibis::fileManager::totalBytes += inc;
00500 LOGGER(inc > 0 && evt != 0 && *evt != 0 && ibis::gVerbose > 9)
00501 << evt << " added " << inc << " bytes to increase totalBytes to "
00502 << ibis::fileManager::totalBytes();
00503 }
00504
00505 inline void
00506 ibis::fileManager::decreaseUse(size_t dec, const char* evt) {
00507 ibis::fileManager::totalBytes -= dec;
00508 LOGGER(dec > 0 && evt != 0 && *evt != 0 && ibis::gVerbose > 9)
00509 << evt << " removed " << dec << " bytes to decrease totalBytes to "
00510 << ibis::fileManager::totalBytes();
00511 }
00512
00522 inline void
00523 ibis::fileManager::storage::swap(ibis::fileManager::storage& rhs) throw () {
00524 {char* tmp = name; name = rhs.name; rhs.name = tmp;}
00525 {char* tmp = m_begin; m_begin = rhs.m_begin; rhs.m_begin = tmp;}
00526 {char* tmp = m_end; m_end = rhs.m_end; rhs.m_end = tmp;}
00527 {unsigned itmp = nacc; nacc = rhs.nacc; rhs.nacc = itmp;}
00528
00529 }
00530 #endif // IBIS_FILEMANAGER_H