2025-08-10 01:34:16 +02:00

125 lines
3.3 KiB
C++

#pragma once
#include <storage/DirInode.h>
#include <common/storage/StorageErrors.h>
#include <common/net/message/storage/attribs/StatMsg.h>
#include <net/message/MirroredMessage.h>
// The "getattr" operation for linux-kernel filesystems
class StatMsgResponseState : public MirroredMessageResponseState
{
public:
StatMsgResponseState() : result(FhgfsOpsErr_INTERNAL), hasParentInfo(false) {}
explicit StatMsgResponseState(Deserializer& des)
{
serialize(this, des);
}
StatMsgResponseState(StatMsgResponseState&& other) :
result(other.result),
statData(other.statData),
parentNodeID(other.parentNodeID),
parentEntryID(other.parentEntryID),
hasParentInfo(other.hasParentInfo)
{}
void sendResponse(NetMessage::ResponseContext& ctx) override
{
StatRespMsg resp(result, statData);
if (this->hasParentInfo)
{
resp.addParentInfo(parentNodeID, parentEntryID);
}
ctx.sendResponse(resp);
}
// StatMsgEx is converted to mirrored message to leverage locking part of
// mirrored messages to prevent races with unlink, open etc.
//
// Always return false from changeObservableState() to prohibit forwarding
// to secondary. See MirroredMessage::finishOperation() for more details.
bool changesObservableState() const override
{
return false;
}
void setParentInfo(NumNodeID nodeID, const std::string& parentEntryID)
{
this->hasParentInfo = true;
this->parentNodeID = nodeID;
this->parentEntryID = parentEntryID;
}
void setStatData(const StatData& statData)
{
this->statData = statData;
}
void setStatResult(FhgfsOpsErr statRes) { this->result = statRes; }
protected:
uint32_t serializerTag() const override { return NETMSGTYPE_Stat; }
template<typename This, typename Ctx>
static void serialize(This obj, Ctx& ctx)
{
ctx
% obj->result
% obj->statData.serializeAs(StatDataFormat_NET);
if (obj->hasParentInfo)
{
ctx
% serdes::stringAlign4(obj->parentEntryID)
% obj->parentNodeID;
}
}
void serializeContents(Serializer& ser) const override
{
serialize(this, ser);
}
private:
FhgfsOpsErr result;
StatData statData;
NumNodeID parentNodeID;
std::string parentEntryID;
bool hasParentInfo;
};
class StatMsgEx: public MirroredMessage<StatMsg, FileIDLock>
{
public:
typedef StatMsgResponseState ResponseState;
virtual bool processIncoming(ResponseContext& ctx) override;
FileIDLock lock(EntryLockStore& store) override;
bool isMirrored() override
{
return getEntryInfo()->getIsBuddyMirrored();
}
private:
std::unique_ptr<MirroredMessageResponseState> executeLocally(ResponseContext& ctx,
bool isSecondary) override;
void forwardToSecondary(ResponseContext& ctx) override {}
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
{
return FhgfsOpsErr_SUCCESS;
}
const char* mirrorLogContext() const override { return "StatMsgEx/forward"; }
FhgfsOpsErr statRoot(StatData& outStatData);
};