diff --git a/src/IOCoordinator.cpp b/src/IOCoordinator.cpp index fbcc40ae3..e1a07cebb 100644 --- a/src/IOCoordinator.cpp +++ b/src/IOCoordinator.cpp @@ -435,4 +435,50 @@ string IOCoordinator::getNewKey(string sourceName, size_t offset, size_t length) return ss.str(); } +bool IOCoordinator::readLock(const string &filename) +{ + boost::unique_lock s(lockMutex); + + auto ins = locks.insert(pair(filename, NULL)); + if (ins.second) + ins.first->second = new RWLock(); + ins.first->second->readLock(s); +} + +void IOCoordinator::readUnlock(const string &filename) +{ + boost::unique_lock s(lockMutex); + + auto it = locks.find(filename); + it->second->readUnlock(); + if (!it->second->inUse()) + { + delete it->second; + locks.erase(it); + } +} + +bool IOCoordinator::writeLock(const string &filename) +{ + boost::unique_lock s(lockMutex); + + auto ins = locks.insert(pair(filename, NULL)); + if (ins.second) + ins.first->second = new RWLock(); + ins.first->second->writeLock(s); +} + +void IOCoordinator::writeUnlock(const string &filename) +{ + boost::unique_lock s(lockMutex); + + auto it = locks.find(filename); + it->second->readUnlock(); + if (!it->second->inUse()) + { + delete it->second; + locks.erase(it); + } +} + } diff --git a/src/IOCoordinator.h b/src/IOCoordinator.h index 134187aa1..a91347a37 100644 --- a/src/IOCoordinator.h +++ b/src/IOCoordinator.h @@ -13,6 +13,7 @@ #include "Config.h" #include "SMLogging.h" +#include "RWLock.h" namespace storagemanager { @@ -44,11 +45,20 @@ class IOCoordinator : public boost::noncopyable boost::shared_array mergeJournal(const char *objectPath, const char *journalPath, off_t offset = 0, size_t len = 0) const; int mergeJournalInMem(uint8_t *objData, const char *journalPath); + /* Lock manipulation fcns. They can lock on any param given to them. */ + bool readLock(const std::string &filename); + bool writeLock(const std::string &filename); + void readUnlock(const std::string &filename); + void writeUnlock(const std::string &filename); + private: IOCoordinator(); Config *config; SMLogging *logger; size_t objectSize; + + std::map locks; + boost::mutex lockMutex; // lol }; } diff --git a/src/RWLock.cpp b/src/RWLock.cpp index 22f5cf59c..c6af32190 100644 --- a/src/RWLock.cpp +++ b/src/RWLock.cpp @@ -15,6 +15,11 @@ RWLock::~RWLock() assert(!writersRunning); } +bool RWLock::inUse() +{ + return readersWaiting || readersRunning || writersWaiting || writersRunning; +} + void RWLock::readLock() { boost::unique_lock s(m); @@ -27,6 +32,19 @@ void RWLock::readLock() --readersWaiting; } +void RWLock::readLock(boost::unique_lock &l) +{ + boost::unique_lock s(m); + l.unlock(); + + ++readersWaiting; + while (writersWaiting != 0 || writersRunning != 0) + okToRead.wait(s); + + ++readersRunning; + --readersWaiting; +} + void RWLock::readUnlock() { boost::unique_lock s(m); @@ -48,6 +66,19 @@ void RWLock::writeLock() --writersWaiting; } +void RWLock::writeLock(boost::unique_lock &l) +{ + boost::unique_lock s(m); + l.unlock(); + + ++writersWaiting; + while (readersRunning != 0 || writersRunning != 0) + okToWrite.wait(s); + + ++writersRunning; + --writersWaiting; +} + void RWLock::writeUnlock() { boost::unique_lock s(m); diff --git a/src/RWLock.h b/src/RWLock.h index 188ff4e0c..28eab3ff0 100644 --- a/src/RWLock.h +++ b/src/RWLock.h @@ -1,7 +1,6 @@ #include #include - /* Quicky impl of a read-write lock that prioritizes writers. */ namespace storagemanager { @@ -12,10 +11,17 @@ namespace storagemanager ~RWLock(); void readLock(); + // this version will release the lock in the parameter after locking this instance + void readLock(boost::unique_lock &); void readUnlock(); void writeLock(); + // this version will release the lock in the parameter after locking this instance + void writeLock(boost::unique_lock &); void writeUnlock(); + // returns true if anything is blocked on or owns this lock instance. + bool inUse(); + private: uint readersWaiting; uint readersRunning;