beegfs/meta/source/storage/SyncedDiskAccessPath.h
2025-08-10 01:34:16 +02:00

134 lines
3.4 KiB
C++

#pragma once
#include <common/storage/Path.h>
#include <common/system/System.h>
#include <toolkit/StorageTkEx.h>
class SyncedDiskAccessPath : public Path
{
public:
SyncedDiskAccessPath() : Path()
{
initStorageVersion();
}
SyncedDiskAccessPath(const std::string& pathStr) : Path(pathStr)
{
initStorageVersion();
}
private:
uint64_t storageVersion; // zero is the invalid version!
uint64_t highVersion; // high part of storageVersion (high 42 bits)
unsigned int lowVersion; // low part of storageVersion (low 22 bits)
Mutex diskMutex;
// inliners
void initStorageVersion()
{
const uint64_t currentSecs = System::getCurrentTimeSecs();
const unsigned int minorVersion = 0;
setStorageVersion(currentSecs, minorVersion);
}
/**
* @param high currentTimeSecs (high 42 bits)
* @param low minorVersion (low 22 bits)
*/
void setStorageVersion(uint64_t highVersion, unsigned int lowVersion)
{
this->highVersion = highVersion;
this->lowVersion = lowVersion;
this->storageVersion = (highVersion << 22);
this->storageVersion |= ( (lowVersion << 10) >> 10);
}
public:
// inliners
/**
* note: remember to call storageUpdateEnd()
* @return storageVersion of the current update
*/
void storageUpdateBegin()
{
diskMutex.lock();
}
void storageUpdateEnd()
{
diskMutex.unlock();
}
/**
* Requires a call to storageUpdateBegin before! (and ...End() afterwards)
*/
uint64_t incStorageVersion()
{
// note: this relies on the fact that the currentTimeSecs never ever decrease!
uint64_t nextHighVersion;
unsigned int nextLowVersion;
// we try to avoid the getTime sys-call for some minor versions
if(lowVersion < 1024)
{
nextHighVersion = this->highVersion; // remains unchanged
nextLowVersion = this->lowVersion+1;
}
else
{
// in this case, we have to check that the timeSecs really have increased
// before we reset the minor version
nextHighVersion = System::getCurrentTimeSecs();
if(nextHighVersion == this->highVersion)
{ // no timeSecs increase yet => use the minor version
nextLowVersion = this->lowVersion+1;
}
else
{ // high version increased => we can reset the minor version
nextLowVersion = 0;
}
}
setStorageVersion(nextHighVersion, nextLowVersion);
return storageVersion;
}
bool createSubPathOnDisk(Path& subpath, bool excludeLastElement)
{
storageUpdateBegin();
Path completePath = *this / subpath;
bool createRes = StorageTk::createPathOnDisk(completePath, excludeLastElement);
storageUpdateEnd();
return createRes;
}
bool removeSubPathDirsFromDisk(Path& subpath, unsigned subKeepDepth)
{
storageUpdateBegin();
Path completePath = *this / subpath;
bool removeRes = StorageTk::removePathDirsFromDisk(
completePath, subKeepDepth + this->size() );
storageUpdateEnd();
return removeRes;
}
};