#include #include #include #include class ParentNameLockTestThread : public PThread { public: ParentNameLockTestThread(const unsigned id, EntryLockStore& entryLockStore, const std::string& parentID, const std::string& name): PThread("ParentNameLockTestThread" + StringTk::uintToStr(id)), entryLockStore(entryLockStore), parentID(parentID), name(name) { } void run() override { const unsigned maxSleepSeconds = 1; const std::string threadName = getCurrentThreadName(); const char* logContext(threadName.c_str()); Random r; const int sleepSec = r.getNextInRange(0, maxSleepSeconds); LogContext(logContext).log(Log_DEBUG, "Trying to lock '" + parentID + "/" + name + "'"); ParentNameLockData* lock = entryLockStore.lock(parentID, name); LogContext(logContext).log(Log_DEBUG, "Locked '" + parentID + "/" + name + "'"); LogContext(logContext).log(Log_DEBUG, "Sleeping for " + StringTk::intToStr(sleepSec) + " seconds"); sleep(sleepSec); LogContext(logContext).log(Log_DEBUG, "Trying to unlock '" + parentID + "/" + name + "'"); entryLockStore.unlock(lock); LogContext(logContext).log(Log_DEBUG, "Unlocked '" + parentID + "/" + name + "'"); } private: EntryLockStore& entryLockStore; const std::string parentID; const std::string name; }; class FileIDLockTestThread : public PThread { public: FileIDLockTestThread(const unsigned id, EntryLockStore& entryLockStore, const std::string& fileID) : PThread("FileIDLockTestThread" + StringTk::uintToStr(id)), entryLockStore(entryLockStore), fileID(fileID) { } void run() override { const unsigned maxSleepSeconds = 1; const std::string threadName = getCurrentThreadName(); const char* logContext(threadName.c_str()); Random r; const int sleepSec = r.getNextInRange(0, maxSleepSeconds); LogContext(logContext).log(Log_DEBUG, "Trying to lock '" + fileID + "'"); FileIDLockData* lock = entryLockStore.lock(fileID, true); LogContext(logContext).log(Log_DEBUG, "Locked '" + fileID + "'"); LogContext(logContext).log(Log_DEBUG, "Sleeping for " + StringTk::intToStr(sleepSec) + " seconds"); sleep(sleepSec); LogContext(logContext).log(Log_DEBUG, "Trying to unlock '" + fileID + "'"); entryLockStore.unlock(lock); LogContext(logContext).log(Log_DEBUG, "Unlocked '" + fileID + "'"); } private: EntryLockStore& entryLockStore; const std::string fileID; }; class DirIDLockTestThread : public PThread { public: DirIDLockTestThread(const unsigned id, EntryLockStore& entryLockStore, const std::string& dirID, const bool writeLock) : PThread("DirIDLockTestThread" + StringTk::uintToStr(id)), entryLockStore(entryLockStore), dirID(dirID), writeLock(writeLock) { } void run() override { const unsigned maxSleepSeconds = 1; const std::string logInfo(writeLock ? dirID + "/write" : dirID + "/read"); const std::string threadName = getCurrentThreadName(); const char* logContext(threadName.c_str()); Random r; const int sleepSec = r.getNextInRange(0, maxSleepSeconds); LogContext(logContext).log(Log_DEBUG, "Trying to lock '" + logInfo + "'"); FileIDLockData* lock = entryLockStore.lock(dirID, writeLock); LogContext(logContext).log(Log_DEBUG, "Locked '" + logInfo + "'"); LogContext(logContext).log(Log_DEBUG, "Sleeping for " + StringTk::intToStr(sleepSec) + " seconds"); sleep(sleepSec); LogContext(logContext).log(Log_DEBUG, "Trying to unlock '" + logInfo + "'"); entryLockStore.unlock(lock); LogContext(logContext).log(Log_DEBUG, "Unlocked '" + logInfo + "'"); } private: EntryLockStore& entryLockStore; const std::string dirID; const bool writeLock; }; TEST(BuddyMirroring, simpleEntryLocks) { EntryLockStore entryLockStore; const unsigned numThreadsEach = 15; std::list threadList; // prepare ParentNameLocks std::string parentIDA = "PIDA"; std::string nameA = "NAMEA"; std::string parentIDB = "PIDB"; std::string nameB = "NAMEB"; unsigned i=0; for ( ; i::iterator iter = threadList.begin(); iter != threadList.end(); iter++ ) (*iter)->start(); for ( std::list::iterator iter = threadList.begin(); iter != threadList.end(); iter++ ) (*iter)->join(); for ( std::list::iterator iter = threadList.begin(); iter != threadList.end(); iter++ ) SAFE_DELETE(*iter); } TEST(BuddyMirroring, rwEntryLocks) { EntryLockStore entryLockStore; const unsigned numThreadsRead = 15; const unsigned numThreadsWrite = 5; std::list threadList; // prepare FileIDLocks for Directories std::string dirID = "dirID"; for (unsigned i=0 ; i::iterator iter = threadList.begin(); iter != threadList.end(); iter++ ) (*iter)->start(); for ( std::list::iterator iter = threadList.begin(); iter != threadList.end(); iter++ ) (*iter)->join(); for ( std::list::iterator iter = threadList.begin(); iter != threadList.end(); iter++ ) SAFE_DELETE(*iter); }