CMS 3D CMS Logo

LocalCacheFile.cc

Go to the documentation of this file.
00001 #include "Utilities/StorageFactory/interface/LocalCacheFile.h"
00002 #include "Utilities/StorageFactory/interface/File.h"
00003 #include "FWCore/Utilities/interface/EDMException.h"
00004 #include <utility>
00005 #include <iostream>
00006 #include <stdlib.h>
00007 #include <string.h>
00008 #include <unistd.h>
00009 #include <sys/mman.h>
00010 #include <errno.h>
00011 
00012 static const IOOffset CHUNK_SIZE = 128*1024*1024;
00013 
00014 static void
00015 nowrite(const char *why)
00016 {
00017   throw cms::Exception("LocalCacheFile")
00018     << "Cannot change file but operation '" << why << "' was called";
00019 }
00020 
00021 
00022 LocalCacheFile::LocalCacheFile(Storage *base, const std::string &tmpdir /* = "" */)
00023   : image_(base->size()),
00024     file_(0),
00025     storage_(base)
00026 {
00027   present_.resize((image_ + CHUNK_SIZE - 1) / CHUNK_SIZE, 0);
00028 
00029   std::string pattern(tmpdir);
00030   if (pattern.empty())
00031     if (char *p = getenv("TMPDIR"))
00032       pattern = p;
00033   if (pattern.empty())
00034     pattern = "/tmp";
00035   pattern += "/cmssw-shadow-XXXXXX";
00036 
00037   std::vector<char> temp(pattern.c_str(), pattern.c_str()+pattern.size()+1);
00038   int fd = mkstemp(&temp[0]);
00039   if (fd == -1)
00040     throw cms::Exception("LocalCacheFile")
00041       << "Cannot create temporary file '" << pattern << "': "
00042       << strerror(errno) << " (error " << errno << ")";
00043 
00044   unlink(&temp[0]);
00045   file_ = new File(fd);
00046   file_->resize(image_);
00047 }
00048 
00049 LocalCacheFile::~LocalCacheFile(void)
00050 {
00051   delete file_;
00052   delete storage_;
00053 }
00054 
00055 void
00056 LocalCacheFile::cache(IOOffset start, IOOffset end)
00057 {
00058   start = (start / CHUNK_SIZE) * CHUNK_SIZE;
00059   end = std::min(end, image_);
00060 
00061   IOSize nread = 0;
00062   IOSize index = start / CHUNK_SIZE;
00063 
00064   while (start < end)
00065   {
00066     IOSize len = std::min(image_ - start, CHUNK_SIZE);
00067     if (! present_[index])
00068     {
00069       void *window = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, file_->fd(), start);
00070       if (window == MAP_FAILED)
00071         throw cms::Exception("LocalCacheFile")
00072           << "Unable to map a window of local cache file: "
00073           << strerror(errno) << " (error " << errno << ")";
00074 
00075       try
00076       {
00077         nread = storage_->read(window, len, start);
00078       }
00079       catch (cms::Exception &e)
00080       {
00081         munmap(window, len);
00082         throw cms::Exception("LocalCacheFile")
00083           << "Unable to cache " << len << " byte file segment at " << start
00084           << ": " << e.what();
00085       }
00086 
00087       munmap(window, len);
00088 
00089       if (nread != len)
00090         throw cms::Exception("LocalCacheFile")
00091           << "Unable to cache " << len << " byte file segment at " << start
00092           << ": got only " << nread << " bytes back";
00093 
00094       present_[index] = 1;
00095     }
00096 
00097     start += len;
00098     ++index;
00099   }
00100 }
00101 
00102 IOSize
00103 LocalCacheFile::read(void *into, IOSize n)
00104 {
00105   IOOffset here = file_->position();
00106   cache(here, here + n);
00107 
00108   return file_->read(into, n);
00109 }
00110 
00111 IOSize
00112 LocalCacheFile::read(void *into, IOSize n, IOOffset pos)
00113 {
00114   cache(pos, pos + n);
00115   return file_->read(into, n, pos);
00116 }
00117 
00118 IOSize
00119 LocalCacheFile::readv(IOBuffer *into, IOSize n)
00120 {
00121   IOOffset start = file_->position();
00122   IOOffset end = start;
00123   for (IOSize i = 0; i < n; ++i)
00124     end += into[i].size();
00125   cache(start, end);
00126 
00127   return file_->readv(into, n);
00128 }
00129 
00130 IOSize
00131 LocalCacheFile::readv(IOPosBuffer *into, IOSize n)
00132 {
00133   for (IOSize i = 0; i < n; ++i)
00134   {
00135     IOOffset start = into[i].offset();
00136     IOOffset end = start + into[i].size();
00137     cache(start, end);
00138   }
00139 
00140   return storage_->readv(into, n);
00141 }
00142 
00143 IOSize
00144 LocalCacheFile::write(const void *from, IOSize n)
00145 { nowrite("write"); return 0; }
00146 
00147 IOSize
00148 LocalCacheFile::write(const void *from, IOSize n, IOOffset pos)
00149 { nowrite("write"); return 0; }
00150 
00151 IOSize
00152 LocalCacheFile::writev(const IOBuffer *from, IOSize n)
00153 { nowrite("writev"); return 0; }
00154 
00155 IOSize
00156 LocalCacheFile::writev(const IOPosBuffer *from, IOSize n)
00157 { nowrite("writev"); return 0; }
00158 
00159 IOOffset
00160 LocalCacheFile::position(IOOffset offset, Relative whence)
00161 { return file_->position(offset, whence); }
00162 
00163 void
00164 LocalCacheFile::resize(IOOffset size)
00165 { nowrite("resize"); }
00166 
00167 void
00168 LocalCacheFile::flush(void)
00169 { nowrite("flush"); }
00170 
00171 void
00172 LocalCacheFile::close(void)
00173 {
00174   storage_->close();
00175   file_->close();
00176 }
00177 
00178 bool
00179 LocalCacheFile::prefetch(const IOPosBuffer *what, IOSize n)
00180 {
00181   for (IOSize i = 0; i < n; ++i)
00182   {
00183     IOOffset start = what[i].offset();
00184     IOOffset end = start + what[i].size();
00185     cache(start, end);
00186   }
00187   
00188   return file_->prefetch(what, n);
00189 }

Generated on Tue Jun 9 17:48:53 2009 for CMSSW by  doxygen 1.5.4