fileManager.h
Go to the documentation of this file.
00001 // File: $Id$
00002 // Author: K. John Wu <John.Wu at acm.org>
00003 //         Lawrence Berkeley National Laboratory
00004 // Copyright 2000-2012 University of California
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>          // std::set
00018 #include <map>          // std::map
00019 
00023 class FASTBIT_CXX_DLLSPEC ibis::fileManager {
00024 public:
00025 
00029     enum ACCESS_PREFERENCE {
00030         MMAP_LARGE_FILES,       // files > minMapSize are mapped if possible
00031         PREFER_READ,            // read the whole file into memory
00032         PREFER_MMAP             // try to use mmap if possible
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; // forward declaration of fileManager::roFile
00075     class storage; // forward declaration of fileManager::storage
00076 #if defined(HAVE_FILE_MAP)
00077     class rofSegment; // forward declaration of fileManager::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; // mesg identifies the holder of the lock
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     }; // buffer
00153 
00154 protected:
00155     fileManager();  // get its input parameter from ibis::gParameters()
00156     ~fileManager(); // it exists forever
00157 
00158     void recordFile(roFile*); // record a new storage
00159 
00160     // parameters for controlling the resource usage
00162     static ibis::util::sharedInt64 totalBytes;
00164     static uint64_t maxBytes;
00166     static unsigned int maxOpenFiles;
00167 
00168     // not implemented, to prevent compiler from generating these functions
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; // files that are memory mapped
00178     fileList incore; // files that have been read into the main memory
00179     nameList reading;// files that are being read by the function getFile
00180     cleanerList cleaners; // list of external 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; // the multiple read single write lock
00191     mutable pthread_mutex_t mutex; // control access to incore and mapped
00192     mutable pthread_cond_t cond;   // conditional variable -- unload(), etc..
00193 
00194     static time_t hbeat;        // a simple counter, no mutex lock
00196     static uint32_t pagesize;
00197 
00198     int unload(size_t size);    // try to unload size bytes
00199     void invokeCleaners() const;// invoke external cleaners
00200     inline void gainWriteAccess(const char* m) const;
00201 
00202     class writeLock;
00203     class softWriteLock;
00204     friend class writeLock;
00205     friend class softWriteLock;
00206 }; // class fileManager
00207 
00218 class FASTBIT_CXX_DLLSPEC ibis::fileManager::storage {
00219 public:
00220     storage();
00221     explicit storage(size_t n); // allocate n bytes
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     // IO functions
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 //      // compares storage objects according to starting addresses
00273 //      struct less : std::binary_function< storage*, storage*, bool > {
00274 //      bool operator()(const storage* x, const storage* y) const {
00275 //          return (x->begin() < y->begin());
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(); // free memory/close file
00288 }; // class fileManager::storage
00289 
00298 class FASTBIT_CXX_DLLSPEC ibis::fileManager::roFile
00299     : public ibis::fileManager::storage {
00300 public:
00301     virtual ~roFile() {clear();}
00302 
00303     // functions for recording access statistics
00304     virtual void beginUse();
00305     virtual void endUse();
00306     // is the read-only file mapped ?
00307     virtual bool isFileMap() const {return (mapped != 0);}
00308 
00309     // IO functions
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 //      // compares storage objects according to file names
00317 //      struct less : std::binary_function< roFile*, roFile*, bool > {
00318 //      bool operator()(const roFile* x, const roFile* y) const {
00319 //          return strcmp(x->filename(), y->filename()) < 0;
00320 //      }
00321 //      };
00322 protected:
00323     roFile();
00324     // Read the whole file into memory.
00325     void doRead(const char* file);
00326     // Read the specified segment of the file into memory.
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(); // free memory/close file
00355 
00356     void printBody(std::ostream& out) const;
00357 
00358 private:
00359     time_t opened; // time first created, presumably when the file was opened
00360     time_t lastUse; // time of last use
00361     unsigned mapped; // 0 not a mapped file, otherwise yes
00362 
00363 #if defined(_WIN32) && defined(_MSC_VER)
00364     HANDLE fdescriptor; // HANDLE to the open file
00365     HANDLE fmap; // HANDLE to the mapping object
00366     LPVOID map_begin; // actual address returned by MapViewOfFile
00367 #elif (HAVE_MMAP+0 > 0)
00368     int fdescriptor; // descriptor of the open file
00369     size_t fsize;    // the size of the mapped portion of file
00370     void *map_begin; // actual address returned by mmap
00371 #endif
00372 
00373     // not implemented, to prevent automatic generation
00374     roFile(const roFile&);
00375     roFile& operator=(const roFile&);
00376 }; // class fileManager::roFile
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(); // no default constructor
00391     rofSegment(const rofSegment&); // no copy constructor
00392     rofSegment& operator=(const rofSegment&); // no assignment operator
00393 
00394     std::string filename_; // name of the file
00395     off_t begin_, end_;    // the start and the end address of the file map
00396 }; // ibis::fileManager::rofSegment
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 }; // ibis::fileManager::writeLock
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 }; // ibis::fileManager::softWriteLock
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 } // ibis::fileManager::bytesFree
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 } // ibis::fileManager::releaseAccess
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 } // ibis::fileManager::gainReadAccess
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 } // ibis::fileManager::gainWriteAccess
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 } // ibis::fileManager::recordPages
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 } // ibis::fileManager::increaseUse
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 } // ibis::fileManager::decreaseUse
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     //nref.swap(rhs.nref);
00526 } // ibis::fileManager::storage::swap
00527 #endif // IBIS_FILEMANAGER_H

Make It A Bit Faster
Contact us
Disclaimers
FastBit source code
FastBit mailing list archive