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
00023 class FASTBIT_CXX_DLLSPEC ibis::fileManager {
00024 public:
00025
00029 enum ACCESS_PREFERENCE {
00030 MMAP_LARGE_FILES,
00031 PREFER_READ,
00032 PREFER_MMAP
00033 };
00034
00035 template<typename T>
00036 int getFile(const char* name, array_t<T>& arr,
00037 ACCESS_PREFERENCE pref=MMAP_LARGE_FILES);
00038 template<typename T>
00039 int tryGetFile(const char* name, array_t<T>& arr,
00040 ACCESS_PREFERENCE pref=MMAP_LARGE_FILES);
00041
00043 void printStatus(std::ostream& out) const;
00045 void flushFile(const char* name);
00047 void flushDir(const char* name);
00049 void clear();
00050
00052 static fileManager& instance();
00054 static time_t iBeat() {return hbeat++;}
00056 const double& pageCount() const {return page_count;}
00058 static uint32_t pageSize() {return pagesize;}
00059 inline void recordPages(off_t start, off_t stop);
00060 static inline void increaseUse(size_t inc, const char* evt);
00061 static inline void decreaseUse(size_t dec, const char* evt);
00063 void signalMemoryAvailable() const;
00064
00066 class cleaner {
00067 public:
00068 virtual void operator()() const = 0;
00069 virtual ~cleaner() {};
00070 };
00071 void addCleaner(const cleaner* cl);
00072 void removeCleaner(const cleaner* cl);
00073
00074 class roFile;
00075 class storage;
00076 #if defined(HAVE_FILE_MAP)
00077 class rofSegment;
00078 #endif
00079 friend class roFile;
00080 friend class storage;
00081 int getFile(const char* name, storage** st,
00082 ACCESS_PREFERENCE pref=MMAP_LARGE_FILES);
00083 int tryGetFile(const char* name, storage** st,
00084 ACCESS_PREFERENCE pref=MMAP_LARGE_FILES);
00085 static storage* getFileSegment(const char* name, const int fdes,
00086 const off_t b, const off_t e);
00087
00089 inline void gainReadAccess(const char* mesg) const;
00091 inline void releaseAccess(const char* mesg) const;
00094 class readLock {
00095 public:
00096 readLock(const char* m) : mesg(m) {
00097 ibis::fileManager::instance().gainReadAccess(m);
00098 }
00099 ~readLock() {
00100 ibis::fileManager::instance().releaseAccess(mesg);
00101 }
00102 private:
00103 const char* mesg;
00104 };
00105
00107 static uint64_t currentCacheSize() {return maxBytes;}
00109 static int adjustCacheSize(uint64_t);
00111 static uint64_t bytesInUse() {return ibis::fileManager::totalBytes();}
00113 static uint64_t bytesFree();
00114
00118 template <typename T>
00119 class buffer {
00120 public:
00122 buffer(size_t sz=0);
00124 ~buffer();
00125
00127 T& operator[](size_t i) {return buf[i];}
00129 const T& operator[](size_t i) const {return buf[i];}
00131 T* address() const {return buf;}
00133 size_t size() const {return nbuf;}
00135 size_t resize(size_t sz=0);
00137 void swap(buffer<T>& other) throw () {
00138 T* btmp = buf;
00139 buf = other.buf;
00140 other.buf = btmp;
00141 size_t ntmp = nbuf;
00142 nbuf = other.nbuf;
00143 other.nbuf = ntmp;
00144 }
00145
00146 private:
00147 T* buf;
00148 size_t nbuf;
00149
00150 buffer(const buffer<T>&);
00151 buffer<T>& operator=(const buffer<T>&);
00152 };
00153
00154 protected:
00155 fileManager();
00156 ~fileManager();
00157
00158 void recordFile(roFile*);
00159
00160
00162 static ibis::util::sharedInt64 totalBytes;
00164 static uint64_t maxBytes;
00166 static unsigned int maxOpenFiles;
00167
00168
00169 fileManager(const fileManager& rhs);
00170 fileManager& operator=(const fileManager& rhs);
00171
00172 private:
00173 typedef std::map< const char*, roFile*,
00174 std::less< const char* > > fileList;
00175 typedef std::set< const cleaner* > cleanerList;
00176 typedef std::set< const char*, std::less< const char* > > nameList;
00177 fileList mapped;
00178 fileList incore;
00179 nameList reading;
00180 cleanerList cleaners;
00182 double page_count;
00184 uint32_t minMapSize;
00186 uint32_t nwaiting;
00188 pthread_cond_t readCond;
00189
00190 mutable pthread_rwlock_t lock;
00191 mutable pthread_mutex_t mutex;
00192 mutable pthread_cond_t cond;
00193
00194 static time_t hbeat;
00196 static uint32_t pagesize;
00197
00198 int unload(size_t size);
00199 void invokeCleaners() const;
00200 inline void gainWriteAccess(const char* m) const;
00201
00202 class writeLock;
00203 class softWriteLock;
00204 friend class writeLock;
00205 friend class softWriteLock;
00206 };
00207
00218 class FASTBIT_CXX_DLLSPEC ibis::fileManager::storage {
00219 public:
00220 storage();
00221 explicit storage(size_t n);
00222 virtual ~storage() {clear();}
00223
00224 storage(const char* fname, const off_t begin, const off_t end);
00225 storage(const int fdes, const off_t begin, const off_t end);
00226 storage(const char* begin, const char* end);
00227 storage(const storage& rhs);
00228 storage& operator=(const storage& rhs);
00229 void copy(const storage& rhs);
00230
00233 const char* filename() const {return name;}
00234
00236 bool empty() const {return (m_begin == 0 || m_begin >= m_end);}
00238 size_t size() const {
00239 return (m_begin!=0 && m_begin<m_end ? m_end-m_begin : 0);}
00241 size_t bytes() const {
00242 return (m_begin!=0 && m_begin<m_end ? m_end-m_begin : 0);}
00245 void enlarge(size_t nelm=0);
00246
00248 char* begin() {return m_begin;}
00250 const char* end() const {return m_end;}
00252 const char* begin() const {return m_begin;}
00254 char operator[](size_t i) const {return m_begin[i];}
00255
00256 virtual void beginUse();
00257 virtual void endUse();
00259 unsigned inUse() const {return nref();}
00261 unsigned pastUse() const {return nacc;}
00262
00264 virtual bool isFileMap() const {return false;}
00265
00266 virtual void printStatus(std::ostream& out) const;
00267 off_t read(const char* fname, const off_t begin, const off_t end);
00268 off_t read(const int fdes, const off_t begin, const off_t end);
00269 void write(const char* file) const;
00270
00271 inline void swap(storage& rhs) throw ();
00272
00273
00274
00275
00276
00277
00278
00279 protected:
00280 char* name;
00281 char* m_begin;
00282 char* m_end;
00283 unsigned nacc;
00284
00285 ibis::util::sharedInt32 nref;
00286
00287 virtual void clear();
00288 };
00289
00298 class FASTBIT_CXX_DLLSPEC ibis::fileManager::roFile
00299 : public ibis::fileManager::storage {
00300 public:
00301 virtual ~roFile() {clear();}
00302
00303
00304 virtual void beginUse();
00305 virtual void endUse();
00306
00307 virtual bool isFileMap() const {return (mapped != 0);}
00308
00309
00310 virtual void printStatus(std::ostream& out) const;
00311 void read(const char* file);
00312 #if defined(HAVE_FILE_MAP)
00313 void mapFile(const char* file);
00314 #endif
00315
00316
00317
00318
00319
00320
00321
00322 protected:
00323 roFile();
00324
00325 void doRead(const char* file);
00326
00327 void doRead(const char* file, off_t b, off_t e);
00328 #if defined(HAVE_FILE_MAP)
00329 void doMap(const char* file, off_t b, off_t e, int opt=0);
00330 #endif
00331
00335 float score() const {
00336 float sc = FLT_MAX;
00337 time_t now = time(0);
00338 if (opened >= now) {
00339 sc = static_cast<float>(1e-4 * size() + nacc);
00340 }
00341 else if (lastUse >= now) {
00342 sc = static_cast<float>(sqrt(5e-6*size()) + nacc +
00343 (now - opened));
00344 }
00345 else {
00346 sc = static_cast<float>((sqrt(1e-6*size() + now - opened) +
00347 (static_cast<double>(nacc) /
00348 (now - opened))) / (now - lastUse));
00349 }
00350 return sc;
00351 }
00352
00353 friend class ibis::fileManager;
00354 virtual void clear();
00355
00356 void printBody(std::ostream& out) const;
00357
00358 private:
00359 time_t opened;
00360 time_t lastUse;
00361 unsigned mapped;
00362
00363 #if defined(_WIN32) && defined(_MSC_VER)
00364 HANDLE fdescriptor;
00365 HANDLE fmap;
00366 LPVOID map_begin;
00367 #elif (HAVE_MMAP+0 > 0)
00368 int fdescriptor;
00369 size_t fsize;
00370 void *map_begin;
00371 #endif
00372
00373
00374 roFile(const roFile&);
00375 roFile& operator=(const roFile&);
00376 };
00377
00378 #if defined(HAVE_FILE_MAP)
00379
00380
00381
00382 class FASTBIT_CXX_DLLSPEC ibis::fileManager::rofSegment
00383 : public ibis::fileManager::roFile {
00384 public:
00385 rofSegment(const char *fn, off_t b, off_t e);
00386 virtual ~rofSegment() {};
00387 virtual void printStatus(std::ostream& out) const;
00388
00389 private:
00390 rofSegment();
00391 rofSegment(const rofSegment&);
00392 rofSegment& operator=(const rofSegment&);
00393
00394 std::string filename_;
00395 off_t begin_, end_;
00396 };
00397 #endif
00398
00400 class ibis::fileManager::writeLock {
00401 public:
00402 writeLock(const char* m) : mesg(m)
00403 {ibis::fileManager::instance().gainWriteAccess(mesg);}
00404 ~writeLock() {ibis::fileManager::instance().releaseAccess(mesg);}
00405 private:
00406 const char* mesg;
00407
00408 writeLock(const writeLock&);
00409 writeLock& operator=(const writeLock&);
00410 };
00411
00413 class ibis::fileManager::softWriteLock {
00414 public:
00415 softWriteLock(const char* m);
00416 ~softWriteLock();
00419 bool isLocked() const {return(locked_==0);}
00420
00421 private:
00422 const char* mesg;
00423 const int locked_;
00424
00425 softWriteLock(const softWriteLock&);
00426 softWriteLock& operator=(const softWriteLock&);
00427 };
00428
00429 inline uint64_t ibis::fileManager::bytesFree() {
00430 if (maxBytes == 0)
00431 ibis::fileManager::instance();
00432 return (maxBytes > ibis::fileManager::totalBytes() ?
00433 maxBytes - ibis::fileManager::totalBytes() : 0);
00434 }
00435
00436 inline void ibis::fileManager::releaseAccess(const char* mesg) const {
00437 int ierr = pthread_rwlock_unlock(&lock);
00438 if (0 == ierr) {
00439 LOGGER(ibis::gVerbose > 9)
00440 << "fileManager::releaseAccess on "
00441 << static_cast<const void*>(&lock) << " for " << mesg;
00442 }
00443 else {
00444 LOGGER(ibis::gVerbose >= 0)
00445 << "Warning -- fileManager::releaseAccess on "
00446 << static_cast<const void*>(&lock) << " for " << mesg
00447 << " failed with the error code " << ierr << " -- "
00448 << strerror(ierr);
00449 }
00450 }
00451
00452 inline void ibis::fileManager::gainReadAccess(const char* mesg) const {
00453 int ierr = pthread_rwlock_rdlock(&lock);
00454 if (0 == ierr) {
00455 LOGGER(ibis::gVerbose > 9)
00456 << "fileManager::gainReadAccess on "
00457 << static_cast<const void*>(&lock) << " for " << mesg;
00458 }
00459 else {
00460 LOGGER(ibis::gVerbose >= 0)
00461 << "Warning -- fileManager::gainReadAccess on "
00462 << static_cast<const void*>(&lock) << " for " << mesg
00463 << " failed with the error code " << ierr << " -- "
00464 << strerror(ierr);
00465 }
00466 }
00467
00468 inline void ibis::fileManager::gainWriteAccess(const char* mesg) const {
00469 int ierr = pthread_rwlock_wrlock(&lock);
00470 if (0 == ierr) {
00471 LOGGER(ibis::gVerbose > 9)
00472 << "fileManager::gainWriteAccess on "
00473 << static_cast<const void*>(&lock) << " for " << mesg;
00474 }
00475 else {
00476 LOGGER(ibis::gVerbose >= 0)
00477 << "Warning -- fileManager::gainWriteAccess on "
00478 << static_cast<const void*>(&lock) << " for " << mesg
00479 << " failed with the error code " << ierr << " -- "
00480 << strerror(ierr);
00481 }
00482 }
00483
00487 inline void ibis::fileManager::recordPages(off_t start, off_t stop) {
00488 if (stop - start > 0) {
00489 start = (start / pagesize) * pagesize;
00490 page_count += ceil(static_cast<double>((stop - start)) / pagesize);
00491 }
00492 }
00493
00494 inline void
00495 ibis::fileManager::increaseUse(size_t inc, const char* evt) {
00496 ibis::fileManager::totalBytes += inc;
00497 LOGGER(inc > 0 && evt != 0 && *evt != 0 && ibis::gVerbose > 9)
00498 << evt << " added " << inc << " bytes to increase totalBytes to "
00499 << ibis::fileManager::totalBytes();
00500 }
00501
00502 inline void
00503 ibis::fileManager::decreaseUse(size_t dec, const char* evt) {
00504 ibis::fileManager::totalBytes -= dec;
00505 LOGGER(dec > 0 && evt != 0 && *evt != 0 && ibis::gVerbose > 9)
00506 << evt << " removed " << dec << " bytes to decrease totalBytes to "
00507 << ibis::fileManager::totalBytes();
00508 }
00509
00519 inline void
00520 ibis::fileManager::storage::swap(ibis::fileManager::storage& rhs) throw () {
00521 {char* tmp = name; name = rhs.name; rhs.name = tmp;}
00522 {char* tmp = m_begin; m_begin = rhs.m_begin; rhs.m_begin = tmp;}
00523 {char* tmp = m_end; m_end = rhs.m_end; rhs.m_end = tmp;}
00524 {unsigned itmp = nacc; nacc = rhs.nacc; rhs.nacc = itmp;}
00525
00526 }
00527 #endif // IBIS_FILEMANAGER_H