beegfs/storage/source/components/buddyresyncer/BuddyResyncerGatherSlave.h
2025-08-10 01:34:16 +02:00

183 lines
4.8 KiB
C++

#pragma once
#include <common/app/log/LogContext.h>
#include <common/storage/mirroring/SyncCandidateStore.h>
#include <common/components/ComponentInitException.h>
#include <common/threading/PThread.h>
#include <ftw.h>
class StorageTarget;
#define GATHERSLAVEQUEUE_MAXSIZE 5000
class BuddyResyncerGatherSlaveWorkQueue
{
/*
* This is more or less just a small class for convenience, that is tightly coupled to
* BuddyResyncerGatherSlave and BuddyResyncerJob
*/
public:
BuddyResyncerGatherSlaveWorkQueue(): gatherSlavesWorkQueueLen(0) { }
private:
StringList paths;
size_t gatherSlavesWorkQueueLen; // used to avoid constant calling of size() method of list
Mutex mutex;
Condition pathAddedCond;
Condition pathFetchedCond;
public:
void add(std::string& path, PThread* caller)
{
unsigned waitTimeoutMS = 3000;
const std::lock_guard<Mutex> lock(mutex);
while (gatherSlavesWorkQueueLen > GATHERSLAVEQUEUE_MAXSIZE)
{
if((caller) && (unlikely(caller->getSelfTerminate())))
break;
pathFetchedCond.timedwait(&mutex, waitTimeoutMS);
}
paths.push_back(path);
gatherSlavesWorkQueueLen++;
pathAddedCond.signal();
}
std::string fetch(PThread* caller)
{
unsigned waitTimeoutMS = 3000;
const std::lock_guard<Mutex> lock(mutex);
while (paths.empty())
{
if((caller) && (unlikely(caller->getSelfTerminate())))
{
return "";
}
pathAddedCond.timedwait(&mutex, waitTimeoutMS);
}
std::string retVal = paths.front();
paths.pop_front();
gatherSlavesWorkQueueLen--;
pathFetchedCond.signal();
return retVal;
}
bool queueEmpty()
{
const std::lock_guard<Mutex> lock(mutex);
return gatherSlavesWorkQueueLen == 0;
}
void clear()
{
const std::lock_guard<Mutex> lock(mutex);
paths.clear();
gatherSlavesWorkQueueLen = 0;
}
};
class BuddyResyncerGatherSlave : public PThread
{
friend class BuddyResyncer; // (to grant access to internal mutex)
friend class BuddyResyncJob; // (to grant access to internal mutex)
public:
BuddyResyncerGatherSlave(const StorageTarget& target, ChunkSyncCandidateStore* syncCandidates,
BuddyResyncerGatherSlaveWorkQueue* workQueue, uint8_t slaveID);
virtual ~BuddyResyncerGatherSlave();
void workLoop();
private:
AtomicSizeT onlyTerminateIfIdle; // atomic quasi-bool
Mutex statusMutex; // protects isRunning
Condition isRunningChangeCond;
const StorageTarget& target;
AtomicUInt64 numChunksDiscovered;
AtomicUInt64 numChunksMatched;
AtomicUInt64 numDirsDiscovered;
AtomicUInt64 numDirsMatched;
bool isRunning; // true if an instance of this component is currently running
ChunkSyncCandidateStore* syncCandidates;
BuddyResyncerGatherSlaveWorkQueue* workQueue;
// nftw() callback needs access the slave threads
static Mutex staticGatherSlavesMutex;
static std::map<std::string, BuddyResyncerGatherSlave*> staticGatherSlaves;
virtual void run();
static int handleDiscoveredEntry(const char* path, const struct stat* statBuf,
int ftwEntryType, struct FTW* ftwBuf);
public:
// getters & setters
bool getIsRunning()
{
const std::lock_guard<Mutex> lock(statusMutex);
return this->isRunning;
}
void getCounters(uint64_t& outNumChunksDiscovered, uint64_t& outNumChunksMatched,
uint64_t& outNumDirsDiscovered, uint64_t& outNumDirsMatched)
{
outNumChunksDiscovered = numChunksDiscovered.read();
outNumChunksMatched = numChunksMatched.read();
outNumDirsDiscovered = numDirsDiscovered.read();
outNumDirsMatched = numDirsMatched.read();
}
void setOnlyTerminateIfIdle(bool value)
{
if (value)
onlyTerminateIfIdle.set(1);
else
onlyTerminateIfIdle.setZero();
}
bool getOnlyTerminateIfIdle()
{
if (onlyTerminateIfIdle.read() == 0)
return false;
else
return true;
}
private:
// getters & setters
void setIsRunning(bool isRunning)
{
const std::lock_guard<Mutex> lock(statusMutex);
this->isRunning = isRunning;
isRunningChangeCond.broadcast();
}
bool getSelfTerminateNotIdle()
{
return ( (getSelfTerminate() && (!getOnlyTerminateIfIdle())) );
}
};
typedef std::vector<BuddyResyncerGatherSlave*> BuddyResyncerGatherSlaveVec;
typedef BuddyResyncerGatherSlaveVec::iterator BuddyResyncerGatherSlaveVecIter;