Exemplo n.º 1
0
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;      
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 4
0
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;      
}
Exemplo n.º 6
0
/**
 * 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;

}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
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;      
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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;      
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
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;      
}
Exemplo n.º 17
0
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;
}
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
0
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));
  }
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
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;
}
Exemplo n.º 22
0
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, &currentContDirID,
         &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, &currentContDirID,
            &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;
}
Exemplo n.º 24
0
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;
}
Exemplo n.º 25
0
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;
}
Exemplo n.º 26
0
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;
}