New upstream version 8.1.0

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

View File

@@ -0,0 +1,428 @@
#include <common/net/message/nodes/GenericDebugRespMsg.h>
#include <common/net/msghelpers/MsgHelperGenericDebug.h>
#include <common/storage/quota/Quota.h>
#include <common/storage/StoragePoolId.h>
#include <common/toolkit/MessagingTk.h>
#include <program/Program.h>
#include <session/ZfsSession.h>
#include <toolkit/QuotaTk.h>
#include "GenericDebugMsgEx.h"
#define GENDBGMSG_OP_LISTOPENFILES "listopenfiles"
#define GENDBGMSG_OP_VERSION "version"
#define GENDBGMSG_OP_MSGQUEUESTATS "msgqueuestats"
#define GENDBGMSG_OP_RESYNCQUEUELEN "resyncqueuelen"
#define GENDBGMSG_OP_CHUNKLOCKSTORESIZE "chunklockstoresize"
#define GENDBGMSG_OP_CHUNKLOCKSTORECONTENTS "chunklockstore"
#define GENDBGMSG_OP_SETREJECTIONRATE "setrejectionrate"
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() ) );
App* app = Program::getApp();
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), StorageOpCounter_GENERICDEBUG,
getMsgHeaderUserID() );
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_LISTOPENFILES)
responseStr = processOpListOpenFiles(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_QUOTAEXCEEDED)
responseStr = processOpQuotaExceeded(commandStream);
else
if(operation == GENDBGMSG_OP_USEDQUOTA)
responseStr = processOpUsedQuota(commandStream);
else
if(operation == GENDBGMSG_OP_RESYNCQUEUELEN)
responseStr = processOpResyncQueueLen(commandStream);
else
if(operation == GENDBGMSG_OP_CHUNKLOCKSTORESIZE)
responseStr = processOpChunkLockStoreSize(commandStream);
else
if(operation == GENDBGMSG_OP_CHUNKLOCKSTORECONTENTS)
responseStr = processOpChunkLockStoreContents(commandStream);
else
if(operation == GENDBGMSG_OP_LISTSTORAGESTATES)
responseStr = MsgHelperGenericDebug::processOpListTargetStates(commandStream,
app->getTargetStateStore() );
else
if(operation == GENDBGMSG_OP_SETREJECTIONRATE)
responseStr = processOpSetRejectionRate(commandStream);
else
responseStr = "Unknown/invalid operation";
return responseStr;
}
std::string GenericDebugMsgEx::processOpListOpenFiles(std::istringstream& commandStream)
{
// protocol: no arguments
App* app = Program::getApp();
SessionStore* sessions = app->getSessions();
std::ostringstream responseStream;
NumNodeIDList sessionIDs;
size_t numFilesTotal = 0;
size_t numCheckedSessions = 0; // may defer from number of initially queried sessions
size_t numSessions = sessions->getAllSessionIDs(&sessionIDs);
responseStream << "Found " << numSessions << " sessions." << std::endl;
responseStream << std::endl;
// walk over all sessions
for(NumNodeIDListCIter iter = sessionIDs.begin(); iter != sessionIDs.end(); iter++)
{
// note: sessionID might have become removed since we queried it, e.g. because client is gone
auto session = sessions->referenceSession(*iter);
if(!session)
continue;
numCheckedSessions++;
SessionLocalFileStore* sessionFiles = session->getLocalFiles();
size_t numFiles = sessionFiles->getSize();
if(!numFiles)
continue; // only print sessions with open files
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::processOpVersion(std::istringstream& commandStream)
{
return BEEGFS_VERSION;
}
std::string GenericDebugMsgEx::processOpMsgQueueStats(std::istringstream& commandStream)
{
// protocol: no arguments
App* app = Program::getApp();
MultiWorkQueueMap* workQueueMap = app->getWorkQueueMap();
std::ostringstream responseStream;
std::string indirectQueueStats;
std::string directQueueStats;
std::string busyStats;
for(MultiWorkQueueMapCIter iter = workQueueMap->begin(); iter != workQueueMap->end(); iter++)
{
MultiWorkQueue* workQ = iter->second;
workQ->getStatsAsStr(indirectQueueStats, directQueueStats, busyStats);
responseStream << "* [queue id " << iter->first << "] "
"general queue stats: " << std::endl <<
indirectQueueStats << std::endl;
responseStream << "* [queue id " << iter->first << "] "
"direct queue stats: " << std::endl <<
directQueueStats << std::endl;
responseStream << "* [queue id " << iter->first << "] "
"busy worker stats: " << std::endl <<
busyStats << std::endl;
}
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);
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());
}
std::string GenericDebugMsgEx::processOpUsedQuota(std::istringstream& commandStream)
{
App *app = Program::getApp();
std::ostringstream responseStream;
ZfsSession session;
QuotaDataType quotaDataType = QuotaDataType_NONE;
std::string quotaDataTypeStr;
bool forEachTarget = false;
unsigned rangeStart = 0;
unsigned rangeEnd = 0;
// get parameter from command string
std::string inputString;
while(!commandStream.eof() )
{
std::getline(commandStream, inputString, ' ');
if(inputString == "uid")
{
quotaDataType = QuotaDataType_USER;
quotaDataTypeStr = "user";
}
else
if(inputString == "gid")
{
quotaDataType = QuotaDataType_GROUP;
quotaDataTypeStr = "group";
}
else
if(inputString == "forEachTarget")
forEachTarget = true;
else
if(inputString == "range")
{
std::string rangeValue;
std::getline(commandStream, rangeValue, ' ');
rangeStart = StringTk::strToUInt(rangeValue);
std::getline(commandStream, rangeValue, ' ');
rangeEnd = StringTk::strToUInt(rangeValue);
}
}
// verify given parameters
if(quotaDataType == QuotaDataType_NONE)
return "Invalid or missing quota data type argument.";
if(rangeStart == 0 && rangeEnd == 0)
return "Invalid or missing range argument.";
if(forEachTarget)
{
const auto& targets = app->getStorageTargets()->getTargets();
responseStream << "Quota data of " << targets.size() << " targets." << std::endl;
for (const auto& mapping : targets)
{
const auto& target = *mapping.second;
QuotaDataList outQuotaDataList;
QuotaBlockDeviceMap quotaBlockDevices = {
{mapping.first, target.getQuotaBlockDevice()}
};
QuotaTk::requestQuotaForRange(&quotaBlockDevices, rangeStart, rangeEnd, quotaDataType,
&outQuotaDataList, &session);
responseStream << outQuotaDataList.size() << " used quota for " << quotaDataTypeStr
<< " IDs on target: " << mapping.first << std::endl;
QuotaData::quotaDataListToString(outQuotaDataList, &responseStream);
}
}
else
{
auto& targets = app->getStorageTargets()->getTargets();
QuotaBlockDeviceMap quotaBlockDevices;
std::transform(
targets.begin(), targets.end(),
std::inserter(quotaBlockDevices, quotaBlockDevices.end()),
[] (const auto& target) {
return std::make_pair(target.first, target.second->getQuotaBlockDevice());
});
QuotaDataList outQuotaDataList;
QuotaTk::requestQuotaForRange(&quotaBlockDevices, rangeStart, rangeEnd, quotaDataType,
&outQuotaDataList, &session);
QuotaData::quotaDataListToString(outQuotaDataList, &responseStream);
}
return responseStream.str();
}
std::string GenericDebugMsgEx::processOpResyncQueueLen(std::istringstream& commandStream)
{
// protocol: targetID files/dirs as argument (e.g. "resyncqueuelen 1234 files")
// get parameter from command string
std::string targetIDStr;
uint16_t targetID;
std::string typeStr;
std::getline(commandStream, targetIDStr, ' ');
std::getline(commandStream, typeStr, ' ');
targetID = StringTk::strToUInt(targetIDStr);
if (targetID == 0)
return "Invalid or missing targetID";
BuddyResyncJob* resyncJob = Program::getApp()->getBuddyResyncer()->getResyncJob(targetID);
if (!resyncJob)
return "0";
if (typeStr == "files")
{
size_t count = resyncJob->syncCandidates.getNumFiles();
return StringTk::uintToStr(count);
}
else
if (typeStr == "dirs")
{
size_t count = resyncJob->syncCandidates.getNumDirs();
return StringTk::uintToStr(count);
}
else
return "Invalid or missing queue type";
}
std::string GenericDebugMsgEx::processOpChunkLockStoreSize(std::istringstream& commandStream)
{
// protocol: targetID as argument (e.g. "chunklockstoresize 1234")
// get parameter from command string
std::string targetIDStr;
uint16_t targetID;
std::getline(commandStream, targetIDStr, ' ');
targetID = StringTk::strToUInt(targetIDStr);
if (targetID == 0)
return "Invalid or missing targetID";
size_t lockStoreSize = Program::getApp()->getChunkLockStore()->getSize(targetID);
return StringTk::uintToStr(lockStoreSize);
}
std::string GenericDebugMsgEx::processOpChunkLockStoreContents(std::istringstream& commandStream)
{
// protocol: targetID and size limit (optional) as argument (e.g. "chunklockstoresize 1234 50")
std::stringstream outStream;
// get parameter from command string
std::string targetIDStr;
uint16_t targetID;
std::string maxEntriesStr;
unsigned maxEntries;
std::getline(commandStream, targetIDStr, ' ');
targetID = StringTk::strToUInt(targetIDStr);
std::getline(commandStream, maxEntriesStr, ' ');
maxEntries = StringTk::strToUInt(maxEntriesStr);
if (targetID == 0)
return "Invalid or missing targetID";
StringSet lockStoreContents = Program::getApp()->getChunkLockStore()->getLockStoreCopy(targetID);
unsigned lockStoreSize = lockStoreContents.size();
StringSetIter lockStoreIter = lockStoreContents.begin();
if ( (maxEntries == 0) || (maxEntries > lockStoreSize) )
maxEntries = lockStoreSize;
for (unsigned i = 0; i < maxEntries; i++)
{
outStream << *lockStoreIter << std::endl;
lockStoreIter++;
}
return outStream.str();
}
std::string GenericDebugMsgEx::processOpSetRejectionRate(std::istringstream& commandStream)
{
App* app = Program::getApp();
Config* cfg = app->getConfig();
std::string rejectionRateStr;
std::ostringstream responseStream;
std::getline(commandStream, rejectionRateStr, ' ');
unsigned rejectionRate = StringTk::strToUInt(rejectionRateStr);
cfg->setConnectionRejectionRate(rejectionRate);
responseStream << "Setting connection reject rate to " << rejectionRate << std::endl;
return responseStream.str();
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include <common/net/message/nodes/GenericDebugMsg.h>
class GenericDebugMsgEx : public GenericDebugMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
private:
std::string processCommand();
std::string processOpListOpenFiles(std::istringstream& commandStream);
std::string processOpVersion(std::istringstream& commandStream);
std::string processOpMsgQueueStats(std::istringstream& commandStream);
std::string processOpQuotaExceeded(std::istringstream& commandStream);
std::string processOpUsedQuota(std::istringstream& commandStream);
std::string processOpResyncQueueLen(std::istringstream& commandStream);
std::string processOpChunkLockStoreSize(std::istringstream& commandStream);
std::string processOpChunkLockStoreContents(std::istringstream& commandStream);
std::string processOpSetRejectionRate(std::istringstream& commandStream);
};

View File

@@ -0,0 +1,30 @@
#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/StorageNodeOpStats.h>
#include <common/net/message/nodes/GetClientStatsRespMsg.h>
/**
* Server side, called when the server gets a GetClientStatsMsgEx request
*/
bool GetClientStatsMsgEx::processIncoming(ResponseContext& ctx)
{
uint64_t cookieIP = getCookieIP(); // requested is cookie+1
// get stats
StorageNodeOpStats* clientOpStats = Program::getApp()->getNodeOpStats();
bool wantPerUserStats = isMsgHeaderFeatureFlagSet(GETCLIENTSTATSMSG_FLAG_PERUSERSTATS);
UInt64Vector opStatsVec;
clientOpStats->mapToUInt64Vec(
cookieIP, GETCLIENTSTATSRESP_MAX_PAYLOAD_LEN, wantPerUserStats, &opStatsVec);
ctx.sendResponse(GetClientStatsRespMsg(&opStatsVec) );
return true;
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include <common/storage/StorageErrors.h>
#include <common/net/message/nodes/GetClientStatsMsg.h>
// NOTE: The message factory requires this object to have 'deserialize' and
// 'processIncoming' methods. 'deserialize' is derived from other classes.
class GetClientStatsMsgEx : public GetClientStatsMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,24 @@
#include <program/Program.h>
#include <storage/StorageTargets.h>
#include <common/net/message/nodes/GetTargetConsistencyStatesRespMsg.h>
#include "GetTargetConsistencyStatesMsgEx.h"
bool GetTargetConsistencyStatesMsgEx::processIncoming(ResponseContext& ctx)
{
StorageTargets* storageTargets = Program::getApp()->getStorageTargets();
TargetConsistencyStateVec states;
std::transform(
targetIDs.begin(), targetIDs.end(),
std::back_inserter(states),
[storageTargets] (uint16_t targetID) {
auto* const target = storageTargets->getTarget(targetID);
return target ? target->getConsistencyState() : TargetConsistencyState_BAD;
});
ctx.sendResponse(GetTargetConsistencyStatesRespMsg(states));
return true;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <common/net/message/nodes/GetTargetConsistencyStatesMsg.h>
class GetTargetConsistencyStatesMsgEx : public GetTargetConsistencyStatesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,76 @@
#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;
switch(getNodeType() )
{
case NODETYPE_Meta:
nodes = app->getMetaNodes(); break;
case NODETYPE_Mgmt:
nodes = app->getMgmtNodes(); break;
case NODETYPE_Storage:
nodes = app->getStorageNodes(); break;
default:
{
log.logErr("Invalid/unexpected node type: "
+ boost::lexical_cast<std::string>(getNodeType()));
goto ack_resp;
} break;
}
isNodeNew = (nodes->addOrUpdateNode(std::move(node)) == NodeStoreResult::Added);
if(isNodeNew)
{ // log info about new server
bool supportsRDMA = NetworkInterfaceCard::supportsRDMA(&nicList);
log.log(Log_WARNING, std::string("New node: ") +
nodeIDWithTypeStr + "; " +
std::string(supportsRDMA ? "RDMA; " : "") );
}
ack_resp:
acknowledge(ctx);
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), StorageOpCounter_HEARTBEAT,
getMsgHeaderUserID() );
return true;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <common/net/message/nodes/HeartbeatMsg.h>
class HeartbeatMsgEx : public HeartbeatMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,28 @@
#include <common/net/message/nodes/HeartbeatMsg.h>
#include <common/toolkit/MessagingTk.h>
#include <program/Program.h>
#include "HeartbeatRequestMsgEx.h"
bool HeartbeatRequestMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("Heartbeat request incoming");
App* app = Program::getApp();
Config* cfg = app->getConfig();
Node& localNode = app->getLocalNode();
NumNodeID localNodeNumID = localNode.getNumID();
NicAddressList nicList(localNode.getNicList() );
HeartbeatMsg hbMsg(localNode.getAlias(), localNodeNumID, NODETYPE_Storage, &nicList);
hbMsg.setPorts(cfg->getConnStoragePort(), cfg->getConnStoragePort() );
ctx.sendResponse(hbMsg);
log.log(Log_DEBUG, std::string("Heartbeat req ip:") + StringTk::uintToHexStr(ctx.getSocket()->getPeerIP()));
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), StorageOpCounter_HEARTBEAT,
getMsgHeaderUserID() );
return true;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <common/net/message/nodes/HeartbeatRequestMsg.h>
class HeartbeatRequestMsgEx : public HeartbeatRequestMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

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

View File

@@ -0,0 +1,11 @@
#pragma once
#include <common/net/message/nodes/MapTargetsMsg.h>
class MapTargetsMsgEx : public MapTargetsMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,21 @@
#include <common/toolkit/MessagingTk.h>
#include <program/Program.h>
#include "PublishCapacitiesMsgEx.h"
bool PublishCapacitiesMsgEx::processIncoming(ResponseContext& ctx)
{
App* app = Program::getApp();
InternodeSyncer* syncer = app->getInternodeSyncer();
// force upload of capacity information
syncer->setForcePublishCapacities();
// send response
acknowledge(ctx);
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/net/message/nodes/PublishCapacitiesMsg.h>
class PublishCapacitiesMsgEx : public PublishCapacitiesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,21 @@
#include <common/toolkit/MessagingTk.h>
#include <program/Program.h>
#include "RefreshTargetStatesMsgEx.h"
bool RefreshTargetStatesMsgEx::processIncoming(ResponseContext& ctx)
{
App* app = Program::getApp();
InternodeSyncer* syncer = app->getInternodeSyncer();
// force update of capacity pools
syncer->setForceTargetStatesUpdate();
// send response
acknowledge(ctx);
return true;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <common/net/message/nodes/RefreshTargetStatesMsg.h>
class RefreshTargetStatesMsgEx : public RefreshTargetStatesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,124 @@
#include "RemoveBuddyGroupMsgEx.h"
#include <common/net/message/nodes/RemoveBuddyGroupRespMsg.h>
#include <net/message/storage/listing/ListChunkDirIncrementalMsgEx.h>
#include <program/Program.h>
static FhgfsOpsErr checkChunkDirRemovable(const int dirFD)
{
DIR* dir = fdopendir(dirFD);
std::unique_ptr<DIR, StorageTk::CloseDirDeleter> _dir(dir);
while (true)
{
struct dirent* result;
#if USE_READDIR_R
struct dirent buffer;
if (readdir_r(dir, &buffer, &result) != 0)
break;
#else
errno = 0;
result = readdir(dir);
if (!result && errno)
break;
#endif
if (!result)
return FhgfsOpsErr_SUCCESS;
if (strcmp(result->d_name, ".") == 0 || strcmp(result->d_name, "..") == 0)
continue;
struct stat statData;
const int statRes = ::fstatat(dirfd(dir), result->d_name, &statData, AT_SYMLINK_NOFOLLOW);
if (statRes != 0)
{
LOG(MIRRORING, ERR, "Could not stat something in chunk directory.");
return FhgfsOpsErr_INTERNAL;
}
if (!S_ISDIR(statData.st_mode))
return FhgfsOpsErr_NOTEMPTY;
const int subdir = ::openat(dirfd(dir), result->d_name, O_RDONLY);
if (subdir < 0)
{
LOG(MIRRORING, ERR, "Could not open directory in chunk path.");
return FhgfsOpsErr_INTERNAL;
}
const FhgfsOpsErr checkRes = checkChunkDirRemovable(subdir);
if (checkRes != FhgfsOpsErr_SUCCESS)
return checkRes;
}
return FhgfsOpsErr_INTERNAL;
}
bool RemoveBuddyGroupMsgEx::processIncoming(ResponseContext& ctx)
{
App* app = Program::getApp();
if (type != NODETYPE_Storage)
{
ctx.sendResponse(RemoveBuddyGroupRespMsg(FhgfsOpsErr_INTERNAL));
return true;
}
uint16_t targetID = app->getMirrorBuddyGroupMapper()->getPrimaryTargetID(groupID);
if (app->getTargetMapper()->getNodeID(targetID) != app->getLocalNode().getNumID())
targetID = app->getMirrorBuddyGroupMapper()->getSecondaryTargetID(groupID);
if (app->getTargetMapper()->getNodeID(targetID) != app->getLocalNode().getNumID())
{
LOG(MIRRORING, ERR, "Group is not mapped on this target.", groupID);
ctx.sendResponse(RemoveBuddyGroupRespMsg(FhgfsOpsErr_INTERNAL));
return true;
}
auto* const target = app->getStorageTargets()->getTarget(targetID);
if (!target)
{
LOG(MIRRORING, ERR, "Could not open directory file descriptor.", groupID);
ctx.sendResponse(RemoveBuddyGroupRespMsg(FhgfsOpsErr_INTERNAL));
return true;
}
const int dirFD = openat(*target->getMirrorFD(), ".", O_RDONLY);
if (dirFD < 0)
{
LOG(MIRRORING, ERR, "Could not open directory file descriptor.", groupID);
ctx.sendResponse(RemoveBuddyGroupRespMsg(FhgfsOpsErr_INTERNAL));
return true;
}
const FhgfsOpsErr checkRes = checkChunkDirRemovable(dirFD);
const bool forceAndNotEmpty = checkRes == FhgfsOpsErr_NOTEMPTY && force;
if (checkRes == FhgfsOpsErr_SUCCESS || forceAndNotEmpty)
{
if (!checkOnly)
{
auto* const bgm = Program::getApp()->getMirrorBuddyGroupMapper();
const NumNodeID localID = Program::getApp()->getLocalNode().getNumID();
if (!bgm->unmapMirrorBuddyGroup(groupID, localID))
{
ctx.sendResponse(RemoveBuddyGroupRespMsg(FhgfsOpsErr_INTERNAL));
return true;
}
}
ctx.sendResponse(RemoveBuddyGroupRespMsg(FhgfsOpsErr_SUCCESS));
return true;
}
else
{
ctx.sendResponse(RemoveBuddyGroupRespMsg(checkRes));
return true;
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <common/net/message/nodes/RemoveBuddyGroupMsg.h>
class RemoveBuddyGroupMsgEx : public RemoveBuddyGroupMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,37 @@
#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_Storage)
{
NodeStoreServers* nodes = app->getStorageNodes();
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));
app->getNodeOpStats()->updateNodeOp(ctx.getSocket()->getPeerIP(), StorageOpCounter_REMOVENODE,
getMsgHeaderUserID() );
return true;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <common/net/message/nodes/RemoveNodeMsg.h>
class RemoveNodeMsgEx : public RemoveNodeMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,37 @@
#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)
{
uint16_t buddyGroupID = this->getBuddyGroupID();
if (getNodeType() != NODETYPE_Storage)
{
// The storage server has no mapper for meta buddy groups - nothing to do, just acknowledge
if (!acknowledge(ctx))
ctx.sendResponse(SetMirrorBuddyGroupRespMsg(FhgfsOpsErr_SUCCESS, buddyGroupID));
return true;
}
App* app = Program::getApp();
MirrorBuddyGroupMapper* buddyGroupMapper = app->getMirrorBuddyGroupMapper();
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;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <common/net/message/nodes/SetMirrorBuddyGroupMsg.h>
class SetMirrorBuddyGroupMsgEx : public SetMirrorBuddyGroupMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,40 @@
#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)
{
App* app = Program::getApp();
StorageTargets* storageTargets = app->getStorageTargets();
FhgfsOpsErr result = FhgfsOpsErr_SUCCESS;
if (getTargetIDs().size() != getStates().size())
{
LogContext(__func__).logErr("Different list size of targetIDs and states");
result = FhgfsOpsErr_INTERNAL;
goto send_response;
}
for (ZipIterRange<UInt16List, UInt8List> idStateIter(getTargetIDs(), getStates());
!idStateIter.empty(); ++idStateIter)
{
auto* const target = storageTargets->getTarget(*idStateIter()->first);
if (!target)
{
LogContext(__func__).logErr("Unknown targetID: " +
StringTk::uintToStr(*(idStateIter()->first) ) );
result = FhgfsOpsErr_UNKNOWNTARGET;
goto send_response;
}
target->setState(TargetConsistencyState(*idStateIter()->second));
}
send_response:
ctx.sendResponse(SetTargetConsistencyStatesRespMsg(result) );
return true;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <common/net/message/nodes/SetTargetConsistencyStatesMsg.h>
class SetTargetConsistencyStatesMsgEx : public SetTargetConsistencyStatesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,66 @@
#include <app/App.h>
#include <common/net/message/nodes/StorageBenchControlMsgResp.h>
#include <components/benchmarker/StorageBenchOperator.h>
#include <program/Program.h>
#include "StorageBenchControlMsgEx.h"
bool StorageBenchControlMsgEx::processIncoming(ResponseContext& ctx)
{
const char* logContext = "StorageBenchControlMsg incoming";
StorageBenchResultsMap results;
int cmdErrorCode = STORAGEBENCH_ERROR_NO_ERROR;
App* app = Program::getApp();
StorageBenchOperator* storageBench = app->getStorageBenchOperator();
switch(getAction())
{
case StorageBenchAction_START:
{
cmdErrorCode = storageBench->initAndStartStorageBench(&getTargetIDs(), getBlocksize(),
getSize(), getThreads(), getODirect(), getType() );
} break;
case StorageBenchAction_STOP:
{
cmdErrorCode = storageBench->stopBenchmark();
} break;
case StorageBenchAction_STATUS:
{
storageBench->getStatusWithResults(&getTargetIDs(), &results);
cmdErrorCode = STORAGEBENCH_ERROR_NO_ERROR;
} break;
case StorageBenchAction_CLEANUP:
{
cmdErrorCode = storageBench->cleanup(&getTargetIDs());
} break;
default:
{
LogContext(logContext).logErr("unknown action!");
} break;
}
int errorCode;
// check if the last command from the fhgfs_cmd was successful,
// if not send the error code of the command to the fhgfs_cmd
// if it was successful, send the error code of the last run or acutely run of the benchmark
if (cmdErrorCode != STORAGEBENCH_ERROR_NO_ERROR)
{
errorCode = cmdErrorCode;
}
else
{
errorCode = storageBench->getLastRunErrorCode();
}
ctx.sendResponse(
StorageBenchControlMsgResp(storageBench->getStatus(), getAction(),
storageBench->getType(), errorCode, results) );
return true;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <common/net/message/nodes/StorageBenchControlMsg.h>
#include <common/Common.h>
class StorageBenchControlMsgEx: public StorageBenchControlMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -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;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <common/net/message/nodes/storagepools/RefreshStoragePoolsMsg.h>
class RefreshStoragePoolsMsgEx : public RefreshStoragePoolsMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};