diff --git a/[refs] b/[refs] index 8ae13611a234a..09b5fef92bf6d 100644 --- a/[refs] +++ b/[refs] @@ -1,3 +1,3 @@ --- refs/heads/gh-pages: ac155dadd83efa75cad55c0508a57a2b9dd3d66c -"refs/heads/CMSSW_7_1_X": 4797eccd42d4cf15638cf44dddb37faf1e97f1c4 +"refs/heads/CMSSW_7_1_X": 341ba6c01d00fb5eb89bc9658a0c17d301dbeefd diff --git a/trunk/Utilities/StorageFactory/interface/LocalCacheFile.h b/trunk/Utilities/StorageFactory/interface/LocalCacheFile.h new file mode 100644 index 0000000000000..6add850717600 --- /dev/null +++ b/trunk/Utilities/StorageFactory/interface/LocalCacheFile.h @@ -0,0 +1,43 @@ +#ifndef STORAGE_FACTORY_LOCAL_CACHE_FILE_H +# define STORAGE_FACTORY_LOCAL_CACHE_FILE_H + +# include "Utilities/StorageFactory/interface/Storage.h" +# include "Utilities/StorageFactory/interface/File.h" +# include +# include + +/** Proxy class to copy a file locally in large chunks. */ +class LocalCacheFile : public Storage +{ +public: + LocalCacheFile (Storage *base); + ~LocalCacheFile (void); + + using Storage::read; + using Storage::write; + + virtual bool prefetch (const IOPosBuffer *what, IOSize n); + virtual IOSize read (void *into, IOSize n); + virtual IOSize read (void *into, IOSize n, IOOffset pos); + virtual IOSize readv (IOBuffer *into, IOSize n); + virtual IOSize readv (IOPosBuffer *into, IOSize n); + virtual IOSize write (const void *from, IOSize n); + virtual IOSize write (const void *from, IOSize n, IOOffset pos); + virtual IOSize writev (const IOBuffer *from, IOSize n); + virtual IOSize writev (const IOPosBuffer *from, IOSize n); + + virtual IOOffset position (IOOffset offset, Relative whence = SET); + virtual void resize (IOOffset size); + virtual void flush (void); + virtual void close (void); + +private: + void cache (IOOffset start, IOOffset end); + + IOOffset image_; + std::vector present_; + File *file_; + Storage *storage_; +}; + +#endif // STORAGE_FACTORY_LOCAL_CACHE_FILE_H diff --git a/trunk/Utilities/StorageFactory/src/LocalCacheFile.cc b/trunk/Utilities/StorageFactory/src/LocalCacheFile.cc new file mode 100644 index 0000000000000..cd820eaa7bc43 --- /dev/null +++ b/trunk/Utilities/StorageFactory/src/LocalCacheFile.cc @@ -0,0 +1,183 @@ +#include "Utilities/StorageFactory/interface/LocalCacheFile.h" +#include "Utilities/StorageFactory/interface/File.h" +#include "FWCore/Utilities/interface/EDMException.h" +#include +#include +#include +#include +#include +#include +#include + +static const IOOffset CHUNK_SIZE = 128*1024*1024; + +static void +nowrite(const char *why) +{ + throw cms::Exception("LocalCacheFile") + << "Cannot change file but operation '" << why << "' was called"; +} + + +LocalCacheFile::LocalCacheFile(Storage *base) + : image_(base->size()), + file_(0), + storage_(base) +{ + present_.resize((image_ + CHUNK_SIZE - 1) / CHUNK_SIZE, false); + + std::string pattern("/tmp"); + if (char *p = getenv("TMPDIR")) + pattern = p; + pattern += "/cmssw-shadow-XXXXXX"; + + std::vector temp(pattern.c_str(), pattern.c_str()+pattern.size()+1); + int fd = mkstemp(&temp[0]); + if (fd == -1) + throw cms::Exception("LocalCacheFile") + << "Cannot create temporary file '" << pattern << "': " + << strerror(errno) << " (error " << errno << ")"; + + unlink(&temp[0]); + file_ = new File(fd); + file_->resize(image_); +} + +LocalCacheFile::~LocalCacheFile(void) +{ + delete file_; + delete storage_; +} + +void +LocalCacheFile::cache(IOOffset start, IOOffset end) +{ + start = (start / CHUNK_SIZE) * CHUNK_SIZE; + end = std::min(end, image_); + while (start < end) + { + IOSize nread = 0; + IOSize index = start / CHUNK_SIZE; + IOSize len = std::min(image_ - start, CHUNK_SIZE); + if (! present_[index]) + { + void *window = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, file_->fd(), start); + if (window == MAP_FAILED) + throw cms::Exception("LocalCacheFile") + << "Unable to map a window of local cache file: " + << strerror(errno) << " (error " << errno << ")"; + + try + { + nread = storage_->read(window, len, start); + } + catch (cms::Exception &e) + { + munmap(window, len); + throw cms::Exception("LocalCacheFile") + << "Unable to cache " << len << " byte file segment at " << start + << ": " << e.what(); + } + + munmap(window, len); + + if (nread != len) + throw cms::Exception("LocalCacheFile") + << "Unable to cache " << len << " byte file segment at " << start + << ": got only " << nread << " bytes back"; + + present_[index] = true; + } + + start += len; + } +} + +IOSize +LocalCacheFile::read(void *into, IOSize n) +{ + IOOffset here = file_->position(); + cache(here, here + n); + + return file_->read(into, n); +} + +IOSize +LocalCacheFile::read(void *into, IOSize n, IOOffset pos) +{ + cache(pos, pos + n); + return file_->read(into, n, pos); +} + +IOSize +LocalCacheFile::readv(IOBuffer *into, IOSize n) +{ + IOOffset start = file_->position(); + IOOffset end = start; + for (IOSize i = 0; i < n; ++i) + end += into[i].size(); + cache(start, end); + + return file_->readv(into, n); +} + +IOSize +LocalCacheFile::readv(IOPosBuffer *into, IOSize n) +{ + for (IOSize i = 0; i < n; ++i) + { + IOOffset start = into[i].offset(); + IOOffset end = start + into[i].size(); + cache(start, end); + } + + return storage_->readv(into, n); +} + +IOSize +LocalCacheFile::write(const void *from, IOSize n) +{ nowrite("write"); return 0; } + +IOSize +LocalCacheFile::write(const void *from, IOSize n, IOOffset pos) +{ nowrite("write"); return 0; } + +IOSize +LocalCacheFile::writev(const IOBuffer *from, IOSize n) +{ nowrite("writev"); return 0; } + +IOSize +LocalCacheFile::writev(const IOPosBuffer *from, IOSize n) +{ nowrite("writev"); return 0; } + +IOOffset +LocalCacheFile::position(IOOffset offset, Relative whence) +{ return file_->position(offset, whence); } + +void +LocalCacheFile::resize(IOOffset size) +{ nowrite("resize"); } + +void +LocalCacheFile::flush(void) +{ nowrite("flush"); } + +void +LocalCacheFile::close(void) +{ + storage_->close(); + file_->close(); +} + +bool +LocalCacheFile::prefetch(const IOPosBuffer *what, IOSize n) +{ + for (IOSize i = 0; i < n; ++i) + { + IOOffset start = what[i].offset(); + IOOffset end = start + what[i].size(); + cache(start, end); + } + + return file_->prefetch(what, n); +}