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