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

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