bool StatStoragePathMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("StatStoragePathMsgEx incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, 4, std::string("Received a StatStoragePathMsg from: ") + peer); int64_t sizeTotal = 0; int64_t sizeFree = 0; int64_t inodesTotal = 0; int64_t inodesFree = 0; FhgfsOpsErr statRes = statStoragePath(&sizeTotal, &sizeFree, &inodesTotal, &inodesFree); StatStoragePathRespMsg respMsg(statRes, sizeTotal, sizeFree, inodesTotal, inodesFree); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); App* app = Program::getApp(); app->getClientOpStats()->updateNodeOp(sock->getPeerIP(), MetaOpCounter_STATFS); return true; }
bool MkLocalDirMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { const char* logContext = "MkLocalDirMsg incoming"; EntryInfo* entryInfo = getEntryInfo(); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG(logContext, 4, std::string("Received a MkLocalDirMsg from: ") + peer + std::string(" entryID: ") + entryInfo->getEntryID() + std::string(" entryName: ") + entryInfo->getFileName() ); IGNORE_UNUSED_VARIABLE(logContext); IGNORE_UNUSED_VARIABLE(entryInfo); FhgfsOpsErr mkRes = FhgfsOpsErr_INTERNAL; StripePattern* pattern = createPattern(); if(unlikely(pattern->getPatternType() == STRIPEPATTERN_Invalid) ) LogContext(logContext).logErr("Received an invalid stripe pattern from: " + peer); else mkRes = mkLocalDir(pattern); delete(pattern); MkLocalDirRespMsg respMsg(mkRes); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); return true; }
bool RequestExceededQuotaMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("RequestExceededQuotaMsgEx incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, Log_DEBUG, std::string("Received a RequestExceededQuotaMsgEx from: ") + peer); App* app = Program::getApp(); Config* cfg = app->getConfig(); // get exceeded quota ID list RequestExceededQuotaRespMsg respMsg(getQuotaDataType(), getExceededType() ); if(cfg->getQuotaEnableEnforcment() ) app->getQuotaManager()->getExceededQuotaStore()->getExceededQuota( respMsg.getExceededQuotaIDs(), getQuotaDataType(), getExceededType() ); else log.log(Log_ERR, "Unable to provide exceeded quota IDs. " "The storage daemon on " + sock->getPeername() + " has quota enforcement enabled, " "but not this management daemon. Fix this configuration problem or quota enforcement will " "not work."); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); return true; }
bool MkFileWithPatternMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { #ifdef BEEGFS_DEBUG const char* logContext = "MkFileWithPatternMsg incoming"; std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG(logContext, 4, std::string("Received a MkFileWithPatternMsg from: ") + peer); #endif // BEEGFS_DEBUG EntryInfo* parentInfo = this->getParentInfo(); std::string newFileName = this->getNewFileName(); EntryInfo newEntryInfo; FhgfsOpsErr mkRes = mkFile(parentInfo, newFileName, &newEntryInfo); MkFileWithPatternRespMsg respMsg(mkRes, &newEntryInfo ); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); App* app = Program::getApp(); app->getNodeOpStats()->updateNodeOp(sock->getPeerIP(), MetaOpCounter_MKFILE, getMsgHeaderUserID() ); return true; }
bool SetMetadataMirroringMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("SetMetadataMirroringMsgEx incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, Log_DEBUG, "Received a SetMetadataMirroringMsg from: " + peer); EntryInfo* entryInfo = this->getEntryInfo(); LOG_DEBUG("SetMetadataMirroringMsgEx::processIncoming", Log_SPAM, "parentEntryID: " + entryInfo->getParentEntryID() + "; " "entryID: " + entryInfo->getEntryID() + "; " "name: " + entryInfo->getFileName() ); FhgfsOpsErr setRes = setDirMirroring(entryInfo); SetMetadataMirroringRespMsg respMsg(setRes); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); return true; }
/** * Server side gets a GetClientStatsMsgEx request */ bool GetClientStatsMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("GetClientStatsMsgEx incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, 4, std::string("Received a GetClientStatsMsg from: ") + peer); // From deserialization of the incoming buffer. We only want to send stats for clients with IP +1 uint64_t cookieIP = getValue(); // get stats MetaNodeOpStats* ClientOpStats = Program::getApp()->getClientOpStats(); UInt64Vector opStatsVec; ClientOpStats->mapToUInt64Vec(cookieIP, bufLen, &opStatsVec); GetClientStatsRespMsg respMsg(&opStatsVec); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); return true; }
bool CreateDefDirInodesMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG("CreateDefDirInodesMsg incoming", 4, std::string("Received a CreateDefDirInodesMsg from: ") + peer); LogContext log("CreateDefDirInodesMsg incoming"); App* app = Program::getApp(); Config* cfg = app->getConfig(); uint16_t localNodeNumID = app->getLocalNode()->getNumID(); StringList inodeIDs; StringList failedInodeIDs; FsckDirInodeList createdInodes; this->parseInodeIDs(&inodeIDs); for ( StringListIter iter = inodeIDs.begin(); iter != inodeIDs.end(); iter++ ) { std::string inodeID = *iter; int mode = S_IFDIR | S_IRWXU; unsigned userID = 0; // root unsigned groupID = 0; // root uint16_t ownerNodeID = localNodeNumID; 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 DirInode dirInode(inodeID, mode, userID, groupID, ownerNodeID, stripePattern); 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, "", 0, localNodeNumID, statData.getFileSize(), statData.getNumHardlinks(), stripeTargets, FsckStripePatternType_RAID0, localNodeNumID); createdInodes.push_back(fsckDirInode); } else failedInodeIDs.push_back(inodeID); } CreateDefDirInodesRespMsg respMsg(&failedInodeIDs, &createdInodes); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*) fromAddr, sizeof(struct sockaddr_in)); return true; }
bool DeleteDirEntriesMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG("DeleteDirEntriesMsg incoming", 4, std::string("Received a DeleteDirEntriesMsg from: ") + peer); LogContext log("DeleteDirEntriesMsgEx"); MetaStore* metaStore = Program::getApp()->getMetaStore(); FsckDirEntryList entries; FsckDirEntryList failedEntries; this->parseEntries(&entries); for ( FsckDirEntryListIter iter = entries.begin(); iter != entries.end(); iter++ ) { std::string parentID = iter->getParentDirID(); std::string entryName = iter->getName(); FsckDirEntryType dirEntryType = iter->getEntryType(); DirInode* parentDirInode = metaStore->referenceDir(parentID, 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, true, NULL); metaStore->releaseDir(parentID); if (unlinkRes != FhgfsOpsErr_SUCCESS ) { log.logErr("Failed to delete directory entry; ParentID: " + parentID + "; EntryName: " + entryName + "; Err: " + FhgfsOpsErrTk::toErrString(unlinkRes)); failedEntries.push_back(*iter); } } DeleteDirEntriesRespMsg respMsg(&failedEntries); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); return true; }
bool TruncFileMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { #ifdef BEEGFS_DEBUG const char* logContext = "TruncFileMsgEx incoming"; std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG(logContext, Log_DEBUG, std::string("Received a TruncFileMsg from: ") + peer); #endif // BEEGFS_DEBUG int64_t fileSize = getFilesize(); EntryInfo* entryInfo = getEntryInfo(); bool useQuota = isMsgHeaderFeatureFlagSet(TRUNCFILEMSG_FLAG_USE_QUOTA); FhgfsOpsErr truncRes = MsgHelperTrunc::truncFile( entryInfo, fileSize, useQuota, getMsgHeaderUserID() ); // send response if(unlikely(truncRes == FhgfsOpsErr_COMMUNICATION) ) { // forward comm error as indirect communication error to client GenericResponseMsg respMsg(GenericRespMsgCode_INDIRECTCOMMERR, "Communication with storage target failed"); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); } else { // normal response TruncFileRespMsg respMsg(truncRes); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); } // update operation counters Program::getApp()->getNodeOpStats()->updateNodeOp(sock->getPeerIP(), MetaOpCounter_TRUNCATE, getMsgHeaderUserID() ); return true; }
bool RefresherControlMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { #ifdef BEEGFS_DEBUG const char* logContext = "RefresherControlMsg incoming"; std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG(logContext, 4, std::string("Received a RefresherControlMsg from: ") + peer); #endif // BEEGFS_DEBUG App* app = Program::getApp(); FullRefresher* refresher = app->getFullRefresher(); RefresherControlType controlCommand = getControlCommand(); switch(controlCommand) { case RefresherControl_START: { refresher->startRefreshing(); } break; case RefresherControl_STOP: { refresher->stopRefreshing(); } break; default: { // query status // nothing special to be done here, as we always respond with the current stats } break; } // query status bool isRunning = refresher->getIsRunning(); uint64_t numDirsRefreshed; uint64_t numFilesRefreshed; refresher->getNumRefreshed(&numDirsRefreshed, &numFilesRefreshed); // send response RefresherControlRespMsg respMsg(isRunning, numDirsRefreshed, numFilesRefreshed); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); return true; }
bool MapTargetsMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("MapTargetsMsg incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, Log_DEBUG, std::string("Received a MapTargetsMsg from: ") + peer); App* app = Program::getApp(); NodeStoreServers* storageNodes = app->getStorageNodes(); TargetMapper* targetMapper = app->getTargetMapper(); uint16_t nodeID = getNodeID(); UInt16List targetIDs; parseTargetIDs(&targetIDs); for(UInt16ListConstIter iter = targetIDs.begin(); iter != targetIDs.end(); iter++) { bool wasNewTarget = targetMapper->mapTarget(*iter, nodeID); if(wasNewTarget) { LOG_DEBUG_CONTEXT(log, Log_WARNING, "Mapping " "target " + StringTk::uintToStr(*iter) + " => " + storageNodes->getNodeIDWithTypeStr(nodeID) ); IGNORE_UNUSED_VARIABLE(storageNodes); } } // send response if(!MsgHelperAck::respondToAckRequest(this, fromAddr, sock, respBuf, bufLen, app->getDatagramListener() ) ) { MapTargetsRespMsg respMsg(FhgfsOpsErr_SUCCESS); respMsg.serialize(respBuf, bufLen); if(fromAddr) { // datagram => sync via dgramLis send method app->getDatagramListener()->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(*fromAddr) ); } else sock->sendto(respBuf, respMsg.getMsgLength(), 0, NULL, 0); } return true; }
bool GetEntryInfoMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { #ifdef FHGFS_DEBUG const char* logContext = "GetEntryInfoMsg incoming"; std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG(logContext, 4, std::string("Received a GetEntryInfoMsg from: ") + peer); #endif // FHGFS_DEBUG EntryInfo* entryInfo = this->getEntryInfo(); LOG_DEBUG(logContext, 5, std::string("ParentEntryID: ") + entryInfo->getParentEntryID() + " entryID: " + entryInfo->getParentEntryID() ); StripePattern* pattern = NULL; FhgfsOpsErr getInfoRes; if(entryInfo->getEntryID().length() == 0 ) // FIXME Bernd: Test { // special case: get info for root directory getInfoRes = getInfoRoot(&pattern); } else { getInfoRes = getInfoRec(entryInfo, &pattern); } if(getInfoRes != FhgfsOpsErr_SUCCESS) { // error occurred => create a dummy pattern UInt16Vector dummyStripeNodes; pattern = new Raid0Pattern(1, dummyStripeNodes); } GetEntryInfoRespMsg respMsg(getInfoRes, pattern); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); // cleanup delete(pattern); App* app = Program::getApp(); app->getClientOpStats()->updateNodeOp(sock->getPeerIP(), MetaOpCounter_GETENTRYINFO); return true; }
bool MovingDirInsertMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("MovingDirInsertMsg incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, 4, std::string("Received a MovingDirInsertMsg from: ") + peer); FhgfsOpsErr insertRes = insert(); MovingDirInsertRespMsg respMsg(insertRes); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); return true; }
bool FsckSetEventLoggingMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG("FsckSetEventLoggingMsg incoming", Log_DEBUG, std::string("Received a FsckSetEventLoggingMsg from: ") + peer); LogContext log("FsckSetEventLoggingMsg incoming"); bool result; bool missedEvents; App* app = Program::getApp(); bool enableLogging = this->getEnableLogging(); if (enableLogging) { unsigned portUDP = this->getPortUDP(); NicAddressList nicList; this->parseNicList(&nicList); app->getModificationEventFlusher()->enableLogging(portUDP, nicList); if (app->getModificationEventFlusher()->getNumLoggingWorkers() == app->getWorkers()->size() ) result = true; else result = false; missedEvents = true; // (value ignored when logging is enabled) } else { // disable logging result = app->getModificationEventFlusher()->disableLogging(); missedEvents = app->getModificationEventFlusher()->getFsckMissedEvent(); } FsckSetEventLoggingRespMsg respMsg(result, missedEvents); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*) fromAddr, sizeof(struct sockaddr_in) ); return true; }
bool MovingFileInsertMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("MovingFileInsertMsg incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, Log_DEBUG, std::string("Received a MovingFileInsertMsg from: ") + peer); FileInode* unlinkedInode = NULL; FhgfsOpsErr insertRes = this->insert(&unlinkedInode); // create the new file here // prepare response data std::string unlinkedFileID; StripePattern* pattern; unsigned chunkHash; if(unlinkedInode) { unlinkedFileID = unlinkedInode->getEntryID(); pattern = unlinkedInode->getStripePattern(); chunkHash = unlinkedInode->getChunkHash(); } else { // no unlinked file => use empty string as ID and create some fake data unlinkedFileID = ""; UInt16Vector stripeTargetIDs; pattern = new Raid0Pattern(1, stripeTargetIDs, 0); chunkHash = 0; } MovingFileInsertRespMsg respMsg(insertRes, unlinkedFileID.c_str(), pattern, chunkHash); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); // cleanup if(unlinkedInode) delete(unlinkedInode); else delete(pattern); return true; }
bool RmLocalDirMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { #ifdef FHGFS_DEBUG const char* logContext = "RmLocalDirMsg incoming"; std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG(logContext, 4, std::string("Received a RmLocalDirMsg from: ") + peer); #endif // FHGFS_DEBUG FhgfsOpsErr rmRes = rmDir(); RmLocalDirRespMsg respMsg(rmRes); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); return true; }
int WifiMessageHandler::respondStatus(WifiMessageType aType, WifiStatusCode aStatus) { int ret; uint16_t sessionId; sessionId = mSessionMap[aType].front(); mSessionMap[aType].pop(); WifiEmptyMessage<struct WifiMsgResp> respMsg(WIFI_MESSAGE_RESPONSE, aType); respMsg->sessionId = sessionId; respMsg->status = aStatus; ret = sendMsg(respMsg.getBuffer(), respMsg.getLength()); if (ret < 0) { WIFID_ERROR("Fail on responding the message(%s).", strerror(errno)); } return ret; }
bool GetNodesMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("GetNodes incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, 4, std::string("Received a GetNodesMsg from: ") + peer); NodeType nodeType = (NodeType)getValue(); LOG_DEBUG_CONTEXT(log, 5, std::string("NodeType: ") + Node::nodeTypeToStr(nodeType) ); App* app = Program::getApp(); NodeList nodeList; NodeStore* nodes = app->getServerStoreFromType(nodeType); if(unlikely(!nodes) ) { log.logErr("Invalid node type: " + StringTk::intToStr(nodeType) + "(" + Node::nodeTypeToStr(nodeType) + ")"); return true; } nodes->referenceAllNodes(&nodeList); uint16_t rootID = nodes->getRootNodeNumID(); GetNodesRespMsg respMsg(rootID, &nodeList); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); nodes->releaseAllNodes(&nodeList); return true; }
void WifiMessageHandler::handleMessageVersion() { int ret; uint16_t sessionId; sessionId = mSessionMap[WIFI_MESSAGE_TYPE_VERSION].front(); mSessionMap[WIFI_MESSAGE_TYPE_VERSION].pop(); WifiResponseMessage<struct WifiMsgVersion> respMsg(WIFI_MESSAGE_TYPE_VERSION); respMsg.setStatus(WIFI_STATUS_OK); respMsg.setSessionId(sessionId); respMsg->majorVersion = MAJOR_VER; respMsg->minorVersion = MINOR_VER; ret = sendMsg(respMsg.getBuffer(), respMsg.getLength()); if (ret < 0) { WIFID_ERROR("Fail on responding the message of getting version(%s).", strerror(errno)); } }
bool GetTargetMappingsMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("GetTargetMappingsMsg incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, 4, std::string("Received a GetTargetMappingsMsg from: ") + peer); App* app = Program::getApp(); TargetMapper* targetMapper = app->getTargetMapper(); UInt16List targetIDs; UInt16List nodeIDs; targetMapper->getMappingAsLists(targetIDs, nodeIDs); GetTargetMappingsRespMsg respMsg(&targetIDs, &nodeIDs); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, NULL, 0); return true; }
bool RegisterNodeMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("RegisterNodeMsg incoming"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, Log_DEBUG, std::string("Received a RegisterNodeMsg from: ") + peer); App* app = Program::getApp(); NodeType nodeType = getNodeType(); std::string nodeID(getNodeID() ); NicAddressList nicList; BitStore nodeFeatureFlags; Node* node; uint16_t newNodeNumID; bool isNodeNew; LOG_DEBUG_CONTEXT(log, Log_SPAM, "Type: " + Node::nodeTypeToStr(nodeType) + "; " "NodeID: " + nodeID + "; " "NodeNumID: " + StringTk::uintToStr(getNodeNumID() ) ); // check for empty nodeID; (sanity check, should never fail) if(unlikely(nodeID.empty() ) ) { log.log(Log_WARNING, "Rejecting registration of node with empty string ID " "from: " + peer + "; " "type: " + Node::nodeTypeToStr(nodeType) ); return false; } // get the corresponding node store for this node type NodeStoreServers* servers = app->getServerStoreFromType(nodeType); if(unlikely(!servers) ) { log.logErr("Invalid node type for registration: " + Node::nodeTypeToStr(nodeType) + "; " "from: " + peer); newNodeNumID = 0; goto send_response; } // check if adding of new servers is allowed if(!checkNewServerAllowed(servers, getNodeNumID(), nodeType) ) { // this is a new server and adding was disabled log.log(Log_WARNING, "Registration of new servers disabled. Rejecting node: " + nodeID + " (Type: " + Node::nodeTypeToStr(nodeType) + ")"); newNodeNumID = 0; goto send_response; } // construct node parseNicList(&nicList); node = constructNode(nodeID, getNodeNumID(), getPortUDP(), getPortTCP(), nicList); node->setNodeType(getNodeType() ); node->setFhgfsVersion(getFhgfsVersion() ); parseNodeFeatureFlags(&nodeFeatureFlags); node->setFeatureFlags(&nodeFeatureFlags); // add node to store (or update it) isNodeNew = servers->addOrUpdateNodeEx(&node, &newNodeNumID); if(!newNodeNumID) { // unable to add node to store log.log(Log_WARNING, "Unable to add node with given numeric ID: " + StringTk::uintToStr(getNodeNumID() ) + "; " "string ID: " + getNodeID() + "; " "Type: " + Node::nodeTypeToStr(nodeType) ); goto send_response; } /* note on capacity pools: we may not add new nodes to capacity pools here yet, because at this point the registered node is not ready to receive messages yet. so we will add it to capacity pools later when we receive its first heartbeat msg. */ processIncomingRoot(getRootNumID(), nodeType); if(isNodeNew) { // this node is new processNewNode(nodeID, newNodeNumID, nodeType, getFhgfsVersion(), &nicList, peer); } // send response send_response: RegisterNodeRespMsg respMsg(newNodeNumID); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); return true; }
bool RecreateFsIDsMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG("RecreateFsIDsMsg incoming", 4, std::string("Received a RecreateFsIDsMsg from: ") + peer); LogContext log("RecreateFsIDsMsgEx"); FsckDirEntryList entries; FsckDirEntryList failedEntries; this->parseEntries(&entries); for ( FsckDirEntryListIter iter = entries.begin(); iter != entries.end(); iter++ ) { std::string parentID = iter->getParentDirID(); std::string entryName = iter->getName(); std::string entryID = iter->getID(); std::string dirEntryPath = MetaStorageTk::getMetaDirEntryPath( Program::getApp()->getDentriesPath()->getPathAsStrConst(), parentID); std::string dirEntryIDFilePath = MetaStorageTk::getMetaDirEntryIDPath(dirEntryPath) + "/" + entryID; std::string dirEntryNameFilePath = dirEntryPath + "/" + entryName; // 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; } } RecreateFsIDsRespMsg respMsg(&failedEntries); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*) fromAddr, sizeof(struct sockaddr_in)); return true; }
bool AdjustChunkPermissionsMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { LogContext log("Incoming AdjustChunkPermissionsMsg"); std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG_CONTEXT(log, 4, std::string("Received a AdjustChunkPermissionsMsg from: ") + peer); 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, 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; DirInode* parentDirInode = metaStore->referenceDir(parentID, 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); 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( Program::getApp()->getDentriesPath()->getPathAsStrConst(), parentID) + "/" + *namesIter; EntryInfo entryInfo; FileInodeStoreData inodeDiskData; FhgfsOpsErr getEntryRes = 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() ) ) { 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, 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; } } AdjustChunkPermissionsRespMsg respMsg(readOutEntries, currentContDirID, lastHashDirOffset, lastContDirOffset, errorCount); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*) fromAddr, sizeof(struct sockaddr_in)); return true; }
bool LookupIntentMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { #ifdef BEEGFS_DEBUG const char* msgInContext = "LookupIntentMsg incoming"; std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG(msgInContext, 4, std::string("Received a LookupIntentMsg from: ") + peer); #endif App* app = Program::getApp(); std::string parentEntryID = getParentInfo()->getEntryID(); FhgfsOpsErr lookupRes = FhgfsOpsErr_INTERNAL; FhgfsOpsErr createRes = FhgfsOpsErr_INTERNAL; std::string entryName = getEntryName(); const char* logContext = "LookupIntentMsg"; LOG_DEBUG(logContext, 5, "parentID: '" + parentEntryID + "' " + "entryName: '" + entryName + "'"); // (note: following objects must be at the top-level stack frame for response serialization) std::string fileHandleID; Raid0Pattern dummyPattern(1, UInt16Vector() ); EntryInfo diskEntryInfo; int createFlag = getIntentFlags() & LOOKUPINTENTMSG_FLAG_CREATE; FileInodeStoreData inodeData; bool inodeDataOutdated = false; // true if the file/inode is currently open (referenced) LookupIntentRespMsg respMsg(FhgfsOpsErr_INTERNAL); PathInfo pathInfo; /* Added to NetMessage as ref-pointer, so object needs to exist until * the NetMessage got serialized! */ // sanity checks if (unlikely (parentEntryID.empty() || entryName.empty() ) ) { LogContext(logContext).log(3, "Sanity check failed: parentEntryID: '" + parentEntryID + "'" + "entryName: '" + entryName + "'"); // something entirely wrong, fail immediately, error already set above goto send_response; } /* Note: Actually we should first do a lookup. However, a successful create also implies a failed Lookup, so we can take a shortcut. */ // lookup-create if (createFlag) { LOG_DEBUG(logContext, Log_SPAM, "Lookup: create"); // checks in create() if lookup already found the entry createRes = create(this->getParentInfo(), entryName, &diskEntryInfo, &inodeData); FhgfsOpsErr sendCreateRes; if (createRes == FhgfsOpsErr_SUCCESS) { sendCreateRes = FhgfsOpsErr_SUCCESS; // Successful Create, which implies Lookup-before-create would have been failed. respMsg.setLookupResult(FhgfsOpsErr_PATHNOTEXISTS); respMsg.setEntryInfo(&diskEntryInfo); } else { if (createRes == FhgfsOpsErr_EXISTS) { // NOTE: we need to do a Lookup to get required lookup data if (getIntentFlags() & LOOKUPINTENTMSG_FLAG_CREATEEXCLUSIVE) sendCreateRes = FhgfsOpsErr_EXISTS; else sendCreateRes = FhgfsOpsErr_SUCCESS; } else sendCreateRes = FhgfsOpsErr_INTERNAL; } respMsg.addResponseCreate(sendCreateRes); // note: don't quit here on error because caller might still have requested stat info } // lookup if ((!createFlag) || (createRes == FhgfsOpsErr_EXISTS) ) { LOG_DEBUG(logContext, Log_SPAM, "Lookup: lookup"); lookupRes = lookup(parentEntryID, entryName, &diskEntryInfo, &inodeData, inodeDataOutdated); respMsg.setLookupResult(lookupRes); if (lookupRes == FhgfsOpsErr_SUCCESS) respMsg.setEntryInfo(&diskEntryInfo); if(unlikely( (lookupRes != FhgfsOpsErr_SUCCESS) && createFlag) ) { // so createFlag is set, so createRes is either Success or Exists, but now lookup fails // create/unlink race? // we need to set something here, as sendCreateRes = FhgfsOpsErr_SUCCESS respMsg.setEntryInfo(&diskEntryInfo); StatData statData; statData.setAllFake(); // set arbitrary stat values (receiver won't use the values) respMsg.addResponseStat(lookupRes, &statData); goto send_response; } } // lookup-revalidate if(getIntentFlags() & LOOKUPINTENTMSG_FLAG_REVALIDATE) { LOG_DEBUG(logContext, Log_SPAM, "Lookup: revalidate"); FhgfsOpsErr revalidateRes = revalidate(&diskEntryInfo); respMsg.addResponseRevalidate(revalidateRes); if(revalidateRes != FhgfsOpsErr_SUCCESS) goto send_response; } /* lookup-stat note: we do stat before open to avoid the dyn attribs refresh if the file is not opened by someone else currently. */ if ( (getIntentFlags() & LOOKUPINTENTMSG_FLAG_STAT) && (lookupRes == FhgfsOpsErr_SUCCESS || createRes == FhgfsOpsErr_SUCCESS) ) { LOG_DEBUG(logContext, Log_SPAM, "Lookup: stat"); // check if lookup and create failed (we don't have an entryID to stat then) if(diskEntryInfo.getEntryID().empty() ) goto send_response; if ( (diskEntryInfo.getFlags() & ENTRYINFO_FEATURE_INLINED) && !inodeDataOutdated) { // stat-data from the dentry StatData* dentryStatData = inodeData.getInodeStatData(); respMsg.addResponseStat(FhgfsOpsErr_SUCCESS, dentryStatData); } else { // read stat data separately StatData statData; FhgfsOpsErr statRes = stat(&diskEntryInfo, true, statData); respMsg.addResponseStat(statRes, &statData); if(statRes != FhgfsOpsErr_SUCCESS) goto send_response; } } // lookup-open if(getIntentFlags() & LOOKUPINTENTMSG_FLAG_OPEN) { LOG_DEBUG(logContext, Log_SPAM, "Lookup: open"); // don't open if create failed if ((createRes != FhgfsOpsErr_SUCCESS) && (getIntentFlags() & LOOKUPINTENTMSG_FLAG_CREATE) ) goto send_response; if (!DirEntryType_ISREGULARFILE(diskEntryInfo.getEntryType() ) ) goto send_response; // not a regular file, we don't open that // check if lookup and/or create failed (we don't have an entryID to open then) if(diskEntryInfo.getEntryID().empty() ) goto send_response; StripePattern* pattern = NULL; FhgfsOpsErr openRes = open(&diskEntryInfo, &fileHandleID, &pattern, &pathInfo); if(openRes != FhgfsOpsErr_SUCCESS) { // open failed => use dummy pattern for response respMsg.addResponseOpen(openRes, fileHandleID, &dummyPattern, &pathInfo); goto send_response; } respMsg.addResponseOpen(openRes, fileHandleID, pattern, &pathInfo); } send_response: respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); app->getNodeOpStats()->updateNodeOp(sock->getPeerIP(), this->getOpCounterType(), getMsgHeaderUserID() ); return true; }
bool CloseFileMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { #ifdef BEEGFS_DEBUG const char* logContext = "CloseFileMsg incoming"; std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG(logContext, Log_DEBUG, std::string("Received a CloseFileMsg from: ") + peer); #endif // BEEGFS_DEBUG App* app = Program::getApp(); FhgfsOpsErr closeRes; bool unlinkDisposalFile = false; EntryInfo* entryInfo = getEntryInfo(); // update operation counters (here on top because we have an early sock release in this msg) app->getNodeOpStats()->updateNodeOp(sock->getPeerIP(), MetaOpCounter_CLOSE, getMsgHeaderUserID() ); if(isMsgHeaderFeatureFlagSet(CLOSEFILEMSG_FLAG_CANCELAPPENDLOCKS) ) { // client requests cleanup of granted or pending locks for this handle unsigned ownerFD = SessionTk::ownerFDFromHandleID(getFileHandleID() ); EntryLockDetails lockDetails(getSessionID(), 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(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; FileInode* inode; closeRes = MsgHelperClose::closeSessionFile( getSessionID(), getFileHandleID(), entryInfo, &accessFlags, &inode); // send response CloseFileRespMsg respMsg(closeRes); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); IncomingPreprocessedMsgWork::releaseSocket(app, &sock, this); if(likely(closeRes == FhgfsOpsErr_SUCCESS) ) closeRes = closeFileAfterEarlyResponse(inode, accessFlags, &unlinkDisposalFile); } else { // alternative 2: normal response (after chunk file close) closeRes = MsgHelperClose::closeFile(getSessionID(), getFileHandleID(), entryInfo, getMaxUsedNodeIndex(), getMsgHeaderUserID(), &unlinkDisposalFile); // send response // (caller won't be interested in the unlink result below, so no reason to wait for that) if(unlikely(closeRes == FhgfsOpsErr_COMMUNICATION) ) { // forward comm error as indirect communication error to client GenericResponseMsg respMsg(GenericRespMsgCode_INDIRECTCOMMERR, "Communication with storage target failed"); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); } else { // normal response CloseFileRespMsg respMsg(closeRes); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); } } // 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 */ MsgHelperClose::unlinkDisposableFile(entryInfo->getEntryID(), getMsgHeaderUserID() ); } return true; }
bool FLockEntryMsgEx::processIncoming(struct sockaddr_in* fromAddr, Socket* sock, char* respBuf, size_t bufLen, HighResolutionStats* stats) { /* 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 = "FLockEntryMsg incoming"; std::string peer = fromAddr ? Socket::ipaddrToStr(&fromAddr->sin_addr) : sock->getPeername(); LOG_DEBUG(logContext, Log_DEBUG, std::string("Received a FLockEntryMsg from: ") + peer); #endif // BEEGFS_DEBUG App* app = Program::getApp(); SessionStore* sessions = app->getSessions(); MetaStore* metaStore = app->getMetaStore(); FhgfsOpsErr clientResult = FhgfsOpsErr_INTERNAL; // reponse error code unsigned ownerFD = SessionTk::ownerFDFromHandleID(getFileHandleID() ); EntryLockDetails lockDetails(getClientID(), getClientFD(), getOwnerPID(), getLockAckID(), getLockTypeFlags() ); LOG_DEBUG(logContext, Log_SPAM, lockDetails.toString() ); EntryInfo* entryInfo = getEntryInfo(); // find sessionFile Session* session = sessions->referenceSession(getClientID(), 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 FileInode* lockCancelFile = 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, getClientID(), 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) FileInode* file = sessionFile->getInode(); bool lockGranted = file->flockEntry(lockDetails); if(!lockGranted) clientResult = FhgfsOpsErr_WOULDBLOCK; else clientResult = FhgfsOpsErr_SUCCESS; // cleanup sessionFiles->releaseSession(sessionFile, entryInfo); } // cleanup cleanup_session: sessions->releaseSession(session); LOG_DEBUG(logContext, Log_SPAM, std::string("Client result: ") + FhgfsOpsErrTk::toErrString(clientResult) ); // send response FLockEntryRespMsg respMsg(clientResult); respMsg.serialize(respBuf, bufLen); sock->sendto(respBuf, respMsg.getMsgLength(), 0, (struct sockaddr*)fromAddr, sizeof(struct sockaddr_in) ); app->getNodeOpStats()->updateNodeOp(sock->getPeerIP(), MetaOpCounter_FLOCKENTRY, getMsgHeaderUserID() ); return true; }