CMS 3D CMS Logo

DCacheFile.cc

Go to the documentation of this file.
00001 #include "Utilities/DCacheAdaptor/interface/DCacheFile.h"
00002 #include "FWCore/Utilities/interface/Exception.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 #include <unistd.h>
00005 #include <fcntl.h>
00006 #include <dcap.h>
00007 
00008 DCacheFile::DCacheFile (void)
00009   : m_fd (EDM_IOFD_INVALID),
00010     m_close (false)
00011 {}
00012 
00013 DCacheFile::DCacheFile (IOFD fd)
00014   : m_fd (fd),
00015     m_close (true)
00016 {}
00017 
00018 DCacheFile::DCacheFile (const char *name,
00019             int flags /* = IOFlags::OpenRead */,
00020             int perms /* = 066 */)
00021   : m_fd (EDM_IOFD_INVALID),
00022     m_close (false)
00023 { open (name, flags, perms); }
00024 
00025 DCacheFile::DCacheFile (const std::string &name,
00026             int flags /* = IOFlags::OpenRead */,
00027             int perms /* = 066 */)
00028   : m_fd (EDM_IOFD_INVALID),
00029     m_close (false)
00030 { open (name.c_str (), flags, perms); }
00031 
00032 DCacheFile::~DCacheFile (void)
00033 {
00034   if (m_close)
00035     edm::LogError("DCacheFileError")
00036       << "Destructor called on dCache file '" << m_name
00037       << "' but the file is still open";
00038 }
00039 
00041 void
00042 DCacheFile::create (const char *name,
00043                     bool exclusive /* = false */,
00044                     int perms /* = 066 */)
00045 {
00046   open (name,
00047         (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00048          | (exclusive ? IOFlags::OpenExclusive : 0)),
00049         perms);
00050 }
00051 
00052 void
00053 DCacheFile::create (const std::string &name,
00054                     bool exclusive /* = false */,
00055                     int perms /* = 066 */)
00056 {
00057   open (name.c_str (),
00058         (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00059          | (exclusive ? IOFlags::OpenExclusive : 0)),
00060         perms);
00061 }
00062 
00063 void
00064 DCacheFile::open (const std::string &name,
00065                   int flags /* = IOFlags::OpenRead */,
00066                   int perms /* = 066 */)
00067 { open (name.c_str (), flags, perms); }
00068 
00069 void
00070 DCacheFile::open (const char *name,
00071                   int flags /* = IOFlags::OpenRead */,
00072                   int perms /* = 066 */)
00073 {
00074   m_name = name;
00075 
00076   // Actual open
00077   if ((name == 0) || (*name == 0))
00078     throw cms::Exception("DCacheFile::open()")
00079       << "Cannot open a file without a name";
00080 
00081   if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0)
00082     throw cms::Exception("DCacheFile::open()")
00083       << "Must open file '" << name << "' at least for read or write";
00084 
00085   // If I am already open, close old file first
00086   if (m_fd != EDM_IOFD_INVALID && m_close)
00087     close ();
00088 
00089   // Translate our flags to system flags
00090   int openflags = 0;
00091 
00092   if ((flags & IOFlags::OpenRead) && (flags & IOFlags::OpenWrite))
00093     openflags |= O_RDWR;
00094   else if (flags & IOFlags::OpenRead)
00095     openflags |= O_RDONLY;
00096   else if (flags & IOFlags::OpenWrite)
00097     openflags |= O_WRONLY;
00098 
00099   if (flags & IOFlags::OpenNonBlock)
00100     openflags |= O_NONBLOCK;
00101 
00102   if (flags & IOFlags::OpenAppend)
00103     openflags |= O_APPEND;
00104 
00105   if (flags & IOFlags::OpenCreate)
00106     openflags |= O_CREAT;
00107 
00108   if (flags & IOFlags::OpenExclusive)
00109     openflags |= O_EXCL;
00110 
00111   if (flags & IOFlags::OpenTruncate)
00112     openflags |= O_TRUNC;
00113 
00114   IOFD newfd = EDM_IOFD_INVALID;
00115   dc_errno = 0;
00116   if ((newfd = dc_open (name, openflags, perms)) == -1)
00117     throw cms::Exception("DCacheFile::open()")
00118       << "dc_open(name='" << name
00119       << "', flags=0x" << std::hex << openflags
00120       << ", permissions=0" << std::oct << perms << std::dec
00121       << ") => error '" << dc_strerror(dc_errno)
00122       << "' (dc_errno=" << dc_errno << ")";
00123 
00124   m_fd = newfd;
00125 
00126   // Turn off read-ahead, or adjust read-ahead size depending on
00127   // whether buffering has been requested.  This is a very tricky
00128   // balance here.  Without read-ahead data processing appears to
00129   // become exceedingly slow, and with default (1MB) read-ahead
00130   // it appears to saturate disk servers and network.  Try tread
00131   // reasonable middle ground here.
00132   if (flags & IOFlags::OpenUnbuffered)
00133     dc_noBuffering(m_fd);
00134   else
00135     dc_setBufferSize(m_fd, 64000);
00136 
00137   m_close = true;
00138 
00139   edm::LogInfo("DCacheFileInfo") << "Opened " << m_name;
00140 }
00141 
00142 void
00143 DCacheFile::close (void)
00144 {
00145   if (m_fd == EDM_IOFD_INVALID)
00146   {
00147     edm::LogError("DCacheFileError")
00148       << "DCacheFile::close(name='" << m_name
00149       << "') called but the file is not open";
00150     m_close = false;
00151     return;
00152   }
00153 
00154   dc_errno = 0;
00155   if (dc_close (m_fd) == -1)
00156     edm::LogWarning("DCacheFileWarning")
00157       << "dc_close(name='" << m_name
00158       << "') failed with error '" << dc_strerror (dc_errno)
00159       << "' (dc_errno=" << dc_errno << ")";
00160 
00161   m_close = false;
00162   m_fd = EDM_IOFD_INVALID;
00163 
00164   // Caused hang.  Will be added back after problem is fixed.
00165   // edm::LogInfo("DCacheFileInfo") << "Closed " << m_name;
00166 }
00167 
00168 void
00169 DCacheFile::abort (void)
00170 {
00171   if (m_fd != EDM_IOFD_INVALID)
00172     dc_close (m_fd);
00173 
00174   m_close = false;
00175   m_fd = EDM_IOFD_INVALID;
00176 }
00177 
00179 static const int BUGLINE = __LINE__ + 1;
00180 // Apparently dc_read can return short reads; I don't know if dc_write
00181 // will also return short writes.  This is a bug in dCache.  POSIX,
00182 // apparently contrary to the understanding of dCache authors, does
00183 // not allow reads from files to return short, and in fact no network
00184 // file system returns short reads.  For more details please refer to
00185 // https://www.opengroup.org/onlinepubs/000095399/functions/read.html:
00186 //    The value returned may be less than nbyte if the number of
00187 //    bytes left in the file is less than nbyte, if the read()
00188 //    request was interrupted by a signal, or if the file is a
00189 //    pipe or FIFO or special file and has fewer than nbyte bytes
00190 //    immediately available for reading.
00191 // (In other words, barring signals (which should use SA_RESTART and
00192 // in any case should not affect dCache) the only way a read from a
00193 // file can return short is when there is nothing left to read.)
00194 IOSize
00195 DCacheFile::read (void *into, IOSize n)
00196 {
00197   IOSize done = 0;
00198   while (done < n)
00199   {
00200     dc_errno = 0;
00201     ssize_t s = dc_read (m_fd, (char *) into + done, n - done);
00202     if (s == -1)
00203       throw cms::Exception("DCacheFile::read()")
00204         << "dc_read(name='" << m_name << "', n=" << (n-done)
00205         << ") failed with error '" << dc_strerror(dc_errno)
00206         << "' (dc_errno=" << dc_errno << ")";
00207     else if (s == 0)
00208       // end of file
00209       break;
00210     else if (s < ssize_t (n-done))
00211       edm::LogInfo("DCacheFileWarning")
00212         << "dc_read(name='" << m_name << "', n=" << (n-done)
00213         << ") returned a short read of " << s << " bytes; "
00214         << "please report a bug in dCache referencing the "
00215         << "comment on line " << BUGLINE << " of " << __FILE__;
00216     done += s;
00217   }
00218 
00219   return done;
00220 }
00221 
00222 IOSize
00223 DCacheFile::write (const void *from, IOSize n)
00224 {
00225   IOSize done = 0;
00226   while (done < n)
00227   {
00228     dc_errno = 0;
00229     ssize_t s = dc_write (m_fd, (const char *) from + done, n - done);
00230     if (s == -1)
00231       throw cms::Exception("DCacheFile::write()")
00232         << "dc_write(name='" << m_name << "', n=" << (n-done)
00233         << ") failed with error '" << dc_strerror(dc_errno)
00234         << "' (dc_errno=" << dc_errno << ")";
00235     else if (s < ssize_t (n-done))
00236       edm::LogInfo("DCacheFileWarning")
00237         << "dc_write(name='" << m_name << "', n=" << (n-done)
00238         << ") returned a short write of " << s << " bytes; "
00239         << "please report a bug in dCache referencing the "
00240         << "comment on line " << BUGLINE << " of " << __FILE__;
00241     done += s;
00242   }
00243 
00244   return done;
00245 }
00246 
00250 IOOffset
00251 DCacheFile::position (IOOffset offset, Relative whence /* = SET */)
00252 {
00253   if (m_fd == EDM_IOFD_INVALID)
00254     throw cms::Exception("DCacheFile::position()")
00255       << "DCacheFile::position() called on a closed file";
00256   if (whence != CURRENT && whence != SET && whence != END)
00257     throw cms::Exception("DCacheFile::position()")
00258       << "DCacheFile::position() called with incorrect 'whence' parameter";
00259 
00260   IOOffset      result;
00261   int           mywhence = (whence == SET ? SEEK_SET
00262                             : whence == CURRENT ? SEEK_CUR
00263                             : SEEK_END);
00264 
00265   dc_errno = 0;
00266   if ((result = dc_lseek64 (m_fd, offset, mywhence)) == -1)
00267     throw cms::Exception("DCacheFile::position()")
00268       << "dc_lseek64(name='" << m_name << "', offset=" << offset
00269       << ", whence=" << mywhence << ") failed with error '"
00270       << dc_strerror (dc_errno) << "' (dc_errno=" << dc_errno << ")";
00271 
00272   // FIXME: dCache returns incorrect value on SEEK_END.
00273   // Remove this hack when dcap has been fixed.
00274   if (whence == SEEK_END && (result = dc_lseek64 (m_fd, result, SEEK_SET)) == -1)
00275     throw cms::Exception("DCacheFile::position()")
00276       << "dc_lseek64(name='" << m_name << "', offset=" << offset
00277       << ", whence=" << SEEK_SET << ") failed with error '"
00278       << dc_strerror (dc_errno) << "' (dc_errno=" << dc_errno << ")";
00279   
00280   return result;
00281 }
00282 
00283 void
00284 DCacheFile::resize (IOOffset /* size */)
00285 {
00286   throw cms::Exception("DCacheFile::resize()")
00287     << "DCacheFile::resize(name='" << m_name << "') not implemented";
00288 }

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