New upstream version 8.1.0
This commit is contained in:
445
meta/source/net/message/MirroredMessage.h
Normal file
445
meta/source/net/message/MirroredMessage.h
Normal file
@@ -0,0 +1,445 @@
|
||||
#pragma once
|
||||
|
||||
#include <app/App.h>
|
||||
#include <common/app/log/Logger.h>
|
||||
#include <common/components/streamlistenerv2/IncomingPreprocessedMsgWork.h>
|
||||
#include <common/net/message/session/AckNotifyMsg.h>
|
||||
#include <common/net/message/session/AckNotifyRespMsg.h>
|
||||
#include <common/net/message/NetMessage.h>
|
||||
#include <common/storage/StorageErrors.h>
|
||||
#include <common/toolkit/DebugVariable.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <program/Program.h>
|
||||
#include <session/MirrorMessageResponseState.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
template<typename BaseT, typename LockStateT>
|
||||
class MirroredMessage : public BaseT
|
||||
{
|
||||
protected:
|
||||
typedef MirroredMessage BaseType;
|
||||
|
||||
BuddyResyncJob* resyncJob;
|
||||
LockStateT lockState;
|
||||
|
||||
MirroredMessage():
|
||||
resyncJob(nullptr)
|
||||
{}
|
||||
|
||||
virtual FhgfsOpsErr processSecondaryResponse(NetMessage& resp) = 0;
|
||||
|
||||
virtual const char* mirrorLogContext() const = 0;
|
||||
|
||||
virtual std::unique_ptr<MirroredMessageResponseState> executeLocally(
|
||||
NetMessage::ResponseContext& ctx, bool isSecondary) = 0;
|
||||
|
||||
virtual bool isMirrored() = 0;
|
||||
|
||||
// IMPORTANT NOTE ON LOCKING ORDER:
|
||||
// * always take locks the order
|
||||
// - HashDirLock
|
||||
// - DirIDLock
|
||||
// - ParentNameLock
|
||||
// - FileIDLock
|
||||
// * always take locks of each type with the order induced by:
|
||||
// - HashDirLock: id
|
||||
// - DirIDLock: (id, forWrite)
|
||||
// - ParentNameLock: (parentID, name)
|
||||
// - FileIDLock: id
|
||||
//
|
||||
// not doing this may result in deadlocks.
|
||||
virtual LockStateT lock(EntryLockStore& store) = 0;
|
||||
|
||||
virtual void forwardToSecondary(NetMessage::ResponseContext& ctx) = 0;
|
||||
|
||||
virtual bool processIncoming(NetMessage::ResponseContext& ctx)
|
||||
{
|
||||
Session* session = nullptr;
|
||||
bool isNewState = true;
|
||||
|
||||
if (isMirrored() && !this->hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond))
|
||||
{
|
||||
if (Program::getApp()->getInternodeSyncer()->getResyncInProgress())
|
||||
resyncJob = Program::getApp()->getBuddyResyncer()->getResyncJob();
|
||||
|
||||
lockState = lock(*Program::getApp()->getMirroredSessions()->getEntryLockStore());
|
||||
}
|
||||
|
||||
// make sure that the thread change set is *always* cleared when we leave this method.
|
||||
struct _ClearChangeSet {
|
||||
~_ClearChangeSet()
|
||||
{
|
||||
if (BuddyResyncer::getSyncChangeset())
|
||||
{
|
||||
LOG(MIRRORING, WARNING, "Abandoning sync changeset");
|
||||
BuddyResyncer::abandonSyncChangeset();
|
||||
}
|
||||
}
|
||||
} _clearChangeSet;
|
||||
(void) _clearChangeSet;
|
||||
|
||||
mirrorState.reset();
|
||||
if (isMirrored())
|
||||
{
|
||||
const auto nodeID = this->getRequestorID(ctx).second;
|
||||
session = Program::getApp()->getMirroredSessions()->referenceSession(nodeID, true);
|
||||
}
|
||||
|
||||
if (isMirrored() && this->hasFlag(NetMessageHeader::Flag_HasSequenceNumber))
|
||||
{
|
||||
// special case: client has not been told where to start its sequence. in this case,
|
||||
// we want to answer with only the new seqNoBase for the client, and do NO processing.
|
||||
if (this->getSequenceNumber() == 0)
|
||||
{
|
||||
GenericResponseMsg response(GenericRespMsgCode_NEWSEQNOBASE, "New seqNoBase");
|
||||
|
||||
response.addFlag(NetMessageHeader::Flag_HasSequenceNumber);
|
||||
response.setSequenceNumber(session->getSeqNoBase());
|
||||
ctx.sendResponse(response);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// a note on locking of mirrorState. since clients process each request in only one
|
||||
// thread, per client we can have only one request for a given sequence number at any
|
||||
// given time. retries may reuse the same sequence number, and they may be processed in
|
||||
// a different thread on the server, but no two threads process the same sequence number
|
||||
// from the same client at the same time. thus, no locking for the actual structure is
|
||||
// needed, but extra memory barriers to ensure propagation of results between threads
|
||||
// are necessary.
|
||||
__sync_synchronize();
|
||||
if (this->hasFlag(NetMessageHeader::Flag_IsSelectiveAck))
|
||||
std::tie(mirrorState, isNewState) = session->acquireMirrorStateSlotSelective(
|
||||
this->getSequenceNumberDone(),
|
||||
this->getSequenceNumber());
|
||||
else
|
||||
std::tie(mirrorState, isNewState) = session->acquireMirrorStateSlot(
|
||||
this->getSequenceNumberDone(),
|
||||
this->getSequenceNumber());
|
||||
}
|
||||
|
||||
if (!isNewState)
|
||||
{
|
||||
if (mirrorState->response)
|
||||
mirrorState->response->sendResponse(ctx);
|
||||
else
|
||||
ctx.sendResponse(
|
||||
GenericResponseMsg(
|
||||
GenericRespMsgCode_TRYAGAIN,
|
||||
"Request for same sequence number is currently in progress"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resyncJob && resyncJob->isRunning())
|
||||
{
|
||||
BuddyResyncer::registerSyncChangeset();
|
||||
resyncJob->registerOps();
|
||||
}
|
||||
|
||||
auto responseState = executeLocally(ctx,
|
||||
isMirrored() && this->hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond));
|
||||
|
||||
// responseState may ne null if the message has called earlyComplete(). do not finish
|
||||
// the operation twice in this case.
|
||||
if (responseState)
|
||||
finishOperation(ctx, std::move(responseState));
|
||||
}
|
||||
|
||||
exit:
|
||||
if (session)
|
||||
Program::getApp()->getMirroredSessions()->releaseSession(session);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename ResponseT>
|
||||
void earlyComplete(NetMessage::ResponseContext& ctx, ResponseT&& state)
|
||||
{
|
||||
finishOperation(ctx, boost::make_unique<ResponseT>(std::move(state)));
|
||||
|
||||
Socket* sock = ctx.getSocket();
|
||||
IncomingPreprocessedMsgWork::releaseSocket(Program::getApp(), &sock, this);
|
||||
}
|
||||
|
||||
void buddyResyncNotify(NetMessage::ResponseContext& ctx, bool stateChanged)
|
||||
{
|
||||
// pairs with the memory barrier before acquireMirrorStateSlot
|
||||
__sync_synchronize();
|
||||
|
||||
if (BuddyResyncer::getSyncChangeset())
|
||||
{
|
||||
if (isMirrored() &&
|
||||
!this->hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) &&
|
||||
stateChanged)
|
||||
BuddyResyncer::commitThreadChangeSet();
|
||||
else
|
||||
BuddyResyncer::abandonSyncChangeset();
|
||||
}
|
||||
}
|
||||
|
||||
void finishOperation(NetMessage::ResponseContext& ctx,
|
||||
std::unique_ptr<MirroredMessageResponseState> state)
|
||||
{
|
||||
auto* responsePtr = state.get();
|
||||
|
||||
if (isMirrored() &&
|
||||
!this->hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) &&
|
||||
state)
|
||||
{
|
||||
if (state->changesObservableState())
|
||||
forwardToSecondary(ctx);
|
||||
else
|
||||
notifySecondaryOfACK(ctx);
|
||||
}
|
||||
|
||||
if (mirrorState)
|
||||
mirrorState->response = std::move(state);
|
||||
|
||||
// pairs with the memory barrier before acquireMirrorStateSlot
|
||||
__sync_synchronize();
|
||||
|
||||
if (BuddyResyncer::getSyncChangeset())
|
||||
{
|
||||
resyncJob = Program::getApp()->getBuddyResyncer()->getResyncJob();
|
||||
if (isMirrored() &&
|
||||
!this->hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) &&
|
||||
responsePtr &&
|
||||
responsePtr->changesObservableState())
|
||||
BuddyResyncer::commitThreadChangeSet();
|
||||
else
|
||||
BuddyResyncer::abandonSyncChangeset();
|
||||
|
||||
resyncJob->unregisterOps();
|
||||
}
|
||||
|
||||
if (responsePtr)
|
||||
responsePtr->sendResponse(ctx);
|
||||
|
||||
lockState = {};
|
||||
}
|
||||
|
||||
void notifySecondaryOfACK(NetMessage::ResponseContext& ctx)
|
||||
{
|
||||
AckNotifiyMsg msg;
|
||||
// if the secondary does not respond with SUCCESS, it will automatically be set to
|
||||
// needs-resync. eventually, resync will clear the secondary sessions entirely, which will
|
||||
// also flush the sequence number store.
|
||||
sendToSecondary(ctx, msg, NETMSGTYPE_AckNotifyResp);
|
||||
}
|
||||
|
||||
virtual void prepareMirrorRequestArgs(RequestResponseArgs& args)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void sendToSecondary(NetMessage::ResponseContext& ctx, MirroredMessageBase<T>& message,
|
||||
unsigned respType, FhgfsOpsErr expectedResult = FhgfsOpsErr_SUCCESS)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
NodeStoreServers* metaNodes = app->getMetaNodes();
|
||||
MirrorBuddyGroupMapper* buddyGroups = app->getMetaBuddyGroupMapper();
|
||||
|
||||
DEBUG_ENV_VAR(unsigned, FORWARD_DELAY, 0, "BEEGFS_FORWARD_DELAY_SECS");
|
||||
|
||||
if (FORWARD_DELAY)
|
||||
sleep(FORWARD_DELAY);
|
||||
|
||||
// if a resync is currently running, abort right here, immediatly. we do not need to know
|
||||
// the exact state of the buddy: a resync is running. it's bad.
|
||||
if (app->getInternodeSyncer()->getResyncInProgress())
|
||||
return;
|
||||
|
||||
// check whether the secondary is viable at all: if it is not online and good,
|
||||
// communicating will not do any good. even online/needs-resync must be skipped, because
|
||||
// the resyncer must be the only entitity that changes the secondary as long as it is not
|
||||
// good yet.
|
||||
{
|
||||
CombinedTargetState secondaryState;
|
||||
NumNodeID secondaryID(buddyGroups->getSecondaryTargetID(
|
||||
buddyGroups->getLocalGroupID()));
|
||||
|
||||
bool getStateRes = app->getMetaStateStore()->getState(secondaryID.val(),
|
||||
secondaryState);
|
||||
|
||||
// if the secondary is anything except online/good, set it to needs-resync immediately.
|
||||
// whenever we pass this point, the secondary will have missed *something* of
|
||||
// importance, so anything except online/good must be set to needs-resync right here.
|
||||
if (!getStateRes
|
||||
|| secondaryState.reachabilityState != TargetReachabilityState_ONLINE
|
||||
|| secondaryState.consistencyState != TargetConsistencyState_GOOD)
|
||||
{
|
||||
auto* const resyncer = app->getBuddyResyncer();
|
||||
auto* const job = resyncer->getResyncJob();
|
||||
|
||||
// if we have no job or a running job, we must start a resync soon. if we have a
|
||||
// job that has finished successfully, the management server may not have noticed
|
||||
// that the secondary is completely resynced, so our buddys state may well not be
|
||||
// GOOD even though we have resynced completely. we may assume that a successful
|
||||
// resync implies that the buddy is good, even if the management server thinks it
|
||||
// isn't.
|
||||
if (!job ||
|
||||
(!job->isRunning() && job->getState() != BuddyResyncJobState_SUCCESS))
|
||||
{
|
||||
setBuddyNeedsResync();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RequestResponseArgs rrArgs(NULL, &message, respType);
|
||||
RequestResponseNode rrNode(NumNodeID(buddyGroups->getLocalGroupID()), metaNodes);
|
||||
|
||||
rrNode.setMirrorInfo(buddyGroups, true);
|
||||
rrNode.setTargetStates(app->getMetaStateStore());
|
||||
|
||||
prepareMirrorRequestArgs(rrArgs);
|
||||
|
||||
// copy sequence numbers and set original requestor info for secondary
|
||||
message.setSequenceNumber(this->getSequenceNumber());
|
||||
message.setSequenceNumberDone(this->getSequenceNumberDone());
|
||||
message.setRequestorID(this->getRequestorID(ctx));
|
||||
// (almost) all messages do some sort of statistics gathering by user ID
|
||||
message.setMsgHeaderUserID(this->getMsgHeaderUserID());
|
||||
// set flag here instead of at the beginning because &message == this is often used
|
||||
message.addFlag(NetMessageHeader::Flag_BuddyMirrorSecond);
|
||||
message.addFlag(this->getFlags() & NetMessageHeader::Flag_IsSelectiveAck);
|
||||
message.addFlag(this->getFlags() & NetMessageHeader::Flag_HasSequenceNumber);
|
||||
|
||||
FhgfsOpsErr commRes = MessagingTk::requestResponseNode(&rrNode, &rrArgs);
|
||||
|
||||
message.removeFlag(NetMessageHeader::Flag_BuddyMirrorSecond);
|
||||
|
||||
if (commRes != FhgfsOpsErr_SUCCESS)
|
||||
{
|
||||
// since we have reached this point, the secondary has indubitably not received
|
||||
// important information from the primary. we now have two choices to keep the system
|
||||
// in a consistent, safe state:
|
||||
//
|
||||
// 1) set the secondary to needs-resync
|
||||
// 2) rollback the modifications we have made and let the client retry, hoping that
|
||||
// some future communication with the secondary is successful
|
||||
//
|
||||
// 2 is not a viable option: since some operations may move data off of this metadata
|
||||
// server and onto another one completely; allowing these to be undone requires a
|
||||
// two-phase commit protocol, which incurs large communication overhead for a
|
||||
// (hopefully) very rare error case. other operations delete local state (eg unlink,
|
||||
// or close of an unlinked file), which would have to be held in limbo until either a
|
||||
// commit or a rollback is issued.
|
||||
//
|
||||
// since we assume that communication errors are very rare, option 1 is the most
|
||||
// efficient in the general case (as it does not have to keep objects alive past their
|
||||
// intended lifetimes), so we set the secondary to needs-resync on any kind of
|
||||
// communication error.
|
||||
// other errors, e.g. out-of-memory conditions or errors caused by streamout hooks, are
|
||||
// also assumed to be rare. if any of these happens, the secondary must be resynced no
|
||||
// matter what actually happened. since the operations itself succeeded, we cannot send
|
||||
// a notification about the communication error either - we'd have to drop the operation
|
||||
// result to do that.
|
||||
|
||||
#ifdef BEEGFS_DEBUG
|
||||
int buddyNodeID = buddyGroups->getBuddyTargetID(app->getLocalNodeNumID().val());
|
||||
|
||||
LOG_CTX(MIRRORING, DEBUG, mirrorLogContext(), "Communication with secondary failed. "
|
||||
"Resync will be required when secondary comes back", buddyNodeID, commRes);
|
||||
#endif
|
||||
setBuddyNeedsResync();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
FhgfsOpsErr respMsgRes = processSecondaryResponse(*rrArgs.outRespMsg);
|
||||
|
||||
if (respMsgRes != expectedResult)
|
||||
{
|
||||
// whoops; primary and secondary did different things; if secondary is not resyncing
|
||||
// AND communication was good this is concerning (result must have been success on
|
||||
// primary, otherwise no forwarding would have happened).
|
||||
// usually, this would mean that primary and secondary do not have the same state, or
|
||||
// that the secondary has some kind of system error. (if the primary had a system error,
|
||||
// it would be more likely to fail than to succeed).
|
||||
// in either case, the secondary should be resynced, even if the primary experienced
|
||||
// a hardware fault or similar errors: at this point, we can no longer differentiate
|
||||
// between good and bad state on the primary, and the secondary may be arbitrarily out
|
||||
// of sync.
|
||||
LOG_CTX(MIRRORING, NOTICE, mirrorLogContext(),
|
||||
"Different return codes from primary and secondary buddy. "
|
||||
"Setting secondary to needs-resync.",
|
||||
("Expected response", expectedResult),
|
||||
("Received response", respMsgRes));
|
||||
setBuddyNeedsResync();
|
||||
}
|
||||
}
|
||||
|
||||
// inodes that are changes during mirrored processing on the secondary (eg file creation or
|
||||
// deletion, setxattr, etc) may have timestamps changes to a different value than the primary.
|
||||
// to remedy this, the secondary must explicitly set these timestamps during processing.
|
||||
bool shouldFixTimestamps()
|
||||
{
|
||||
return isMirrored() && Program::getApp()->getConfig()->getTuneMirrorTimestamps();
|
||||
}
|
||||
|
||||
void fixInodeTimestamp(DirInode& inode, MirroredTimestamps& ts)
|
||||
{
|
||||
if (!isMirrored())
|
||||
return;
|
||||
|
||||
BEEGFS_BUG_ON_DEBUG(!inode.getIsLoaded(), "inode not loaded");
|
||||
|
||||
StatData stat;
|
||||
|
||||
inode.getStatData(stat);
|
||||
|
||||
if (!this->hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond))
|
||||
{
|
||||
ts = stat.getMirroredTimestamps();
|
||||
}
|
||||
else
|
||||
{
|
||||
stat.setMirroredTimestamps(ts);
|
||||
|
||||
inode.setStatData(stat);
|
||||
}
|
||||
}
|
||||
|
||||
void fixInodeTimestamp(FileInode& inode, MirroredTimestamps& ts,
|
||||
EntryInfo* const saveEntryInfo)
|
||||
{
|
||||
if (!isMirrored())
|
||||
return;
|
||||
|
||||
StatData stat;
|
||||
|
||||
inode.getStatData(stat);
|
||||
|
||||
if (!this->hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond))
|
||||
{
|
||||
ts = stat.getMirroredTimestamps();
|
||||
}
|
||||
else
|
||||
{
|
||||
stat.setMirroredTimestamps(ts);
|
||||
|
||||
inode.setStatData(stat);
|
||||
if (saveEntryInfo)
|
||||
inode.updateInodeOnDisk(saveEntryInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void updateNodeOp(NetMessage::ResponseContext& ctx, MetaOpCounterTypes type)
|
||||
{
|
||||
const auto counter = isMirrored() && this->hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond)
|
||||
? MetaOpCounter_MIRROR
|
||||
: type;
|
||||
|
||||
Program::getApp()->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(),
|
||||
counter, this->getMsgHeaderUserID());
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<MirrorStateSlot> mirrorState;
|
||||
|
||||
void setBuddyNeedsResync()
|
||||
{
|
||||
BuddyCommTk::setBuddyNeedsResync(Program::getApp()->getMetaPath(), true);
|
||||
}
|
||||
};
|
||||
|
||||
354
meta/source/net/message/NetMessageFactory.cpp
Normal file
354
meta/source/net/message/NetMessageFactory.cpp
Normal file
@@ -0,0 +1,354 @@
|
||||
// control messages
|
||||
#include <common/net/message/control/AuthenticateChannelMsgEx.h>
|
||||
#include <common/net/message/control/GenericResponseMsg.h>
|
||||
#include <common/net/message/control/PeerInfoMsgEx.h>
|
||||
#include <net/message/control/AckMsgEx.h>
|
||||
#include <net/message/control/SetChannelDirectMsgEx.h>
|
||||
|
||||
// nodes messages
|
||||
#include <common/net/message/nodes/ChangeTargetConsistencyStatesRespMsg.h>
|
||||
#include <common/net/message/nodes/GetNodeCapacityPoolsRespMsg.h>
|
||||
#include <common/net/message/nodes/GetNodesRespMsg.h>
|
||||
#include <common/net/message/nodes/GetTargetMappingsRespMsg.h>
|
||||
#include <common/net/message/nodes/GetMirrorBuddyGroupsRespMsg.h>
|
||||
#include <common/net/message/nodes/GetStatesAndBuddyGroupsRespMsg.h>
|
||||
#include <common/net/message/nodes/GetTargetStatesRespMsg.h>
|
||||
#include <common/net/message/nodes/RegisterNodeRespMsg.h>
|
||||
#include <common/net/message/nodes/RemoveNodeRespMsg.h>
|
||||
#include <common/net/message/nodes/SetTargetConsistencyStatesRespMsg.h>
|
||||
#include <common/net/message/nodes/storagepools/GetStoragePoolsRespMsg.h>
|
||||
#include <net/message/nodes/GenericDebugMsgEx.h>
|
||||
#include <net/message/nodes/GetClientStatsMsgEx.h>
|
||||
#include <net/message/nodes/GetNodeCapacityPoolsMsgEx.h>
|
||||
#include <net/message/nodes/GetNodesMsgEx.h>
|
||||
#include <net/message/nodes/GetTargetMappingsMsgEx.h>
|
||||
#include <net/message/nodes/HeartbeatMsgEx.h>
|
||||
#include <net/message/nodes/HeartbeatRequestMsgEx.h>
|
||||
#include <net/message/nodes/MapTargetsMsgEx.h>
|
||||
#include <net/message/nodes/PublishCapacitiesMsgEx.h>
|
||||
#include <net/message/nodes/RefreshCapacityPoolsMsgEx.h>
|
||||
#include <net/message/nodes/RemoveNodeMsgEx.h>
|
||||
#include <net/message/nodes/RefreshTargetStatesMsgEx.h>
|
||||
#include <net/message/nodes/SetMirrorBuddyGroupMsgEx.h>
|
||||
#include <net/message/nodes/SetTargetConsistencyStatesMsgEx.h>
|
||||
#include <net/message/nodes/storagepools/RefreshStoragePoolsMsgEx.h>
|
||||
|
||||
// storage messages
|
||||
#include <common/net/message/storage/attribs/RefreshEntryInfoRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/GetChunkFileAttribsRespMsg.h>
|
||||
#include <common/net/message/storage/listing/ListDirFromOffsetRespMsg.h>
|
||||
#include <common/net/message/storage/lookup/FindOwnerRespMsg.h>
|
||||
#include <common/net/message/storage/lookup/LookupIntentRespMsg.h>
|
||||
#include <common/net/message/storage/creating/MkDirRespMsg.h>
|
||||
#include <common/net/message/storage/creating/MkFileRespMsg.h>
|
||||
#include <common/net/message/storage/creating/MkFileWithPatternRespMsg.h>
|
||||
#include <common/net/message/storage/creating/MkLocalDirRespMsg.h>
|
||||
#include <common/net/message/storage/creating/RmChunkPathsRespMsg.h>
|
||||
#include <common/net/message/storage/creating/RmDirRespMsg.h>
|
||||
#include <common/net/message/storage/creating/RmLocalDirRespMsg.h>
|
||||
#include <common/net/message/storage/mirroring/MirrorMetadataRespMsg.h>
|
||||
#include <common/net/message/storage/mirroring/ResyncRawInodesRespMsg.h>
|
||||
#include <common/net/message/storage/mirroring/ResyncSessionStoreRespMsg.h>
|
||||
#include <common/net/message/storage/moving/MovingDirInsertRespMsg.h>
|
||||
#include <common/net/message/storage/moving/MovingFileInsertRespMsg.h>
|
||||
#include <common/net/message/storage/moving/RenameRespMsg.h>
|
||||
#include <common/net/message/storage/quota/RequestExceededQuotaRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/SetAttrRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/SetFilePatternRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/SetLocalAttrRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/StatRespMsg.h>
|
||||
#include <common/net/message/storage/StatStoragePathRespMsg.h>
|
||||
#include <common/net/message/storage/TruncFileRespMsg.h>
|
||||
#include <common/net/message/storage/TruncLocalFileRespMsg.h>
|
||||
#include <common/net/message/storage/creating/UnlinkFileRespMsg.h>
|
||||
#include <common/net/message/storage/creating/UnlinkLocalFileRespMsg.h>
|
||||
#include <common/net/message/storage/creating/MoveFileInodeMsg.h>
|
||||
#include <common/net/message/storage/creating/MoveFileInodeRespMsg.h>
|
||||
#include <common/net/message/storage/creating/UnlinkLocalFileInodeRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/GetEntryInfoRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/RemoveXAttrRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/SetXAttrRespMsg.h>
|
||||
#include <common/net/message/storage/creating/HardlinkRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/UpdateDirParentRespMsg.h>
|
||||
#include <common/net/message/storage/SetStorageTargetInfoRespMsg.h>
|
||||
#include <common/net/message/storage/mirroring/StorageResyncStartedRespMsg.h>
|
||||
#include <net/message/storage/lookup/FindOwnerMsgEx.h>
|
||||
#include <net/message/storage/listing/ListDirFromOffsetMsgEx.h>
|
||||
#include <net/message/storage/creating/MkDirMsgEx.h>
|
||||
#include <net/message/storage/creating/MkFileMsgEx.h>
|
||||
#include <net/message/storage/creating/MkFileWithPatternMsgEx.h>
|
||||
#include <net/message/storage/creating/MkLocalDirMsgEx.h>
|
||||
#include <net/message/storage/creating/RmDirMsgEx.h>
|
||||
#include <net/message/storage/creating/RmLocalDirMsgEx.h>
|
||||
#include <net/message/storage/creating/UnlinkLocalFileInodeMsgEx.h>
|
||||
#include <net/message/storage/creating/RmDirEntryMsgEx.h>
|
||||
#include <net/message/storage/mirroring/GetMetaResyncStatsMsgEx.h>
|
||||
#include <net/message/storage/mirroring/ResyncSessionStoreMsgEx.h>
|
||||
#include <net/message/storage/mirroring/SetMetadataMirroringMsgEx.h>
|
||||
#include <net/message/storage/mirroring/StorageResyncStartedMsgEx.h>
|
||||
#include <net/message/storage/moving/MovingDirInsertMsgEx.h>
|
||||
#include <net/message/storage/moving/MovingFileInsertMsgEx.h>
|
||||
#include <net/message/storage/moving/RenameV2MsgEx.h>
|
||||
#include <net/message/storage/quota/SetExceededQuotaMsgEx.h>
|
||||
#include <net/message/storage/attribs/GetEntryInfoMsgEx.h>
|
||||
#include <net/message/storage/lookup/LookupIntentMsgEx.h>
|
||||
#include <net/message/storage/attribs/GetXAttrMsgEx.h>
|
||||
#include <net/message/storage/attribs/ListXAttrMsgEx.h>
|
||||
#include <net/message/storage/attribs/RemoveXAttrMsgEx.h>
|
||||
#include <net/message/storage/attribs/SetAttrMsgEx.h>
|
||||
#include <net/message/storage/attribs/SetDirPatternMsgEx.h>
|
||||
#include <net/message/storage/attribs/SetFilePatternMsgEx.h>
|
||||
#include <net/message/storage/attribs/SetFileStateMsgEx.h>
|
||||
#include <net/message/storage/attribs/SetXAttrMsgEx.h>
|
||||
#include <net/message/storage/attribs/StatMsgEx.h>
|
||||
#include <net/message/storage/attribs/UpdateDirParentMsgEx.h>
|
||||
#include <net/message/storage/StatStoragePathMsgEx.h>
|
||||
#include <net/message/storage/TruncFileMsgEx.h>
|
||||
#include <net/message/storage/creating/UnlinkFileMsgEx.h>
|
||||
#include <net/message/storage/GetHighResStatsMsgEx.h>
|
||||
#include <net/message/storage/attribs/RefreshEntryInfoMsgEx.h>
|
||||
#include <net/message/storage/lookup/FindLinkOwnerMsgEx.h>
|
||||
#include <net/message/storage/creating/HardlinkMsgEx.h>
|
||||
#include <net/message/storage/creating/MoveFileInodeMsgEx.h>
|
||||
#include <net/message/storage/attribs/UpdateDirParentMsgEx.h>
|
||||
#include <net/message/storage/mirroring/ResyncRawInodesMsgEx.h>
|
||||
|
||||
// session messages
|
||||
#include <common/net/message/session/AckNotifyRespMsg.h>
|
||||
#include <common/net/message/session/BumpFileVersionRespMsg.h>
|
||||
#include <common/net/message/session/FSyncLocalFileRespMsg.h>
|
||||
#include <common/net/message/session/locking/FLockEntryRespMsg.h>
|
||||
#include <common/net/message/session/locking/FLockRangeRespMsg.h>
|
||||
#include <common/net/message/session/opening/CloseChunkFileRespMsg.h>
|
||||
#include <common/net/message/session/opening/CloseFileRespMsg.h>
|
||||
#include <common/net/message/session/opening/OpenFileRespMsg.h>
|
||||
#include <common/net/message/session/rw/WriteLocalFileRespMsg.h>
|
||||
#include <common/net/message/storage/attribs/SetDirPatternRespMsg.h>
|
||||
#include <net/message/session/AckNotifyMsgEx.h>
|
||||
#include <net/message/session/BumpFileVersionMsgEx.h>
|
||||
#include <net/message/session/GetFileVersionMsgEx.h>
|
||||
#include <net/message/session/locking/FLockAppendMsgEx.h>
|
||||
#include <net/message/session/locking/FLockEntryMsgEx.h>
|
||||
#include <net/message/session/locking/FLockRangeMsgEx.h>
|
||||
#include <net/message/session/opening/CloseFileMsgEx.h>
|
||||
#include <net/message/session/opening/OpenFileMsgEx.h>
|
||||
|
||||
// mon message
|
||||
#include <net/message/mon/RequestMetaDataMsgEx.h>
|
||||
|
||||
// fsck messages
|
||||
#include <net/message/fsck/CreateDefDirInodesMsgEx.h>
|
||||
#include <net/message/fsck/CreateEmptyContDirsMsgEx.h>
|
||||
#include <net/message/fsck/DeleteDirEntriesMsgEx.h>
|
||||
#include <net/message/fsck/FixInodeOwnersMsgEx.h>
|
||||
#include <net/message/fsck/FixInodeOwnersInDentryMsgEx.h>
|
||||
#include <net/message/fsck/LinkToLostAndFoundMsgEx.h>
|
||||
#include <net/message/fsck/RecreateFsIDsMsgEx.h>
|
||||
#include <net/message/fsck/RecreateDentriesMsgEx.h>
|
||||
#include <net/message/fsck/RemoveInodesMsgEx.h>
|
||||
#include <net/message/fsck/RetrieveDirEntriesMsgEx.h>
|
||||
#include <net/message/fsck/RetrieveInodesMsgEx.h>
|
||||
#include <net/message/fsck/RetrieveFsIDsMsgEx.h>
|
||||
#include <net/message/fsck/FsckSetEventLoggingMsgEx.h>
|
||||
#include <net/message/fsck/UpdateDirAttribsMsgEx.h>
|
||||
#include <net/message/fsck/UpdateFileAttribsMsgEx.h>
|
||||
#include <net/message/fsck/AdjustChunkPermissionsMsgEx.h>
|
||||
#include <net/message/fsck/CheckAndRepairDupInodeMsgEx.h>
|
||||
|
||||
// chunk balancing
|
||||
#include <common/net/message/storage/chunkbalancing/CpChunkPathsRespMsg.h>
|
||||
#include <net/message/storage/chunkbalancing/ChunkBalanceMsgEx.h>
|
||||
#include <net/message/storage/chunkbalancing/StripePatternUpdateMsgEx.h>
|
||||
|
||||
|
||||
#include <common/net/message/SimpleMsg.h>
|
||||
#include <net/message/nodes/storagepools/RefreshStoragePoolsMsgEx.h>
|
||||
|
||||
#include "NetMessageFactory.h"
|
||||
|
||||
|
||||
/**
|
||||
* @return NetMessage that must be deleted by the caller
|
||||
* (msg->msgType is NETMSGTYPE_Invalid on error)
|
||||
*/
|
||||
std::unique_ptr<NetMessage> NetMessageFactory::createFromMsgType(unsigned short msgType) const
|
||||
{
|
||||
NetMessage* msg;
|
||||
|
||||
switch(msgType)
|
||||
{
|
||||
// The following lines are grouped by "type of the message" and ordered alphabetically inside
|
||||
// the groups. There should always be one message per line to keep a clear layout (although
|
||||
// this might lead to lines that are longer than usual)
|
||||
|
||||
// control messages
|
||||
case NETMSGTYPE_Ack: { msg = new AckMsgEx(); } break;
|
||||
case NETMSGTYPE_AuthenticateChannel: { msg = new AuthenticateChannelMsgEx(); } break;
|
||||
case NETMSGTYPE_GenericResponse: { msg = new GenericResponseMsg(); } break;
|
||||
case NETMSGTYPE_SetChannelDirect: { msg = new SetChannelDirectMsgEx(); } break;
|
||||
case NETMSGTYPE_PeerInfo: { msg = new PeerInfoMsgEx(); } break;
|
||||
|
||||
// nodes messages
|
||||
case NETMSGTYPE_ChangeTargetConsistencyStatesResp: { msg = new ChangeTargetConsistencyStatesRespMsg(); } break;
|
||||
case NETMSGTYPE_GenericDebug: { msg = new GenericDebugMsgEx(); } break;
|
||||
case NETMSGTYPE_GetClientStats: { msg = new GetClientStatsMsgEx(); } break;
|
||||
case NETMSGTYPE_GetMirrorBuddyGroupsResp: { msg = new GetMirrorBuddyGroupsRespMsg(); } break;
|
||||
case NETMSGTYPE_GetNodeCapacityPools: { msg = new GetNodeCapacityPoolsMsgEx(); } break;
|
||||
case NETMSGTYPE_GetNodeCapacityPoolsResp: { msg = new GetNodeCapacityPoolsRespMsg(); } break;
|
||||
case NETMSGTYPE_GetNodes: { msg = new GetNodesMsgEx(); } break;
|
||||
case NETMSGTYPE_GetNodesResp: { msg = new GetNodesRespMsg(); } break;
|
||||
case NETMSGTYPE_GetStatesAndBuddyGroupsResp: { msg = new GetStatesAndBuddyGroupsRespMsg(); } break;
|
||||
case NETMSGTYPE_GetStoragePoolsResp: { msg = new GetStoragePoolsRespMsg(); } break;
|
||||
case NETMSGTYPE_GetTargetMappings: { msg = new GetTargetMappingsMsgEx(); } break;
|
||||
case NETMSGTYPE_GetTargetMappingsResp: { msg = new GetTargetMappingsRespMsg(); } break;
|
||||
case NETMSGTYPE_GetTargetStatesResp: { msg = new GetTargetStatesRespMsg(); } break;
|
||||
case NETMSGTYPE_HeartbeatRequest: { msg = new HeartbeatRequestMsgEx(); } break;
|
||||
case NETMSGTYPE_Heartbeat: { msg = new HeartbeatMsgEx(); } break;
|
||||
case NETMSGTYPE_MapTargets: { msg = new MapTargetsMsgEx(); } break;
|
||||
case NETMSGTYPE_PublishCapacities: { msg = new PublishCapacitiesMsgEx(); } break;
|
||||
case NETMSGTYPE_RefreshStoragePools: { msg = new RefreshStoragePoolsMsgEx(); } break;
|
||||
case NETMSGTYPE_RegisterNodeResp: { msg = new RegisterNodeRespMsg(); } break;
|
||||
case NETMSGTYPE_RemoveNode: { msg = new RemoveNodeMsgEx(); } break;
|
||||
case NETMSGTYPE_RemoveNodeResp: { msg = new RemoveNodeRespMsg(); } break;
|
||||
case NETMSGTYPE_RefreshCapacityPools: { msg = new RefreshCapacityPoolsMsgEx(); } break;
|
||||
case NETMSGTYPE_RefreshTargetStates: { msg = new RefreshTargetStatesMsgEx(); } break;
|
||||
case NETMSGTYPE_SetMirrorBuddyGroup: { msg = new SetMirrorBuddyGroupMsgEx(); } break;
|
||||
case NETMSGTYPE_SetTargetConsistencyStates: { msg = new SetTargetConsistencyStatesMsgEx(); } break;
|
||||
case NETMSGTYPE_SetTargetConsistencyStatesResp: { msg = new SetTargetConsistencyStatesRespMsg(); } break;
|
||||
|
||||
// storage messages
|
||||
case NETMSGTYPE_ChunkBalance: { msg = new ChunkBalanceMsgEx(); } break;
|
||||
case NETMSGTYPE_CpChunkPathsResp: { msg = new CpChunkPathsRespMsg(); } break;
|
||||
case NETMSGTYPE_FindLinkOwner: { msg = new FindLinkOwnerMsgEx(); } break;
|
||||
case NETMSGTYPE_FindOwner: { msg = new FindOwnerMsgEx(); } break;
|
||||
case NETMSGTYPE_FindOwnerResp: { msg = new FindOwnerRespMsg(); } break;
|
||||
case NETMSGTYPE_GetChunkFileAttribsResp: { msg = new GetChunkFileAttribsRespMsg(); } break;
|
||||
case NETMSGTYPE_GetEntryInfo: { msg = new GetEntryInfoMsgEx(); } break;
|
||||
case NETMSGTYPE_GetEntryInfoResp: { msg = new GetEntryInfoRespMsg(); } break;
|
||||
case NETMSGTYPE_GetHighResStats: { msg = new GetHighResStatsMsgEx(); } break;
|
||||
case NETMSGTYPE_GetMetaResyncStats: { msg = new GetMetaResyncStatsMsgEx(); } break;
|
||||
case NETMSGTYPE_RequestExceededQuotaResp: {msg = new RequestExceededQuotaRespMsg(); } break;
|
||||
case NETMSGTYPE_SetExceededQuota: {msg = new SetExceededQuotaMsgEx(); } break;
|
||||
case NETMSGTYPE_StorageResyncStarted: { msg = new StorageResyncStartedMsgEx(); } break;
|
||||
case NETMSGTYPE_StorageResyncStartedResp: { msg = new StorageResyncStartedRespMsg(); } break;
|
||||
case NETMSGTYPE_GetXAttr: { msg = new GetXAttrMsgEx(); } break;
|
||||
case NETMSGTYPE_GetXAttrResp: { msg = new GetXAttrRespMsg(); } break;
|
||||
case NETMSGTYPE_Hardlink: { msg = new HardlinkMsgEx(); } break;
|
||||
case NETMSGTYPE_HardlinkResp: { msg = new HardlinkRespMsg(); } break;
|
||||
case NETMSGTYPE_ListDirFromOffset: { msg = new ListDirFromOffsetMsgEx(); } break;
|
||||
case NETMSGTYPE_ListDirFromOffsetResp: { msg = new ListDirFromOffsetRespMsg(); } break;
|
||||
case NETMSGTYPE_ListXAttr: { msg = new ListXAttrMsgEx(); } break;
|
||||
case NETMSGTYPE_ListXAttrResp: { msg = new ListXAttrRespMsg(); } break;
|
||||
case NETMSGTYPE_LookupIntent: { msg = new LookupIntentMsgEx(); } break;
|
||||
case NETMSGTYPE_LookupIntentResp: { msg = new LookupIntentRespMsg(); } break;
|
||||
case NETMSGTYPE_MkDir: { msg = new MkDirMsgEx(); } break;
|
||||
case NETMSGTYPE_MkDirResp: { msg = new MkDirRespMsg(); } break;
|
||||
case NETMSGTYPE_MkFile: { msg = new MkFileMsgEx(); } break;
|
||||
case NETMSGTYPE_MkFileResp: { msg = new MkFileRespMsg(); } break;
|
||||
case NETMSGTYPE_MkFileWithPattern: { msg = new MkFileWithPatternMsgEx(); } break;
|
||||
case NETMSGTYPE_MkFileWithPatternResp: { msg = new MkFileWithPatternRespMsg(); } break;
|
||||
case NETMSGTYPE_MkLocalDir: { msg = new MkLocalDirMsgEx(); } break;
|
||||
case NETMSGTYPE_MkLocalDirResp: { msg = new MkLocalDirRespMsg(); } break;
|
||||
case NETMSGTYPE_MovingDirInsert: { msg = new MovingDirInsertMsgEx(); } break;
|
||||
case NETMSGTYPE_MovingDirInsertResp: { msg = new MovingDirInsertRespMsg(); } break;
|
||||
case NETMSGTYPE_MovingFileInsert: { msg = new MovingFileInsertMsgEx(); } break;
|
||||
case NETMSGTYPE_MovingFileInsertResp: { msg = new MovingFileInsertRespMsg(); } break;
|
||||
case NETMSGTYPE_RefreshEntryInfo: { msg = new RefreshEntryInfoMsgEx(); } break;
|
||||
case NETMSGTYPE_RefreshEntryInfoResp: { msg = new RefreshEntryInfoRespMsg(); } break;
|
||||
case NETMSGTYPE_ResyncRawInodes: { msg = new ResyncRawInodesMsgEx(); } break;
|
||||
case NETMSGTYPE_ResyncRawInodesResp: { msg = new ResyncRawInodesRespMsg(); } break;
|
||||
case NETMSGTYPE_ResyncSessionStore: { msg = new ResyncSessionStoreMsgEx(); } break;
|
||||
case NETMSGTYPE_ResyncSessionStoreResp: { msg = new ResyncSessionStoreRespMsg(); } break;
|
||||
case NETMSGTYPE_RemoveXAttr: { msg = new RemoveXAttrMsgEx(); } break;
|
||||
case NETMSGTYPE_RemoveXAttrResp: { msg = new RemoveXAttrRespMsg(); } break;
|
||||
case NETMSGTYPE_Rename: { msg = new RenameV2MsgEx(); } break;
|
||||
case NETMSGTYPE_RenameResp: { msg = new RenameRespMsg(); } break;
|
||||
case NETMSGTYPE_RmChunkPathsResp: { msg = new RmChunkPathsRespMsg(); } break;
|
||||
case NETMSGTYPE_RmDirEntry: { msg = new RmDirEntryMsgEx(); } break;
|
||||
case NETMSGTYPE_RmDir: { msg = new RmDirMsgEx(); } break;
|
||||
case NETMSGTYPE_RmDirResp: { msg = new RmDirRespMsg(); } break;
|
||||
case NETMSGTYPE_RmLocalDir: { msg = new RmLocalDirMsgEx(); } break;
|
||||
case NETMSGTYPE_RmLocalDirResp: { msg = new RmLocalDirRespMsg(); } break;
|
||||
case NETMSGTYPE_SetAttr: { msg = new SetAttrMsgEx(); } break;
|
||||
case NETMSGTYPE_SetAttrResp: { msg = new SetAttrRespMsg(); } break;
|
||||
case NETMSGTYPE_SetDirPattern: { msg = new SetDirPatternMsgEx(); } break;
|
||||
case NETMSGTYPE_SetDirPatternResp: { msg = new SetDirPatternRespMsg(); } break;
|
||||
case NETMSGTYPE_SetLocalAttrResp: { msg = new SetLocalAttrRespMsg(); } break;
|
||||
case NETMSGTYPE_SetMetadataMirroring: { msg = new SetMetadataMirroringMsgEx(); } break;
|
||||
case NETMSGTYPE_SetStorageTargetInfoResp: { msg = new SetStorageTargetInfoRespMsg(); } break;
|
||||
case NETMSGTYPE_SetXAttr: { msg = new SetXAttrMsgEx(); } break;
|
||||
case NETMSGTYPE_SetXAttrResp: { msg = new SetXAttrRespMsg(); } break;
|
||||
case NETMSGTYPE_Stat: { msg = new StatMsgEx(); } break;
|
||||
case NETMSGTYPE_StatResp: { msg = new StatRespMsg(); } break;
|
||||
case NETMSGTYPE_StatStoragePath: { msg = new StatStoragePathMsgEx(); } break;
|
||||
case NETMSGTYPE_StatStoragePathResp: { msg = new StatStoragePathRespMsg(); } break;
|
||||
case NETMSGTYPE_StripePatternUpdate: { msg = new StripePatternUpdateMsgEx(); } break;
|
||||
case NETMSGTYPE_TruncFile: { msg = new TruncFileMsgEx(); } break;
|
||||
case NETMSGTYPE_TruncFileResp: { msg = new TruncFileRespMsg(); } break;
|
||||
case NETMSGTYPE_TruncLocalFileResp: { msg = new TruncLocalFileRespMsg(); } break;
|
||||
case NETMSGTYPE_UnlinkFile: { msg = new UnlinkFileMsgEx(); } break;
|
||||
case NETMSGTYPE_UnlinkFileResp: { msg = new UnlinkFileRespMsg(); } break;
|
||||
case NETMSGTYPE_UnlinkLocalFileResp: { msg = new UnlinkLocalFileRespMsg(); } break;
|
||||
case NETMSGTYPE_UpdateDirParent: { msg = new UpdateDirParentMsgEx(); } break;
|
||||
case NETMSGTYPE_UpdateDirParentResp: { msg = new UpdateDirParentRespMsg(); } break;
|
||||
case NETMSGTYPE_MoveFileInode: { msg = new MoveFileInodeMsgEx(); } break;
|
||||
case NETMSGTYPE_MoveFileInodeResp: {msg = new MoveFileInodeRespMsg(); } break;
|
||||
case NETMSGTYPE_UnlinkLocalFileInode: {msg = new UnlinkLocalFileInodeMsgEx(); } break;
|
||||
case NETMSGTYPE_UnlinkLocalFileInodeResp: {msg = new UnlinkLocalFileInodeRespMsg(); } break;
|
||||
case NETMSGTYPE_SetFilePattern: { msg = new SetFilePatternMsgEx(); } break;
|
||||
case NETMSGTYPE_SetFilePatternResp: { msg = new SetFilePatternRespMsg(); } break;
|
||||
case NETMSGTYPE_SetFileState: { msg = new SetFileStateMsgEx(); } break;
|
||||
case NETMSGTYPE_SetFileStateResp: { msg = new SetFileStateRespMsg(); } break;
|
||||
|
||||
// session messages
|
||||
case NETMSGTYPE_BumpFileVersion: { msg = new BumpFileVersionMsgEx(); } break;
|
||||
case NETMSGTYPE_BumpFileVersionResp: { msg = new BumpFileVersionRespMsg(); } break;
|
||||
case NETMSGTYPE_OpenFile: { msg = new OpenFileMsgEx(); } break;
|
||||
case NETMSGTYPE_OpenFileResp: { msg = new OpenFileRespMsg(); } break;
|
||||
case NETMSGTYPE_CloseFile: { msg = new CloseFileMsgEx(); } break;
|
||||
case NETMSGTYPE_CloseFileResp: { msg = new CloseFileRespMsg(); } break;
|
||||
case NETMSGTYPE_CloseChunkFileResp: { msg = new CloseChunkFileRespMsg(); } break;
|
||||
case NETMSGTYPE_WriteLocalFileResp: { msg = new WriteLocalFileRespMsg(); } break;
|
||||
case NETMSGTYPE_FSyncLocalFileResp: { msg = new FSyncLocalFileRespMsg(); } break;
|
||||
case NETMSGTYPE_FLockAppend: { msg = new FLockAppendMsgEx(); } break;
|
||||
case NETMSGTYPE_FLockAppendResp: { msg = new FLockAppendRespMsg(); } break;
|
||||
case NETMSGTYPE_FLockEntry: { msg = new FLockEntryMsgEx(); } break;
|
||||
case NETMSGTYPE_FLockEntryResp: { msg = new FLockEntryRespMsg(); } break;
|
||||
case NETMSGTYPE_FLockRange: { msg = new FLockRangeMsgEx(); } break;
|
||||
case NETMSGTYPE_FLockRangeResp: { msg = new FLockRangeRespMsg(); } break;
|
||||
case NETMSGTYPE_GetFileVersion: { msg = new GetFileVersionMsgEx(); } break;
|
||||
case NETMSGTYPE_GetFileVersionResp: { msg = new GetFileVersionRespMsg(); } break;
|
||||
case NETMSGTYPE_AckNotify: { msg = new AckNotifiyMsgEx(); } break;
|
||||
case NETMSGTYPE_AckNotifyResp: { msg = new AckNotifiyRespMsg(); } break;
|
||||
|
||||
// mon message
|
||||
case NETMSGTYPE_RequestMetaData: { msg = new RequestMetaDataMsgEx(); } break;
|
||||
|
||||
// fsck messages
|
||||
case NETMSGTYPE_RetrieveDirEntries: { msg = new RetrieveDirEntriesMsgEx(); } break;
|
||||
case NETMSGTYPE_RetrieveInodes: { msg = new RetrieveInodesMsgEx(); } break;
|
||||
case NETMSGTYPE_RetrieveFsIDs: { msg = new RetrieveFsIDsMsgEx(); } break;
|
||||
case NETMSGTYPE_DeleteDirEntries: { msg = new DeleteDirEntriesMsgEx(); } break;
|
||||
case NETMSGTYPE_CreateDefDirInodes: { msg = new CreateDefDirInodesMsgEx(); } break;
|
||||
case NETMSGTYPE_FixInodeOwners: { msg = new FixInodeOwnersMsgEx(); } break;
|
||||
case NETMSGTYPE_FixInodeOwnersInDentry: { msg = new FixInodeOwnersInDentryMsgEx(); } break;
|
||||
case NETMSGTYPE_LinkToLostAndFound: { msg = new LinkToLostAndFoundMsgEx(); } break;
|
||||
case NETMSGTYPE_CreateEmptyContDirs: { msg = new CreateEmptyContDirsMsgEx(); } break;
|
||||
case NETMSGTYPE_UpdateFileAttribs: { msg = new UpdateFileAttribsMsgEx(); } break;
|
||||
case NETMSGTYPE_UpdateDirAttribs: { msg = new UpdateDirAttribsMsgEx(); } break;
|
||||
case NETMSGTYPE_RemoveInodes: { msg = new RemoveInodesMsgEx(); } break;
|
||||
case NETMSGTYPE_RecreateFsIDs: { msg = new RecreateFsIDsMsgEx(); } break;
|
||||
case NETMSGTYPE_RecreateDentries: { msg = new RecreateDentriesMsgEx(); } break;
|
||||
case NETMSGTYPE_FsckSetEventLogging: { msg = new FsckSetEventLoggingMsgEx(); } break;
|
||||
case NETMSGTYPE_AdjustChunkPermissions: { msg = new AdjustChunkPermissionsMsgEx(); } break;
|
||||
case NETMSGTYPE_CheckAndRepairDupInode: { msg = new CheckAndRepairDupInodeMsgEx(); } break;
|
||||
|
||||
default:
|
||||
{
|
||||
msg = new SimpleMsg(NETMSGTYPE_Invalid);
|
||||
} break;
|
||||
}
|
||||
|
||||
return std::unique_ptr<NetMessage>(msg);
|
||||
}
|
||||
|
||||
14
meta/source/net/message/NetMessageFactory.h
Normal file
14
meta/source/net/message/NetMessageFactory.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/Common.h>
|
||||
#include <common/net/message/AbstractNetMessageFactory.h>
|
||||
|
||||
class NetMessageFactory : public AbstractNetMessageFactory
|
||||
{
|
||||
public:
|
||||
NetMessageFactory() {}
|
||||
|
||||
protected:
|
||||
virtual std::unique_ptr<NetMessage> createFromMsgType(unsigned short msgType) const override;
|
||||
} ;
|
||||
|
||||
24
meta/source/net/message/control/AckMsgEx.cpp
Normal file
24
meta/source/net/message/control/AckMsgEx.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <program/Program.h>
|
||||
#include "AckMsgEx.h"
|
||||
|
||||
bool AckMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
#ifdef BEEGFS_DEBUG
|
||||
const char* logContext = "Ack incoming";
|
||||
#endif //BEEGFS_DEBUG
|
||||
|
||||
LOG_DEBUG(logContext, 5, std::string("Value: ") + getValue() );
|
||||
|
||||
AcknowledgmentStore* ackStore = Program::getApp()->getAckStore();
|
||||
ackStore->receivedAck(getValue() );
|
||||
|
||||
App* app = Program::getApp();
|
||||
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), MetaOpCounter_ACK,
|
||||
getMsgHeaderUserID() );
|
||||
|
||||
// note: this message does not require a response
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
13
meta/source/net/message/control/AckMsgEx.h
Normal file
13
meta/source/net/message/control/AckMsgEx.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/control/AckMsg.h>
|
||||
|
||||
// see class AcknowledgeableMsg (fhgfs_common) for a short description
|
||||
|
||||
class AckMsgEx : public AckMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
|
||||
21
meta/source/net/message/control/SetChannelDirectMsgEx.cpp
Normal file
21
meta/source/net/message/control/SetChannelDirectMsgEx.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <program/Program.h>
|
||||
#include "SetChannelDirectMsgEx.h"
|
||||
|
||||
bool SetChannelDirectMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
#ifdef BEEGFS_DEBUG
|
||||
const char* logContext = "SetChannelDirect incoming";
|
||||
|
||||
LOG_DEBUG(logContext, 5, std::string("Value: ") + StringTk::intToStr(getValue() ) );
|
||||
#endif // BEEGFS_DEBUG
|
||||
|
||||
ctx.getSocket()->setIsDirect(getValue() );
|
||||
|
||||
App* app = Program::getApp();
|
||||
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), MetaOpCounter_SETCHANNELDIRECT,
|
||||
getMsgHeaderUserID() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
11
meta/source/net/message/control/SetChannelDirectMsgEx.h
Normal file
11
meta/source/net/message/control/SetChannelDirectMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/control/SetChannelDirectMsg.h>
|
||||
|
||||
class SetChannelDirectMsgEx : public SetChannelDirectMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
|
||||
213
meta/source/net/message/fsck/AdjustChunkPermissionsMsgEx.cpp
Normal file
213
meta/source/net/message/fsck/AdjustChunkPermissionsMsgEx.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
#include "AdjustChunkPermissionsMsgEx.h"
|
||||
|
||||
#include <program/Program.h>
|
||||
#include <common/net/message/storage/attribs/SetLocalAttrMsg.h>
|
||||
#include <common/net/message/storage/attribs/SetLocalAttrRespMsg.h>
|
||||
#include <common/storage/striping/Raid0Pattern.h>
|
||||
#include <components/worker/SetChunkFileAttribsWork.h>
|
||||
|
||||
bool AdjustChunkPermissionsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("Incoming AdjustChunkPermissionsMsg");
|
||||
|
||||
MetaStore *metaStore = Program::getApp()->getMetaStore();
|
||||
|
||||
unsigned hashDirNum = this->getHashDirNum();
|
||||
unsigned maxEntries = this->getMaxEntries();
|
||||
int64_t lastHashDirOffset = this->getLastHashDirOffset();
|
||||
int64_t lastContDirOffset = this->getLastContDirOffset();
|
||||
std::string currentContDirID = this->getCurrentContDirID();
|
||||
int64_t newHashDirOffset = 0;
|
||||
int64_t newContDirOffset = 0;
|
||||
unsigned errorCount = 0;
|
||||
|
||||
unsigned readOutEntries = 0;
|
||||
|
||||
bool hasNext;
|
||||
|
||||
if ( currentContDirID.empty() )
|
||||
{
|
||||
hasNext = StorageTkEx::getNextContDirID(hashDirNum, getIsBuddyMirrored(), lastHashDirOffset,
|
||||
¤tContDirID, &newHashDirOffset);
|
||||
if ( hasNext )
|
||||
{
|
||||
lastHashDirOffset = newHashDirOffset;
|
||||
}
|
||||
}
|
||||
else
|
||||
hasNext = true;
|
||||
|
||||
while ( hasNext )
|
||||
{
|
||||
std::string parentID = currentContDirID;
|
||||
|
||||
unsigned remainingEntries = maxEntries - readOutEntries;
|
||||
StringList entryNames;
|
||||
|
||||
bool parentDirInodeIsTemp = false;
|
||||
|
||||
FileIDLock dirLock;
|
||||
|
||||
if (getIsBuddyMirrored())
|
||||
dirLock = {Program::getApp()->getMirroredSessions()->getEntryLockStore(), parentID, false};
|
||||
|
||||
DirInode* parentDirInode = metaStore->referenceDir(parentID, getIsBuddyMirrored(), true);
|
||||
|
||||
// it could be, that parentDirInode does not exist
|
||||
// in fsck we create a temporary inode for this case
|
||||
if ( unlikely(!parentDirInode) )
|
||||
{
|
||||
log.log(
|
||||
Log_NOTICE,
|
||||
"Could not reference directory. EntryID: " + parentID
|
||||
+ " => using temporary directory inode ");
|
||||
|
||||
// create temporary inode
|
||||
int mode = S_IFDIR | S_IRWXU;
|
||||
UInt16Vector stripeTargets;
|
||||
Raid0Pattern stripePattern(0, stripeTargets, 0);
|
||||
parentDirInode = new DirInode(parentID, mode, 0, 0,
|
||||
Program::getApp()->getLocalNode().getNumID(), stripePattern, getIsBuddyMirrored());
|
||||
|
||||
parentDirInodeIsTemp = true;
|
||||
}
|
||||
|
||||
if ( parentDirInode->listIncremental(lastContDirOffset, remainingEntries, &entryNames,
|
||||
&newContDirOffset) == FhgfsOpsErr_SUCCESS )
|
||||
{
|
||||
lastContDirOffset = newContDirOffset;
|
||||
readOutEntries += entryNames.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.log(Log_WARNING, "Could not list contents of directory. EntryID: " + parentID);
|
||||
}
|
||||
|
||||
// actually process the entries; for the dentry part we only need to know if it is a file
|
||||
// with inlined inode data
|
||||
for ( StringListIter namesIter = entryNames.begin(); namesIter != entryNames.end();
|
||||
namesIter++ )
|
||||
{
|
||||
std::string filename = MetaStorageTk::getMetaDirEntryPath(
|
||||
getIsBuddyMirrored()
|
||||
? Program::getApp()->getBuddyMirrorDentriesPath()->str()
|
||||
: Program::getApp()->getDentriesPath()->str(), parentID) + "/" + *namesIter;
|
||||
|
||||
EntryInfo entryInfo;
|
||||
FileInodeStoreData inodeDiskData;
|
||||
|
||||
auto [getEntryRes, isFileOpen] = metaStore->getEntryData(parentDirInode, *namesIter, &entryInfo,
|
||||
&inodeDiskData);
|
||||
inodeDiskData.setDynamicOrigParentEntryID(parentID);
|
||||
|
||||
if (getEntryRes == FhgfsOpsErr_SUCCESS ||
|
||||
getEntryRes == FhgfsOpsErr_DYNAMICATTRIBSOUTDATED )
|
||||
{
|
||||
DirEntryType entryType = entryInfo.getEntryType();
|
||||
|
||||
// we only care if inode data is present
|
||||
if ( (DirEntryType_ISFILE(entryType)) && (entryInfo.getIsInlined() ) )
|
||||
{
|
||||
const std::string& inodeID = inodeDiskData.getEntryID();
|
||||
unsigned userID = inodeDiskData.getInodeStatData()->getUserID();
|
||||
unsigned groupID = inodeDiskData.getInodeStatData()->getGroupID();
|
||||
StripePattern* pattern = inodeDiskData.getStripePattern();
|
||||
|
||||
PathInfo pathInfo;
|
||||
inodeDiskData.getPathInfo(&pathInfo);
|
||||
|
||||
if ( !this->sendSetAttrMsg(inodeID, userID, groupID, &pathInfo, pattern) )
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.log(Log_WARNING, "Unable to create dir entry from entry with name " + *namesIter
|
||||
+ " in directory with ID " + parentID);
|
||||
}
|
||||
}
|
||||
|
||||
if ( parentDirInodeIsTemp )
|
||||
SAFE_DELETE(parentDirInode);
|
||||
else
|
||||
metaStore->releaseDir(parentID);
|
||||
|
||||
if ( entryNames.size() < remainingEntries )
|
||||
{
|
||||
// directory is at the end => proceed with next
|
||||
hasNext = StorageTkEx::getNextContDirID(hashDirNum, getIsBuddyMirrored(),
|
||||
lastHashDirOffset, ¤tContDirID, &newHashDirOffset);
|
||||
|
||||
if ( hasNext )
|
||||
{
|
||||
lastHashDirOffset = newHashDirOffset;
|
||||
lastContDirOffset = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// there are more to come, but we need to exit the loop now, because maxCount is reached
|
||||
hasNext = false;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.sendResponse(
|
||||
AdjustChunkPermissionsRespMsg(readOutEntries, currentContDirID, lastHashDirOffset,
|
||||
lastContDirOffset, errorCount) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AdjustChunkPermissionsMsgEx::sendSetAttrMsg(const std::string& entryID, unsigned userID,
|
||||
unsigned groupID, PathInfo* pathInfo, StripePattern* pattern)
|
||||
{
|
||||
const char* logContext = "AdjustChunkPermissionsMsgEx::sendSetAttrMsg";
|
||||
|
||||
MultiWorkQueue* slaveQueue = Program::getApp()->getCommSlaveQueue();
|
||||
|
||||
int validAttribs = SETATTR_CHANGE_USERID | SETATTR_CHANGE_GROUPID; // only interested in these
|
||||
SettableFileAttribs attribs;
|
||||
attribs.userID = userID;
|
||||
attribs.groupID = groupID;
|
||||
|
||||
const UInt16Vector* stripeTargets = pattern->getStripeTargetIDs();
|
||||
size_t numTargetWorks = stripeTargets->size();
|
||||
|
||||
FhgfsOpsErrVec nodeResults(numTargetWorks);
|
||||
SynchronizedCounter counter;
|
||||
|
||||
// generate work for storage targets...
|
||||
|
||||
for(size_t i=0; i < numTargetWorks; i++)
|
||||
{
|
||||
SetChunkFileAttribsWork* work = new SetChunkFileAttribsWork(
|
||||
entryID, validAttribs, &attribs, false, pattern, (*stripeTargets)[i], pathInfo,
|
||||
NULL, &(nodeResults[i]), &counter);
|
||||
|
||||
work->setQuotaChown(true);
|
||||
work->setMsgUserID(getMsgHeaderUserID() );
|
||||
|
||||
slaveQueue->addDirectWork(work);
|
||||
}
|
||||
|
||||
// wait for work completion...
|
||||
|
||||
counter.waitForCount(numTargetWorks);
|
||||
|
||||
// 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: " + entryID );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
17
meta/source/net/message/fsck/AdjustChunkPermissionsMsgEx.h
Normal file
17
meta/source/net/message/fsck/AdjustChunkPermissionsMsgEx.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/fsck/AdjustChunkPermissionsMsg.h>
|
||||
#include <common/net/message/fsck/AdjustChunkPermissionsRespMsg.h>
|
||||
#include <common/storage/PathInfo.h>
|
||||
#include <common/storage/striping/StripePattern.h>
|
||||
|
||||
class AdjustChunkPermissionsMsgEx : public AdjustChunkPermissionsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
|
||||
private:
|
||||
bool sendSetAttrMsg(const std::string& entryID, unsigned userID, unsigned groupID,
|
||||
PathInfo* pathInfo, StripePattern* pattern);
|
||||
};
|
||||
|
||||
38
meta/source/net/message/fsck/CheckAndRepairDupInodeMsgEx.cpp
Normal file
38
meta/source/net/message/fsck/CheckAndRepairDupInodeMsgEx.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <program/Program.h>
|
||||
#include <common/net/message/fsck/CheckAndRepairDupInodeRespMsg.h>
|
||||
|
||||
#include "CheckAndRepairDupInodeMsgEx.h"
|
||||
|
||||
bool CheckAndRepairDupInodeMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
StringList failedIDList;
|
||||
|
||||
for (const auto& inode : getDuplicateInodes())
|
||||
{
|
||||
const std::string& entryID = inode.getID();
|
||||
const std::string& parentEntryID = inode.getParentDirID();
|
||||
const bool isBuddyMirrored = inode.getIsBuddyMirrored();
|
||||
|
||||
FileIDLock dirLock = {entryLockStore, parentEntryID, true};
|
||||
FileIDLock fileLock = {entryLockStore, entryID, true};
|
||||
|
||||
EntryInfo fileInfo(NumNodeID(0), parentEntryID, entryID, std::string(""), DirEntryType_REGULARFILE, 0);
|
||||
fileInfo.setBuddyMirroredFlag(isBuddyMirrored);
|
||||
|
||||
DirInode* parentDir = metaStore->referenceDir(parentEntryID, isBuddyMirrored, true);
|
||||
FhgfsOpsErr repairRes = metaStore->checkAndRepairDupFileInode(*parentDir, &fileInfo);
|
||||
|
||||
if (repairRes != FhgfsOpsErr_SUCCESS)
|
||||
{
|
||||
failedIDList.push_back(entryID);
|
||||
}
|
||||
|
||||
metaStore->releaseDir(parentDir->getID());
|
||||
}
|
||||
|
||||
ctx.sendResponse(CheckAndRepairDupInodeRespMsg(std::move(failedIDList)));
|
||||
return true;
|
||||
}
|
||||
10
meta/source/net/message/fsck/CheckAndRepairDupInodeMsgEx.h
Normal file
10
meta/source/net/message/fsck/CheckAndRepairDupInodeMsgEx.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/fsck/CheckAndRepairDupInodeMsg.h>
|
||||
|
||||
class CheckAndRepairDupInodeMsgEx : public CheckAndRepairDupInodeMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
60
meta/source/net/message/fsck/CreateDefDirInodesMsgEx.cpp
Normal file
60
meta/source/net/message/fsck/CreateDefDirInodesMsgEx.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include "CreateDefDirInodesMsgEx.h"
|
||||
#include <program/Program.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
bool CreateDefDirInodesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("CreateDefDirInodesMsg incoming");
|
||||
|
||||
App* app = Program::getApp();
|
||||
Config* cfg = app->getConfig();
|
||||
|
||||
StringList failedInodeIDs;
|
||||
FsckDirInodeList createdInodes;
|
||||
|
||||
for (auto it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
const std::string& inodeID = std::get<0>(*it);
|
||||
const bool isBuddyMirrored = std::get<1>(*it);
|
||||
int mode = S_IFDIR | S_IRWXU;
|
||||
unsigned userID = 0; // root
|
||||
unsigned groupID = 0; // root
|
||||
const NumNodeID ownerNodeID = isBuddyMirrored
|
||||
? NumNodeID(app->getMetaBuddyGroupMapper()->getLocalGroupID())
|
||||
: app->getLocalNode().getNumID();
|
||||
|
||||
UInt16Vector stripeTargets;
|
||||
unsigned defaultChunkSize = cfg->getTuneDefaultChunkSize();
|
||||
unsigned defaultNumStripeTargets = cfg->getTuneDefaultNumStripeTargets();
|
||||
Raid0Pattern stripePattern(defaultChunkSize, stripeTargets, defaultNumStripeTargets);
|
||||
|
||||
// we try to create a new directory inode, with default values
|
||||
|
||||
FileIDLock dirLock;
|
||||
|
||||
if (isBuddyMirrored)
|
||||
dirLock = {Program::getApp()->getMirroredSessions()->getEntryLockStore(), inodeID, true};
|
||||
|
||||
DirInode dirInode(inodeID, mode, userID, groupID, ownerNodeID, stripePattern,
|
||||
isBuddyMirrored);
|
||||
if ( dirInode.storeAsReplacementFile(inodeID) == FhgfsOpsErr_SUCCESS )
|
||||
{
|
||||
// try to refresh the metainfo (maybe a .cont directory was already present)
|
||||
dirInode.refreshMetaInfo();
|
||||
|
||||
StatData statData;
|
||||
dirInode.getStatData(statData);
|
||||
|
||||
FsckDirInode fsckDirInode(inodeID, "", NumNodeID(), ownerNodeID, statData.getFileSize(),
|
||||
statData.getNumHardlinks(), stripeTargets, FsckStripePatternType_RAID0,
|
||||
ownerNodeID, isBuddyMirrored, true, false);
|
||||
createdInodes.push_back(fsckDirInode);
|
||||
}
|
||||
else
|
||||
failedInodeIDs.push_back(inodeID);
|
||||
}
|
||||
|
||||
ctx.sendResponse(CreateDefDirInodesRespMsg(&failedInodeIDs, &createdInodes) );
|
||||
|
||||
return true;
|
||||
}
|
||||
12
meta/source/net/message/fsck/CreateDefDirInodesMsgEx.h
Normal file
12
meta/source/net/message/fsck/CreateDefDirInodesMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/storage/striping/Raid0Pattern.h>
|
||||
#include <common/net/message/fsck/CreateDefDirInodesMsg.h>
|
||||
#include <common/net/message/fsck/CreateDefDirInodesRespMsg.h>
|
||||
|
||||
class CreateDefDirInodesMsgEx : public CreateDefDirInodesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
77
meta/source/net/message/fsck/CreateEmptyContDirsMsgEx.cpp
Normal file
77
meta/source/net/message/fsck/CreateEmptyContDirsMsgEx.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "CreateEmptyContDirsMsgEx.h"
|
||||
#include <program/Program.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
bool CreateEmptyContDirsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
const char* logContext = "CreateEmptyContDirsMsg incoming";
|
||||
|
||||
App* app = Program::getApp();
|
||||
MetaStore* metaStore = app->getMetaStore();
|
||||
|
||||
StringList failedIDs;
|
||||
|
||||
for (auto iter = items.begin(); iter != items.end(); iter++)
|
||||
{
|
||||
const std::string& dirID = std::get<0>(*iter);
|
||||
const bool isBuddyMirrored = std::get<1>(*iter);
|
||||
|
||||
std::string contentsDirStr = MetaStorageTk::getMetaDirEntryPath(
|
||||
isBuddyMirrored
|
||||
? app->getBuddyMirrorDentriesPath()->str()
|
||||
: app->getDentriesPath()->str(), dirID);
|
||||
|
||||
// create contents directory
|
||||
int mkRes = mkdir(contentsDirStr.c_str(), 0755);
|
||||
|
||||
if ( mkRes != 0 )
|
||||
{ // error
|
||||
LOG(GENERAL, ERR, "Unable to create contents directory.", contentsDirStr, sysErr);
|
||||
failedIDs.push_back(dirID);
|
||||
continue;
|
||||
}
|
||||
|
||||
// create the dirEntryID directory, which allows access to inlined inodes via dirID access
|
||||
std::string contentsDirIDStr = MetaStorageTk::getMetaDirEntryIDPath(contentsDirStr);
|
||||
|
||||
int mkDirIDRes = mkdir(contentsDirIDStr.c_str(), 0755);
|
||||
|
||||
if ( mkDirIDRes != 0 )
|
||||
{ // error
|
||||
LOG(GENERAL, ERR, "Unable to create dirEntryID directory.", contentsDirIDStr, sysErr);
|
||||
failedIDs.push_back(dirID);
|
||||
continue;
|
||||
}
|
||||
|
||||
FileIDLock lock;
|
||||
|
||||
if (isBuddyMirrored)
|
||||
lock = {Program::getApp()->getMirroredSessions()->getEntryLockStore(), dirID, true};
|
||||
|
||||
// update the dir attribs
|
||||
|
||||
DirInode* dirInode = metaStore->referenceDir(dirID, isBuddyMirrored, true);
|
||||
|
||||
if (!dirInode)
|
||||
{
|
||||
LOG(GENERAL, ERR, "Unable to reference directory.", dirID);
|
||||
failedIDs.push_back(dirID);
|
||||
continue;
|
||||
}
|
||||
|
||||
FhgfsOpsErr refreshRes = dirInode->refreshMetaInfo();
|
||||
|
||||
if (refreshRes != FhgfsOpsErr_SUCCESS)
|
||||
{
|
||||
LogContext(logContext).log(Log_NOTICE, "Unable to refresh contents directory metadata: "
|
||||
+ contentsDirStr + ". " + "SysErr: " + System::getErrString());
|
||||
}
|
||||
|
||||
metaStore->releaseDir(dirID);
|
||||
}
|
||||
|
||||
ctx.sendResponse(CreateEmptyContDirsRespMsg(&failedIDs) );
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
12
meta/source/net/message/fsck/CreateEmptyContDirsMsgEx.h
Normal file
12
meta/source/net/message/fsck/CreateEmptyContDirsMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/storage/striping/Raid0Pattern.h>
|
||||
#include <common/net/message/fsck/CreateEmptyContDirsMsg.h>
|
||||
#include <common/net/message/fsck/CreateEmptyContDirsRespMsg.h>
|
||||
|
||||
class CreateEmptyContDirsMsgEx : public CreateEmptyContDirsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
66
meta/source/net/message/fsck/DeleteDirEntriesMsgEx.cpp
Normal file
66
meta/source/net/message/fsck/DeleteDirEntriesMsgEx.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "DeleteDirEntriesMsgEx.h"
|
||||
|
||||
#include <program/Program.h>
|
||||
#include <common/fsck/FsckDirEntry.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
bool DeleteDirEntriesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("DeleteDirEntriesMsgEx");
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
FsckDirEntryList& entries = getEntries();
|
||||
FsckDirEntryList failedEntries;
|
||||
|
||||
for ( FsckDirEntryListIter iter = entries.begin(); iter != entries.end(); iter++ )
|
||||
{
|
||||
const std::string& parentID = iter->getParentDirID();
|
||||
const std::string& entryName = iter->getName();
|
||||
FsckDirEntryType dirEntryType = iter->getEntryType();
|
||||
|
||||
FileIDLock dirLock;
|
||||
ParentNameLock dentryLock;
|
||||
|
||||
if (iter->getIsBuddyMirrored())
|
||||
{
|
||||
dirLock = {entryLockStore, parentID, true};
|
||||
dentryLock = {entryLockStore, parentID, entryName};
|
||||
}
|
||||
|
||||
DirInode* parentDirInode = metaStore->referenceDir(parentID, iter->getIsBuddyMirrored(),
|
||||
true);
|
||||
|
||||
if (!parentDirInode)
|
||||
{
|
||||
log.log(3,"Failed to delete directory entry; ParentID: " + parentID + "; EntryName: " +
|
||||
entryName + " - ParentID does not exist");
|
||||
failedEntries.push_back(*iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
FhgfsOpsErr unlinkRes;
|
||||
|
||||
if (FsckDirEntryType_ISDIR(dirEntryType))
|
||||
unlinkRes = parentDirInode->removeDir(entryName, NULL);
|
||||
else
|
||||
unlinkRes = parentDirInode->unlinkDirEntry(entryName, NULL,
|
||||
DirEntry_UNLINK_ID_AND_FILENAME);
|
||||
|
||||
metaStore->releaseDir(parentID);
|
||||
|
||||
if (unlinkRes != FhgfsOpsErr_SUCCESS )
|
||||
{
|
||||
log.logErr("Failed to delete directory entry; ParentID: " + parentID + "; EntryName: " +
|
||||
entryName + "; Err: " + boost::lexical_cast<std::string>(unlinkRes));
|
||||
failedEntries.push_back(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.sendResponse(DeleteDirEntriesRespMsg(&failedEntries) );
|
||||
|
||||
return true;
|
||||
}
|
||||
12
meta/source/net/message/fsck/DeleteDirEntriesMsgEx.h
Normal file
12
meta/source/net/message/fsck/DeleteDirEntriesMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/NetMessage.h>
|
||||
#include <common/net/message/fsck/DeleteDirEntriesMsg.h>
|
||||
#include <common/net/message/fsck/DeleteDirEntriesRespMsg.h>
|
||||
|
||||
class DeleteDirEntriesMsgEx : public DeleteDirEntriesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
77
meta/source/net/message/fsck/FixInodeOwnersInDentryMsgEx.cpp
Normal file
77
meta/source/net/message/fsck/FixInodeOwnersInDentryMsgEx.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "FixInodeOwnersInDentryMsgEx.h"
|
||||
|
||||
#include <common/storage/striping/Raid0Pattern.h>
|
||||
#include <common/fsck/FsckDirEntry.h>
|
||||
#include <program/Program.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
bool FixInodeOwnersInDentryMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("FixInodeOwnersInDentryMsgEx");
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
FsckDirEntryList& dentries = getDentries();
|
||||
FsckDirEntryList failedEntries;
|
||||
|
||||
FsckDirEntryListIter dentryIter = dentries.begin();
|
||||
NumNodeIDListIter ownerIter = getOwners().begin();
|
||||
|
||||
while (dentryIter != dentries.end() )
|
||||
{
|
||||
const std::string& parentID = dentryIter->getParentDirID();
|
||||
const std::string& entryName = dentryIter->getName();
|
||||
|
||||
ParentNameLock lock;
|
||||
|
||||
if (dentryIter->getIsBuddyMirrored())
|
||||
lock = {entryLockStore, parentID, entryName};
|
||||
|
||||
bool parentDirInodeIsTemp = false;
|
||||
DirInode* parentDirInode = metaStore->referenceDir(parentID,
|
||||
dentryIter->getIsBuddyMirrored(), true);
|
||||
|
||||
// it could be, that parentDirInode does not exist
|
||||
// in fsck we create a temporary inode for this case, so that we can modify the dentry
|
||||
// hopefully, the inode itself will get fixed later
|
||||
if (unlikely(!parentDirInode))
|
||||
{
|
||||
log.log(Log_NOTICE,
|
||||
"Failed to update directory entry. Parent directory could not be "
|
||||
"referenced. parentID: " + parentID + " entryName: " + entryName
|
||||
+ " => Using temporary inode");
|
||||
|
||||
// create temporary inode
|
||||
int mode = S_IFDIR | S_IRWXU;
|
||||
UInt16Vector stripeTargets;
|
||||
Raid0Pattern stripePattern(0, stripeTargets, 0);
|
||||
parentDirInode = new DirInode(parentID, mode, 0, 0,
|
||||
Program::getApp()->getLocalNode().getNumID(), stripePattern,
|
||||
dentryIter->getIsBuddyMirrored());
|
||||
|
||||
parentDirInodeIsTemp = true;
|
||||
}
|
||||
|
||||
FhgfsOpsErr updateRes = parentDirInode->setOwnerNodeID(entryName, *ownerIter);
|
||||
|
||||
if (updateRes != FhgfsOpsErr_SUCCESS )
|
||||
{
|
||||
log.log(Log_WARNING, "Failed to update directory entry. parentID: " + parentID +
|
||||
" entryName: " + entryName);
|
||||
failedEntries.push_back(*dentryIter);
|
||||
}
|
||||
|
||||
if (parentDirInodeIsTemp)
|
||||
SAFE_DELETE(parentDirInode);
|
||||
else
|
||||
metaStore->releaseDir(parentID);
|
||||
|
||||
dentryIter++;
|
||||
ownerIter++;
|
||||
}
|
||||
|
||||
ctx.sendResponse(FixInodeOwnersInDentryRespMsg(&failedEntries) );
|
||||
|
||||
return true;
|
||||
}
|
||||
12
meta/source/net/message/fsck/FixInodeOwnersInDentryMsgEx.h
Normal file
12
meta/source/net/message/fsck/FixInodeOwnersInDentryMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/NetMessage.h>
|
||||
#include <common/net/message/fsck/FixInodeOwnersInDentryMsg.h>
|
||||
#include <common/net/message/fsck/FixInodeOwnersInDentryRespMsg.h>
|
||||
|
||||
class FixInodeOwnersInDentryMsgEx : public FixInodeOwnersInDentryMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
51
meta/source/net/message/fsck/FixInodeOwnersMsgEx.cpp
Normal file
51
meta/source/net/message/fsck/FixInodeOwnersMsgEx.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "FixInodeOwnersMsgEx.h"
|
||||
|
||||
#include <common/fsck/FsckDirEntry.h>
|
||||
#include <program/Program.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
bool FixInodeOwnersMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
const char* logContext = "FixInodeOwnersMsgEx incoming";
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
FsckDirInodeList& inodes = getInodes();
|
||||
FsckDirInodeList failedInodes;
|
||||
|
||||
for ( FsckDirInodeListIter iter = inodes.begin(); iter != inodes.end(); iter++ )
|
||||
{
|
||||
const std::string& entryID = iter->getID();
|
||||
NumNodeID ownerNodeID = iter->getOwnerNodeID();
|
||||
|
||||
FileIDLock lock;
|
||||
|
||||
if (iter->getIsBuddyMirrored())
|
||||
lock = {entryLockStore, entryID, true};
|
||||
|
||||
DirInode* dirInode = metaStore->referenceDir(entryID, iter->getIsBuddyMirrored(), true);
|
||||
|
||||
if (unlikely(!dirInode))
|
||||
{
|
||||
LogContext(logContext).log(Log_WARNING, "Failed to update directory inode. Inode could"
|
||||
" not be referenced. entryID: " + entryID);
|
||||
continue; // continue to next entry
|
||||
}
|
||||
|
||||
bool updateRes = dirInode->setOwnerNodeID(ownerNodeID);
|
||||
|
||||
metaStore->releaseDir(entryID);
|
||||
|
||||
if (!updateRes)
|
||||
{
|
||||
LogContext(logContext).log(Log_WARNING, "Failed to update directory inode. entryID: "
|
||||
+ entryID);
|
||||
failedInodes.push_back(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.sendResponse(FixInodeOwnersRespMsg(&failedInodes) );
|
||||
|
||||
return true;
|
||||
}
|
||||
12
meta/source/net/message/fsck/FixInodeOwnersMsgEx.h
Normal file
12
meta/source/net/message/fsck/FixInodeOwnersMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/NetMessage.h>
|
||||
#include <common/net/message/fsck/FixInodeOwnersMsg.h>
|
||||
#include <common/net/message/fsck/FixInodeOwnersRespMsg.h>
|
||||
|
||||
class FixInodeOwnersMsgEx : public FixInodeOwnersMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
34
meta/source/net/message/fsck/FsckSetEventLoggingMsgEx.cpp
Normal file
34
meta/source/net/message/fsck/FsckSetEventLoggingMsgEx.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <components/ModificationEventFlusher.h>
|
||||
#include <program/Program.h>
|
||||
#include "FsckSetEventLoggingMsgEx.h"
|
||||
|
||||
bool FsckSetEventLoggingMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("FsckSetEventLoggingMsg incoming");
|
||||
|
||||
App* app = Program::getApp();
|
||||
ModificationEventFlusher* flusher = app->getModificationEventFlusher();
|
||||
|
||||
bool result;
|
||||
bool loggingEnabled;
|
||||
bool missedEvents;
|
||||
|
||||
bool enableLogging = this->getEnableLogging();
|
||||
|
||||
if (enableLogging)
|
||||
{
|
||||
loggingEnabled = flusher->enableLogging(getPortUDP(), getNicList(), getForceRestart());
|
||||
result = true; // (always true when logging is enabled)
|
||||
missedEvents = true; // (value ignored when logging is enabled)
|
||||
}
|
||||
else
|
||||
{ // disable logging
|
||||
result = flusher->disableLogging();
|
||||
loggingEnabled = false; // (value ignored when logging is disabled)
|
||||
missedEvents = flusher->getFsckMissedEvent();
|
||||
}
|
||||
|
||||
ctx.sendResponse(FsckSetEventLoggingRespMsg(result, loggingEnabled, missedEvents));
|
||||
|
||||
return true;
|
||||
}
|
||||
11
meta/source/net/message/fsck/FsckSetEventLoggingMsgEx.h
Normal file
11
meta/source/net/message/fsck/FsckSetEventLoggingMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/fsck/FsckSetEventLoggingMsg.h>
|
||||
#include <common/net/message/fsck/FsckSetEventLoggingRespMsg.h>
|
||||
|
||||
class FsckSetEventLoggingMsgEx : public FsckSetEventLoggingMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
108
meta/source/net/message/fsck/LinkToLostAndFoundMsgEx.cpp
Normal file
108
meta/source/net/message/fsck/LinkToLostAndFoundMsgEx.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "LinkToLostAndFoundMsgEx.h"
|
||||
|
||||
#include <common/net/message/fsck/RemoveInodesMsg.h>
|
||||
#include <common/net/message/fsck/RemoveInodesRespMsg.h>
|
||||
#include <program/Program.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
bool LinkToLostAndFoundMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
if (FsckDirEntryType_ISDIR(this->getEntryType()))
|
||||
{
|
||||
FsckDirEntryList createdDirEntries;
|
||||
FsckDirInodeList failedInodes;
|
||||
linkDirInodes(&failedInodes, &createdDirEntries);
|
||||
ctx.sendResponse(LinkToLostAndFoundRespMsg(&failedInodes, &createdDirEntries) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(COMMUNICATION, ERR, "LinkToLostAndFoundMsg received for non-inlined file inode.",
|
||||
("from", ctx.peerName()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LinkToLostAndFoundMsgEx::linkDirInodes(FsckDirInodeList* outFailedInodes,
|
||||
FsckDirEntryList* outCreatedDirEntries)
|
||||
{
|
||||
const char* logContext = "LinkToLostAndFoundMsgEx (linkDirInodes)";
|
||||
|
||||
NumNodeID localNodeNumID = Program::getApp()->getLocalNode().getNumID();
|
||||
|
||||
FsckDirInodeList& dirInodes = getDirInodes();
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
EntryInfo* lostAndFoundInfo = this->getLostAndFoundInfo();
|
||||
DirInode* lostAndFoundDir = metaStore->referenceDir(lostAndFoundInfo->getEntryID(),
|
||||
lostAndFoundInfo->getIsBuddyMirrored(), true);
|
||||
|
||||
if ( !lostAndFoundDir )
|
||||
{
|
||||
*outFailedInodes = dirInodes;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( FsckDirInodeListIter iter = dirInodes.begin(); iter != dirInodes.end(); iter++ )
|
||||
{
|
||||
const std::string& entryID = iter->getID();
|
||||
NumNodeID ownerNodeID = iter->getOwnerNodeID();
|
||||
DirEntryType entryType = DirEntryType_DIRECTORY;
|
||||
DirEntry newDirEntry(entryType, entryID, entryID, ownerNodeID);
|
||||
|
||||
FileIDLock lock;
|
||||
|
||||
if (iter->getIsBuddyMirrored())
|
||||
{
|
||||
lock = {entryLockStore, entryID, true};
|
||||
newDirEntry.setBuddyMirrorFeatureFlag();
|
||||
}
|
||||
|
||||
bool makeRes = lostAndFoundDir->makeDirEntry(newDirEntry);
|
||||
|
||||
// stat the new file to get device and inode information
|
||||
std::string filename = MetaStorageTk::getMetaDirEntryPath(
|
||||
lostAndFoundInfo->getIsBuddyMirrored()
|
||||
? Program::getApp()->getBuddyMirrorDentriesPath()->str()
|
||||
: Program::getApp()->getDentriesPath()->str(),
|
||||
lostAndFoundInfo->getEntryID()) + "/" + entryID;
|
||||
|
||||
struct stat statBuf;
|
||||
|
||||
int statRes = stat(filename.c_str(), &statBuf);
|
||||
|
||||
int saveDevice;
|
||||
uint64_t saveInode;
|
||||
if ( likely(!statRes) )
|
||||
{
|
||||
saveDevice = statBuf.st_dev;
|
||||
saveInode = statBuf.st_ino;
|
||||
}
|
||||
else
|
||||
{
|
||||
saveDevice = 0;
|
||||
saveInode = 0;
|
||||
LogContext(logContext).log(Log_CRITICAL,
|
||||
"Could not stat dir entry file; entryID: " + entryID + ";filename: " + filename);
|
||||
}
|
||||
|
||||
if ( makeRes != FhgfsOpsErr_SUCCESS )
|
||||
outFailedInodes->push_back(*iter);
|
||||
else
|
||||
{
|
||||
std::string parentID = lostAndFoundInfo->getEntryID();
|
||||
FsckDirEntry newFsckDirEntry(entryID, entryID, parentID, localNodeNumID,
|
||||
ownerNodeID, FsckDirEntryType_DIRECTORY, false, localNodeNumID,
|
||||
saveDevice, saveInode, lostAndFoundInfo->getIsBuddyMirrored());
|
||||
outCreatedDirEntries->push_back(newFsckDirEntry);
|
||||
}
|
||||
}
|
||||
|
||||
lostAndFoundDir->refreshMetaInfo();
|
||||
metaStore->releaseDir(lostAndFoundInfo->getEntryID() );
|
||||
}
|
||||
}
|
||||
24
meta/source/net/message/fsck/LinkToLostAndFoundMsgEx.h
Normal file
24
meta/source/net/message/fsck/LinkToLostAndFoundMsgEx.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/NetMessage.h>
|
||||
#include <common/net/message/fsck/LinkToLostAndFoundMsg.h>
|
||||
#include <common/net/message/fsck/LinkToLostAndFoundRespMsg.h>
|
||||
#include <common/net/message/storage/creating/MkDirMsg.h>
|
||||
#include <common/net/message/storage/creating/MkDirRespMsg.h>
|
||||
#include <common/storage/StorageErrors.h>
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
class LinkToLostAndFoundMsgEx : public LinkToLostAndFoundMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
|
||||
private:
|
||||
void linkDirInodes(FsckDirInodeList* outFailedInodes, FsckDirEntryList* outCreatedDirEntries);
|
||||
void linkFileInodes(FsckFileInodeList* outFailedInodes,
|
||||
FsckDirEntryList* outCreatedDirEntries);
|
||||
|
||||
FhgfsOpsErr deleteInode(std::string& entryID, uint16_t ownerNodeID);
|
||||
};
|
||||
|
||||
141
meta/source/net/message/fsck/RecreateDentriesMsgEx.cpp
Normal file
141
meta/source/net/message/fsck/RecreateDentriesMsgEx.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "RecreateDentriesMsgEx.h"
|
||||
|
||||
#include <common/fsck/FsckDirEntry.h>
|
||||
#include <common/fsck/FsckFsID.h>
|
||||
#include <program/Program.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
bool RecreateDentriesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("RecreateDentriesMsgEx");
|
||||
|
||||
App* app = Program::getApp();
|
||||
MetaStore* metaStore = app->getMetaStore();
|
||||
|
||||
EntryLockStore* entryLockStore = app->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
FsckFsIDList& fsIDs = getFsIDs();
|
||||
FsckFsIDList failedCreates;
|
||||
FsckDirEntryList createdDentries;
|
||||
FsckFileInodeList createdInodes;
|
||||
|
||||
for ( FsckFsIDListIter iter = fsIDs.begin(); iter != fsIDs.end(); iter++ )
|
||||
{
|
||||
NumNodeID localNodeID = iter->getIsBuddyMirrored()
|
||||
? NumNodeID(app->getMetaBuddyGroupMapper()->getLocalGroupID())
|
||||
: app->getLocalNodeNumID();
|
||||
|
||||
std::string parentPath = MetaStorageTk::getMetaDirEntryPath(
|
||||
iter->getIsBuddyMirrored()
|
||||
? app->getBuddyMirrorDentriesPath()->str()
|
||||
: app->getDentriesPath()->str(), iter->getParentDirID());
|
||||
|
||||
std::string dirEntryIDFilePath = MetaStorageTk::getMetaDirEntryIDPath(parentPath) + "/"
|
||||
+ iter->getID();
|
||||
|
||||
// the name is lost, so we take the ID as new name
|
||||
std::string dirEntryNameFilePath = parentPath + "/" + iter->getID();
|
||||
|
||||
// before we link, let's see if we can open the parent dir, otherwise we should not mess
|
||||
// around here
|
||||
const std::string& dirID = iter->getParentDirID();
|
||||
|
||||
FileIDLock dirLock;
|
||||
ParentNameLock dentryLock;
|
||||
|
||||
if (iter->getIsBuddyMirrored())
|
||||
{
|
||||
dirLock = {entryLockStore, dirID, true};
|
||||
dentryLock = {entryLockStore, dirID, iter->getID()};
|
||||
}
|
||||
|
||||
DirInode* parentDirInode = metaStore->referenceDir(dirID, iter->getIsBuddyMirrored(), false);
|
||||
|
||||
if (!parentDirInode)
|
||||
{
|
||||
log.logErr("Unable to reference parent directory; ID: " + iter->getParentDirID());
|
||||
failedCreates.push_back(*iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
// link the dentry-by-name file
|
||||
int linkRes = link(dirEntryIDFilePath.c_str(), dirEntryNameFilePath.c_str());
|
||||
|
||||
if ( linkRes )
|
||||
{
|
||||
// error occured while linking
|
||||
log.logErr(
|
||||
"Failed to link dentry file; ParentID: " + iter->getParentDirID() + "; ID: "
|
||||
+ iter->getID());
|
||||
failedCreates.push_back(*iter);
|
||||
|
||||
metaStore->releaseDir(dirID);
|
||||
continue;
|
||||
}
|
||||
|
||||
// linking was OK => gather dentry (and inode) data, so fsck can add it
|
||||
|
||||
DirEntry dirEntry(iter->getID());
|
||||
bool getRes = parentDirInode->getDentry(iter->getID(), dirEntry);
|
||||
|
||||
if (!getRes)
|
||||
{
|
||||
log.logErr(
|
||||
"Could not read the created dentry file; ParentID: " + iter->getParentDirID() + "; ID: "
|
||||
+ iter->getID());
|
||||
failedCreates.push_back(*iter);
|
||||
|
||||
metaStore->releaseDir(dirID);
|
||||
continue;
|
||||
}
|
||||
|
||||
// create the FsckDirEntry
|
||||
FsckDirEntry fsckDirEntry(dirEntry.getID(), dirEntry.getName(), iter->getParentDirID(),
|
||||
localNodeID, localNodeID,
|
||||
FsckTk::DirEntryTypeToFsckDirEntryType(dirEntry.getEntryType()), true, localNodeID,
|
||||
iter->getSaveDevice(), iter->getSaveInode(), iter->getIsBuddyMirrored());
|
||||
createdDentries.push_back(fsckDirEntry);
|
||||
|
||||
// inlined inode data should be present, because otherwise dentry-by-id file would not
|
||||
// exist, and we could not get this far
|
||||
FileInodeStoreData* inodeData = dirEntry.getInodeStoreData();
|
||||
|
||||
if ( inodeData )
|
||||
{
|
||||
int pathInfoFlags;
|
||||
|
||||
if (inodeData->getOrigFeature() == FileInodeOrigFeature_TRUE)
|
||||
pathInfoFlags = PATHINFO_FEATURE_ORIG;
|
||||
else
|
||||
pathInfoFlags = PATHINFO_FEATURE_ORIG_UNKNOWN;
|
||||
|
||||
PathInfo pathInfo(inodeData->getOrigUID(), inodeData->getOrigParentEntryID(),
|
||||
pathInfoFlags);
|
||||
|
||||
UInt16Vector targetIDs;
|
||||
unsigned chunkSize;
|
||||
FsckStripePatternType fsckStripePatternType = FsckTk::stripePatternToFsckStripePattern(
|
||||
inodeData->getPattern(), &chunkSize, &targetIDs);
|
||||
|
||||
FsckFileInode fsckFileInode(inodeData->getEntryID(), iter->getParentDirID(),
|
||||
localNodeID, pathInfo, inodeData->getInodeStatData(),
|
||||
inodeData->getInodeStatData()->getNumBlocks(), targetIDs, fsckStripePatternType,
|
||||
chunkSize, localNodeID, iter->getSaveInode(), iter->getSaveDevice(), true,
|
||||
iter->getIsBuddyMirrored(), true, false);
|
||||
|
||||
createdInodes.push_back(fsckFileInode);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.logErr(
|
||||
"No inlined inode data found; parentID: " + iter->getParentDirID() + "; ID: "
|
||||
+ iter->getID());
|
||||
}
|
||||
|
||||
metaStore->releaseDir(dirID);
|
||||
}
|
||||
|
||||
ctx.sendResponse(RecreateDentriesRespMsg(&failedCreates, &createdDentries, &createdInodes) );
|
||||
|
||||
return true;
|
||||
}
|
||||
12
meta/source/net/message/fsck/RecreateDentriesMsgEx.h
Normal file
12
meta/source/net/message/fsck/RecreateDentriesMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/NetMessage.h>
|
||||
#include <common/net/message/fsck/RecreateDentriesMsg.h>
|
||||
#include <common/net/message/fsck/RecreateDentriesRespMsg.h>
|
||||
|
||||
class RecreateDentriesMsgEx : public RecreateDentriesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
65
meta/source/net/message/fsck/RecreateFsIDsMsgEx.cpp
Normal file
65
meta/source/net/message/fsck/RecreateFsIDsMsgEx.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "RecreateFsIDsMsgEx.h"
|
||||
|
||||
#include <common/fsck/FsckDirEntry.h>
|
||||
#include <program/Program.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
bool RecreateFsIDsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
LogContext log("RecreateFsIDsMsgEx");
|
||||
|
||||
FsckDirEntryList& entries = getEntries();
|
||||
FsckDirEntryList failedEntries;
|
||||
|
||||
for ( FsckDirEntryListIter iter = entries.begin(); iter != entries.end(); iter++ )
|
||||
{
|
||||
const std::string& parentID = iter->getParentDirID();
|
||||
const std::string& entryName = iter->getName();
|
||||
const std::string& entryID = iter->getID();
|
||||
|
||||
std::string dirEntryPath = MetaStorageTk::getMetaDirEntryPath(
|
||||
iter->getIsBuddyMirrored()
|
||||
? Program::getApp()->getBuddyMirrorDentriesPath()->str()
|
||||
: Program::getApp()->getDentriesPath()->str(), parentID);
|
||||
|
||||
std::string dirEntryIDFilePath = MetaStorageTk::getMetaDirEntryIDPath(dirEntryPath) +
|
||||
"/" + entryID;
|
||||
|
||||
std::string dirEntryNameFilePath = dirEntryPath + "/" + entryName;
|
||||
|
||||
FileIDLock dirLock(entryLockStore, parentID, true);
|
||||
ParentNameLock dentryLock(entryLockStore, parentID, entryName);
|
||||
FileIDLock fileLock(entryLockStore, entryID, true);
|
||||
|
||||
// delete the old dentry-by-id file link (if one existed)
|
||||
int removeRes = unlink(dirEntryIDFilePath.c_str());
|
||||
|
||||
if ( (removeRes) && (errno != ENOENT) )
|
||||
{
|
||||
log.logErr(
|
||||
"Failed to recreate dentry-by-id file for directory entry; ParentID: " + parentID
|
||||
+ "; EntryName: " + entryName
|
||||
+ " - Could not delete old, faulty dentry-by-id file link");
|
||||
failedEntries.push_back(*iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
// link a new one
|
||||
int linkRes = link(dirEntryNameFilePath.c_str(), dirEntryIDFilePath.c_str());
|
||||
|
||||
if ( linkRes )
|
||||
{
|
||||
log.logErr(
|
||||
"Failed to recreate dentry-by-id file for directory entry; ParentID: " + parentID
|
||||
+ "; EntryName: " + entryName + " - File could not be linked");
|
||||
failedEntries.push_back(*iter);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.sendResponse(RecreateFsIDsRespMsg(&failedEntries) );
|
||||
|
||||
return true;
|
||||
}
|
||||
12
meta/source/net/message/fsck/RecreateFsIDsMsgEx.h
Normal file
12
meta/source/net/message/fsck/RecreateFsIDsMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/NetMessage.h>
|
||||
#include <common/net/message/fsck/RecreateFsIDsMsg.h>
|
||||
#include <common/net/message/fsck/RecreateFsIDsRespMsg.h>
|
||||
|
||||
class RecreateFsIDsMsgEx : public RecreateFsIDsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
44
meta/source/net/message/fsck/RemoveInodesMsgEx.cpp
Normal file
44
meta/source/net/message/fsck/RemoveInodesMsgEx.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <program/Program.h>
|
||||
#include <common/net/message/fsck/RemoveInodesRespMsg.h>
|
||||
#include <common/toolkit/ZipIterator.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
#include "RemoveInodesMsgEx.h"
|
||||
|
||||
|
||||
bool RemoveInodesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
StringList failedIDList;
|
||||
|
||||
for (auto it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
const std::string& entryID = std::get<0>(*it);
|
||||
const DirEntryType entryType = std::get<1>(*it);
|
||||
const bool isBuddyMirrored = std::get<2>(*it);
|
||||
FhgfsOpsErr rmRes;
|
||||
|
||||
FileIDLock dirLock;
|
||||
FileIDLock fileLock;
|
||||
|
||||
if (entryType == DirEntryType_DIRECTORY)
|
||||
{
|
||||
dirLock = {entryLockStore, entryID, true};
|
||||
rmRes = metaStore->removeDirInode(entryID, isBuddyMirrored);
|
||||
}
|
||||
else
|
||||
{
|
||||
fileLock = {entryLockStore, entryID, true};
|
||||
rmRes = metaStore->fsckUnlinkFileInode(entryID, isBuddyMirrored);
|
||||
}
|
||||
|
||||
if (rmRes != FhgfsOpsErr_SUCCESS)
|
||||
failedIDList.push_back(entryID);
|
||||
}
|
||||
|
||||
ctx.sendResponse(RemoveInodesRespMsg(std::move(failedIDList)));
|
||||
|
||||
return true;
|
||||
}
|
||||
10
meta/source/net/message/fsck/RemoveInodesMsgEx.h
Normal file
10
meta/source/net/message/fsck/RemoveInodesMsgEx.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/fsck/RemoveInodesMsg.h>
|
||||
|
||||
class RemoveInodesMsgEx : public RemoveInodesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
269
meta/source/net/message/fsck/RetrieveDirEntriesMsgEx.cpp
Normal file
269
meta/source/net/message/fsck/RetrieveDirEntriesMsgEx.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
#include "RetrieveDirEntriesMsgEx.h"
|
||||
|
||||
#include <common/storage/striping/Raid0Pattern.h>
|
||||
#include <net/msghelpers/MsgHelperStat.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
bool RetrieveDirEntriesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("Incoming RetrieveDirEntriesMsg");
|
||||
|
||||
unsigned hashDirNum = getHashDirNum();
|
||||
std::string currentContDirID = getCurrentContDirID();
|
||||
unsigned maxOutEntries = getMaxOutEntries();
|
||||
|
||||
int64_t lastContDirOffset = getLastContDirOffset();
|
||||
int64_t lastHashDirOffset = getLastHashDirOffset();
|
||||
int64_t newHashDirOffset;
|
||||
int64_t newContDirOffset;
|
||||
|
||||
FsckContDirList contDirsOutgoing;
|
||||
FsckDirEntryList dirEntriesOutgoing;
|
||||
FsckFileInodeList inlinedFileInodesOutgoing;
|
||||
|
||||
unsigned readOutEntries = 0;
|
||||
|
||||
NumNodeID localNodeNumID = getIsBuddyMirrored()
|
||||
? NumNodeID(Program::getApp()->getMetaBuddyGroupMapper()->getLocalGroupID())
|
||||
: Program::getApp()->getLocalNode().getNumID();
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
MirrorBuddyGroupMapper* bgm = Program::getApp()->getMetaBuddyGroupMapper();
|
||||
|
||||
if (getIsBuddyMirrored() &&
|
||||
(bgm->getLocalBuddyGroup().secondTargetID
|
||||
== Program::getApp()->getLocalNode().getNumID().val()
|
||||
|| bgm->getLocalGroupID() == 0))
|
||||
{
|
||||
ctx.sendResponse(
|
||||
RetrieveDirEntriesRespMsg(&contDirsOutgoing, &dirEntriesOutgoing,
|
||||
&inlinedFileInodesOutgoing, currentContDirID, lastHashDirOffset, lastContDirOffset));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasNext;
|
||||
|
||||
if ( currentContDirID.empty() )
|
||||
{
|
||||
hasNext = StorageTkEx::getNextContDirID(hashDirNum, getIsBuddyMirrored(), lastHashDirOffset,
|
||||
¤tContDirID, &newHashDirOffset);
|
||||
if ( hasNext )
|
||||
{
|
||||
lastHashDirOffset = newHashDirOffset;
|
||||
// we found a new .cont directory => send it to fsck
|
||||
FsckContDir contDir(currentContDirID, localNodeNumID, getIsBuddyMirrored());
|
||||
contDirsOutgoing.push_back(contDir);
|
||||
}
|
||||
}
|
||||
else
|
||||
hasNext = true;
|
||||
|
||||
while ( hasNext )
|
||||
{
|
||||
std::string parentID = currentContDirID;
|
||||
|
||||
unsigned remainingOutNames = maxOutEntries - readOutEntries;
|
||||
StringList entryNames;
|
||||
|
||||
bool parentDirInodeIsTemp = false;
|
||||
DirInode* parentDirInode = metaStore->referenceDir(parentID, getIsBuddyMirrored(), true);
|
||||
|
||||
// it could be, that parentDirInode does not exist
|
||||
// in fsck we create a temporary inode for this case, so that we can modify the dentry
|
||||
// hopefully, the inode itself will get fixed later
|
||||
if ( unlikely(!parentDirInode) )
|
||||
{
|
||||
log.log(
|
||||
Log_NOTICE,
|
||||
"Could not reference directory. EntryID: " + parentID
|
||||
+ " => using temporary directory inode ");
|
||||
|
||||
// create temporary inode
|
||||
int mode = S_IFDIR | S_IRWXU;
|
||||
UInt16Vector stripeTargets;
|
||||
Raid0Pattern stripePattern(0, stripeTargets, 0);
|
||||
parentDirInode = new DirInode(parentID, mode, 0, 0,
|
||||
Program::getApp()->getLocalNode().getNumID(), stripePattern, getIsBuddyMirrored());
|
||||
|
||||
parentDirInodeIsTemp = true;
|
||||
}
|
||||
|
||||
if ( parentDirInode->listIncremental(lastContDirOffset, remainingOutNames, &entryNames,
|
||||
&newContDirOffset) == FhgfsOpsErr_SUCCESS )
|
||||
{
|
||||
lastContDirOffset = newContDirOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.log(Log_WARNING, "Could not list contents of directory. EntryID: " + parentID);
|
||||
}
|
||||
|
||||
// actually process the entries
|
||||
for ( StringListIter namesIter = entryNames.begin(); namesIter != entryNames.end();
|
||||
namesIter++ )
|
||||
{
|
||||
std::string filename = MetaStorageTk::getMetaDirEntryPath(
|
||||
getIsBuddyMirrored()
|
||||
? Program::getApp()->getBuddyMirrorDentriesPath()->str()
|
||||
: Program::getApp()->getDentriesPath()->str(), parentID) + "/" + *namesIter;
|
||||
|
||||
// create a EntryInfo and put the information into an FsckDirEntry object
|
||||
EntryInfo entryInfo;
|
||||
FileInodeStoreData inodeDiskData;
|
||||
bool hasInlinedInode = false;
|
||||
|
||||
int32_t saveDevice = 0;
|
||||
uint64_t saveInode = 0;
|
||||
|
||||
auto [getEntryRes, isFileOpen] = metaStore->getEntryData(parentDirInode, *namesIter, &entryInfo,
|
||||
&inodeDiskData);
|
||||
|
||||
if (getEntryRes == FhgfsOpsErr_SUCCESS ||
|
||||
getEntryRes == FhgfsOpsErr_DYNAMICATTRIBSOUTDATED )
|
||||
{
|
||||
DirEntryType entryType = entryInfo.getEntryType();
|
||||
|
||||
const std::string& dentryID = entryInfo.getEntryID();
|
||||
const std::string& dentryName = *namesIter;
|
||||
NumNodeID dentryOwnerID = entryInfo.getOwnerNodeID();
|
||||
FsckDirEntryType fsckEntryType = FsckTk::DirEntryTypeToFsckDirEntryType(entryType);
|
||||
|
||||
// stat the file to get device and inode information
|
||||
struct stat statBuf;
|
||||
|
||||
int statRes = stat(filename.c_str(), &statBuf);
|
||||
|
||||
if (likely(!statRes))
|
||||
{
|
||||
saveDevice = statBuf.st_dev;
|
||||
saveInode = statBuf.st_ino;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.log(Log_CRITICAL, "Could not stat dir entry file; entryID: " + dentryID
|
||||
+ ";filename: " + filename);
|
||||
}
|
||||
|
||||
if ( (DirEntryType_ISFILE(entryType)) && (entryInfo.getIsInlined() ) )
|
||||
{
|
||||
hasInlinedInode = true;
|
||||
}
|
||||
|
||||
FsckDirEntry fsckDirEntry(dentryID, dentryName, parentID, localNodeNumID,
|
||||
dentryOwnerID, fsckEntryType, hasInlinedInode, localNodeNumID,
|
||||
saveDevice, saveInode, entryInfo.getIsBuddyMirrored());
|
||||
|
||||
dirEntriesOutgoing.push_back(fsckDirEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.log(Log_WARNING, "Unable to create dir entry from entry with name " + *namesIter
|
||||
+ " in directory with ID " + parentID);
|
||||
}
|
||||
|
||||
// now, if the inode data is inlined we create an fsck inode object here
|
||||
if ( hasInlinedInode )
|
||||
{
|
||||
std::string inodeID = inodeDiskData.getEntryID();
|
||||
|
||||
int pathInfoFlag;
|
||||
if (inodeDiskData.getOrigFeature() == FileInodeOrigFeature_TRUE)
|
||||
pathInfoFlag = PATHINFO_FEATURE_ORIG;
|
||||
else
|
||||
pathInfoFlag = PATHINFO_FEATURE_ORIG_UNKNOWN;
|
||||
|
||||
unsigned origUID = inodeDiskData.getOrigUID();
|
||||
std::string origParentEntryID = inodeDiskData.getOrigParentEntryID();
|
||||
PathInfo pathInfo(origUID, origParentEntryID, pathInfoFlag);
|
||||
|
||||
unsigned userID;
|
||||
unsigned groupID;
|
||||
|
||||
int64_t fileSize;
|
||||
unsigned numHardLinks;
|
||||
uint64_t numBlocks;
|
||||
|
||||
StatData* statData;
|
||||
StatData updatedStatData;
|
||||
|
||||
if (getEntryRes == FhgfsOpsErr_SUCCESS)
|
||||
statData = inodeDiskData.getInodeStatData();
|
||||
else
|
||||
{
|
||||
FhgfsOpsErr statRes = MsgHelperStat::stat(&entryInfo, true, getMsgHeaderUserID(),
|
||||
updatedStatData);
|
||||
|
||||
if (statRes == FhgfsOpsErr_SUCCESS)
|
||||
statData = &updatedStatData;
|
||||
else
|
||||
statData = NULL;
|
||||
}
|
||||
|
||||
if ( statData )
|
||||
{
|
||||
userID = statData->getUserID();
|
||||
groupID = statData->getGroupID();
|
||||
fileSize = statData->getFileSize();
|
||||
numHardLinks = statData->getNumHardlinks();
|
||||
numBlocks = statData->getNumBlocks();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.logErr(std::string("Unable to get stat data of inlined file inode: ") + inodeID
|
||||
+ ". SysErr: " + System::getErrString());
|
||||
userID = 0;
|
||||
groupID = 0;
|
||||
fileSize = 0;
|
||||
numHardLinks = 0;
|
||||
numBlocks = 0;
|
||||
}
|
||||
|
||||
UInt16Vector stripeTargets;
|
||||
unsigned chunkSize;
|
||||
FsckStripePatternType stripePatternType = FsckTk::stripePatternToFsckStripePattern(
|
||||
inodeDiskData.getPattern(), &chunkSize, &stripeTargets);
|
||||
|
||||
FsckFileInode fileInode(inodeID, parentID, localNodeNumID, pathInfo, userID, groupID,
|
||||
fileSize, numHardLinks, numBlocks, stripeTargets, stripePatternType, chunkSize,
|
||||
localNodeNumID, saveInode, saveDevice, true, entryInfo.getIsBuddyMirrored(),
|
||||
true, inodeDiskData.getIsBuddyMirrored() != getIsBuddyMirrored());
|
||||
|
||||
inlinedFileInodesOutgoing.push_back(fileInode);
|
||||
}
|
||||
}
|
||||
|
||||
if ( parentDirInodeIsTemp )
|
||||
SAFE_DELETE(parentDirInode);
|
||||
else
|
||||
metaStore->releaseDir(parentID);
|
||||
|
||||
if ( entryNames.size() < remainingOutNames )
|
||||
{
|
||||
// directory is at the end => proceed with next
|
||||
hasNext = StorageTkEx::getNextContDirID(hashDirNum, getIsBuddyMirrored(),
|
||||
lastHashDirOffset, ¤tContDirID, &newHashDirOffset);
|
||||
|
||||
if ( hasNext )
|
||||
{
|
||||
lastHashDirOffset = newHashDirOffset;
|
||||
lastContDirOffset = 0;
|
||||
|
||||
readOutEntries += entryNames.size();
|
||||
|
||||
// we found a new .cont directory => send it to fsck
|
||||
FsckContDir contDir(currentContDirID, localNodeNumID, getIsBuddyMirrored());
|
||||
contDirsOutgoing.push_back(contDir);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// there are more to come, but we need to exit the loop now, because maxCount is reached
|
||||
hasNext = false;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.sendResponse(
|
||||
RetrieveDirEntriesRespMsg(&contDirsOutgoing, &dirEntriesOutgoing,
|
||||
&inlinedFileInodesOutgoing, currentContDirID, lastHashDirOffset, lastContDirOffset) );
|
||||
|
||||
return true;
|
||||
}
|
||||
11
meta/source/net/message/fsck/RetrieveDirEntriesMsgEx.h
Normal file
11
meta/source/net/message/fsck/RetrieveDirEntriesMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/fsck/RetrieveDirEntriesMsg.h>
|
||||
#include <common/net/message/fsck/RetrieveDirEntriesRespMsg.h>
|
||||
|
||||
class RetrieveDirEntriesMsgEx : public RetrieveDirEntriesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
166
meta/source/net/message/fsck/RetrieveFsIDsMsgEx.cpp
Normal file
166
meta/source/net/message/fsck/RetrieveFsIDsMsgEx.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "RetrieveFsIDsMsgEx.h"
|
||||
|
||||
#include <common/storage/striping/Raid0Pattern.h>
|
||||
#include <common/threading/SafeRWLock.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
bool RetrieveFsIDsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("Incoming RetrieveFsIDsMsg");
|
||||
|
||||
App* app = Program::getApp();
|
||||
MetaStore* metaStore = app->getMetaStore();
|
||||
|
||||
unsigned hashDirNum = getHashDirNum();
|
||||
bool buddyMirrored = getBuddyMirrored();
|
||||
std::string currentContDirID = getCurrentContDirID();
|
||||
unsigned maxOutIDs = getMaxOutIDs();
|
||||
|
||||
int64_t lastContDirOffset = getLastContDirOffset();
|
||||
int64_t lastHashDirOffset = getLastHashDirOffset();
|
||||
int64_t newHashDirOffset;
|
||||
|
||||
FsckFsIDList fsIDsOutgoing;
|
||||
|
||||
unsigned readOutIDs = 0;
|
||||
|
||||
NumNodeID localNodeNumID = buddyMirrored
|
||||
? NumNodeID(Program::getApp()->getMetaBuddyGroupMapper()->getLocalGroupID())
|
||||
: Program::getApp()->getLocalNode().getNumID();
|
||||
MirrorBuddyGroupMapper* bgm = Program::getApp()->getMetaBuddyGroupMapper();
|
||||
|
||||
if (buddyMirrored &&
|
||||
(bgm->getLocalBuddyGroup().secondTargetID == app->getLocalNode().getNumID().val()
|
||||
|| bgm->getLocalGroupID() == 0))
|
||||
{
|
||||
ctx.sendResponse(
|
||||
RetrieveFsIDsRespMsg(&fsIDsOutgoing, currentContDirID, lastHashDirOffset,
|
||||
lastContDirOffset));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasNext;
|
||||
|
||||
if ( currentContDirID.empty() )
|
||||
{
|
||||
hasNext = StorageTkEx::getNextContDirID(hashDirNum, buddyMirrored, lastHashDirOffset,
|
||||
¤tContDirID, &newHashDirOffset);
|
||||
if ( hasNext )
|
||||
lastHashDirOffset = newHashDirOffset;
|
||||
}
|
||||
else
|
||||
hasNext = true;
|
||||
|
||||
while ( hasNext )
|
||||
{
|
||||
std::string parentID = currentContDirID;
|
||||
std::string idPath = MetaStorageTk::getMetaDirEntryIDPath(
|
||||
MetaStorageTk::getMetaDirEntryPath(
|
||||
buddyMirrored
|
||||
? app->getBuddyMirrorDentriesPath()->str()
|
||||
: app->getDentriesPath()->str(),
|
||||
parentID));
|
||||
|
||||
bool parentDirInodeIsTemp = false;
|
||||
StringList outNames;
|
||||
int64_t outNewServerOffset;
|
||||
ListIncExOutArgs outArgs(&outNames, NULL, NULL, NULL, &outNewServerOffset);
|
||||
|
||||
FhgfsOpsErr listRes;
|
||||
|
||||
unsigned remainingOutIDs = maxOutIDs - readOutIDs;
|
||||
|
||||
DirInode* parentDirInode = metaStore->referenceDir(parentID, buddyMirrored, true);
|
||||
|
||||
// it could be, that parentDirInode does not exist
|
||||
// in fsck we create a temporary inode for this case, so that we can modify the dentry
|
||||
// hopefully, the inode itself will get fixed later
|
||||
if ( unlikely(!parentDirInode) )
|
||||
{
|
||||
log.log(
|
||||
Log_NOTICE,
|
||||
"Could not reference directory. EntryID: " + parentID
|
||||
+ " => using temporary directory inode ");
|
||||
|
||||
// create temporary inode
|
||||
int mode = S_IFDIR | S_IRWXU;
|
||||
UInt16Vector stripeTargets;
|
||||
Raid0Pattern stripePattern(0, stripeTargets, 0);
|
||||
parentDirInode = new DirInode(parentID, mode, 0, 0,
|
||||
Program::getApp()->getLocalNode().getNumID(), stripePattern, buddyMirrored);
|
||||
|
||||
parentDirInodeIsTemp = true;
|
||||
}
|
||||
|
||||
listRes = parentDirInode->listIDFilesIncremental(lastContDirOffset, 0, remainingOutIDs,
|
||||
outArgs);
|
||||
|
||||
lastContDirOffset = outNewServerOffset;
|
||||
|
||||
if ( parentDirInodeIsTemp )
|
||||
SAFE_DELETE(parentDirInode);
|
||||
else
|
||||
metaStore->releaseDir(parentID);
|
||||
|
||||
if (listRes != FhgfsOpsErr_SUCCESS)
|
||||
{
|
||||
log.logErr("Could not read dentry-by-ID files; parentID: " + parentID);
|
||||
}
|
||||
|
||||
// process entries
|
||||
readOutIDs += outNames.size();
|
||||
|
||||
for ( StringListIter iter = outNames.begin(); iter != outNames.end(); iter++ )
|
||||
{
|
||||
std::string id = *iter;
|
||||
std::string filename = idPath + "/" + id;
|
||||
|
||||
// stat the file to get device and inode information
|
||||
struct stat statBuf;
|
||||
|
||||
int statRes = stat(filename.c_str(), &statBuf);
|
||||
|
||||
int saveDevice;
|
||||
uint64_t saveInode;
|
||||
if ( likely(!statRes) )
|
||||
{
|
||||
saveDevice = statBuf.st_dev;
|
||||
saveInode = statBuf.st_ino;
|
||||
}
|
||||
else
|
||||
{
|
||||
saveDevice = 0;
|
||||
saveInode = 0;
|
||||
log.log(Log_CRITICAL,
|
||||
"Could not stat ID file; ID: " + id + ";filename: " + filename);
|
||||
}
|
||||
|
||||
FsckFsID fsID(id, parentID, localNodeNumID, saveDevice, saveInode, buddyMirrored);
|
||||
fsIDsOutgoing.push_back(fsID);
|
||||
}
|
||||
|
||||
if ( readOutIDs < maxOutIDs )
|
||||
{
|
||||
// directory is at the end => proceed with next
|
||||
hasNext = StorageTkEx::getNextContDirID(hashDirNum, buddyMirrored, lastHashDirOffset,
|
||||
¤tContDirID, &newHashDirOffset);
|
||||
|
||||
if ( hasNext )
|
||||
{
|
||||
lastHashDirOffset = newHashDirOffset;
|
||||
lastContDirOffset = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// there are more to come, but we need to exit the loop now, because maxCount is reached
|
||||
hasNext = false;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.sendResponse(
|
||||
RetrieveFsIDsRespMsg(&fsIDsOutgoing, currentContDirID, lastHashDirOffset,
|
||||
lastContDirOffset) );
|
||||
|
||||
return true;
|
||||
}
|
||||
11
meta/source/net/message/fsck/RetrieveFsIDsMsgEx.h
Normal file
11
meta/source/net/message/fsck/RetrieveFsIDsMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/fsck/RetrieveFsIDsMsg.h>
|
||||
#include <common/net/message/fsck/RetrieveFsIDsRespMsg.h>
|
||||
|
||||
class RetrieveFsIDsMsgEx : public RetrieveFsIDsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
25
meta/source/net/message/fsck/RetrieveInodesMsgEx.cpp
Normal file
25
meta/source/net/message/fsck/RetrieveInodesMsgEx.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "RetrieveInodesMsgEx.h"
|
||||
|
||||
#include <program/Program.h>
|
||||
|
||||
bool RetrieveInodesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("Incoming RetrieveInodesMsg");
|
||||
|
||||
MetaStore *metaStore = Program::getApp()->getMetaStore();
|
||||
|
||||
unsigned hashDirNum = getHashDirNum();
|
||||
unsigned maxOutInodes = getMaxOutInodes();
|
||||
int64_t lastOffset = getLastOffset();
|
||||
int64_t newOffset;
|
||||
|
||||
FsckFileInodeList fileInodesOutgoing;
|
||||
FsckDirInodeList dirInodesOutgoing;
|
||||
|
||||
metaStore->getAllInodesIncremental(hashDirNum, lastOffset, maxOutInodes, &dirInodesOutgoing,
|
||||
&fileInodesOutgoing, &newOffset, getIsBuddyMirrored());
|
||||
|
||||
ctx.sendResponse(RetrieveInodesRespMsg(&fileInodesOutgoing, &dirInodesOutgoing, newOffset) );
|
||||
|
||||
return true;
|
||||
}
|
||||
11
meta/source/net/message/fsck/RetrieveInodesMsgEx.h
Normal file
11
meta/source/net/message/fsck/RetrieveInodesMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/fsck/RetrieveInodesMsg.h>
|
||||
#include <common/net/message/fsck/RetrieveInodesRespMsg.h>
|
||||
|
||||
class RetrieveInodesMsgEx : public RetrieveInodesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
51
meta/source/net/message/fsck/UpdateDirAttribsMsgEx.cpp
Normal file
51
meta/source/net/message/fsck/UpdateDirAttribsMsgEx.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "UpdateDirAttribsMsgEx.h"
|
||||
|
||||
#include <storage/MetaStore.h>
|
||||
#include <program/Program.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
bool UpdateDirAttribsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
const char* logContext = "UpdateDirAttribsMsg incoming";
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
FsckDirInodeList& inodes = getInodes();
|
||||
FsckDirInodeList failedInodes;
|
||||
|
||||
for (FsckDirInodeListIter iter = inodes.begin(); iter != inodes.end(); iter++)
|
||||
{
|
||||
// call the updating method
|
||||
const std::string& dirID = iter->getID();
|
||||
|
||||
FileIDLock lock;
|
||||
|
||||
if (iter->getIsBuddyMirrored())
|
||||
lock = {entryLockStore, dirID, true};
|
||||
|
||||
DirInode* dirInode = metaStore->referenceDir(dirID, iter->getIsBuddyMirrored(), true);
|
||||
|
||||
if (!dirInode)
|
||||
{
|
||||
LogContext(logContext).logErr("Unable to reference directory; ID: " + dirID);
|
||||
failedInodes.push_back(*iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
FhgfsOpsErr refreshRes = dirInode->refreshMetaInfo();
|
||||
|
||||
metaStore->releaseDir(dirID);
|
||||
|
||||
if (refreshRes != FhgfsOpsErr_SUCCESS)
|
||||
{
|
||||
LogContext(logContext).log(Log_WARNING, "Failed to update attributes of directory. "
|
||||
"entryID: " + dirID);
|
||||
failedInodes.push_back(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.sendResponse(UpdateDirAttribsRespMsg(&failedInodes) );
|
||||
|
||||
return true;
|
||||
}
|
||||
12
meta/source/net/message/fsck/UpdateDirAttribsMsgEx.h
Normal file
12
meta/source/net/message/fsck/UpdateDirAttribsMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/NetMessage.h>
|
||||
#include <common/net/message/fsck/UpdateDirAttribsMsg.h>
|
||||
#include <common/net/message/fsck/UpdateDirAttribsRespMsg.h>
|
||||
|
||||
class UpdateDirAttribsMsgEx : public UpdateDirAttribsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
62
meta/source/net/message/fsck/UpdateFileAttribsMsgEx.cpp
Normal file
62
meta/source/net/message/fsck/UpdateFileAttribsMsgEx.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "UpdateFileAttribsMsgEx.h"
|
||||
|
||||
#include <net/msghelpers/MsgHelperStat.h>
|
||||
#include <program/Program.h>
|
||||
#include <toolkit/BuddyCommTk.h>
|
||||
|
||||
bool UpdateFileAttribsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
const char* logContext = "UpdateFileAttribsMsg incoming";
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
|
||||
|
||||
FsckFileInodeList& inodes = getInodes();
|
||||
FsckFileInodeList failedInodes;
|
||||
|
||||
for (FsckFileInodeListIter iter = inodes.begin(); iter != inodes.end(); iter++)
|
||||
{
|
||||
// create an EntryInfo object (NOTE: dummy fileName)
|
||||
EntryInfo entryInfo(iter->getSaveNodeID(), iter->getParentDirID(), iter->getID(), "",
|
||||
DirEntryType_REGULARFILE,
|
||||
(iter->getIsBuddyMirrored() ? ENTRYINFO_FEATURE_BUDDYMIRRORED : 0) |
|
||||
(iter->getIsInlined() ? ENTRYINFO_FEATURE_INLINED : 0));
|
||||
|
||||
FileIDLock lock;
|
||||
|
||||
if (iter->getIsBuddyMirrored())
|
||||
lock = {entryLockStore, entryInfo.getEntryID(), true};
|
||||
|
||||
auto [inode, referenceRes] = metaStore->referenceFile(&entryInfo);
|
||||
|
||||
if (inode)
|
||||
{
|
||||
inode->setNumHardlinksUnpersistent(iter->getNumHardLinks());
|
||||
inode->updateInodeOnDisk(&entryInfo);
|
||||
|
||||
// call the dynamic attribs refresh method
|
||||
FhgfsOpsErr refreshRes = MsgHelperStat::refreshDynAttribs(&entryInfo, true,
|
||||
getMsgHeaderUserID() );
|
||||
if (refreshRes != FhgfsOpsErr_SUCCESS)
|
||||
{
|
||||
LogContext(logContext).log(Log_WARNING, "Failed to update dynamic attributes of file. "
|
||||
"entryID: " + iter->getID());
|
||||
failedInodes.push_back(*iter);
|
||||
}
|
||||
|
||||
/* only release it here, as refreshDynAttribs() also takes an inode reference and can
|
||||
* do the reference from in-memory data then */
|
||||
metaStore->releaseFile(entryInfo.getParentEntryID(), inode);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogContext(logContext).log(Log_WARNING, "Could not reference inode to update attributes. "
|
||||
"entryID: " + iter->getID());
|
||||
failedInodes.push_back(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.sendResponse(UpdateFileAttribsRespMsg(&failedInodes) );
|
||||
|
||||
return true;
|
||||
}
|
||||
12
meta/source/net/message/fsck/UpdateFileAttribsMsgEx.h
Normal file
12
meta/source/net/message/fsck/UpdateFileAttribsMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/NetMessage.h>
|
||||
#include <common/net/message/fsck/UpdateFileAttribsMsg.h>
|
||||
#include <common/net/message/fsck/UpdateFileAttribsRespMsg.h>
|
||||
|
||||
class UpdateFileAttribsMsgEx : public UpdateFileAttribsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
39
meta/source/net/message/mon/RequestMetaDataMsgEx.cpp
Normal file
39
meta/source/net/message/mon/RequestMetaDataMsgEx.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <common/components/worker/queue/MultiWorkQueue.h>
|
||||
#include <program/Program.h>
|
||||
#include <session/SessionStore.h>
|
||||
#include "RequestMetaDataMsgEx.h"
|
||||
|
||||
bool RequestMetaDataMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("RequestMetaDataMsg incoming");
|
||||
|
||||
App *app = Program::getApp();
|
||||
Node& node = app->getLocalNode();
|
||||
MultiWorkQueue *workQueue = app->getWorkQueue();
|
||||
|
||||
unsigned sessionCount = app->getSessions()->getSize() + app->getMirroredSessions()->getSize();
|
||||
|
||||
NicAddressList nicList(node.getNicList());
|
||||
std::string hostnameid = System::getHostname();
|
||||
|
||||
// highresStats
|
||||
HighResStatsList statsHistory;
|
||||
uint64_t lastStatsMS = getValue();
|
||||
|
||||
// get stats history
|
||||
StatsCollector* statsCollector = app->getStatsCollector();
|
||||
statsCollector->getStatsSince(lastStatsMS, statsHistory);
|
||||
|
||||
RequestMetaDataRespMsg requestMetaDataRespMsg(node.getAlias(), hostnameid, node.getNumID(), &nicList,
|
||||
app->getMetaRoot().getID() == node.getNumID(), workQueue->getIndirectWorkListSize(),
|
||||
workQueue->getDirectWorkListSize(), sessionCount, &statsHistory);
|
||||
ctx.sendResponse(requestMetaDataRespMsg);
|
||||
|
||||
LOG_DEBUG_CONTEXT(log, 5, std::string("Sent a message with type: " ) +
|
||||
StringTk::uintToStr(requestMetaDataRespMsg.getMsgType() ) + std::string(" to mon") );
|
||||
|
||||
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), MetaOpCounter_REQUESTMETADATA,
|
||||
getMsgHeaderUserID() );
|
||||
|
||||
return true;
|
||||
}
|
||||
13
meta/source/net/message/mon/RequestMetaDataMsgEx.h
Normal file
13
meta/source/net/message/mon/RequestMetaDataMsgEx.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <app/App.h>
|
||||
#include <common/app/log/LogContext.h>
|
||||
#include <common/net/message/mon/RequestMetaDataMsg.h>
|
||||
#include <common/net/message/mon/RequestMetaDataRespMsg.h>
|
||||
|
||||
class RequestMetaDataMsgEx : public RequestMetaDataMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
900
meta/source/net/message/nodes/GenericDebugMsgEx.cpp
Normal file
900
meta/source/net/message/nodes/GenericDebugMsgEx.cpp
Normal file
@@ -0,0 +1,900 @@
|
||||
#include <common/net/message/nodes/GenericDebugRespMsg.h>
|
||||
#include <common/net/msghelpers/MsgHelperGenericDebug.h>
|
||||
#include <common/storage/quota/Quota.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <program/Program.h>
|
||||
#include <session/SessionStore.h>
|
||||
#include "GenericDebugMsgEx.h"
|
||||
|
||||
|
||||
#define GENDBGMSG_OP_LISTFILEAPPENDLOCKS "listfileappendlocks"
|
||||
#define GENDBGMSG_OP_LISTFILEENTRYLOCKS "listfileentrylocks"
|
||||
#define GENDBGMSG_OP_LISTFILERANGELOCKS "listfilerangelocks"
|
||||
#define GENDBGMSG_OP_LISTOPENFILES "listopenfiles"
|
||||
#define GENDBGMSG_OP_REFERENCESTATISTICS "refstats"
|
||||
#define GENDBGMSG_OP_CACHESTATISTICS "cachestats"
|
||||
#define GENDBGMSG_OP_VERSION "version"
|
||||
#define GENDBGMSG_OP_MSGQUEUESTATS "msgqueuestats"
|
||||
#define GENDBGMSG_OP_LISTPOOLS "listpools"
|
||||
#define GENDBGMSG_OP_DUMPDENTRY "dumpdentry"
|
||||
#define GENDBGMSG_OP_DUMPINODE "dumpinode"
|
||||
#define GENDBGMSG_OP_DUMPINLINEDINODE "dumpinlinedinode"
|
||||
|
||||
#ifdef BEEGFS_DEBUG
|
||||
#define GENDBGMSG_OP_WRITEDIRDENTRY "writedirdentry"
|
||||
#define GENDBGMSG_OP_WRITEDIRINODE "writedirinode"
|
||||
#define GENDBGMSG_OP_WRITEFILEINODE "writefileinode"
|
||||
#endif // BEEGFS_DEBUG
|
||||
|
||||
|
||||
bool GenericDebugMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("GenericDebugMsg incoming");
|
||||
|
||||
LOG_DEBUG_CONTEXT(log, 5, std::string("Command string: ") + getCommandStr() );
|
||||
|
||||
std::string cmdRespStr = processCommand();
|
||||
|
||||
ctx.sendResponse(GenericDebugRespMsg(cmdRespStr.c_str() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return command response string
|
||||
*/
|
||||
std::string GenericDebugMsgEx::processCommand()
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
Config* cfg = app->getConfig();
|
||||
|
||||
std::string responseStr;
|
||||
std::string operation;
|
||||
|
||||
// load command string into a stream to allow us to use getline
|
||||
std::istringstream commandStream(getCommandStr() );
|
||||
|
||||
// get operation type from command string
|
||||
std::getline(commandStream, operation, ' ');
|
||||
|
||||
if(operation == GENDBGMSG_OP_LISTFILEAPPENDLOCKS)
|
||||
responseStr = processOpListFileAppendLocks(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_LISTFILEENTRYLOCKS)
|
||||
responseStr = processOpListFileEntryLocks(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_LISTFILERANGELOCKS)
|
||||
responseStr = processOpListFileRangeLocks(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_LISTOPENFILES)
|
||||
responseStr = processOpListOpenFiles(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_REFERENCESTATISTICS)
|
||||
responseStr = processOpReferenceStatistics(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_CACHESTATISTICS)
|
||||
responseStr = processOpCacheStatistics(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_VERSION)
|
||||
responseStr = processOpVersion(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_MSGQUEUESTATS)
|
||||
responseStr = processOpMsgQueueStats(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_VARLOGMESSAGES)
|
||||
responseStr = MsgHelperGenericDebug::processOpVarLogMessages(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_VARLOGKERNLOG)
|
||||
responseStr = MsgHelperGenericDebug::processOpVarLogKernLog(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_FHGFSLOG)
|
||||
responseStr = MsgHelperGenericDebug::processOpFhgfsLog(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_LOADAVG)
|
||||
responseStr = MsgHelperGenericDebug::processOpLoadAvg(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_DROPCACHES)
|
||||
responseStr = MsgHelperGenericDebug::processOpDropCaches(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_GETCFG)
|
||||
responseStr = MsgHelperGenericDebug::processOpCfgFile(commandStream, cfg->getCfgFile() );
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_GETLOGLEVEL)
|
||||
responseStr = MsgHelperGenericDebug::processOpGetLogLevel(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_SETLOGLEVEL)
|
||||
responseStr = MsgHelperGenericDebug::processOpSetLogLevel(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_NETOUT)
|
||||
responseStr = MsgHelperGenericDebug::processOpNetOut(commandStream,
|
||||
app->getMgmtNodes(), app->getMetaNodes(), app->getStorageNodes() );
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_LISTMETASTATES)
|
||||
responseStr = MsgHelperGenericDebug::processOpListTargetStates(commandStream,
|
||||
app->getMetaStateStore() );
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_LISTSTORAGESTATES)
|
||||
responseStr = MsgHelperGenericDebug::processOpListTargetStates(commandStream,
|
||||
app->getTargetStateStore() );
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_LISTPOOLS)
|
||||
responseStr = processOpListPools(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_DUMPDENTRY)
|
||||
responseStr = processOpDumpDentry(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_DUMPINODE)
|
||||
responseStr = processOpDumpInode(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_DUMPINLINEDINODE)
|
||||
responseStr = processOpDumpInlinedInode(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_QUOTAEXCEEDED)
|
||||
responseStr = processOpQuotaExceeded(commandStream);
|
||||
else if(operation == GENDBGMSG_OP_LISTSTORAGEPOOLS)
|
||||
responseStr = MsgHelperGenericDebug::processOpListStoragePools(commandStream,
|
||||
app->getStoragePoolStore());
|
||||
#ifdef BEEGFS_DEBUG
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_WRITEDIRDENTRY)
|
||||
responseStr = processOpWriteDirDentry(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_WRITEDIRINODE)
|
||||
responseStr = processOpWriteDirInode(commandStream);
|
||||
else
|
||||
if(operation == GENDBGMSG_OP_WRITEFILEINODE)
|
||||
responseStr = processOpWriteInlinedFileInode(commandStream);
|
||||
#endif // BEEGFS_DEBUG
|
||||
else
|
||||
responseStr = "Unknown/invalid operation";
|
||||
|
||||
return responseStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve append lock stats for a certain file.
|
||||
*/
|
||||
std::string GenericDebugMsgEx::processOpListFileAppendLocks(std::istringstream& commandStream)
|
||||
{
|
||||
// procotol: entryID as only argument
|
||||
|
||||
std::string parentEntryID;
|
||||
std::string entryID;
|
||||
std::string responseStr;
|
||||
std::string isBuddyMirroredStr;
|
||||
bool isBuddyMirrored;
|
||||
|
||||
// get entryID from command string
|
||||
std::getline(commandStream, parentEntryID, ' ');
|
||||
std::getline(commandStream, entryID, ' ');
|
||||
std::getline(commandStream, isBuddyMirroredStr, ' ');
|
||||
|
||||
if (parentEntryID.empty() )
|
||||
return "Invalid or missing parentEntryID";
|
||||
|
||||
if(entryID.empty() )
|
||||
return "Invalid or missing entryID";
|
||||
|
||||
if(isBuddyMirroredStr.empty())
|
||||
isBuddyMirrored = false;
|
||||
else
|
||||
isBuddyMirrored = StringTk::strToBool(isBuddyMirroredStr);
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
MetaFileHandle inode = metaStore->referenceLoadedFile(parentEntryID, isBuddyMirrored, entryID);
|
||||
if(!inode)
|
||||
return "FileID not exists: " + entryID;
|
||||
|
||||
responseStr = inode->flockAppendGetAllAsStr();
|
||||
|
||||
metaStore->releaseFile(parentEntryID, inode);
|
||||
|
||||
return responseStr;
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpListFileEntryLocks(std::istringstream& commandStream)
|
||||
{
|
||||
// procotol: entryID as only argument
|
||||
|
||||
std::string parentEntryID;
|
||||
std::string entryID;
|
||||
std::string responseStr;
|
||||
std::string isBuddyMirroredStr;
|
||||
bool isBuddyMirrored;
|
||||
|
||||
// get entryID from command string
|
||||
std::getline(commandStream, parentEntryID, ' ');
|
||||
std::getline(commandStream, entryID, ' ');
|
||||
std::getline(commandStream, isBuddyMirroredStr, ' ');
|
||||
|
||||
if (parentEntryID.empty() )
|
||||
return "Invalid or missing parentEntryID";
|
||||
|
||||
if(entryID.empty() )
|
||||
return "Invalid or missing entryID";
|
||||
|
||||
if(isBuddyMirroredStr.empty())
|
||||
isBuddyMirrored = false;
|
||||
else
|
||||
isBuddyMirrored = StringTk::strToBool(isBuddyMirroredStr);
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
MetaFileHandle inode = metaStore->referenceLoadedFile(parentEntryID, isBuddyMirrored, entryID);
|
||||
if(!inode)
|
||||
return "FileID not exists: " + entryID;
|
||||
|
||||
responseStr = inode->flockEntryGetAllAsStr();
|
||||
|
||||
metaStore->releaseFile(parentEntryID, inode);
|
||||
|
||||
return responseStr;
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpListFileRangeLocks(std::istringstream& commandStream)
|
||||
{
|
||||
// procotol: entryID as only argument
|
||||
|
||||
std::string parentEntryID;
|
||||
std::string entryID;
|
||||
std::string isBuddyMirroredStr;
|
||||
bool isBuddyMirrored;
|
||||
|
||||
// get parentEntryID from command string
|
||||
std::getline(commandStream, parentEntryID, ' ');
|
||||
|
||||
if(parentEntryID.empty() )
|
||||
return "Invalid or missing parentEntryID";
|
||||
|
||||
// get entryID from command string
|
||||
std::getline(commandStream, entryID, ' ');
|
||||
|
||||
if(entryID.empty() )
|
||||
return "Invalid or missing entryID";
|
||||
|
||||
// get isBuddyMirrored from command string
|
||||
std::getline(commandStream, isBuddyMirroredStr, ' ');
|
||||
|
||||
if(isBuddyMirroredStr.empty())
|
||||
isBuddyMirrored = false;
|
||||
else
|
||||
isBuddyMirrored = StringTk::strToBool(isBuddyMirroredStr);
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
MetaFileHandle file = metaStore->referenceLoadedFile(parentEntryID, isBuddyMirrored, entryID);
|
||||
if(!file)
|
||||
return "FileID not found: " + entryID;
|
||||
|
||||
std::string responseStr = file->flockRangeGetAllAsStr();
|
||||
|
||||
metaStore->releaseFile(parentEntryID, file);
|
||||
|
||||
return responseStr;
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpListOpenFiles(std::istringstream& commandStream)
|
||||
{
|
||||
// protocol: no arguments
|
||||
|
||||
App* app = Program::getApp();
|
||||
SessionStore* sessions = app->getSessions();
|
||||
SessionStore* mirroredSessions = app->getMirroredSessions();
|
||||
|
||||
std::ostringstream responseStream;
|
||||
size_t numFilesTotal = 0;
|
||||
size_t numCheckedSessions = 0; // may defer from number of initially queried sessions
|
||||
|
||||
NumNodeIDList sessionIDs = sessions->getAllSessionIDs();
|
||||
NumNodeIDList mirroredSessionIDs = mirroredSessions->getAllSessionIDs();
|
||||
|
||||
responseStream << "Found " << sessionIDs.size() << " non-mirrored sessions and "
|
||||
<< mirroredSessionIDs.size() << " mirrored sessions." << std::endl;
|
||||
|
||||
responseStream << std::endl;
|
||||
|
||||
responseStream << "Non-mirrored sessions:" << std::endl;
|
||||
// walk over all sessions
|
||||
for(NumNodeIDListCIter iter = sessionIDs.begin(); iter != sessionIDs.end(); iter++)
|
||||
{
|
||||
Session* session = sessions->referenceSession(*iter, false);
|
||||
// note: sessionID might have been removed since we queried it, e.g. because client is gone
|
||||
if(!session)
|
||||
continue;
|
||||
|
||||
numCheckedSessions++;
|
||||
|
||||
SessionFileStore* sessionFiles = session->getFiles();
|
||||
size_t numFiles = sessionFiles->getSize();
|
||||
sessions->releaseSession(session);
|
||||
|
||||
if(!numFiles)
|
||||
continue; // only print sessions with open files
|
||||
|
||||
numFilesTotal += numFiles;
|
||||
|
||||
responseStream << *iter << ": " << numFiles << std::endl;
|
||||
}
|
||||
|
||||
responseStream << "Mirrored sessions:" << std::endl;
|
||||
// ...and the mirrored sessions
|
||||
for(NumNodeIDListCIter iter = mirroredSessionIDs.begin(); iter != mirroredSessionIDs.end();
|
||||
++iter)
|
||||
{
|
||||
Session* session = mirroredSessions->referenceSession(*iter, false);
|
||||
if (!session)
|
||||
continue;
|
||||
|
||||
numCheckedSessions++;
|
||||
|
||||
SessionFileStore* sessionFiles = session->getFiles();
|
||||
size_t numFiles = sessionFiles->getSize();
|
||||
mirroredSessions->releaseSession(session);
|
||||
|
||||
if (!numFiles)
|
||||
continue;
|
||||
|
||||
numFilesTotal += numFiles;
|
||||
responseStream << *iter << ": " << numFiles << std::endl;
|
||||
}
|
||||
|
||||
responseStream << std::endl;
|
||||
|
||||
responseStream << "Final results: " << numFilesTotal << " open files in " <<
|
||||
numCheckedSessions << " checked sessions";
|
||||
|
||||
return responseStream.str();
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpReferenceStatistics(std::istringstream& commandStream)
|
||||
{
|
||||
// protocol: no arguments
|
||||
|
||||
App* app = Program::getApp();
|
||||
MetaStore* metaStore = app->getMetaStore();
|
||||
|
||||
std::ostringstream responseStream;
|
||||
size_t numDirs;
|
||||
size_t numFiles;
|
||||
|
||||
metaStore->getReferenceStats(&numDirs, &numFiles);
|
||||
|
||||
responseStream << "Dirs: " << numDirs << std::endl;
|
||||
responseStream << "Files: " << numFiles;
|
||||
|
||||
return responseStream.str();
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpCacheStatistics(std::istringstream& commandStream)
|
||||
{
|
||||
// protocol: no arguments
|
||||
|
||||
App* app = Program::getApp();
|
||||
MetaStore* metaStore = app->getMetaStore();
|
||||
|
||||
std::ostringstream responseStream;
|
||||
size_t numDirs;
|
||||
|
||||
metaStore->getCacheStats(&numDirs);
|
||||
|
||||
responseStream << "Dirs: " << numDirs;
|
||||
|
||||
return responseStream.str();
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpVersion(std::istringstream& commandStream)
|
||||
{
|
||||
return BEEGFS_VERSION;
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpMsgQueueStats(std::istringstream& commandStream)
|
||||
{
|
||||
// protocol: no arguments
|
||||
|
||||
App* app = Program::getApp();
|
||||
MultiWorkQueue* workQ = app->getWorkQueue();
|
||||
|
||||
std::ostringstream responseStream;
|
||||
std::string indirectQueueStats;
|
||||
std::string directQueueStats;
|
||||
std::string busyStats;
|
||||
|
||||
workQ->getStatsAsStr(indirectQueueStats, directQueueStats, busyStats);
|
||||
|
||||
responseStream << "general queue stats: " << std::endl <<
|
||||
indirectQueueStats << std::endl;
|
||||
|
||||
responseStream << "direct queue stats: " << std::endl <<
|
||||
directQueueStats << std::endl;
|
||||
|
||||
responseStream << "busy worker stats: " << std::endl <<
|
||||
busyStats << std::endl;
|
||||
|
||||
return responseStream.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* List internal state of meta and storage capacity pools.
|
||||
*/
|
||||
std::string GenericDebugMsgEx::processOpListPools(std::istringstream& commandStream)
|
||||
{
|
||||
// protocol: no arguments
|
||||
|
||||
const App* app = Program::getApp();
|
||||
const NodeCapacityPools* metaPools = app->getMetaCapacityPools();
|
||||
|
||||
std::ostringstream responseStream;
|
||||
|
||||
responseStream << "META POOLS STATE: " << std::endl << metaPools->getStateAsStr() << std::endl;
|
||||
|
||||
const StoragePoolPtrVec storagePools = app->getStoragePoolStore()->getPoolsAsVec();
|
||||
|
||||
for (auto iter = storagePools.begin(); iter != storagePools.end(); iter++)
|
||||
{
|
||||
const TargetCapacityPools* capPool = (*iter)->getTargetCapacityPools();
|
||||
|
||||
responseStream << "STORAGE CAPACITY POOLS STATE (STORAGE POOL ID: " << (*iter)->getId()
|
||||
<< "): " << std::endl << capPool->getStateAsStr() << std::endl;
|
||||
}
|
||||
|
||||
for (auto iter = storagePools.begin(); iter != storagePools.end(); iter++)
|
||||
{
|
||||
const NodeCapacityPools* capPool = (*iter)->getBuddyCapacityPools();
|
||||
|
||||
responseStream << "STORAGE BUDDY CAPACITY POOLS STATE (STORAGE POOL ID: "
|
||||
<< (*iter)->getId() << "): " << std::endl << capPool->getStateAsStr()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
return responseStream.str();
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpDumpDentry(std::istringstream& commandStream)
|
||||
{
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
|
||||
std::ostringstream responseStream;
|
||||
|
||||
StringList parameterList;
|
||||
StringTk::explode(commandStream.str(), ' ', ¶meterList);
|
||||
|
||||
if ( parameterList.size() < 3 || parameterList.size() > 4 )
|
||||
return "Invalid or missing parameters; Parameter format: parentDirID entryName "
|
||||
"[isBuddyMirrored]";
|
||||
|
||||
StringListIter iter = parameterList.begin();
|
||||
iter++;
|
||||
std::string parentDirID = *iter;
|
||||
iter++;
|
||||
std::string entryName = *iter;
|
||||
iter++;
|
||||
bool isBuddyMirrored = false;
|
||||
if (iter != parameterList.end())
|
||||
{
|
||||
isBuddyMirrored = StringTk::strToBool(*iter);
|
||||
}
|
||||
|
||||
DirInode* parentDirInode = metaStore->referenceDir(parentDirID, isBuddyMirrored, false);
|
||||
|
||||
if (!parentDirInode)
|
||||
return "Unable to reference parent directory.";
|
||||
|
||||
DirEntry dentry(entryName);
|
||||
bool getDentryRes = parentDirInode->getDentry(entryName, dentry);
|
||||
|
||||
metaStore->releaseDir(parentDirID);
|
||||
|
||||
if (!getDentryRes)
|
||||
return "Unable to get dentry from parent directory.";
|
||||
|
||||
responseStream << "entryType: " << dentry.getEntryType() << std::endl;
|
||||
responseStream << "ID: " << dentry.getID() << std::endl;
|
||||
responseStream << "ownerNodeID: " << dentry.getOwnerNodeID() << std::endl;
|
||||
responseStream << "featureFlags: " << dentry.getDentryFeatureFlags() << std::endl;
|
||||
|
||||
return responseStream.str();
|
||||
}
|
||||
|
||||
#ifdef BEEGFS_DEBUG
|
||||
std::string GenericDebugMsgEx::processOpWriteDirDentry(std::istringstream& commandStream)
|
||||
{
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
std::string dentriesPath = Program::getApp()->getDentriesPath()->str();
|
||||
|
||||
std::ostringstream responseStream;
|
||||
|
||||
StringList parameterList;
|
||||
StringTk::explode(commandStream.str(), ' ', ¶meterList);
|
||||
|
||||
if ( parameterList.size() < 4 || parameterList.size() > 5 )
|
||||
return "Invalid or missing parameters; Parameter format: parentDirID entryName ownerNodeID "
|
||||
"[isBuddyMirrored]";
|
||||
|
||||
StringListIter iter = parameterList.begin();
|
||||
iter++;
|
||||
std::string parentDirID = *iter;
|
||||
iter++;
|
||||
std::string entryName = *iter;
|
||||
iter++;
|
||||
NumNodeID ownerNodeID(StringTk::strToUInt(*iter) );
|
||||
|
||||
iter++;
|
||||
bool isBuddyMirrored = false;
|
||||
if (iter!=parameterList.end())
|
||||
{
|
||||
isBuddyMirrored = StringTk::strToBool(*iter);
|
||||
}
|
||||
|
||||
DirInode* parentDirInode = metaStore->referenceDir(parentDirID, isBuddyMirrored, true);
|
||||
|
||||
if (!parentDirInode)
|
||||
return "Unable to reference parent directory.";
|
||||
|
||||
DirEntry dentry(entryName);
|
||||
bool getDentryRes = parentDirInode->getDentry(entryName, dentry);
|
||||
|
||||
metaStore->releaseDir(parentDirID);
|
||||
|
||||
if (!getDentryRes)
|
||||
return "Unable to get dentry from parent directory.";
|
||||
|
||||
bool setOwnerRes = dentry.setOwnerNodeID(
|
||||
MetaStorageTk::getMetaDirEntryPath(dentriesPath, parentDirID), ownerNodeID);
|
||||
|
||||
if (!setOwnerRes)
|
||||
return "Unable to set new owner node ID in dentry.";
|
||||
|
||||
return "OK";
|
||||
}
|
||||
#endif // BEEGFS_DEBUG
|
||||
|
||||
std::string GenericDebugMsgEx::processOpDumpInode(std::istringstream& commandStream)
|
||||
{
|
||||
// commandStream: ID of inode
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
|
||||
std::ostringstream responseStream;
|
||||
|
||||
std::string inodeID;
|
||||
std::string isBuddyMirroredStr;
|
||||
bool isBuddyMirrored;
|
||||
|
||||
// get inodeID from command string
|
||||
std::getline(commandStream, inodeID, ' ');
|
||||
|
||||
if(inodeID.empty() )
|
||||
return "Invalid or missing inode ID";
|
||||
|
||||
// get isBuddyMirrored from command string
|
||||
std::getline(commandStream, isBuddyMirroredStr, ' ');
|
||||
if(isBuddyMirroredStr.empty())
|
||||
isBuddyMirrored = false;
|
||||
else
|
||||
isBuddyMirrored = StringTk::strToBool(isBuddyMirroredStr);
|
||||
|
||||
MetaFileHandle fileInode;
|
||||
DirInode* dirInode = NULL;
|
||||
|
||||
metaStore->referenceInode(inodeID, isBuddyMirrored, fileInode, dirInode);
|
||||
|
||||
if (fileInode)
|
||||
{
|
||||
StatData statData;
|
||||
if (fileInode->getStatData(statData) != FhgfsOpsErr_SUCCESS)
|
||||
{ // stat data retrieval failed
|
||||
metaStore->releaseFile("", fileInode);
|
||||
return "Could not get stat data for requested file inode";
|
||||
}
|
||||
|
||||
DirEntryType dirEntryType = MetadataTk::posixFileTypeToDirEntryType(fileInode->getMode() );
|
||||
|
||||
std::string parentDirID = "cannotBeUsed";
|
||||
uint16_t parentNodeID = 0;
|
||||
|
||||
responseStream << "entryType: " << dirEntryType << std::endl;
|
||||
responseStream << "parentEntryID: " << parentDirID << std::endl;
|
||||
responseStream << "parentNodeID: " << StringTk::uintToStr(parentNodeID) << std::endl;
|
||||
responseStream << "mode: " << StringTk::intToStr(statData.getMode()) << std::endl;
|
||||
responseStream << "uid: " << StringTk::uintToStr(statData.getUserID()) << std::endl;
|
||||
responseStream << "gid: " << StringTk::uintToStr(statData.getGroupID()) << std::endl;
|
||||
responseStream << "filesize: " << StringTk::int64ToStr(statData.getFileSize()) << std::endl;
|
||||
responseStream << "ctime: " << StringTk::int64ToStr(statData.getCreationTimeSecs()) << std::endl;
|
||||
responseStream << "atime: " << StringTk::int64ToStr(statData.getLastAccessTimeSecs()) << std::endl;
|
||||
responseStream << "mtime: " << StringTk::int64ToStr(statData.getModificationTimeSecs()) << std::endl;
|
||||
responseStream << "hardlinks: " << StringTk::intToStr(statData.getNumHardlinks()) << std::endl;
|
||||
responseStream << "stripeTargets: "
|
||||
<< StringTk::uint16VecToStr(fileInode->getStripePattern()->getStripeTargetIDs())
|
||||
<< std::endl;
|
||||
responseStream << "chunkSize: "
|
||||
<< StringTk::uintToStr(fileInode->getStripePattern()->getChunkSize()) << std::endl;
|
||||
responseStream << "featureFlags: " << fileInode->getFeatureFlags() << std::endl;
|
||||
|
||||
metaStore->releaseFile("", fileInode);
|
||||
}
|
||||
else
|
||||
if (dirInode)
|
||||
{
|
||||
StatData statData;
|
||||
if (dirInode->getStatData(statData) != FhgfsOpsErr_SUCCESS)
|
||||
{ // stat data retrieval failed
|
||||
metaStore->releaseDir(inodeID);
|
||||
return "Could not get stat data for requested dir inode";
|
||||
}
|
||||
|
||||
DirEntryType dirEntryType = MetadataTk::posixFileTypeToDirEntryType(dirInode->getMode() );
|
||||
|
||||
std::string parentDirID;
|
||||
NumNodeID parentNodeID;
|
||||
dirInode->getParentInfo(&parentDirID, &parentNodeID);
|
||||
|
||||
responseStream << "entryType: " << dirEntryType << std::endl;
|
||||
responseStream << "parentEntryID: " << parentDirID << std::endl;
|
||||
responseStream << "parentNodeID: " << parentNodeID.str() << std::endl;
|
||||
responseStream << "ownerNodeID: " << dirInode->getOwnerNodeID().str() << std::endl;
|
||||
responseStream << "mode: " << StringTk::intToStr(statData.getMode()) << std::endl;
|
||||
responseStream << "uid: " << StringTk::uintToStr(statData.getUserID()) << std::endl;
|
||||
responseStream << "gid: " << StringTk::uintToStr(statData.getGroupID()) << std::endl;
|
||||
responseStream << "size: " << StringTk::int64ToStr(statData.getFileSize()) << std::endl;
|
||||
responseStream << "numLinks: " << StringTk::int64ToStr(statData.getNumHardlinks())
|
||||
<< std::endl;
|
||||
responseStream << "ctime: " << StringTk::int64ToStr(statData.getCreationTimeSecs())
|
||||
<< std::endl;
|
||||
responseStream << "atime: " << StringTk::int64ToStr(statData.getLastAccessTimeSecs())
|
||||
<< std::endl;
|
||||
responseStream << "mtime: " << StringTk::int64ToStr(statData.getModificationTimeSecs())
|
||||
<< std::endl;
|
||||
responseStream << "featureFlags: " << dirInode->getFeatureFlags() << std::endl;
|
||||
|
||||
metaStore->releaseDir(inodeID);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Could not read requested inode";
|
||||
}
|
||||
|
||||
return responseStream.str();
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpDumpInlinedInode(std::istringstream& commandStream)
|
||||
{
|
||||
// commandStream: parentID, name
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
NumNodeID localNodeID = Program::getApp()->getLocalNode().getNumID();
|
||||
std::ostringstream responseStream;
|
||||
|
||||
StringList parameterList;
|
||||
StringTk::explode(commandStream.str(), ' ', ¶meterList);
|
||||
|
||||
if ( parameterList.size() < 3 || parameterList.size() > 4 )
|
||||
return "Invalid or missing parameters; Parameter format: parentDirID entryName "
|
||||
"[isBuddyMirrored]";
|
||||
|
||||
StringListIter iter = parameterList.begin();
|
||||
iter++;
|
||||
std::string parentEntryID = *iter;
|
||||
iter++;
|
||||
std::string entryName = *iter;
|
||||
iter++;
|
||||
bool isBuddyMirrored = false;
|
||||
if (iter != parameterList.end())
|
||||
{
|
||||
isBuddyMirrored = StringTk::strToBool(*iter);
|
||||
}
|
||||
|
||||
EntryInfo entryInfo(localNodeID, parentEntryID, "unknown", entryName, DirEntryType_REGULARFILE,
|
||||
0);
|
||||
|
||||
DirInode* parentInode = metaStore->referenceDir(parentEntryID, isBuddyMirrored, false);
|
||||
|
||||
if ( !parentInode )
|
||||
return "Could not open parent directory";
|
||||
|
||||
DirEntry dirEntry(entryName);
|
||||
bool getDentryRes = parentInode->getDentry(entryName, dirEntry);
|
||||
|
||||
if ( !getDentryRes )
|
||||
{
|
||||
metaStore->releaseDir(parentEntryID);
|
||||
return "Could not open dir entry";
|
||||
}
|
||||
|
||||
FileInodeStoreData* inodeData = dirEntry.getInodeStoreData();
|
||||
|
||||
if ( !inodeData )
|
||||
{
|
||||
metaStore->releaseDir(parentEntryID);
|
||||
return "Could not get inlined inode data";
|
||||
}
|
||||
|
||||
StatData* statData = inodeData->getInodeStatData();
|
||||
if ( !statData )
|
||||
{
|
||||
metaStore->releaseDir(parentEntryID);
|
||||
return "Could not get stat data for requested file inode";
|
||||
}
|
||||
|
||||
responseStream << "entryID: " << inodeData->getEntryID() << std::endl;
|
||||
responseStream << "mode: " << StringTk::intToStr(statData->getMode()) << std::endl;
|
||||
responseStream << "uid: " << StringTk::uintToStr(statData->getUserID()) << std::endl;
|
||||
responseStream << "gid: " << StringTk::uintToStr(statData->getGroupID()) << std::endl;
|
||||
responseStream << "filesize: " << StringTk::int64ToStr(statData->getFileSize()) << std::endl;
|
||||
responseStream << "ctime: " << StringTk::int64ToStr(statData->getCreationTimeSecs()) << std::endl;
|
||||
responseStream << "atime: " << StringTk::int64ToStr(statData->getLastAccessTimeSecs())
|
||||
<< std::endl;
|
||||
responseStream << "mtime: " << StringTk::int64ToStr(statData->getModificationTimeSecs())
|
||||
<< std::endl;
|
||||
responseStream << "hardlinks: " << StringTk::intToStr(statData->getNumHardlinks()) << std::endl;
|
||||
responseStream << "stripeTargets: "
|
||||
<< StringTk::uint16VecToStr(inodeData->getPattern()->getStripeTargetIDs()) << std::endl;
|
||||
responseStream << "chunkSize: "
|
||||
<< StringTk::uintToStr(inodeData->getPattern()->getChunkSize()) << std::endl;
|
||||
responseStream << "featureFlags: " << inodeData->getInodeFeatureFlags() << std::endl;
|
||||
|
||||
metaStore->releaseDir(parentEntryID);
|
||||
|
||||
return responseStream.str();
|
||||
}
|
||||
|
||||
std::string GenericDebugMsgEx::processOpQuotaExceeded(std::istringstream& commandStream)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
|
||||
std::string targetIdStr;
|
||||
std::getline(commandStream, targetIdStr, ' ');
|
||||
uint16_t targetId = StringTk::strToUInt(targetIdStr);
|
||||
|
||||
std::string returnString;
|
||||
|
||||
if(!app->getConfig()->getQuotaEnableEnforcement() )
|
||||
return "No quota exceeded IDs on this storage daemon because quota enforcement is"
|
||||
"disabled.";
|
||||
|
||||
ExceededQuotaStorePtr exQuotaStore = app->getExceededQuotaStores()->get(targetId);
|
||||
// exQuotaStore may be null;needs to be checked in MsgHelperGenericDebug::processOpQuotaExceeded
|
||||
return MsgHelperGenericDebug::processOpQuotaExceeded(commandStream, exQuotaStore.get());
|
||||
}
|
||||
|
||||
#ifdef BEEGFS_DEBUG
|
||||
std::string GenericDebugMsgEx::processOpWriteDirInode(std::istringstream& commandStream)
|
||||
{
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
|
||||
// get parameters from command string
|
||||
StringVector paramVec;
|
||||
StringTk::explode(commandStream.str(), ' ', ¶mVec);
|
||||
|
||||
std::string entryID;
|
||||
std::string parentDirID;
|
||||
NumNodeID parentNodeID;
|
||||
NumNodeID ownerNodeID;
|
||||
int mode;
|
||||
uint uid;
|
||||
uint gid;
|
||||
int64_t size;
|
||||
unsigned numLinks;
|
||||
bool isBuddyMirrored;
|
||||
|
||||
try
|
||||
{
|
||||
unsigned i = 1;
|
||||
entryID = paramVec.at(i++);
|
||||
parentDirID = paramVec.at(i++);
|
||||
parentNodeID = NumNodeID(StringTk::strToUInt(paramVec.at(i++)));
|
||||
ownerNodeID = NumNodeID(StringTk::strToUInt(paramVec.at(i++)));
|
||||
mode = StringTk::strToInt(paramVec.at(i++));
|
||||
uid = StringTk::strToUInt(paramVec.at(i++));
|
||||
gid = StringTk::strToUInt(paramVec.at(i++));
|
||||
size = StringTk::strToInt64(paramVec.at(i++));
|
||||
numLinks = StringTk::strToUInt(paramVec.at(i++));
|
||||
if (i<paramVec.size())
|
||||
isBuddyMirrored = StringTk::strToBool(paramVec.at(i));
|
||||
else
|
||||
isBuddyMirrored = false;
|
||||
}
|
||||
catch (std::out_of_range& e)
|
||||
{
|
||||
std::string paramFormatStr =
|
||||
"entryID parentDirID parentNodeID ownerNodeID mode uid gid size numLinks "
|
||||
"[isBuddyMirrored]";
|
||||
return "Invalid or missing parameters; Parameter format: " + paramFormatStr;
|
||||
}
|
||||
|
||||
DirInode* dirInode = metaStore->referenceDir(entryID, isBuddyMirrored, true);
|
||||
|
||||
if ( !dirInode )
|
||||
return "Could not find directory with ID: " + entryID;
|
||||
|
||||
StatData statData;
|
||||
if ( dirInode->getStatData(statData) != FhgfsOpsErr_SUCCESS )
|
||||
{
|
||||
metaStore->releaseDir(entryID);
|
||||
return "Could not get stat data for requested dir inode";
|
||||
}
|
||||
|
||||
dirInode->setParentInfoInitial(parentDirID, parentNodeID);
|
||||
dirInode->setOwnerNodeID(ownerNodeID);
|
||||
|
||||
statData.setMode(mode);
|
||||
statData.setUserID(uid);
|
||||
statData.setGroupID(gid);
|
||||
statData.setFileSize(size);
|
||||
statData.setNumHardLinks(numLinks);
|
||||
|
||||
dirInode->setStatData(statData);
|
||||
|
||||
metaStore->releaseDir(entryID);
|
||||
|
||||
return "OK";
|
||||
}
|
||||
|
||||
|
||||
std::string GenericDebugMsgEx::processOpWriteInlinedFileInode(std::istringstream& commandStream)
|
||||
{
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
std::string retStr = "OK";
|
||||
|
||||
// get parameters from command string
|
||||
StringVector paramVec;
|
||||
StringTk::explode(commandStream.str(), ' ', ¶mVec);
|
||||
|
||||
std::string parentDirID;
|
||||
std::string name;
|
||||
std::string entryID;
|
||||
int mode;
|
||||
uint uid;
|
||||
uint gid;
|
||||
int64_t filesize;
|
||||
unsigned numLinks;
|
||||
UInt16Vector stripeTargets;
|
||||
// UInt16Vector* origStripeTargets;
|
||||
|
||||
try
|
||||
{
|
||||
unsigned i = 1;
|
||||
parentDirID = paramVec.at(i++);
|
||||
name = paramVec.at(i++);
|
||||
entryID = paramVec.at(i++);
|
||||
mode = StringTk::strToInt(paramVec.at(i++));
|
||||
uid = StringTk::strToUInt(paramVec.at(i++));
|
||||
gid = StringTk::strToUInt(paramVec.at(i++));
|
||||
filesize = StringTk::strToInt64(paramVec.at(i++));
|
||||
numLinks = StringTk::strToUInt(paramVec.at(i++));
|
||||
StringTk::strToUint16Vec(paramVec.at(i++), &stripeTargets);
|
||||
}
|
||||
catch (std::out_of_range& e)
|
||||
{
|
||||
std::string paramFormatStr =
|
||||
"parentDirID entryName entryID mode uid gid filesize numLinks stripeTargets";
|
||||
return "Invalid or missing parameters; Parameter format: " + paramFormatStr;
|
||||
}
|
||||
|
||||
EntryInfo entryInfo(Program::getApp()->getLocalNodeNumID(), parentDirID, entryID, name,
|
||||
DirEntryType_REGULARFILE, 0);
|
||||
|
||||
auto [fileInode, referenceRes] = metaStore->referenceFile(&entryInfo);
|
||||
|
||||
if (!fileInode)
|
||||
return "Could not reference inode";
|
||||
|
||||
StatData statData;
|
||||
fileInode->getStatData(statData);
|
||||
|
||||
statData.setMode(mode);
|
||||
statData.setUserID(uid);
|
||||
statData.setGroupID(gid);
|
||||
statData.setFileSize(filesize);
|
||||
statData.setNumHardLinks(numLinks);
|
||||
|
||||
fileInode->setStatData(statData);
|
||||
|
||||
StripePattern* pattern = fileInode->getStripePattern();
|
||||
UInt16Vector* origTargets = pattern->getStripeTargetIDsModifyable();
|
||||
*origTargets = stripeTargets;
|
||||
|
||||
fileInode->updateInodeOnDisk(&entryInfo, pattern);
|
||||
|
||||
metaStore->releaseFile(parentDirID, fileInode);
|
||||
|
||||
return retStr;
|
||||
}
|
||||
#endif // BEEGFS_DEBUG
|
||||
36
meta/source/net/message/nodes/GenericDebugMsgEx.h
Normal file
36
meta/source/net/message/nodes/GenericDebugMsgEx.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/GenericDebugMsg.h>
|
||||
#include <common/Common.h>
|
||||
|
||||
|
||||
class GenericDebugMsgEx : public GenericDebugMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
|
||||
private:
|
||||
std::string processCommand();
|
||||
|
||||
std::string processOpListFileAppendLocks(std::istringstream& commandStream);
|
||||
std::string processOpListFileEntryLocks(std::istringstream& commandStream);
|
||||
std::string processOpListFileRangeLocks(std::istringstream& commandStream);
|
||||
std::string processOpListOpenFiles(std::istringstream& commandStream);
|
||||
std::string processOpReferenceStatistics(std::istringstream& commandStream);
|
||||
std::string processOpCacheStatistics(std::istringstream& commandStream);
|
||||
std::string processOpVersion(std::istringstream& commandStream);
|
||||
std::string processOpMsgQueueStats(std::istringstream& commandStream);
|
||||
std::string processOpListPools(std::istringstream& commandStream);
|
||||
std::string processOpDumpDentry(std::istringstream& commandStream);
|
||||
std::string processOpDumpInode(std::istringstream& commandStream);
|
||||
std::string processOpDumpInlinedInode(std::istringstream& commandStream);
|
||||
std::string processOpQuotaExceeded(std::istringstream& commandStream);
|
||||
|
||||
#ifdef BEEGFS_DEBUG
|
||||
std::string processOpWriteDirDentry(std::istringstream& commandStream);
|
||||
std::string processOpWriteDirInode(std::istringstream& commandStream);
|
||||
std::string processOpWriteInlinedFileInode(std::istringstream& commandStream);
|
||||
#endif // BEEGFS_DEBUG
|
||||
|
||||
};
|
||||
|
||||
32
meta/source/net/message/nodes/GetClientStatsMsgEx.cpp
Normal file
32
meta/source/net/message/nodes/GetClientStatsMsgEx.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <program/Program.h>
|
||||
#include <common/net/message/storage/GetHighResStatsRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <common/nodes/OpCounter.h>
|
||||
#include "GetClientStatsMsgEx.h"
|
||||
#include <nodes/MetaNodeOpStats.h>
|
||||
#include <common/net/message/nodes/GetClientStatsRespMsg.h>
|
||||
|
||||
|
||||
/**
|
||||
* Server side gets a GetClientStatsMsgEx request
|
||||
*/
|
||||
bool GetClientStatsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("GetClientStatsMsgEx incoming");
|
||||
|
||||
uint64_t cookieIP = getCookieIP(); // requested is cookie+1
|
||||
|
||||
// get stats
|
||||
MetaNodeOpStats* opStats = Program::getApp()->getNodeOpStats();
|
||||
|
||||
bool wantPerUserStats = isMsgHeaderFeatureFlagSet(GETCLIENTSTATSMSG_FLAG_PERUSERSTATS);
|
||||
UInt64Vector opStatsVec;
|
||||
|
||||
opStats->mapToUInt64Vec(
|
||||
cookieIP, GETCLIENTSTATSRESP_MAX_PAYLOAD_LEN, wantPerUserStats, &opStatsVec);
|
||||
|
||||
ctx.sendResponse(GetClientStatsRespMsg(&opStatsVec) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
12
meta/source/net/message/nodes/GetClientStatsMsgEx.h
Normal file
12
meta/source/net/message/nodes/GetClientStatsMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/storage/StorageErrors.h>
|
||||
#include <common/net/message/nodes/GetClientStatsMsg.h>
|
||||
|
||||
|
||||
class GetClientStatsMsgEx : public GetClientStatsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
65
meta/source/net/message/nodes/GetNodeCapacityPoolsMsgEx.cpp
Normal file
65
meta/source/net/message/nodes/GetNodeCapacityPoolsMsgEx.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <common/net/message/nodes/GetNodeCapacityPoolsRespMsg.h>
|
||||
#include <common/storage/StoragePool.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
#include "GetNodeCapacityPoolsMsgEx.h"
|
||||
|
||||
bool GetNodeCapacityPoolsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
const char* logContext = "GetNodeCapacityPools incoming";
|
||||
|
||||
CapacityPoolQueryType poolType = getCapacityPoolQueryType();
|
||||
|
||||
LOG_DEBUG(logContext, Log_SPAM, "PoolType: " + StringTk::intToStr(poolType) );
|
||||
|
||||
const App* app = Program::getApp();
|
||||
|
||||
GetNodeCapacityPoolsRespMsg::PoolsMap capacityPoolsMap;
|
||||
|
||||
switch(poolType)
|
||||
{
|
||||
case CapacityPoolQuery_META:
|
||||
{
|
||||
const NodeCapacityPools* capPools = app->getMetaCapacityPools();
|
||||
|
||||
capacityPoolsMap[StoragePoolId(StoragePoolStore::INVALID_POOL_ID)] =
|
||||
capPools->getPoolsAsLists();
|
||||
} break;
|
||||
|
||||
case CapacityPoolQuery_STORAGE:
|
||||
{
|
||||
const StoragePoolPtrVec storagePools = app->getStoragePoolStore()->getPoolsAsVec();
|
||||
|
||||
for (auto iter = storagePools.begin(); iter != storagePools.end(); iter++)
|
||||
{
|
||||
const TargetCapacityPools* capPools = (*iter)->getTargetCapacityPools();
|
||||
|
||||
capacityPoolsMap[(*iter)->getId()] = capPools->getPoolsAsLists();
|
||||
}
|
||||
} break;
|
||||
|
||||
case CapacityPoolQuery_STORAGEBUDDIES:
|
||||
{
|
||||
const StoragePoolPtrVec storagePools = app->getStoragePoolStore()->getPoolsAsVec();
|
||||
|
||||
for (auto iter = storagePools.begin(); iter != storagePools.end(); iter++)
|
||||
{
|
||||
const NodeCapacityPools* capPools = (*iter)->getBuddyCapacityPools();
|
||||
|
||||
capacityPoolsMap[(*iter)->getId()] = capPools->getPoolsAsLists();
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
LogContext(logContext).logErr("Invalid pool type: " + StringTk::intToStr(poolType) );
|
||||
|
||||
return false;
|
||||
} break;
|
||||
}
|
||||
|
||||
ctx.sendResponse(GetNodeCapacityPoolsRespMsg(&capacityPoolsMap));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
10
meta/source/net/message/nodes/GetNodeCapacityPoolsMsgEx.h
Normal file
10
meta/source/net/message/nodes/GetNodeCapacityPoolsMsgEx.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/GetNodeCapacityPoolsMsg.h>
|
||||
|
||||
class GetNodeCapacityPoolsMsgEx : public GetNodeCapacityPoolsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
37
meta/source/net/message/nodes/GetNodesMsgEx.cpp
Normal file
37
meta/source/net/message/nodes/GetNodesMsgEx.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <common/net/message/nodes/GetNodesRespMsg.h>
|
||||
#include <program/Program.h>
|
||||
#include "GetNodesMsgEx.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
bool GetNodesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("GetNodes incoming");
|
||||
|
||||
NodeType nodeType = (NodeType)getValue();
|
||||
|
||||
LOG_DEBUG_CONTEXT(log, 5, "NodeType: " + boost::lexical_cast<std::string>(nodeType));
|
||||
|
||||
App* app = Program::getApp();
|
||||
|
||||
NodeStore* nodes = app->getServerStoreFromType(nodeType);
|
||||
if(unlikely(!nodes) )
|
||||
{
|
||||
LOG(GENERAL, ERR, "Invalid node type.",
|
||||
("Node Type", getNodeType()),
|
||||
("Sender", ctx.peerName())
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto nodeList = nodes->referenceAllNodes();
|
||||
|
||||
NumNodeID rootID = app->getMetaRoot().getID();
|
||||
bool rootIsBuddyMirrored = app->getMetaRoot().getIsMirrored();
|
||||
|
||||
ctx.sendResponse(GetNodesRespMsg(rootID, rootIsBuddyMirrored, nodeList) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
10
meta/source/net/message/nodes/GetNodesMsgEx.h
Normal file
10
meta/source/net/message/nodes/GetNodesMsgEx.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/GetNodesMsg.h>
|
||||
|
||||
class GetNodesMsgEx : public GetNodesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
16
meta/source/net/message/nodes/GetTargetMappingsMsgEx.cpp
Normal file
16
meta/source/net/message/nodes/GetTargetMappingsMsgEx.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <common/net/message/nodes/GetTargetMappingsRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <program/Program.h>
|
||||
#include "GetTargetMappingsMsgEx.h"
|
||||
|
||||
|
||||
bool GetTargetMappingsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
TargetMapper* targetMapper = app->getTargetMapper();
|
||||
|
||||
ctx.sendResponse(GetTargetMappingsRespMsg(targetMapper->getMapping()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
11
meta/source/net/message/nodes/GetTargetMappingsMsgEx.h
Normal file
11
meta/source/net/message/nodes/GetTargetMappingsMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/GetTargetMappingsMsg.h>
|
||||
|
||||
class GetTargetMappingsMsgEx : public GetTargetMappingsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
|
||||
90
meta/source/net/message/nodes/HeartbeatMsgEx.cpp
Normal file
90
meta/source/net/message/nodes/HeartbeatMsgEx.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include <common/net/sock/NetworkInterfaceCard.h>
|
||||
#include <program/Program.h>
|
||||
#include "HeartbeatMsgEx.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
bool HeartbeatMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("Heartbeat incoming");
|
||||
|
||||
App* app = Program::getApp();
|
||||
bool isNodeNew;
|
||||
|
||||
// construct node
|
||||
|
||||
NicAddressList& nicList = getNicList();
|
||||
|
||||
auto node = std::make_shared<Node>(getNodeType(), getNodeID(), getNodeNumID(), getPortUDP(),
|
||||
getPortTCP(), nicList);
|
||||
|
||||
// set local nic capabilities
|
||||
|
||||
NicAddressList localNicList(app->getLocalNicList() );
|
||||
NicListCapabilities localNicCaps;
|
||||
|
||||
NetworkInterfaceCard::supportedCapabilities(&localNicList, &localNicCaps);
|
||||
node->getConnPool()->setLocalNicList(localNicList, localNicCaps);
|
||||
|
||||
std::string nodeIDWithTypeStr = node->getNodeIDWithTypeStr();
|
||||
|
||||
log.log(Log_DEBUG, std::string("Heartbeat node: ") + nodeIDWithTypeStr);
|
||||
|
||||
// add/update node in store
|
||||
AbstractNodeStore* nodes = app->getAbstractNodeStoreFromType(getNodeType() );
|
||||
if(!nodes)
|
||||
{
|
||||
log.logErr("Invalid node type: " + StringTk::intToStr(getNodeType() ) +
|
||||
"(" + boost::lexical_cast<std::string>(getNodeType()) + ")");
|
||||
|
||||
goto ack_resp;
|
||||
}
|
||||
|
||||
isNodeNew = (nodes->addOrUpdateNode(std::move(node)) == NodeStoreResult::Added);
|
||||
if( (isNodeNew) && (getNodeType() != NODETYPE_Client) )
|
||||
{ // log info about new server
|
||||
bool supportsRDMA = NetworkInterfaceCard::supportsRDMA(&nicList);
|
||||
|
||||
std::string supports;
|
||||
if (supportsRDMA)
|
||||
supports = "; RDMA.";
|
||||
|
||||
|
||||
log.log(Log_WARNING, std::string("New node: ") + nodeIDWithTypeStr + supports);
|
||||
|
||||
log.log(Log_DEBUG, "Number of nodes: "
|
||||
"Meta: " + StringTk::intToStr(app->getMetaNodes()->getSize() ) + "; "
|
||||
"Storage: " + StringTk::intToStr(app->getStorageNodes()->getSize() ) );
|
||||
}
|
||||
|
||||
processIncomingRoot();
|
||||
|
||||
ack_resp:
|
||||
acknowledge(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the contained root information.
|
||||
*/
|
||||
void HeartbeatMsgEx::processIncomingRoot()
|
||||
{
|
||||
LogContext log("Heartbeat incoming");
|
||||
|
||||
// check whether root info is defined
|
||||
if( (getNodeType() != NODETYPE_Meta) || !getRootNumID() )
|
||||
return;
|
||||
|
||||
// try to apply the contained root info
|
||||
if(Program::getApp()->getMetaRoot().setIfDefault(getRootNumID(), getRootIsBuddyMirrored()))
|
||||
{
|
||||
log.log(Log_CRITICAL, "Root (by Heartbeat): " + getRootNumID().str() );
|
||||
|
||||
Program::getApp()->getRootDir()->setOwnerNodeID(getRootNumID() );
|
||||
if (getRootIsBuddyMirrored())
|
||||
Program::getApp()->getRootDir()->setIsBuddyMirroredFlag(true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
13
meta/source/net/message/nodes/HeartbeatMsgEx.h
Normal file
13
meta/source/net/message/nodes/HeartbeatMsgEx.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/HeartbeatMsg.h>
|
||||
|
||||
class HeartbeatMsgEx : public HeartbeatMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
|
||||
private:
|
||||
void processIncomingRoot();
|
||||
};
|
||||
|
||||
24
meta/source/net/message/nodes/HeartbeatRequestMsgEx.cpp
Normal file
24
meta/source/net/message/nodes/HeartbeatRequestMsgEx.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <common/net/message/nodes/HeartbeatMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <program/Program.h>
|
||||
#include "HeartbeatRequestMsgEx.h"
|
||||
|
||||
bool HeartbeatRequestMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
Config* cfg = app->getConfig();
|
||||
|
||||
Node& localNode = app->getLocalNode();
|
||||
NumNodeID localNodeNumID = localNode.getNumID();
|
||||
NumNodeID rootNodeID = app->getMetaRoot().getID();
|
||||
NicAddressList nicList(localNode.getNicList());
|
||||
|
||||
HeartbeatMsg hbMsg(localNode.getAlias(), localNodeNumID, NODETYPE_Meta, &nicList);
|
||||
hbMsg.setRootNumID(rootNodeID);
|
||||
hbMsg.setPorts(cfg->getConnMetaPort(), cfg->getConnMetaPort() );
|
||||
|
||||
ctx.sendResponse(hbMsg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
10
meta/source/net/message/nodes/HeartbeatRequestMsgEx.h
Normal file
10
meta/source/net/message/nodes/HeartbeatRequestMsgEx.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/HeartbeatRequestMsg.h>
|
||||
|
||||
class HeartbeatRequestMsgEx : public HeartbeatRequestMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
45
meta/source/net/message/nodes/MapTargetsMsgEx.cpp
Normal file
45
meta/source/net/message/nodes/MapTargetsMsgEx.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <common/net/message/nodes/MapTargetsRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <common/toolkit/ZipIterator.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
#include "MapTargetsMsgEx.h"
|
||||
|
||||
|
||||
bool MapTargetsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("MapTargetsMsg incoming");
|
||||
|
||||
const App* app = Program::getApp();
|
||||
const NodeStoreServers* storageNodes = app->getStorageNodes();
|
||||
TargetMapper* targetMapper = app->getTargetMapper();
|
||||
|
||||
const NumNodeID nodeID = getNodeID();
|
||||
std::map<uint16_t, FhgfsOpsErr> results;
|
||||
|
||||
for (const auto mapping : getTargets())
|
||||
{
|
||||
const auto targetId = mapping.first;
|
||||
const auto poolId = mapping.second;
|
||||
|
||||
const auto mapRes = targetMapper->mapTarget(targetId, nodeID, poolId);
|
||||
|
||||
results[targetId] = mapRes.first;
|
||||
|
||||
if ( (mapRes.first != FhgfsOpsErr_SUCCESS) && (mapRes.second) )
|
||||
{ // target could be mapped and is new
|
||||
LOG_DEBUG_CONTEXT(log, Log_WARNING, "Mapping "
|
||||
"target " + StringTk::uintToStr(targetId) +
|
||||
" => " +
|
||||
storageNodes->getNodeIDWithTypeStr(nodeID) );
|
||||
|
||||
IGNORE_UNUSED_VARIABLE(storageNodes);
|
||||
}
|
||||
}
|
||||
|
||||
if(!acknowledge(ctx) )
|
||||
ctx.sendResponse(MapTargetsRespMsg(results));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
11
meta/source/net/message/nodes/MapTargetsMsgEx.h
Normal file
11
meta/source/net/message/nodes/MapTargetsMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/MapTargetsMsg.h>
|
||||
|
||||
class MapTargetsMsgEx : public MapTargetsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
|
||||
23
meta/source/net/message/nodes/PublishCapacitiesMsgEx.cpp
Normal file
23
meta/source/net/message/nodes/PublishCapacitiesMsgEx.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
#include "PublishCapacitiesMsgEx.h"
|
||||
|
||||
|
||||
bool PublishCapacitiesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("PublishCapacitiesMsg incoming");
|
||||
|
||||
App* app = Program::getApp();
|
||||
InternodeSyncer* syncer = app->getInternodeSyncer();
|
||||
|
||||
|
||||
// force upload of capacity information
|
||||
syncer->setForcePublishCapacities();
|
||||
|
||||
// send response
|
||||
acknowledge(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
12
meta/source/net/message/nodes/PublishCapacitiesMsgEx.h
Normal file
12
meta/source/net/message/nodes/PublishCapacitiesMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/PublishCapacitiesMsg.h>
|
||||
|
||||
|
||||
class PublishCapacitiesMsgEx : public PublishCapacitiesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
|
||||
23
meta/source/net/message/nodes/RefreshCapacityPoolsMsgEx.cpp
Normal file
23
meta/source/net/message/nodes/RefreshCapacityPoolsMsgEx.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <program/Program.h>
|
||||
#include "RefreshCapacityPoolsMsgEx.h"
|
||||
|
||||
|
||||
bool RefreshCapacityPoolsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("RefreshCapacityPoolsMsg incoming");
|
||||
|
||||
App* app = Program::getApp();
|
||||
InternodeSyncer* syncer = app->getInternodeSyncer();
|
||||
|
||||
|
||||
// force update of capacity pools
|
||||
syncer->setForcePoolsUpdate();
|
||||
|
||||
|
||||
// send response
|
||||
acknowledge(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
11
meta/source/net/message/nodes/RefreshCapacityPoolsMsgEx.h
Normal file
11
meta/source/net/message/nodes/RefreshCapacityPoolsMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/RefreshCapacityPoolsMsg.h>
|
||||
|
||||
|
||||
class RefreshCapacityPoolsMsgEx : public RefreshCapacityPoolsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
22
meta/source/net/message/nodes/RefreshTargetStatesMsgEx.cpp
Normal file
22
meta/source/net/message/nodes/RefreshTargetStatesMsgEx.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
#include "RefreshTargetStatesMsgEx.h"
|
||||
|
||||
|
||||
bool RefreshTargetStatesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("RefreshTargetStatesMsg incoming");
|
||||
|
||||
App* app = Program::getApp();
|
||||
InternodeSyncer* syncer = app->getInternodeSyncer();
|
||||
|
||||
// force update of target states
|
||||
syncer->setForceTargetStatesUpdate();
|
||||
|
||||
// send response
|
||||
acknowledge(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
11
meta/source/net/message/nodes/RefreshTargetStatesMsgEx.h
Normal file
11
meta/source/net/message/nodes/RefreshTargetStatesMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/RefreshTargetStatesMsg.h>
|
||||
|
||||
|
||||
class RefreshTargetStatesMsgEx : public RefreshTargetStatesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
34
meta/source/net/message/nodes/RemoveNodeMsgEx.cpp
Normal file
34
meta/source/net/message/nodes/RemoveNodeMsgEx.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <common/net/message/nodes/RemoveNodeRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <program/Program.h>
|
||||
#include "RemoveNodeMsgEx.h"
|
||||
|
||||
|
||||
bool RemoveNodeMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
|
||||
LOG_DBG(GENERAL, SPAM, "Removing node.", getNodeNumID());
|
||||
|
||||
if (getNodeType() == NODETYPE_Meta || getNodeType() == NODETYPE_Storage)
|
||||
{
|
||||
NodeStoreServers* nodes = app->getServerStoreFromType(getNodeType());
|
||||
auto node = nodes->referenceNode(getNodeNumID());
|
||||
bool delRes = nodes->deleteNode(getNodeNumID());
|
||||
|
||||
// log
|
||||
if (delRes)
|
||||
{
|
||||
LOG(GENERAL, WARNING, "Node removed.", ("node", node->getNodeIDWithTypeStr()));
|
||||
LOG(GENERAL, WARNING, "Number of nodes in the system:",
|
||||
("meta", app->getMetaNodes()->getSize()),
|
||||
("storage", app->getStorageNodes()->getSize()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!acknowledge(ctx))
|
||||
ctx.sendResponse(RemoveNodeRespMsg(0));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
11
meta/source/net/message/nodes/RemoveNodeMsgEx.h
Normal file
11
meta/source/net/message/nodes/RemoveNodeMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/RemoveNodeMsg.h>
|
||||
|
||||
class RemoveNodeMsgEx : public RemoveNodeMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
|
||||
48
meta/source/net/message/nodes/SetMirrorBuddyGroupMsgEx.cpp
Normal file
48
meta/source/net/message/nodes/SetMirrorBuddyGroupMsgEx.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <common/net/message/nodes/SetMirrorBuddyGroupRespMsg.h>
|
||||
#include <common/nodes/MirrorBuddyGroupMapper.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
|
||||
#include <program/Program.h>
|
||||
|
||||
#include "SetMirrorBuddyGroupMsgEx.h"
|
||||
|
||||
bool SetMirrorBuddyGroupMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LogContext log("SetMirrorBuddyGroupMsg incoming");
|
||||
|
||||
App* app = Program::getApp();
|
||||
|
||||
MirrorBuddyGroupMapper* buddyGroupMapper;
|
||||
NodeType nodeType = getNodeType();
|
||||
|
||||
switch (nodeType)
|
||||
{
|
||||
case NODETYPE_Storage:
|
||||
buddyGroupMapper = app->getStorageBuddyGroupMapper();
|
||||
break;
|
||||
|
||||
case NODETYPE_Meta:
|
||||
buddyGroupMapper = app->getMetaBuddyGroupMapper();
|
||||
break;
|
||||
|
||||
default:
|
||||
log.logErr("Node type mismatch");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint16_t buddyGroupID = this->getBuddyGroupID();
|
||||
uint16_t primaryTargetID = this->getPrimaryTargetID();
|
||||
uint16_t secondaryTargetID = this->getSecondaryTargetID();
|
||||
bool allowUpdate = this->getAllowUpdate();
|
||||
uint16_t newBuddyGroupID = 0;
|
||||
|
||||
FhgfsOpsErr mapResult = buddyGroupMapper->mapMirrorBuddyGroup(buddyGroupID, primaryTargetID,
|
||||
secondaryTargetID, app->getLocalNode().getNumID(), allowUpdate, &newBuddyGroupID);
|
||||
|
||||
if(!acknowledge(ctx) )
|
||||
ctx.sendResponse(SetMirrorBuddyGroupRespMsg(mapResult, newBuddyGroupID) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
11
meta/source/net/message/nodes/SetMirrorBuddyGroupMsgEx.h
Normal file
11
meta/source/net/message/nodes/SetMirrorBuddyGroupMsgEx.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/SetMirrorBuddyGroupMsg.h>
|
||||
|
||||
class SetMirrorBuddyGroupMsgEx : public SetMirrorBuddyGroupMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#include <common/net/message/nodes/SetTargetConsistencyStatesRespMsg.h>
|
||||
#include <common/nodes/TargetStateStore.h>
|
||||
#include <common/toolkit/ZipIterator.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
#include "SetTargetConsistencyStatesMsgEx.h"
|
||||
|
||||
bool SetTargetConsistencyStatesMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
const char* logContext = "Set target states incoming";
|
||||
|
||||
App* app = Program::getApp();
|
||||
InternodeSyncer* internodeSyncer = app->getInternodeSyncer();
|
||||
FhgfsOpsErr result = FhgfsOpsErr_SUCCESS;
|
||||
|
||||
if (getTargetIDs().size() != 1 || getStates().size() != 1)
|
||||
{
|
||||
LogContext(logContext).logErr("Invalid list size of target ID or state List (must be 1).");
|
||||
result = FhgfsOpsErr_INTERNAL;
|
||||
goto send_response;
|
||||
}
|
||||
|
||||
if (getTargetIDs().front() != app->getLocalNodeNumID().val() )
|
||||
{
|
||||
LogContext(logContext).logErr("ID in message does not match local node ID.");
|
||||
result = FhgfsOpsErr_INTERNAL;
|
||||
goto send_response;
|
||||
}
|
||||
|
||||
internodeSyncer->setNodeConsistencyState(
|
||||
static_cast<TargetConsistencyState>(getStates().front() ) );
|
||||
|
||||
send_response:
|
||||
ctx.sendResponse(SetTargetConsistencyStatesRespMsg(result) );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/SetTargetConsistencyStatesMsg.h>
|
||||
|
||||
class SetTargetConsistencyStatesMsgEx : public SetTargetConsistencyStatesMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "RefreshStoragePoolsMsgEx.h"
|
||||
|
||||
#include <program/Program.h>
|
||||
|
||||
bool RefreshStoragePoolsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
Program::getApp()->getInternodeSyncer()->setForceStoragePoolsUpdate();
|
||||
|
||||
// can only come as an AcknowledgableMsg from mgmtd
|
||||
acknowledge(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/nodes/storagepools/RefreshStoragePoolsMsg.h>
|
||||
|
||||
class RefreshStoragePoolsMsgEx : public RefreshStoragePoolsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
38
meta/source/net/message/session/AckNotifyMsgEx.h
Normal file
38
meta/source/net/message/session/AckNotifyMsgEx.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/session/AckNotifyMsg.h>
|
||||
#include <common/net/message/session/AckNotifyRespMsg.h>
|
||||
#include <net/message/MirroredMessage.h>
|
||||
#include <session/MirrorMessageResponseState.h>
|
||||
|
||||
class AckNotifiyMsgEx : public MirroredMessage<AckNotifiyMsg, std::tuple<>>
|
||||
{
|
||||
public:
|
||||
typedef ErrorCodeResponseState<
|
||||
AckNotifiyRespMsg,
|
||||
NETMSGTYPE_AckNotify> ResponseState;
|
||||
|
||||
std::unique_ptr<MirroredMessageResponseState> executeLocally(ResponseContext&, bool) override
|
||||
{
|
||||
// do nothing at all. MirroredMessage has taken care of everything
|
||||
return boost::make_unique<ResponseState>(FhgfsOpsErr_SUCCESS);
|
||||
}
|
||||
|
||||
std::tuple<> lock(EntryLockStore&) override { return {}; }
|
||||
|
||||
bool isMirrored() override { return true; }
|
||||
|
||||
private:
|
||||
void forwardToSecondary(ResponseContext& ctx) override
|
||||
{
|
||||
sendToSecondary(ctx, *this, NETMSGTYPE_AckNotifyResp);
|
||||
}
|
||||
|
||||
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
|
||||
{
|
||||
return static_cast<AckNotifiyRespMsg&>(resp).getResult();
|
||||
}
|
||||
|
||||
const char* mirrorLogContext() const override { return "AckNotifiyMsgEx/forward"; }
|
||||
};
|
||||
|
||||
62
meta/source/net/message/session/BumpFileVersionMsgEx.cpp
Normal file
62
meta/source/net/message/session/BumpFileVersionMsgEx.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "BumpFileVersionMsgEx.h"
|
||||
|
||||
#include <components/FileEventLogger.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
bool BumpFileVersionMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LOG_DBG(SESSIONS, DEBUG, "", getEntryInfo().getEntryID(), getEntryInfo().getIsBuddyMirrored(),
|
||||
hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond),
|
||||
isMsgHeaderFeatureFlagSet(BUMPFILEVERSIONMSG_FLAG_PERSISTENT),
|
||||
isMsgHeaderFeatureFlagSet(BUMPFILEVERSIONMSG_FLAG_HASEVENT));
|
||||
if (isMsgHeaderFeatureFlagSet(BUMPFILEVERSIONMSG_FLAG_HASEVENT))
|
||||
LOG_DBG(SESSIONS, DEBUG, "", int(getFileEvent()->type), getFileEvent()->path);
|
||||
|
||||
return BaseType::processIncoming(ctx);
|
||||
}
|
||||
|
||||
FileIDLock BumpFileVersionMsgEx::lock(EntryLockStore& store)
|
||||
{
|
||||
return {&store, getEntryInfo().getEntryID(), true};
|
||||
}
|
||||
|
||||
std::unique_ptr<MirroredMessageResponseState> BumpFileVersionMsgEx::executeLocally(
|
||||
ResponseContext& ctx, bool isSecondary)
|
||||
{
|
||||
auto* app = Program::getApp();
|
||||
auto* metaStore = app->getMetaStore();
|
||||
|
||||
auto [inode, referenceRes] = metaStore->referenceFile(&getEntryInfo());
|
||||
if (!inode)
|
||||
return boost::make_unique<ResponseState>(FhgfsOpsErr_INTERNAL);
|
||||
|
||||
if (isMsgHeaderFeatureFlagSet(BUMPFILEVERSIONMSG_FLAG_PERSISTENT) &&
|
||||
!inode->incrementFileVersion(&getEntryInfo()))
|
||||
{
|
||||
metaStore->releaseFile(getEntryInfo().getParentEntryID(), inode);
|
||||
return boost::make_unique<ResponseState>(FhgfsOpsErr_SAVEERROR);
|
||||
}
|
||||
|
||||
if (!isSecondary && app->getFileEventLogger() && getFileEvent())
|
||||
{
|
||||
EventContext eventCtx = makeEventContext(
|
||||
&getEntryInfo(),
|
||||
getEntryInfo().getParentEntryID(),
|
||||
getMsgHeaderUserID(),
|
||||
"",
|
||||
inode->getNumHardlinks(),
|
||||
isSecondary
|
||||
);
|
||||
|
||||
logEvent(app->getFileEventLogger(), *getFileEvent(), eventCtx);
|
||||
}
|
||||
|
||||
metaStore->releaseFile(getEntryInfo().getParentEntryID(), inode);
|
||||
return boost::make_unique<ResponseState>(FhgfsOpsErr_SUCCESS);
|
||||
}
|
||||
|
||||
void BumpFileVersionMsgEx::forwardToSecondary(ResponseContext& ctx)
|
||||
{
|
||||
unsetMsgHeaderFeatureFlag(BUMPFILEVERSIONMSG_FLAG_HASEVENT);
|
||||
sendToSecondary(ctx, *this, NETMSGTYPE_BumpFileVersionResp);
|
||||
}
|
||||
32
meta/source/net/message/session/BumpFileVersionMsgEx.h
Normal file
32
meta/source/net/message/session/BumpFileVersionMsgEx.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/session/BumpFileVersionMsg.h>
|
||||
#include <common/net/message/session/BumpFileVersionRespMsg.h>
|
||||
#include <net/message/MirroredMessage.h>
|
||||
|
||||
class BumpFileVersionMsgEx : public MirroredMessage<BumpFileVersionMsg, FileIDLock>
|
||||
{
|
||||
public:
|
||||
typedef ErrorCodeResponseState<BumpFileVersionRespMsg, NETMSGTYPE_BumpFileVersion>
|
||||
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:
|
||||
void forwardToSecondary(ResponseContext& ctx) override;
|
||||
|
||||
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
|
||||
{
|
||||
return (FhgfsOpsErr) static_cast<BumpFileVersionRespMsg&>(resp).getValue();
|
||||
}
|
||||
|
||||
const char* mirrorLogContext() const override { return "BumpFileVersionMsgEx/forward"; }
|
||||
};
|
||||
|
||||
35
meta/source/net/message/session/GetFileVersionMsgEx.cpp
Normal file
35
meta/source/net/message/session/GetFileVersionMsgEx.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "GetFileVersionMsgEx.h"
|
||||
#include <program/Program.h>
|
||||
|
||||
bool GetFileVersionMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
LOG_DBG(SESSIONS, DEBUG, "", getEntryInfo().getEntryID(), getEntryInfo().getIsBuddyMirrored());
|
||||
return BaseType::processIncoming(ctx);
|
||||
}
|
||||
|
||||
FileIDLock GetFileVersionMsgEx::lock(EntryLockStore& store)
|
||||
{
|
||||
return {&store, getEntryInfo().getEntryID(), false};
|
||||
}
|
||||
|
||||
std::unique_ptr<MirroredMessageResponseState> GetFileVersionMsgEx::executeLocally(ResponseContext& ctx,
|
||||
bool isSecondary)
|
||||
{
|
||||
GetFileVersionMsgResponseState resp;
|
||||
|
||||
auto& metaStore = *Program::getApp()->getMetaStore();
|
||||
auto [inode, referenceRes] = metaStore.referenceFile(&getEntryInfo());
|
||||
if (!inode)
|
||||
{
|
||||
// The GetFileVersionMsgResponseState constructor sets default values for 'result' and
|
||||
// 'version', indicating an error condition, eliminating the need to specify them
|
||||
// separately. Hence, returning a ResponseState with the moved 'resp'.
|
||||
return boost::make_unique<ResponseState>(std::move(resp));
|
||||
}
|
||||
|
||||
resp.setGetFileVersionResult(FhgfsOpsErr_SUCCESS);
|
||||
resp.setFileVersion(inode->getFileVersion());
|
||||
metaStore.releaseFile(getEntryInfo().getParentEntryID(), inode);
|
||||
|
||||
return boost::make_unique<ResponseState>(std::move(resp));
|
||||
}
|
||||
74
meta/source/net/message/session/GetFileVersionMsgEx.h
Normal file
74
meta/source/net/message/session/GetFileVersionMsgEx.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/session/GetFileVersionMsg.h>
|
||||
#include <common/net/message/session/GetFileVersionRespMsg.h>
|
||||
#include <common/net/message/session/GetFileVersionRespMsg.h>
|
||||
#include <net/message/MirroredMessage.h>
|
||||
|
||||
class GetFileVersionMsgResponseState : public MirroredMessageResponseState
|
||||
{
|
||||
public:
|
||||
GetFileVersionMsgResponseState() : result(FhgfsOpsErr_INTERNAL), version(0)
|
||||
{
|
||||
}
|
||||
|
||||
GetFileVersionMsgResponseState(GetFileVersionMsgResponseState&& other) :
|
||||
result(other.result),
|
||||
version(other.version)
|
||||
{
|
||||
}
|
||||
|
||||
void sendResponse(NetMessage::ResponseContext& ctx) override
|
||||
{
|
||||
GetFileVersionRespMsg resp(result, version);
|
||||
ctx.sendResponse(resp);
|
||||
}
|
||||
|
||||
// GetFileVersionMsgEx 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 changeObservableState() function to always return false ensures
|
||||
// that this message is never forwarded unnecessarily.
|
||||
bool changesObservableState() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void setGetFileVersionResult(FhgfsOpsErr result) { this->result = result; }
|
||||
void setFileVersion(uint32_t version) { this->version = version; }
|
||||
|
||||
protected:
|
||||
uint32_t serializerTag() const override { return NETMSGTYPE_GetFileVersion; }
|
||||
void serializeContents(Serializer& ser) const override {}
|
||||
|
||||
private:
|
||||
FhgfsOpsErr result;
|
||||
uint32_t version;
|
||||
};
|
||||
|
||||
class GetFileVersionMsgEx : public MirroredMessage<GetFileVersionMsg, FileIDLock>
|
||||
{
|
||||
public:
|
||||
typedef GetFileVersionMsgResponseState ResponseState;
|
||||
virtual bool processIncoming(ResponseContext& ctx) override;
|
||||
|
||||
FileIDLock lock(EntryLockStore& store) override;
|
||||
bool isMirrored() override
|
||||
{
|
||||
return getEntryInfo().getIsBuddyMirrored();
|
||||
}
|
||||
|
||||
private:
|
||||
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 "GetFileVersionMsgEx/forward"; }
|
||||
};
|
||||
|
||||
57
meta/source/net/message/session/locking/FLockAppendMsgEx.cpp
Normal file
57
meta/source/net/message/session/locking/FLockAppendMsgEx.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include <common/net/message/session/locking/FLockAppendRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <common/toolkit/SessionTk.h>
|
||||
#include <net/msghelpers/MsgHelperLocking.h>
|
||||
#include <program/Program.h>
|
||||
#include <session/SessionStore.h>
|
||||
#include <storage/MetaStore.h>
|
||||
#include "FLockAppendMsgEx.h"
|
||||
|
||||
|
||||
bool FLockAppendMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
/* note: this code is very similar to FLockRangeMsgEx::processIncoming(), so if you change
|
||||
something here, you probably want to change it there, too. */
|
||||
|
||||
#ifdef BEEGFS_DEBUG
|
||||
const char* logContext = "FLockAppendMsg incoming";
|
||||
#endif // BEEGFS_DEBUG
|
||||
|
||||
LOG_DEBUG(logContext, Log_DEBUG, "entryID: " + this->getEntryInfo()->getEntryID());
|
||||
|
||||
clientResult = FhgfsOpsErr_INTERNAL;
|
||||
return BaseType::processIncoming(ctx);
|
||||
}
|
||||
|
||||
FileIDLock FLockAppendMsgEx::lock(EntryLockStore& store)
|
||||
{
|
||||
return {&store, getEntryInfo()->getEntryID(), true};
|
||||
}
|
||||
|
||||
std::unique_ptr<MirroredMessageResponseState> FLockAppendMsgEx::executeLocally(ResponseContext& ctx,
|
||||
bool isSecondary)
|
||||
{
|
||||
const char* logContext = "FLock Append Msg";
|
||||
|
||||
unsigned ownerFD = SessionTk::ownerFDFromHandleID(getFileHandleID() );
|
||||
|
||||
EntryLockDetails lockDetails(getClientNumID(), getClientFD(), getOwnerPID(), getLockAckID(),
|
||||
getLockTypeFlags() );
|
||||
|
||||
LogContext(logContext).log(Log_DEBUG, lockDetails.toString());
|
||||
|
||||
EntryInfo* entryInfo = getEntryInfo();
|
||||
clientResult = MsgHelperLocking::flockAppend(entryInfo, ownerFD, lockDetails);
|
||||
|
||||
LogContext(logContext).log(Log_DEBUG, "FLock Append result: " + std::to_string(clientResult));
|
||||
|
||||
Program::getApp()->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(),
|
||||
MetaOpCounter_FLOCKAPPEND, getMsgHeaderUserID() );
|
||||
|
||||
return boost::make_unique<ResponseState>(clientResult);
|
||||
}
|
||||
|
||||
void FLockAppendMsgEx::forwardToSecondary(ResponseContext& ctx)
|
||||
{
|
||||
sendToSecondary(ctx, *this, NETMSGTYPE_FLockAppendResp, clientResult);
|
||||
}
|
||||
32
meta/source/net/message/session/locking/FLockAppendMsgEx.h
Normal file
32
meta/source/net/message/session/locking/FLockAppendMsgEx.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/session/locking/FLockAppendMsg.h>
|
||||
#include <common/net/message/session/locking/FLockAppendRespMsg.h>
|
||||
#include <net/message/MirroredMessage.h>
|
||||
#include <common/storage/StorageErrors.h>
|
||||
#include <storage/FileInode.h>
|
||||
|
||||
class FLockAppendMsgEx : public MirroredMessage<FLockAppendMsg, FileIDLock>
|
||||
{
|
||||
public:
|
||||
typedef ErrorCodeResponseState<FLockAppendRespMsg, NETMSGTYPE_FLockAppend> 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:
|
||||
FhgfsOpsErr clientResult;
|
||||
|
||||
void forwardToSecondary(ResponseContext& ctx) override;
|
||||
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
|
||||
{
|
||||
return static_cast<FLockAppendRespMsg&>(resp).getResult();
|
||||
}
|
||||
|
||||
const char* mirrorLogContext() const override { return "FLockAppendMsgEx/forward"; }
|
||||
};
|
||||
|
||||
135
meta/source/net/message/session/locking/FLockEntryMsgEx.cpp
Normal file
135
meta/source/net/message/session/locking/FLockEntryMsgEx.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#include <common/net/message/session/locking/FLockEntryRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <common/toolkit/SessionTk.h>
|
||||
#include <net/msghelpers/MsgHelperLocking.h>
|
||||
#include <program/Program.h>
|
||||
#include <session/SessionStore.h>
|
||||
#include <storage/MetaStore.h>
|
||||
#include "FLockEntryMsgEx.h"
|
||||
|
||||
|
||||
bool FLockEntryMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
/* note: this code is very similar to FLockRangeMsgEx::processIncoming(), so if you change
|
||||
something here, you probably want to change it there, too. */
|
||||
|
||||
clientResult = FhgfsOpsErr_INTERNAL;
|
||||
|
||||
updateNodeOp(ctx, MetaOpCounter_FLOCKENTRY);
|
||||
|
||||
return BaseType::processIncoming(ctx);
|
||||
}
|
||||
|
||||
FileIDLock FLockEntryMsgEx::lock(EntryLockStore& store)
|
||||
{
|
||||
return {&store, getEntryInfo()->getEntryID(), true};
|
||||
}
|
||||
|
||||
std::unique_ptr<MirroredMessageResponseState> FLockEntryMsgEx::executeLocally(ResponseContext& ctx,
|
||||
bool isSecondary)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
MetaStore* metaStore = app->getMetaStore();
|
||||
|
||||
unsigned ownerFD = SessionTk::ownerFDFromHandleID(getFileHandleID() );
|
||||
|
||||
EntryLockDetails lockDetails(getClientNumID(), getClientFD(), getOwnerPID(), getLockAckID(),
|
||||
getLockTypeFlags() );
|
||||
|
||||
LOG_DBG(GENERAL, SPAM, lockDetails.toString());
|
||||
|
||||
EntryInfo* entryInfo = getEntryInfo();
|
||||
|
||||
SessionStore* sessions = entryInfo->getIsBuddyMirrored()
|
||||
? app->getMirroredSessions()
|
||||
: app->getSessions();
|
||||
|
||||
// find sessionFile
|
||||
Session* session = sessions->referenceSession(getClientNumID(), true);
|
||||
SessionFileStore* sessionFiles = session->getFiles();
|
||||
|
||||
SessionFile* sessionFile = sessionFiles->referenceSession(ownerFD);
|
||||
if(!sessionFile)
|
||||
{ // sessionFile not exists (mds restarted?)
|
||||
|
||||
// check if this is just an UNLOCK REQUEST
|
||||
|
||||
if(getLockTypeFlags() & ENTRYLOCKTYPE_UNLOCK)
|
||||
{ // it's an unlock => we'll just ignore it (since the locks are gone anyways)
|
||||
clientResult = FhgfsOpsErr_SUCCESS;
|
||||
|
||||
goto cleanup_session;
|
||||
}
|
||||
|
||||
// check if this is a LOCK CANCEL REQUEST
|
||||
|
||||
if(getLockTypeFlags() & ENTRYLOCKTYPE_CANCEL)
|
||||
{ // it's a lock cancel
|
||||
/* this is an important special case, because client might have succeeded in closing the
|
||||
file but the conn might have been interrupted during unlock, so we definitely have to try
|
||||
canceling the lock here */
|
||||
|
||||
// if the file still exists, just do the lock cancel without session recovery attempt
|
||||
|
||||
auto [lockCancelFile, referenceRes] = metaStore->referenceFile(entryInfo);
|
||||
if(lockCancelFile)
|
||||
{
|
||||
lockCancelFile->flockEntry(lockDetails);
|
||||
metaStore->releaseFile(entryInfo->getParentEntryID(), lockCancelFile);
|
||||
}
|
||||
|
||||
clientResult = FhgfsOpsErr_SUCCESS;
|
||||
|
||||
goto cleanup_session;
|
||||
}
|
||||
|
||||
// it's a LOCK REQUEST => try to recover session file to do the locking
|
||||
|
||||
clientResult = MsgHelperLocking::trySesssionRecovery(entryInfo, getClientNumID(),
|
||||
ownerFD, sessionFiles, &sessionFile);
|
||||
|
||||
// (note: sessionFile==NULL now if recovery was not successful)
|
||||
|
||||
} // end of session file session recovery attempt
|
||||
|
||||
if(sessionFile)
|
||||
{ // sessionFile exists (or was successfully recovered)
|
||||
auto& file = sessionFile->getInode();
|
||||
|
||||
auto lockGranted = file->flockEntry(lockDetails);
|
||||
if (!lockGranted.first)
|
||||
clientResult = FhgfsOpsErr_WOULDBLOCK;
|
||||
else
|
||||
clientResult = FhgfsOpsErr_SUCCESS;
|
||||
|
||||
if ((getLockTypeFlags() & ENTRYLOCKTYPE_UNLOCK) && !file->incrementFileVersion(entryInfo))
|
||||
{
|
||||
LOG(GENERAL, ERR, "Could not bump file version.", file->getEntryID());
|
||||
sessionFiles->releaseSession(sessionFile, entryInfo);
|
||||
clientResult = FhgfsOpsErr_INTERNAL;
|
||||
goto cleanup_session;
|
||||
}
|
||||
|
||||
if (!lockGranted.second.empty() && !isSecondary)
|
||||
LockingNotifier::notifyWaitersEntryLock(LockEntryNotifyType_FLOCK,
|
||||
file->getReferenceParentID(), file->getEntryID(), file->getIsBuddyMirrored(),
|
||||
std::move(lockGranted.second));
|
||||
|
||||
// cleanup
|
||||
sessionFiles->releaseSession(sessionFile, entryInfo);
|
||||
}
|
||||
|
||||
|
||||
// cleanup
|
||||
cleanup_session:
|
||||
sessions->releaseSession(session);
|
||||
|
||||
LOG_DBG(GENERAL, SPAM, "", getClientNumID(), clientResult);
|
||||
|
||||
return boost::make_unique<ResponseState>(clientResult);
|
||||
}
|
||||
|
||||
void FLockEntryMsgEx::forwardToSecondary(ResponseContext& ctx)
|
||||
{
|
||||
sendToSecondary(ctx, *this, NETMSGTYPE_FLockEntryResp, clientResult);
|
||||
}
|
||||
36
meta/source/net/message/session/locking/FLockEntryMsgEx.h
Normal file
36
meta/source/net/message/session/locking/FLockEntryMsgEx.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/session/locking/FLockEntryMsg.h>
|
||||
#include <common/net/message/session/locking/FLockEntryRespMsg.h>
|
||||
#include <common/storage/StorageErrors.h>
|
||||
#include <net/message/MirroredMessage.h>
|
||||
#include <storage/FileInode.h>
|
||||
|
||||
|
||||
class FLockEntryMsgEx : public MirroredMessage<FLockEntryMsg, FileIDLock>
|
||||
{
|
||||
public:
|
||||
typedef ErrorCodeResponseState<FLockEntryRespMsg, NETMSGTYPE_FLockEntry> 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:
|
||||
FhgfsOpsErr clientResult;
|
||||
|
||||
void forwardToSecondary(ResponseContext& ctx) override;
|
||||
|
||||
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
|
||||
{
|
||||
return static_cast<FLockEntryRespMsg&>(resp).getResult();
|
||||
}
|
||||
|
||||
const char* mirrorLogContext() const override { return "FLockEntryMsgEx/forward"; }
|
||||
};
|
||||
|
||||
134
meta/source/net/message/session/locking/FLockRangeMsgEx.cpp
Normal file
134
meta/source/net/message/session/locking/FLockRangeMsgEx.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include <common/net/message/session/locking/FLockRangeRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <common/toolkit/SessionTk.h>
|
||||
#include <net/msghelpers/MsgHelperLocking.h>
|
||||
#include <program/Program.h>
|
||||
#include <session/SessionStore.h>
|
||||
#include <storage/MetaStore.h>
|
||||
#include "FLockRangeMsgEx.h"
|
||||
|
||||
|
||||
bool FLockRangeMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
/* note: this code is very similar to FLockEntryMsgEx::processIncoming(), so if you change
|
||||
something here, you probably want to change it there, too. */
|
||||
|
||||
clientResult = FhgfsOpsErr_INTERNAL;
|
||||
|
||||
updateNodeOp(ctx, MetaOpCounter_FLOCKRANGE);
|
||||
|
||||
return BaseType::processIncoming(ctx);
|
||||
}
|
||||
|
||||
FileIDLock FLockRangeMsgEx::lock(EntryLockStore& store)
|
||||
{
|
||||
return {&store, getEntryInfo()->getEntryID(), true};
|
||||
}
|
||||
|
||||
std::unique_ptr<MirroredMessageResponseState> FLockRangeMsgEx::executeLocally(ResponseContext& ctx,
|
||||
bool isSecondary)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
MetaStore* metaStore = app->getMetaStore();
|
||||
|
||||
unsigned ownerFD = SessionTk::ownerFDFromHandleID(getFileHandleID() );
|
||||
|
||||
RangeLockDetails lockDetails(getClientNumID(), getOwnerPID(), getLockAckID(),
|
||||
getLockTypeFlags(), getStart(), getEnd() );
|
||||
|
||||
LOG_DBG(GENERAL, SPAM, lockDetails.toString());
|
||||
|
||||
EntryInfo* entryInfo = getEntryInfo();
|
||||
|
||||
SessionStore* sessions = entryInfo->getIsBuddyMirrored()
|
||||
? app->getMirroredSessions()
|
||||
: app->getSessions();
|
||||
|
||||
// find sessionFile
|
||||
Session* session = sessions->referenceSession(getClientNumID(), true);
|
||||
SessionFileStore* sessionFiles = session->getFiles();
|
||||
|
||||
SessionFile* sessionFile = sessionFiles->referenceSession(ownerFD);
|
||||
if(!sessionFile)
|
||||
{ // sessionFile not exists (mds restarted?)
|
||||
|
||||
// check if this is just an UNLOCK REQUEST
|
||||
|
||||
if(getLockTypeFlags() & ENTRYLOCKTYPE_LOCKOPS_REMOVE)
|
||||
{ // it's an unlock => we'll just ignore it (since the locks are gone anyways)
|
||||
clientResult = FhgfsOpsErr_SUCCESS;
|
||||
|
||||
goto cleanup_session;
|
||||
}
|
||||
|
||||
// check if this is a LOCK CANCEL REQUEST
|
||||
|
||||
if(getLockTypeFlags() & ENTRYLOCKTYPE_CANCEL)
|
||||
{ // it's a lock cancel
|
||||
/* this is an important special case, because client might have succeeded in closing the
|
||||
file but the conn might have been interrupted during unlock, so we definitely have to try
|
||||
canceling the lock here */
|
||||
|
||||
// if the file still exists, just do the lock cancel without session recovery attempt
|
||||
|
||||
auto [lockCancelFile, referenceRes] = metaStore->referenceFile(entryInfo);
|
||||
if(lockCancelFile)
|
||||
{
|
||||
lockCancelFile->flockRange(lockDetails);
|
||||
metaStore->releaseFile(entryInfo->getParentEntryID(), lockCancelFile);
|
||||
}
|
||||
|
||||
clientResult = FhgfsOpsErr_SUCCESS;
|
||||
|
||||
goto cleanup_session;
|
||||
}
|
||||
|
||||
// it's a LOCK REQUEST => try to recover session file to do the locking
|
||||
|
||||
clientResult = MsgHelperLocking::trySesssionRecovery(entryInfo, getClientNumID(),
|
||||
ownerFD, sessionFiles, &sessionFile);
|
||||
|
||||
// (note: sessionFile==NULL now if recovery was not successful)
|
||||
|
||||
} // end of session file session recovery attempt
|
||||
|
||||
if(sessionFile)
|
||||
{ // sessionFile exists (or was successfully recovered)
|
||||
auto& file = sessionFile->getInode();
|
||||
|
||||
auto lockGranted = file->flockRange(lockDetails);
|
||||
if (!lockGranted.first)
|
||||
clientResult = FhgfsOpsErr_WOULDBLOCK;
|
||||
else
|
||||
clientResult = FhgfsOpsErr_SUCCESS;
|
||||
|
||||
if ((getLockTypeFlags() & ENTRYLOCKTYPE_UNLOCK) && !file->incrementFileVersion(entryInfo))
|
||||
{
|
||||
LOG(GENERAL, ERR, "Could not bump file version.", file->getEntryID());
|
||||
sessionFiles->releaseSession(sessionFile, entryInfo);
|
||||
clientResult = FhgfsOpsErr_INTERNAL;
|
||||
goto cleanup_session;
|
||||
}
|
||||
|
||||
if (!lockGranted.second.empty() && !isSecondary)
|
||||
LockingNotifier::notifyWaitersRangeLock(file->getReferenceParentID(), file->getEntryID(),
|
||||
file->getIsBuddyMirrored(), std::move(lockGranted.second));
|
||||
|
||||
// cleanup
|
||||
sessionFiles->releaseSession(sessionFile, entryInfo);
|
||||
}
|
||||
|
||||
|
||||
// cleanup
|
||||
cleanup_session:
|
||||
sessions->releaseSession(session);
|
||||
|
||||
LOG_DBG(GENERAL, SPAM, "", clientResult);
|
||||
|
||||
return boost::make_unique<ResponseState>(clientResult);
|
||||
}
|
||||
|
||||
void FLockRangeMsgEx::forwardToSecondary(ResponseContext& ctx)
|
||||
{
|
||||
sendToSecondary(ctx, *this, NETMSGTYPE_FLockRangeResp, clientResult);
|
||||
}
|
||||
36
meta/source/net/message/session/locking/FLockRangeMsgEx.h
Normal file
36
meta/source/net/message/session/locking/FLockRangeMsgEx.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/session/locking/FLockRangeMsg.h>
|
||||
#include <common/net/message/session/locking/FLockRangeRespMsg.h>
|
||||
#include <common/storage/StorageErrors.h>
|
||||
#include <net/message/MirroredMessage.h>
|
||||
#include <storage/FileInode.h>
|
||||
|
||||
|
||||
class FLockRangeMsgEx : public MirroredMessage<FLockRangeMsg, FileIDLock>
|
||||
{
|
||||
public:
|
||||
typedef ErrorCodeResponseState<FLockRangeRespMsg, NETMSGTYPE_FLockRange> 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:
|
||||
FhgfsOpsErr clientResult;
|
||||
|
||||
void forwardToSecondary(ResponseContext& ctx) override;
|
||||
|
||||
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
|
||||
{
|
||||
return static_cast<FLockRangeRespMsg&>(resp).getResult();
|
||||
}
|
||||
|
||||
const char* mirrorLogContext() const override { return "FLockRangeMsgEx/forward"; }
|
||||
};
|
||||
|
||||
246
meta/source/net/message/session/opening/CloseFileMsgEx.cpp
Normal file
246
meta/source/net/message/session/opening/CloseFileMsgEx.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
#include <common/components/streamlistenerv2/IncomingPreprocessedMsgWork.h>
|
||||
#include <common/net/message/control/GenericResponseMsg.h>
|
||||
#include <common/net/message/session/opening/CloseFileRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <common/toolkit/SessionTk.h>
|
||||
#include <components/FileEventLogger.h>
|
||||
#include <net/msghelpers/MsgHelperClose.h>
|
||||
#include <net/msghelpers/MsgHelperLocking.h>
|
||||
#include <program/Program.h>
|
||||
#include <session/EntryLock.h>
|
||||
#include <storage/MetaStore.h>
|
||||
#include "CloseFileMsgEx.h"
|
||||
|
||||
FileIDLock CloseFileMsgEx::lock(EntryLockStore& store)
|
||||
{
|
||||
return {&store, getEntryInfo()->getEntryID(), true};
|
||||
}
|
||||
|
||||
bool CloseFileMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
#ifdef BEEGFS_DEBUG
|
||||
const char* logContext = "CloseFileMsg incoming";
|
||||
#endif // BEEGFS_DEBUG
|
||||
|
||||
LOG_DEBUG(logContext, Log_DEBUG,
|
||||
"BuddyMirrored: " + std::string(getEntryInfo()->getIsBuddyMirrored() ? "Yes" : "No") +
|
||||
" Secondary: " +
|
||||
std::string(hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) ? "Yes" : "No") );
|
||||
|
||||
// update operation counters (here on top because we have an early sock release in this msg)
|
||||
updateNodeOp(ctx, MetaOpCounter_CLOSE);
|
||||
|
||||
return BaseType::processIncoming(ctx);
|
||||
}
|
||||
|
||||
std::unique_ptr<MirroredMessageResponseState> CloseFileMsgEx::executeLocally(ResponseContext& ctx,
|
||||
bool isSecondary)
|
||||
{
|
||||
if (isSecondary)
|
||||
return closeFileSecondary(ctx);
|
||||
else
|
||||
return closeFilePrimary(ctx);
|
||||
}
|
||||
|
||||
std::unique_ptr<CloseFileMsgEx::ResponseState> CloseFileMsgEx::closeFilePrimary(
|
||||
ResponseContext& ctx)
|
||||
{
|
||||
FhgfsOpsErr closeRes;
|
||||
bool unlinkDisposalFile = false;
|
||||
bool outLastWriterClosed = false;
|
||||
EntryInfo* entryInfo = getEntryInfo();
|
||||
unsigned numHardlinks;
|
||||
bool closeSucceeded;
|
||||
|
||||
if(isMsgHeaderFeatureFlagSet(CLOSEFILEMSG_FLAG_CANCELAPPENDLOCKS) )
|
||||
{ // client requests cleanup of granted or pending locks for this handle
|
||||
|
||||
unsigned ownerFD = SessionTk::ownerFDFromHandleID(getFileHandleID() );
|
||||
EntryLockDetails lockDetails(getClientNumID(), 0, 0, "", ENTRYLOCKTYPE_CANCEL);
|
||||
|
||||
MsgHelperLocking::flockAppend(entryInfo, ownerFD, lockDetails);
|
||||
}
|
||||
|
||||
/* two alternatives:
|
||||
1) early response before chunk file close (if client isn't interested in chunks result).
|
||||
2) normal response after chunk file close. */
|
||||
|
||||
// if we are buddy mirrored, *do not* allow early close responses. since the primary will close
|
||||
// the chunk files (and update the inodes dynamic attributes), the secondary cannot do that.
|
||||
// thus we need to close all chunks, get the dynamic attributes, and push them to the secondary
|
||||
if (getEntryInfo()->getIsBuddyMirrored())
|
||||
unsetMsgHeaderFeatureFlag(CLOSEFILEMSG_FLAG_EARLYRESPONSE);
|
||||
|
||||
if(isMsgHeaderFeatureFlagSet(CLOSEFILEMSG_FLAG_EARLYRESPONSE) )
|
||||
{ // alternative 1: client requests an early response
|
||||
|
||||
/* note: linux won't even return the vfs release() result to userspace apps, so there's
|
||||
usually no point in waiting for the chunk file close result before sending the response */
|
||||
|
||||
unsigned accessFlags;
|
||||
MetaFileHandle inode;
|
||||
|
||||
closeRes = MsgHelperClose::closeSessionFile(
|
||||
getClientNumID(), getFileHandleID(), entryInfo, &accessFlags, inode);
|
||||
closeSucceeded = closeRes == FhgfsOpsErr_SUCCESS;
|
||||
|
||||
// send response
|
||||
earlyComplete(ctx, ResponseState(closeRes));
|
||||
|
||||
// if session file close succeeds but chunk file close fails we should not attempt to
|
||||
// dispose. if chunk close failed for any other reason than network outages we might
|
||||
// put the storage server into an even weirder state by unlinking the chunk file:
|
||||
// the file itself is still open (has a session), but is gone on disk, and thus cannot
|
||||
// be reopened from stored sessions when the server is restarted.
|
||||
if(likely(closeRes == FhgfsOpsErr_SUCCESS) )
|
||||
closeRes = closeFileAfterEarlyResponse(std::move(inode), accessFlags, &unlinkDisposalFile,
|
||||
numHardlinks, outLastWriterClosed);
|
||||
}
|
||||
else
|
||||
{ // alternative 2: normal response (after chunk file close)
|
||||
|
||||
closeRes = MsgHelperClose::closeFile(getClientNumID(), getFileHandleID(),
|
||||
entryInfo, getMaxUsedNodeIndex(), getMsgHeaderUserID(), &unlinkDisposalFile,
|
||||
&numHardlinks, outLastWriterClosed, &dynAttribs, &inodeTimestamps);
|
||||
|
||||
closeSucceeded = closeRes == FhgfsOpsErr_SUCCESS;
|
||||
|
||||
if (getEntryInfo()->getIsBuddyMirrored() && getMaxUsedNodeIndex() >= 0)
|
||||
addMsgHeaderFeatureFlag(CLOSEFILEMSG_FLAG_DYNATTRIBS);
|
||||
|
||||
//Avoid sending early response. Let unlink of Disposal file happens.
|
||||
//with Locks held. But make sure before file gets unlink we synchronise
|
||||
//the operation with any on-going buddy mirror resync operation.
|
||||
ResponseState responseState(closeRes);
|
||||
buddyResyncNotify(ctx, responseState.changesObservableState());
|
||||
}
|
||||
|
||||
if (closeSucceeded && Program::getApp()->getFileEventLogger() && getFileEvent())
|
||||
{
|
||||
// Important Note:
|
||||
// - If the last writer, who previously opened this file with write permissions,
|
||||
// is currently closing it,
|
||||
// - And it is not marked for disposal,
|
||||
// - And it is not due to a symlink creation,
|
||||
// Then we update the event type to LAST_WRITER_CLOSED.
|
||||
bool isSymlinkEvent = getFileEvent()->type == FileEventType::SYMLINK;
|
||||
if (!isSymlinkEvent && outLastWriterClosed && !unlinkDisposalFile)
|
||||
{
|
||||
auto fileEvent = const_cast<FileEvent*>(getFileEvent());
|
||||
fileEvent->type = FileEventType::LAST_WRITER_CLOSED;
|
||||
}
|
||||
|
||||
EventContext eventCtx = makeEventContext(
|
||||
entryInfo,
|
||||
entryInfo->getParentEntryID(),
|
||||
getMsgHeaderUserID(),
|
||||
"", // targetParentID
|
||||
numHardlinks,
|
||||
false // This is not the secondary node if closeFilePrimary() was called.
|
||||
);
|
||||
|
||||
logEvent(Program::getApp()->getFileEventLogger(), *getFileEvent(), eventCtx);
|
||||
}
|
||||
|
||||
// unlink if file marked as disposable
|
||||
if( (closeRes == FhgfsOpsErr_SUCCESS) && unlinkDisposalFile)
|
||||
{ // check whether file has been unlinked (and perform the unlink operation on last close)
|
||||
|
||||
/* note: we do this only if also the chunk file close succeeded, because if storage servers
|
||||
are down, unlinkDisposableFile() will keep the file in the disposal store anyways */
|
||||
|
||||
// this only touches timestamps on the disposal dirinode, which is not visible to the user,
|
||||
// so no need to fix up timestamps that have diverged between primary and secondary
|
||||
MsgHelperClose::unlinkDisposableFile(entryInfo->getEntryID(), getMsgHeaderUserID(),
|
||||
entryInfo->getIsBuddyMirrored());
|
||||
}
|
||||
|
||||
//for alternative 2: forward the operation to secondary
|
||||
//after unlinkDisposalFile on primary is complete.
|
||||
if(!isMsgHeaderFeatureFlagSet(CLOSEFILEMSG_FLAG_EARLYRESPONSE))
|
||||
return boost::make_unique<ResponseState>(closeRes);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<CloseFileMsgEx::ResponseState> CloseFileMsgEx::closeFileSecondary(
|
||||
ResponseContext& ctx)
|
||||
{
|
||||
if (isMsgHeaderFeatureFlagSet(CLOSEFILEMSG_FLAG_CANCELAPPENDLOCKS))
|
||||
{
|
||||
// client requests cleanup of granted or pending locks for this handle
|
||||
unsigned ownerFD = SessionTk::ownerFDFromHandleID(getFileHandleID() );
|
||||
EntryLockDetails lockDetails(getClientNumID(), 0, 0, "", ENTRYLOCKTYPE_CANCEL);
|
||||
|
||||
MsgHelperLocking::flockAppend(getEntryInfo(), ownerFD, lockDetails);
|
||||
}
|
||||
|
||||
// on secondary we only need to close the session and the meta file, because the chunk files
|
||||
// will be closed by primary
|
||||
|
||||
unsigned accessFlags;
|
||||
MetaFileHandle inode;
|
||||
|
||||
FhgfsOpsErr closeRes = MsgHelperClose::closeSessionFile(
|
||||
getClientNumID(), getFileHandleID(), getEntryInfo(), &accessFlags, inode);
|
||||
|
||||
// the file may not be open on the secondary, in which case inode == nullptr
|
||||
if (closeRes != FhgfsOpsErr_SUCCESS)
|
||||
return boost::make_unique<ResponseState>(closeRes);
|
||||
|
||||
// maybe assert?
|
||||
if (isMsgHeaderFeatureFlagSet(CLOSEFILEMSG_FLAG_DYNATTRIBS))
|
||||
inode->setDynAttribs(dynAttribs);
|
||||
|
||||
fixInodeTimestamp(*inode, inodeTimestamps, getEntryInfo());
|
||||
|
||||
unsigned numHardlinks;
|
||||
unsigned numInodeRefs;
|
||||
bool outLastWriterClosed;
|
||||
|
||||
Program::getApp()->getMetaStore()->closeFile(getEntryInfo(), std::move(inode), accessFlags,
|
||||
&numHardlinks, &numInodeRefs, outLastWriterClosed);
|
||||
|
||||
// unlink if file marked as disposable
|
||||
// this only touches timestamps on the disposal dirinode, which is not visible to the user,
|
||||
// so no need to fix up timestamps that have diverged between primary and secondary
|
||||
if( (closeRes == FhgfsOpsErr_SUCCESS) && (!numHardlinks) && (!numInodeRefs))
|
||||
MsgHelperClose::unlinkDisposableFile(getEntryInfo()->getEntryID(), getMsgHeaderUserID(),
|
||||
getEntryInfo()->getIsBuddyMirrored());
|
||||
|
||||
return boost::make_unique<ResponseState>(closeRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* The rest after MsgHelperClose::closeSessionFile(), i.e. MsgHelperClose::closeChunkFile()
|
||||
* and metaStore->closeFile().
|
||||
*
|
||||
* @param inode inode for closed file (as returned by MsgHelperClose::closeSessionFile() )
|
||||
* @param maxUsedNodeIndex zero-based index, -1 means "none"
|
||||
* @param outFileWasUnlinked true if the hardlink count of the file was 0
|
||||
*/
|
||||
FhgfsOpsErr CloseFileMsgEx::closeFileAfterEarlyResponse(MetaFileHandle inode, unsigned accessFlags,
|
||||
bool* outUnlinkDisposalFile, unsigned& outNumHardlinks, bool& outLastWriterClosed)
|
||||
{
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
unsigned numInodeRefs;
|
||||
|
||||
*outUnlinkDisposalFile = false;
|
||||
|
||||
FhgfsOpsErr chunksRes = MsgHelperClose::closeChunkFile(
|
||||
getClientNumID(), getFileHandleID(), getMaxUsedNodeIndex(), *inode, getEntryInfo(),
|
||||
getMsgHeaderUserID(), NULL);
|
||||
|
||||
metaStore->closeFile(getEntryInfo(), std::move(inode), accessFlags, &outNumHardlinks,
|
||||
&numInodeRefs, outLastWriterClosed);
|
||||
|
||||
if (!outNumHardlinks && !numInodeRefs)
|
||||
*outUnlinkDisposalFile = true;
|
||||
|
||||
return chunksRes;
|
||||
}
|
||||
|
||||
void CloseFileMsgEx::forwardToSecondary(ResponseContext& ctx)
|
||||
{
|
||||
sendToSecondary(ctx, *this, NETMSGTYPE_CloseFileResp);
|
||||
}
|
||||
38
meta/source/net/message/session/opening/CloseFileMsgEx.h
Normal file
38
meta/source/net/message/session/opening/CloseFileMsgEx.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/storage/StorageErrors.h>
|
||||
#include <common/net/message/session/opening/CloseFileMsg.h>
|
||||
#include <common/net/message/session/opening/CloseFileRespMsg.h>
|
||||
#include <net/message/MirroredMessage.h>
|
||||
#include <session/EntryLock.h>
|
||||
#include <storage/FileInode.h>
|
||||
|
||||
class CloseFileMsgEx : public MirroredMessage<CloseFileMsg, FileIDLock>
|
||||
{
|
||||
public:
|
||||
typedef ErrorCodeResponseState<CloseFileRespMsg, NETMSGTYPE_CloseFile> 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:
|
||||
std::unique_ptr<ResponseState> closeFilePrimary(ResponseContext& ctx);
|
||||
std::unique_ptr<ResponseState> closeFileSecondary(ResponseContext& ctx);
|
||||
void forwardToSecondary(ResponseContext& ctx) override;
|
||||
FhgfsOpsErr closeFileAfterEarlyResponse(MetaFileHandle inode, unsigned accessFlags,
|
||||
bool* outUnlinkDisposalFile, unsigned& numHardlinks, bool& outLastWriterClosed);
|
||||
|
||||
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
|
||||
{
|
||||
return (FhgfsOpsErr) static_cast<CloseFileRespMsg&>(resp).getValue();
|
||||
}
|
||||
|
||||
const char* mirrorLogContext() const override { return "CloseFileMsgEx/forward"; }
|
||||
};
|
||||
|
||||
157
meta/source/net/message/session/opening/OpenFileMsgEx.cpp
Normal file
157
meta/source/net/message/session/opening/OpenFileMsgEx.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
#include <common/net/message/control/GenericResponseMsg.h>
|
||||
#include <common/net/message/session/opening/OpenFileRespMsg.h>
|
||||
#include <common/toolkit/SessionTk.h>
|
||||
#include <common/storage/striping/Raid0Pattern.h>
|
||||
#include <components/FileEventLogger.h>
|
||||
#include <net/msghelpers/MsgHelperOpen.h>
|
||||
#include <program/Program.h>
|
||||
#include <session/EntryLock.h>
|
||||
#include <session/SessionStore.h>
|
||||
#include "OpenFileMsgEx.h"
|
||||
|
||||
FileIDLock OpenFileMsgEx::lock(EntryLockStore& store)
|
||||
{
|
||||
return {&store, getEntryInfo()->getEntryID(), true};
|
||||
}
|
||||
|
||||
bool OpenFileMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
#ifdef BEEGFS_DEBUG
|
||||
const char* logContext = "OpenFileMsg incoming";
|
||||
|
||||
EntryInfo* entryInfo = getEntryInfo();
|
||||
|
||||
LOG_DEBUG(logContext, Log_SPAM, "ParentInfo: " + entryInfo->getParentEntryID() +
|
||||
" EntryID: " + entryInfo->getEntryID() + " FileName: " + entryInfo->getFileName() );
|
||||
|
||||
LOG_DEBUG(logContext, Log_DEBUG,
|
||||
"BuddyMirrored: " + std::string(entryInfo->getIsBuddyMirrored() ? "Yes" : "No") +
|
||||
" Secondary: " +
|
||||
std::string(hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond) ? "Yes" : "No") );
|
||||
#endif // BEEGFS_DEBUG
|
||||
|
||||
return BaseType::processIncoming(ctx);
|
||||
}
|
||||
|
||||
std::unique_ptr<MirroredMessageResponseState> OpenFileMsgEx::executeLocally(ResponseContext& ctx,
|
||||
bool isSecondary)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
|
||||
EntryInfo* entryInfo = this->getEntryInfo();
|
||||
bool useQuota = isMsgHeaderFeatureFlagSet(OPENFILEMSG_FLAG_USE_QUOTA);
|
||||
bool bypassAccessCheck = isMsgHeaderFeatureFlagSet(OPENFILEMSG_FLAG_BYPASS_ACCESS_CHECK);
|
||||
|
||||
const bool eventLoggingEnabled = !isSecondary && app->getFileEventLogger() && getFileEvent();
|
||||
MetaFileHandle inode;
|
||||
|
||||
PathInfo pathInfo;
|
||||
StripePattern* pattern;
|
||||
unsigned sessionFileID;
|
||||
SessionStore* sessions = entryInfo->getIsBuddyMirrored()
|
||||
? app->getMirroredSessions()
|
||||
: app->getSessions();
|
||||
|
||||
FhgfsOpsErr openRes = MsgHelperOpen::openFile(
|
||||
entryInfo, getAccessFlags(), useQuota, bypassAccessCheck, getMsgHeaderUserID(),
|
||||
inode, isSecondary);
|
||||
|
||||
if (openRes == FhgfsOpsErr_SUCCESS && shouldFixTimestamps())
|
||||
fixInodeTimestamp(*inode, fileTimestamps, entryInfo);
|
||||
|
||||
// update operation counters
|
||||
updateNodeOp(ctx, MetaOpCounter_OPEN);
|
||||
|
||||
if (openRes != FhgfsOpsErr_SUCCESS)
|
||||
{
|
||||
// If open() fails due to file state restrictions, emit an OPEN_BLOCKED event
|
||||
// (when event logging is enabled). The numHardlinks in event context will be 0
|
||||
// since inode is nullptr after access denial.
|
||||
if ((openRes == FhgfsOpsErr_FILEACCESS_DENIED) && eventLoggingEnabled)
|
||||
{
|
||||
FileEvent* fileEvent = const_cast<FileEvent*>(getFileEvent());
|
||||
fileEvent->type = FileEventType::OPEN_BLOCKED;
|
||||
|
||||
EventContext eventCtx = makeEventContext(
|
||||
entryInfo,
|
||||
entryInfo->getParentEntryID(),
|
||||
getMsgHeaderUserID(),
|
||||
"",
|
||||
inode ? inode->getNumHardlinks() : 0,
|
||||
isSecondary
|
||||
);
|
||||
logEvent(app->getFileEventLogger(), *fileEvent, eventCtx);
|
||||
}
|
||||
|
||||
// error occurred
|
||||
Raid0Pattern dummyPattern(1, UInt16Vector{});
|
||||
|
||||
// generate response
|
||||
if(unlikely(openRes == FhgfsOpsErr_COMMUNICATION))
|
||||
{
|
||||
return boost::make_unique<OpenFileResponseState>();
|
||||
}
|
||||
else
|
||||
{ // normal response
|
||||
return boost::make_unique<OpenFileResponseState>(openRes, std::string(), dummyPattern,
|
||||
pathInfo, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (eventLoggingEnabled)
|
||||
{
|
||||
EventContext eventCtx = makeEventContext(
|
||||
entryInfo,
|
||||
entryInfo->getParentEntryID(),
|
||||
getMsgHeaderUserID(),
|
||||
"",
|
||||
inode->getNumHardlinks(),
|
||||
isSecondary
|
||||
);
|
||||
|
||||
logEvent(app->getFileEventLogger(), *getFileEvent(), eventCtx);
|
||||
}
|
||||
|
||||
// success => insert session
|
||||
SessionFile* sessionFile = new SessionFile(std::move(inode), getAccessFlags(), entryInfo);
|
||||
|
||||
Session* session = sessions->referenceSession(getClientNumID(), true);
|
||||
|
||||
pattern = sessionFile->getInode()->getStripePattern();
|
||||
|
||||
if (!isSecondary)
|
||||
{
|
||||
sessionFileID = session->getFiles()->addSession(sessionFile);
|
||||
fileHandleID = SessionTk::generateFileHandleID(sessionFileID, entryInfo->getEntryID() );
|
||||
|
||||
setSessionFileID(sessionFileID);
|
||||
setFileHandleID(fileHandleID.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
fileHandleID = getFileHandleID();
|
||||
sessionFileID = getSessionFileID();
|
||||
|
||||
bool addRes = session->getFiles()->addSession(sessionFile, sessionFileID);
|
||||
|
||||
if (!addRes)
|
||||
{
|
||||
const char* logContext = "OpenFileMsgEx (executeLocally)";
|
||||
LogContext(logContext).log(Log_NOTICE,
|
||||
"Couldn't add sessionFile on secondary buddy; sessionID: " + getClientNumID().str()
|
||||
+ "; sessionFileID: " + StringTk::uintToStr(sessionFileID));
|
||||
}
|
||||
}
|
||||
|
||||
sessions->releaseSession(session);
|
||||
|
||||
sessionFile->getInode()->getPathInfo(&pathInfo);
|
||||
|
||||
return boost::make_unique<OpenFileResponseState>(openRes, fileHandleID, *pattern, pathInfo,
|
||||
sessionFile->getInode()->getFileVersion());
|
||||
}
|
||||
|
||||
void OpenFileMsgEx::forwardToSecondary(ResponseContext& ctx)
|
||||
{
|
||||
sendToSecondary(ctx, *this, NETMSGTYPE_OpenFileResp);
|
||||
}
|
||||
105
meta/source/net/message/session/opening/OpenFileMsgEx.h
Normal file
105
meta/source/net/message/session/opening/OpenFileMsgEx.h
Normal file
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/storage/StorageErrors.h>
|
||||
#include <common/net/message/session/opening/OpenFileMsg.h>
|
||||
#include <common/net/message/session/opening/OpenFileRespMsg.h>
|
||||
#include <storage/DirInode.h>
|
||||
#include <storage/FileInode.h>
|
||||
#include <net/message/MirroredMessage.h>
|
||||
#include <session/EntryLock.h>
|
||||
|
||||
class OpenFileResponseState : public MirroredMessageResponseState
|
||||
{
|
||||
public:
|
||||
OpenFileResponseState()
|
||||
: isIndirectCommErr(true)
|
||||
{
|
||||
}
|
||||
|
||||
explicit OpenFileResponseState(Deserializer& des)
|
||||
{
|
||||
serialize(this, des);
|
||||
}
|
||||
|
||||
OpenFileResponseState(FhgfsOpsErr result, const std::string& fileHandleID,
|
||||
const StripePattern& pattern, const PathInfo& pathInfo, uint32_t fileVersion)
|
||||
: isIndirectCommErr(false), result(result), fileHandleID(fileHandleID),
|
||||
pattern(pattern.clone()), pathInfo(pathInfo), fileVersion(fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
void sendResponse(NetMessage::ResponseContext& ctx) override
|
||||
{
|
||||
if (isIndirectCommErr)
|
||||
ctx.sendResponse(
|
||||
GenericResponseMsg(
|
||||
GenericRespMsgCode_INDIRECTCOMMERR,
|
||||
"Communication with storage targets failed"));
|
||||
else
|
||||
ctx.sendResponse(
|
||||
OpenFileRespMsg(
|
||||
result, fileHandleID, pattern.get(), &pathInfo, fileVersion));
|
||||
}
|
||||
|
||||
bool changesObservableState() const override
|
||||
{
|
||||
return !isIndirectCommErr && result == FhgfsOpsErr_SUCCESS;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t serializerTag() const override { return NETMSGTYPE_OpenFile; }
|
||||
|
||||
template<typename This, typename Ctx>
|
||||
static void serialize(This* obj, Ctx& ctx)
|
||||
{
|
||||
ctx
|
||||
% obj->isIndirectCommErr;
|
||||
|
||||
if (!obj->isIndirectCommErr)
|
||||
ctx
|
||||
% serdes::as<int32_t>(obj->result)
|
||||
% obj->fileHandleID
|
||||
% obj->pattern
|
||||
% obj->pathInfo;
|
||||
}
|
||||
|
||||
void serializeContents(Serializer& ser) const override
|
||||
{
|
||||
serialize(this, ser);
|
||||
}
|
||||
|
||||
private:
|
||||
bool isIndirectCommErr;
|
||||
|
||||
FhgfsOpsErr result;
|
||||
std::string fileHandleID;
|
||||
std::unique_ptr<StripePattern> pattern;
|
||||
PathInfo pathInfo;
|
||||
uint32_t fileVersion;
|
||||
};
|
||||
|
||||
class OpenFileMsgEx : public MirroredMessage<OpenFileMsg, FileIDLock>
|
||||
{
|
||||
public:
|
||||
typedef OpenFileResponseState ResponseState;
|
||||
|
||||
bool processIncoming(ResponseContext& ctx) override;
|
||||
|
||||
FileIDLock lock(EntryLockStore& store) override;
|
||||
std::unique_ptr<MirroredMessageResponseState> executeLocally(ResponseContext& ctx,
|
||||
bool isSecondary) override;
|
||||
void forwardToSecondary(ResponseContext& ctx) override;
|
||||
|
||||
bool isMirrored() override { return getEntryInfo()->getIsBuddyMirrored(); }
|
||||
|
||||
private:
|
||||
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
|
||||
{
|
||||
return (FhgfsOpsErr) static_cast<OpenFileRespMsg&>(resp).getResult();
|
||||
}
|
||||
|
||||
const char* mirrorLogContext() const override { return "OpenFileMsgEx/forward"; }
|
||||
|
||||
std::string fileHandleID;
|
||||
};
|
||||
|
||||
20
meta/source/net/message/storage/GetHighResStatsMsgEx.cpp
Normal file
20
meta/source/net/message/storage/GetHighResStatsMsgEx.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <program/Program.h>
|
||||
#include <common/net/message/storage/GetHighResStatsRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include "GetHighResStatsMsgEx.h"
|
||||
|
||||
|
||||
bool GetHighResStatsMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
HighResStatsList statsHistory;
|
||||
uint64_t lastStatsMS = getValue();
|
||||
|
||||
// get stats history
|
||||
StatsCollector* statsCollector = Program::getApp()->getStatsCollector();
|
||||
statsCollector->getStatsSince(lastStatsMS, statsHistory);
|
||||
|
||||
ctx.sendResponse(GetHighResStatsRespMsg(&statsHistory) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
12
meta/source/net/message/storage/GetHighResStatsMsgEx.h
Normal file
12
meta/source/net/message/storage/GetHighResStatsMsgEx.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/storage/StorageErrors.h>
|
||||
#include <common/net/message/storage/GetHighResStatsMsg.h>
|
||||
|
||||
|
||||
class GetHighResStatsMsgEx : public GetHighResStatsMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
};
|
||||
|
||||
49
meta/source/net/message/storage/StatStoragePathMsgEx.cpp
Normal file
49
meta/source/net/message/storage/StatStoragePathMsgEx.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <program/Program.h>
|
||||
#include <common/net/message/storage/StatStoragePathRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include "StatStoragePathMsgEx.h"
|
||||
|
||||
|
||||
bool StatStoragePathMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
int64_t sizeTotal = 0;
|
||||
int64_t sizeFree = 0;
|
||||
int64_t inodesTotal = 0;
|
||||
int64_t inodesFree = 0;
|
||||
|
||||
FhgfsOpsErr statRes = statStoragePath(&sizeTotal, &sizeFree, &inodesTotal, &inodesFree);
|
||||
|
||||
ctx.sendResponse(StatStoragePathRespMsg(statRes, sizeTotal, sizeFree, inodesTotal, inodesFree) );
|
||||
|
||||
App* app = Program::getApp();
|
||||
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), MetaOpCounter_STATFS,
|
||||
getMsgHeaderUserID() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FhgfsOpsErr StatStoragePathMsgEx::statStoragePath(int64_t* outSizeTotal, int64_t* outSizeFree,
|
||||
int64_t* outInodesTotal, int64_t* outInodesFree)
|
||||
{
|
||||
const char* logContext = "StatStoragePathMsg (stat path)";
|
||||
|
||||
std::string pathStr = Program::getApp()->getMetaPath();
|
||||
|
||||
bool statSuccess = StorageTk::statStoragePath(
|
||||
pathStr, outSizeTotal, outSizeFree, outInodesTotal, outInodesFree);
|
||||
|
||||
if(unlikely(!statSuccess) )
|
||||
{ // error
|
||||
LogContext(logContext).logErr("Unable to statfs() storage path: " + pathStr +
|
||||
" (SysErr: " + System::getErrString() );
|
||||
|
||||
return FhgfsOpsErr_INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
StorageTk::statStoragePathOverride(pathStr, outSizeFree, outInodesFree);
|
||||
|
||||
return FhgfsOpsErr_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
18
meta/source/net/message/storage/StatStoragePathMsgEx.h
Normal file
18
meta/source/net/message/storage/StatStoragePathMsgEx.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/storage/StorageErrors.h>
|
||||
#include <common/net/message/storage/StatStoragePathMsg.h>
|
||||
|
||||
// derives from config option "StoragePath" and actually is similar to statfs()
|
||||
|
||||
class StatStoragePathMsgEx : public StatStoragePathMsg
|
||||
{
|
||||
public:
|
||||
virtual bool processIncoming(ResponseContext& ctx);
|
||||
|
||||
private:
|
||||
FhgfsOpsErr statStoragePath(int64_t* outSizeTotal, int64_t* outSizeFree,
|
||||
int64_t* outInodesTotal, int64_t* outInodesFree);
|
||||
};
|
||||
|
||||
|
||||
81
meta/source/net/message/storage/TruncFileMsgEx.cpp
Normal file
81
meta/source/net/message/storage/TruncFileMsgEx.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <common/net/message/control/GenericResponseMsg.h>
|
||||
#include <common/net/message/storage/TruncFileRespMsg.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <components/FileEventLogger.h>
|
||||
#include <net/msghelpers/MsgHelperTrunc.h>
|
||||
#include "TruncFileMsgEx.h"
|
||||
#include <program/Program.h>
|
||||
|
||||
FileIDLock TruncFileMsgEx::lock(EntryLockStore& store)
|
||||
{
|
||||
return {&store, getEntryInfo()->getEntryID(), true};
|
||||
}
|
||||
|
||||
bool TruncFileMsgEx::processIncoming(ResponseContext& ctx)
|
||||
{
|
||||
return BaseType::processIncoming(ctx);
|
||||
}
|
||||
|
||||
std::unique_ptr<MirroredMessageResponseState> TruncFileMsgEx::executeLocally(ResponseContext& ctx,
|
||||
bool isSecondary)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
// update operation counters
|
||||
updateNodeOp(ctx, MetaOpCounter_TRUNCATE);
|
||||
|
||||
MetaStore* metaStore = Program::getApp()->getMetaStore();
|
||||
|
||||
if (!isSecondary)
|
||||
{
|
||||
FhgfsOpsErr truncRes = MsgHelperTrunc::truncFile(getEntryInfo(), getFilesize(),
|
||||
isMsgHeaderFeatureFlagSet(TRUNCFILEMSG_FLAG_USE_QUOTA), getMsgHeaderUserID(),
|
||||
dynAttribs);
|
||||
if (truncRes == FhgfsOpsErr_SUCCESS && (shouldFixTimestamps() || getFileEvent()))
|
||||
{
|
||||
auto [inode, referenceRes] = metaStore->referenceFile(getEntryInfo());
|
||||
unsigned numHardlinks = 0;
|
||||
|
||||
if (likely(inode))
|
||||
{
|
||||
if (shouldFixTimestamps())
|
||||
fixInodeTimestamp(*inode, mirroredTimestamps, nullptr);
|
||||
|
||||
numHardlinks = inode->getNumHardlinks();
|
||||
metaStore->releaseFile(getEntryInfo()->getParentEntryID(), inode);
|
||||
}
|
||||
|
||||
if (app->getFileEventLogger() && getFileEvent())
|
||||
{
|
||||
EventContext eventCtx = makeEventContext(
|
||||
getEntryInfo(),
|
||||
getEntryInfo()->getParentEntryID(),
|
||||
getMsgHeaderUserID(),
|
||||
"",
|
||||
numHardlinks,
|
||||
isSecondary
|
||||
);
|
||||
|
||||
logEvent(app->getFileEventLogger(), *getFileEvent(), eventCtx);
|
||||
}
|
||||
}
|
||||
return boost::make_unique<ResponseState>(truncRes);
|
||||
}
|
||||
|
||||
auto [inode, referenceRes] = metaStore->referenceFile(getEntryInfo());
|
||||
if(!inode)
|
||||
return boost::make_unique<ResponseState>(referenceRes);
|
||||
|
||||
inode->setDynAttribs(dynAttribs);
|
||||
if (shouldFixTimestamps())
|
||||
fixInodeTimestamp(*inode, mirroredTimestamps, nullptr);
|
||||
inode->updateInodeOnDisk(getEntryInfo());
|
||||
|
||||
metaStore->releaseFile(getEntryInfo()->getParentEntryID(), inode);
|
||||
|
||||
return boost::make_unique<ResponseState>(FhgfsOpsErr_SUCCESS);
|
||||
}
|
||||
|
||||
void TruncFileMsgEx::forwardToSecondary(ResponseContext& ctx)
|
||||
{
|
||||
sendToSecondary(ctx, *this, NETMSGTYPE_TruncFileResp);
|
||||
}
|
||||
34
meta/source/net/message/storage/TruncFileMsgEx.h
Normal file
34
meta/source/net/message/storage/TruncFileMsgEx.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/net/message/storage/TruncFileMsg.h>
|
||||
#include <common/net/message/storage/TruncFileRespMsg.h>
|
||||
#include <net/message/MirroredMessage.h>
|
||||
#include <storage/MetaStore.h>
|
||||
|
||||
|
||||
class TruncFileMsgEx : public MirroredMessage<TruncFileMsg, FileIDLock>
|
||||
{
|
||||
public:
|
||||
typedef ErrorCodeResponseState<TruncFileRespMsg, NETMSGTYPE_TruncFile> 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:
|
||||
void forwardToSecondary(ResponseContext& ctx) override;
|
||||
|
||||
FhgfsOpsErr processSecondaryResponse(NetMessage& resp) override
|
||||
{
|
||||
return (FhgfsOpsErr) static_cast<TruncFileRespMsg&>(resp).getValue();
|
||||
}
|
||||
|
||||
const char* mirrorLogContext() const override { return "TruncFileMsgEx/forward"; }
|
||||
};
|
||||
|
||||
|
||||
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"; }
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user