Пример #1
0
/**
 * Close the given file. Also updates the InodeFile on disk.
 */
bool InodeFileStore::closeFile(EntryInfo* entryInfo, FileInode* inode, unsigned accessFlags,
   unsigned* outNumHardlinks, unsigned* outNumRefs)
{
   // FIXME Bernd: Maybe we should test with a read-lock if the file is in the store at all?

   SafeRWLock safeLock(&rwlock, SafeRWLock_WRITE); // L O C K

   bool inStore = false;
   *outNumHardlinks = 1; // (we're careful here about inodes that are not currently open)

   InodeMapIter iter = this->inodes.find(inode->getEntryID() );
   if(iter != this->inodes.end() )
   { // outInode exists

      *outNumHardlinks = inode->getNumHardlinks();

      // Store inode information on disk, they have been set with inode->setDynAttribs() before
      entryInfo->setInodeInlinedFlag(inode->getIsInlined() );
      inode->decNumSessionsAndStore(entryInfo, accessFlags);

      *outNumRefs = decreaseInodeRefCountUnlocked(iter);

      inStore = true;
   }

   safeLock.unlock(); // U N L O C K

   return inStore;
}
Пример #2
0
/**
 * @param disableLoading true to check the in-memory tree only (and don't try to load the
 * metadata from disk)
 */
FhgfsOpsErr InodeFileStore::stat(EntryInfo* entryInfo, bool loadFromDisk, StatData& outStatData)
{
   std::string entryID = entryInfo->getEntryID();
   FhgfsOpsErr statRes = FhgfsOpsErr_PATHNOTEXISTS;

   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K

   InodeMapIter iter = inodes.find(entryID);
   if(iter != inodes.end() )
   { // inode loaded
      FileInodeReferencer* fileRefer = iter->second;
      FileInode* inode = fileRefer->getReferencedObject();

      statRes = inode->getStatData(outStatData);

      safeLock.unlock(); // U N L O C K
   }
   else
   if (loadFromDisk == true)
   {  // not loaded => static stat
      safeLock.unlock(); // U N L O C K  give up the lock, as we don't do anything with the store

      statRes = FileInode::getStatData(entryInfo, outStatData);
   }
   else
      safeLock.unlock(); // U N L O C K

   return statRes;
}
Пример #3
0
/**
 * Note: This works by serializing the original and marking the object unreferencable (exclusive),
 * so remember to call movingCancel() or movingComplete()
 *
 * @param buf target buffer for serialization (only valid if success is returned)
 * @param bufLen must be at least META_SERBUF_SIZE
 * @param outUsedBufLen the used bufLen
 */
FhgfsOpsErr InodeFileStore::moveRemoteBegin(EntryInfo* entryInfo, char* buf, size_t bufLen,
   size_t* outUsedBufLen)
{
   const char* logContext = "Serialize Inode";
   FhgfsOpsErr retVal = FhgfsOpsErr_PATHNOTEXISTS;

   if(bufLen < META_SERBUF_SIZE)
   {
      LogContext(logContext).log(Log_ERR, "Error: Buffer too small!");
      return FhgfsOpsErr_INTERNAL;
   }

   SafeRWLock safeLock(&rwlock, SafeRWLock_WRITE); // L O C K

   FileInode* inode;
   retVal = getUnreferencedInodeUnlocked(entryInfo, &inode); // does not set refCount
   if (retVal == FhgfsOpsErr_SUCCESS)
   {
      /* We got an inode, which is in the map, but is unreferenced. Now we are going to exclusively
       * lock it. If another thread should try to reference it, it will fail due to this lock.
       */
      *outUsedBufLen = inode->serializeMetaData(buf);
      inode->setExclusive(true);
   }

   safeLock.unlock(); // U N L O C K

   return retVal;
}
Пример #4
0
/**
 * Note: remember to call releaseFileInode()
 *
 * @param loadFromDisk - true for the per-directory InodeFileStore, false for references
 *                       from MetaStore (global map)
 * @return NULL if no such file exists
 *
 * FIXME: Bernd: Does not need writeLock if loadFromDisk=false and nothing found
 */
FileInode* InodeFileStore::referenceFileInode(EntryInfo* entryInfo, bool loadFromDisk)
{
   SafeRWLock safeLock(&rwlock, SafeRWLock_WRITE); // L O C K

   FileInode* inode = referenceFileInodeUnlocked(entryInfo, loadFromDisk);

   safeLock.unlock(); // U N L O C K

   return inode;
}
Пример #5
0
FhgfsOpsErr InodeFileStore::makeFileInode(FileInode* inode, bool keepInode)
{
   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K

   FhgfsOpsErr retVal = makeFileInodeUnlocked(inode, keepInode);

   safeLock.unlock();

   return retVal;
}
Пример #6
0
/**
 * Insert the existing FileInodeReferencer into the map.
 *
 * This is mainly required to move references between stores (per-directory to metaStore)
 */
bool InodeFileStore::insertReferencer(std::string entryID, FileInodeReferencer* fileRefer)
{
   SafeRWLock safeLock(&rwlock, SafeRWLock_WRITE); // L O C K

   bool retVal = this->inodes.insert(InodeMapVal(entryID, fileRefer) ).second;

   safeLock.unlock(); // U N L O C K

   return retVal;
}
Пример #7
0
bool InodeFileStore::exists(std::string fileID)
{
   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K

   bool existsRes = existsUnlocked(fileID);

   safeLock.unlock(); // U N L O C K

   return existsRes;
}
Пример #8
0
/**
 * Note: This does not load any entries, so it will only return the number of already loaded
 * entries. (Only useful for debugging and statistics probably.)
 */
size_t InodeFileStore::getSize()
{
   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K

   size_t filesSize = inodes.size();

   safeLock.unlock(); // U N L O C K

   return filesSize;
}
Пример #9
0
/**
 * @param outFile will be set to the unlinked file and the object must then be deleted by the caller
 * (can be NULL if the caller is not interested in the file)
 */
FhgfsOpsErr InodeFileStore::unlinkFileInode(EntryInfo* entryInfo, FileInode** outInode)
{
   SafeRWLock safeLock(&rwlock, SafeRWLock_WRITE); // L O C K

   FhgfsOpsErr delErr = unlinkFileInodeUnlocked(entryInfo, outInode);

   safeLock.unlock(); // U N L O C K

   return delErr;
}
Пример #10
0
void DataRequestorStats::waitForShutdown()
{
   SafeMutexLock safeLock(&this->statusMutex);

   while(DATAREQUESTORSTATSSTATUS_IS_ACTIVE(this->status))
   {
      this->statusChangeCond.wait(&this->statusMutex);
   }

   safeLock.unlock();
}
Пример #11
0
FhgfsOpsErr InodeFileStore::isUnlinkable(EntryInfo* entryInfo, bool loadFromDisk,
   FileInode** outInode)
{
   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K

   FhgfsOpsErr retVal = this->isUnlinkableUnlocked(entryInfo, loadFromDisk, outInode);

   safeLock.unlock();

   return retVal;
}
Пример #12
0
/**
 * Unlink an overwritten dentry. From this dentry either the #fsid# entry or its inode is left.
 *
 * Locking:
 *   We lock everything ourself
 */
FhgfsOpsErr MetaStore::unlinkOverwrittenEntry(DirInode* parentDir,
   DirEntry* overWrittenEntry, FileInode** outInode)
{
   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K
   SafeRWLock parentLock(&parentDir->rwlock, SafeRWLock_WRITE);

   FhgfsOpsErr unlinkRes = unlinkOverwrittenEntryUnlocked(parentDir, overWrittenEntry, outInode);

   parentLock.unlock();
   safeLock.unlock();

   return unlinkRes;
}
Пример #13
0
/**
 * check if the given ID is in the store
 *
 */
bool InodeFileStore::isInStore(std::string fileID)
{
   bool inStore = false;

   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K

   InodeMapIter iter = inodes.find(fileID);
   if(iter != inodes.end() )
      inStore = true;

   safeLock.unlock(); // U N L O C K

   return inStore;
}
Пример #14
0
/**
 * References a file to be known to already referenced.
 * Also could be called "referenceReferencedFile"
 *
 * Note: remember to call releaseFileInode()
 *
 * @param loadFromDisk - true for the per-directory InodeFileStore, false for references
 *                       from MetaStore (global map)
 * @return NULL if no such file exists
 */
FileInode* InodeFileStore::referenceLoadedFile(std::string entryID)
{
   FileInode* inode = NULL;

   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K

   InodeMapIter iter = this->inodes.find(entryID);

   if(iter != this->inodes.end() )
   {
      inode = referenceFileInodeMapIterUnlocked(iter, &this->inodes);
   }

   safeLock.unlock(); // U N L O C K

   return inode;
}
Пример #15
0
/**
 * @return entryID of the old entry
 */
void InodeFileStore::moveRemoteComplete(std::string entryID)
{
   // moving succeeded => delete original

   SafeRWLock safeLock(&rwlock, SafeRWLock_WRITE); // L O C K

   InodeMapIter iter = inodes.find(entryID);
   if(iter != inodes.end() )
   { // file exists
      FileInodeReferencer* fileRefer = iter->second;

      delete fileRefer;
      inodes.erase(entryID);
   }

   safeLock.unlock(); // U N L O C K
}
Пример #16
0
/**
 * @param outNumHardlinks for quick on-close unlink check (may not be NULL!)
 * @return false if file was not in store at all, true if we found the file in the store
 */
bool InodeFileStore::releaseFileInode(FileInode* inode)
{
   bool inStore = false;

   SafeRWLock safeLock(&rwlock, SafeRWLock_WRITE); // L O C K

   InodeMapIter iter = this->inodes.find(inode->getEntryID() );
   if(iter != this->inodes.end() )
   { // outInode exists => decrease refCount
      decreaseInodeRefCountUnlocked(iter);
      inStore = true;
   }

   safeLock.unlock(); // U N L O C K

   return inStore;
}
Пример #17
0
void MetaStore::moveRemoteFileComplete(DirInode* dir, std::string entryID)
{
   SafeRWLock safeLock(&this->rwlock, SafeRWLock_WRITE); // L O C K

   if (this->fileStore.isInStore(entryID) )
      this->fileStore.moveRemoteComplete(entryID);
   else
   {
      SafeRWLock safeDirLock(&dir->rwlock, SafeRWLock_READ);

      dir->fileStore.moveRemoteComplete(entryID);

      safeDirLock.unlock();

   }

   safeLock.unlock(); // U N L O C K
}
Пример #18
0
/**
 * @param validAttribs SETATTR_CHANGE_...-Flags
 */
FhgfsOpsErr InodeFileStore::setAttr(EntryInfo* entryInfo, int validAttribs,
   SettableFileAttribs* attribs)
{
   std::string entryID = entryInfo->getEntryID();
   FhgfsOpsErr retVal = FhgfsOpsErr_PATHNOTEXISTS;

   SafeRWLock safeLock(&rwlock, SafeRWLock_WRITE); // L O C K

   InodeMapIter iter = inodes.find(entryID);
   if(iter == inodes.end() )
   { // not loaded => load, apply, destroy

      // Note: A very uncommon code path, as SetAttrMsgEx::setAttr() references the inode first.

      // FIXME Bernd: Another use case for loadFromEntryInfo().

      FileInode* inode = FileInode::createFromEntryInfo(entryInfo);

      if(inode)
      { // loaded
         bool setRes = inode->setAttrData(entryInfo, validAttribs, attribs);

         retVal = setRes ? FhgfsOpsErr_SUCCESS : FhgfsOpsErr_INTERNAL;

         delete inode;
      }
   }
   else
   { // inode loaded
      FileInodeReferencer* inodeRefer = iter->second;
      FileInode* inode = inodeRefer->getReferencedObject();

      if(!inode->getExclusive() )
      {
         bool setRes = inode->setAttrData(entryInfo, validAttribs, attribs);

         retVal = setRes ? FhgfsOpsErr_SUCCESS : FhgfsOpsErr_INTERNAL;
      }
   }

   safeLock.unlock(); // U N L O C K

   return retVal;
}
Пример #19
0
/**
 * Get the referencer and delete this ID from the map. Mainly used to move the referencer between
 * Stores.
 */
FileInodeReferencer* InodeFileStore::getReferencerAndDeleteFromMap(std::string fileID)
{
   FileInodeReferencer* fileRefer = NULL;

   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K

   InodeMapIter iter = this->inodes.find(fileID);

   if(iter != inodes.end() )
   { // exists in map
      fileRefer = iter->second;

      this->inodes.erase(iter);
   }

   safeLock.unlock(); // U N L O C K

   return fileRefer;

}
Пример #20
0
/**
 * Copies (serializes) the original file object to a buffer.
 *
 * Note: This works by inserting a temporary placeholder and returning the original, so remember to
 * call movingComplete()
 *
 * @param buf target buffer for serialization
 * @param bufLen must be at least META_SERBUF_SIZE
 */
FhgfsOpsErr MetaStore::moveRemoteFileBegin(DirInode* dir, EntryInfo* entryInfo,
   char* buf, size_t bufLen, size_t* outUsedBufLen)
{
   FhgfsOpsErr retVal = FhgfsOpsErr_INTERNAL;

   SafeRWLock safeLock(&this->rwlock, SafeRWLock_READ); // L O C K

   // lock the dir to make sure no renameInSameDir is going on
   SafeRWLock safeDirLock(&dir->rwlock, SafeRWLock_READ);

   if (this->fileStore.isInStore(entryInfo->getEntryID() ) )
      retVal = this->fileStore.moveRemoteBegin(entryInfo, buf, bufLen, outUsedBufLen);
   else
   {
      retVal = dir->fileStore.moveRemoteBegin(entryInfo, buf, bufLen, outUsedBufLen);
   }

   safeDirLock.unlock();
   safeLock.unlock(); // U N L O C K

   return retVal;
}
Пример #21
0
/**
 * Clears out stale capacity reports, i.e. reports where the target/node is not ONLINE+GOOD
 * or where the target node is unknown to the targetStateStore (has been unmapped in the
 * meantime) from the target/nodeCapacityReportMap.
 *
 * @param nodeType Selects whether to look at storage targets or metadata nodes.
 */
void InternodeSyncer::clearStaleCapacityReports(const NodeType nodeType)
{
   TargetStateStore* stateStore = (nodeType == NODETYPE_Meta)
      ? Program::getApp()->getMetaStateStore()
      : Program::getApp()->getTargetStateStore();

   RWLock* reportsRWLock = (nodeType == NODETYPE_Meta)
      ? &nodeCapacityReportMapLock
      : &targetCapacityReportMapLock;

   TargetCapacityReportMap& capacityReportMap = (nodeType == NODETYPE_Meta)
      ? nodeCapacityReportMap
      : targetCapacityReportMap;

   const CombinedTargetState onlineGoodState(
      TargetReachabilityState_ONLINE, TargetConsistencyState_GOOD);

   SafeRWLock safeLock(reportsRWLock, SafeRWLock_WRITE); // L O C K

   for (TargetCapacityReportMapIter reportIter = capacityReportMap.begin();
        reportIter != capacityReportMap.end(); /* iter increment in loop body */ )
   {
      const uint16_t targetID = reportIter->first;

      CombinedTargetState targetState;

      bool getStateRes = stateStore->getState(targetID, targetState);

      if ( !getStateRes || (targetState != onlineGoodState) )
         capacityReportMap.erase(reportIter++);
      else
         ++reportIter;
   }

   safeLock.unlock(); // U N L O C K
}
Пример #22
0
void XMMediaStream::OnPatchStart()
{
  if (IsSource()) {
        
    PSafeLockReadWrite safeLock(*this);
    if (!safeLock.IsLocked()) {
      return;
    }
      
    // Ensure the code below runs just once.
    // Also avoid possible race conditions
    if (hasStarted == true || isTerminated == true) {
      return;
    }
      
    RTP_DataFrame::PayloadTypes payloadType = mediaFormat.GetPayloadType();
        
    unsigned frameTime = mediaFormat.GetFrameTime();
    unsigned framesPerSecond = (unsigned)round((double)OpalMediaFormat::VideoClockRate / (double)frameTime);
    framesPerSecond = std::min((unsigned)XM_MAX_FPS, framesPerSecond);
    framesPerSecond = std::max(framesPerSecond, (unsigned)1);
        
    unsigned bitrate = mediaFormat.GetBandwidth();
    bitrate = std::min(bitrate, XMOpalManager::GetManager()->GetVideoBandwidthLimit(mediaFormat));
        
    unsigned flags = 0;
        
    XMCodecIdentifier codecIdentifier = _XMGetMediaFormatCodec(mediaFormat);
    XMVideoSize videoSize = _XMGetMediaFormatSize(mediaFormat);
        
    if (codecIdentifier == XMCodecIdentifier_UnknownCodec ||
       videoSize == XMVideoSize_NoVideo || videoSize == XMVideoSize_Custom) {
      // Shouldn't actually happen
      return;
    }
        
    if (codecIdentifier == XMCodecIdentifier_H263) {
      // If we're  sending H.263, we need to know which
      // format to send. The payload code is submitted in the
      // flags parameter
      flags = payloadType;
            
      if (payloadType == RTP_DataFrame::H263) {
        cout << "Sending RFC2190" << endl;
      } else {
        cout << "Sending RFC2429" << endl;
      }
    } else if (codecIdentifier == XMCodecIdentifier_H264) {
      unsigned packetizationMode = _XMGetH264PacketizationMode(mediaFormat);
      if (packetizationMode == XM_H264_PACKETIZATION_MODE_SINGLE_NAL) {
        // We send only at a limited bitrate to avoid too many
        // NAL units which are TOO big to fit
        if (bitrate > 380000) {
          bitrate = 380000;
        }
      }
      flags = (packetizationMode << 8) + (_XMGetH264Profile(mediaFormat) << 4) + _XMGetH264Level(mediaFormat);
    }
        
    videoTransmitterStream = this;
    hasStarted = true;
        
    dataFrame.SetPayloadSize(0);
    dataFrame.SetPayloadType(payloadType);
        
    unsigned keyFrameInterval = GetKeyFrameInterval(codecIdentifier);
    _XMStartMediaTransmit(2, codecIdentifier, videoSize, framesPerSecond, bitrate, keyFrameInterval, flags);
  }
}
Пример #23
0
/**
 * Simple rename on the same server in the same directory.
 *
 * @param outUnlinkInode is the inode of a dirEntry being possibly overwritten (toName already
 *    existed).
 */
FhgfsOpsErr MetaStore::renameInSameDir(DirInode* parentDir, std::string fromName,
   std::string toName, FileInode** outUnlinkInode)
{
   const char* logContext = "Rename in dir";

   SafeRWLock safeLock(&rwlock, SafeRWLock_READ); // L O C K
   SafeRWLock fromMutexLock(&parentDir->rwlock, SafeRWLock_WRITE); // L O C K ( F R O M )

   FhgfsOpsErr retVal;
   FhgfsOpsErr unlinkRes;

   DirEntry* overWrittenEntry = NULL;

   retVal = performRenameEntryInSameDir(parentDir, fromName, toName, &overWrittenEntry);

   if (retVal != FhgfsOpsErr_SUCCESS)
   {
      fromMutexLock.unlock();
      safeLock.unlock();

      SAFE_DELETE(overWrittenEntry);

      return retVal;
   }

   EntryInfo unlinkEntryInfo;
   bool unlinkedWasInlined;

   if (overWrittenEntry)
   {
      std::string parentDirID = parentDir->getID();
      overWrittenEntry->getEntryInfo(parentDirID, 0, &unlinkEntryInfo);
      unlinkedWasInlined = overWrittenEntry->getIsInodeInlined();

      unlinkRes = unlinkOverwrittenEntryUnlocked(parentDir, overWrittenEntry, outUnlinkInode);
   }
   else
   {
      *outUnlinkInode = NULL;

      // irrelevant values, just to please the compiler
      unlinkRes = FhgfsOpsErr_SUCCESS;
      unlinkedWasInlined = true;
   }

   /* Now update the ctime (attribChangeTime) of the renamed entry.
    * Only do that for Directory dentry after giving up the DirInodes (fromMutex) lock
    * as dirStore.setAttr() will aquire the InodeDirStore:: lock
    * and the lock order is InodeDirStore:: and then DirInode::  (risk of deadlock) */

   DirEntry* entry = parentDir->dirEntryCreateFromFileUnlocked(toName);
   if (likely(entry) ) // entry was just renamed to, so very likely it exists
   {
      EntryInfo entryInfo;
      std::string parentID = parentDir->getID();
      entry->getEntryInfo(parentID, 0, &entryInfo);

      fromMutexLock.unlock();
      setAttrUnlocked(&entryInfo, 0, NULL); /* This will fail if the DirInode is on another
                                             * meta server, but as updating the ctime is not
                                             * a real posix requirement (but filesystems usually
                                             * do it) we simply ignore this issue for now. */

      SAFE_DELETE(entry);
   }
   else
      fromMutexLock.unlock();

   safeLock.unlock();

   // unlink later must be called after releasing all locks

   if (overWrittenEntry)
   {
      if (unlinkRes == FhgfsOpsErr_INUSE)
      {
         unlinkRes = unlinkInodeLater(&unlinkEntryInfo, unlinkedWasInlined );
         if (unlinkRes == FhgfsOpsErr_AGAIN)
         {
            unlinkRes = unlinkOverwrittenEntry(parentDir, overWrittenEntry, outUnlinkInode);
         }
      }

      if (unlinkRes != FhgfsOpsErr_SUCCESS && unlinkRes != FhgfsOpsErr_PATHNOTEXISTS)
      {
         LogContext(logContext).logErr("Failed to unlink overwritten entry:"
            " FileName: "      + toName                         +
            " ParentEntryID: " + parentDir->getID()             +
            " entryID: "       + overWrittenEntry->getEntryID() +
            " Error: "         + FhgfsOpsErrTk::toErrString(unlinkRes) );


         // TODO: Restore the dentry
      }
   }

   SAFE_DELETE(overWrittenEntry);

   return retVal;
}