CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/Utilities/StorageFactory/src/LocalCacheFile.cc

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