// ---------------------------------------------------------------------- // File: OpenFileTracker.hh // Author: Georgios Bitzes - CERN // ---------------------------------------------------------------------- /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2019 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ #ifndef EOS_FST_UTILS_OPENFILETRACKER_H #define EOS_FST_UTILS_OPENFILETRACKER_H #include "fst/Namespace.hh" #include "common/FileSystem.hh" #include "common/RWMutex.hh" #include EOSFSTNAMESPACE_BEGIN //------------------------------------------------------------------------------ //! Class to track which files are open at any given moment, on a //! filesystem-basis. //! //! Thread-safe. To track both "open-for-read" and "open-for-write" files, //! use two different objects. //------------------------------------------------------------------------------ class OpenFileTracker { public: //---------------------------------------------------------------------------- //! Constructor //---------------------------------------------------------------------------- OpenFileTracker(); //---------------------------------------------------------------------------- //! Mark that the given file ID, on the given filesystem ID, was just opened //---------------------------------------------------------------------------- void up(eos::common::FileSystem::fsid_t fsid, uint64_t fid); //---------------------------------------------------------------------------- //! Wait for an excl open of a file and count up //---------------------------------------------------------------------------- void waitExclOpen(eos::common::FileSystem::fsid_t fsid, uint64_t fid); //---------------------------------------------------------------------------- //! Mark that the given file ID, on the given filesystem ID, was just closed //! //! Prints warning in the logs if the value was about to go negative - it will //! never go negative. //---------------------------------------------------------------------------- void down(eos::common::FileSystem::fsid_t fsid, uint64_t fid); //---------------------------------------------------------------------------- //! Checks if the given file ID, on the given filesystem ID, is currently open //---------------------------------------------------------------------------- bool isOpen(eos::common::FileSystem::fsid_t fsid, uint64_t fid) const; //---------------------------------------------------------------------------- //! Checks if there's _any_ operation currently in progress //---------------------------------------------------------------------------- bool isAnyOpen() const; //---------------------------------------------------------------------------- //! Checks if there was ever more than one writer on that file //---------------------------------------------------------------------------- bool hadMultiOpen(eos::common::FileSystem::fsid_t fsid, uint64_t fid) const; //---------------------------------------------------------------------------- //! Checks if the given file ID, on the given filesystem ID, is currently open //---------------------------------------------------------------------------- int32_t getUseCount(eos::common::FileSystem::fsid_t fsid, uint64_t fid) const; //---------------------------------------------------------------------------- //! Get number of distinct open files by filesystem //---------------------------------------------------------------------------- int32_t getOpenOnFilesystem(eos::common::FileSystem::fsid_t fsid) const; //---------------------------------------------------------------------------- //! Get open file IDs of a filesystem, sorted by usecount //---------------------------------------------------------------------------- std::map> getSortedByUsecount( eos::common::FileSystem::fsid_t fsid) const; //---------------------------------------------------------------------------- //! Get the RR scheduling object per filesystem/app //---------------------------------------------------------------------------- std::mutex* scheduleRR(eos::common::FileSystem::fsid_t fsid, const std::string app); //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- //! Get top hot files on current filesystem //---------------------------------------------------------------------------- struct HotEntry { HotEntry(eos::common::FileSystem::fsid_t fs, uint64_t f, size_t u) : fsid(fs), fid(f), uses(u) {} HotEntry() {} bool operator==(const HotEntry& other) const { return fsid == other.fsid && fid == other.fid && uses == other.uses; } bool operator!=(const HotEntry& other) const { return !(*this == other); } eos::common::FileSystem::fsid_t fsid; uint64_t fid; size_t uses; }; std::vector getHotFiles(eos::common::FileSystem::fsid_t fsid, size_t maxEntries) const; //---------------------------------------------------------------------------- //! Class acting as a barrier to avoid concurrent file creation interference //---------------------------------------------------------------------------- class CreationBarrier { public: CreationBarrier(OpenFileTracker& tracker, eos::common::FileSystem::fsid_t fsid, uint64_t fid) : mTracker(tracker), mFsid(fsid), mFid(fid) , mReleased(false) { mTracker.waitExclOpen(fsid, fid); }; ~CreationBarrier() { Release(); } void Release() { if (!mReleased) { mTracker.down(mFsid, mFid); } mReleased = true; } private: OpenFileTracker& mTracker; eos::common::FileSystem::fsid_t mFsid; uint64_t mFid; bool mReleased; }; private: mutable eos::common::RWMutex mMutex; std::map> mContents; std::map> mMultiOpen; std::map> mClosing; std::map> mApp; }; EOSFSTNAMESPACE_END #endif