New upstream version 8.1.0
This commit is contained in:
143
meta/source/net/message/storage/attribs/GetEntryInfoMsgEx.cpp
Normal file
143
meta/source/net/message/storage/attribs/GetEntryInfoMsgEx.cpp
Normal 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;
|
||||
}
|
||||
98
meta/source/net/message/storage/attribs/GetEntryInfoMsgEx.h
Normal file
98
meta/source/net/message/storage/attribs/GetEntryInfoMsgEx.h
Normal 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"; }
|
||||
};
|
||||
|
||||
66
meta/source/net/message/storage/attribs/GetXAttrMsgEx.cpp
Normal file
66
meta/source/net/message/storage/attribs/GetXAttrMsgEx.cpp
Normal 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));
|
||||
}
|
||||
74
meta/source/net/message/storage/attribs/GetXAttrMsgEx.h
Normal file
74
meta/source/net/message/storage/attribs/GetXAttrMsgEx.h
Normal 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"; }
|
||||
};
|
||||
|
||||
72
meta/source/net/message/storage/attribs/ListXAttrMsgEx.cpp
Normal file
72
meta/source/net/message/storage/attribs/ListXAttrMsgEx.cpp
Normal 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));
|
||||
}
|
||||
74
meta/source/net/message/storage/attribs/ListXAttrMsgEx.h
Normal file
74
meta/source/net/message/storage/attribs/ListXAttrMsgEx.h
Normal 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"; }
|
||||
};
|
||||
|
||||
104
meta/source/net/message/storage/attribs/RefreshEntryInfoMsg.cpp
Normal file
104
meta/source/net/message/storage/attribs/RefreshEntryInfoMsg.cpp
Normal 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);
|
||||
}
|
||||
@@ -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"; }
|
||||
};
|
||||
|
||||
|
||||
86
meta/source/net/message/storage/attribs/RemoveXAttrMsgEx.cpp
Normal file
86
meta/source/net/message/storage/attribs/RemoveXAttrMsgEx.cpp
Normal 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);
|
||||
}
|
||||
32
meta/source/net/message/storage/attribs/RemoveXAttrMsgEx.h
Normal file
32
meta/source/net/message/storage/attribs/RemoveXAttrMsgEx.h
Normal 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"; }
|
||||
};
|
||||
|
||||
|
||||
436
meta/source/net/message/storage/attribs/SetAttrMsgEx.cpp
Normal file
436
meta/source/net/message/storage/attribs/SetAttrMsgEx.cpp
Normal 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;
|
||||
}
|
||||
38
meta/source/net/message/storage/attribs/SetAttrMsgEx.h
Normal file
38
meta/source/net/message/storage/attribs/SetAttrMsgEx.h
Normal 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"; }
|
||||
};
|
||||
|
||||
|
||||
127
meta/source/net/message/storage/attribs/SetDirPatternMsgEx.cpp
Normal file
127
meta/source/net/message/storage/attribs/SetDirPatternMsgEx.cpp
Normal 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);
|
||||
}
|
||||
37
meta/source/net/message/storage/attribs/SetDirPatternMsgEx.h
Normal file
37
meta/source/net/message/storage/attribs/SetDirPatternMsgEx.h
Normal 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"; }
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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"; }
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
30
meta/source/net/message/storage/attribs/SetFileStateMsgEx.h
Normal file
30
meta/source/net/message/storage/attribs/SetFileStateMsgEx.h
Normal 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"; }
|
||||
};
|
||||
85
meta/source/net/message/storage/attribs/SetXAttrMsgEx.cpp
Normal file
85
meta/source/net/message/storage/attribs/SetXAttrMsgEx.cpp
Normal 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);
|
||||
}
|
||||
31
meta/source/net/message/storage/attribs/SetXAttrMsgEx.h
Normal file
31
meta/source/net/message/storage/attribs/SetXAttrMsgEx.h
Normal 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"; }
|
||||
};
|
||||
|
||||
87
meta/source/net/message/storage/attribs/StatMsgEx.cpp
Normal file
87
meta/source/net/message/storage/attribs/StatMsgEx.cpp
Normal 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;
|
||||
}
|
||||
|
||||
124
meta/source/net/message/storage/attribs/StatMsgEx.h
Normal file
124
meta/source/net/message/storage/attribs/StatMsgEx.h
Normal 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);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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"; }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user