diff options
Diffstat (limited to 'src/mongo/util/mmap.h')
-rw-r--r-- | src/mongo/util/mmap.h | 386 |
1 files changed, 204 insertions, 182 deletions
diff --git a/src/mongo/util/mmap.h b/src/mongo/util/mmap.h index efadd91b124..c99453d7d11 100644 --- a/src/mongo/util/mmap.h +++ b/src/mongo/util/mmap.h @@ -42,220 +42,242 @@ namespace mongo { #if !defined(_WIN32) - typedef int HANDLE; +typedef int HANDLE; #endif - extern const size_t g_minOSPageSizeBytes; - void minOSPageSizeBytesTest(size_t minOSPageSizeBytes); // lame-o +extern const size_t g_minOSPageSizeBytes; +void minOSPageSizeBytesTest(size_t minOSPageSizeBytes); // lame-o - // call this if syncing data fails - void dataSyncFailedHandler(); +// call this if syncing data fails +void dataSyncFailedHandler(); - class MAdvise { - MONGO_DISALLOW_COPYING(MAdvise); - public: - enum Advice { Sequential=1 , Random=2 }; - MAdvise(void *p, unsigned len, Advice a); - ~MAdvise(); // destructor resets the range to MADV_NORMAL - private: - void *_p; - unsigned _len; - }; +class MAdvise { + MONGO_DISALLOW_COPYING(MAdvise); - // lock order: lock dbMutex before this if you lock both - class MONGO_CLIENT_API LockMongoFilesShared { - friend class LockMongoFilesExclusive; - static RWLockRecursiveNongreedy mmmutex; - static unsigned era; - RWLockRecursive::Shared lk; - public: - LockMongoFilesShared() : lk(mmmutex) { } +public: + enum Advice { Sequential = 1, Random = 2 }; + MAdvise(void* p, unsigned len, Advice a); + ~MAdvise(); // destructor resets the range to MADV_NORMAL +private: + void* _p; + unsigned _len; +}; - /** era changes anytime memory maps come and go. thus you can use this as a cheap way to check - if nothing has changed since the last time you locked. Of course you must be shared locked - at the time of this call, otherwise someone could be in progress. +// lock order: lock dbMutex before this if you lock both +class MONGO_CLIENT_API LockMongoFilesShared { + friend class LockMongoFilesExclusive; + static RWLockRecursiveNongreedy mmmutex; + static unsigned era; + RWLockRecursive::Shared lk; - This is used for yielding; see PageFaultException::touch(). - */ - static unsigned getEra() { return era; } +public: + LockMongoFilesShared() : lk(mmmutex) {} - static void assertExclusivelyLocked() { mmmutex.assertExclusivelyLocked(); } - static void assertAtLeastReadLocked() { mmmutex.assertAtLeastReadLocked(); } - }; + /** era changes anytime memory maps come and go. thus you can use this as a cheap way to check + if nothing has changed since the last time you locked. Of course you must be shared locked + at the time of this call, otherwise someone could be in progress. - class MONGO_CLIENT_API LockMongoFilesExclusive { - RWLockRecursive::Exclusive lk; - public: - LockMongoFilesExclusive() : lk(LockMongoFilesShared::mmmutex) { - LockMongoFilesShared::era++; - } - }; + This is used for yielding; see PageFaultException::touch(). + */ + static unsigned getEra() { + return era; + } - /* the administrative-ish stuff here */ - class MongoFile : boost::noncopyable { - public: - /** Flushable has to fail nicely if the underlying object gets killed */ - class Flushable { - public: - virtual ~Flushable() {} - virtual void flush() = 0; - }; - - virtual ~MongoFile() {} - - enum Options { - SEQUENTIAL = 1, // hint - e.g. FILE_FLAG_SEQUENTIAL_SCAN on windows - READONLY = 2 // not contractually guaranteed, but if specified the impl has option to fault writes - }; - - /** @param fun is called for each MongoFile. - called from within a mutex that MongoFile uses. so be careful not to deadlock. - */ - template < class F > - static void forEach( F fun ); + static void assertExclusivelyLocked() { + mmmutex.assertExclusivelyLocked(); + } + static void assertAtLeastReadLocked() { + mmmutex.assertAtLeastReadLocked(); + } +}; - /** note: you need to be in mmmutex when using this. forEach (above) handles that for you automatically. -*/ - static std::set<MongoFile*>& getAllFiles(); +class MONGO_CLIENT_API LockMongoFilesExclusive { + RWLockRecursive::Exclusive lk; - // callbacks if you need them - static void (*notifyPreFlush)(); - static void (*notifyPostFlush)(); +public: + LockMongoFilesExclusive() : lk(LockMongoFilesShared::mmmutex) { + LockMongoFilesShared::era++; + } +}; - static int flushAll( bool sync ); // returns n flushed - static long long totalMappedLength(); - static void closeAllFiles( std::stringstream &message ); +/* the administrative-ish stuff here */ +class MongoFile : boost::noncopyable { +public: + /** Flushable has to fail nicely if the underlying object gets killed */ + class Flushable { + public: + virtual ~Flushable() {} + virtual void flush() = 0; + }; - virtual bool isDurableMappedFile() { return false; } + virtual ~MongoFile() {} - std::string filename() const { return _filename; } - void setFilename(const std::string& fn); + enum Options { + SEQUENTIAL = 1, // hint - e.g. FILE_FLAG_SEQUENTIAL_SCAN on windows + READONLY = + 2 // not contractually guaranteed, but if specified the impl has option to fault writes + }; - virtual uint64_t getUniqueId() const = 0; + /** @param fun is called for each MongoFile. + called from within a mutex that MongoFile uses. so be careful not to deadlock. + */ + template <class F> + static void forEach(F fun); - private: - std::string _filename; - static int _flushAll( bool sync ); // returns n flushed - protected: - virtual void close() = 0; - virtual void flush(bool sync) = 0; - /** - * returns a thread safe object that you can call flush on - * Flushable has to fail nicely if the underlying object gets killed - */ - virtual Flushable * prepareFlush() = 0; + /** note: you need to be in mmmutex when using this. forEach (above) handles that for you automatically. +*/ + static std::set<MongoFile*>& getAllFiles(); - void created(); /* subclass must call after create */ + // callbacks if you need them + static void (*notifyPreFlush)(); + static void (*notifyPostFlush)(); - /* subclass must call in destructor (or at close). - removes this from pathToFile and other maps - safe to call more than once, albeit might be wasted work - ideal to call close to the close, if the close is well before object destruction - */ - void destroyed(); + static int flushAll(bool sync); // returns n flushed + static long long totalMappedLength(); + static void closeAllFiles(std::stringstream& message); - virtual unsigned long long length() const = 0; - }; + virtual bool isDurableMappedFile() { + return false; + } - /** look up a MMF by filename. scoped mutex locking convention. - example: - MMFFinderByName finder; - DurableMappedFile *a = finder.find("file_name_a"); - DurableMappedFile *b = finder.find("file_name_b"); + std::string filename() const { + return _filename; + } + void setFilename(const std::string& fn); + + virtual uint64_t getUniqueId() const = 0; + +private: + std::string _filename; + static int _flushAll(bool sync); // returns n flushed +protected: + virtual void close() = 0; + virtual void flush(bool sync) = 0; + /** + * returns a thread safe object that you can call flush on + * Flushable has to fail nicely if the underlying object gets killed + */ + virtual Flushable* prepareFlush() = 0; + + void created(); /* subclass must call after create */ + + /* subclass must call in destructor (or at close). + removes this from pathToFile and other maps + safe to call more than once, albeit might be wasted work + ideal to call close to the close, if the close is well before object destruction */ - class MONGO_CLIENT_API MongoFileFinder : boost::noncopyable { - public: - /** @return The MongoFile object associated with the specified file name. If no file is open - with the specified name, returns null. - */ - MongoFile* findByPath(const std::string& path) const; + void destroyed(); - private: - LockMongoFilesShared _lk; - }; + virtual unsigned long long length() const = 0; +}; - class MemoryMappedFile : public MongoFile { - protected: - virtual void* viewForFlushing() { - if( views.size() == 0 ) - return 0; - verify( views.size() == 1 ); - return views[0]; - } - public: - MemoryMappedFile(); +/** look up a MMF by filename. scoped mutex locking convention. + example: + MMFFinderByName finder; + DurableMappedFile *a = finder.find("file_name_a"); + DurableMappedFile *b = finder.find("file_name_b"); +*/ +class MONGO_CLIENT_API MongoFileFinder : boost::noncopyable { +public: + /** @return The MongoFile object associated with the specified file name. If no file is open + with the specified name, returns null. + */ + MongoFile* findByPath(const std::string& path) const; + +private: + LockMongoFilesShared _lk; +}; + +class MemoryMappedFile : public MongoFile { +protected: + virtual void* viewForFlushing() { + if (views.size() == 0) + return 0; + verify(views.size() == 1); + return views[0]; + } - virtual ~MemoryMappedFile() { - LockMongoFilesExclusive lk; - close(); - } +public: + MemoryMappedFile(); - virtual void close(); + virtual ~MemoryMappedFile() { + LockMongoFilesExclusive lk; + close(); + } - // Throws exception if file doesn't exist. (dm may2010: not sure if this is always true?) - void* map(const char *filename); + virtual void close(); - /** @param options see MongoFile::Options - */ - void* mapWithOptions(const char *filename, int options); + // Throws exception if file doesn't exist. (dm may2010: not sure if this is always true?) + void* map(const char* filename); - /* Creates with length if DNE, otherwise uses existing file length, - passed length. - @param options MongoFile::Options bits - */ - void* map(const char *filename, unsigned long long &length, int options = 0 ); + /** @param options see MongoFile::Options + */ + void* mapWithOptions(const char* filename, int options); - /* Create. Must not exist. - @param zero fill file with zeros when true - */ - void* create(const std::string& filename, unsigned long long len, bool zero); - - void flush(bool sync); - virtual Flushable * prepareFlush(); - - long shortLength() const { return (long) len; } - unsigned long long length() const { return len; } - HANDLE getFd() const { return fd; } - /** create a new view with the specified properties. - automatically cleaned up upon close/destruction of the MemoryMappedFile object. - */ - void* createReadOnlyMap(); - void* createPrivateMap(); - - virtual uint64_t getUniqueId() const { return _uniqueId; } - - private: - static void updateLength( const char *filename, unsigned long long &length ); - - HANDLE fd; - HANDLE maphandle; - std::vector<void *> views; - unsigned long long len; - const uint64_t _uniqueId; -#ifdef _WIN32 - // flush Mutex - // - // Protects: - // Prevent flush() and close() from concurrently running. - // It ensures close() cannot complete while flush() is running - // Lock Ordering: - // LockMongoFilesShared must be taken before _flushMutex if both are taken - boost::mutex _flushMutex; -#endif + /* Creates with length if DNE, otherwise uses existing file length, + passed length. + @param options MongoFile::Options bits + */ + void* map(const char* filename, unsigned long long& length, int options = 0); - protected: + /* Create. Must not exist. + @param zero fill file with zeros when true + */ + void* create(const std::string& filename, unsigned long long len, bool zero); - /** close the current private view and open a new replacement */ - void* remapPrivateView(void *oldPrivateAddr); - }; + void flush(bool sync); + virtual Flushable* prepareFlush(); + + long shortLength() const { + return (long)len; + } + unsigned long long length() const { + return len; + } + HANDLE getFd() const { + return fd; + } + /** create a new view with the specified properties. + automatically cleaned up upon close/destruction of the MemoryMappedFile object. + */ + void* createReadOnlyMap(); + void* createPrivateMap(); - /** p is called from within a mutex that MongoFile uses. so be careful not to deadlock. */ - template < class F > - inline void MongoFile::forEach( F p ) { - LockMongoFilesShared lklk; - const std::set<MongoFile*>& mmfiles = MongoFile::getAllFiles(); - for ( std::set<MongoFile*>::const_iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) - p(*i); + virtual uint64_t getUniqueId() const { + return _uniqueId; } -} // namespace mongo +private: + static void updateLength(const char* filename, unsigned long long& length); + + HANDLE fd; + HANDLE maphandle; + std::vector<void*> views; + unsigned long long len; + const uint64_t _uniqueId; +#ifdef _WIN32 + // flush Mutex + // + // Protects: + // Prevent flush() and close() from concurrently running. + // It ensures close() cannot complete while flush() is running + // Lock Ordering: + // LockMongoFilesShared must be taken before _flushMutex if both are taken + boost::mutex _flushMutex; +#endif + +protected: + /** close the current private view and open a new replacement */ + void* remapPrivateView(void* oldPrivateAddr); +}; + +/** p is called from within a mutex that MongoFile uses. so be careful not to deadlock. */ +template <class F> +inline void MongoFile::forEach(F p) { + LockMongoFilesShared lklk; + const std::set<MongoFile*>& mmfiles = MongoFile::getAllFiles(); + for (std::set<MongoFile*>::const_iterator i = mmfiles.begin(); i != mmfiles.end(); i++) + p(*i); +} + +} // namespace mongo |