diff --git a/src/XrdFileCache/XrdFileCache.cc b/src/XrdFileCache/XrdFileCache.cc index 9a432bfca26..6c326893eb2 100644 --- a/src/XrdFileCache/XrdFileCache.cc +++ b/src/XrdFileCache/XrdFileCache.cc @@ -65,14 +65,14 @@ void *PrefetchThread(void* ptr) extern "C" { XrdOucCache2 *XrdOucGetCache2(XrdSysLogger *logger, - const char *config_filename, - const char *parameters) + const char *config_filename, + const char *parameters) { XrdSysError err(0, ""); err.logger(logger); err.Emsg("Retrieve", "Retrieving a caching proxy factory."); Cache &factory = Cache::GetInstance(); - if (!factory.Config(logger, config_filename, parameters)) + if (! factory.Config(logger, config_filename, parameters)) { err.Emsg("Retrieve", "Error - unable to create a factory."); return NULL; @@ -110,15 +110,15 @@ XrdOucCache *Cache::Create(Parms & parms, XrdOucCacheIO::aprParms * prParms) bool Cache::Decide(XrdOucCacheIO* io) { - if (!m_decisionpoints.empty()) + if (! m_decisionpoints.empty()) { std::string filename = io->Path(); std::vector::const_iterator it; for (it = m_decisionpoints.begin(); it != m_decisionpoints.end(); ++it) { XrdFileCache::Decision *d = *it; - if (!d) continue; - if (!d->Decide(filename, *m_output_fs)) + if (! d) continue; + if (! d->Decide(filename, *m_output_fs)) { return false; } @@ -131,15 +131,15 @@ bool Cache::Decide(XrdOucCacheIO* io) Cache::Cache() : XrdOucCache(), - m_log(0, "XrdFileCache_"), - m_trace(0), - m_traceID("Manager"), - m_prefetch_condVar(0), - m_RAMblocks_used(0) + m_log(0, "XrdFileCache_"), + m_trace(0), + m_traceID("Manager"), + m_prefetch_condVar(0), + m_RAMblocks_used(0) { - m_trace = new XrdOucTrace(&m_log); - // default log level is Warning - m_trace->What = 2; + m_trace = new XrdOucTrace(&m_log); + // default log level is Warning + m_trace->What = 2; } //______________________________________________________________________________ @@ -162,7 +162,7 @@ XrdOucCacheIO2 *Cache::Attach(XrdOucCacheIO2 *io, int Options) } else { - TRACE(Info, "Cache::Attach() decision decline " << io->Path()); + TRACE(Info, "Cache::Attach() decision decline " << io->Path()); } return io; } @@ -171,14 +171,14 @@ XrdOucCacheIO2 *Cache::Attach(XrdOucCacheIO2 *io, int Options) int Cache::isAttached() { - // virutal function of XrdOucCache, don't see it used in pfc or posix layer - return true; + // virutal function of XrdOucCache, don't see it used in pfc or posix layer + return true; } void Cache::Detach(File* file) { TRACE(Debug, "Cache::Detach() file = " << file); - + std::map::iterator it = m_active.find(file->GetLocalPath()); assert (it != m_active.end()); m_active.erase(it); @@ -192,7 +192,7 @@ Cache::AddWriteTask(Block* b, bool fromRead) TRACE(Dump, "Cache::AddWriteTask() bOff=%ld " << b->m_offset); m_writeQ.condVar.Lock(); if (fromRead) - m_writeQ.queue.push_back(b); + m_writeQ.queue.push_back(b); else m_writeQ.queue.push_front(b); // AMT should this not be the opposite m_writeQ.size++; @@ -278,12 +278,13 @@ File* Cache::GetFileWithLocalPath(std::string path, IO* iIo) XrdSysMutexHelper lock(&m_active_mutex); std::map::iterator it = m_active.find(path); - if (it != m_active.end()) { + if (it != m_active.end()) + { it->second->WakeUp(iIo); return it->second; } - - + + return 0; } @@ -301,21 +302,21 @@ bool Cache::HaveActiveFileWithLocalPath(std::string path) //======================= PREFETCH =================================== //============================================================================== /* -namespace { -struct prefetch_less_than -{ + namespace { + struct prefetch_less_than + { inline bool operator() (const File* struct1, const File* struct2) { return (struct1->GetPrefetchScore() < struct2->GetPrefetchScore()); } -}myobject; -}*/ + }myobject; + }*/ //______________________________________________________________________________ void Cache::RegisterPrefetchFile(File* file) { - // called from File::Open() + // called from File::Open() if (Cache::GetInstance().RefConfiguration().m_prefetch_max_blocks) { @@ -334,8 +335,10 @@ Cache::DeRegisterPrefetchFile(File* file) // called from last line File::InitiateClose() m_prefetch_condVar.Lock(); - for (PrefetchList::iterator it = m_prefetchList.begin(); it != m_prefetchList.end(); ++it) { - if (*it == file) { + for (PrefetchList::iterator it = m_prefetchList.begin(); it != m_prefetchList.end(); ++it) + { + if (*it == file) + { m_prefetchList.erase(it); break; } @@ -345,11 +348,12 @@ Cache::DeRegisterPrefetchFile(File* file) //______________________________________________________________________________ -File* +File* Cache::GetNextFileToPrefetch() { m_prefetch_condVar.Lock(); - while (m_prefetchList.empty()) { + while (m_prefetchList.empty()) + { m_prefetch_condVar.Wait(); } @@ -373,7 +377,7 @@ Cache::GetNextFileToPrefetch() //! XrdOucCacheIO2::Open() method to open the file at a later time. //------------------------------------------------------------------------------ -int +int Cache::Prepare(const char *url, int oflags, mode_t mode) { std::string curl(url); @@ -383,11 +387,13 @@ Cache::Prepare(const char *url, int oflags, mode_t mode) struct stat buf; int res = m_output_fs->Stat(spath.c_str(), &buf); - if (res == 0) { + if (res == 0) + { TRACE( Dump, "Cache::Prefetch defer open " << spath); return 1; } - else { + else + { return 0; } } @@ -406,16 +412,20 @@ int Cache::Stat(const char *curl, struct stat &sbuff) std::string name = url.GetPath(); name += ".cinfo"; - if (m_output_fs->Stat(name.c_str(), &sbuff) == XrdOssOK) { - if ( S_ISDIR(sbuff.st_mode)) { + if (m_output_fs->Stat(name.c_str(), &sbuff) == XrdOssOK) + { + if ( S_ISDIR(sbuff.st_mode)) + { return 0; } - else { + else + { bool success = false; - XrdOssDF* infoFile = m_output_fs->newFile(m_configuration.m_username.c_str()); - XrdOucEnv myEnv; + XrdOssDF* infoFile = m_output_fs->newFile(m_configuration.m_username.c_str()); + XrdOucEnv myEnv; int res = infoFile->Open(name.c_str(), O_RDONLY, 0600, myEnv); - if (res >= 0) { + if (res >= 0) + { Info info(m_trace, 0); if (info.Read(infoFile, name)) { @@ -428,28 +438,31 @@ int Cache::Stat(const char *curl, struct stat &sbuff) return success ? 0 : 1; } } - + return 1; } //______________________________________________________________________________ -void +void Cache::Prefetch() { - int limitRAM= Cache::GetInstance().RefConfiguration().m_NRamBuffers * 0.7; - while (true) { + int limitRAM = Cache::GetInstance().RefConfiguration().m_NRamBuffers * 0.7; + while (true) + { m_RAMblock_mutex.Lock(); bool doPrefetch = (m_RAMblocks_used < limitRAM); m_RAMblock_mutex.UnLock(); - if (doPrefetch) { + if (doPrefetch) + { File* f = GetNextFileToPrefetch(); f->Prefetch(); } - else { + else + { XrdSysTimer::Wait(5); } - } -} + } +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCache.hh b/src/XrdFileCache/XrdFileCache.hh index 1a43f980654..24b30eaa0df 100644 --- a/src/XrdFileCache/XrdFileCache.hh +++ b/src/XrdFileCache/XrdFileCache.hh @@ -33,7 +33,7 @@ class XrdSysError; class XrdOucTrace; namespace XrdCl { - class Log; +class Log; } namespace XrdFileCache { class File; @@ -43,217 +43,218 @@ class IO; namespace XrdFileCache { - //---------------------------------------------------------------------------- - //! Contains parameters configurable from the xrootd config file. - //---------------------------------------------------------------------------- - struct Configuration - { - 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) - {} - - bool m_hdfsmode; //!< flag for enabling block-level operation - 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 - 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 - }; +//---------------------------------------------------------------------------- +//! Contains parameters configurable from the xrootd config file. +//---------------------------------------------------------------------------- +struct Configuration +{ + 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) + {} + + bool m_hdfsmode; //!< flag for enabling block-level operation + + 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 + 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. +//---------------------------------------------------------------------------- +class Cache : public XrdOucCache2 +{ +public: + //--------------------------------------------------------------------- + //! Constructor + //--------------------------------------------------------------------- + Cache(); - struct TmpConfiguration - { - std::string m_diskUsageLWM; - std::string m_diskUsageHWM; + //--------------------------------------------------------------------- + //! Obtain a new IO object that fronts existing XrdOucCacheIO. + //--------------------------------------------------------------------- + virtual XrdOucCacheIO2 *Attach(XrdOucCacheIO2 *, int Options = 0); - TmpConfiguration() : - m_diskUsageLWM("0.90"), m_diskUsageHWM("0.95") - {} - }; + //--------------------------------------------------------------------- + //! Number of cache-io objects atteched through this cache. + //--------------------------------------------------------------------- + virtual int isAttached(); - //---------------------------------------------------------------------------- - //! Attaches/creates and detaches/deletes cache-io objects for disk based cache. - //---------------------------------------------------------------------------- - class Cache : public XrdOucCache2 - { - public: - //--------------------------------------------------------------------- - //! Constructor - //--------------------------------------------------------------------- - Cache(); + //--------------------------------------------------------------------- + // this is an obsolete method + virtual XrdOucCache* Create(XrdOucCache::Parms&, XrdOucCacheIO::aprParms*); + + // Virtual function of XrdOucCache2. Used for deferred open. + virtual int Prepare(const char *url, int oflags, mode_t mode); - //--------------------------------------------------------------------- - //! Obtain a new IO object that fronts existing XrdOucCacheIO. - //--------------------------------------------------------------------- - virtual XrdOucCacheIO2 *Attach(XrdOucCacheIO2 *, int Options=0); - //--------------------------------------------------------------------- - //! Number of cache-io objects atteched through this cache. - //--------------------------------------------------------------------- - virtual int isAttached(); - - //--------------------------------------------------------------------- - // this is an obsolete method - virtual XrdOucCache* Create(XrdOucCache::Parms&, XrdOucCacheIO::aprParms*); - - // Virtual function of XrdOucCache2. Used for deferred open. - virtual int Prepare(const char *url, int oflags, mode_t mode); - - - // virtual function of XrdOucCache2::Stat() - virtual int Stat(const char *url, struct stat &sbuff); + // virtual function of XrdOucCache2::Stat() + virtual int Stat(const char *url, struct stat &sbuff); - //-------------------------------------------------------------------- - //! \brief Makes decision if the original XrdOucCacheIO should be cached. - //! - //! @param & URL of file - //! - //! @return decision if IO object will be cached. - //-------------------------------------------------------------------- - bool Decide(XrdOucCacheIO*); + //-------------------------------------------------------------------- + //! \brief Makes decision if the original XrdOucCacheIO should be cached. + //! + //! @param & URL of file + //! + //! @return decision if IO object will be cached. + //-------------------------------------------------------------------- + bool Decide(XrdOucCacheIO*); - //------------------------------------------------------------------------ - //! Reference XrdFileCache configuration - //------------------------------------------------------------------------ - const Configuration& RefConfiguration() const { return m_configuration; } + //------------------------------------------------------------------------ + //! Reference XrdFileCache configuration + //------------------------------------------------------------------------ + const Configuration& RefConfiguration() const { return m_configuration; } - //--------------------------------------------------------------------- - //! \brief Parse configuration file - //! - //! @param logger xrootd logger - //! @param config_filename path to configuration file - //! @param parameters optional parameters to be passed - //! - //! @return parse status - //--------------------------------------------------------------------- - bool Config(XrdSysLogger *logger, const char *config_filename, const char *parameters); + //--------------------------------------------------------------------- + //! \brief Parse configuration file + //! + //! @param logger xrootd logger + //! @param config_filename path to configuration file + //! @param parameters optional parameters to be passed + //! + //! @return parse status + //--------------------------------------------------------------------- + bool Config(XrdSysLogger *logger, const char *config_filename, const char *parameters); - //--------------------------------------------------------------------- - //! Singleton access. - //--------------------------------------------------------------------- - static Cache &GetInstance(); + //--------------------------------------------------------------------- + //! Singleton access. + //--------------------------------------------------------------------- + static Cache &GetInstance(); - //--------------------------------------------------------------------- - //! Version check. - //--------------------------------------------------------------------- - static bool VCheck(XrdVersionInfo &urVersion) { return true; } + //--------------------------------------------------------------------- + //! Version check. + //--------------------------------------------------------------------- + static bool VCheck(XrdVersionInfo &urVersion) { return true; } - //--------------------------------------------------------------------- - //! Thread function running disk cache purge periodically. - //--------------------------------------------------------------------- - void CacheDirCleanup(); + //--------------------------------------------------------------------- + //! Thread function running disk cache purge periodically. + //--------------------------------------------------------------------- + void CacheDirCleanup(); - //--------------------------------------------------------------------- - //! Add downloaded block in write queue. - //--------------------------------------------------------------------- - void AddWriteTask(Block* b, bool from_read); + //--------------------------------------------------------------------- + //! Add downloaded block in write queue. + //--------------------------------------------------------------------- + void AddWriteTask(Block* b, bool from_read); - //--------------------------------------------------------------------- - //! \brief Remove blocks from write queue which belong to given prefetch. - //! This method is used at the time of File destruction. - //--------------------------------------------------------------------- - void RemoveWriteQEntriesFor(File *f); + //--------------------------------------------------------------------- + //! \brief Remove blocks from write queue which belong to given prefetch. + //! This method is used at the time of File destruction. + //--------------------------------------------------------------------- + void RemoveWriteQEntriesFor(File *f); - //--------------------------------------------------------------------- - //! Separate task which writes blocks from ram to disk. - //--------------------------------------------------------------------- - void ProcessWriteTasks(); + //--------------------------------------------------------------------- + //! Separate task which writes blocks from ram to disk. + //--------------------------------------------------------------------- + void ProcessWriteTasks(); - bool RequestRAMBlock(); + bool RequestRAMBlock(); - void RAMBlockReleased(); + void RAMBlockReleased(); - void RegisterPrefetchFile(File*); - void DeRegisterPrefetchFile(File*); + void RegisterPrefetchFile(File*); + void DeRegisterPrefetchFile(File*); - File* GetNextFileToPrefetch(); + File* GetNextFileToPrefetch(); - void Prefetch(); + void Prefetch(); - //! Decrease attached count. Called from IO::Detach(). - void Detach(File*); + //! Decrease attached count. Called from IO::Detach(). + void Detach(File*); - XrdOss* GetOss() const { return m_output_fs; } + XrdOss* GetOss() const { return m_output_fs; } - XrdSysError& GetSysError() { return m_log; } + XrdSysError& GetSysError() { return m_log; } - File* GetFileWithLocalPath(std::string, IO* io); + File* GetFileWithLocalPath(std::string, IO* io); - bool HaveActiveFileWithLocalPath(std::string); - - void AddActive(File*); - - XrdOucTrace* GetTrace() { return m_trace; } + bool HaveActiveFileWithLocalPath(std::string); - private: - bool ConfigParameters(std::string, XrdOucStream&, TmpConfiguration &tmpc); - bool ConfigXeq(char *, XrdOucStream &); - bool xdlib(XrdOucStream &); - bool xtrace(XrdOucStream &); - static Cache *m_factory; //!< this object + void AddActive(File*); - XrdSysError m_log; //!< XrdFileCache namespace logger - XrdOucTrace* m_trace; - const char* m_traceID; + XrdOucTrace* GetTrace() { return m_trace; } - XrdOucCacheStats m_stats; //!< - XrdOss *m_output_fs; //!< disk cache file system +private: + bool ConfigParameters(std::string, XrdOucStream&, TmpConfiguration &tmpc); + bool ConfigXeq(char *, XrdOucStream &); + bool xdlib(XrdOucStream &); + bool xtrace(XrdOucStream &); + static Cache *m_factory; //!< this object - std::vector m_decisionpoints; //!< decision plugins + XrdSysError m_log; //!< XrdFileCache namespace logger + XrdOucTrace* m_trace; + const char* m_traceID; - std::map m_filesInQueue; + XrdOucCacheStats m_stats; //!< + XrdOss *m_output_fs; //!< disk cache file system - Configuration m_configuration; //!< configurable parameters + std::vector m_decisionpoints; //!< decision plugins - XrdSysCondVar m_prefetch_condVar; //!< central lock for this class + std::map m_filesInQueue; - XrdSysMutex m_RAMblock_mutex; //!< central lock for this class - int m_RAMblocks_used; + Configuration m_configuration; //!< configurable parameters - struct WriteQ - { - WriteQ() : condVar(0), size(0) {} - XrdSysCondVar condVar; //!< write list condVar - size_t size; //!< cache size of a container - std::list queue; //!< container - }; + XrdSysCondVar m_prefetch_condVar; //!< central lock for this class - WriteQ m_writeQ; + XrdSysMutex m_RAMblock_mutex; //!< central lock for this class + int m_RAMblocks_used; - struct DiskNetIO - { - DiskNetIO(IO* iIO, File* iFile): io(iIO), file(iFile){} - IO* io; - File* file; - }; + struct WriteQ + { + WriteQ() : condVar(0), size(0) {} + XrdSysCondVar condVar; //!< write list condVar + size_t size; //!< cache size of a container + std::list queue; //!< container + }; - std::map m_active; - XrdSysMutex m_active_mutex; + WriteQ m_writeQ; - // prefetching - typedef std::vector PrefetchList; - PrefetchList m_prefetchList; + struct DiskNetIO + { + DiskNetIO(IO* iIO, File* iFile) : io(iIO), file(iFile){} + IO* io; + File* file; }; + std::map m_active; + XrdSysMutex m_active_mutex; + + // prefetching + typedef std::vector PrefetchList; + PrefetchList m_prefetchList; +}; + } #endif diff --git a/src/XrdFileCache/XrdFileCacheAllowDecision.cc b/src/XrdFileCache/XrdFileCacheAllowDecision.cc index 392e43284ce..0e0f8699df3 100644 --- a/src/XrdFileCache/XrdFileCacheAllowDecision.cc +++ b/src/XrdFileCache/XrdFileCacheAllowDecision.cc @@ -22,12 +22,12 @@ class AllowDecision : public XrdFileCache::Decision { - //---------------------------------------------------------------------------- - //! The simplest example of plugin - always allow the file to be prefetched. - //---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +//! The simplest example of plugin - always allow the file to be prefetched. +//---------------------------------------------------------------------------- - public: - virtual bool Decide(std::string &, XrdOss &) const {return true; } +public: +virtual bool Decide(std::string &, XrdOss &) const {return true; } }; @@ -40,7 +40,6 @@ extern "C" { XrdFileCache::Decision *XrdFileCacheGetDecision(XrdSysError &) { - return new AllowDecision(); + return new AllowDecision(); } -} - +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheBlacklistDecision.cc b/src/XrdFileCache/XrdFileCacheBlacklistDecision.cc index dadb501b5ce..a9a91f3dd8d 100644 --- a/src/XrdFileCache/XrdFileCacheBlacklistDecision.cc +++ b/src/XrdFileCache/XrdFileCacheBlacklistDecision.cc @@ -26,90 +26,89 @@ class BlacklistDecision : public XrdFileCache::Decision { - //---------------------------------------------------------------------------- - //! A decision library that allows all files to be cached except for a blacklist - //---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +//! A decision library that allows all files to be cached except for a blacklist +//---------------------------------------------------------------------------- - public: - virtual bool Decide(const std::string & url, XrdOss &) const - { - size_t slashslash = url.find("//"); - const char *fname = url.c_str(); - if (slashslash != std::string::npos) - { - fname += slashslash+2; - fname = strchr(fname, '/'); - if (!fname) {return true;} - } - std::string url_path = fname; - size_t question = url_path.find("?"); - if (question != std::string::npos) - { - url_path[question] = '\0'; - fname = url_path.c_str(); - } - if ((strlen(fname) > 1) && (fname[0] == '/') && (fname[1] == '/')) - { - fname++; - } - //m_log.Emsg("BlacklistDecide", "Deciding whether to cache file", fname); - for (std::vector::const_iterator it = m_blacklist.begin(); it != m_blacklist.end(); it++) - { - if (!fnmatch(it->c_str(), fname, FNM_PATHNAME)) - { - //m_log.Emsg("BlacklistDecide", "Not caching file as it matches blacklist entry", it->c_str()); - return false; - } - } - //m_log.Emsg("BlacklistDecide", "Caching file", fname); - return true; - } +public: +virtual bool Decide(const std::string & url, XrdOss &) const +{ + size_t slashslash = url.find("//"); + const char *fname = url.c_str(); + if (slashslash != std::string::npos) + { + fname += slashslash+2; + fname = strchr(fname, '/'); + if (! fname) {return true; } + } + std::string url_path = fname; + size_t question = url_path.find("?"); + if (question != std::string::npos) + { + url_path[question] = '\0'; + fname = url_path.c_str(); + } + if ((strlen(fname) > 1) && (fname[0] == '/') && (fname[1] == '/')) + { + fname++; + } + //m_log.Emsg("BlacklistDecide", "Deciding whether to cache file", fname); + for (std::vector::const_iterator it = m_blacklist.begin(); it != m_blacklist.end(); it++) + { + if (! fnmatch(it->c_str(), fname, FNM_PATHNAME)) + { + //m_log.Emsg("BlacklistDecide", "Not caching file as it matches blacklist entry", it->c_str()); + return false; + } + } + //m_log.Emsg("BlacklistDecide", "Caching file", fname); + return true; +} - BlacklistDecision(XrdSysError &log) - : m_log(log) - { - } +BlacklistDecision(XrdSysError &log) + : m_log(log) +{} - virtual bool ConfigDecision(const char * parms) - { - if (!parms || !parms[0] || (strlen(parms) == 0)) - { - m_log.Emsg("ConfigDecision", "Blacklist file not specified."); - return false; - } - m_log.Emsg("ConfigDecision", "Using blacklist", parms); - FILE * fp = fopen(parms, "r"); - if (fp == 0) - { - m_log.Emsg("ConfigDecision", errno, "Failed to open blacklist:", parms); - return false; - } +virtual bool ConfigDecision(const char * parms) +{ + if (! parms || ! parms[0] || (strlen(parms) == 0)) + { + m_log.Emsg("ConfigDecision", "Blacklist file not specified."); + return false; + } + m_log.Emsg("ConfigDecision", "Using blacklist", parms); + FILE * fp = fopen(parms, "r"); + if (fp == 0) + { + m_log.Emsg("ConfigDecision", errno, "Failed to open blacklist:", parms); + return false; + } - char line[4096]; - while(fgets(line, sizeof(line), fp)) - { - char *trimmed = line; - while (trimmed[0] && isspace(trimmed[0])) {trimmed++;} - if (trimmed[0] == 0) {continue;} - size_t filelen = strlen(trimmed); - if (trimmed[filelen-1] == '\n') {trimmed[filelen-1] = '\0';} - m_blacklist.push_back(trimmed); - } - if (!feof(fp)) - { - m_log.Emsg("ConfigDecision", errno, "Failed to parse blacklist"); - } - fclose(fp); - for (std::vector::const_iterator it=m_blacklist.begin(); it!=m_blacklist.end(); it++) - { - m_log.Emsg("ConfigDecision", "Cache is blacklisting paths matching", it->c_str()); - } - return true; - } + char line[4096]; + while(fgets(line, sizeof(line), fp)) + { + char *trimmed = line; + while (trimmed[0] && isspace(trimmed[0])) {trimmed++; } + if (trimmed[0] == 0) {continue; } + size_t filelen = strlen(trimmed); + if (trimmed[filelen-1] == '\n') {trimmed[filelen-1] = '\0'; } + m_blacklist.push_back(trimmed); + } + if (! feof(fp)) + { + m_log.Emsg("ConfigDecision", errno, "Failed to parse blacklist"); + } + fclose(fp); + for (std::vector::const_iterator it = m_blacklist.begin(); it!=m_blacklist.end(); it++) + { + m_log.Emsg("ConfigDecision", "Cache is blacklisting paths matching", it->c_str()); + } + return true; +} - private: - std::vector m_blacklist; - XrdSysError &m_log; +private: +std::vector m_blacklist; +XrdSysError &m_log; }; /******************************************************************************/ @@ -121,7 +120,6 @@ extern "C" { XrdFileCache::Decision *XrdFileCacheGetDecision(XrdSysError &err) { - return new BlacklistDecision(err); + return new BlacklistDecision(err); } -} - +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheConfiguration.cc b/src/XrdFileCache/XrdFileCacheConfiguration.cc index c96c7f0a0ee..a39caca18dc 100644 --- a/src/XrdFileCache/XrdFileCacheConfiguration.cc +++ b/src/XrdFileCache/XrdFileCacheConfiguration.cc @@ -29,40 +29,40 @@ XrdVERSIONINFO(XrdOucGetCache2, XrdFileCache); */ bool Cache::xdlib(XrdOucStream &Config) { - const char* val; - - std::string libp; - if (!(val = Config.GetWord()) || !val[0]) - { - TRACE(Info," Cache::Config() decisionlib not specified; always caching files"); - return true; - } - else - { - libp = val; - } - - const char* params; - params = (val[0]) ? Config.GetWord() : 0; - - XrdOucPinLoader* myLib = new XrdOucPinLoader(&m_log, 0, "decisionlib", - libp.c_str()); - - Decision *(*ep)(XrdSysError&); - ep = (Decision *(*)(XrdSysError&))myLib->Resolve("XrdFileCacheGetDecision"); - if (!ep) {myLib->Unload(true); return false;} - - Decision * d = ep(m_log); - if (!d) - { - TRACE(Error, "Cache::Config() decisionlib was not able to create a decision object"); - return false; - } - if (params) - d->ConfigDecision(params); - - m_decisionpoints.push_back(d); - return true; + const char* val; + + std::string libp; + if (! (val = Config.GetWord()) || ! val[0]) + { + TRACE(Info," Cache::Config() decisionlib not specified; always caching files"); + return true; + } + else + { + libp = val; + } + + const char* params; + params = (val[0]) ? Config.GetWord() : 0; + + XrdOucPinLoader* myLib = new XrdOucPinLoader(&m_log, 0, "decisionlib", + libp.c_str()); + + Decision *(*ep)(XrdSysError&); + ep = (Decision *(*)(XrdSysError&))myLib->Resolve("XrdFileCacheGetDecision"); + if (! ep) {myLib->Unload(true); return false; } + + Decision * d = ep(m_log); + if (! d) + { + TRACE(Error, "Cache::Config() decisionlib was not able to create a decision object"); + return false; + } + if (params) + d->ConfigDecision(params); + + m_decisionpoints.push_back(d); + return true; } /* Function: xtrace @@ -73,26 +73,27 @@ bool Cache::xdlib(XrdOucStream &Config) bool Cache::xtrace(XrdOucStream &Config) { char *val; - static struct traceopts {const char *opname; int opval;} tropts[] = - { + static struct traceopts {const char *opname; int opval; } tropts[] = + { {"none", 0}, {"error", 1}, {"warning", 2}, {"info", 3}, {"debug", 4}, {"dump", 5} - }; - int numopts = sizeof(tropts)/sizeof(struct traceopts); + }; + int numopts = sizeof(tropts)/sizeof(struct traceopts); - if (!(val = Config.GetWord())) - {m_log.Emsg("Config", "trace option not specified"); return 1;} + if (! (val = Config.GetWord())) + {m_log.Emsg("Config", "trace option not specified"); return 1; } for (int i = 0; i < numopts; i++) { - if (!strcmp(val, tropts[i].opname)) { + if (! strcmp(val, tropts[i].opname)) + { m_trace->What = tropts[i].opval; return true; - } + } } return false; } @@ -101,293 +102,300 @@ bool Cache::xtrace(XrdOucStream &Config) bool Cache::Config(XrdSysLogger *logger, const char *config_filename, const char *parameters) { - m_log.logger(logger); - - const char * cache_env; - if (!(cache_env = getenv("XRDPOSIX_CACHE")) || !*cache_env) - XrdOucEnv::Export("XRDPOSIX_CACHE", "mode=s&optwr=0"); - - XrdOucEnv myEnv; - XrdOucStream Config(&m_log, getenv("XRDINSTANCE"), &myEnv, "=====> "); - - if (!config_filename || !*config_filename) - { - TRACE(Error, "Cache::Config() configuration file not specified."); - return false; - } - - int fd; - if ( (fd = open(config_filename, O_RDONLY, 0)) < 0) - { - TRACE( Error, "Cache::Config() can't open configuration file " << config_filename); - return false; - } - - Config.Attach(fd); - - // Obtain plugin configurator - XrdOfsConfigPI *ofsCfg = XrdOfsConfigPI::New(config_filename,&Config,&m_log, - &XrdVERSIONINFOVAR(XrdOucGetCache2)); - if (!ofsCfg) return false; - - TmpConfiguration tmpc; - - if (ofsCfg->Load(XrdOfsConfigPI::theOssLib)) - { - ofsCfg->Plugin(m_output_fs); - } - else - { - TRACE(Error, "Cache::Config() Unable to create an OSS object"); - m_output_fs = 0; - return false; - } - - - // Actual parsing of the config file. - bool retval = true; - char *var; - while((var = Config.GetMyFirstWord())) - { - if (!strcmp(var,"pfc.osslib")) - { - ofsCfg->Parse(XrdOfsConfigPI::theOssLib); - } - else if (!strcmp(var,"pfc.decisionlib")) - { - retval = xdlib(Config); - } - else if (!strcmp(var,"pfc.trace")) - { - retval = xtrace(Config); - } - else if (!strncmp(var,"pfc.", 4)) - { - retval = ConfigParameters(std::string(var+4), Config, tmpc); - } - - if ( ! retval) - { - retval = false; - TRACE(Error, "Cache::Config() error in parsing"); - break; - } - - } - - Config.Close(); - - // sets default value for disk usage - { - XrdOssVSInfo sP; - 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()); + m_log.logger(logger); + + const char * cache_env; + if (! (cache_env = getenv("XRDPOSIX_CACHE")) || ! *cache_env) + XrdOucEnv::Export("XRDPOSIX_CACHE", "mode=s&optwr=0"); + + XrdOucEnv myEnv; + XrdOucStream Config(&m_log, getenv("XRDINSTANCE"), &myEnv, "=====> "); + + if (! config_filename || ! *config_filename) + { + TRACE(Error, "Cache::Config() configuration file not specified."); + return false; + } + + int fd; + if ( (fd = open(config_filename, O_RDONLY, 0)) < 0) + { + TRACE( Error, "Cache::Config() can't open configuration file " << config_filename); + return false; + } + + Config.Attach(fd); + + // Obtain plugin configurator + XrdOfsConfigPI *ofsCfg = XrdOfsConfigPI::New(config_filename,&Config,&m_log, + &XrdVERSIONINFOVAR(XrdOucGetCache2)); + if (! ofsCfg) return false; + + TmpConfiguration tmpc; + + if (ofsCfg->Load(XrdOfsConfigPI::theOssLib)) + { + ofsCfg->Plugin(m_output_fs); + } + else + { + TRACE(Error, "Cache::Config() Unable to create an OSS object"); + m_output_fs = 0; + return false; + } + + + // Actual parsing of the config file. + bool retval = true; + char *var; + while((var = Config.GetMyFirstWord())) + { + if (! strcmp(var,"pfc.osslib")) + { + ofsCfg->Parse(XrdOfsConfigPI::theOssLib); + } + else if (! strcmp(var,"pfc.decisionlib")) + { + retval = xdlib(Config); + } + else if (! strcmp(var,"pfc.trace")) + { + retval = xtrace(Config); + } + else if (! strncmp(var,"pfc.", 4)) + { + retval = ConfigParameters(std::string(var+4), Config, tmpc); + } + + if ( ! retval) + { + retval = false; + TRACE(Error, "Cache::Config() error in parsing"); + break; + } + + } + + Config.Close(); + + // sets default value for disk usage + { + XrdOssVSInfo sP; + 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; - } - - 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) - { - 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); - - // Set tracing to debug if this is set in environment - char* cenv = getenv("XRDDEBUG"); - if (cenv && !strcmp(cenv,"1")) m_trace->What = 4; - - if (retval) - { - int loff = 0; - 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\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) - { - char buff2[512]; - snprintf(buff2, sizeof(buff2), "\tpfc.hdfsmode hdfsbsize %lld\n", m_configuration.m_hdfsbsize); - loff += snprintf(&buff[loff], strlen(buff2), "%s", buff2); - } - - char unameBuff[256]; - if (m_configuration.m_username.empty()) { - 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); - } - - m_log.Say( buff); - } - - m_log.Say("------ File Caching Proxy interface initialization ", retval ? "completed" : "failed"); - - if (ofsCfg) delete ofsCfg; - - return retval; + } + + 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) + { + 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); + + // Set tracing to debug if this is set in environment + char* cenv = getenv("XRDDEBUG"); + if (cenv && ! strcmp(cenv,"1")) m_trace->What = 4; + + if (retval) + { + int loff = 0; + 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\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) + { + char buff2[512]; + snprintf(buff2, sizeof(buff2), "\tpfc.hdfsmode hdfsbsize %lld\n", m_configuration.m_hdfsbsize); + loff += snprintf(&buff[loff], strlen(buff2), "%s", buff2); + } + + char unameBuff[256]; + if (m_configuration.m_username.empty()) + { + 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); + } + + m_log.Say( buff); + } + + 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, TmpConfiguration &tmpc) -{ - XrdSysError err(0, ""); - if ( part == "user" ) - { - m_configuration.m_username = config.GetWord(); - } - else if ( part == "diskusage" ) - { - 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)) - { +{ + XrdSysError err(0, ""); + if ( part == "user" ) + { + m_configuration.m_username = config.GetWord(); + } + else if ( part == "diskusage" ) + { + 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; - } - } - } - else if ( part == "blocksize" ) - { - 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)) - { - return false; - } - } - else if ( part == "prefetch" ) - { - const char* params = config.GetWord(); - if (params) { - int p = ::atoi(params); - if (p > 0) { - printf("prefetch enabled, max blocks per file=%d\n", p); - m_configuration.m_prefetch_max_blocks = p; - } else { - m_log.Emsg("Config", "Prefetch is disabled"); - m_configuration.m_prefetch_max_blocks = 0; - } - } - else - { - m_log.Emsg("Config", "Error setting prefetch level."); - return false; - } - } - else if ( part == "ram" ) - { - 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 = 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)) + } + 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)) { - return false; + return false; } - } - else - { - m_log.Emsg("Config", "Error setting the fragment size parameter name"); - return false; - } - } - } - else - { - m_log.Emsg("Cache::ConfigParameters() unmatched pfc parameter", part.c_str()); - return false; - } - - assert (config.GetWord() == 0 && "Cache::ConfigParameters() lost argument"); - - return true; -} + } + } + else if ( part == "blocksize" ) + { + 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)) + { + return false; + } + } + else if ( part == "prefetch" ) + { + const char* params = config.GetWord(); + if (params) + { + int p = ::atoi(params); + if (p > 0) + { + printf("prefetch enabled, max blocks per file=%d\n", p); + m_configuration.m_prefetch_max_blocks = p; + } + else + { + m_log.Emsg("Config", "Prefetch is disabled"); + m_configuration.m_prefetch_max_blocks = 0; + } + } + else + { + m_log.Emsg("Config", "Error setting prefetch level."); + return false; + } + } + else if ( part == "ram" ) + { + 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 = 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 + { + m_log.Emsg("Config", "Error setting the fragment size parameter name"); + return false; + } + } + } + else + { + m_log.Emsg("Cache::ConfigParameters() unmatched pfc parameter", part.c_str()); + return false; + } + + assert (config.GetWord() == 0 && "Cache::ConfigParameters() lost argument"); + + return true; +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheDecision.hh b/src/XrdFileCache/XrdFileCacheDecision.hh index 08b1947bc28..b1793f69685 100644 --- a/src/XrdFileCache/XrdFileCacheDecision.hh +++ b/src/XrdFileCache/XrdFileCacheDecision.hh @@ -27,40 +27,40 @@ class XrdSysError; namespace XrdFileCache { - //---------------------------------------------------------------------------- - //! Base class for selecting which files should be cached. - //---------------------------------------------------------------------------- - class Decision - { - public: - //-------------------------------------------------------------------------- - //! Destructor - //-------------------------------------------------------------------------- - virtual ~Decision() {} +//---------------------------------------------------------------------------- +//! Base class for selecting which files should be cached. +//---------------------------------------------------------------------------- +class Decision +{ +public: + //-------------------------------------------------------------------------- + //! Destructor + //-------------------------------------------------------------------------- + virtual ~Decision() {} - //--------------------------------------------------------------------- - //! Decide if original source will be cached. - //! - //! @param & path - //! @param & file system - //! - //! @return decision - //--------------------------------------------------------------------- - virtual bool Decide(const std::string &, XrdOss &) const = 0; + //--------------------------------------------------------------------- + //! Decide if original source will be cached. + //! + //! @param & path + //! @param & file system + //! + //! @return decision + //--------------------------------------------------------------------- + virtual bool Decide(const std::string &, XrdOss &) const = 0; - //------------------------------------------------------------------------------ - //! Parse configuration arguments. - //! - //! @param params configuration parameters - //! - //! @return status of configuration - //------------------------------------------------------------------------------ - virtual bool ConfigDecision(const char* params) - { - (void) params; - return true; - } - }; + //------------------------------------------------------------------------------ + //! Parse configuration arguments. + //! + //! @param params configuration parameters + //! + //! @return status of configuration + //------------------------------------------------------------------------------ + virtual bool ConfigDecision(const char* params) + { + (void) params; + return true; + } +}; } -#endif +#endif \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheFile.cc b/src/XrdFileCache/XrdFileCacheFile.cc index 1473d84074f..ecfb941969e 100644 --- a/src/XrdFileCache/XrdFileCacheFile.cc +++ b/src/XrdFileCache/XrdFileCacheFile.cc @@ -40,31 +40,31 @@ namespace XrdPosixGlobals { - extern XrdScheduler *schedP; +extern XrdScheduler *schedP; } using namespace XrdFileCache; namespace { - const int PREFETCH_MAX_ATTEMPTS = 10; - - class DiskSyncer : public XrdJob - { - private: - File *m_file; - public: - DiskSyncer(File *pref, const char *desc="") : - XrdJob(desc), - m_file(pref) - {} - void DoIt() - { - m_file->Sync(); - } - }; +const int PREFETCH_MAX_ATTEMPTS = 10; + +class DiskSyncer : public XrdJob +{ +private: + File *m_file; +public: + DiskSyncer(File *pref, const char *desc = "") : + XrdJob(desc), + m_file(pref) + {} + void DoIt() + { + m_file->Sync(); + } +}; - Cache* cache() { return &Cache::GetInstance(); } +Cache* cache() { return &Cache::GetInstance(); } } const char *File::m_traceID = "File"; @@ -111,7 +111,7 @@ File::~File() m_output = NULL; } - delete m_syncer; + delete m_syncer; m_syncer = NULL; TRACEF(Debug, "File::~File() ended, prefetch score = " << m_prefetchScore); @@ -133,11 +133,11 @@ void File::BlockRemovedFromWriteQ(Block* b) bool File::ioActive() { // Retruns true if delay is needed - + TRACEF(Debug, "File::ioActive start"); - if (!m_is_open) return false; - + if (! m_is_open) return false; + // remove failed blocks and check if map is empty m_downloadCond.Lock(); @@ -178,38 +178,41 @@ bool File::ioActive() if (blockMapEmpty) { - // file is not active when block map is empty and sync is done - bool schedule_sync = false; - - { - XrdSysCondVarHelper _lck(m_downloadCond); - - if (m_in_sync) return true; - - if (m_writes_during_sync.empty() && m_non_flushed_cnt == 0) - { - if (!m_detachTimeIsLogged) { - m_cfi.WriteIOStatDetach(m_stats); - m_detachTimeIsLogged = true; - schedule_sync = true; - } - } - else - { - // write leftovers + // file is not active when block map is empty and sync is done + bool schedule_sync = false; + + { + XrdSysCondVarHelper _lck(m_downloadCond); + + if (m_in_sync) return true; + + if (m_writes_during_sync.empty() && m_non_flushed_cnt == 0) + { + if (! m_detachTimeIsLogged) + { + m_cfi.WriteIOStatDetach(m_stats); + m_detachTimeIsLogged = true; schedule_sync = true; - } + } + } + else + { + // write leftovers + schedule_sync = true; + } - if (schedule_sync) - m_in_sync = true; - } - - if (schedule_sync) { - XrdPosixGlobals::schedP->Schedule(m_syncer); - } - else { - return false; - } + if (schedule_sync) + m_in_sync = true; + } + + if (schedule_sync) + { + XrdPosixGlobals::schedP->Schedule(m_syncer); + } + else + { + return false; + } } return true; @@ -235,24 +238,24 @@ bool File::Open() XrdOss &myOss = * Cache::GetInstance().GetOss(); const char *myUser = Cache::GetInstance().RefConfiguration().m_username.c_str(); - XrdOucEnv myEnv; + XrdOucEnv myEnv; // Create the data file itself. char size_str[16]; sprintf(size_str, "%lld", m_fileSize); 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 - << ", err=" << strerror(errno)); + << ", err=" << strerror(errno)); return false; } m_output = myOss.newFile(myUser); if (m_output->Open(m_temp_filename.c_str(), O_RDWR, 0600, myEnv) != XrdOssOK) { - TRACEF(Error, "File::Open() Open failed for data file " << m_temp_filename - << ", err=" << strerror(errno)); + TRACEF(Error, "File::Open() Open failed for data file " << m_temp_filename + << ", err=" << strerror(errno)); delete m_output; m_output = 0; return false; } @@ -268,7 +271,7 @@ bool File::Open() if (myOss.Create(myUser, ifn.c_str(), 0600, myEnv, XRDOSS_mkpath) != XrdOssOK) { TRACEF(Error, "File::Open() Create failed for info file " << ifn - << ", err=" << strerror(errno)); + << ", err=" << strerror(errno)); delete m_output; m_output = 0; return false; } @@ -277,7 +280,7 @@ bool File::Open() if (m_infoFile->Open(ifn.c_str(), O_RDWR, 0600, myEnv) != XrdOssOK) { TRACEF(Error, "File::Open() Open failed for info file " << ifn - << ", err=" << strerror(errno)); + << ", err=" << strerror(errno)); delete m_infoFile; m_infoFile = 0; delete m_output; m_output = 0; return false; @@ -312,10 +315,10 @@ bool File::Open() // Read and helpers //============================================================================== -bool File::overlap(int blk, // block to query +bool File::overlap(int blk, // block to query long long blk_size, // long long req_off, // offset of user request - int req_size, // size of user request + int req_size, // size of user request // output: long long &off, // offset in user buffer long long &blk_off, // offset in block @@ -353,7 +356,7 @@ Block* File::PrepareBlockRequest(int i, bool prefetch) // Reference count is 0 so increase it in calling function if you want to // catch the block while still in memory. - const long long BS = m_cfi.GetBufferSize(); + const long long BS = m_cfi.GetBufferSize(); const int last_block = m_cfi.GetSizeInBits() - 1; long long off = i * BS; @@ -369,7 +372,7 @@ Block* File::PrepareBlockRequest(int i, bool prefetch) if (m_prefetchState == kOn && m_block_map.size() > Cache::GetInstance().RefConfiguration().m_prefetch_max_blocks) { m_prefetchState = kHold; - cache()->DeRegisterPrefetchFile(this); + cache()->DeRegisterPrefetchFile(this); } return b; @@ -394,11 +397,11 @@ int File::RequestBlocksDirect(DirectResponseHandler *handler, IntList_t& blocks, { const long long BS = m_cfi.GetBufferSize(); - // XXX Use readv to load more at the same time. + // XXX Use readv to load more at the same time. long long total = 0; - for (IntList_i ii = blocks.begin() ; ii != blocks.end(); ++ii) + for (IntList_i ii = blocks.begin(); ii != blocks.end(); ++ii) { // overlap and request long long off; // offset in user buffer @@ -409,7 +412,7 @@ int File::RequestBlocksDirect(DirectResponseHandler *handler, IntList_t& blocks, m_io->GetInput()->Read( *handler, req_buf + off, *ii * BS + blk_off, size); TRACEF(Dump, "RequestBlockDirect success, idx = " << *ii << " size = " << size); - + total += size; } @@ -428,7 +431,7 @@ int File::ReadBlocksFromDisk(std::list& blocks, // XXX Coalesce adjacent reads. - for (IntList_i ii = blocks.begin() ; ii != blocks.end(); ++ii) + for (IntList_i ii = blocks.begin(); ii != blocks.end(); ++ii) { // overlap and read long long off; // offset in user buffer @@ -454,7 +457,7 @@ int File::ReadBlocksFromDisk(std::list& blocks, } total += rs; - } + } m_stats.m_BytesDisk += total; return total; @@ -481,7 +484,7 @@ int File::Read(char* iUserBuff, long long iUserOff, int iUserSize) // unlock BlockList_t blks; - bool preProcOK = true; + bool preProcOK = true; m_downloadCond.Lock(); @@ -491,12 +494,12 @@ int File::Read(char* iUserBuff, long long iUserOff, int iUserSize) const int idx_last = (iUserOff + iUserSize - 1) / BS; BlockList_t blks_to_request, blks_to_process, blks_processed; - IntList_t blks_on_disk, blks_direct; + IntList_t blks_on_disk, blks_direct; for (int block_idx = idx_first; block_idx <= idx_last; ++block_idx) { TRACEF(Dump, "File::Read() idx " << block_idx); - BlockMap_i bi = m_block_map.find(block_idx); + BlockMap_i bi = m_block_map.find(block_idx); // In RAM or incoming? if (bi != m_block_map.end()) @@ -538,7 +541,7 @@ int File::Read(char* iUserBuff, long long iUserOff, int iUserSize) TRACEF(Dump, "File::Read() direct block " << block_idx); blks_direct.push_back(block_idx); } - } + } } m_downloadCond.UnLock(); @@ -557,7 +560,7 @@ int File::Read(char* iUserBuff, long long iUserOff, int iUserSize) // First, send out any direct requests. // XXX Could send them all out in a single vector read. DirectResponseHandler *direct_handler = 0; - int direct_size = 0; + int direct_size = 0; if ( ! blks_direct.empty()) { @@ -565,7 +568,8 @@ int File::Read(char* iUserBuff, long long iUserOff, int iUserSize) direct_size = RequestBlocksDirect(direct_handler, blks_direct, iUserBuff, iUserOff, iUserSize); // failed to send direct client request - if (direct_size < 0) { + if (direct_size < 0) + { for (BlockList_i i = blks_to_process.begin(); i!= blks_to_process.end(); ++i ) dec_ref_count(*i); delete direct_handler; @@ -646,9 +650,9 @@ int File::Read(char* iUserBuff, long long iUserOff, int iUserSize) else // it has failed ... krap up. { bytes_read = -1; - errno = - (*bi)->m_errno; + errno = -(*bi)->m_errno; TRACEF(Error, "File::Read(), block "<< (*bi)->m_offset/BS << " finished with error " - << errno << " " << strerror(errno)); + << errno << " " << strerror(errno)); break; } ++bi; @@ -676,7 +680,7 @@ int File::Read(char* iUserBuff, long long iUserOff, int iUserSize) } else { - errno = - direct_handler->m_errno; + errno = -direct_handler->m_errno; bytes_read = -1; } @@ -688,7 +692,7 @@ int File::Read(char* iUserBuff, long long iUserOff, int iUserSize) { XrdSysCondVarHelper _lck(m_downloadCond); - // AMT what is stamp block ??? + // AMT what is stamp block ??? // blks_to_process can be non-empty, if we're exiting with an error. std::copy(blks_to_process.begin(), blks_to_process.end(), std::back_inserter(blks_processed)); @@ -702,7 +706,8 @@ int File::Read(char* iUserBuff, long long iUserOff, int iUserSize) // update prefetch score m_prefetchHitCnt += prefetchHitsRam; - for (IntList_i d = blks_on_disk.begin(); d != blks_on_disk.end(); ++d) { + for (IntList_i d = blks_on_disk.begin(); d != blks_on_disk.end(); ++d) + { if (m_cfi.TestPrefetchBit(offsetIdx(*d))) m_prefetchHitCnt++; } @@ -747,7 +752,7 @@ void File::WriteBlockToDisk(Block* b) TRACEF(Dump, "File::WriteToDisk() success set bit for block " << b->m_offset << " size " << size); int pfIdx = (b->m_offset - m_offset)/m_cfi.GetBufferSize(); - bool schedule_sync = false; + bool schedule_sync = false; { XrdSysCondVarHelper _lck(m_downloadCond); @@ -847,7 +852,7 @@ void File::free_block(Block* b) if (m_prefetchState == kHold && m_block_map.size() < Cache::GetInstance().RefConfiguration().m_prefetch_max_blocks) { m_prefetchState = kOn; - cache()->RegisterPrefetchFile(this); + cache()->RegisterPrefetchFile(this); } } @@ -858,7 +863,7 @@ void File::ProcessBlockResponse(Block* b, int res) m_downloadCond.Lock(); TRACEF(Dump, "File::ProcessBlockResponse " << (void*)b << " " << b->m_offset/BufferSize()); - if (res >= 0) + if (res >= 0) { b->m_downloaded = true; TRACEF(Dump, "File::ProcessBlockResponse inc_ref_count " << (int)(b->m_offset/BufferSize())); @@ -914,27 +919,28 @@ void File::Prefetch() TRACEF(Dump, "File::Prefetch enter to check download status"); { - XrdSysCondVarHelper _lck(m_downloadCond); + XrdSysCondVarHelper _lck(m_downloadCond); - if (m_prefetchState != kOn) + if (m_prefetchState != kOn) return; - for (int f = 0; f < m_cfi.GetSizeInBits(); ++f) - { - if ( ! m_cfi.TestBit(f)) - { - f += m_offset/m_cfi.GetBufferSize(); - BlockMap_i bi = m_block_map.find(f); - if (bi == m_block_map.end()) { - TRACEF(Dump, "File::Prefetch take block " << f); - cache()->RequestRAMBlock(); - blks.push_back( PrepareBlockRequest(f, true) ); - m_prefetchReadCnt++; - m_prefetchScore = float(m_prefetchHitCnt)/m_prefetchReadCnt; - break; - } - } - } + for (int f = 0; f < m_cfi.GetSizeInBits(); ++f) + { + if ( ! m_cfi.TestBit(f)) + { + f += m_offset/m_cfi.GetBufferSize(); + BlockMap_i bi = m_block_map.find(f); + if (bi == m_block_map.end()) + { + TRACEF(Dump, "File::Prefetch take block " << f); + cache()->RequestRAMBlock(); + blks.push_back( PrepareBlockRequest(f, true) ); + m_prefetchReadCnt++; + m_prefetchScore = float(m_prefetchHitCnt)/m_prefetchReadCnt; + break; + } + } + } } @@ -943,12 +949,12 @@ void File::Prefetch() ProcessBlockRequests(blks); } else - { + { TRACEF(Dump, "File::Prefetch no free block found "); m_downloadCond.Lock(); m_prefetchState = kComplete; m_downloadCond.UnLock(); - cache()->DeRegisterPrefetchFile(this); + cache()->DeRegisterPrefetchFile(this); } } @@ -993,4 +999,4 @@ void DirectResponseHandler::Done(int res) { m_cond.Signal(); } -} +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheFile.hh b/src/XrdFileCache/XrdFileCacheFile.hh index 16a80e66546..5e57b9eb307 100644 --- a/src/XrdFileCache/XrdFileCacheFile.hh +++ b/src/XrdFileCache/XrdFileCacheFile.hh @@ -35,238 +35,238 @@ class XrdOucIOVec; namespace XrdCl { - class Log; +class Log; } namespace XrdFileCache { - class BlockResponseHandler; - class DirectResponseHandler; - class IO; - - struct ReadVBlockListRAM; - struct ReadVChunkListRAM; - struct ReadVBlockListDisk; - struct ReadVChunkListDisk; +class BlockResponseHandler; +class DirectResponseHandler; +class IO; + +struct ReadVBlockListRAM; +struct ReadVChunkListRAM; +struct ReadVBlockListDisk; +struct ReadVChunkListDisk; } namespace XrdFileCache { - class File; +class File; - class Block +class Block +{ +public: + std::vector m_buff; + long long m_offset; + File *m_file; + bool m_prefetch; + int m_refcnt; + int m_errno; // stores negative errno + bool m_downloaded; + + Block(File *f, long long off, int size, bool m_prefetch) : + m_offset(off), m_file(f), m_prefetch(m_prefetch), m_refcnt(0), + m_errno(0), m_downloaded(false) { - public: - std::vector m_buff; - long long m_offset; - File *m_file; - bool m_prefetch; - int m_refcnt; - int m_errno; // stores negative errno - bool m_downloaded; - - Block(File *f, long long off, int size, bool m_prefetch) : - m_offset(off), m_file(f), m_prefetch(m_prefetch), m_refcnt(0), - m_errno(0), m_downloaded(false) - { - m_buff.resize(size); - } - - char* get_buff(long long pos = 0) { return &m_buff[pos]; } - int get_size() { return (int) m_buff.size(); } - long long get_offset() { return m_offset; } - - bool is_finished() { return m_downloaded || m_errno != 0; } - bool is_ok() { return m_downloaded; } - bool is_failed() { return m_errno != 0; } - - void set_error_and_free(int err) - { - m_errno = err; - std::vector x; - m_buff.swap(x); - } - }; - - - class File + m_buff.resize(size); + } + + char* get_buff(long long pos = 0) { return &m_buff[pos]; } + int get_size() { return (int) m_buff.size(); } + long long get_offset() { return m_offset; } + + bool is_finished() { return m_downloaded || m_errno != 0; } + bool is_ok() { return m_downloaded; } + bool is_failed() { return m_errno != 0; } + + void set_error_and_free(int err) { - private: - enum PrefetchState_e { kOff=-1, kOn, kHold, kStopped, kComplete }; + m_errno = err; + std::vector x; + m_buff.swap(x); + } +}; - bool m_is_open; //!< open state - IO *m_io; //!< original data source - XrdOssDF *m_output; //!< file handle for data file on disk - XrdOssDF *m_infoFile; //!< file handle for data-info file on disk - Info m_cfi; //!< download status of file blocks and access statistics +class File +{ +private: + enum PrefetchState_e { kOff=-1, kOn, kHold, kStopped, kComplete }; - std::string m_temp_filename; //!< filename of data file on disk - long long m_offset; //!< offset of cached file for block-based operation - long long m_fileSize; //!< size of cached disk file for block-based operation + bool m_is_open; //!< open state - // fsync - XrdJob *m_syncer; - std::vector m_writes_during_sync; - int m_non_flushed_cnt; - bool m_in_sync; + IO *m_io; //!< original data source + XrdOssDF *m_output; //!< file handle for data file on disk + XrdOssDF *m_infoFile; //!< file handle for data-info file on disk + Info m_cfi; //!< download status of file blocks and access statistics - typedef std::list IntList_t; - typedef IntList_t::iterator IntList_i; + std::string m_temp_filename; //!< filename of data file on disk + long long m_offset; //!< offset of cached file for block-based operation + long long m_fileSize; //!< size of cached disk file for block-based operation - typedef std::list BlockList_t; - typedef BlockList_t::iterator BlockList_i; + // fsync + XrdJob *m_syncer; + std::vector m_writes_during_sync; + int m_non_flushed_cnt; + bool m_in_sync; - typedef std::map BlockMap_t; - typedef BlockMap_t::iterator BlockMap_i; + typedef std::list IntList_t; + typedef IntList_t::iterator IntList_i; + typedef std::list BlockList_t; + typedef BlockList_t::iterator BlockList_i; - BlockMap_t m_block_map; + typedef std::map BlockMap_t; + typedef BlockMap_t::iterator BlockMap_i; - XrdSysCondVar m_downloadCond; - Stats m_stats; //!< cache statistics, used in IO detach + BlockMap_t m_block_map; - PrefetchState_e m_prefetchState; + XrdSysCondVar m_downloadCond; - int m_prefetchReadCnt; - int m_prefetchHitCnt; - float m_prefetchScore; //cached - bool m_detachTimeIsLogged; + Stats m_stats; //!< cache statistics, used in IO detach - static const char *m_traceID; + PrefetchState_e m_prefetchState; - public: - //------------------------------------------------------------------------ - //! Constructor. - //------------------------------------------------------------------------ - File(IO *io, std::string &path, - long long offset, long long fileSize); + int m_prefetchReadCnt; + int m_prefetchHitCnt; + float m_prefetchScore; //cached + bool m_detachTimeIsLogged; - //------------------------------------------------------------------------ - //! Destructor. - //------------------------------------------------------------------------ - ~File(); + static const char *m_traceID; - void BlockRemovedFromWriteQ(Block*); - //! Open file handle for data file and info file on local disk. - bool Open(); +public: + //------------------------------------------------------------------------ + //! Constructor. + //------------------------------------------------------------------------ + File(IO *io, std::string &path, + long long offset, long long fileSize); - //! Vector read from disk if block is already downloaded, else ReadV from client. - int ReadV (const XrdOucIOVec *readV, int n); + //------------------------------------------------------------------------ + //! Destructor. + //------------------------------------------------------------------------ + ~File(); - int Read(char* buff, long long offset, int size); + void BlockRemovedFromWriteQ(Block*); + //! Open file handle for data file and info file on local disk. + bool Open(); - //---------------------------------------------------------------------- - //! \brief Data and cinfo files are open. - //---------------------------------------------------------------------- - bool isOpen() const { return m_is_open; } + //! Vector read from disk if block is already downloaded, else ReadV from client. + int ReadV (const XrdOucIOVec *readV, int n); - //---------------------------------------------------------------------- - //! \brief Initiate close. Return true if still IO active. - //! Used in XrdPosixXrootd::Close() - //---------------------------------------------------------------------- - bool ioActive(); + int Read(char* buff, long long offset, int size); - //---------------------------------------------------------------------- - //! Sync file cache inf o and output data with disk - //---------------------------------------------------------------------- - void Sync(); + //---------------------------------------------------------------------- + //! \brief Data and cinfo files are open. + //---------------------------------------------------------------------- + bool isOpen() const { return m_is_open; } - //---------------------------------------------------------------------- - //! Reference to prefetch statistics. - //---------------------------------------------------------------------- - Stats& GetStats() { return m_stats; } + //---------------------------------------------------------------------- + //! \brief Initiate close. Return true if still IO active. + //! Used in XrdPosixXrootd::Close() + //---------------------------------------------------------------------- + bool ioActive(); - void ProcessBlockResponse(Block* b, int res); - void WriteBlockToDisk(Block* b); + //---------------------------------------------------------------------- + //! Sync file cache inf o and output data with disk + //---------------------------------------------------------------------- + void Sync(); - void Prefetch(); + //---------------------------------------------------------------------- + //! Reference to prefetch statistics. + //---------------------------------------------------------------------- + Stats& GetStats() { return m_stats; } - float GetPrefetchScore() const; + void ProcessBlockResponse(Block* b, int res); + void WriteBlockToDisk(Block* b); - //! Log path - const char* lPath() const; + void Prefetch(); - std::string GetLocalPath() { return m_temp_filename; } + float GetPrefetchScore() const; - XrdOucTrace* GetTrace(); + //! Log path + const char* lPath() const; - long long GetFileSize() { return m_fileSize;} + std::string GetLocalPath() { return m_temp_filename; } - void WakeUp(IO* io); + XrdOucTrace* GetTrace(); - private: - bool overlap(int blk, // block to query - long long blk_size, // - long long req_off, // offset of user request - int req_size, // size of user request - // output: - long long &off, // offset in user buffer - long long &blk_off, // offset in block - long long &size); - // Read - Block* PrepareBlockRequest(int i, bool prefetch); - void ProcessBlockRequests(BlockList_t& blks); + long long GetFileSize() { return m_fileSize; } - int RequestBlocksDirect(DirectResponseHandler *handler, IntList_t& blocks, - char* buff, long long req_off, long long req_size); + void WakeUp(IO* io); - int ReadBlocksFromDisk(IntList_t& blocks, - char* req_buf, long long req_off, long long req_size); +private: + bool overlap(int blk, // block to query + long long blk_size, // + long long req_off, // offset of user request + int req_size, // size of user request + // output: + long long &off, // offset in user buffer + long long &blk_off, // offset in block + long long &size); + // Read + Block* PrepareBlockRequest(int i, bool prefetch); + void ProcessBlockRequests(BlockList_t& blks); - // VRead - bool VReadValidate (const XrdOucIOVec *readV, int n); - bool VReadPreProcess (const XrdOucIOVec *readV, int n, - ReadVBlockListRAM& blks_to_process, - ReadVBlockListDisk& blks_on_disk, - std::vector& chunkVec); - int VReadFromDisk (const XrdOucIOVec *readV, int n, - ReadVBlockListDisk& blks_on_disk); - int VReadProcessBlocks(const XrdOucIOVec *readV, int n, - std::vector& blks_to_process, - std::vector& blks_rocessed); + int RequestBlocksDirect(DirectResponseHandler *handler, IntList_t& blocks, + char* buff, long long req_off, long long req_size); - long long BufferSize(); - void AppendIOStatToFileInfo(); - - void inc_ref_count(Block*); - void dec_ref_count(Block*); - void free_block(Block*); - - int offsetIdx(int idx); - }; - - - // ================================================================ + int ReadBlocksFromDisk(IntList_t& blocks, + char* req_buf, long long req_off, long long req_size); - class BlockResponseHandler : public XrdOucCacheIOCB - { - public: - Block *m_block; + // VRead + bool VReadValidate (const XrdOucIOVec *readV, int n); + bool VReadPreProcess (const XrdOucIOVec *readV, int n, + ReadVBlockListRAM& blks_to_process, + ReadVBlockListDisk& blks_on_disk, + std::vector& chunkVec); + int VReadFromDisk (const XrdOucIOVec *readV, int n, + ReadVBlockListDisk& blks_on_disk); + int VReadProcessBlocks(const XrdOucIOVec *readV, int n, + std::vector& blks_to_process, + std::vector& blks_rocessed); - BlockResponseHandler(Block *b) : m_block(b) {} + long long BufferSize(); + void AppendIOStatToFileInfo(); - virtual void Done(int result); - }; + void inc_ref_count(Block*); + void dec_ref_count(Block*); + void free_block(Block*); - class DirectResponseHandler : public XrdOucCacheIOCB - { - public: - XrdSysCondVar m_cond; - int m_to_wait; - int m_errno; + int offsetIdx(int idx); +}; + + +// ================================================================ + +class BlockResponseHandler : public XrdOucCacheIOCB +{ +public: + Block *m_block; + + BlockResponseHandler(Block *b) : m_block(b) {} + + virtual void Done(int result); +}; + +class DirectResponseHandler : public XrdOucCacheIOCB +{ +public: + XrdSysCondVar m_cond; + int m_to_wait; + int m_errno; - DirectResponseHandler(int to_wait) : m_cond(0), m_to_wait(to_wait), m_errno(0) {} + DirectResponseHandler(int to_wait) : m_cond(0), m_to_wait(to_wait), m_errno(0) {} - bool is_finished() { XrdSysCondVarHelper _lck(m_cond); return m_to_wait == 0; } - bool is_ok() { XrdSysCondVarHelper _lck(m_cond); return m_to_wait == 0 && m_errno == 0; } - bool is_failed() { XrdSysCondVarHelper _lck(m_cond); return m_errno != 0; } + bool is_finished() { XrdSysCondVarHelper _lck(m_cond); return m_to_wait == 0; } + bool is_ok() { XrdSysCondVarHelper _lck(m_cond); return m_to_wait == 0 && m_errno == 0; } + bool is_failed() { XrdSysCondVarHelper _lck(m_cond); return m_errno != 0; } - virtual void Done(int result); - }; + virtual void Done(int result); +}; } -#endif +#endif \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheIO.cc b/src/XrdFileCache/XrdFileCacheIO.cc index d1678f718ab..2da353d1cff 100644 --- a/src/XrdFileCache/XrdFileCacheIO.cc +++ b/src/XrdFileCache/XrdFileCacheIO.cc @@ -4,28 +4,28 @@ using namespace XrdFileCache; -IO::IO(XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache &cache): -m_statsGlobal(stats), m_cache(cache), m_traceID("IO"), m_io(io) +IO::IO(XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache &cache) : + m_statsGlobal(stats), m_cache(cache), m_traceID("IO"), m_io(io) { - m_path = m_io->Path(); + m_path = m_io->Path(); } void IO::Update(XrdOucCacheIO2 &iocp) { - SetInput(&iocp); - TRACE_PC(Info, const char* loc = m_io->Location(), - "IO::Update() " << Path() << " location: " << - ((loc && loc[0] != 0) ? loc : "")); + SetInput(&iocp); + TRACE_PC(Info, const char* loc = m_io->Location(), + "IO::Update() " << Path() << " location: " << + ((loc && loc[0] != 0) ? loc : "")); } void IO::SetInput(XrdOucCacheIO2* x) { - XrdSysMutexHelper lock(&updMutex); - m_io = x; + XrdSysMutexHelper lock(&updMutex); + m_io = x; } XrdOucCacheIO2* IO::GetInput() { - XrdSysMutexHelper lock(&updMutex); - return m_io; -} + XrdSysMutexHelper lock(&updMutex); + return m_io; +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheIO.hh b/src/XrdFileCache/XrdFileCacheIO.hh index 15e21624065..6fdbc1559a5 100644 --- a/src/XrdFileCache/XrdFileCacheIO.hh +++ b/src/XrdFileCache/XrdFileCacheIO.hh @@ -10,48 +10,48 @@ class XrdOucTrace; namespace XrdFileCache { - //---------------------------------------------------------------------------- - //! Base cache-io class that implements XrdOucCacheIO abstract methods. - //---------------------------------------------------------------------------- - class IO : public XrdOucCacheIO2 - { - public: - IO (XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache &cache); +//---------------------------------------------------------------------------- +//! Base cache-io class that implements XrdOucCacheIO abstract methods. +//---------------------------------------------------------------------------- +class IO : public XrdOucCacheIO2 +{ +public: + IO (XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache &cache); + + //! Original data source. + virtual XrdOucCacheIO *Base() { return m_io; } + + //! Original data source URL. + virtual const char *Path() { return m_io->Path(); } - //! Original data source. - virtual XrdOucCacheIO *Base() { return m_io; } + virtual int Sync() { return 0; } - //! Original data source URL. - virtual const char *Path() { return m_io->Path(); } + virtual int Trunc(long long Offset) { errno = ENOTSUP; return -1; } - virtual int Sync() { return 0; } + virtual int Write(char *Buffer, long long Offset, int Length) + { errno = ENOTSUP; return -1; } - virtual int Trunc(long long Offset) { errno = ENOTSUP; return -1; } + virtual void Update(XrdOucCacheIO2 &iocp); - virtual int Write(char *Buffer, long long Offset, int Length) - { errno = ENOTSUP; return -1; } + virtual void RelinquishFile(File*) = 0; - virtual void Update(XrdOucCacheIO2 &iocp); + XrdOucTrace* GetTrace() {return m_cache.GetTrace(); } - virtual void RelinquishFile(File*) = 0; + XrdOucCacheIO2* GetInput(); - XrdOucTrace* GetTrace() {return m_cache.GetTrace();} - - XrdOucCacheIO2* GetInput(); +protected: + XrdOucCacheStats &m_statsGlobal; //!< reference to Cache statistics + Cache &m_cache; //!< reference to Cache needed in detach - protected: - XrdOucCacheStats &m_statsGlobal; //!< reference to Cache statistics - Cache &m_cache; //!< reference to Cache needed in detach - - const char* m_traceID; - std::string m_path; - const char* GetPath() { return m_path.c_str(); } + const char* m_traceID; + std::string m_path; + const char* GetPath() { return m_path.c_str(); } - private: - XrdOucCacheIO2 *m_io; //!< original data source - XrdSysMutex updMutex; - void SetInput(XrdOucCacheIO2*); - }; +private: + XrdOucCacheIO2 *m_io; //!< original data source + XrdSysMutex updMutex; + void SetInput(XrdOucCacheIO2*); +}; } -#endif +#endif \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheIOEntireFile.cc b/src/XrdFileCache/XrdFileCacheIOEntireFile.cc index 86bc7ebff84..4575f0fc262 100644 --- a/src/XrdFileCache/XrdFileCacheIOEntireFile.cc +++ b/src/XrdFileCache/XrdFileCacheIOEntireFile.cc @@ -35,173 +35,176 @@ using namespace XrdFileCache; IOEntireFile::IOEntireFile(XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache & cache) - : IO(io, stats, cache), - m_file(0), - m_localStat(0) + : IO(io, stats, cache), + m_file(0), + m_localStat(0) { - XrdCl::URL url(GetInput()->Path()); - std::string fname = url.GetPath(); + XrdCl::URL url(GetInput()->Path()); + std::string fname = url.GetPath(); - m_file = Cache::GetInstance().GetFileWithLocalPath(fname, this); - if (!m_file) - { - struct stat st; - int res = Fstat(st); + m_file = Cache::GetInstance().GetFileWithLocalPath(fname, this); + if (! m_file) + { + struct stat st; + int res = Fstat(st); - // This should not happen, but make a printout to see it. - if (res) - TRACEIO(Error, "IOEntireFile::IOEntireFile, could not get valid stat"); + // This should not happen, but make a printout to see it. + if (res) + TRACEIO(Error, "IOEntireFile::IOEntireFile, could not get valid stat"); - m_file = new File(this, fname, 0, st.st_size); - } + m_file = new File(this, fname, 0, st.st_size); + } - Cache::GetInstance().AddActive(m_file); + Cache::GetInstance().AddActive(m_file); } IOEntireFile::~IOEntireFile() { - TRACEIO(Debug, "IOEntireFile::~IOEntireFile() "); - delete m_localStat; + TRACEIO(Debug, "IOEntireFile::~IOEntireFile() "); + delete m_localStat; } int IOEntireFile::Fstat(struct stat &sbuff) { - XrdCl::URL url(GetPath()); - std::string name = url.GetPath(); - name += Info::m_infoExtension; - - int res = 0; - if( ! m_localStat) - { - res = initCachedStat(name.c_str()); - if (res) return res; - } - - memcpy(&sbuff, m_localStat, sizeof(struct stat)); - return 0; + XrdCl::URL url(GetPath()); + std::string name = url.GetPath(); + name += Info::m_infoExtension; + + int res = 0; + if( ! m_localStat) + { + res = initCachedStat(name.c_str()); + if (res) return res; + } + + memcpy(&sbuff, m_localStat, sizeof(struct stat)); + return 0; } long long IOEntireFile::FSize() { - return m_file->GetFileSize(); + return m_file->GetFileSize(); } void IOEntireFile::RelinquishFile(File* f) { - TRACEIO(Info, "IOEntireFile::RelinquishFile"); - assert(m_file == f); - m_file = 0; + TRACEIO(Info, "IOEntireFile::RelinquishFile"); + assert(m_file == f); + m_file = 0; } int IOEntireFile::initCachedStat(const char* path) { - // Called indirectly from the constructor. - - int res = -1; - struct stat tmpStat; - - if (m_cache.GetOss()->Stat(path, &tmpStat) == XrdOssOK) - { - XrdOssDF* infoFile = m_cache.GetOss()->newFile(Cache::GetInstance().RefConfiguration().m_username.c_str()); - XrdOucEnv myEnv; - if (infoFile->Open(path, O_RDONLY, 0600, myEnv) == XrdOssOK) - { - Info info(m_cache.GetTrace()); - if (info.Read(infoFile, path)) - { - tmpStat.st_size = info.GetFileSize(); - TRACEIO(Info, "IOEntireFile::initCachedStat successfuly read size from info file = " << tmpStat.st_size); - res = 0; - } - else - { - // file exist but can't read it - TRACEIO(Error, "IOEntireFile::initCachedStat failed to read file size from info file"); - } - } - else - { - TRACEIO(Error, "IOEntireFile::initCachedStat can't open info file " << strerror(errno)); - } - infoFile->Close(); - delete infoFile; - } - - if (res) - { - res = GetInput()->Fstat(tmpStat); - TRACEIO(Debug, "IOEntireFile::initCachedStat get stat from client res= " << res << "size = " << tmpStat.st_size); - } - - if (res == 0) - { - m_localStat = new struct stat; - memcpy(m_localStat, &tmpStat, sizeof(struct stat)); - } - return res; + // Called indirectly from the constructor. + + int res = -1; + struct stat tmpStat; + + if (m_cache.GetOss()->Stat(path, &tmpStat) == XrdOssOK) + { + XrdOssDF* infoFile = m_cache.GetOss()->newFile(Cache::GetInstance().RefConfiguration().m_username.c_str()); + XrdOucEnv myEnv; + if (infoFile->Open(path, O_RDONLY, 0600, myEnv) == XrdOssOK) + { + Info info(m_cache.GetTrace()); + if (info.Read(infoFile, path)) + { + tmpStat.st_size = info.GetFileSize(); + TRACEIO(Info, "IOEntireFile::initCachedStat successfuly read size from info file = " << tmpStat.st_size); + res = 0; + } + else + { + // file exist but can't read it + TRACEIO(Error, "IOEntireFile::initCachedStat failed to read file size from info file"); + } + } + else + { + TRACEIO(Error, "IOEntireFile::initCachedStat can't open info file " << strerror(errno)); + } + infoFile->Close(); + delete infoFile; + } + + if (res) + { + res = GetInput()->Fstat(tmpStat); + TRACEIO(Debug, "IOEntireFile::initCachedStat get stat from client res= " << res << "size = " << tmpStat.st_size); + } + + if (res == 0) + { + m_localStat = new struct stat; + memcpy(m_localStat, &tmpStat, sizeof(struct stat)); + } + return res; } bool IOEntireFile::ioActive() { - if ( ! m_file) { - return false; - } - else { - bool active = m_file->ioActive(); - if (!active && m_file) { - TRACEIO(Debug, "IOEntireFile::ioActive() detaching file"); - m_cache.Detach(m_file); - m_file = 0; - } - return active; - } + if ( ! m_file) + { + return false; + } + else + { + bool active = m_file->ioActive(); + if (! active && m_file) + { + TRACEIO(Debug, "IOEntireFile::ioActive() detaching file"); + m_cache.Detach(m_file); + m_file = 0; + } + return active; + } } XrdOucCacheIO *IOEntireFile::Detach() { - TRACEIO(Debug, "IOEntireFile::Detach() "); + TRACEIO(Debug, "IOEntireFile::Detach() "); - XrdOucCacheIO * io = GetInput(); + XrdOucCacheIO * io = GetInput(); - delete this; - return io; + delete this; + return io; } int IOEntireFile::Read (char *buff, long long off, int size) { - TRACEIO(Dump, "IOEntireFile::Read() "<< this << " off: " << off << " size: " << size ); - - // protect from reads over the file size - if (off >= FSize()) - return 0; - if (off < 0) - { - errno = EINVAL; - return -1; - } - if (off + size > FSize()) - size = FSize() - off; - - - ssize_t bytes_read = 0; - ssize_t retval = 0; - - retval = m_file->Read(buff, off, size); - if (retval >= 0) - { - bytes_read += retval; - buff += retval; - size -= retval; - - if (size > 0) - TRACEIO(Warning, "IOEntireFile::Read() bytes missed " << size ); - } - else - { - TRACEIO(Warning, "IOEntireFile::Read() pass to origin bytes ret " << retval ); - } - - return (retval < 0) ? retval : bytes_read; + TRACEIO(Dump, "IOEntireFile::Read() "<< this << " off: " << off << " size: " << size ); + + // protect from reads over the file size + if (off >= FSize()) + return 0; + if (off < 0) + { + errno = EINVAL; + return -1; + } + if (off + size > FSize()) + size = FSize() - off; + + + ssize_t bytes_read = 0; + ssize_t retval = 0; + + retval = m_file->Read(buff, off, size); + if (retval >= 0) + { + bytes_read += retval; + buff += retval; + size -= retval; + + if (size > 0) + TRACEIO(Warning, "IOEntireFile::Read() bytes missed " << size ); + } + else + { + TRACEIO(Warning, "IOEntireFile::Read() pass to origin bytes ret " << retval ); + } + + return (retval < 0) ? retval : bytes_read; } @@ -210,6 +213,6 @@ int IOEntireFile::Read (char *buff, long long off, int size) */ int IOEntireFile::ReadV (const XrdOucIOVec *readV, int n) { - TRACEIO(Dump, "IO::ReadV(), get " << n << " requests" ); - return m_file->ReadV(readV, n); -} + TRACEIO(Dump, "IO::ReadV(), get " << n << " requests" ); + return m_file->ReadV(readV, n); +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheIOEntireFile.hh b/src/XrdFileCache/XrdFileCacheIOEntireFile.hh index 132281efcd3..43154e8ef8c 100644 --- a/src/XrdFileCache/XrdFileCacheIOEntireFile.hh +++ b/src/XrdFileCache/XrdFileCacheIOEntireFile.hh @@ -33,66 +33,66 @@ class XrdOucIOVec; namespace XrdFileCache { - //---------------------------------------------------------------------------- - //! \brief Downloads original file into a single file on local disk. - //! Handles read requests as they come along. - //---------------------------------------------------------------------------- - class IOEntireFile : public IO - { - public: - //------------------------------------------------------------------------ - //! Constructor - //------------------------------------------------------------------------ - IOEntireFile(XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache &cache); +//---------------------------------------------------------------------------- +//! \brief Downloads original file into a single file on local disk. +//! Handles read requests as they come along. +//---------------------------------------------------------------------------- +class IOEntireFile : public IO +{ +public: + //------------------------------------------------------------------------ + //! Constructor + //------------------------------------------------------------------------ + IOEntireFile(XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache &cache); + + //------------------------------------------------------------------------ + //! Destructor + //------------------------------------------------------------------------ + ~IOEntireFile(); - //------------------------------------------------------------------------ - //! Destructor - //------------------------------------------------------------------------ - ~IOEntireFile(); + //--------------------------------------------------------------------- + //! Pass Read request to the corresponding File object. + //! + //! @param Buffer + //! @param Offset + //! @param Length + //! + //! @return number of bytes read + //--------------------------------------------------------------------- + virtual int Read(char *Buffer, long long Offset, int Length); - //--------------------------------------------------------------------- - //! Pass Read request to the corresponding File object. - //! - //! @param Buffer - //! @param Offset - //! @param Length - //! - //! @return number of bytes read - //--------------------------------------------------------------------- - virtual int Read(char *Buffer, long long Offset, int Length); + //--------------------------------------------------------------------- + //! Pass ReadV request to the corresponding File object. + //! + //! @param readV + //! @param n number of XrdOucIOVecs + //! + //! @return total bytes read + //--------------------------------------------------------------------- + virtual int ReadV(const XrdOucIOVec *readV, int n); - //--------------------------------------------------------------------- - //! Pass ReadV request to the corresponding File object. - //! - //! @param readV - //! @param n number of XrdOucIOVecs - //! - //! @return total bytes read - //--------------------------------------------------------------------- - virtual int ReadV(const XrdOucIOVec *readV, int n); + //--------------------------------------------------------------------- + //! Detach itself from Cache. Note: this will delete the object. + //! + //! @return original source \ref XrdPosixFile + //--------------------------------------------------------------------- + virtual XrdOucCacheIO* Detach(); - //--------------------------------------------------------------------- - //! Detach itself from Cache. Note: this will delete the object. - //! - //! @return original source \ref XrdPosixFile - //--------------------------------------------------------------------- - virtual XrdOucCacheIO* Detach(); + //! \brief Virtual method of XrdOucCacheIO. + //! Called to check if destruction needs to be done in a separate task. + virtual bool ioActive(); - //! \brief Virtual method of XrdOucCacheIO. - //! Called to check if destruction needs to be done in a separate task. - virtual bool ioActive(); + virtual int Fstat(struct stat &sbuff); - virtual int Fstat(struct stat &sbuff); - - virtual long long FSize(); + virtual long long FSize(); - virtual void RelinquishFile(File*); + virtual void RelinquishFile(File*); - private: - File* m_file; - struct stat *m_localStat; - int initCachedStat(const char* path); - }; +private: + File* m_file; + struct stat *m_localStat; + int initCachedStat(const char* path); +}; } -#endif +#endif \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheIOFileBlock.cc b/src/XrdFileCache/XrdFileCacheIOFileBlock.cc index 27ed597510d..19ce622e8a6 100644 --- a/src/XrdFileCache/XrdFileCacheIOFileBlock.cc +++ b/src/XrdFileCache/XrdFileCacheIOFileBlock.cc @@ -37,56 +37,56 @@ using namespace XrdFileCache; //______________________________________________________________________________ IOFileBlock::IOFileBlock(XrdOucCacheIO2 *io, XrdOucCacheStats &statsGlobal, Cache & cache) - : IO(io, statsGlobal, cache), m_localStat(0), m_info(cache.GetTrace(), false), m_infoFile(0) + : IO(io, statsGlobal, cache), m_localStat(0), m_info(cache.GetTrace(), false), m_infoFile(0) { - m_blocksize = Cache::GetInstance().RefConfiguration().m_hdfsbsize; - GetBlockSizeFromPath(); - initLocalStat(); - if (m_infoFile) m_info.WriteIOStatAttach(); + m_blocksize = Cache::GetInstance().RefConfiguration().m_hdfsbsize; + GetBlockSizeFromPath(); + initLocalStat(); + if (m_infoFile) m_info.WriteIOStatAttach(); } //______________________________________________________________________________ XrdOucCacheIO* IOFileBlock::Detach() { - // this is called when this IO is no longer active - XrdOucCacheIO * io = GetInput(); - - while (!m_blocks.empty()) - { - std::map::iterator it = m_blocks.begin(); - m_cache.Detach(it->second); - m_blocks.erase(it); - } - delete this; - - return io; + // this is called when this IO is no longer active + XrdOucCacheIO * io = GetInput(); + + while (! m_blocks.empty()) + { + std::map::iterator it = m_blocks.begin(); + m_cache.Detach(it->second); + m_blocks.erase(it); + } + delete this; + + return io; } //______________________________________________________________________________ void IOFileBlock::CloseInfoFile() { - // write access statistics to info file and close it - // detach time is needed for file purge - if (m_infoFile) - { - if (m_info.GetFileSize() > 0) - { - Stats as; - m_info.WriteIOStatDetach(as); - } - m_infoFile->Fsync(); - m_infoFile->Close(); - - delete m_infoFile; - m_infoFile = 0; - } + // write access statistics to info file and close it + // detach time is needed for file purge + if (m_infoFile) + { + if (m_info.GetFileSize() > 0) + { + Stats as; + m_info.WriteIOStatDetach(as); + } + m_infoFile->Fsync(); + m_infoFile->Close(); + + delete m_infoFile; + m_infoFile = 0; + } } //______________________________________________________________________________ void IOFileBlock::GetBlockSizeFromPath() { const static std::string tag = "hdfsbsize="; - std::string path= GetInput()->Path(); + std::string path = GetInput()->Path(); size_t pos1 = path.find(tag); size_t t = tag.length(); if ( pos1 != path.npos) @@ -98,9 +98,10 @@ void IOFileBlock::GetBlockSizeFromPath() std::string bs = path.substr(pos1, pos2 - pos1); m_blocksize = atoi(bs.c_str()); } - else { + else + { m_blocksize = atoi(path.substr(pos1).c_str()); - } + } TRACEIO(Debug, "FileBlock::GetBlockSizeFromPath(), blocksize = " << m_blocksize ); } @@ -109,35 +110,35 @@ void IOFileBlock::GetBlockSizeFromPath() //______________________________________________________________________________ File* IOFileBlock::newBlockFile(long long off, int blocksize) { - XrdCl::URL url(GetInput()->Path()); - std::string fname = url.GetPath(); - - std::stringstream ss; - ss << fname; - char offExt[64]; - // filename like ____ - sprintf(&offExt[0],"___%lld_%lld", m_blocksize, off ); - ss << &offExt[0]; - fname = ss.str(); - - TRACEIO(Debug, "FileBlock::FileBlock(), create XrdFileCacheFile "); - - File* file = Cache::GetInstance().GetFileWithLocalPath(fname, this); - if (!file) - { - file = new File(this, fname, off, blocksize); - Cache::GetInstance().AddActive(file); - } - - return file; + XrdCl::URL url(GetInput()->Path()); + std::string fname = url.GetPath(); + + std::stringstream ss; + ss << fname; + char offExt[64]; + // filename like ____ + sprintf(&offExt[0],"___%lld_%lld", m_blocksize, off ); + ss << &offExt[0]; + fname = ss.str(); + + TRACEIO(Debug, "FileBlock::FileBlock(), create XrdFileCacheFile "); + + File* file = Cache::GetInstance().GetFileWithLocalPath(fname, this); + if (! file) + { + file = new File(this, fname, off, blocksize); + Cache::GetInstance().AddActive(file); + } + + return file; } //______________________________________________________________________________ int IOFileBlock::Fstat(struct stat &sbuff) { - // local stat is create in constructor. if file was on disk before - // attach that the only way stat was not successful is becuse there - // were info file read errors + // local stat is create in constructor. if file was on disk before + // attach that the only way stat was not successful is becuse there + // were info file read errors if ( ! m_localStat) return -1; memcpy(&sbuff, m_localStat, sizeof(struct stat)); @@ -147,215 +148,215 @@ int IOFileBlock::Fstat(struct stat &sbuff) //______________________________________________________________________________ long long IOFileBlock::FSize() { - if ( ! m_localStat) return -1; - - return m_localStat->st_size; + if ( ! m_localStat) return -1; + + return m_localStat->st_size; } //______________________________________________________________________________ int IOFileBlock::initLocalStat() { - XrdCl::URL url(GetPath()); - std::string path = url.GetPath(); - path += ".cinfo"; - - int res = -1; - struct stat tmpStat; - XrdOucEnv myEnv; - - // try to read from existing file - if (m_cache.GetOss()->Stat(path.c_str(), &tmpStat) == XrdOssOK) - { - m_infoFile = m_cache.GetOss()->newFile(m_cache.RefConfiguration().m_username.c_str()); - if (m_infoFile->Open(path.c_str(), O_RDWR, 0600, myEnv) == XrdOssOK) - { - if (m_info.Read(m_infoFile, path)) - { - tmpStat.st_size = m_info.GetFileSize(); - TRACEIO(Info, "IOFileBlock::initCachedStat successfuly read size from existing info file = " << tmpStat.st_size); - res = 0; - } - else - { - // file exist but can't read it - TRACEIO(Error, "IOFileBlock::initCachedStat failed to read file size from info file"); - } - } - } - - // if there is no local info file, try to read from client and then save stat into a new *cinfo file - if (res) - { - if (m_infoFile) { delete m_infoFile; m_infoFile = 0; } - - res = GetInput()->Fstat(tmpStat); - TRACEIO(Debug, "IOFileBlock::initCachedStat get stat from client res= " << res << "size = " << tmpStat.st_size); - if (res == 0) - { - if (m_cache.GetOss()->Create(m_cache.RefConfiguration().m_username.c_str(), path.c_str(), 0600, myEnv, XRDOSS_mkpath) == XrdOssOK) - { - m_infoFile = m_cache.GetOss()->newFile(m_cache.RefConfiguration().m_username.c_str()); - if (m_infoFile->Open(path.c_str(), O_RDWR, 0600, myEnv) == XrdOssOK) + XrdCl::URL url(GetPath()); + std::string path = url.GetPath(); + path += ".cinfo"; + + int res = -1; + struct stat tmpStat; + XrdOucEnv myEnv; + + // try to read from existing file + if (m_cache.GetOss()->Stat(path.c_str(), &tmpStat) == XrdOssOK) + { + m_infoFile = m_cache.GetOss()->newFile(m_cache.RefConfiguration().m_username.c_str()); + if (m_infoFile->Open(path.c_str(), O_RDWR, 0600, myEnv) == XrdOssOK) + { + if (m_info.Read(m_infoFile, path)) { - // This is writing the top-level cinfo - // The info file is used to get file size on defer open - // don't initalize buffer, it does not hold useful information in this case - m_info.SetBufferSize(m_cache.RefConfiguration().m_bufferSize); - m_info.DisableDownloadStatus(); - m_info.SetFileSize(tmpStat.st_size); - m_info.Write(m_infoFile, path); - m_infoFile->Fsync(); + tmpStat.st_size = m_info.GetFileSize(); + TRACEIO(Info, "IOFileBlock::initCachedStat successfuly read size from existing info file = " << tmpStat.st_size); + res = 0; } else { - TRACEIO(Error, "IOFileBlock::initCachedStat can't open info file path"); + // file exist but can't read it + TRACEIO(Error, "IOFileBlock::initCachedStat failed to read file size from info file"); } - } - else - { - TRACEIO(Error, "IOFileBlock::initCachedStat can't create info file path"); - } - } - } - - if (res == 0) - { - m_localStat = new struct stat; - memcpy(m_localStat, &tmpStat, sizeof(struct stat)); - } - - return res; + } + } + + // if there is no local info file, try to read from client and then save stat into a new *cinfo file + if (res) + { + if (m_infoFile) { delete m_infoFile; m_infoFile = 0; } + + res = GetInput()->Fstat(tmpStat); + TRACEIO(Debug, "IOFileBlock::initCachedStat get stat from client res= " << res << "size = " << tmpStat.st_size); + if (res == 0) + { + if (m_cache.GetOss()->Create(m_cache.RefConfiguration().m_username.c_str(), path.c_str(), 0600, myEnv, XRDOSS_mkpath) == XrdOssOK) + { + m_infoFile = m_cache.GetOss()->newFile(m_cache.RefConfiguration().m_username.c_str()); + if (m_infoFile->Open(path.c_str(), O_RDWR, 0600, myEnv) == XrdOssOK) + { + // This is writing the top-level cinfo + // The info file is used to get file size on defer open + // don't initalize buffer, it does not hold useful information in this case + m_info.SetBufferSize(m_cache.RefConfiguration().m_bufferSize); + m_info.DisableDownloadStatus(); + m_info.SetFileSize(tmpStat.st_size); + m_info.Write(m_infoFile, path); + m_infoFile->Fsync(); + } + else + { + TRACEIO(Error, "IOFileBlock::initCachedStat can't open info file path"); + } + } + else + { + TRACEIO(Error, "IOFileBlock::initCachedStat can't create info file path"); + } + } + } + + if (res == 0) + { + m_localStat = new struct stat; + memcpy(m_localStat, &tmpStat, sizeof(struct stat)); + } + + return res; } //______________________________________________________________________________ void IOFileBlock::RelinquishFile(File* f) { - // called from Cache::Detach() or Cache::GetFileWithLocalPath() - // the object is in process of dying - - XrdSysMutexHelper lock(&m_mutex); - for (std::map::iterator it = m_blocks.begin(); it != m_blocks.end(); ++it) - { - if (it->second == f) - { - m_blocks.erase(it); - break; - } - } + // called from Cache::Detach() or Cache::GetFileWithLocalPath() + // the object is in process of dying + + XrdSysMutexHelper lock(&m_mutex); + for (std::map::iterator it = m_blocks.begin(); it != m_blocks.end(); ++it) + { + if (it->second == f) + { + m_blocks.erase(it); + break; + } + } } //______________________________________________________________________________ bool IOFileBlock::ioActive() { - CloseInfoFile(); + CloseInfoFile(); - XrdSysMutexHelper lock(&m_mutex); - for (std::map::iterator it = m_blocks.begin(); it != m_blocks.end(); ++it) - { - if (it->second->ioActive()) - return true; - } + XrdSysMutexHelper lock(&m_mutex); + for (std::map::iterator it = m_blocks.begin(); it != m_blocks.end(); ++it) + { + if (it->second->ioActive()) + return true; + } - return false; + return false; } //______________________________________________________________________________ int IOFileBlock::Read(char *buff, long long off, int size) { - // protect from reads over the file size - - long long fileSize = FSize(); - - if (off >= fileSize) - return 0; - if (off < 0) - { - errno = EINVAL; - return -1; - } - if (off + size > fileSize) - size = fileSize - off; - - long long off0 = off; - int idx_first = off0/m_blocksize; - int idx_last = (off0 + size - 1) / m_blocksize; - int bytes_read = 0; - TRACEIO(Dump, "IOFileBlock::Read() "<< off << "@" << size << " block range ["<< idx_first << ", " << idx_last << "]"); - - for (int blockIdx = idx_first; blockIdx <= idx_last; ++blockIdx ) - { - // locate block - File* fb; - m_mutex.Lock(); - std::map::iterator it = m_blocks.find(blockIdx); - if (it != m_blocks.end()) - { - fb = it->second; - } - else - { - size_t pbs = m_blocksize; - // check if this is last block - int lastIOFileBlock = (fileSize-1)/m_blocksize; - if (blockIdx == lastIOFileBlock ) - { - pbs = fileSize - blockIdx*m_blocksize; - // TRACEIO(Dump, "IOFileBlock::Read() last block, change output file size to " << pbs); - } - - fb = newBlockFile(blockIdx*m_blocksize, pbs); - m_blocks.insert(std::pair(blockIdx, (File*) fb)); - } - m_mutex.UnLock(); - - // edit size if read request is reaching more than a block - int readBlockSize = size; - if (idx_first != idx_last) - { - if (blockIdx == idx_first) - { - readBlockSize = (blockIdx + 1) *m_blocksize - off0; - TRACEIO(Dump, "Read partially till the end of the block"); - } - else if (blockIdx == idx_last) - { - readBlockSize = (off0+size) - blockIdx*m_blocksize; - TRACEIO(Dump, "Read partially till the end of the block %s"); - } - else - { - readBlockSize = m_blocksize; - } - } - // MT-XXXX - assert(readBlockSize); - - TRACEIO(Dump, "IOFileBlock::Read() block[ " << blockIdx << "] read-block-size[" << readBlockSize << "], offset[" << readBlockSize << "] off = " << off ); - - long long min = blockIdx * m_blocksize; - if ( off < min) { assert(0); } // MT-XXXX - // MT-XXXX - assert(off+readBlockSize <= (min + m_blocksize)); - int retvalBlock = fb->Read(buff, off, readBlockSize); - - TRACEIO(Dump, "IOFileBlock::Read() Block read returned " << retvalBlock); - if (retvalBlock == readBlockSize) - { - bytes_read += retvalBlock; - buff += retvalBlock; - off += retvalBlock; - } - else if (retvalBlock > 0) - { - TRACEIO(Warning, "IOFileBlock::Read() incomplete read, missing bytes " << readBlockSize-retvalBlock); - return bytes_read + retvalBlock; - } - else - { - TRACEIO(Error, "IOFileBlock::Read() read error, retval" << retvalBlock); - return retvalBlock; - } - } - - return bytes_read; -} + // protect from reads over the file size + + long long fileSize = FSize(); + + if (off >= fileSize) + return 0; + if (off < 0) + { + errno = EINVAL; + return -1; + } + if (off + size > fileSize) + size = fileSize - off; + + long long off0 = off; + int idx_first = off0/m_blocksize; + int idx_last = (off0 + size - 1) / m_blocksize; + int bytes_read = 0; + TRACEIO(Dump, "IOFileBlock::Read() "<< off << "@" << size << " block range ["<< idx_first << ", " << idx_last << "]"); + + for (int blockIdx = idx_first; blockIdx <= idx_last; ++blockIdx ) + { + // locate block + File* fb; + m_mutex.Lock(); + std::map::iterator it = m_blocks.find(blockIdx); + if (it != m_blocks.end()) + { + fb = it->second; + } + else + { + size_t pbs = m_blocksize; + // check if this is last block + int lastIOFileBlock = (fileSize-1)/m_blocksize; + if (blockIdx == lastIOFileBlock ) + { + pbs = fileSize - blockIdx*m_blocksize; + // TRACEIO(Dump, "IOFileBlock::Read() last block, change output file size to " << pbs); + } + + fb = newBlockFile(blockIdx*m_blocksize, pbs); + m_blocks.insert(std::pair(blockIdx, (File*) fb)); + } + m_mutex.UnLock(); + + // edit size if read request is reaching more than a block + int readBlockSize = size; + if (idx_first != idx_last) + { + if (blockIdx == idx_first) + { + readBlockSize = (blockIdx + 1) *m_blocksize - off0; + TRACEIO(Dump, "Read partially till the end of the block"); + } + else if (blockIdx == idx_last) + { + readBlockSize = (off0+size) - blockIdx*m_blocksize; + TRACEIO(Dump, "Read partially till the end of the block %s"); + } + else + { + readBlockSize = m_blocksize; + } + } + // MT-XXXX + assert(readBlockSize); + + TRACEIO(Dump, "IOFileBlock::Read() block[ " << blockIdx << "] read-block-size[" << readBlockSize << "], offset[" << readBlockSize << "] off = " << off ); + + long long min = blockIdx * m_blocksize; + if ( off < min) { assert(0); } // MT-XXXX + // MT-XXXX + assert(off+readBlockSize <= (min + m_blocksize)); + int retvalBlock = fb->Read(buff, off, readBlockSize); + + TRACEIO(Dump, "IOFileBlock::Read() Block read returned " << retvalBlock); + if (retvalBlock == readBlockSize) + { + bytes_read += retvalBlock; + buff += retvalBlock; + off += retvalBlock; + } + else if (retvalBlock > 0) + { + TRACEIO(Warning, "IOFileBlock::Read() incomplete read, missing bytes " << readBlockSize-retvalBlock); + return bytes_read + retvalBlock; + } + else + { + TRACEIO(Error, "IOFileBlock::Read() read error, retval" << retvalBlock); + return retvalBlock; + } + } + + return bytes_read; +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheIOFileBlock.hh b/src/XrdFileCache/XrdFileCacheIOFileBlock.hh index 88ac27d0f43..b02527da037 100644 --- a/src/XrdFileCache/XrdFileCacheIOFileBlock.hh +++ b/src/XrdFileCache/XrdFileCacheIOFileBlock.hh @@ -30,59 +30,59 @@ class XrdOssDF; namespace XrdFileCache { - //---------------------------------------------------------------------------- - //! \brief Downloads original file into multiple files, chunked into - //! blocks. Only blocks that are asked for are downloaded. - //! Handles read requests as they come along. - //---------------------------------------------------------------------------- - class IOFileBlock : public IO - { - public: - //------------------------------------------------------------------------ - //! Constructor. - //------------------------------------------------------------------------ - IOFileBlock(XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache &cache); +//---------------------------------------------------------------------------- +//! \brief Downloads original file into multiple files, chunked into +//! blocks. Only blocks that are asked for are downloaded. +//! Handles read requests as they come along. +//---------------------------------------------------------------------------- +class IOFileBlock : public IO +{ +public: + //------------------------------------------------------------------------ + //! Constructor. + //------------------------------------------------------------------------ + IOFileBlock(XrdOucCacheIO2 *io, XrdOucCacheStats &stats, Cache &cache); + + //------------------------------------------------------------------------ + //! Destructor. + //------------------------------------------------------------------------ + ~IOFileBlock(){} - //------------------------------------------------------------------------ - //! Destructor. - //------------------------------------------------------------------------ - ~IOFileBlock(){} + //--------------------------------------------------------------------- + //! Detach from Cache. Note: this will delete the object. + //! + //! @return original source \ref XrdPosixFile + //--------------------------------------------------------------------- + virtual XrdOucCacheIO *Detach(); - //--------------------------------------------------------------------- - //! Detach from Cache. Note: this will delete the object. - //! - //! @return original source \ref XrdPosixFile - //--------------------------------------------------------------------- - virtual XrdOucCacheIO *Detach(); + //--------------------------------------------------------------------- + //! Pass Read request to the corresponding File object. + //--------------------------------------------------------------------- + virtual int Read(char *Buffer, long long Offset, int Length); - //--------------------------------------------------------------------- - //! Pass Read request to the corresponding File object. - //--------------------------------------------------------------------- - virtual int Read(char *Buffer, long long Offset, int Length); + //! \brief Virtual method of XrdOucCacheIO. + //! Called to check if destruction needs to be done in a separate task. + virtual bool ioActive(); - //! \brief Virtual method of XrdOucCacheIO. - //! Called to check if destruction needs to be done in a separate task. - virtual bool ioActive(); + virtual int Fstat(struct stat &sbuff); - virtual int Fstat(struct stat &sbuff); - - virtual long long FSize(); + virtual long long FSize(); - virtual void RelinquishFile(File*); + virtual void RelinquishFile(File*); - private: - long long m_blocksize; //!< size of file-block - std::map m_blocks; //!< map of created blocks - XrdSysMutex m_mutex; //!< map mutex - struct stat *m_localStat; - Info m_info; - XrdOssDF* m_infoFile; +private: + long long m_blocksize; //!< size of file-block + std::map m_blocks; //!< map of created blocks + XrdSysMutex m_mutex; //!< map mutex + struct stat *m_localStat; + Info m_info; + XrdOssDF* m_infoFile; - void GetBlockSizeFromPath(); - int initLocalStat(); - File* newBlockFile(long long off, int blocksize); - void CloseInfoFile(); - }; + void GetBlockSizeFromPath(); + int initLocalStat(); + File* newBlockFile(long long off, int blocksize); + void CloseInfoFile(); +}; } -#endif +#endif \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheInfo.cc b/src/XrdFileCache/XrdFileCacheInfo.cc index fe9e5d88a6a..c8e80c706e7 100644 --- a/src/XrdFileCache/XrdFileCacheInfo.cc +++ b/src/XrdFileCache/XrdFileCacheInfo.cc @@ -36,106 +36,106 @@ namespace { - struct FpHelper - { - XrdOssDF *f_fp; - off_t f_off; - XrdOucTrace *f_trace; - const char *m_traceID; - std::string f_ttext; - - XrdOucTrace* GetTrace() const { return f_trace; } - - FpHelper(XrdOssDF* fp, off_t off, - XrdOucTrace *trace, const char *tid, const std::string &ttext) : - f_fp(fp), f_off(off), - f_trace(trace), m_traceID(tid), f_ttext(ttext) - {} - - // Returns true on error - bool ReadRaw(void *buf, ssize_t size, bool warnp=true) - { - ssize_t ret = f_fp->Read(buf, f_off, size); - if (ret != size) - { +struct FpHelper +{ + XrdOssDF *f_fp; + off_t f_off; + XrdOucTrace *f_trace; + const char *m_traceID; + std::string f_ttext; + + XrdOucTrace* GetTrace() const { return f_trace; } + + FpHelper(XrdOssDF* fp, off_t off, + XrdOucTrace *trace, const char *tid, const std::string &ttext) : + f_fp(fp), f_off(off), + f_trace(trace), m_traceID(tid), f_ttext(ttext) + {} + + // Returns true on error + bool ReadRaw(void *buf, ssize_t size, bool warnp = true) + { + ssize_t ret = f_fp->Read(buf, f_off, size); + if (ret != size) + { if (warnp) { - TRACE(Warning, f_ttext << " off=" << f_off << " size=" << size - << " ret=" << ret << " error=" << ((ret < 0) ? strerror(errno) : "")); + 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, bool warnp=true) - { - return ReadRaw(&loc, sizeof(T), warnp); - } - - // Returns true on error - bool WriteRaw(void *buf, ssize_t size) - { - ssize_t ret = f_fp->Write(buf, f_off, size); - if (ret != size) - { + } + f_off += ret; + return false; + } + + template bool Read(T &loc, bool warnp = true) + { + return ReadRaw(&loc, sizeof(T), warnp); + } + + // Returns true on error + bool WriteRaw(void *buf, ssize_t size) + { + ssize_t ret = f_fp->Write(buf, f_off, size); + if (ret != size) + { TRACE(Warning, f_ttext << " off=" << f_off << " size=" << size - << " ret=" << ret << " error=" << ((ret < 0) ? strerror(errno) : "")); + << " ret=" << ret << " error=" << ((ret < 0) ? strerror(errno) : "")); return true; - } - f_off += ret; - return false; - } - - template bool Write(T &loc) - { - return WriteRaw(&loc, sizeof(T)); - } - }; + } + f_off += ret; + return false; + } + + template bool Write(T &loc) + { + return WriteRaw(&loc, sizeof(T)); + } +}; } using namespace XrdFileCache; const char* Info::m_infoExtension = ".cinfo"; const char* Info::m_traceID = "Cinfo"; -const int Info::m_defaultVersion = 2; -const int Info::m_maxNumAccess = 3; +const int Info::m_defaultVersion = 2; +const int Info::m_maxNumAccess = 3; //------------------------------------------------------------------------------ Info::Info(XrdOucTrace* trace, bool prefetchBuffer) : - m_trace(trace), - m_hasPrefetchBuffer(prefetchBuffer), - m_buff_written(0), m_buff_prefetch(0), - m_sizeInBits(0), - m_complete(false), - m_cksCalc(0) + m_trace(trace), + m_hasPrefetchBuffer(prefetchBuffer), + m_buff_written(0), m_buff_prefetch(0), + m_sizeInBits(0), + m_complete(false), + m_cksCalc(0) {} Info::~Info() { - if (m_store.m_buff_synced) free(m_store.m_buff_synced); - if (m_buff_written) free(m_buff_written); - if (m_buff_prefetch) free(m_buff_prefetch); - delete m_cksCalc; + if (m_store.m_buff_synced) free(m_store.m_buff_synced); + if (m_buff_written) free(m_buff_written); + if (m_buff_prefetch) free(m_buff_prefetch); + delete m_cksCalc; } //------------------------------------------------------------------------------ void Info::SetBufferSize(long long bs) { - // Needed only info is created first time in File::Open() - m_store.m_bufferSize = bs; + // Needed only info is created first time in File::Open() + m_store.m_bufferSize = bs; } //------------------------------------------------------------------------------s void Info::SetFileSize(long long fs) { - m_store.m_fileSize = fs; - ResizeBits((m_store.m_fileSize - 1)/m_store.m_bufferSize + 1); - m_store.m_creationTime = time(0); + m_store.m_fileSize = fs; + ResizeBits((m_store.m_fileSize - 1)/m_store.m_bufferSize + 1); + m_store.m_creationTime = time(0); } //------------------------------------------------------------------------------ @@ -144,21 +144,21 @@ void Info::ResizeBits(int s) { // drop buffer in case of failed/partial reads - if (m_store.m_buff_synced) free(m_store.m_buff_synced); - if (m_buff_written) free(m_buff_written); - if (m_buff_prefetch) free(m_buff_prefetch); - - m_sizeInBits = s; - m_buff_written = (unsigned char*) malloc(GetSizeInBytes()); - m_store.m_buff_synced = (unsigned char*) malloc(GetSizeInBytes()); - memset(m_buff_written, 0, GetSizeInBytes()); - memset(m_store.m_buff_synced, 0, GetSizeInBytes()); - - if (m_hasPrefetchBuffer) - { - m_buff_prefetch = (unsigned char*) malloc(GetSizeInBytes()); - memset(m_buff_prefetch, 0, GetSizeInBytes()); - } + if (m_store.m_buff_synced) free(m_store.m_buff_synced); + if (m_buff_written) free(m_buff_written); + if (m_buff_prefetch) free(m_buff_prefetch); + + m_sizeInBits = s; + m_buff_written = (unsigned char*) malloc(GetSizeInBytes()); + m_store.m_buff_synced = (unsigned char*) malloc(GetSizeInBytes()); + memset(m_buff_written, 0, GetSizeInBytes()); + memset(m_store.m_buff_synced, 0, GetSizeInBytes()); + + if (m_hasPrefetchBuffer) + { + m_buff_prefetch = (unsigned char*) malloc(GetSizeInBytes()); + memset(m_buff_prefetch, 0, GetSizeInBytes()); + } } @@ -166,89 +166,91 @@ void Info::ResizeBits(int s) bool Info::Read(XrdOssDF* fp, const std::string &fname) { - // does not need lock, called only in File::Open - // before File::Run() starts - - std::string trace_pfx("Info:::Read() "); - trace_pfx += fname + " "; - - FpHelper r(fp, 0, m_trace, m_traceID, trace_pfx + "oss read failed"); - - if (r.Read(m_store.m_version)) return false; - - if (m_store.m_version == 0) { - TRACE(Warning, trace_pfx << " File version 0 non supported"); - return false; - } - else if (abs(m_store.m_version) == 1) - return ReadV1(fp, fname); - - if (r.Read(m_store.m_bufferSize)) return false; - - long long fs; - if (r.Read(fs)) return false; - SetFileSize(fs); - - if (r.ReadRaw(m_store.m_buff_synced, GetSizeInBytes())) return false; - memcpy(m_buff_written, m_store.m_buff_synced, GetSizeInBytes()); - - - if (r.ReadRaw(m_store.m_cksum, 16)) return false; - char tmpCksum[16]; - GetCksum(&m_store.m_buff_synced[0], &tmpCksum[0]); - - /* - // debug print cksum - for (int i =0; i < 16; ++i) - printf("%x", tmpCksum[i] & 0xff); - - for (int i =0; i < 16; ++i) - printf("%x", m_store.m_cksum[i] & 0xff); - */ - if (strncmp(m_store.m_cksum, &tmpCksum[0], 16)) { - TRACE(Error, trace_pfx << " buffer cksum and saved cksum don't match \n"); - return false; - } - - // cache complete status - m_complete = ! IsAnythingEmptyInRng(0, m_sizeInBits); - - - // read creation time - if (r.Read(m_store.m_creationTime)) return false; - - // get number of accessess - if (r.Read(m_store.m_accessCnt, false)) m_store.m_accessCnt = 0; // was: return false; - TRACE(Dump, trace_pfx << " complete "<< m_complete << " access_cnt " << m_store.m_accessCnt); - - // read access statistics - int vs = m_store.m_accessCnt < m_maxNumAccess ? m_store.m_accessCnt : m_maxNumAccess; - m_store.m_astats.resize(vs); - for (std::vector::iterator it = m_store.m_astats.begin(); it != m_store.m_astats.end(); ++it) - { - if (r.Read(*it, sizeof(AStat))) return false; - } - - - return true; + // does not need lock, called only in File::Open + // before File::Run() starts + + std::string trace_pfx("Info:::Read() "); + trace_pfx += fname + " "; + + FpHelper r(fp, 0, m_trace, m_traceID, trace_pfx + "oss read failed"); + + if (r.Read(m_store.m_version)) return false; + + if (m_store.m_version == 0) + { + TRACE(Warning, trace_pfx << " File version 0 non supported"); + return false; + } + else if (abs(m_store.m_version) == 1) + return ReadV1(fp, fname); + + if (r.Read(m_store.m_bufferSize)) return false; + + long long fs; + if (r.Read(fs)) return false; + SetFileSize(fs); + + if (r.ReadRaw(m_store.m_buff_synced, GetSizeInBytes())) return false; + memcpy(m_buff_written, m_store.m_buff_synced, GetSizeInBytes()); + + + if (r.ReadRaw(m_store.m_cksum, 16)) return false; + char tmpCksum[16]; + GetCksum(&m_store.m_buff_synced[0], &tmpCksum[0]); + + /* + // debug print cksum + for (int i =0; i < 16; ++i) + printf("%x", tmpCksum[i] & 0xff); + + for (int i =0; i < 16; ++i) + printf("%x", m_store.m_cksum[i] & 0xff); + */ + if (strncmp(m_store.m_cksum, &tmpCksum[0], 16)) + { + TRACE(Error, trace_pfx << " buffer cksum and saved cksum don't match \n"); + return false; + } + + // cache complete status + m_complete = ! IsAnythingEmptyInRng(0, m_sizeInBits); + + + // read creation time + if (r.Read(m_store.m_creationTime)) return false; + + // get number of accessess + if (r.Read(m_store.m_accessCnt, false)) m_store.m_accessCnt = 0; // was: return false; + TRACE(Dump, trace_pfx << " complete "<< m_complete << " access_cnt " << m_store.m_accessCnt); + + // read access statistics + int vs = m_store.m_accessCnt < m_maxNumAccess ? m_store.m_accessCnt : m_maxNumAccess; + m_store.m_astats.resize(vs); + for (std::vector::iterator it = m_store.m_astats.begin(); it != m_store.m_astats.end(); ++it) + { + if (r.Read(*it, sizeof(AStat))) return false; + } + + + return true; } bool Info::ReadV1(XrdOssDF* fp, const std::string &fname) { struct AStatV1 { - time_t DetachTime; //! close time + time_t DetachTime; //! close time long long BytesDisk; //! read from disk long long BytesRam; //! read from ram long long BytesMissed; //! read remote client }; - + std::string trace_pfx("Info:::ReadV1() "); trace_pfx += fname + " "; FpHelper r(fp, 0, m_trace, m_traceID, trace_pfx + "oss read failed"); - - - + + + if (r.Read(m_store.m_version)) return false; if (r.Read(m_store.m_bufferSize)) return false; @@ -259,33 +261,34 @@ bool Info::ReadV1(XrdOssDF* fp, const std::string &fname) if (r.ReadRaw(m_store.m_buff_synced, GetSizeInBytes())) return false; memcpy(m_buff_written, m_store.m_buff_synced, GetSizeInBytes()); - + m_complete = ! IsAnythingEmptyInRng(0, m_sizeInBits); if (r.Read(m_store.m_accessCnt, false)) m_store.m_accessCnt = 0; // was: return false; TRACE(Dump, trace_pfx << " complete "<< m_complete << " access_cnt " << m_store.m_accessCnt); - + int startFillIdx = m_store.m_accessCnt < m_maxNumAccess ? 0 : m_store.m_accessCnt - m_maxNumAccess; AStatV1 av1; - for (int i = 0 ; i < m_store.m_accessCnt; ++i) + for (int i = 0; i < m_store.m_accessCnt; ++i) { - if (r.ReadRaw(&av1, sizeof(AStatV1))) return false; - - if (i >= startFillIdx) { - AStat av2; - av2.AttachTime = av1.DetachTime; - av2.DetachTime = av1.DetachTime; - av2.BytesDisk = av1.BytesDisk; - av2.BytesRam = av1.BytesRam; - av2.BytesMissed = av1.BytesMissed; - - m_store.m_astats.push_back(av2); - } - - if (i == 0) m_store.m_creationTime = av1.DetachTime; + if (r.ReadRaw(&av1, sizeof(AStatV1))) return false; + + if (i >= startFillIdx) + { + AStat av2; + av2.AttachTime = av1.DetachTime; + av2.DetachTime = av1.DetachTime; + av2.BytesDisk = av1.BytesDisk; + av2.BytesRam = av1.BytesRam; + av2.BytesMissed = av1.BytesMissed; + + m_store.m_astats.push_back(av2); + } + + if (i == 0) m_store.m_creationTime = av1.DetachTime; } - + return true; } @@ -297,10 +300,10 @@ void Info::GetCksum( unsigned char* buff, char* digest) else m_cksCalc = new XrdCksCalcmd5(); - m_cksCalc->Update((const char*)buff, GetSizeInBytes()); - memcpy(digest, m_cksCalc->Final(), 16); + m_cksCalc->Update((const char*)buff, GetSizeInBytes()); + memcpy(digest, m_cksCalc->Final(), 16); } - + //------------------------------------------------------------------------------ void Info::DisableDownloadStatus() { @@ -311,42 +314,42 @@ void Info::DisableDownloadStatus() bool Info::Write(XrdOssDF* fp, const std::string &fname) { - std::string trace_pfx("Info:::Write() "); - trace_pfx += fname + " "; - - if (XrdOucSxeq::Serialize(fp->getFD(), XrdOucSxeq::noWait)) - { - TRACE(Error, trace_pfx << " lock failed " << strerror(errno)); - return false; - } - - FpHelper w(fp, 0, m_trace, m_traceID, trace_pfx + "oss write failed"); - - m_store.m_version = m_defaultVersion; - if (w.Write(m_store.m_version)) return false; - if (w.Write(m_store.m_bufferSize)) return false; - if (w.Write(m_store.m_fileSize)) return false; - - if (w.WriteRaw(m_store.m_buff_synced, GetSizeInBytes())) return false; - - GetCksum(&m_store.m_buff_synced[0], &m_store.m_cksum[0]); - if (w.Write(m_store.m_cksum)) return false; - - if (w.Write(m_store.m_creationTime)) return false; - - if (w.Write(m_store.m_accessCnt)) return false; - for (std::vector::iterator it = m_store.m_astats.begin(); it != m_store.m_astats.end(); ++it) - { - if (w.WriteRaw(&(*it), sizeof(AStat))) return false; - } - - // Can this really fail? - if (XrdOucSxeq::Release(fp->getFD())) - { - TRACE(Error, trace_pfx << "un-lock failed"); - } - - return true; + std::string trace_pfx("Info:::Write() "); + trace_pfx += fname + " "; + + if (XrdOucSxeq::Serialize(fp->getFD(), XrdOucSxeq::noWait)) + { + TRACE(Error, trace_pfx << " lock failed " << strerror(errno)); + return false; + } + + FpHelper w(fp, 0, m_trace, m_traceID, trace_pfx + "oss write failed"); + + m_store.m_version = m_defaultVersion; + if (w.Write(m_store.m_version)) return false; + if (w.Write(m_store.m_bufferSize)) return false; + if (w.Write(m_store.m_fileSize)) return false; + + if (w.WriteRaw(m_store.m_buff_synced, GetSizeInBytes())) return false; + + GetCksum(&m_store.m_buff_synced[0], &m_store.m_cksum[0]); + if (w.Write(m_store.m_cksum)) return false; + + if (w.Write(m_store.m_creationTime)) return false; + + if (w.Write(m_store.m_accessCnt)) return false; + for (std::vector::iterator it = m_store.m_astats.begin(); it != m_store.m_astats.end(); ++it) + { + if (w.WriteRaw(&(*it), sizeof(AStat))) return false; + } + + // Can this really fail? + if (XrdOucSxeq::Release(fp->getFD())) + { + TRACE(Error, trace_pfx << "un-lock failed"); + } + + return true; } //------------------------------------------------------------------------------ @@ -364,7 +367,7 @@ void Info::WriteIOStatAttach() m_store.m_accessCnt++; if ( m_store.m_astats.size() >= m_maxNumAccess) m_store.m_astats.erase( m_store.m_astats.begin()); - + AStat as; as.AttachTime = time(0); m_store.m_astats.push_back(as); @@ -374,8 +377,8 @@ void Info::WriteIOStatAttach() bool Info::GetLatestDetachTime(time_t& t) const { - if (!m_store.m_accessCnt) return false; + if (! m_store.m_accessCnt) return false; t = m_store.m_astats[m_store.m_accessCnt-1].DetachTime; return true; -} +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheInfo.hh b/src/XrdFileCache/XrdFileCacheInfo.hh index ff627d7108a..4f3fc138216 100644 --- a/src/XrdFileCache/XrdFileCacheInfo.hh +++ b/src/XrdFileCache/XrdFileCacheInfo.hh @@ -34,332 +34,331 @@ class XrdOucTrace; namespace XrdCl { - class Log; +class Log; } namespace XrdFileCache { - class Stats; - - //---------------------------------------------------------------------------- - //! Status of cached file. Can be read from and written into a binary file. - //---------------------------------------------------------------------------- - class Info - { - public: - // !Access statistics - struct AStat - { - time_t AttachTime; //! open time - time_t DetachTime; //! close time - long long BytesDisk; //! read from disk - long long BytesRam; //! read from ram - long long BytesMissed; //! read remote client - - AStat() :AttachTime(0), DetachTime(0), BytesDisk(0), BytesRam(0), BytesMissed(0) {} - }; - - struct Store { - int m_version; //!< info version - long long m_bufferSize; //!< prefetch buffer size - long long m_fileSize; //!< number of file blocks - unsigned char *m_buff_synced; //!< disk written state vector - char m_cksum[16]; //!< cksum of downloaded information - time_t m_creationTime; //!< time the info file was created - int m_accessCnt; //!< number of written AStat structs - std::vector m_astats; //!< number of last m_maxAcessCnts - - Store () : m_version(1), m_bufferSize(-1), m_fileSize(0), m_buff_synced(0),m_creationTime(0), m_accessCnt(0) { - } - }; - - - - //------------------------------------------------------------------------ - //! Constructor. - //------------------------------------------------------------------------ - Info(XrdOucTrace* trace, bool prefetchBuffer = false); - - //------------------------------------------------------------------------ - //! Destructor. - //------------------------------------------------------------------------ - ~Info(); - - //--------------------------------------------------------------------- - //! \brief Mark block as downloaded - //! - //! @param i block index - //--------------------------------------------------------------------- - void SetBitWritten(int i); - - //! \brief Mark block as disk written - //! - //! @param i block index - //--------------------------------------------------------------------- - void SetBitSynced(int i); - - //! \brief Mark block as written from prefetchxs - //! - //! @param i block index - //--------------------------------------------------------------------- - void SetBitPrefetch(int i); - - void SetBufferSize(long long); - void SetFileSize(long long); - - //--------------------------------------------------------------------- - //! \brief Reserve buffer for fileSize/bufferSize bytes - //! - //! @param n number of file blocks - //--------------------------------------------------------------------- - void ResizeBits(int n); - - //--------------------------------------------------------------------- - //! \brief Rea load content from cinfo file into this object - //! - //! @param fp file handle - //! @param fname optional file name for trace output - //! - //! @return true on success - //--------------------------------------------------------------------- - bool Read(XrdOssDF* fp, const std::string &fname=""); - - //--------------------------------------------------------------------- - //! Write number of blocks and read buffer size - //! @return true on success - //--------------------------------------------------------------------- - bool Write(XrdOssDF* fp, const std::string &fname=""); - - //--------------------------------------------------------------------- - //! Disable allocating, writing, and reading of downlaod status - //--------------------------------------------------------------------- - void DisableDownloadStatus(); - - //--------------------------------------------------------------------- - //! Write open time in the last entry of access statistics - //--------------------------------------------------------------------- - void WriteIOStatAttach(); - - //--------------------------------------------------------------------- - //! Write close time together with bytes missed, hits, and disk - //--------------------------------------------------------------------- - void WriteIOStatDetach(Stats& s); - - //--------------------------------------------------------------------- - //! Check download status in given block range - //--------------------------------------------------------------------- - bool IsAnythingEmptyInRng(int firstIdx, int lastIdx) const; - - //--------------------------------------------------------------------- - //! Get size of download-state bit-vector in bytes. - //--------------------------------------------------------------------- - int GetSizeInBytes() const; - - //--------------------------------------------------------------------- - //! Get number of blocks represented in download-state bit-vector. - //--------------------------------------------------------------------- - int GetSizeInBits() const; - - //--------------------------------------------------------------------- - //! Get file size - //--------------------------------------------------------------------- - long long GetFileSize() const; - - //--------------------------------------------------------------------- - //! Get latest detach time - //--------------------------------------------------------------------- - bool GetLatestDetachTime(time_t& t) const; - - //--------------------------------------------------------------------- - //! Get prefetch buffer size - //--------------------------------------------------------------------- - long long GetBufferSize() const; - - //--------------------------------------------------------------------- - //! Test if block at the given index is downlaoded - //--------------------------------------------------------------------- - bool TestBit(int i) const; - - //--------------------------------------------------------------------- - //! Test if block at the given index is prewritten - //--------------------------------------------------------------------- - bool TestPrefetchBit(int i) const; - - //--------------------------------------------------------------------- - //! Get complete status - //--------------------------------------------------------------------- - bool IsComplete() const; - - //--------------------------------------------------------------------- - //! Get number of downloaded blocks - //--------------------------------------------------------------------- - int GetNDownloadedBlocks() const; - - //--------------------------------------------------------------------- - //! Get number of downloaded bytes - //--------------------------------------------------------------------- - long long GetNDownloadedBytes() const; - - //--------------------------------------------------------------------- - //! Update complete status - //--------------------------------------------------------------------- - void UpdateDownloadCompleteStatus(); - - //--------------------------------------------------------------------- - //! Get number of accesses - //--------------------------------------------------------------------- - int GetAccessCnt() { return m_store.m_accessCnt; } - - //--------------------------------------------------------------------- - //! Get version - //--------------------------------------------------------------------- - int GetVersion() { return m_store.m_version; } - - //--------------------------------------------------------------------- - //! Get stored data - //--------------------------------------------------------------------- - const Store& RefStoredData() const { return m_store; } - - //--------------------------------------------------------------------- - //! Get md5 cksum - //--------------------------------------------------------------------- - void GetCksum( unsigned char* buff, char* digest); - - const static char* m_infoExtension; - const static char* m_traceID; - const static int m_defaultVersion; - const static int m_maxNumAccess; - - XrdOucTrace* GetTrace() const {return m_trace;} - - static int GetMaxNumAccess() { return m_maxNumAccess; } - - protected: - XrdOucTrace* m_trace; - - Store m_store; - bool m_hasPrefetchBuffer; //!< constains current prefetch score - unsigned char *m_buff_written; //!< download state vector - unsigned char *m_buff_prefetch; //!< prefetch statistics - - int m_sizeInBits ; //!cached - bool m_complete; //!< cached - - private: - inline unsigned char cfiBIT(int n) const { return 1 << n; } - - // split reading for V1 - bool ReadV1(XrdOssDF* fp, const std::string &fname); - XrdCksCalc* m_cksCalc; - }; - - inline bool Info::TestBit(int i) const - { - const int cn = i/8; - assert(cn < GetSizeInBytes()); - - const int off = i - cn*8; - return (m_buff_written[cn] & cfiBIT(off)) == cfiBIT(off); - } - - // AMT could have only one function to test bit and pass an argument, but would loose clarity - inline bool Info::TestPrefetchBit(int i) const - { - const int cn = i/8; - assert(cn < GetSizeInBytes()); - - const int off = i - cn*8; - return (m_buff_written[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 long long Info::GetNDownloadedBytes() const - { - return m_store.m_bufferSize * GetNDownloadedBlocks(); - } - - inline int Info::GetSizeInBytes() const - { - if (m_sizeInBits) - return ((m_sizeInBits - 1)/8 + 1); - else - return 0; - } - - inline int Info::GetSizeInBits() const - { - return m_sizeInBits; - } - - inline long long Info::GetFileSize() const - { - return m_store.m_fileSize; - } - - inline bool Info::IsComplete() const - { - return m_complete; - } - - inline bool Info::IsAnythingEmptyInRng(int firstIdx, int lastIdx) const - { - // XXX rewrite to use full byte comparisons outside of edges ? - // Also, it is always called with fisrtsdx = 0, lastIdx = m_sizeInBits. - for (int i = firstIdx; i < lastIdx; ++i) - if (!TestBit(i)) return true; - - return false; - } - - inline void Info::UpdateDownloadCompleteStatus() - { - m_complete = ! IsAnythingEmptyInRng(0, m_sizeInBits); - } - - inline void Info::SetBitSynced(int i) - { - const int cn = i/8; - assert(cn < GetSizeInBytes()); - - const int off = i - cn*8; - m_store.m_buff_synced[cn] |= cfiBIT(off); - } - - inline void Info::SetBitWritten(int i) - { - const int cn = i/8; - assert(cn < GetSizeInBytes()); - - const int off = i - cn*8; - m_buff_written[cn] |= cfiBIT(off); - } - - inline void Info::SetBitPrefetch(int i) - { - const int cn = i/8; - assert(cn < GetSizeInBytes()); - - const int off = i - cn*8; - m_buff_prefetch[cn] |= cfiBIT(off); - } - - - inline long long Info::GetBufferSize() const - { - return m_store.m_bufferSize; - } - - - //---------------------------------------------------------------- - // XrdFileCacheInfoBlock - //---------------------------------------------------------------- +class Stats; + +//---------------------------------------------------------------------------- +//! Status of cached file. Can be read from and written into a binary file. +//---------------------------------------------------------------------------- +class Info +{ +public: + // !Access statistics + struct AStat + { + time_t AttachTime; //! open time + time_t DetachTime; //! close time + long long BytesDisk; //! read from disk + long long BytesRam; //! read from ram + long long BytesMissed; //! read remote client + + AStat() : AttachTime(0), DetachTime(0), BytesDisk(0), BytesRam(0), BytesMissed(0) {} + }; + + struct Store { + int m_version; //!< info version + long long m_bufferSize; //!< prefetch buffer size + long long m_fileSize; //!< number of file blocks + unsigned char *m_buff_synced; //!< disk written state vector + char m_cksum[16]; //!< cksum of downloaded information + time_t m_creationTime; //!< time the info file was created + int m_accessCnt; //!< number of written AStat structs + std::vector m_astats; //!< number of last m_maxAcessCnts + + Store () : m_version(1), m_bufferSize(-1), m_fileSize(0), m_buff_synced(0),m_creationTime(0), m_accessCnt(0) {} + }; + + + + //------------------------------------------------------------------------ + //! Constructor. + //------------------------------------------------------------------------ + Info(XrdOucTrace* trace, bool prefetchBuffer = false); + + //------------------------------------------------------------------------ + //! Destructor. + //------------------------------------------------------------------------ + ~Info(); + + //--------------------------------------------------------------------- + //! \brief Mark block as downloaded + //! + //! @param i block index + //--------------------------------------------------------------------- + void SetBitWritten(int i); + + //! \brief Mark block as disk written + //! + //! @param i block index + //--------------------------------------------------------------------- + void SetBitSynced(int i); + + //! \brief Mark block as written from prefetchxs + //! + //! @param i block index + //--------------------------------------------------------------------- + void SetBitPrefetch(int i); + + void SetBufferSize(long long); + void SetFileSize(long long); + + //--------------------------------------------------------------------- + //! \brief Reserve buffer for fileSize/bufferSize bytes + //! + //! @param n number of file blocks + //--------------------------------------------------------------------- + void ResizeBits(int n); + + //--------------------------------------------------------------------- + //! \brief Rea load content from cinfo file into this object + //! + //! @param fp file handle + //! @param fname optional file name for trace output + //! + //! @return true on success + //--------------------------------------------------------------------- + bool Read(XrdOssDF* fp, const std::string &fname = ""); + + //--------------------------------------------------------------------- + //! Write number of blocks and read buffer size + //! @return true on success + //--------------------------------------------------------------------- + bool Write(XrdOssDF* fp, const std::string &fname = ""); + + //--------------------------------------------------------------------- + //! Disable allocating, writing, and reading of downlaod status + //--------------------------------------------------------------------- + void DisableDownloadStatus(); + + //--------------------------------------------------------------------- + //! Write open time in the last entry of access statistics + //--------------------------------------------------------------------- + void WriteIOStatAttach(); + + //--------------------------------------------------------------------- + //! Write close time together with bytes missed, hits, and disk + //--------------------------------------------------------------------- + void WriteIOStatDetach(Stats& s); + + //--------------------------------------------------------------------- + //! Check download status in given block range + //--------------------------------------------------------------------- + bool IsAnythingEmptyInRng(int firstIdx, int lastIdx) const; + + //--------------------------------------------------------------------- + //! Get size of download-state bit-vector in bytes. + //--------------------------------------------------------------------- + int GetSizeInBytes() const; + + //--------------------------------------------------------------------- + //! Get number of blocks represented in download-state bit-vector. + //--------------------------------------------------------------------- + int GetSizeInBits() const; + + //--------------------------------------------------------------------- + //! Get file size + //--------------------------------------------------------------------- + long long GetFileSize() const; + + //--------------------------------------------------------------------- + //! Get latest detach time + //--------------------------------------------------------------------- + bool GetLatestDetachTime(time_t& t) const; + + //--------------------------------------------------------------------- + //! Get prefetch buffer size + //--------------------------------------------------------------------- + long long GetBufferSize() const; + + //--------------------------------------------------------------------- + //! Test if block at the given index is downlaoded + //--------------------------------------------------------------------- + bool TestBit(int i) const; + + //--------------------------------------------------------------------- + //! Test if block at the given index is prewritten + //--------------------------------------------------------------------- + bool TestPrefetchBit(int i) const; + + //--------------------------------------------------------------------- + //! Get complete status + //--------------------------------------------------------------------- + bool IsComplete() const; + + //--------------------------------------------------------------------- + //! Get number of downloaded blocks + //--------------------------------------------------------------------- + int GetNDownloadedBlocks() const; + + //--------------------------------------------------------------------- + //! Get number of downloaded bytes + //--------------------------------------------------------------------- + long long GetNDownloadedBytes() const; + + //--------------------------------------------------------------------- + //! Update complete status + //--------------------------------------------------------------------- + void UpdateDownloadCompleteStatus(); + + //--------------------------------------------------------------------- + //! Get number of accesses + //--------------------------------------------------------------------- + int GetAccessCnt() { return m_store.m_accessCnt; } + + //--------------------------------------------------------------------- + //! Get version + //--------------------------------------------------------------------- + int GetVersion() { return m_store.m_version; } + + //--------------------------------------------------------------------- + //! Get stored data + //--------------------------------------------------------------------- + const Store& RefStoredData() const { return m_store; } + + //--------------------------------------------------------------------- + //! Get md5 cksum + //--------------------------------------------------------------------- + void GetCksum( unsigned char* buff, char* digest); + + const static char* m_infoExtension; + const static char* m_traceID; + const static int m_defaultVersion; + const static int m_maxNumAccess; + + XrdOucTrace* GetTrace() const {return m_trace; } + + static int GetMaxNumAccess() { return m_maxNumAccess; } + +protected: + XrdOucTrace* m_trace; + + Store m_store; + bool m_hasPrefetchBuffer; //!< constains current prefetch score + unsigned char *m_buff_written; //!< download state vector + unsigned char *m_buff_prefetch; //!< prefetch statistics + + int m_sizeInBits; //!cached + bool m_complete; //!< cached + +private: + inline unsigned char cfiBIT(int n) const { return 1 << n; } + + // split reading for V1 + bool ReadV1(XrdOssDF* fp, const std::string &fname); + XrdCksCalc* m_cksCalc; +}; + +inline bool Info::TestBit(int i) const +{ + const int cn = i/8; + assert(cn < GetSizeInBytes()); + + const int off = i - cn*8; + return (m_buff_written[cn] & cfiBIT(off)) == cfiBIT(off); +} + +// AMT could have only one function to test bit and pass an argument, but would loose clarity +inline bool Info::TestPrefetchBit(int i) const +{ + const int cn = i/8; + assert(cn < GetSizeInBytes()); + + const int off = i - cn*8; + return (m_buff_written[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 long long Info::GetNDownloadedBytes() const +{ + return m_store.m_bufferSize * GetNDownloadedBlocks(); +} + +inline int Info::GetSizeInBytes() const +{ + if (m_sizeInBits) + return ((m_sizeInBits - 1)/8 + 1); + else + return 0; +} + +inline int Info::GetSizeInBits() const +{ + return m_sizeInBits; +} + +inline long long Info::GetFileSize() const +{ + return m_store.m_fileSize; +} + +inline bool Info::IsComplete() const +{ + return m_complete; +} + +inline bool Info::IsAnythingEmptyInRng(int firstIdx, int lastIdx) const +{ + // XXX rewrite to use full byte comparisons outside of edges ? + // Also, it is always called with fisrtsdx = 0, lastIdx = m_sizeInBits. + for (int i = firstIdx; i < lastIdx; ++i) + if (! TestBit(i)) return true; + + return false; +} + +inline void Info::UpdateDownloadCompleteStatus() +{ + m_complete = ! IsAnythingEmptyInRng(0, m_sizeInBits); +} + +inline void Info::SetBitSynced(int i) +{ + const int cn = i/8; + assert(cn < GetSizeInBytes()); + + const int off = i - cn*8; + m_store.m_buff_synced[cn] |= cfiBIT(off); +} + +inline void Info::SetBitWritten(int i) +{ + const int cn = i/8; + assert(cn < GetSizeInBytes()); + + const int off = i - cn*8; + m_buff_written[cn] |= cfiBIT(off); +} + +inline void Info::SetBitPrefetch(int i) +{ + const int cn = i/8; + assert(cn < GetSizeInBytes()); + + const int off = i - cn*8; + m_buff_prefetch[cn] |= cfiBIT(off); +} + + +inline long long Info::GetBufferSize() const +{ + return m_store.m_bufferSize; +} + + +//---------------------------------------------------------------- +// XrdFileCacheInfoBlock +//---------------------------------------------------------------- } -#endif +#endif \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCachePrint.cc b/src/XrdFileCache/XrdFileCachePrint.cc index b22785e5c50..4c54ca6689c 100644 --- a/src/XrdFileCache/XrdFileCachePrint.cc +++ b/src/XrdFileCache/XrdFileCachePrint.cc @@ -31,14 +31,17 @@ using namespace XrdFileCache; -Print::Print(XrdOss* oss, bool v, const char* path): m_oss(oss), m_verbose(v), m_ossUser("nobody") +Print::Print(XrdOss* oss, bool v, const char* path) : m_oss(oss), m_verbose(v), m_ossUser("nobody") { - if (isInfoFile(path)) { + if (isInfoFile(path)) + { printFile(std::string(path)); } - else { + else + { XrdOssDF* dh = m_oss->newDir(m_ossUser); - if ( dh->Opendir(path, m_env) >= 0 ) { + if ( dh->Opendir(path, m_env) >= 0 ) + { printDir(dh, path); } } @@ -53,8 +56,8 @@ bool Print::isInfoFile(const char* path) { } -void Print::printFile(const std::string& path) -{ +void Print::printFile(const std::string& path) +{ printf("printing %s ...\n", path.c_str()); XrdOssDF* fh = m_oss->newFile(m_ossUser); fh->Open((path).c_str(),O_RDONLY, 0600, m_env); @@ -69,9 +72,10 @@ void Print::printFile(const std::string& path) return; } - + int cntd = 0; - for (int i = 0; i < cfi.GetSizeInBits(); ++i) if (cfi.TestBit(i)) cntd++; + for (int i = 0; i < cfi.GetSizeInBits(); ++i) + if (cfi.TestBit(i)) cntd++; const Info::Store& store = cfi.RefStoredData(); char creationBuff[1000]; @@ -79,60 +83,66 @@ void Print::printFile(const std::string& path) strftime(creationBuff, 1000, "%c", localtime(&creationTime)); printf("version %d, creation %s\n", cfi.GetVersion(), creationBuff); - + printf("fileSize %lld, bufferSize %lld nBlocks %d nDownloaded %d %s\n", cfi.GetFileSize(),cfi.GetBufferSize(), cfi.GetSizeInBits(), cntd, (cfi.GetSizeInBits() == cntd) ? "complete" : ""); - + if (m_verbose) { - int n_db = 0; - { int x = cfi.GetSizeInBits(); while (x) { x /= 10; ++n_db; } } - static const char *nums = "0123456789"; - printf("printing %d blocks:\n", cfi.GetSizeInBits()); - printf("%*s %10d%10d%10d%10d%10d%10d\n", n_db, "", 1, 2, 3, 4, 5, 6); - printf("%*s %s%s%s%s%s%s0123", n_db, "", nums, nums, nums, nums, nums, nums); - for (int i = 0; i < cfi.GetSizeInBits(); ++i) - { - if (i % 64 == 0) - printf("\n%*d ", n_db, i); - printf("%c", cfi.TestBit(i) ? 'x' : '.'); - } - printf("\n"); + int n_db = 0; + { int x = cfi.GetSizeInBits(); while (x) + { + x /= 10; ++n_db; + } + } + static const char *nums = "0123456789"; + printf("printing %d blocks:\n", cfi.GetSizeInBits()); + printf("%*s %10d%10d%10d%10d%10d%10d\n", n_db, "", 1, 2, 3, 4, 5, 6); + printf("%*s %s%s%s%s%s%s0123", n_db, "", nums, nums, nums, nums, nums, nums); + for (int i = 0; i < cfi.GetSizeInBits(); ++i) + { + if (i % 64 == 0) + printf("\n%*d ", n_db, i); + printf("%c", cfi.TestBit(i) ? 'x' : '.'); + } + printf("\n"); } - + // printf("\nlatest access statistics:\n"); int startIdx = cfi.GetAccessCnt() < cfi.GetMaxNumAccess() ? 0 : cfi.GetAccessCnt() - cfi.GetMaxNumAccess(); for (std::vector::const_iterator it = store.m_astats.begin(); it != store.m_astats.end(); ++it) { - printf("access %d: ", startIdx++); - char as[1000]; - strftime(as, 1000, "%c", localtime(&(it->AttachTime))); - char ds[1000]; - strftime(ds, 1000, "%c", localtime(&(it->DetachTime))); - int lasting = it->DetachTime - it->AttachTime; - int hours = lasting/3600; - int min = (lasting - hours * 3600)/60; - int sec = lasting % 60; - - printf("%s, openedTime %02d:%02d:%02d, bytesDisk=%lld, bytesRAM=%lld, bytesMissed=%lld\n", as, hours, min, sec, it->BytesDisk, it->BytesRam, it->BytesMissed); + printf("access %d: ", startIdx++); + char as[1000]; + strftime(as, 1000, "%c", localtime(&(it->AttachTime))); + char ds[1000]; + strftime(ds, 1000, "%c", localtime(&(it->DetachTime))); + int lasting = it->DetachTime - it->AttachTime; + int hours = lasting/3600; + int min = (lasting - hours * 3600)/60; + int sec = lasting % 60; + + printf("%s, openedTime %02d:%02d:%02d, bytesDisk=%lld, bytesRAM=%lld, bytesMissed=%lld\n", as, hours, min, sec, it->BytesDisk, it->BytesRam, it->BytesMissed); } - + delete fh; printf("\n"); } -void Print::printDir(XrdOssDF* iOssDF, const std::string& path) +void Print::printDir(XrdOssDF* iOssDF, const std::string& path) { // printf("---------> print dir %s \n", path.c_str()); char buff[256]; int rdr; while ( (rdr = iOssDF->Readdir(&buff[0], 256)) >= 0) { - if (strncmp("..", &buff[0], 2) && strncmp(".", &buff[0], 1)) { + if (strncmp("..", &buff[0], 2) && strncmp(".", &buff[0], 1)) + { - if (strlen(buff) == 0) { + if (strlen(buff) == 0) + { break; // end of readdir } std::string np = path + "/" + std::string(&buff[0]); @@ -140,9 +150,11 @@ void Print::printDir(XrdOssDF* iOssDF, const std::string& path) { printFile(np); } - else { + else + { XrdOssDF* dh = m_oss->newDir(m_ossUser); - if (dh->Opendir(np.c_str(), m_env) >= 0) { + if (dh->Opendir(np.c_str(), m_env) >= 0) + { printDir(dh, np); } delete dh; dh = 0; @@ -155,11 +167,11 @@ void Print::printDir(XrdOssDF* iOssDF, const std::string& path) //______________________________________________________________________________ int main(int argc, char *argv[]) -{ +{ static const char* usage = "Usage: pfc_print [-c config_file] [-v] path\n\n"; bool verbose = false; const char* cfgn = 0; - + XrdOucEnv myEnv; XrdSysLogger log; @@ -167,7 +179,7 @@ int main(int argc, char *argv[]) XrdOucStream Config(&err, getenv("XRDINSTANCE"), &myEnv, "=====> "); - XrdOucArgs Spec(&err, "pfc_print: ", "", + XrdOucArgs Spec(&err, "pfc_print: ", "", "verbose", 1, "v", "config", 1, "c", (const char *)0); @@ -180,46 +192,53 @@ int main(int argc, char *argv[]) { switch(theOpt) { - case 'c': { - cfgn = Spec.getarg(); - int fd = open(cfgn, O_RDONLY, 0); - Config.Attach(fd); - break; - } - case 'v': { - verbose = true; - break; - } - default: { - printf("%s", usage); - exit(1); - } + case 'c': + { + cfgn = Spec.getarg(); + int fd = open(cfgn, O_RDONLY, 0); + Config.Attach(fd); + break; + } + case 'v': + { + verbose = true; + break; + } + default: + { + printf("%s", usage); + exit(1); + } } } // suppress oss init messages - int efs = open("/dev/null",O_RDWR, 0); + int efs = open("/dev/null",O_RDWR, 0); XrdSysLogger ossLog(efs); XrdSysError ossErr(&ossLog, "print"); - XrdOss *oss; + XrdOss *oss; XrdOfsConfigPI *ofsCfg = XrdOfsConfigPI::New(cfgn,&Config,&ossErr); bool ossSucc = ofsCfg->Load(XrdOfsConfigPI::theOssLib); - if (!ossSucc) { + if (! ossSucc) + { printf("can't load oss\n"); exit(1); } ofsCfg->Plugin(oss); const char* path = Spec.getarg(); - if (!path) { + if (! path) + { printf("%s", usage); exit(1); } // append oss.localroot if path starts with 'root://' - if (!strncmp(&path[0], "root:/", 6)) { - if (Config.FDNum() < 0) { + if (! strncmp(&path[0], "root:/", 6)) + { + if (Config.FDNum() < 0) + { printf("Configuration file not specified.\n"); exit(1); } @@ -227,18 +246,17 @@ int main(int argc, char *argv[]) while((var = Config.GetFirstWord())) { // printf("var %s \n", var); - if (!strncmp(var,"oss.localroot", strlen("oss.localroot"))) + if (! strncmp(var,"oss.localroot", strlen("oss.localroot"))) { std::string tmp = Config.GetWord(); tmp += &path[6]; - // printf("Absolute path %s \n", tmp.c_str()); + // printf("Absolute path %s \n", tmp.c_str()); XrdFileCache::Print p(oss, verbose, tmp.c_str()); } } } - else { - XrdFileCache::Print p(oss, verbose, path); + else + { + XrdFileCache::Print p(oss, verbose, path); } -} - - +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCachePrint.hh b/src/XrdFileCache/XrdFileCachePrint.hh index 562c63f09ae..4602246cc50 100644 --- a/src/XrdFileCache/XrdFileCachePrint.hh +++ b/src/XrdFileCache/XrdFileCachePrint.hh @@ -25,30 +25,30 @@ namespace XrdFileCache { class Print { public: - //------------------------------------------------------------------------ - //! Constructor. - //------------------------------------------------------------------------ - Print(XrdOss* oss, bool v, const char* path); + //------------------------------------------------------------------------ + //! Constructor. + //------------------------------------------------------------------------ + Print(XrdOss* oss, bool v, const char* path); private: - XrdOss* m_oss; //! file system - XrdOucEnv m_env; //! env used by file system - bool m_verbose; //! print each block - const char* m_ossUser; //! file system user + XrdOss* m_oss; //! file system + XrdOucEnv m_env; //! env used by file system + bool m_verbose; //! print each block + const char* m_ossUser; //! file system user - //--------------------------------------------------------------------- - //! Check file ends with *.cinfo suffix - //--------------------------------------------------------------------- - bool isInfoFile(const char* path); + //--------------------------------------------------------------------- + //! Check file ends with *.cinfo suffix + //--------------------------------------------------------------------- + bool isInfoFile(const char* path); - //--------------------------------------------------------------------- - //! Print information in meta-data file - //--------------------------------------------------------------------- - void printFile(const std::string& path); + //--------------------------------------------------------------------- + //! Print information in meta-data file + //--------------------------------------------------------------------- + void printFile(const std::string& path); - //--------------------------------------------------------------------- - //! Print information in meta-data file recursivly - //--------------------------------------------------------------------- - void printDir(XrdOssDF* iOssDF, const std::string& path); + //--------------------------------------------------------------------- + //! Print information in meta-data file recursivly + //--------------------------------------------------------------------- + void printDir(XrdOssDF* iOssDF, const std::string& path); }; -} +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCachePurge.cc b/src/XrdFileCache/XrdFileCachePurge.cc index ed94255b20a..f8244b7fb34 100644 --- a/src/XrdFileCache/XrdFileCachePurge.cc +++ b/src/XrdFileCache/XrdFileCachePurge.cc @@ -9,47 +9,47 @@ using namespace XrdFileCache; namespace { - class FPurgeState - { - public: - struct FS - { - std::string path; - long long nByte; +class FPurgeState +{ +public: +struct FS +{ + std::string path; + long long nByte; - FS(const char* p, long long n) : path(p), nByte(n) {} - }; + FS(const char* p, long long n) : path(p), nByte(n) {} +}; - typedef std::multimap map_t; - typedef map_t::iterator map_i; +typedef std::multimap map_t; +typedef map_t::iterator map_i; - FPurgeState(long long iNByteReq) : nByteReq(iNByteReq), nByteAccum(0) {} +FPurgeState(long long iNByteReq) : nByteReq(iNByteReq), nByteAccum(0) {} - map_t fmap; +map_t fmap; - void checkFile (time_t iTime, const char* iPath, long long iNByte) - { - if (nByteAccum < nByteReq || iTime < fmap.rbegin()->first) - { - fmap.insert(std::pair (iTime, FS(iPath, iNByte))); - nByteAccum += iNByte; +void checkFile (time_t iTime, const char* iPath, long long iNByte) +{ + if (nByteAccum < nByteReq || iTime < fmap.rbegin()->first) + { + fmap.insert(std::pair (iTime, FS(iPath, iNByte))); + nByteAccum += iNByte; - // remove newest files from map if necessary - while (nByteAccum > nByteReq) - { - time_t nt = fmap.begin()->first; - std::pair ret = fmap.equal_range(nt); - for (map_i it2 = ret.first; it2 != ret.second; ++it2) - nByteAccum -= it2->second.nByte; - fmap.erase(ret.first, ret.second); - } - } + // remove newest files from map if necessary + while (nByteAccum > nByteReq) + { + time_t nt = fmap.begin()->first; + std::pair ret = fmap.equal_range(nt); + for (map_i it2 = ret.first; it2 != ret.second; ++it2) + nByteAccum -= it2->second.nByte; + fmap.erase(ret.first, ret.second); } + } +} - private: - long long nByteReq; - long long nByteAccum; - }; +private: +long long nByteReq; +long long nByteAccum; +}; XrdOucTrace* GetTrace() { @@ -115,7 +115,7 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, FPurgeState& // This really shouldn't happen ... but if it does remove cinfo and the data file right away. TRACE(Warning, "FillFileMapRecurse() could not get access time for " << np - << "; purging."); + << "; purging."); oss->Unlink(np.c_str()); np = np.substr(0, np.size() - strlen(XrdFileCache::Info::m_infoExtension)); oss->Unlink(np.c_str()); @@ -125,7 +125,7 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, FPurgeState& else { TRACE(Warning, "FillFileMapRecurse() can't open or read " << np << ", err " << strerror(errno) - << "; purging."); + << "; purging."); XrdOss* oss = Cache::GetInstance().GetOss(); oss->Unlink(np.c_str()); np = np.substr(0, np.size() - strlen(XrdFileCache::Info::m_infoExtension)); @@ -145,7 +145,7 @@ void FillFileMapRecurse( XrdOssDF* iOssDF, const std::string& path, FPurgeState& } void Cache::CacheDirCleanup() { - XrdOucEnv env; + XrdOucEnv env; XrdOss* oss = Cache::GetInstance().GetOss(); XrdOssVSInfo sP; @@ -180,16 +180,16 @@ void Cache::CacheDirCleanup() FillFileMapRecurse(dh, "", purgeState); // loop over map and remove files with highest value of access time - struct stat fstat; + struct stat fstat; for (FPurgeState::map_i it = purgeState.fmap.begin(); it != purgeState.fmap.end(); ++it) { std::string infoPath = it->second.path; std::string dataPath = infoPath.substr(0, infoPath.size() - strlen(XrdFileCache::Info::m_infoExtension)); - if (HaveActiveFileWithLocalPath(dataPath)) - continue; - + if (HaveActiveFileWithLocalPath(dataPath)) + continue; + // remove info file if (oss->Stat(infoPath.c_str(), &fstat) == XrdOssOK) { @@ -212,10 +212,10 @@ void Cache::CacheDirCleanup() break; } } - dh->Close(); - delete dh; dh = 0; + dh->Close(); + delete dh; dh = 0; } sleep(m_configuration.m_purgeInterval); } -} +} \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheStats.hh b/src/XrdFileCache/XrdFileCacheStats.hh index a05a7b5e55a..3d5ca8451a9 100644 --- a/src/XrdFileCache/XrdFileCacheStats.hh +++ b/src/XrdFileCache/XrdFileCacheStats.hh @@ -24,38 +24,38 @@ namespace XrdFileCache { - //---------------------------------------------------------------------------- - //! Statistics of disk cache utilisation. - //---------------------------------------------------------------------------- - class Stats : public XrdOucCacheStats - { - public: - //---------------------------------------------------------------------- - //! Constructor. - //---------------------------------------------------------------------- - Stats() { - m_BytesDisk = m_BytesRam = m_BytesMissed = 0; - } - - long long m_BytesDisk; //!< number of bytes served from disk cache - long long m_BytesRam; //!< number of bytes served from RAM cache - long long m_BytesMissed; //!< number of bytes served directly from XrdCl - - inline void AddStat(Stats &Src) - { - XrdOucCacheStats::Add(Src); - - m_MutexXfc.Lock(); - m_BytesDisk += Src.m_BytesDisk; - m_BytesRam += Src.m_BytesRam; - m_BytesMissed += Src.m_BytesMissed; - - m_MutexXfc.UnLock(); - } - - private: - XrdSysMutex m_MutexXfc; - }; +//---------------------------------------------------------------------------- +//! Statistics of disk cache utilisation. +//---------------------------------------------------------------------------- +class Stats : public XrdOucCacheStats +{ +public: + //---------------------------------------------------------------------- + //! Constructor. + //---------------------------------------------------------------------- + Stats() { + m_BytesDisk = m_BytesRam = m_BytesMissed = 0; + } + + long long m_BytesDisk; //!< number of bytes served from disk cache + long long m_BytesRam; //!< number of bytes served from RAM cache + long long m_BytesMissed; //!< number of bytes served directly from XrdCl + + inline void AddStat(Stats &Src) + { + XrdOucCacheStats::Add(Src); + + m_MutexXfc.Lock(); + m_BytesDisk += Src.m_BytesDisk; + m_BytesRam += Src.m_BytesRam; + m_BytesMissed += Src.m_BytesMissed; + + m_MutexXfc.UnLock(); + } + +private: + XrdSysMutex m_MutexXfc; +}; } -#endif +#endif \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheTrace.hh b/src/XrdFileCache/XrdFileCacheTrace.hh index 55118f5e4b2..db9dbe2a3f0 100644 --- a/src/XrdFileCache/XrdFileCacheTrace.hh +++ b/src/XrdFileCache/XrdFileCacheTrace.hh @@ -28,20 +28,20 @@ #endif #define TRACE(act, x) \ - if (XRD_TRACE What >= TRACE_ ## act) \ - {XRD_TRACE Beg(m_traceID); cerr << TRACE_STR_##act <= TRACE_ ## act) \ + {XRD_TRACE Beg(m_traceID); cerr << TRACE_STR_ ## act <= TRACE_ ## act) \ - {pre_code; XRD_TRACE Beg(m_traceID); cerr << TRACE_STR_##act <= TRACE_ ## act) \ + {pre_code; XRD_TRACE Beg(m_traceID); cerr << TRACE_STR_ ## act <= TRACE_ ## act) \ - {XRD_TRACE Beg(m_traceID); cerr << TRACE_STR_##act <= TRACE_ ## act) \ + {XRD_TRACE Beg(m_traceID); cerr << TRACE_STR_ ## act <= TRACE_ ## act) \ - {XRD_TRACE Beg(m_traceID); cerr << TRACE_STR_##act << x << " " << GetLocalPath(); XRD_TRACE End();} + if (XRD_TRACE What >= TRACE_ ## act) \ + {XRD_TRACE Beg(m_traceID); cerr << TRACE_STR_ ## act << x << " " << GetLocalPath(); XRD_TRACE End(); } #else @@ -52,4 +52,4 @@ #endif -#endif +#endif \ No newline at end of file diff --git a/src/XrdFileCache/XrdFileCacheVRead.cc b/src/XrdFileCache/XrdFileCacheVRead.cc index 776ec36805e..42985d9cbea 100644 --- a/src/XrdFileCache/XrdFileCacheVRead.cc +++ b/src/XrdFileCache/XrdFileCacheVRead.cc @@ -14,64 +14,64 @@ namespace XrdFileCache { - // a list of IOVec chuncks that match a given block index - // first element is block index, the following vector elements are chunk readv indicies - struct ReadVChunkListDisk - { - ReadVChunkListDisk(int i) : block_idx(i) {} - - int block_idx; - std::vector arr; - }; - - struct ReadVChunkListRAM - { - ReadVChunkListRAM(Block*b, std::vector * iarr) : block(b), arr(iarr) {} - - Block *block; - std::vector *arr; - }; - - // RAM - struct ReadVBlockListRAM - { - std::vector bv; - - bool AddEntry(Block* block, int chunkIdx) - { - for (std::vector::iterator i = bv.begin(); i != bv.end(); ++i) - { +// a list of IOVec chuncks that match a given block index +// first element is block index, the following vector elements are chunk readv indicies +struct ReadVChunkListDisk +{ + ReadVChunkListDisk(int i) : block_idx(i) {} + + int block_idx; + std::vector arr; +}; + +struct ReadVChunkListRAM +{ + ReadVChunkListRAM(Block*b, std::vector * iarr) : block(b), arr(iarr) {} + + Block *block; + std::vector *arr; +}; + +// RAM +struct ReadVBlockListRAM +{ + std::vector bv; + + bool AddEntry(Block* block, int chunkIdx) + { + for (std::vector::iterator i = bv.begin(); i != bv.end(); ++i) + { if (i->block == block) { - i->arr->push_back(chunkIdx); - return false; + i->arr->push_back(chunkIdx); + return false; } - } - bv.push_back(ReadVChunkListRAM(block, new std::vector)); - bv.back().arr->push_back(chunkIdx); - return true; - } - }; - - // Disk - struct ReadVBlockListDisk - { - std::vector bv; - - void AddEntry(int blockIdx, int chunkIdx) - { - for (std::vector::iterator i = bv.begin(); i != bv.end(); ++i) - { + } + bv.push_back(ReadVChunkListRAM(block, new std::vector)); + bv.back().arr->push_back(chunkIdx); + return true; + } +}; + +// Disk +struct ReadVBlockListDisk +{ + std::vector bv; + + void AddEntry(int blockIdx, int chunkIdx) + { + for (std::vector::iterator i = bv.begin(); i != bv.end(); ++i) + { if (i->block_idx == blockIdx) { - i->arr.push_back(chunkIdx); - return; + i->arr.push_back(chunkIdx); + return; } - } - bv.push_back(XrdFileCache::ReadVChunkListDisk(blockIdx)); - bv.back().arr.push_back(chunkIdx); - } - }; + } + bv.push_back(XrdFileCache::ReadVChunkListDisk(blockIdx)); + bv.back().arr.push_back(chunkIdx); + } +}; } using namespace XrdFileCache; @@ -80,127 +80,127 @@ using namespace XrdFileCache; int File::ReadV(const XrdOucIOVec *readV, int n) { - if ( ! isOpen()) - { - return m_io->GetInput()->ReadV(readV, n); - } - - TRACEF(Dump, "ReadV for " << n << " chunks."); - - if ( ! VReadValidate(readV, n)) - { - errno = EINVAL; - return -1; - } - - int bytesRead = 0; - - ReadVBlockListRAM blocks_to_process; - std::vector blks_processed; - ReadVBlockListDisk blocks_on_disk; - std::vector chunkVec; - DirectResponseHandler *direct_handler = 0; - - // XXXX The following call never fails (other than with out of mem exception). - // XXXX This should be implemented in PrepareBlockRequest(). - if ( ! VReadPreProcess(readV, n, blocks_to_process, blocks_on_disk, chunkVec)) - { - bytesRead = -1; - errno = ENOMEM; - } - - // issue a client read - - if (bytesRead >= 0) - { - if ( ! chunkVec.empty()) - { - direct_handler = new DirectResponseHandler(1); - m_io->GetInput()->ReadV(*direct_handler, &chunkVec[0], chunkVec.size()); - } - } - - // disk read - if (bytesRead >= 0) - { - int dr = VReadFromDisk(readV, n, blocks_on_disk); - if (dr < 0) - bytesRead = dr; - else - bytesRead += dr; - } - - // read from cached blocks - if (bytesRead >= 0) - { - int br = VReadProcessBlocks(readV, n, blocks_to_process.bv, blks_processed); - if (br < 0) - bytesRead = br; - else - bytesRead += br; - } - - // check direct requests have arrived, get bytes read from read handle - if (bytesRead >= 0 && direct_handler != 0) - { - XrdSysCondVarHelper _lck(direct_handler->m_cond); - - while (direct_handler->m_to_wait > 0) - { - direct_handler->m_cond.Wait(); - } - - if (direct_handler->m_errno == 0) - { - for (std::vector::iterator i = chunkVec.begin(); i != chunkVec.end(); ++i) - { - bytesRead += i->size; - m_stats.m_BytesMissed += i->size; - } - } - else - { - errno = - direct_handler->m_errno; - bytesRead = -1; - } - } - - { - XrdSysCondVarHelper _lck(m_downloadCond); - - // decrease ref count on the remaining blocks - // this happens in case read process has been broke due to previous errors - for (std::vector::iterator i = blocks_to_process.bv.begin(); i != blocks_to_process.bv.end(); ++i) - dec_ref_count(i->block); - - for (std::vector::iterator i = blks_processed.begin(); i != blks_processed.end(); ++i) - dec_ref_count(i->block); - } - - // remove objects on heap - delete direct_handler; - for (std::vector::iterator i = blocks_to_process.bv.begin(); i != blocks_to_process.bv.end(); ++i) - delete i->arr; - for (std::vector::iterator i = blks_processed.begin(); i != blks_processed.end(); ++i) - delete i->arr; - - TRACEF(Dump, "VRead exit, total = " << bytesRead); - return bytesRead; + if ( ! isOpen()) + { + return m_io->GetInput()->ReadV(readV, n); + } + + TRACEF(Dump, "ReadV for " << n << " chunks."); + + if ( ! VReadValidate(readV, n)) + { + errno = EINVAL; + return -1; + } + + int bytesRead = 0; + + ReadVBlockListRAM blocks_to_process; + std::vector blks_processed; + ReadVBlockListDisk blocks_on_disk; + std::vector chunkVec; + DirectResponseHandler *direct_handler = 0; + + // XXXX The following call never fails (other than with out of mem exception). + // XXXX This should be implemented in PrepareBlockRequest(). + if ( ! VReadPreProcess(readV, n, blocks_to_process, blocks_on_disk, chunkVec)) + { + bytesRead = -1; + errno = ENOMEM; + } + + // issue a client read + + if (bytesRead >= 0) + { + if ( ! chunkVec.empty()) + { + direct_handler = new DirectResponseHandler(1); + m_io->GetInput()->ReadV(*direct_handler, &chunkVec[0], chunkVec.size()); + } + } + + // disk read + if (bytesRead >= 0) + { + int dr = VReadFromDisk(readV, n, blocks_on_disk); + if (dr < 0) + bytesRead = dr; + else + bytesRead += dr; + } + + // read from cached blocks + if (bytesRead >= 0) + { + int br = VReadProcessBlocks(readV, n, blocks_to_process.bv, blks_processed); + if (br < 0) + bytesRead = br; + else + bytesRead += br; + } + + // check direct requests have arrived, get bytes read from read handle + if (bytesRead >= 0 && direct_handler != 0) + { + XrdSysCondVarHelper _lck(direct_handler->m_cond); + + while (direct_handler->m_to_wait > 0) + { + direct_handler->m_cond.Wait(); + } + + if (direct_handler->m_errno == 0) + { + for (std::vector::iterator i = chunkVec.begin(); i != chunkVec.end(); ++i) + { + bytesRead += i->size; + m_stats.m_BytesMissed += i->size; + } + } + else + { + errno = -direct_handler->m_errno; + bytesRead = -1; + } + } + + { + XrdSysCondVarHelper _lck(m_downloadCond); + + // decrease ref count on the remaining blocks + // this happens in case read process has been broke due to previous errors + for (std::vector::iterator i = blocks_to_process.bv.begin(); i != blocks_to_process.bv.end(); ++i) + dec_ref_count(i->block); + + for (std::vector::iterator i = blks_processed.begin(); i != blks_processed.end(); ++i) + dec_ref_count(i->block); + } + + // remove objects on heap + delete direct_handler; + for (std::vector::iterator i = blocks_to_process.bv.begin(); i != blocks_to_process.bv.end(); ++i) + delete i->arr; + for (std::vector::iterator i = blks_processed.begin(); i != blks_processed.end(); ++i) + delete i->arr; + + TRACEF(Dump, "VRead exit, total = " << bytesRead); + return bytesRead; } //------------------------------------------------------------------------------ bool File::VReadValidate(const XrdOucIOVec *vr, int n) { - for (int i = 0; i < n; ++i) - { - if (vr[i].offset < 0 || vr[i].offset >= m_fileSize || - vr[i].offset + vr[i].size > m_fileSize) - { - return false; - } - } - return true; + for (int i = 0; i < n; ++i) + { + if (vr[i].offset < 0 || vr[i].offset >= m_fileSize || + vr[i].offset + vr[i].size > m_fileSize) + { + return false; + } + } + return true; } //------------------------------------------------------------------------------ @@ -210,105 +210,105 @@ bool File::VReadPreProcess(const XrdOucIOVec *readV, int n, ReadVBlockListDisk &blocks_on_disk, std::vector &chunkVec) { - BlockList_t blks_to_request; - - m_downloadCond.Lock(); - - for (int iov_idx = 0; iov_idx < n; iov_idx++) - { - const int blck_idx_first = readV[iov_idx].offset / m_cfi.GetBufferSize(); - const int blck_idx_last = (readV[iov_idx].offset + readV[iov_idx].size - 1) / m_cfi.GetBufferSize(); - - for (int block_idx = blck_idx_first; block_idx <= blck_idx_last; ++block_idx) - { - TRACEF(Dump, "VReadPreProcess chunk "<< readV[iov_idx].size << "@"<< readV[iov_idx].offset); - - BlockMap_i bi = m_block_map.find(block_idx); - if (bi != m_block_map.end()) - { - if (blocks_to_process.AddEntry(bi->second, iov_idx)) - inc_ref_count(bi->second); - - TRACEF(Dump, "VReadPreProcess block "<< block_idx <<" in map"); - } - else if (m_cfi.TestBit(offsetIdx(block_idx))) - { - blocks_on_disk.AddEntry(block_idx, iov_idx); - - TRACEF(Dump, "VReadPreProcess block "<< block_idx <<" , chunk idx = " << iov_idx << " on disk"); - } - else - { - if (Cache::GetInstance().RequestRAMBlock()) + BlockList_t blks_to_request; + + m_downloadCond.Lock(); + + for (int iov_idx = 0; iov_idx < n; iov_idx++) + { + const int blck_idx_first = readV[iov_idx].offset / m_cfi.GetBufferSize(); + const int blck_idx_last = (readV[iov_idx].offset + readV[iov_idx].size - 1) / m_cfi.GetBufferSize(); + + for (int block_idx = blck_idx_first; block_idx <= blck_idx_last; ++block_idx) + { + TRACEF(Dump, "VReadPreProcess chunk "<< readV[iov_idx].size << "@"<< readV[iov_idx].offset); + + BlockMap_i bi = m_block_map.find(block_idx); + if (bi != m_block_map.end()) + { + if (blocks_to_process.AddEntry(bi->second, iov_idx)) + inc_ref_count(bi->second); + + TRACEF(Dump, "VReadPreProcess block "<< block_idx <<" in map"); + } + else if (m_cfi.TestBit(offsetIdx(block_idx))) { - Block *b = PrepareBlockRequest(block_idx, false); - // MT XXX this can not fail (other than out of memory which we don't handle). - if (!b) return false; - inc_ref_count(b); - blocks_to_process.AddEntry(b, iov_idx); - blks_to_request.push_back(b); - - TRACEF(Dump, "VReadPreProcess request block " << block_idx); + blocks_on_disk.AddEntry(block_idx, iov_idx); + + TRACEF(Dump, "VReadPreProcess block "<< block_idx <<" , chunk idx = " << iov_idx << " on disk"); } else { - long long off; // offset in user buffer - long long blk_off; // offset in block - long long size; // size to copy - const long long BS = m_cfi.GetBufferSize(); - overlap(block_idx, BS, readV[iov_idx].offset, readV[iov_idx].size, off, blk_off, size); - chunkVec.push_back(XrdOucIOVec2(readV[iov_idx].data+off, BS*block_idx + blk_off,size)); - - TRACEF(Dump, "VReadPreProcess direct read " << block_idx); + if (Cache::GetInstance().RequestRAMBlock()) + { + Block *b = PrepareBlockRequest(block_idx, false); + // MT XXX this can not fail (other than out of memory which we don't handle). + if (! b) return false; + inc_ref_count(b); + blocks_to_process.AddEntry(b, iov_idx); + blks_to_request.push_back(b); + + TRACEF(Dump, "VReadPreProcess request block " << block_idx); + } + else + { + long long off; // offset in user buffer + long long blk_off; // offset in block + long long size; // size to copy + const long long BS = m_cfi.GetBufferSize(); + overlap(block_idx, BS, readV[iov_idx].offset, readV[iov_idx].size, off, blk_off, size); + chunkVec.push_back(XrdOucIOVec2(readV[iov_idx].data+off, BS*block_idx + blk_off,size)); + + TRACEF(Dump, "VReadPreProcess direct read " << block_idx); + } } - } - } - } + } + } - m_downloadCond.UnLock(); + m_downloadCond.UnLock(); - ProcessBlockRequests(blks_to_request); + ProcessBlockRequests(blks_to_request); - return true; + return true; } //------------------------------------------------------------------------------ int File::VReadFromDisk(const XrdOucIOVec *readV, int n, ReadVBlockListDisk& blocks_on_disk) { - int bytes_read = 0; - for (std::vector::iterator bit = blocks_on_disk.bv.begin(); bit != blocks_on_disk.bv.end(); ++bit ) - { - int blockIdx = bit->block_idx; - for (std::vector::iterator chunkIt = bit->arr.begin(); chunkIt != bit->arr.end(); ++chunkIt) - { - int chunkIdx = *chunkIt; - - long long off; // offset in user buffer - long long blk_off; // offset in block - long long size; // size to copy - - TRACEF(Dump, "VReadFromDisk block= " << blockIdx <<" chunk=" << chunkIdx); - - overlap(blockIdx, m_cfi.GetBufferSize(), readV[chunkIdx].offset, readV[chunkIdx].size, off, blk_off, size); - - int rs = m_output->Read(readV[chunkIdx].data + off, blockIdx*m_cfi.GetBufferSize() + blk_off - m_offset, size); - if (rs >=0) - { - bytes_read += rs; - m_stats.m_BytesDisk += rs; - } - else - { - // ofs read should set the errno - TRACEF(Error, "VReadFromDisk FAILED block=" << blockIdx << " chunk=" << chunkIdx << " off= " << off << " blk_off=" << blk_off << " size = " << size << "chunOff " << readV[chunkIdx].offset); - - return -1; - } - } - } - - return bytes_read; + int bytes_read = 0; + for (std::vector::iterator bit = blocks_on_disk.bv.begin(); bit != blocks_on_disk.bv.end(); ++bit ) + { + int blockIdx = bit->block_idx; + for (std::vector::iterator chunkIt = bit->arr.begin(); chunkIt != bit->arr.end(); ++chunkIt) + { + int chunkIdx = *chunkIt; + + long long off; // offset in user buffer + long long blk_off; // offset in block + long long size; // size to copy + + TRACEF(Dump, "VReadFromDisk block= " << blockIdx <<" chunk=" << chunkIdx); + + overlap(blockIdx, m_cfi.GetBufferSize(), readV[chunkIdx].offset, readV[chunkIdx].size, off, blk_off, size); + + int rs = m_output->Read(readV[chunkIdx].data + off, blockIdx*m_cfi.GetBufferSize() + blk_off - m_offset, size); + if (rs >=0) + { + bytes_read += rs; + m_stats.m_BytesDisk += rs; + } + else + { + // ofs read should set the errno + TRACEF(Error, "VReadFromDisk FAILED block=" << blockIdx << " chunk=" << chunkIdx << " off= " << off << " blk_off=" << blk_off << " size = " << size << "chunOff " << readV[chunkIdx].offset); + + return -1; + } + } + } + + return bytes_read; } //------------------------------------------------------------------------------ @@ -317,68 +317,68 @@ int File::VReadProcessBlocks(const XrdOucIOVec *readV, int n, std::vector& blocks_to_process, std::vector& blocks_processed) { - int bytes_read = 0; - while ((! blocks_to_process.empty()) && (bytes_read >= 0)) - { - std::vector finished; - { - XrdSysCondVarHelper _lck(m_downloadCond); - std::vector::iterator bi = blocks_to_process.begin(); - while (bi != blocks_to_process.end()) - { - if (bi->block->is_finished()) + int bytes_read = 0; + while ((! blocks_to_process.empty()) && (bytes_read >= 0)) + { + std::vector finished; + { + XrdSysCondVarHelper _lck(m_downloadCond); + std::vector::iterator bi = blocks_to_process.begin(); + while (bi != blocks_to_process.end()) { - finished.push_back(ReadVChunkListRAM(bi->block, bi->arr)); - // Here we rely on the fact that std::vector does not reallocate on erase! - blocks_to_process.erase(bi); + if (bi->block->is_finished()) + { + finished.push_back(ReadVChunkListRAM(bi->block, bi->arr)); + // Here we rely on the fact that std::vector does not reallocate on erase! + blocks_to_process.erase(bi); + } + else + { + ++bi; + } } - else + + if (finished.empty()) { - ++bi; + m_downloadCond.Wait(); + continue; } - } - - if (finished.empty()) - { - m_downloadCond.Wait(); - continue; - } - } - - std::vector::iterator bi = finished.begin(); - while (bi != finished.end()) - { - if (bi->block->is_ok()) - { - for (std::vector::iterator chunkIt = bi->arr->begin(); chunkIt < bi->arr->end(); ++chunkIt) + } + + std::vector::iterator bi = finished.begin(); + while (bi != finished.end()) + { + if (bi->block->is_ok()) { - long long off; // offset in user buffer - long long blk_off; // offset in block - long long size; // size to copy - - int block_idx =bi->block->m_offset/m_cfi.GetBufferSize(); - overlap(block_idx, m_cfi.GetBufferSize(), readV[*chunkIt].offset, readV[*chunkIt].size, off, blk_off, size); - memcpy(readV[*chunkIt].data + off, &(bi->block->m_buff[blk_off]), size); - bytes_read += size; - m_stats.m_BytesRam += size; + for (std::vector::iterator chunkIt = bi->arr->begin(); chunkIt < bi->arr->end(); ++chunkIt) + { + long long off; // offset in user buffer + long long blk_off; // offset in block + long long size; // size to copy + + int block_idx = bi->block->m_offset/m_cfi.GetBufferSize(); + overlap(block_idx, m_cfi.GetBufferSize(), readV[*chunkIt].offset, readV[*chunkIt].size, off, blk_off, size); + memcpy(readV[*chunkIt].data + off, &(bi->block->m_buff[blk_off]), size); + bytes_read += size; + m_stats.m_BytesRam += size; + } + } + else + { + bytes_read = -1; + errno = -bi->block->m_errno; + break; } - } - else - { - bytes_read = -1; - errno = - bi->block->m_errno; - break; - } - ++bi; - } + ++bi; + } - // add finished to processed list - std::copy(finished.begin(), finished.end(), std::back_inserter(blocks_processed)); - finished.clear(); - } + // add finished to processed list + std::copy(finished.begin(), finished.end(), std::back_inserter(blocks_processed)); + finished.clear(); + } - TRACEF(Dump, "VReadProcessBlocks total read " << bytes_read); + TRACEF(Dump, "VReadProcessBlocks total read " << bytes_read); - return bytes_read; -} + return bytes_read; +} \ No newline at end of file