From e1c38bcfabf49522903582d6cc1a972222e9a443 Mon Sep 17 00:00:00 2001 From: Alja Mrak-Tadel Date: Wed, 4 Mar 2015 13:26:14 -0800 Subject: [PATCH 1/3] Use multimap to order files to purge by time. --- src/XrdFileCache/XrdFileCacheFactory.cc | 84 ++++++++----------------- src/XrdFileCache/XrdFileCacheFactory.hh | 3 - 2 files changed, 25 insertions(+), 62 deletions(-) diff --git a/src/XrdFileCache/XrdFileCacheFactory.cc b/src/XrdFileCache/XrdFileCacheFactory.cc index 85d85b42b10..280000c68b2 100644 --- a/src/XrdFileCache/XrdFileCacheFactory.cc +++ b/src/XrdFileCache/XrdFileCacheFactory.cc @@ -157,9 +157,6 @@ bool Factory::xdlib(XrdOucStream &Config) bool Factory::Decide(XrdOucCacheIO* io) { - // if ( CheckFileForDiskSpace(io->Path(), io->FSize()) == false ) - // return false; - if(!m_decisionpoints.empty()) { std::string filename = io->Path(); @@ -376,7 +373,7 @@ bool Factory::ConfigParameters(std::string part, XrdOucStream& config ) //______________________________________________________________________________ -void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, std::map& fcmap) +void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, std::multimap& fcmap) { char buff[256]; XrdOucEnv env; @@ -410,7 +407,7 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, std::mapDebug(XrdCl::AppMsg, "FillFileMapRecurse() checking %s accessTime %d ", buff, (int)accessTime); - fcmap[np] = accessTime; + fcmap.insert(std::pair (accessTime, buff)); } else { @@ -462,7 +459,7 @@ void Factory::CacheDirCleanup() if (bytesToRemove > 0) { - typedef std::map fcmap_t; + typedef std::multimap fcmap_t; fcmap_t fcmap; // make a sorted map of file patch by access time XrdOssDF* dh = oss->newDir(m_configuration.m_username.c_str()); @@ -471,27 +468,32 @@ void Factory::CacheDirCleanup() FillFileMapRecurse(dh, m_configuration.m_cache_dir, fcmap); // loop over map and remove files with highest value of access time - for (fcmap_t::iterator i = fcmap.begin(); i != fcmap.end(); ++i) + for (fcmap_t::iterator it = fcmap.begin(); it != fcmap.end(); ++it) { - std::string path = i->first; - // remove info file - if (oss->Stat(path.c_str(), &fstat) == XrdOssOK) - { - bytesToRemove -= fstat.st_size; - oss->Unlink(path.c_str()); - clLog()->Info(XrdCl::AppMsg, "Factory::CacheDirCleanup() removed %s size %lld ", path.c_str(), fstat.st_size); - } - - // remove data file - path = path.substr(0, path.size() - strlen(XrdFileCache::Info::m_infoExtension)); - if (oss->Stat(path.c_str(), &fstat) == XrdOssOK) + std::pair ret; + ret = fcmap.equal_range(it->first); + for (fcmap_t::iterator it2 = ret.first; it2 != ret.second; ++it2) { - bytesToRemove -= fstat.st_size; - oss->Unlink(path.c_str()); - clLog()->Info(XrdCl::AppMsg, "Factory::CacheDirCleanup() removed %s size %lld ", path.c_str(), fstat.st_size); + std::string path = it2->second; + // remove info file + if (oss->Stat(path.c_str(), &fstat) == XrdOssOK) + { + bytesToRemove -= fstat.st_size; + oss->Unlink(path.c_str()); + clLog()->Info(XrdCl::AppMsg, "Factory::CacheDirCleanup() removed %s size %lld ", path.c_str(), fstat.st_size); + } + + // remove data file + path = path.substr(0, path.size() - strlen(XrdFileCache::Info::m_infoExtension)); + if (oss->Stat(path.c_str(), &fstat) == XrdOssOK) + { + bytesToRemove -= fstat.st_size; + oss->Unlink(path.c_str()); + clLog()->Info(XrdCl::AppMsg, "Factory::CacheDirCleanup() removed %s size %lld ", path.c_str(), fstat.st_size); + } } if (bytesToRemove <= 0) - break; + break; } } dh->Close(); @@ -501,39 +503,3 @@ void Factory::CacheDirCleanup() } } - - -bool Factory::CheckFileForDiskSpace(const char* path, long long fsize) -{ - long long inQueue = 0; - for (std::map::iterator i = m_filesInQueue.begin(); i!= m_filesInQueue.end(); ++i) - inQueue += i->second; - - - XrdOssVSInfo sP; - long long availableSpace = 0; - - if(m_output_fs->StatVS(&sP, "public", 1) < 0 ) { - clLog()->Error(XrdCl::AppMsg, "Factory:::CheckFileForDiskSpace can't get statvfs for dir [%s] \n", m_configuration.m_cache_dir.c_str()); - exit(1); - } - float oc = 1 - float(sP.Free)/sP.Total; - long long availableSpaceLong = static_cast((m_configuration.m_hwm -oc)* static_cast(s_diskSpacePrecisionFactor)); - if (oc < m_configuration.m_hwm) { - availableSpace = (sP.Free * availableSpaceLong) / s_diskSpacePrecisionFactor; - - if (availableSpace > fsize) { - m_filesInQueue[path] = fsize; - return true; - } - - } - clLog()->Error(XrdCl::AppMsg, "Factory:::CheckFileForDiskSpace not enugh space , availableSpace = %lld \n", availableSpace); - return false; -} - - -void Factory::UnCheckFileForDiskSpace(const char* path) -{ - m_filesInQueue.erase(path); -} diff --git a/src/XrdFileCache/XrdFileCacheFactory.hh b/src/XrdFileCache/XrdFileCacheFactory.hh index 35ca1425b0f..175e70581ef 100644 --- a/src/XrdFileCache/XrdFileCacheFactory.hh +++ b/src/XrdFileCache/XrdFileCacheFactory.hh @@ -144,9 +144,6 @@ namespace XrdFileCache void CacheDirCleanup(); private: - bool CheckFileForDiskSpace(const char* path, long long fsize); - void UnCheckFileForDiskSpace(const char* path); - bool ConfigParameters(std::string, XrdOucStream&); bool ConfigXeq(char *, XrdOucStream &); bool xdlib(XrdOucStream &); From 03dc632dc8f083c0bd796dab8f5cce0c3174ae44 Mon Sep 17 00:00:00 2001 From: Alja Mrak-Tadel Date: Wed, 4 Mar 2015 15:37:19 -0800 Subject: [PATCH 2/3] Keep only necessary elements in file purge map during FillFileMapRecurse. --- src/XrdFileCache/XrdFileCacheFactory.cc | 63 ++++++++++++++++++++----- src/XrdFileCache/XrdFileCacheInfo.hh | 15 ++++++ 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/XrdFileCache/XrdFileCacheFactory.cc b/src/XrdFileCache/XrdFileCacheFactory.cc index 280000c68b2..712649c21c6 100644 --- a/src/XrdFileCache/XrdFileCacheFactory.cc +++ b/src/XrdFileCache/XrdFileCacheFactory.cc @@ -371,9 +371,49 @@ bool Factory::ConfigParameters(std::string part, XrdOucStream& config ) } //______________________________________________________________________________ +//namespace { +class FPurgeState { +public: + struct FS { + std::string path; + int nBlck; -void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, std::multimap& fcmap) + FS(const char* p, int n) : path(p), nBlck(n) {} + }; + + typedef std::multimap map_t; + typedef map_t::iterator map_i; + + FPurgeState(long long iNBlckReq) : nBlckReq(iNBlckReq), nBlckAccum(0) {} + + map_t fmap; + + void checkFile (time_t iTime, const char* iPath, int iNBlck) + { + if ( (nBlckAccum < nBlckReq ) || (iTime < fmap.rbegin()->first) ) { + fmap.insert(std::pair (iTime, FS(iPath, iNBlck))); + nBlckAccum += iNBlck; + + // remove newest files from map if necessary + while (nBlckAccum > nBlckReq) { + time_t nt = fmap.begin()->first; + std::pair ret = fmap.equal_range(nt); + for (map_i it2 = ret.first; it2 != ret.second; ++it2) + nBlckAccum -= it2->second.nBlck; + } + } + } + + private: + long long nBlckReq; + long long nBlckAccum; +}; + + +//} + +void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, FPurgeState& purgeState) { char buff[256]; XrdOucEnv env; @@ -407,7 +447,7 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, std::multima if (cinfo.GetLatestDetachTime(accessTime, fh)) { log->Debug(XrdCl::AppMsg, "FillFileMapRecurse() checking %s accessTime %d ", buff, (int)accessTime); - fcmap.insert(std::pair (accessTime, buff)); + purgeState.checkFile(accessTime, buff, cinfo.GetNDownloadedBlocks()); } else { @@ -416,7 +456,7 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, std::multima } else if ( dh->Opendir(np.c_str(), env) >= 0 ) { - FillFileMapRecurse(dh, np, fcmap); + FillFileMapRecurse(dh, np, purgeState); } delete dh; dh = 0; @@ -459,22 +499,21 @@ void Factory::CacheDirCleanup() if (bytesToRemove > 0) { - typedef std::multimap fcmap_t; - fcmap_t fcmap; - // make a sorted map of file patch by access time + // make a sorted map of file patch by access time XrdOssDF* dh = oss->newDir(m_configuration.m_username.c_str()); if (dh->Opendir(m_configuration.m_cache_dir.c_str(), env) >= 0) { - FillFileMapRecurse(dh, m_configuration.m_cache_dir, fcmap); + long long nReq = (bytesToRemove*1.4)/m_configuration.m_bufferSize; // check more that required + FPurgeState purgeState(nReq); + FillFileMapRecurse(dh, m_configuration.m_cache_dir, purgeState); // loop over map and remove files with highest value of access time - for (fcmap_t::iterator it = fcmap.begin(); it != fcmap.end(); ++it) + for (FPurgeState::map_i it = purgeState.fmap.begin(); it != purgeState.fmap.end(); ++it) { - std::pair ret; - ret = fcmap.equal_range(it->first); - for (fcmap_t::iterator it2 = ret.first; it2 != ret.second; ++it2) + std::pair ret = purgeState.fmap.equal_range(it->first); + for (FPurgeState::map_i it2 = ret.first; it2 != ret.second; ++it2) { - std::string path = it2->second; + std::string path = it2->second.path; // remove info file if (oss->Stat(path.c_str(), &fstat) == XrdOssOK) { diff --git a/src/XrdFileCache/XrdFileCacheInfo.hh b/src/XrdFileCache/XrdFileCacheInfo.hh index e52fa14ac7f..dc0c32b1bc7 100644 --- a/src/XrdFileCache/XrdFileCacheInfo.hh +++ b/src/XrdFileCache/XrdFileCacheInfo.hh @@ -131,6 +131,11 @@ namespace XrdFileCache //--------------------------------------------------------------------- bool IsComplete() const; + //--------------------------------------------------------------------- + //! Get number of downloaded blocks + //--------------------------------------------------------------------- + int GetNDownloadedBlocks() const; + //--------------------------------------------------------------------- //! Update complete status //--------------------------------------------------------------------- @@ -171,6 +176,16 @@ namespace XrdFileCache return (m_buff_fetched[cn] & cfiBIT(off)) == cfiBIT(off); } + + inline int Info::GetNDownloadedBlocks() const + { + int cntd = 0; + for (int i = 0; i < m_sizeInBits; ++i) + if (TestBit(i)) cntd++; + + return cntd; + } + inline int Info::GetSizeInBytes() const { return ((m_sizeInBits -1)/8 + 1); From d731450219cb1b8b81d56c2bd0243fb9e9cfb6be Mon Sep 17 00:00:00 2001 From: Alja Mrak-Tadel Date: Thu, 5 Mar 2015 09:27:55 -0800 Subject: [PATCH 3/3] Pass full path name in FPurgeState::checkFile(). --- src/XrdFileCache/XrdFileCacheFactory.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/XrdFileCache/XrdFileCacheFactory.cc b/src/XrdFileCache/XrdFileCacheFactory.cc index 712649c21c6..b3f21df8adb 100644 --- a/src/XrdFileCache/XrdFileCacheFactory.cc +++ b/src/XrdFileCache/XrdFileCacheFactory.cc @@ -447,7 +447,7 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, FPurgeState& if (cinfo.GetLatestDetachTime(accessTime, fh)) { log->Debug(XrdCl::AppMsg, "FillFileMapRecurse() checking %s accessTime %d ", buff, (int)accessTime); - purgeState.checkFile(accessTime, buff, cinfo.GetNDownloadedBlocks()); + purgeState.checkFile(accessTime, np.c_str(), cinfo.GetNDownloadedBlocks()); } else {