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