New upstream version 8.1.0

This commit is contained in:
geos_one
2025-08-10 01:34:16 +02:00
commit c891bb7105
4398 changed files with 838833 additions and 0 deletions

View File

@@ -0,0 +1,143 @@
#include <common/net/message/storage/attribs/GetEntryInfoRespMsg.h>
#include <common/storage/striping/Raid0Pattern.h>
#include <common/toolkit/MessagingTk.h>
#include <program/Program.h>
#include <storage/MetaStore.h>
#include "GetEntryInfoMsgEx.h"
bool GetEntryInfoMsgEx::processIncoming(ResponseContext& ctx)
{
#ifdef BEEGFS_DEBUG
const char* logContext = "GetEntryInfoMsg incoming";
#endif // BEEGFS_DEBUG
LOG_DEBUG(logContext, Log_SPAM,
"ParentEntryID: " + this->getEntryInfo()->getParentEntryID() + "; "
"entryID: " + this->getEntryInfo()->getParentEntryID() );
return BaseType::processIncoming(ctx);
}
FileIDLock GetEntryInfoMsgEx::lock(EntryLockStore& store)
{
return {&store, getEntryInfo()->getEntryID(), false};
}
std::unique_ptr<MirroredMessageResponseState> GetEntryInfoMsgEx::executeLocally(ResponseContext& ctx,
bool isSecondary)
{
GetEntryInfoMsgResponseState resp;
EntryInfo* entryInfo = this->getEntryInfo();
StripePattern* pattern = NULL;
FhgfsOpsErr getInfoRes;
PathInfo pathInfo;
RemoteStorageTarget rstInfo;
uint32_t numSessionsRead = 0;
uint32_t numSessionsWrite = 0;
uint8_t dataState = 0;
if (entryInfo->getParentEntryID().empty())
{
// special case: get info for root directory
// no pathInfo here, as this is currently only used for fileInodes
getInfoRes = getRootInfo(&pattern, &rstInfo);
}
else
{
getInfoRes = getInfo(entryInfo, &pattern, &pathInfo, &rstInfo, numSessionsRead,
numSessionsWrite, dataState);
}
if (getInfoRes != FhgfsOpsErr_SUCCESS)
{ // error occurred => create a dummy pattern
UInt16Vector dummyStripeNodes;
pattern = new Raid0Pattern(1, dummyStripeNodes);
}
resp.setGetEntryInfoResult(getInfoRes);
resp.setStripePattern(pattern);
resp.setPathInfo(pathInfo);
resp.setRemoteStorageTarget(rstInfo);
resp.setNumSessionsRead(numSessionsRead);
resp.setNumSessionsWrite(numSessionsWrite);
resp.setFileDataState(dataState);
App* app = Program::getApp();
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), MetaOpCounter_GETENTRYINFO,
getMsgHeaderUserID() );
return boost::make_unique<ResponseState>(std::move(resp));
}
/**
* @param outPattern StripePattern clone (in case of success), that must be deleted by the caller
*/
FhgfsOpsErr GetEntryInfoMsgEx::getInfo(EntryInfo* entryInfo, StripePattern** outPattern,
PathInfo* outPathInfo, RemoteStorageTarget* outRstInfo, uint32_t& outNumReadSessions,
uint32_t& outNumWriteSessions, uint8_t& outDataState)
{
MetaStore* metaStore = Program::getApp()->getMetaStore();
if (entryInfo->getEntryType() == DirEntryType_DIRECTORY)
{ // entry is a directory
DirInode* dir = metaStore->referenceDir(entryInfo->getEntryID(),
entryInfo->getIsBuddyMirrored(), true);
if(dir)
{
*outPattern = dir->getStripePatternClone();
outRstInfo->set(dir->getRemoteStorageTargetInfo());
metaStore->releaseDir(entryInfo->getEntryID() );
return FhgfsOpsErr_SUCCESS;
}
}
else
{ // entry is a file
auto [fileInode, referenceRes] = metaStore->referenceFile(entryInfo);
if(fileInode)
{
*outPattern = fileInode->getStripePattern()->clone();
outRstInfo->set(fileInode->getRemoteStorageTargetInfo());
fileInode->getPathInfo(outPathInfo);
outNumReadSessions = fileInode->getNumSessionsRead();
outNumWriteSessions = fileInode->getNumSessionsWrite();
outDataState = fileInode->getFileState().getRawValue();
metaStore->releaseFile(entryInfo->getParentEntryID(), fileInode);
return referenceRes;
}
}
return FhgfsOpsErr_PATHNOTEXISTS;
}
/**
* @param outPattern StripePattern clone (in case of success), that must be deleted by the caller
*/
FhgfsOpsErr GetEntryInfoMsgEx::getRootInfo(StripePattern** outPattern, RemoteStorageTarget* outRstInfo)
{
App* app = Program::getApp();
MirrorBuddyGroupMapper* metaBuddyGroupMapper = app->getMetaBuddyGroupMapper();
DirInode* rootDir = app->getRootDir();
NumNodeID localNodeID = app->getLocalNodeNumID();
if (rootDir->getIsBuddyMirrored())
{
uint16_t buddyGroupID = metaBuddyGroupMapper->getBuddyGroupID(localNodeID.val());
if (buddyGroupID != rootDir->getOwnerNodeID().val() )
return FhgfsOpsErr_NOTOWNER;
}
else
if (localNodeID != rootDir->getOwnerNodeID() )
return FhgfsOpsErr_NOTOWNER;
*outPattern = rootDir->getStripePatternClone();
outRstInfo->set(rootDir->getRemoteStorageTargetInfo());
return FhgfsOpsErr_SUCCESS;
}

View File

@@ -0,0 +1,98 @@
#pragma once
#include <storage/DirInode.h>
#include <common/storage/StorageErrors.h>
#include <common/net/message/storage/attribs/GetEntryInfoMsg.h>
#include <common/net/message/storage/attribs/GetEntryInfoRespMsg.h>
#include <net/message/MirroredMessage.h>
class GetEntryInfoMsgResponseState : public MirroredMessageResponseState
{
public:
GetEntryInfoMsgResponseState() : result(FhgfsOpsErr_INTERNAL), mirrorNodeID(0)
{
}
GetEntryInfoMsgResponseState(GetEntryInfoMsgResponseState&& other) :
result(other.result),
mirrorNodeID(other.mirrorNodeID),
pattern(std::move(other.pattern)),
pathInfo(std::move(other.pathInfo)),
rst(std::move(other.rst)),
numSessionsRead(other.numSessionsRead),
numSessionsWrite(other.numSessionsWrite),
fileDataState(other.fileDataState)
{
}
void sendResponse(NetMessage::ResponseContext& ctx) override
{
GetEntryInfoRespMsg resp(result, pattern.get(), mirrorNodeID, &pathInfo, &rst,
numSessionsRead, numSessionsWrite, fileDataState);
ctx.sendResponse(resp);
}
// GetEntryInfoMsgEx is transformed into a mirrored message to utilize
// MirroredMessage::lock(), thereby preventing races with operations such
// as unlink. However, forwarding this message to the secondary is unnecessary.
// Overriding the changeObservableState() function to always return false ensures
// that this message never gets forwarded to seconadary.
bool changesObservableState() const override
{
return false;
}
void setGetEntryInfoResult(FhgfsOpsErr result) { this->result = result; }
void setMirrorNodeID(uint16_t nodeId) { this->mirrorNodeID = nodeId; }
void setStripePattern(StripePattern* pattern) { this->pattern.reset(pattern); }
void setPathInfo(PathInfo const& pathInfo) { this->pathInfo = pathInfo; }
void setRemoteStorageTarget(RemoteStorageTarget const& rstInfo) { rst = rstInfo; }
void setNumSessionsRead(uint32_t numReaders) { numSessionsRead = numReaders; }
void setNumSessionsWrite(uint32_t numWriters) { numSessionsWrite = numWriters; }
void setFileDataState(uint8_t dataState) { fileDataState = dataState; }
protected:
uint32_t serializerTag() const override { return NETMSGTYPE_GetEntryInfo; }
void serializeContents(Serializer& ser) const override {}
private:
FhgfsOpsErr result;
uint16_t mirrorNodeID; // metadata mirror node (0 means "none")
std::unique_ptr<StripePattern> pattern;
PathInfo pathInfo;
RemoteStorageTarget rst;
uint32_t numSessionsRead;
uint32_t numSessionsWrite;
uint8_t fileDataState;
};
class GetEntryInfoMsgEx : public MirroredMessage<GetEntryInfoMsg, FileIDLock>
{
public:
typedef GetEntryInfoMsgResponseState 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;
}
FhgfsOpsErr getInfo(EntryInfo* entryInfo, StripePattern** outPattern, PathInfo* outPathInfo,
RemoteStorageTarget* outRstInfo, uint32_t& outNumReadSessions, uint32_t& outNumWriteSessions,
uint8_t& outDataState);
FhgfsOpsErr getRootInfo(StripePattern** outPattern, RemoteStorageTarget* outRstInfo);
const char* mirrorLogContext() const override { return "GetEntryInfoMsgEx/forward"; }
};

View File

@@ -0,0 +1,66 @@
#include <program/Program.h>
#include <common/net/message/storage/attribs/GetXAttrRespMsg.h>
#include <net/msghelpers/MsgHelperXAttr.h>
#include "GetXAttrMsgEx.h"
bool GetXAttrMsgEx::processIncoming(ResponseContext& ctx)
{
const char* logContext = "GetXAttrMsg incoming";
LogContext(logContext).log(Log_DEBUG , "name: " + this->getName() + "; size: " +
StringTk::intToStr(this->getSize()) + ";");
return BaseType::processIncoming(ctx);
}
FileIDLock GetXAttrMsgEx::lock(EntryLockStore& store)
{
return {&store, getEntryInfo()->getEntryID(), false};
}
std::unique_ptr<MirroredMessageResponseState> GetXAttrMsgEx::executeLocally(ResponseContext& ctx,
bool isSecondary)
{
const char* logContext = "Get XAttr Msg";
GetXAttrMsgResponseState resp;
EntryInfo* entryInfo = this->getEntryInfo();
CharVector xAttrValue;
FhgfsOpsErr getXAttrRes;
ssize_t size = this->getSize();
const std::string& name = this->getName();
App* app = Program::getApp();
Config* config = app->getConfig();
if (!config->getStoreClientXAttrs())
{
LogContext(logContext).log(Log_ERR,
"Received a GetXAttrMsg, but client-side extended attributes are disabled in config.");
getXAttrRes = FhgfsOpsErr_NOTSUPP;
goto resp;
}
// Clamp buffer size to the maximum the NetMsg can handle, plus one byte in the (unlikely) case
// the on-disk metadata is larger than that.
if (size > MsgHelperXAttr::MAX_VALUE_SIZE)
size = MsgHelperXAttr::MAX_VALUE_SIZE + 1;
std::tie(getXAttrRes, xAttrValue, size) = MsgHelperXAttr::getxattr(entryInfo, name, size);
if (size >= MsgHelperXAttr::MAX_VALUE_SIZE + 1 && getXAttrRes == FhgfsOpsErr_SUCCESS)
{
// The xattr on disk is at least one byte too large. In this case, we have to return
// an internal error because it won't fit the net message.
xAttrValue.clear();
getXAttrRes = FhgfsOpsErr_INTERNAL;
}
resp:
resp.setGetXAttrValue(xAttrValue);
resp.setSize(size);
resp.setGetXAttrResult(getXAttrRes);
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), MetaOpCounter_GETXATTR,
getMsgHeaderUserID() );
return boost::make_unique<ResponseState>(std::move(resp));
}

View File

@@ -0,0 +1,74 @@
#pragma once
#include <common/net/message/storage/attribs/GetXAttrMsg.h>
#include <common/net/message/storage/attribs/GetXAttrRespMsg.h>
#include <net/message/MirroredMessage.h>
class GetXAttrMsgResponseState : public MirroredMessageResponseState
{
public:
GetXAttrMsgResponseState() : size(0), returnCode(FhgfsOpsErr_INTERNAL)
{
}
GetXAttrMsgResponseState(GetXAttrMsgResponseState&& other) :
value(std::move(other.value)),
size(other.size),
returnCode(other.returnCode)
{
}
void sendResponse(NetMessage::ResponseContext& ctx) override
{
GetXAttrRespMsg resp(value, size, returnCode);
ctx.sendResponse(resp);
}
// GetXAttrMsgEx is converted into a mirrored message to utilize MirroredMessage::lock(),
// thereby preventing races with operations like unlink. However, forwarding this message
// to the secondary is unnecessary. Overriding the changesObservableState() function to
// always return false ensures that this message is never forwarded unnecessarily.
bool changesObservableState() const override
{
return false;
}
void setGetXAttrValue(const CharVector& value) { this->value = value; }
void setSize(size_t size) { this->size = size; }
void setGetXAttrResult(FhgfsOpsErr result) { this->returnCode = result; }
protected:
uint32_t serializerTag() const override { return NETMSGTYPE_GetXAttr; }
void serializeContents(Serializer& ser) const override {}
private:
CharVector value;
size_t size;
FhgfsOpsErr returnCode;
};
class GetXAttrMsgEx : public MirroredMessage<GetXAttrMsg, FileIDLock>
{
public:
typedef GetXAttrMsgResponseState ResponseState;
virtual bool processIncoming(ResponseContext& ctx);
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 "GetXAttrMsgEx/forward"; }
};

View File

@@ -0,0 +1,72 @@
#include <program/Program.h>
#include <common/net/message/storage/attribs/ListXAttrRespMsg.h>
#include <net/msghelpers/MsgHelperXAttr.h>
#include "ListXAttrMsgEx.h"
bool ListXAttrMsgEx::processIncoming(ResponseContext& ctx)
{
#ifdef BEEGFS_DEBUG
const char* logContext = "ListXAttrMsg incoming";
#endif // BEEGFS_DEBUG
LOG_DEBUG(logContext, Log_DEBUG, "size: " + StringTk::intToStr(this->getSize()) + ";");
return BaseType::processIncoming(ctx);
}
FileIDLock ListXAttrMsgEx::lock(EntryLockStore& store)
{
return {&store, getEntryInfo()->getEntryID(), false};
}
std::unique_ptr<MirroredMessageResponseState> ListXAttrMsgEx::executeLocally(ResponseContext& ctx,
bool isSecondary)
{
const char* logContext = "List XAttr Msg";
ListXAttrMsgResponseState resp;
App* app = Program::getApp();
Config* config = app->getConfig();
EntryInfo* entryInfo = this->getEntryInfo();
size_t listSize = 0;
StringVector xAttrVec;
FhgfsOpsErr listXAttrRes;
if (!config->getStoreClientXAttrs() )
{
LogContext(logContext).log(Log_ERR,
"Received a ListXAttrMsg, but client-side extended attributes are disabled in config.");
listXAttrRes = FhgfsOpsErr_NOTSUPP;
goto resp;
}
std::tie(listXAttrRes, xAttrVec) = MsgHelperXAttr::listxattr(entryInfo);
for (StringVectorConstIter it = xAttrVec.begin(); it != xAttrVec.end(); ++it)
{
// Plus one byte to account for the '\0's separating the list elements in the buffer.
listSize += it->size() + 1;
}
// note: MsgHelperXAttr::MAX_SIZE is a ssize_t, which is always positive, so it will always fit
// into a size_t
if ((listSize >= (size_t)MsgHelperXAttr::MAX_VALUE_SIZE + 1)
&& (listXAttrRes == FhgfsOpsErr_SUCCESS))
{
// The xattr list on disk is at least one byte too large. In this case, we have to return
// an internal error because it won't fit the net message.
xAttrVec.clear();
listXAttrRes = FhgfsOpsErr_TOOBIG;
}
resp:
resp.setListXAttrValue(xAttrVec);
resp.setSize(listSize);
resp.setListXAttrResult(listXAttrRes);
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), MetaOpCounter_LISTXATTR,
getMsgHeaderUserID() );
return boost::make_unique<ResponseState>(std::move(resp));
}

View File

@@ -0,0 +1,74 @@
#pragma once
#include <common/net/message/storage/attribs/ListXAttrMsg.h>
#include <common/net/message/storage/attribs/ListXAttrRespMsg.h>
#include <net/message/MirroredMessage.h>
class ListXAttrMsgResponseState : public MirroredMessageResponseState
{
public:
ListXAttrMsgResponseState() : size(0), returnCode(FhgfsOpsErr_INTERNAL)
{
}
ListXAttrMsgResponseState(ListXAttrMsgResponseState&& other) :
value(std::move(other.value)),
size(other.size),
returnCode(other.returnCode)
{
}
void sendResponse(NetMessage::ResponseContext& ctx) override
{
ListXAttrRespMsg resp(value, size, returnCode);
ctx.sendResponse(resp);
}
// ListXAttrMsgEx is transformed into a mirrored message to leverage MirroredMessage::lock(),
// preventing races with operations such as unlink. However, forwarding this message to the
// secondary is unnecessary. Overriding the changesObservableState() function to always
// return false ensures that this message is never forwarded unnecessarily.
bool changesObservableState() const override
{
return false;
}
void setListXAttrValue(const StringVector& value) { this->value = value; }
void setSize(size_t size) { this->size = size; }
void setListXAttrResult(FhgfsOpsErr result) { this->returnCode = result; }
protected:
uint32_t serializerTag() const override { return NETMSGTYPE_ListXAttr; }
void serializeContents(Serializer& ser) const override {}
private:
StringVector value;
size_t size;
FhgfsOpsErr returnCode;
};
class ListXAttrMsgEx : public MirroredMessage<ListXAttrMsg, FileIDLock>
{
public:
typedef ListXAttrMsgResponseState 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 "ListXAttrMsgEx/forward"; }
};

View File

@@ -0,0 +1,104 @@
#include <common/net/message/storage/attribs/RefreshEntryInfoRespMsg.h>
#include <common/storage/striping/Raid0Pattern.h>
#include <common/toolkit/MessagingTk.h>
#include <net/msghelpers/MsgHelperStat.h>
#include <common/storage/EntryInfo.h>
#include <program/Program.h>
#include <session/EntryLock.h>
#include <storage/MetaStore.h>
#include "RefreshEntryInfoMsgEx.h"
bool RefreshEntryInfoMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("RefreshEntryInfoMsgEx incoming");
LOG_DEBUG_CONTEXT(log, Log_DEBUG, "Received a RefreshEntryInfoMsg from: " + ctx.peerName() );
LOG_DEBUG("RefreshEntryInfoMsgEx::processIncoming", Log_SPAM,
"ParentID: " + getEntryInfo()->getParentEntryID() + " EntryID: " +
getEntryInfo()->getEntryID() + " BuddyMirrored: " +
(getEntryInfo()->getIsBuddyMirrored() ? "Yes" : "No") + " Secondary: " +
(hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) ? "Yes" : "No"));
BaseType::processIncoming(ctx);
updateNodeOp(ctx, MetaOpCounter_REFRESHENTRYINFO);
return true;
}
std::tuple<FileIDLock, FileIDLock> RefreshEntryInfoMsgEx::lock(EntryLockStore& store)
{
if (DirEntryType_ISDIR(getEntryInfo()->getEntryType()))
return std::make_tuple(
FileIDLock(),
FileIDLock(&store, getEntryInfo()->getEntryID(), true));
else
return std::make_tuple(
FileIDLock(&store, getEntryInfo()->getEntryID(), true),
FileIDLock());
}
std::unique_ptr<MirroredMessageResponseState> RefreshEntryInfoMsgEx::executeLocally(
ResponseContext& ctx, bool isSecondary)
{
if (getEntryInfo()->getParentEntryID().empty()) // special case: get info for root directory
return boost::make_unique<ResponseState>(refreshInfoRoot());
else
return boost::make_unique<ResponseState>(refreshInfoRec());
}
/**
* @param outPattern StripePattern clone (in case of success), that must be deleted by the caller
*/
FhgfsOpsErr RefreshEntryInfoMsgEx::refreshInfoRec()
{
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryInfo* entryInfo = getEntryInfo();
DirInode* dir = metaStore->referenceDir(entryInfo->getEntryID(),
entryInfo->getIsBuddyMirrored(), true);
if(dir)
{ // entry is a directory
dir->refreshMetaInfo();
metaStore->releaseDir(entryInfo->getEntryID() );
return FhgfsOpsErr_SUCCESS;
}
// not a dir => try file
auto refreshRes = MsgHelperStat::refreshDynAttribs(entryInfo, true, getMsgHeaderUserID());
if (refreshRes == FhgfsOpsErr_SUCCESS && shouldFixTimestamps())
{
auto [file, referenceRes] = metaStore->referenceFile(getEntryInfo());
if (file)
fixInodeTimestamp(*file, fileTimestamps, getEntryInfo());
metaStore->releaseFile(getEntryInfo()->getParentEntryID(), file);
}
return refreshRes;
}
FhgfsOpsErr RefreshEntryInfoMsgEx::refreshInfoRoot()
{
App* app = Program::getApp();
DirInode* rootDir = app->getRootDir();
NumNodeID expectedOwnerNode = rootDir->getIsBuddyMirrored()
? NumNodeID(app->getMetaBuddyGroupMapper()->getLocalGroupID() )
: app->getLocalNode().getNumID();
if ( expectedOwnerNode != rootDir->getOwnerNodeID() )
return FhgfsOpsErr_NOTOWNER;
rootDir->refreshMetaInfo();
return FhgfsOpsErr_SUCCESS;
}
void RefreshEntryInfoMsgEx::forwardToSecondary(ResponseContext& ctx)
{
sendToSecondary(ctx, *this, NETMSGTYPE_RefreshEntryInfoResp);
}

View File

@@ -0,0 +1,40 @@
#pragma once
#include <storage/DirInode.h>
#include <common/storage/StorageErrors.h>
#include <common/net/message/storage/attribs/RefreshEntryInfoMsg.h>
#include <common/net/message/storage/attribs/RefreshEntryInfoRespMsg.h>
#include <net/message/MirroredMessage.h>
// Update entry info, called by fsck or by fhgfs-ctl
class RefreshEntryInfoMsgEx : public MirroredMessage<RefreshEntryInfoMsg,
std::tuple<FileIDLock, FileIDLock>>
{
public:
typedef ErrorCodeResponseState<RefreshEntryInfoRespMsg, NETMSGTYPE_RefreshEntryInfo>
ResponseState;
virtual bool processIncoming(ResponseContext& ctx) override;
std::tuple<FileIDLock, FileIDLock> lock(EntryLockStore& store) override;
bool isMirrored() override { return getEntryInfo()->getIsBuddyMirrored(); }
private:
std::unique_ptr<MirroredMessageResponseState> executeLocally(ResponseContext& ctx,
bool isSecondary) override;
FhgfsOpsErr refreshInfoRec();
FhgfsOpsErr refreshInfoRoot();
void forwardToSecondary(ResponseContext& ctx) override;
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
{
return (FhgfsOpsErr) static_cast<RefreshEntryInfoRespMsg&>(resp).getValue();
}
const char* mirrorLogContext() const override { return "RefreshEntryInfoMsgEx/forward"; }
};

View File

@@ -0,0 +1,86 @@
#include <program/Program.h>
#include <common/net/message/storage/attribs/RemoveXAttrRespMsg.h>
#include <net/msghelpers/MsgHelperXAttr.h>
#include <session/EntryLock.h>
#include "RemoveXAttrMsgEx.h"
bool RemoveXAttrMsgEx::processIncoming(ResponseContext& ctx)
{
#ifdef BEEGFS_DEBUG
const char* logContext = "RemoveXAttrMsg incoming";
EntryInfo* entryInfo = this->getEntryInfo();
const std::string& name = this->getName();
LOG_DEBUG(logContext, Log_DEBUG, "name: " + name + ";");
LOG_DEBUG("RemoveXAttrMsgEx::processIncoming", Log_DEBUG,
"ParentID: " + entryInfo->getParentEntryID() + " EntryID: " +
entryInfo->getEntryID() + " BuddyMirrored: " +
(entryInfo->getIsBuddyMirrored() ? "Yes" : "No") + " Secondary: " +
(hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) ? "Yes" : "No"));
#endif
BaseType::processIncoming(ctx);
updateNodeOp(ctx, MetaOpCounter_REMOVEXATTR);
return true;
}
std::tuple<FileIDLock, FileIDLock> RemoveXAttrMsgEx::lock(EntryLockStore& store)
{
if (getEntryInfo()->getEntryType() == DirEntryType_DIRECTORY)
return std::make_tuple(
FileIDLock(),
FileIDLock(&store, getEntryInfo()->getEntryID(), true));
else
return std::make_tuple(
FileIDLock(&store, getEntryInfo()->getEntryID(), true),
FileIDLock());
}
std::unique_ptr<MirroredMessageResponseState> RemoveXAttrMsgEx::executeLocally(ResponseContext& ctx,
bool isSecondary)
{
if (!Program::getApp()->getConfig()->getStoreClientXAttrs() ) // xattrs disabled in config
{
LOG(GENERAL, ERR, "Received a RemoveXAttrMsg, "
"but client-side extended attributes are disabled in config.");
return boost::make_unique<ResponseState>(FhgfsOpsErr_NOTSUPP);
}
auto rmRes = MsgHelperXAttr::removexattr(getEntryInfo(), getName());
if (rmRes == FhgfsOpsErr_SUCCESS && shouldFixTimestamps())
{
MetaStore* metaStore = Program::getApp()->getMetaStore();
if (DirEntryType_ISDIR(getEntryInfo()->getEntryType()))
{
auto dir = metaStore->referenceDir(getEntryInfo()->getEntryID(),
getEntryInfo()->getIsBuddyMirrored(), true);
if (dir)
{
fixInodeTimestamp(*dir, inodeTimestamps);
metaStore->releaseDir(dir->getID());
}
}
else
{
auto [file, referenceRes] = metaStore->referenceFile(getEntryInfo());
if (file)
{
fixInodeTimestamp(*file, inodeTimestamps, getEntryInfo());
metaStore->releaseFile(getEntryInfo()->getParentEntryID(), file);
}
}
}
return boost::make_unique<ResponseState>(rmRes);
}
void RemoveXAttrMsgEx::forwardToSecondary(ResponseContext& ctx)
{
sendToSecondary(ctx, *this, NETMSGTYPE_RemoveXAttrResp);
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include <common/net/message/storage/attribs/RemoveXAttrMsg.h>
#include <common/net/message/storage/attribs/RemoveXAttrRespMsg.h>
#include <net/message/MirroredMessage.h>
class RemoveXAttrMsgEx : public MirroredMessage<RemoveXAttrMsg, std::tuple<FileIDLock, FileIDLock>>
{
public:
typedef ErrorCodeResponseState<RemoveXAttrRespMsg, NETMSGTYPE_RemoveXAttr> ResponseState;
virtual bool processIncoming(ResponseContext& ctx) override;
std::tuple<FileIDLock, FileIDLock> lock(EntryLockStore& store) override;
std::unique_ptr<MirroredMessageResponseState> executeLocally(ResponseContext& ctx,
bool isSecondary) override;
bool isMirrored() override { return getEntryInfo()->getIsBuddyMirrored(); }
private:
void forwardToSecondary(ResponseContext& ctx) override;
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
{
return (FhgfsOpsErr) static_cast<RemoveXAttrRespMsg&>(resp).getValue();
}
const char* mirrorLogContext() const override { return "RemoveXAttrMsgEx/forward"; }
};

View File

@@ -0,0 +1,436 @@
#include <common/components/streamlistenerv2/IncomingPreprocessedMsgWork.h>
#include <common/net/message/control/GenericResponseMsg.h>
#include <common/net/message/storage/attribs/SetAttrRespMsg.h>
#include <common/net/message/storage/attribs/SetLocalAttrMsg.h>
#include <common/net/message/storage/attribs/SetLocalAttrRespMsg.h>
#include <common/toolkit/MessagingTk.h>
#include <components/FileEventLogger.h>
#include <components/worker/SetChunkFileAttribsWork.h>
#include <program/Program.h>
#include <session/EntryLock.h>
#include "SetAttrMsgEx.h"
#include <boost/lexical_cast.hpp>
bool SetAttrMsgEx::processIncoming(ResponseContext& ctx)
{
#ifdef BEEGFS_DEBUG
const char* logContext = "SetAttrMsg incoming";
#endif // BEEGFS_DEBUG
EntryInfo* entryInfo = getEntryInfo();
LOG_DEBUG(logContext, Log_DEBUG,
"BuddyMirrored: " + std::string(entryInfo->getIsBuddyMirrored() ? "Yes" : "No") +
" Secondary: " + std::string(hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond)
? "Yes" : "No") );
(void) entryInfo;
// update operation counters (here on top because we have an early sock release in this msg)
updateNodeOp(ctx, MetaOpCounter_SETATTR);
return BaseType::processIncoming(ctx);
}
std::tuple<FileIDLock, FileIDLock> SetAttrMsgEx::lock(EntryLockStore& store)
{
if (DirEntryType_ISDIR(getEntryInfo()->getEntryType()))
return std::make_tuple(
FileIDLock(),
FileIDLock(&store, getEntryInfo()->getEntryID(), true));
else
return std::make_tuple(
FileIDLock(&store, getEntryInfo()->getEntryID(), true),
FileIDLock());
}
std::unique_ptr<MirroredMessageResponseState> SetAttrMsgEx::executeLocally(ResponseContext& ctx,
bool isSecondary)
{
const char* logContext = "Set file attribs";
App* app = Program::getApp();
MetaStore* metaStore = app->getMetaStore();
Config* cfg = app->getConfig();
EntryInfo* entryInfo = getEntryInfo();
FhgfsOpsErr setAttrRes;
const bool forwardToStorage = !entryInfo->getIsBuddyMirrored()
|| !hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond);
bool responseSent = false;
if (entryInfo->getParentEntryID().empty() || DirEntryType_ISDIR(entryInfo->getEntryType()))
{
// special case: setAttr for root directory
if (entryInfo->getParentEntryID().empty())
setAttrRes = setAttrRoot();
else
setAttrRes = metaStore->setAttr(entryInfo, getValidAttribs(), getAttribs());
if (setAttrRes != FhgfsOpsErr_SUCCESS || !(shouldFixTimestamps() || getFileEvent()))
return boost::make_unique<ResponseState>(setAttrRes);
if (shouldFixTimestamps())
{
auto dir = metaStore->referenceDir(entryInfo->getEntryID(),
entryInfo->getIsBuddyMirrored(), true);
if (dir)
{
fixInodeTimestamp(*dir, inodeTimestamps);
metaStore->releaseDir(dir->getID());
}
}
if (!isSecondary && getFileEvent() && app->getFileEventLogger() && getFileEvent())
{
unsigned numHardlinks = 0;
auto dir = metaStore->referenceDir(entryInfo->getEntryID(),
entryInfo->getIsBuddyMirrored(), true);
if (likely(dir))
{
numHardlinks = dir->getNumHardlinks();
metaStore->releaseDir(dir->getID());
}
EventContext eventCtx = makeEventContext(entryInfo, entryInfo->getParentEntryID(),
getMsgHeaderUserID(), "", numHardlinks, isSecondary);
logEvent(app->getFileEventLogger(), *getFileEvent(), eventCtx);
}
return boost::make_unique<ResponseState>(setAttrRes);
}
// update nlink count if requested by caller
if (isMsgHeaderFeatureFlagSet(SETATTRMSG_FLAG_INCR_NLINKCNT) &&
isMsgHeaderFeatureFlagSet(SETATTRMSG_FLAG_DECR_NLINKCNT))
{
// error: both increase and decrease of nlink count was requested
return boost::make_unique<ResponseState>(FhgfsOpsErr_INTERNAL);
}
else if (isMsgHeaderFeatureFlagSet(SETATTRMSG_FLAG_INCR_NLINKCNT) ||
isMsgHeaderFeatureFlagSet(SETATTRMSG_FLAG_DECR_NLINKCNT))
{
int val = isMsgHeaderFeatureFlagSet(SETATTRMSG_FLAG_INCR_NLINKCNT) ? 1 : -1;
setAttrRes = metaStore->incDecLinkCount(entryInfo, val);
return boost::make_unique<ResponseState>(setAttrRes);
}
// we need to reference the inode first, as we want to use it several times
auto [inode, referenceRes] = metaStore->referenceFile(entryInfo);
if (!inode)
return boost::make_unique<ResponseState>(referenceRes);
// in the following we need to distinguish between several cases.
// 1. if times shall be updated we need to send the update to the storage servers first
// because, we need to rely on storage server's attrib version to prevent races with
// other messages that update the times (e.g. Close)
// 2. if times shall not be updated (must be chmod or chown then) and quota is enabled
// we first set the local attributes and then send the update to the storage server.
// if an early response optimization is set in this case we send the response between
// these two steps
// 3. no times update (i.e. chmod or chown) and quota is disabled => only update locally,
// as we don't have a reason to waste time with contacting the storage servers
bool timeUpdate =
getValidAttribs() & (SETATTR_CHANGE_MODIFICATIONTIME | SETATTR_CHANGE_LASTACCESSTIME);
// note: time update and mode/owner update can never be at the same time
if (timeUpdate && forwardToStorage)
{
// only relevant if message needs to be sent to the storage server. if not (e.g.
// because this is secondary of a buddy group, we can use the "default" case later
setAttrRes = setChunkFileAttribs(*inode, true);
if (setAttrRes == FhgfsOpsErr_SUCCESS)
setAttrRes = metaStore->setAttr(entryInfo, getValidAttribs(), getAttribs());
}
else if (isMsgHeaderFeatureFlagSet(SETATTRMSG_FLAG_USE_QUOTA) && forwardToStorage)
{
const UInt16Vector* targetIdVec = inode->getStripePattern()->getStripeTargetIDs();
ExceededQuotaStorePtr quotaExStore;
for (auto targetIter = targetIdVec->begin(); targetIter != targetIdVec->end(); targetIter++)
{
if (inode->getStripePattern()->getPatternType() == StripePatternType_BuddyMirror)
{
uint16_t primaryTargetID = app->getStorageBuddyGroupMapper()->getPrimaryTargetID(*targetIter);
quotaExStore = app->getExceededQuotaStores()->get(primaryTargetID);
}
else
{
// this is not very efficient at the moment, as we need to look at every quota exceeded
// store for every target in the stripe pattern; we need to do that because storage pools
// might change over time, i.e. the pool that is stored in the metadata doesn't always
// match the actual targets a file is stored on
quotaExStore = app->getExceededQuotaStores()->get(*targetIter);
}
// check if exceeded quotas exists, before doing a more expensive and explicit check
if (quotaExStore && quotaExStore->someQuotaExceeded())
{ // store for this target is present AND someQuotaExceeded() was true
QuotaExceededErrorType quotaExceeded = quotaExStore->isQuotaExceeded(
getAttribs()->userID, getAttribs()->groupID);
if (quotaExceeded != QuotaExceededErrorType_NOT_EXCEEDED)
{
LogContext(logContext).log(Log_NOTICE,
QuotaData::QuotaExceededErrorTypeToString(quotaExceeded) + " "
"UID: " + StringTk::uintToStr(getAttribs()->userID) + "; "
"GID: " + StringTk::uintToStr(getAttribs()->groupID));
setAttrRes = FhgfsOpsErr_DQUOT;
goto finish;
}
}
}
// only relevant if message needs to be sent to the storage server. if not (e.g.
// because this is secondary of a buddy group, we can use the "default" case later
setAttrRes = metaStore->setAttr(entryInfo, getValidAttribs(), getAttribs());
// allowed only if early chown respnse for quota is set
if (cfg->getQuotaEarlyChownResponse())
{
earlyComplete(ctx, ResponseState(setAttrRes));
responseSent = true;
}
if (setAttrRes == FhgfsOpsErr_SUCCESS)
setChunkFileAttribs(*inode, false);
}
else
{
setAttrRes = metaStore->setAttr(entryInfo, getValidAttribs(), getAttribs());
}
finish:
if (shouldFixTimestamps())
fixInodeTimestamp(*inode, inodeTimestamps, entryInfo);
if (!isSecondary && setAttrRes == FhgfsOpsErr_SUCCESS &&
app->getFileEventLogger() && getFileEvent())
{
EventContext eventCtx = makeEventContext(
entryInfo,
entryInfo->getParentEntryID(),
getMsgHeaderUserID(),
"",
inode->getNumHardlinks(),
isSecondary
);
logEvent(app->getFileEventLogger(), *getFileEvent(), eventCtx);
}
metaStore->releaseFile(entryInfo->getParentEntryID(), inode);
if (!responseSent)
return boost::make_unique<ResponseState>(setAttrRes);
else
return {};
}
void SetAttrMsgEx::forwardToSecondary(ResponseContext& ctx)
{
sendToSecondary(ctx, *this, NETMSGTYPE_SetAttrResp);
}
FhgfsOpsErr SetAttrMsgEx::setAttrRoot()
{
App* app = Program::getApp();
DirInode* rootDir = app->getRootDir();
NumNodeID expectedOwnerNode = rootDir->getIsBuddyMirrored()
? NumNodeID(app->getMetaBuddyGroupMapper()->getLocalGroupID() )
: app->getLocalNode().getNumID();
if ( expectedOwnerNode != rootDir->getOwnerNodeID() )
return FhgfsOpsErr_NOTOWNER;
if(!rootDir->setAttrData(getValidAttribs(), getAttribs() ) )
return FhgfsOpsErr_INTERNAL;
return FhgfsOpsErr_SUCCESS;
}
FhgfsOpsErr SetAttrMsgEx::setChunkFileAttribs(FileInode& file, bool requestDynamicAttribs)
{
StripePattern* pattern = file.getStripePattern();
if( (pattern->getStripeTargetIDs()->size() > 1) ||
(pattern->getPatternType() == StripePatternType_BuddyMirror) )
return setChunkFileAttribsParallel(file, requestDynamicAttribs);
else
return setChunkFileAttribsSequential(file, requestDynamicAttribs);
}
/**
* Note: This method does not work for mirrored files; use setChunkFileAttribsParallel() for those.
*/
FhgfsOpsErr SetAttrMsgEx::setChunkFileAttribsSequential(FileInode& inode,
bool requestDynamicAttribs)
{
const char* logContext = "Set chunk file attribs S";
StripePattern* pattern = inode.getStripePattern();
const UInt16Vector* targetIDs = pattern->getStripeTargetIDs();
TargetMapper* targetMapper = Program::getApp()->getTargetMapper();
TargetStateStore* targetStates = Program::getApp()->getTargetStateStore();
NodeStore* nodes = Program::getApp()->getStorageNodes();
FhgfsOpsErr retVal = FhgfsOpsErr_SUCCESS;
std::string fileID(inode.getEntryID());
PathInfo pathInfo;
inode.getPathInfo(&pathInfo);
// send request to each node and receive the response message
unsigned currentTargetIndex = 0;
for(UInt16VectorConstIter iter = targetIDs->begin();
iter != targetIDs->end();
iter++, currentTargetIndex++)
{
uint16_t targetID = *iter;
bool enableFileCreation = (currentTargetIndex == 0); // enable inode creation of first node
SetLocalAttrMsg setAttrMsg(fileID, targetID, &pathInfo, getValidAttribs(), getAttribs(),
enableFileCreation);
setAttrMsg.setMsgHeaderUserID(inode.getUserID());
if(isMsgHeaderFeatureFlagSet(SETATTRMSG_FLAG_USE_QUOTA))
setAttrMsg.addMsgHeaderFeatureFlag(SETLOCALATTRMSG_FLAG_USE_QUOTA);
RequestResponseArgs rrArgs(NULL, &setAttrMsg, NETMSGTYPE_SetLocalAttrResp);
RequestResponseTarget rrTarget(targetID, targetMapper, nodes);
rrTarget.setTargetStates(targetStates);
// send request to node and receive response
FhgfsOpsErr requestRes = MessagingTk::requestResponseTarget(&rrTarget, &rrArgs);
if(requestRes != FhgfsOpsErr_SUCCESS)
{ // communication error
LogContext(logContext).log(Log_WARNING,
"Communication with storage target failed: " + StringTk::uintToStr(targetID) + "; "
"fileID: " + inode.getEntryID() + "; "
"Error: " + boost::lexical_cast<std::string>(requestRes));
if(retVal == FhgfsOpsErr_SUCCESS)
retVal = requestRes;
continue;
}
// correct response type received
const auto setRespMsg = (const SetLocalAttrRespMsg*)rrArgs.outRespMsg.get();
FhgfsOpsErr setRespResult = setRespMsg->getResult();
if (setRespResult != FhgfsOpsErr_SUCCESS)
{ // error: local inode attribs not set
LogContext(logContext).log(Log_WARNING,
"Target failed to set attribs of chunk file: " + StringTk::uintToStr(targetID) + "; "
"fileID: " + inode.getEntryID());
if(retVal == FhgfsOpsErr_SUCCESS)
retVal = setRespResult;
continue;
}
// success: local inode attribs set
if (setRespMsg->isMsgHeaderFeatureFlagSet(SETLOCALATTRRESPMSG_FLAG_HAS_ATTRS))
{
DynamicFileAttribsVec dynAttribsVec(1);
setRespMsg->getDynamicAttribs(&(dynAttribsVec[0]));
inode.setDynAttribs(dynAttribsVec);
}
LOG_DEBUG(logContext, Log_DEBUG,
"Target has set attribs of chunk file: " + StringTk::uintToStr(targetID) + "; " +
"fileID: " + inode.getEntryID());
}
if(unlikely(retVal != FhgfsOpsErr_SUCCESS) )
LogContext(logContext).log(Log_WARNING,
"Problems occurred during setting of chunk file attribs. "
"fileID: " + inode.getEntryID());
return retVal;
}
FhgfsOpsErr SetAttrMsgEx::setChunkFileAttribsParallel(FileInode& inode, bool requestDynamicAttribs)
{
const char* logContext = "Set chunk file attribs";
App* app = Program::getApp();
MultiWorkQueue* slaveQ = app->getCommSlaveQueue();
StripePattern* pattern = inode.getStripePattern();
const UInt16Vector* targetIDs = pattern->getStripeTargetIDs();
size_t numTargetWorks = targetIDs->size();
FhgfsOpsErr retVal = FhgfsOpsErr_SUCCESS;
DynamicFileAttribsVec dynAttribsVec(numTargetWorks);
FhgfsOpsErrVec nodeResults(numTargetWorks);
SynchronizedCounter counter;
PathInfo pathInfo;
inode.getPathInfo(&pathInfo);
// generate work for storage targets...
for(size_t i=0; i < numTargetWorks; i++)
{
bool enableFileCreation = (i == 0); // enable inode creation on first target
SetChunkFileAttribsWork* work = NULL;
if (requestDynamicAttribs) // we are interested in the chunk's dynamic attributes, because we
{ // modify timestamps and this operation might race with others
work = new SetChunkFileAttribsWork(inode.getEntryID(), getValidAttribs(), getAttribs(),
enableFileCreation, pattern, (*targetIDs)[i], &pathInfo, &(dynAttribsVec[i]),
&(nodeResults[i]), &counter);
}
else
{
work = new SetChunkFileAttribsWork(inode.getEntryID(), getValidAttribs(), getAttribs(),
enableFileCreation, pattern, (*targetIDs)[i], &pathInfo, NULL, &(nodeResults[i]),
&counter);
}
work->setQuotaChown(isMsgHeaderFeatureFlagSet(SETATTRMSG_FLAG_USE_QUOTA) );
work->setMsgUserID(getMsgHeaderUserID() );
slaveQ->addDirectWork(work);
}
// wait for work completion...
counter.waitForCount(numTargetWorks);
// we set the dynamic attribs here, no matter if the remote operation suceeded or not. If it
// did not, storageVersion will be zero and the corresponding data will be ignored
// note: if the chunk's attributes were not requested from server at all, this is also OK here,
// because the storageVersion will be 0
inode.setDynAttribs(dynAttribsVec);
// check target results...
for(size_t i=0; i < numTargetWorks; i++)
{
if(unlikely(nodeResults[i] != FhgfsOpsErr_SUCCESS) )
{
LogContext(logContext).log(Log_WARNING,
"Problems occurred during setting of chunk file attribs. "
"fileID: " + inode.getEntryID());
retVal = nodeResults[i];
goto error_exit;
}
}
error_exit:
return retVal;
}

View File

@@ -0,0 +1,38 @@
#pragma once
#include <storage/MetaStore.h>
#include <common/storage/StorageErrors.h>
#include <common/net/message/storage/attribs/SetAttrMsg.h>
#include <common/net/message/storage/attribs/SetAttrRespMsg.h>
#include <net/message/MirroredMessage.h>
class SetAttrMsgEx : public MirroredMessage<SetAttrMsg, std::tuple<FileIDLock, FileIDLock>>
{
public:
typedef ErrorCodeResponseState<SetAttrRespMsg, NETMSGTYPE_SetAttr> ResponseState;
virtual bool processIncoming(ResponseContext& ctx) override;
std::tuple<FileIDLock, 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 setAttrRoot();
FhgfsOpsErr setChunkFileAttribs(FileInode& file, bool requestDynamicAttribs);
FhgfsOpsErr setChunkFileAttribsSequential(FileInode& inode, bool requestDynamicAttribs);
FhgfsOpsErr setChunkFileAttribsParallel(FileInode& inode, bool requestDynamicAttribs);
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
{
return (FhgfsOpsErr) static_cast<SetAttrRespMsg&>(resp).getValue();
}
const char* mirrorLogContext() const override { return "SetAttrMsgEx/forward"; }
};

View File

@@ -0,0 +1,127 @@
#include <common/net/message/storage/attribs/SetDirPatternRespMsg.h>
#include <common/storage/striping/Raid0Pattern.h>
#include <common/toolkit/MessagingTk.h>
#include <program/Program.h>
#include <session/EntryLock.h>
#include <storage/DirInode.h>
#include <storage/MetaStore.h>
#include "SetDirPatternMsgEx.h"
bool SetDirPatternMsgEx::processIncoming(ResponseContext& ctx)
{
EntryInfo* entryInfo = this->getEntryInfo();
LOG_DEBUG("SetDirPatternMsgEx::processIncoming", Log_SPAM,
"parentEntryID: " + entryInfo->getParentEntryID() + " EntryID: " +
entryInfo->getEntryID() + " BuddyMirrored: " +
(entryInfo->getIsBuddyMirrored() ? "Yes" : "No") + " Secondary: " +
(hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) ? "Yes" : "No"));
(void) entryInfo;
BaseType::processIncoming(ctx);
updateNodeOp(ctx, MetaOpCounter_SETDIRPATTERN);
return true;
}
std::unique_ptr<MirroredMessageResponseState> SetDirPatternMsgEx::executeLocally(
ResponseContext& ctx, bool isSecondary)
{
const char* logContext = "SetDirPatternMsg (set dir pattern)";
App* app = Program::getApp();
MetaStore* metaStore = app->getMetaStore();
EntryInfo* entryInfo = getEntryInfo();
StripePattern* pattern = &getPattern();
RemoteStorageTarget* rst = getRemoteStorageTarget();
FhgfsOpsErr retVal = FhgfsOpsErr_NOTADIR;
uint32_t actorUID = isMsgHeaderFeatureFlagSet(Flags::HAS_UID)
? getUID()
: 0;
if (actorUID != 0 && !app->getConfig()->getSysAllowUserSetPattern())
return boost::make_unique<ResponseState>(FhgfsOpsErr_PERM);
if (pattern->getChunkSize() < STRIPEPATTERN_MIN_CHUNKSIZE ||
!MathTk::isPowerOfTwo(pattern->getChunkSize()))
{ // check of stripe pattern details validity failed
LOG(GENERAL, ERR, "Received an invalid pattern chunksize",
("chunkSize", pattern->getChunkSize()));
return boost::make_unique<ResponseState>(FhgfsOpsErr_INTERNAL);
}
// verify owner of root dir
if (entryInfo->getEntryID() == META_ROOTDIR_ID_STR)
{
const bool isMirrored = entryInfo->getIsBuddyMirrored();
const NumNodeID rootOwnerID = app->getRootDir()->getOwnerNodeID();
const NumNodeID localGroupID(app->getMetaBuddyGroupMapper()->getLocalGroupID());
if ((!isMirrored && rootOwnerID != app->getLocalNodeNumID())
|| (isMirrored && rootOwnerID != localGroupID))
{
LogContext(logContext).log(Log_DEBUG, "This node does not own the root directory.");
return boost::make_unique<ResponseState>(FhgfsOpsErr_NOTOWNER);
}
}
DirInode* dir = metaStore->referenceDir(entryInfo->getEntryID(), entryInfo->getIsBuddyMirrored(),
true);
if (unlikely(!dir))
return boost::make_unique<ResponseState>(FhgfsOpsErr_PATHNOTEXISTS);
// entry is a directory
retVal = dir->setStripePattern(*pattern, actorUID);
if (retVal != FhgfsOpsErr_SUCCESS)
{
LogContext(logContext).logErr("Update of stripe pattern failed. "
"DirID: " + entryInfo->getEntryID());
metaStore->releaseDir(entryInfo->getEntryID());
return boost::make_unique<ResponseState>(retVal);
}
// Ignore if the request did not contain RST configuration:
if (!rst->hasInvalidVersion())
{
auto const& rstIDs = rst->getRstIdVector();
if (rstIDs.empty())
{
// Empty RST ID list indicates a request to clear/unset RSTs for this directory.
retVal = dir->clearRemoteStorageTarget();
if (retVal != FhgfsOpsErr_SUCCESS)
{
LogContext(logContext).logErr("Failed to clear RST info; "
"DirID: " + entryInfo->getEntryID());
metaStore->releaseDir(entryInfo->getEntryID());
return boost::make_unique<ResponseState>(retVal);
}
}
else
{
retVal = dir->setRemoteStorageTarget(*rst);
if (retVal != FhgfsOpsErr_SUCCESS)
{
LogContext(logContext).logErr("Storing remote storage targets failed. "
"DirID: " + entryInfo->getEntryID());
metaStore->releaseDir(entryInfo->getEntryID());
return boost::make_unique<ResponseState>(retVal);
}
}
}
metaStore->releaseDir(entryInfo->getEntryID());
return boost::make_unique<ResponseState>(retVal);
}
void SetDirPatternMsgEx::forwardToSecondary(ResponseContext& ctx)
{
sendToSecondary(ctx, *this, NETMSGTYPE_SetDirPatternResp);
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <common/storage/StorageErrors.h>
#include <common/net/message/storage/attribs/SetDirPatternMsg.h>
#include <common/net/message/storage/attribs/SetDirPatternRespMsg.h>
#include <net/message/MirroredMessage.h>
// set stripe pattern, called by fhgfs-ctl
class SetDirPatternMsgEx : public MirroredMessage<SetDirPatternMsg, FileIDLock>
{
public:
typedef ErrorCodeResponseState<SetDirPatternRespMsg, NETMSGTYPE_SetDirPattern> ResponseState;
virtual bool processIncoming(ResponseContext& ctx) override;
FileIDLock lock(EntryLockStore& store) override
{
return {&store, getEntryInfo()->getEntryID(), true};
}
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) static_cast<SetDirPatternRespMsg&>(resp).getValue();
}
const char* mirrorLogContext() const override { return "SetDirPatternMsgEx/forward"; }
};

View File

@@ -0,0 +1,73 @@
#include <session/EntryLock.h>
#include "SetFilePatternMsgEx.h"
bool SetFilePatternMsgEx::processIncoming(ResponseContext& ctx)
{
#ifdef BEEGFS_DEBUG
const char* logContext = "SetFilePatternMsgEx incoming";
EntryInfo* entryInfo = this->getEntryInfo();
LOG_DEBUG(logContext, 5, "EntryID: " + entryInfo->getEntryID() +
"; FileName: " + entryInfo->getFileName() +
"; EntryType: " + StringTk::intToStr(entryInfo->getEntryType()) +
"; isBuddyMirrored: " + StringTk::intToStr(entryInfo->getIsBuddyMirrored()) +
"; remoteStorageTarget (to be set) info: " + getRemoteStorageTarget()->toStr());
#endif
BaseType::processIncoming(ctx);
return true;
}
FileIDLock SetFilePatternMsgEx::lock(EntryLockStore& store)
{
return {&store, getEntryInfo()->getEntryID(), true};
}
std::unique_ptr<MirroredMessageResponseState> SetFilePatternMsgEx::executeLocally(
ResponseContext& ctx, bool isSecondary)
{
const char* logContext = "Set File Pattern";
FhgfsOpsErr res = FhgfsOpsErr_SUCCESS;
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryInfo* entryInfo = this->getEntryInfo();
RemoteStorageTarget* rst = this->getRemoteStorageTarget();
auto [inode, referenceRes] = metaStore->referenceFile(entryInfo);
if (unlikely(!inode))
return boost::make_unique<ResponseState>(referenceRes);
// Ignore if the request did not contain RST configuration:
if (!rst->hasInvalidVersion())
{
auto const& rstIDs = rst->getRstIdVector();
if (rstIDs.empty())
{
// Empty RST ID list indicates a request to clear/unset RSTs for this file.
res = inode->clearRemoteStorageTarget(entryInfo);
if (res != FhgfsOpsErr_SUCCESS)
{
LogContext(logContext).logErr("Failed to clear RST info; entryID: " +
entryInfo->getEntryID());
}
}
else
{
res = inode->setRemoteStorageTarget(entryInfo, *rst);
if (res != FhgfsOpsErr_SUCCESS)
{
LogContext(logContext).logErr("Setting RST info failed; entryID: " +
entryInfo->getEntryID());
}
}
}
metaStore->releaseFile(entryInfo->getParentEntryID(), inode);
return boost::make_unique<ResponseState>(res);
}
void SetFilePatternMsgEx::forwardToSecondary(ResponseContext& ctx)
{
sendToSecondary(ctx, *this, NETMSGTYPE_SetFilePatternResp);
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include <net/message/MirroredMessage.h>
#include <common/net/message/storage/attribs/SetFilePatternMsg.h>
#include <common/net/message/storage/attribs/SetFilePatternRespMsg.h>
class SetFilePatternMsgEx : public MirroredMessage<SetFilePatternMsg, FileIDLock>
{
public:
typedef ErrorCodeResponseState<SetFilePatternRespMsg, NETMSGTYPE_SetFilePattern> 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) static_cast<SetFilePatternRespMsg&>(resp).getValue();
}
const char* mirrorLogContext() const override { return "SetFilePatternMsgEx/forward"; }
};

View File

@@ -0,0 +1,48 @@
#include <session/EntryLock.h>
#include "SetFileStateMsgEx.h"
bool SetFileStateMsgEx::processIncoming(ResponseContext& ctx)
{
#ifdef BEEGFS_DEBUG
const char* logContext = "SetFileStateMsgEx incoming";
EntryInfo* entryInfo = this->getEntryInfo();
LOG_DEBUG(logContext, 5, "EntryID: " + entryInfo->getEntryID() +
"; FileName: " + entryInfo->getFileName() +
"; EntryType: " + StringTk::intToStr(entryInfo->getEntryType()) +
"; isBuddyMirrored: " + StringTk::intToStr(entryInfo->getIsBuddyMirrored()) +
"; file state (accessFlags+dataState): " + StringTk::intToStr(this->getFileState()));
#endif
BaseType::processIncoming(ctx);
return true;
}
FileIDLock SetFileStateMsgEx::lock(EntryLockStore& store)
{
return {&store, getEntryInfo()->getEntryID(), true};
}
std::unique_ptr<MirroredMessageResponseState> SetFileStateMsgEx::executeLocally(
ResponseContext& ctx, bool isSecondary)
{
const char* logContext = "Set File State";
FhgfsOpsErr res = FhgfsOpsErr_INTERNAL;
MetaStore* metaStore = Program::getApp()->getMetaStore();
res = metaStore->setFileState(getEntryInfo(), FileState(getFileState()));
if (res != FhgfsOpsErr_SUCCESS)
{
LogContext(logContext).log(Log_DEBUG, "Setting file state failed. EntryID: " +
getEntryInfo()->getEntryID());
return boost::make_unique<ResponseState>(res);
}
return boost::make_unique<ResponseState>(res);
}
void SetFileStateMsgEx::forwardToSecondary(ResponseContext& ctx)
{
sendToSecondary(ctx, *this, NETMSGTYPE_SetFileStateResp);
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include <net/message/MirroredMessage.h>
#include <common/net/message/storage/attribs/SetFileStateMsg.h>
#include <common/net/message/storage/attribs/SetFileStateRespMsg.h>
class SetFileStateMsgEx : public MirroredMessage<SetFileStateMsg, FileIDLock>
{
public:
typedef ErrorCodeResponseState<SetFileStateRespMsg, NETMSGTYPE_SetFileState> 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) static_cast<SetFileStateRespMsg&>(resp).getValue();
}
const char* mirrorLogContext() const override { return "SetFileStateMsgEx/forward"; }
};

View File

@@ -0,0 +1,85 @@
#include <program/Program.h>
#include <common/net/message/storage/attribs/SetXAttrRespMsg.h>
#include <net/msghelpers/MsgHelperXAttr.h>
#include <session/EntryLock.h>
#include "SetXAttrMsgEx.h"
std::tuple<FileIDLock, FileIDLock> SetXAttrMsgEx::lock(EntryLockStore& store)
{
if (getEntryInfo()->getEntryType() == DirEntryType_DIRECTORY)
return std::make_tuple(
FileIDLock(),
FileIDLock(&store, getEntryInfo()->getEntryID(), true));
else
return std::make_tuple(
FileIDLock(&store, getEntryInfo()->getEntryID(), true),
FileIDLock());
}
bool SetXAttrMsgEx::processIncoming(ResponseContext& ctx)
{
#ifdef BEEGFS_DEBUG
const char* logContext = "SetXAttrMsg incoming";
EntryInfo* entryInfo = this->getEntryInfo();
const std::string& name = this->getName();
LOG_DEBUG(logContext, Log_DEBUG, "name: " + name + ";");
LOG_DEBUG("SetXAttrMsgEx::processIncoming", Log_DEBUG,
"ParentID: " + entryInfo->getParentEntryID() + " EntryID: " +
entryInfo->getEntryID() + " BuddyMirrored: " +
(entryInfo->getIsBuddyMirrored() ? "Yes" : "No") + " Secondary: " +
(hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) ? "Yes" : "No"));
#endif
BaseType::processIncoming(ctx);
updateNodeOp(ctx, MetaOpCounter_SETXATTR);
return true;
}
std::unique_ptr<MirroredMessageResponseState> SetXAttrMsgEx::executeLocally(ResponseContext& ctx,
bool isSecondary)
{
if (!Program::getApp()->getConfig()->getStoreClientXAttrs())
{
LOG(GENERAL, ERR,
"Received a SetXAttrMsg, but client-side extended attributes are disabled in config.");
return boost::make_unique<ResponseState>(FhgfsOpsErr_NOTSUPP);
}
auto setXAttrRes = MsgHelperXAttr::setxattr(getEntryInfo(), getName(), getValue(), getFlags());
if (setXAttrRes == FhgfsOpsErr_SUCCESS && shouldFixTimestamps())
{
MetaStore* metaStore = Program::getApp()->getMetaStore();
if (DirEntryType_ISDIR(getEntryInfo()->getEntryType()))
{
auto dir = metaStore->referenceDir(getEntryInfo()->getEntryID(),
getEntryInfo()->getIsBuddyMirrored(), true);
if (dir)
{
fixInodeTimestamp(*dir, inodeTimestamps);
metaStore->releaseDir(dir->getID());
}
}
else
{
auto [file, referenceRes] = metaStore->referenceFile(getEntryInfo());
if (file)
{
fixInodeTimestamp(*file, inodeTimestamps, getEntryInfo());
metaStore->releaseFile(getEntryInfo()->getParentEntryID(), file);
}
}
}
return boost::make_unique<ResponseState>(setXAttrRes);
}
void SetXAttrMsgEx::forwardToSecondary(ResponseContext& ctx)
{
sendToSecondary(ctx, *this, NETMSGTYPE_SetXAttrResp);
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include <common/net/message/storage/attribs/SetXAttrMsg.h>
#include <common/net/message/storage/attribs/SetXAttrRespMsg.h>
#include <net/message/MirroredMessage.h>
class SetXAttrMsgEx : public MirroredMessage<SetXAttrMsg, std::tuple<FileIDLock, FileIDLock>>
{
public:
typedef ErrorCodeResponseState<SetXAttrRespMsg, NETMSGTYPE_SetXAttr> ResponseState;
virtual bool processIncoming(ResponseContext& ctx) override;
std::tuple<FileIDLock, FileIDLock> lock(EntryLockStore& store) override;
bool isMirrored() override { return getEntryInfo()->getIsBuddyMirrored(); }
std::unique_ptr<MirroredMessageResponseState> executeLocally(ResponseContext& ctx,
bool isSecondary) override;
private:
void forwardToSecondary(ResponseContext& ctx) override;
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
{
return (FhgfsOpsErr) static_cast<SetXAttrRespMsg&>(resp).getValue();
}
const char* mirrorLogContext() const override { return "SetXAttrMsgEx/forward"; }
};

View File

@@ -0,0 +1,87 @@
#include <program/Program.h>
#include <common/net/message/storage/attribs/StatRespMsg.h>
#include <common/toolkit/MessagingTk.h>
#include <net/msghelpers/MsgHelperStat.h>
#include "StatMsgEx.h"
bool StatMsgEx::processIncoming(ResponseContext& ctx)
{
#ifdef BEEGFS_DEBUG
const char* logContext = "StatMsgEx incoming";
#endif // BEEGFS_DEBUG
LOG_DEBUG(logContext, 5, "ParentID: " + getEntryInfo()->getParentEntryID() +
"; EntryID: " + getEntryInfo()->getEntryID() +
"; EntryType: " + StringTk::intToStr(getEntryInfo()->getEntryType() ) +
"; isBuddyMirrored: " + StringTk::intToStr(getEntryInfo()->getIsBuddyMirrored()));
return BaseType::processIncoming(ctx);
}
FileIDLock StatMsgEx::lock(EntryLockStore& store)
{
return {&store, getEntryInfo()->getEntryID(), false};
}
std::unique_ptr<MirroredMessageResponseState> StatMsgEx::executeLocally(ResponseContext& ctx,
bool isSecondary)
{
StatMsgResponseState resp;
StatData statData;
FhgfsOpsErr statRes;
NumNodeID parentNodeID;
std::string parentEntryID;
EntryInfo* entryInfo = this->getEntryInfo();
if (entryInfo->getParentEntryID().empty() || (entryInfo->getEntryID() == META_ROOTDIR_ID_STR) )
{ // special case: stat for root directory
statRes = statRoot(statData);
}
else
{
statRes = MsgHelperStat::stat(entryInfo, true, getMsgHeaderUserID(), statData, &parentNodeID,
&parentEntryID);
}
LOG_DBG(GENERAL, DEBUG, "", statRes);
resp.setStatResult(statRes);
resp.setStatData(statData);
if (isMsgHeaderFeatureFlagSet(STATMSG_FLAG_GET_PARENTINFO) && parentNodeID)
resp.setParentInfo(parentNodeID, parentEntryID);
updateNodeOp(ctx, MetaOpCounter_STAT);
return boost::make_unique<ResponseState>(std::move(resp));
}
FhgfsOpsErr StatMsgEx::statRoot(StatData& outStatData)
{
App* app = Program::getApp();
Node& localNode = app->getLocalNode();
DirInode* rootDir = app->getRootDir();
NumNodeID expectedOwnerID;
// if root is buddy mirrored compare ownership to buddy group id, otherwise to node id itself
if ( rootDir->getIsBuddyMirrored() )
expectedOwnerID =
NumNodeID(app->getMetaBuddyGroupMapper()->getBuddyGroupID(localNode.getNumID().val() ) );
else
expectedOwnerID = localNode.getNumID();
if(expectedOwnerID != rootDir->getOwnerNodeID() )
{
return FhgfsOpsErr_NOTOWNER;
}
rootDir->getStatData(outStatData);
return FhgfsOpsErr_SUCCESS;
}

View File

@@ -0,0 +1,124 @@
#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);
};

View File

@@ -0,0 +1,64 @@
#include <program/Program.h>
#include <common/net/message/storage/attribs/UpdateDirParentRespMsg.h>
#include <common/net/message/storage/attribs/SetLocalAttrMsg.h>
#include <common/net/message/storage/attribs/SetLocalAttrRespMsg.h>
#include <common/toolkit/MessagingTk.h>
#include <components/worker/SetChunkFileAttribsWork.h>
#include <session/EntryLock.h>
#include "UpdateDirParentMsgEx.h"
bool UpdateDirParentMsgEx::processIncoming(ResponseContext& ctx)
{
EntryInfo* entryInfo = getEntryInfo();
NumNodeID parentNodeID = getParentNodeID();
LOG_DEBUG("UpdateDirParentMsgEx::processIncoming", Log_DEBUG,
"ParentID: " + entryInfo->getParentEntryID() + " EntryID: " +
entryInfo->getEntryID() + " parentNodeID: " + parentNodeID.str() + " BuddyMirrored: " +
(entryInfo->getIsBuddyMirrored() ? "Yes" : "No") + " Secondary: " +
(hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) ? "Yes" : "No"));
(void) entryInfo;
(void) parentNodeID;
rctx = &ctx;
BaseType::processIncoming(ctx);
// update operation counters
updateNodeOp(ctx, MetaOpCounter_UPDATEDIRPARENT);
return true;
}
FileIDLock UpdateDirParentMsgEx::lock(EntryLockStore& store)
{
if (rctx->isLocallyGenerated())
return {};
return {&store, getEntryInfo()->getEntryID(), true};
}
std::unique_ptr<MirroredMessageResponseState> UpdateDirParentMsgEx::executeLocally(
ResponseContext& ctx, bool isSecondary)
{
auto setRes = Program::getApp()->getMetaStore()->setDirParent(getEntryInfo(), getParentNodeID());
if (setRes == FhgfsOpsErr_SUCCESS && shouldFixTimestamps())
{
auto dir = Program::getApp()->getMetaStore()->referenceDir(getEntryInfo()->getEntryID(),
true, true);
if (dir)
{
fixInodeTimestamp(*dir, dirTimestamps);
Program::getApp()->getMetaStore()->releaseDir(dir->getID());
}
}
return boost::make_unique<ResponseState>(setRes);
}
void UpdateDirParentMsgEx::forwardToSecondary(ResponseContext& ctx)
{
sendToSecondary(ctx, *this, NETMSGTYPE_UpdateDirParentResp);
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <storage/MetaStore.h>
#include <common/storage/StorageErrors.h>
#include <common/net/message/storage/attribs/UpdateDirParentMsg.h>
#include <common/net/message/storage/attribs/UpdateDirParentRespMsg.h>
#include <net/message/MirroredMessage.h>
class UpdateDirParentMsgEx : public MirroredMessage<UpdateDirParentMsg, FileIDLock>
{
public:
typedef ErrorCodeResponseState<UpdateDirParentRespMsg, NETMSGTYPE_UpdateDirParent>
ResponseState;
virtual bool processIncoming(ResponseContext& ctx) override;
std::unique_ptr<MirroredMessageResponseState> executeLocally(ResponseContext& ctx,
bool isSecondary) override;
FileIDLock lock(EntryLockStore& store) override;
bool isMirrored() override { return getEntryInfo()->getIsBuddyMirrored(); }
private:
ResponseContext* rctx;
void forwardToSecondary(ResponseContext& ctx) override;
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
{
return (FhgfsOpsErr) static_cast<UpdateDirParentRespMsg&>(resp).getValue();
}
const char* mirrorLogContext() const override { return "UpdateDirParentMsgEx/forward"; }
};