00001 #include "Utilities/DCacheAdaptor/interface/DCacheFile.h"
00002 #include "FWCore/Utilities/interface/Exception.h"
00003 #include "FWCore/Utilities/interface/EDMException.h"
00004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00005 #include <cassert>
00006 #include <vector>
00007 #include <unistd.h>
00008 #include <fcntl.h>
00009 #include <dcap.h>
00010
00011 DCacheFile::DCacheFile (void)
00012 : m_fd (EDM_IOFD_INVALID),
00013 m_close (false)
00014 {}
00015
00016 DCacheFile::DCacheFile (IOFD fd)
00017 : m_fd (fd),
00018 m_close (true)
00019 {}
00020
00021 DCacheFile::DCacheFile (const char *name,
00022 int flags ,
00023 int perms )
00024 : m_fd (EDM_IOFD_INVALID),
00025 m_close (false)
00026 { open (name, flags, perms); }
00027
00028 DCacheFile::DCacheFile (const std::string &name,
00029 int flags ,
00030 int perms )
00031 : m_fd (EDM_IOFD_INVALID),
00032 m_close (false)
00033 { open (name.c_str (), flags, perms); }
00034
00035 DCacheFile::~DCacheFile (void)
00036 {
00037 if (m_close)
00038 edm::LogError("DCacheFileError")
00039 << "Destructor called on dCache file '" << m_name
00040 << "' but the file is still open";
00041 }
00042
00044 void
00045 DCacheFile::create (const char *name,
00046 bool exclusive ,
00047 int perms )
00048 {
00049 open (name,
00050 (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00051 | (exclusive ? IOFlags::OpenExclusive : 0)),
00052 perms);
00053 }
00054
00055 void
00056 DCacheFile::create (const std::string &name,
00057 bool exclusive ,
00058 int perms )
00059 {
00060 open (name.c_str (),
00061 (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate
00062 | (exclusive ? IOFlags::OpenExclusive : 0)),
00063 perms);
00064 }
00065
00066 void
00067 DCacheFile::open (const std::string &name,
00068 int flags ,
00069 int perms )
00070 { open (name.c_str (), flags, perms); }
00071
00072 void
00073 DCacheFile::open (const char *name,
00074 int flags ,
00075 int perms )
00076 {
00077
00078 if ((name == 0) || (*name == 0)) {
00079 edm::Exception ex(edm::errors::FileOpenError);
00080 ex << "Cannot open a file without a name";
00081 ex.addContext("Calling DCacheFile::open()");
00082 throw ex;
00083 }
00084
00085 if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0) {
00086 edm::Exception ex(edm::errors::FileOpenError);
00087 ex << "Must open file '" << name << "' at least for read or write";
00088 ex.addContext("Calling DCacheFile::open()");
00089 throw ex;
00090 }
00091
00092
00093 if (m_fd != EDM_IOFD_INVALID && m_close)
00094 close ();
00095
00096
00097 int openflags = 0;
00098
00099 if ((flags & IOFlags::OpenRead) && (flags & IOFlags::OpenWrite))
00100 openflags |= O_RDWR;
00101 else if (flags & IOFlags::OpenRead)
00102 openflags |= O_RDONLY;
00103 else if (flags & IOFlags::OpenWrite)
00104 openflags |= O_WRONLY;
00105
00106 if (flags & IOFlags::OpenNonBlock)
00107 openflags |= O_NONBLOCK;
00108
00109 if (flags & IOFlags::OpenAppend)
00110 openflags |= O_APPEND;
00111
00112 if (flags & IOFlags::OpenCreate)
00113 openflags |= O_CREAT;
00114
00115 if (flags & IOFlags::OpenExclusive)
00116 openflags |= O_EXCL;
00117
00118 if (flags & IOFlags::OpenTruncate)
00119 openflags |= O_TRUNC;
00120
00121 IOFD newfd = EDM_IOFD_INVALID;
00122 dc_errno = 0;
00123 if ((newfd = dc_open (name, openflags, perms)) == -1) {
00124 edm::Exception ex(edm::errors::FileOpenError);
00125 ex << "dc_open(name='" << name
00126 << "', flags=0x" << std::hex << openflags
00127 << ", permissions=0" << std::oct << perms << std::dec
00128 << ") => error '" << dc_strerror(dc_errno)
00129 << "' (dc_errno=" << dc_errno << ")";
00130 ex.addContext("Calling DCacheFile::open()");
00131 throw ex;
00132 }
00133
00134 m_name = name;
00135 m_fd = newfd;
00136
00137
00138
00139
00140
00141
00142
00143 if (flags & IOFlags::OpenUnbuffered)
00144 dc_noBuffering(m_fd);
00145 else
00146 dc_setBufferSize(m_fd, 64000);
00147
00148 m_close = true;
00149
00150 edm::LogInfo("DCacheFileInfo") << "Opened " << m_name;
00151 }
00152
00153 void
00154 DCacheFile::close (void)
00155 {
00156 if (m_fd == EDM_IOFD_INVALID)
00157 {
00158 edm::LogError("DCacheFileError")
00159 << "DCacheFile::close(name='" << m_name
00160 << "') called but the file is not open";
00161 m_close = false;
00162 return;
00163 }
00164
00165 dc_errno = 0;
00166 if (dc_close (m_fd) == -1)
00167 edm::LogWarning("DCacheFileWarning")
00168 << "dc_close(name='" << m_name
00169 << "') failed with error '" << dc_strerror (dc_errno)
00170 << "' (dc_errno=" << dc_errno << ")";
00171
00172 m_close = false;
00173 m_fd = EDM_IOFD_INVALID;
00174
00175
00176
00177 }
00178
00179 void
00180 DCacheFile::abort (void)
00181 {
00182 if (m_fd != EDM_IOFD_INVALID)
00183 dc_close (m_fd);
00184
00185 m_close = false;
00186 m_fd = EDM_IOFD_INVALID;
00187 }
00188
00190 static const int BUGLINE = __LINE__ + 1;
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 IOSize
00206 DCacheFile::read (void *into, IOSize n)
00207 {
00208 IOSize done = 0;
00209 while (done < n)
00210 {
00211 dc_errno = 0;
00212 ssize_t s = dc_read (m_fd, (char *) into + done, n - done);
00213 if (s == -1) {
00214 edm::Exception ex(edm::errors::FileReadError);
00215 ex << "dc_read(name='" << m_name << "', n=" << (n-done)
00216 << ") failed with error '" << dc_strerror(dc_errno)
00217 << "' (dc_errno=" << dc_errno << ")";
00218 ex.addContext("Calling DCacheFile::read()");
00219 throw ex;
00220 }
00221 else if (s == 0)
00222
00223 break;
00224 else if (s < ssize_t (n-done))
00225 edm::LogInfo("DCacheFileWarning")
00226 << "dc_read(name='" << m_name << "', n=" << (n-done)
00227 << ") returned a short read of " << s << " bytes; "
00228 << "please report a bug in dCache referencing the "
00229 << "comment on line " << BUGLINE << " of " << __FILE__;
00230 done += s;
00231 }
00232
00233 return done;
00234 }
00235
00236 IOSize
00237 DCacheFile::write (const void *from, IOSize n)
00238 {
00239 IOSize done = 0;
00240 while (done < n)
00241 {
00242 dc_errno = 0;
00243 ssize_t s = dc_write (m_fd, (const char *) from + done, n - done);
00244 if (s == -1) {
00245 cms::Exception ex("FileWriteError");
00246 ex << "dc_write(name='" << m_name << "', n=" << (n-done)
00247 << ") failed with error '" << dc_strerror(dc_errno)
00248 << "' (dc_errno=" << dc_errno << ")";
00249 ex.addContext("Calling DCacheFile::write()");
00250 throw ex;
00251 }
00252 else if (s < ssize_t (n-done))
00253 edm::LogInfo("DCacheFileWarning")
00254 << "dc_write(name='" << m_name << "', n=" << (n-done)
00255 << ") returned a short write of " << s << " bytes; "
00256 << "please report a bug in dCache referencing the "
00257 << "comment on line " << BUGLINE << " of " << __FILE__;
00258 done += s;
00259 }
00260
00261 return done;
00262 }
00263
00264 IOSize
00265 DCacheFile::readv (IOBuffer *into, IOSize buffers)
00266 {
00267 assert (! buffers || into);
00268
00269
00270 if (! buffers)
00271 return 0;
00272
00273
00274 std::vector<iovec> bufs (buffers);
00275 for (IOSize i = 0; i < buffers; ++i)
00276 {
00277 bufs [i].iov_len = into [i].size ();
00278 bufs [i].iov_base = (caddr_t) into [i].data ();
00279 }
00280
00281
00282 dc_errno = 0;
00283 ssize_t n = dc_readv (m_fd, &bufs [0], buffers);
00284
00285
00286 if (n == -1) {
00287 edm::Exception ex(edm::errors::FileReadError);
00288 ex << "dc_readv(name='" << m_name << "', iov[" << buffers
00289 << "]) failed with error '" << dc_strerror(dc_errno)
00290 << "' (dc_errno=" << dc_errno << ")";
00291 ex.addContext("Calling DCacheFile::readv()");
00292 throw ex;
00293 }
00294
00295
00296 return n;
00297 }
00298
00299 IOSize
00300 DCacheFile::readv (IOPosBuffer *into, IOSize buffers)
00301 {
00302 assert (! buffers || into);
00303
00304
00305 if (! buffers)
00306 return 0;
00307
00308
00309 std::vector<iovec2> bufs (buffers);
00310 IOSize total = 0;
00311 for (IOSize i = 0; i < buffers; ++i)
00312 {
00313 bufs [i].offset = into [i].offset ();
00314 bufs [i].len = into [i].size ();
00315 bufs [i].buf = (char *) into [i].data ();
00316 total += into [i].size ();
00317 }
00318
00319
00320 dc_errno = 0;
00321 ssize_t n = dc_readv2 (m_fd, &bufs [0], buffers);
00322
00323
00324 if (n == -1) {
00325 edm::Exception ex(edm::errors::FileReadError);
00326 ex << "dc_readv2(name='" << m_name << "', iov2[" << buffers
00327 << "]) failed with error '" << dc_strerror(dc_errno)
00328 << "' (dc_errno=" << dc_errno << ")";
00329 ex.addContext("Calling DCacheFile::readv()");
00330 throw ex;
00331 }
00332
00333 return (n == 0) ? total : 0;
00334 }
00335
00339 IOOffset
00340 DCacheFile::position (IOOffset offset, Relative whence )
00341 {
00342 if (m_fd == EDM_IOFD_INVALID) {
00343 cms::Exception ex("FilePositionError");
00344 ex << "DCacheFile::position() called on a closed file";
00345 throw ex;
00346 }
00347 if (whence != CURRENT && whence != SET && whence != END) {
00348 cms::Exception ex("FilePositionError");
00349 ex << "DCacheFile::position() called with incorrect 'whence' parameter";
00350 throw ex;
00351 }
00352 IOOffset result;
00353 int mywhence = (whence == SET ? SEEK_SET
00354 : whence == CURRENT ? SEEK_CUR
00355 : SEEK_END);
00356
00357 dc_errno = 0;
00358 if ((result = dc_lseek64 (m_fd, offset, mywhence)) == -1) {
00359 cms::Exception ex("FilePositionError");
00360 ex << "dc_lseek64(name='" << m_name << "', offset=" << offset
00361 << ", whence=" << mywhence << ") failed with error '"
00362 << dc_strerror (dc_errno) << "' (dc_errno=" << dc_errno << ")";
00363 ex.addContext("Calling DCacheFile::position()");
00364 throw ex;
00365 }
00366
00367
00368 if (whence == SEEK_END && (result = dc_lseek64 (m_fd, result, SEEK_SET)) == -1) {
00369 cms::Exception ex("FilePositionError");
00370 ex << "dc_lseek64(name='" << m_name << "', offset=" << offset
00371 << ", whence=" << SEEK_SET << ") failed with error '"
00372 << dc_strerror (dc_errno) << "' (dc_errno=" << dc_errno << ")";
00373 ex.addContext("Calling DCacheFile::position()");
00374 throw ex;
00375 }
00376 return result;
00377 }
00378
00379 void
00380 DCacheFile::resize (IOOffset )
00381 {
00382 cms::Exception ex("FileResizeError");
00383 ex << "DCacheFile::resize(name='" << m_name << "') not implemented";
00384 throw ex;
00385 }