Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProxyFileCache purge :: fix order of deletion, optimize sorting #209

Merged
merged 3 commits into from
Mar 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
131 changes: 68 additions & 63 deletions src/XrdFileCache/XrdFileCacheFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -374,9 +371,49 @@ bool Factory::ConfigParameters(std::string part, XrdOucStream& config )
}

//______________________________________________________________________________
//namespace {

class FPurgeState {
public:
struct FS {
std::string path;
int nBlck;

FS(const char* p, int n) : path(p), nBlck(n) {}
};

typedef std::multimap<time_t, FS> 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<time_t, FS> (iTime, FS(iPath, iNBlck)));
nBlckAccum += iNBlck;

// remove newest files from map if necessary
while (nBlckAccum > nBlckReq) {
time_t nt = fmap.begin()->first;
std::pair<map_i, map_i> 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, std::map<std::string, time_t>& fcmap)
//}

void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, FPurgeState& purgeState)
{
char buff[256];
XrdOucEnv env;
Expand Down Expand Up @@ -410,7 +447,7 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, std::map<std
if (cinfo.GetLatestDetachTime(accessTime, fh))
{
log->Debug(XrdCl::AppMsg, "FillFileMapRecurse() checking %s accessTime %d ", buff, (int)accessTime);
fcmap[np] = accessTime;
purgeState.checkFile(accessTime, np.c_str(), cinfo.GetNDownloadedBlocks());
}
else
{
Expand All @@ -419,7 +456,7 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, std::map<std
}
else if ( dh->Opendir(np.c_str(), env) >= 0 )
{
FillFileMapRecurse(dh, np, fcmap);
FillFileMapRecurse(dh, np, purgeState);
}

delete dh; dh = 0;
Expand Down Expand Up @@ -462,36 +499,40 @@ void Factory::CacheDirCleanup()

if (bytesToRemove > 0)
{
typedef std::map<std::string, time_t> 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 i = fcmap.begin(); i != fcmap.end(); ++i)
for (FPurgeState::map_i it = purgeState.fmap.begin(); it != purgeState.fmap.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<FPurgeState::map_i, FPurgeState::map_i> ret = purgeState.fmap.equal_range(it->first);
for (FPurgeState::map_i 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.path;
// 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();
Expand All @@ -501,39 +542,3 @@ void Factory::CacheDirCleanup()
}
}



bool Factory::CheckFileForDiskSpace(const char* path, long long fsize)
{
long long inQueue = 0;
for (std::map<std::string, long long>::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<long long>((m_configuration.m_hwm -oc)* static_cast<float>(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);
}
3 changes: 0 additions & 3 deletions src/XrdFileCache/XrdFileCacheFactory.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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 &);
Expand Down
15 changes: 15 additions & 0 deletions src/XrdFileCache/XrdFileCacheInfo.hh
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ namespace XrdFileCache
//---------------------------------------------------------------------
bool IsComplete() const;

//---------------------------------------------------------------------
//! Get number of downloaded blocks
//---------------------------------------------------------------------
int GetNDownloadedBlocks() const;

//---------------------------------------------------------------------
//! Update complete status
//---------------------------------------------------------------------
Expand Down Expand Up @@ -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);
Expand Down