diff --git a/src/XrdFileCache/XrdFileCache.hh b/src/XrdFileCache/XrdFileCache.hh index 4f2a7b6edfc..30f868fb99e 100644 --- a/src/XrdFileCache/XrdFileCache.hh +++ b/src/XrdFileCache/XrdFileCache.hh @@ -50,30 +50,44 @@ namespace XrdFileCache { Configuration() : m_hdfsmode(false), + m_data_space("public"), + m_meta_space("public"), m_diskUsageLWM(-1), m_diskUsageHWM(-1), + m_purgeInterval(300), m_bufferSize(1024*1024), m_RamAbsAvailable(0), m_NRamBuffers(-1), m_prefetch_max_blocks(10), - m_hdfsbsize(128*1024*1024) {} + m_hdfsbsize(128*1024*1024) + {} bool m_hdfsmode; //!< flag for enabling block-level operation - std::string m_cache_dir; //!< path of disk cache std::string m_username; //!< username passed to oss plugin + std::string m_data_space; //!< oss space for data files + std::string m_meta_space; //!< oss space for metadata files (cinfo) long long m_diskUsageLWM; //!< cache purge low water mark long long m_diskUsageHWM; //!< cache purge high water mark + int m_purgeInterval; //!< sleep interval between cache purges long long m_bufferSize; //!< prefetch buffer size, default 1MB - long long m_RamAbsAvailable; //!< available from configuration + long long m_RamAbsAvailable; //!< available from configuration int m_NRamBuffers; //!< number of total in-memory cache blocks, cached size_t m_prefetch_max_blocks;//!< maximum number of blocks to prefetch per file long long m_hdfsbsize; //!< used with m_hdfsmode, default 128MB }; + struct TmpConfiguration + { + std::string m_diskUsageLWM; + std::string m_diskUsageHWM; + TmpConfiguration() : + m_diskUsageLWM("0.90"), m_diskUsageHWM("0.95") + {} + }; //---------------------------------------------------------------------------- //! Attaches/creates and detaches/deletes cache-io objects for disk based cache. @@ -181,15 +195,15 @@ namespace XrdFileCache XrdOss* GetOss() const { return m_output_fs; } XrdSysError& GetSysError() { return m_log; } - + File* GetFileWithLocalPath(std::string, IO* io); - + void AddActive(IO*, File*); - XrdOucTrace* GetTrace() { return m_trace; } + private: - bool ConfigParameters(std::string, XrdOucStream&); + bool ConfigParameters(std::string, XrdOucStream&, TmpConfiguration &tmpc); bool ConfigXeq(char *, XrdOucStream &); bool xdlib(XrdOucStream &); bool xtrace(XrdOucStream &); diff --git a/src/XrdFileCache/XrdFileCacheConfiguration.cc b/src/XrdFileCache/XrdFileCacheConfiguration.cc index 06e3bc9b1f0..c96c7f0a0ee 100644 --- a/src/XrdFileCache/XrdFileCacheConfiguration.cc +++ b/src/XrdFileCache/XrdFileCacheConfiguration.cc @@ -130,11 +130,11 @@ bool Cache::Config(XrdSysLogger *logger, const char *config_filename, const char &XrdVERSIONINFOVAR(XrdOucGetCache2)); if (!ofsCfg) return false; + TmpConfiguration tmpc; - if (ofsCfg->Load(XrdOfsConfigPI::theOssLib)) { + if (ofsCfg->Load(XrdOfsConfigPI::theOssLib)) + { ofsCfg->Plugin(m_output_fs); - XrdOssCache_FS* ocfs = XrdOssCache::Find("public"); - ocfs->Add(m_configuration.m_cache_dir.c_str()); } else { @@ -163,10 +163,10 @@ bool Cache::Config(XrdSysLogger *logger, const char *config_filename, const char } else if (!strncmp(var,"pfc.", 4)) { - retval = ConfigParameters(std::string(var+4), Config); + retval = ConfigParameters(std::string(var+4), Config, tmpc); } - if (!retval) + if ( ! retval) { retval = false; TRACE(Error, "Cache::Config() error in parsing"); @@ -176,21 +176,50 @@ bool Cache::Config(XrdSysLogger *logger, const char *config_filename, const char } Config.Close(); + // sets default value for disk usage - if (m_configuration.m_diskUsageLWM < 0 || m_configuration.m_diskUsageHWM < 0) { XrdOssVSInfo sP; - if (m_output_fs->StatVS(&sP, "public", 1) >= 0) { - m_configuration.m_diskUsageLWM = static_cast(0.90 * sP.Total + 0.5); - m_configuration.m_diskUsageHWM = static_cast(0.95 * sP.Total + 0.5); + if (m_output_fs->StatVS(&sP, m_configuration.m_data_space.c_str(), 1) < 0) + { + m_log.Emsg("Cache::ConfigParameters() error obtaining stat info for space ", m_configuration.m_data_space.c_str()); + return false; + } + + if (::isalpha(*(tmpc.m_diskUsageLWM.rbegin())) && ::isalpha(*(tmpc.m_diskUsageHWM.rbegin()))) + { + if (XrdOuca2x::a2sz(m_log, "Error getting disk usage low watermark", tmpc.m_diskUsageLWM.c_str(), &m_configuration.m_diskUsageLWM, 0, sP.Total) || + XrdOuca2x::a2sz(m_log, "Error getting disk usage high watermark", tmpc.m_diskUsageHWM.c_str(), &m_configuration.m_diskUsageHWM, 0, sP.Total)) + { + return false; + } + } + else + { + char* eP; + errno = 0; + double lwmf = strtod(tmpc.m_diskUsageLWM.c_str(), &eP); + if (errno || eP == tmpc.m_diskUsageLWM.c_str()) + { + m_log.Emsg("Cache::ConfigParameters() error parsing diskusage parameter ", tmpc.m_diskUsageLWM.c_str()); + return false; + } + double hwmf = strtod(tmpc.m_diskUsageHWM.c_str(), &eP); + if (errno || eP == tmpc.m_diskUsageHWM.c_str()) { + m_log.Emsg("Cache::ConfigParameters() error parsing diskusage parameter ", tmpc.m_diskUsageHWM.c_str()); + return false; + } + + m_configuration.m_diskUsageLWM = static_cast(sP.Total * lwmf + 0.5); + m_configuration.m_diskUsageHWM = static_cast(sP.Total * hwmf + 0.5); } } // get number of available RAM blocks after process configuration - if (m_configuration.m_RamAbsAvailable == 0 ) + if (m_configuration.m_RamAbsAvailable == 0) { - TRACE(Error, "RAM usage not specified. Please set pfc.ram value in configuration file."); - return false; + TRACE(Error, "RAM usage not specified. Please set pfc.ram value in configuration file."); + return false; } m_configuration.m_NRamBuffers = static_cast(m_configuration.m_RamAbsAvailable/ m_configuration.m_bufferSize); @@ -204,15 +233,22 @@ bool Cache::Config(XrdSysLogger *logger, const char *config_filename, const char char buff[2048]; float rg = (m_configuration.m_RamAbsAvailable)/float(1024*1024*1024); loff = snprintf(buff, sizeof(buff), "Config effective %s pfc configuration:\n" - " pfc.blocksize %lld\n" - " pfc.prefetch %ld\n" - " pfc.ram %.fg" - " pfc.trace %d", - config_filename, - m_configuration.m_bufferSize, - m_configuration.m_prefetch_max_blocks, // AMT not sure what parsing should be - rg, - m_trace->What); + " pfc.blocksize %lld\n" + " pfc.prefetch %ld\n" + " pfc.ram %.fg\n" + " pfc.diskusage %lld %lld sleep %d\n" + " pfc.spaces %s %s\n" + " pfc.trace %d", + config_filename, + m_configuration.m_bufferSize, + m_configuration.m_prefetch_max_blocks, // AMT not sure what parsing should be + rg, + m_configuration.m_diskUsageLWM, + m_configuration.m_diskUsageHWM, + m_configuration.m_purgeInterval, + m_configuration.m_data_space.c_str(), + m_configuration.m_meta_space.c_str(), + m_trace->What); if (m_configuration.m_hdfsmode) { @@ -223,12 +259,12 @@ bool Cache::Config(XrdSysLogger *logger, const char *config_filename, const char char unameBuff[256]; if (m_configuration.m_username.empty()) { - XrdOucUtils::UserName(getuid(), unameBuff, sizeof(unameBuff)); - m_configuration.m_username = unameBuff; + XrdOucUtils::UserName(getuid(), unameBuff, sizeof(unameBuff)); + m_configuration.m_username = unameBuff; } else { - snprintf(unameBuff, sizeof(unameBuff), "\tpfc.user %s \n", m_configuration.m_username.c_str()); - loff += snprintf(&buff[loff], strlen(unameBuff), "%s", unameBuff); + snprintf(unameBuff, sizeof(unameBuff), "\tpfc.user %s \n", m_configuration.m_username.c_str()); + loff += snprintf(&buff[loff], strlen(unameBuff), "%s", unameBuff); } m_log.Say( buff); @@ -237,56 +273,37 @@ bool Cache::Config(XrdSysLogger *logger, const char *config_filename, const char m_log.Say("------ File Caching Proxy interface initialization ", retval ? "completed" : "failed"); if (ofsCfg) delete ofsCfg; + return retval; } //______________________________________________________________________________ -bool Cache::ConfigParameters(std::string part, XrdOucStream& config ) +bool Cache::ConfigParameters(std::string part, XrdOucStream& config, TmpConfiguration &tmpc) { XrdSysError err(0, ""); if ( part == "user" ) { m_configuration.m_username = config.GetWord(); } - else if ( part == "cachedir" ) - { - m_configuration.m_cache_dir = config.GetWord(); - } else if ( part == "diskusage" ) { - std::string minV = config.GetWord(); - std::string maxV = config.GetWord(); - if (!minV.empty() && !maxV.empty()) { - XrdOssVSInfo sP; - if (m_output_fs->StatVS(&sP, "public", 1) >= 0) + tmpc.m_diskUsageLWM = config.GetWord(); + tmpc.m_diskUsageHWM = config.GetWord(); + + if (tmpc.m_diskUsageHWM.empty()) + { + m_log.Emsg("Config", "Error: diskusage parameter requires two arguments."); + return false; + } + const char *p = config.GetWord(); + if (p && strcmp(p, "sleep") == 0) + { + p = config.GetWord(); + if (XrdOuca2x::a2i(m_log, "Error getting purge interval", p, &m_configuration.m_purgeInterval, 60, 3600)) { - if (::isalpha(*(minV.rbegin())) && ::isalpha(*(minV.rbegin()))) { - if ( XrdOuca2x::a2sz(m_log, "Error getting disk usage low watermark", minV.c_str(), &m_configuration.m_diskUsageLWM, 0, sP.Total) - || XrdOuca2x::a2sz(m_log, "Error getting disk usage high watermark", maxV.c_str(), &m_configuration.m_diskUsageHWM, 0, sP.Total)) - { - return false; - } - } - else - { - char* eP; - errno = 0; - float lwmf = strtod(minV.c_str(), &eP); - if (errno || eP == minV.c_str()) { - m_log.Emsg("Factory::ConfigParameters() error parsing diskusage parameter ", minV.c_str()); - return false; - } - float hwmf = strtod(maxV.c_str(), &eP); - if (errno || eP == maxV.c_str()) { - m_log.Emsg("Factory::ConfigParameters() error parsing diskusage parameter ", maxV.c_str()); - return false; - } - - m_configuration.m_diskUsageLWM = static_cast(sP.Total * lwmf + 0.5); - m_configuration.m_diskUsageHWM = static_cast(sP.Total * hwmf + 0.5); - } + return false; } } } @@ -294,12 +311,12 @@ bool Cache::ConfigParameters(std::string part, XrdOucStream& config ) { long long minBSize = 64 * 1024; long long maxBSize = 16 * 1024 * 1024; - if ( XrdOuca2x::a2sz(m_log, "get block size", config.GetWord(), &m_configuration.m_bufferSize, minBSize, maxBSize)) + if (XrdOuca2x::a2sz(m_log, "get block size", config.GetWord(), &m_configuration.m_bufferSize, minBSize, maxBSize)) { return false; } } - else if (part == "prefetch" ) + else if ( part == "prefetch" ) { const char* params = config.GetWord(); if (params) { @@ -318,31 +335,47 @@ bool Cache::ConfigParameters(std::string part, XrdOucStream& config ) return false; } } - else if (part == "ram" ) + else if ( part == "ram" ) { - long long minRAM = 1024* 1024 * 1024;; - long long maxRAM = 100 * minRAM; + long long minRAM = 1024 * 1024 * 1024; + long long maxRAM = 256 * minRAM; if ( XrdOuca2x::a2sz(m_log, "get RAM available", config.GetWord(), &m_configuration.m_RamAbsAvailable, minRAM, maxRAM)) { return false; } } + else if ( part == "spaces" ) + { + const char *par; + par = config.GetWord(); + if (par) m_configuration.m_data_space = par; + par = config.GetWord(); + if (par) m_configuration.m_meta_space = par; + else + { + m_log.Emsg("Config", "spacenames requires two parameters: ."); + return false; + } + } else if ( part == "hdfsmode" ) { m_configuration.m_hdfsmode = true; - const char* params = config.GetWord(); - if (params) { - if (!strncmp("hdfsbsize", params, 9)) { - long long minBlSize = 128 * 1024; - long long maxBlSize = 1024 * 1024 * 1024; + const char* params = config.GetWord(); + if (params) + { + if (!strncmp("hdfsbsize", params, 9)) + { + long long minBlSize = 32 * 1024; + long long maxBlSize = 128 * 1024 * 1024; params = config.GetWord(); if ( XrdOuca2x::a2sz(m_log, "Error getting file fragment size", params, &m_configuration.m_hdfsbsize, minBlSize, maxBlSize)) { return false; } } - else { + else + { m_log.Emsg("Config", "Error setting the fragment size parameter name"); return false; } @@ -354,7 +387,7 @@ bool Cache::ConfigParameters(std::string part, XrdOucStream& config ) return false; } - assert ( config.GetWord() == 0 && "Cache::ConfigParameters() lost argument"); + assert (config.GetWord() == 0 && "Cache::ConfigParameters() lost argument"); return true; } diff --git a/src/XrdFileCache/XrdFileCacheFile.cc b/src/XrdFileCache/XrdFileCacheFile.cc index 92fded75ed5..1160109dd96 100644 --- a/src/XrdFileCache/XrdFileCacheFile.cc +++ b/src/XrdFileCache/XrdFileCacheFile.cc @@ -219,7 +219,8 @@ bool File::Open() // Create the data file itself. char size_str[16]; sprintf(size_str, "%lld", m_fileSize); - myEnv.Put("oss.asize", size_str); + myEnv.Put("oss.asize", size_str); + myEnv.Put("oss.cgroup", Cache::GetInstance().RefConfiguration().m_data_space.c_str()); if (myOss.Create(myUser, m_temp_filename.c_str(), 0600, myEnv, XRDOSS_mkpath) != XrdOssOK) { TRACEF(Error, "File::Open() Create failed for data file " << m_temp_filename @@ -243,6 +244,7 @@ bool File::Open() bool fileExisted = (myOss.Stat(ifn.c_str(), &infoStat) == XrdOssOK); myEnv.Put("oss.asize", "64k"); // MT-XXX Calculate? Do not know length of access lists ... + myEnv.Put("oss.cgroup", Cache::GetInstance().RefConfiguration().m_meta_space.c_str()); if (myOss.Create(myUser, ifn.c_str(), 0600, myEnv, XRDOSS_mkpath) != XrdOssOK) { TRACEF(Error, "File::Open() Create failed for info file " << ifn diff --git a/src/XrdFileCache/XrdFileCacheIOEntireFile.cc b/src/XrdFileCache/XrdFileCacheIOEntireFile.cc index 66a989ecd27..14ccb0e414e 100644 --- a/src/XrdFileCache/XrdFileCacheIOEntireFile.cc +++ b/src/XrdFileCache/XrdFileCacheIOEntireFile.cc @@ -40,7 +40,7 @@ IOEntireFile::IOEntireFile(XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache & m_localStat(0) { XrdCl::URL url(GetInput()->Path()); - std::string fname = Cache::GetInstance().RefConfiguration().m_cache_dir + url.GetPath(); + std::string fname = url.GetPath(); m_file = Cache::GetInstance().GetFileWithLocalPath(fname, this); if (m_file) diff --git a/src/XrdFileCache/XrdFileCacheIOFileBlock.cc b/src/XrdFileCache/XrdFileCacheIOFileBlock.cc index d7ebd6aa60a..82432fbf674 100644 --- a/src/XrdFileCache/XrdFileCacheIOFileBlock.cc +++ b/src/XrdFileCache/XrdFileCacheIOFileBlock.cc @@ -105,7 +105,7 @@ void IOFileBlock::GetBlockSizeFromPath() File* IOFileBlock::newBlockFile(long long off, int blocksize) { XrdCl::URL url(GetInput()->Path()); - std::string fname = Cache::GetInstance().RefConfiguration().m_cache_dir + url.GetPath(); + std::string fname = url.GetPath(); std::stringstream ss; ss << fname; diff --git a/src/XrdFileCache/XrdFileCacheInfo.cc b/src/XrdFileCache/XrdFileCacheInfo.cc index 71f3beeda7b..d0e1dbbe3fa 100644 --- a/src/XrdFileCache/XrdFileCacheInfo.cc +++ b/src/XrdFileCache/XrdFileCacheInfo.cc @@ -52,26 +52,29 @@ namespace {} // Returns true on error - bool Read(void *buf, ssize_t size) + bool ReadRaw(void *buf, ssize_t size, bool warnp=true) { ssize_t ret = f_fp->Read(buf, f_off, size); if (ret != size) { - TRACE(Warning, f_ttext << " off=" << f_off << " size=" << size - << " ret=" << ret << " error=" << ((ret < 0) ? strerror(errno) : "")); + if (warnp) + { + TRACE(Warning, f_ttext << " off=" << f_off << " size=" << size + << " ret=" << ret << " error=" << ((ret < 0) ? strerror(errno) : "")); + } return true; } f_off += ret; return false; } - template bool Read(T &loc) + template bool Read(T &loc, bool warnp=true) { - return Read(&loc, sizeof(T)); + return ReadRaw(&loc, sizeof(T), warnp); } // Returns true on error - bool Write(void *buf, ssize_t size) + bool WriteRaw(void *buf, ssize_t size) { ssize_t ret = f_fp->Write(buf, f_off, size); if (ret != size) @@ -86,7 +89,7 @@ namespace template bool Write(T &loc) { - return Write(&loc, sizeof(T)); + return WriteRaw(&loc, sizeof(T)); } }; } @@ -131,7 +134,7 @@ void Info::SetFileSize(long long fs) { m_fileSize = fs; if (m_version >= 0) - ResizeBits((m_fileSize - 1)/m_bufferSize + 1) ; + ResizeBits((m_fileSize - 1)/m_bufferSize + 1); } //------------------------------------------------------------------------------ @@ -139,15 +142,15 @@ void Info::SetFileSize(long long fs) void Info::ResizeBits(int s) { // drop buffer in case of failed/partial reads - if (m_buff_written) free(m_buff_written); - if (m_buff_synced) free(m_buff_synced); - if (m_buff_prefetch) free(m_buff_prefetch); + if (m_buff_written) free(m_buff_written); + if (m_buff_synced) free(m_buff_synced); + if (m_buff_prefetch) free(m_buff_prefetch); m_sizeInBits = s; - m_buff_written = (unsigned char*) malloc(GetSizeInBytes()); - m_buff_synced = (unsigned char*) malloc(GetSizeInBytes()); - memset(m_buff_written, 0, GetSizeInBytes()); - memset(m_buff_synced, 0, GetSizeInBytes()); + m_buff_written = (unsigned char*) malloc(GetSizeInBytes()); + m_buff_synced = (unsigned char*) malloc(GetSizeInBytes()); + memset(m_buff_written, 0, GetSizeInBytes()); + memset(m_buff_synced, 0, GetSizeInBytes()); if (m_hasPrefetchBuffer) { @@ -185,13 +188,13 @@ bool Info::Read(XrdOssDF* fp, const std::string &fname) if (m_version > 0) { - if (r.Read(m_buff_written, GetSizeInBytes())) return false; + if (r.ReadRaw(m_buff_written, GetSizeInBytes())) return false; memcpy(m_buff_synced, m_buff_written, GetSizeInBytes()); } m_complete = ! IsAnythingEmptyInRng(0, m_sizeInBits); - if (r.Read(m_accessCnt)) m_accessCnt = 0; // was: return false; + if (r.Read(m_accessCnt, false)) m_accessCnt = 0; // was: return false; TRACE(Dump, trace_pfx << " complete "<< m_complete << " access_cnt " << m_accessCnt); return true; @@ -231,7 +234,7 @@ bool Info::WriteHeader(XrdOssDF* fp, const std::string &fname) if ( m_version >= 0 ) { - if (w.Write(m_buff_synced, GetSizeInBytes())) + if (w.WriteRaw(m_buff_synced, GetSizeInBytes())) return false; } diff --git a/src/XrdFileCache/XrdFileCachePurge.cc b/src/XrdFileCache/XrdFileCachePurge.cc index 44baed76f59..6f912d89ba7 100644 --- a/src/XrdFileCache/XrdFileCachePurge.cc +++ b/src/XrdFileCache/XrdFileCachePurge.cc @@ -145,31 +145,27 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, FPurgeState& } void Cache::CacheDirCleanup() { - // check state every sleep seconds - const static int sleept = 300; - struct stat fstat; - XrdOucEnv env; - - XrdOss* oss = Cache::GetInstance().GetOss(); + XrdOucEnv env; + XrdOss* oss = Cache::GetInstance().GetOss(); XrdOssVSInfo sP; while (1) { // get amount of space to erase long long bytesToRemove = 0; - if (oss->StatVS(&sP, "public", 1) < 0) + if (oss->StatVS(&sP, m_configuration.m_data_space.c_str(), 1) < 0) { - TRACE(Error, "Cache::CacheDirCleanup() can't get statvs for dir " << m_configuration.m_cache_dir.c_str()); + TRACE(Error, "Cache::CacheDirCleanup() can't get statvs for oss space " << m_configuration.m_data_space); exit(1); } else { long long ausage = sP.Total - sP.Free; - TRACE(Debug, "Cache::CacheDirCleanup() occupates disk space == " << ausage); + TRACE(Info, "Cache::CacheDirCleanup() used disk space " << ausage << " bytes."); if (ausage > m_configuration.m_diskUsageHWM) { bytesToRemove = ausage - m_configuration.m_diskUsageLWM; - TRACE(Debug, "Cache::CacheDirCleanup() need space for " << bytesToRemove << " bytes"); + TRACE(Info, "Cache::CacheDirCleanup() need to remove " << bytesToRemove << " bytes."); } } @@ -177,13 +173,14 @@ void Cache::CacheDirCleanup() { // 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) == XrdOssOK) + if (dh->Opendir("", env) == XrdOssOK) { FPurgeState purgeState(bytesToRemove * 5 / 4); // prepare 20% more volume than required - FillFileMapRecurse(dh, m_configuration.m_cache_dir, purgeState); + FillFileMapRecurse(dh, "", purgeState); // loop over map and remove files with highest value of access time + struct stat fstat; for (FPurgeState::map_i it = purgeState.fmap.begin(); it != purgeState.fmap.end(); ++it) { // XXXX MT - shouldn't we re-check if the file is currently opened? @@ -192,9 +189,10 @@ void Cache::CacheDirCleanup() // remove info file if (oss->Stat(path.c_str(), &fstat) == XrdOssOK) { - bytesToRemove -= fstat.st_size; + // cinfo file can be on another oss.space, do not subtract for now. + // bytesToRemove -= fstat.st_size; oss->Unlink(path.c_str()); - TRACE(Info, "Cache::CacheDirCleanup() removed file:" << path << " size: " << fstat.st_size); + TRACE(Info, "Cache::CacheDirCleanup() removed file:" << path << " size: " << fstat.st_size); } // remove data file @@ -203,7 +201,7 @@ void Cache::CacheDirCleanup() { bytesToRemove -= it->second.nByte; oss->Unlink(path.c_str()); - TRACE(Info, "Cache::CacheDirCleanup() removed file: %s " << path << " size " << it->second.nByte); + TRACE(Info, "Cache::CacheDirCleanup() removed file: " << path << " size: " << it->second.nByte); } if (bytesToRemove <= 0) @@ -211,9 +209,9 @@ void Cache::CacheDirCleanup() } } dh->Close(); - delete dh; dh =0; + delete dh; dh = 0; } - sleep(sleept); + sleep(m_configuration.m_purgeInterval); } }