File indexing completed on 2024-04-06 12:31:46
0001 #include "Utilities/DCacheAdaptor/interface/DCacheFile.h"
0002 #include "FWCore/Utilities/interface/Exception.h"
0003 #include "FWCore/Utilities/interface/EDMException.h"
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 #include <cassert>
0006 #include <vector>
0007 #include <unistd.h>
0008 #include <fcntl.h>
0009 #include <dcap.h>
0010
0011 using namespace edm::storage;
0012
0013 DCacheFile::DCacheFile(void) : m_fd(EDM_IOFD_INVALID), m_close(false) {}
0014
0015 DCacheFile::DCacheFile(IOFD fd) : m_fd(fd), m_close(true) {}
0016
0017 DCacheFile::DCacheFile(const char *name, int flags , int perms )
0018 : m_fd(EDM_IOFD_INVALID), m_close(false) {
0019 open(name, flags, perms);
0020 }
0021
0022 DCacheFile::DCacheFile(const std::string &name, int flags , int perms )
0023 : m_fd(EDM_IOFD_INVALID), m_close(false) {
0024 open(name.c_str(), flags, perms);
0025 }
0026
0027 DCacheFile::~DCacheFile(void) {
0028 if (m_close)
0029 edm::LogError("DCacheFileError") << "Destructor called on dCache file '" << m_name
0030 << "' but the file is still open";
0031 }
0032
0033
0034 void DCacheFile::create(const char *name, bool exclusive , int perms ) {
0035 open(name,
0036 (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate | (exclusive ? IOFlags::OpenExclusive : 0)),
0037 perms);
0038 }
0039
0040 void DCacheFile::create(const std::string &name, bool exclusive , int perms ) {
0041 open(name.c_str(),
0042 (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate | (exclusive ? IOFlags::OpenExclusive : 0)),
0043 perms);
0044 }
0045
0046 void DCacheFile::open(const std::string &name, int flags , int perms ) {
0047 open(name.c_str(), flags, perms);
0048 }
0049
0050 void DCacheFile::open(const char *name, int flags , int perms ) {
0051
0052 if ((name == nullptr) || (*name == 0)) {
0053 edm::Exception ex(edm::errors::FileOpenError);
0054 ex << "Cannot open a file without a name";
0055 ex.addContext("Calling DCacheFile::open()");
0056 throw ex;
0057 }
0058
0059 if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0) {
0060 edm::Exception ex(edm::errors::FileOpenError);
0061 ex << "Must open file '" << name << "' at least for read or write";
0062 ex.addContext("Calling DCacheFile::open()");
0063 throw ex;
0064 }
0065
0066
0067 if (m_fd != EDM_IOFD_INVALID && m_close)
0068 close();
0069
0070
0071 int openflags = 0;
0072
0073 if ((flags & IOFlags::OpenRead) && (flags & IOFlags::OpenWrite))
0074 openflags |= O_RDWR;
0075 else if (flags & IOFlags::OpenRead)
0076 openflags |= O_RDONLY;
0077 else if (flags & IOFlags::OpenWrite)
0078 openflags |= O_WRONLY;
0079
0080 if (flags & IOFlags::OpenNonBlock)
0081 openflags |= O_NONBLOCK;
0082
0083 if (flags & IOFlags::OpenAppend)
0084 openflags |= O_APPEND;
0085
0086 if (flags & IOFlags::OpenCreate)
0087 openflags |= O_CREAT;
0088
0089 if (flags & IOFlags::OpenExclusive)
0090 openflags |= O_EXCL;
0091
0092 if (flags & IOFlags::OpenTruncate)
0093 openflags |= O_TRUNC;
0094
0095 IOFD newfd = EDM_IOFD_INVALID;
0096 dc_errno = 0;
0097 if ((newfd = dc_open(name, openflags, perms)) == -1) {
0098 edm::Exception ex(edm::errors::FileOpenError);
0099 ex << "dc_open(name='" << name << "', flags=0x" << std::hex << openflags << ", permissions=0" << std::oct << perms
0100 << std::dec << ") => error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")";
0101 ex.addContext("Calling DCacheFile::open()");
0102 throw ex;
0103 }
0104
0105 m_name = name;
0106 m_fd = newfd;
0107
0108
0109
0110
0111
0112
0113
0114 if (flags & IOFlags::OpenUnbuffered)
0115 dc_noBuffering(m_fd);
0116 else
0117 dc_setBufferSize(m_fd, 64000);
0118
0119 m_close = true;
0120
0121 edm::LogInfo("DCacheFileInfo") << "Opened " << m_name;
0122 }
0123
0124 void DCacheFile::close(void) {
0125 if (m_fd == EDM_IOFD_INVALID) {
0126 edm::LogError("DCacheFileError") << "DCacheFile::close(name='" << m_name << "') called but the file is not open";
0127 m_close = false;
0128 return;
0129 }
0130
0131 dc_errno = 0;
0132 if (dc_close(m_fd) == -1)
0133 edm::LogWarning("DCacheFileWarning") << "dc_close(name='" << m_name << "') failed with error '"
0134 << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")";
0135
0136 m_close = false;
0137 m_fd = EDM_IOFD_INVALID;
0138
0139
0140
0141 }
0142
0143 void DCacheFile::abort(void) {
0144 if (m_fd != EDM_IOFD_INVALID)
0145 dc_close(m_fd);
0146
0147 m_close = false;
0148 m_fd = EDM_IOFD_INVALID;
0149 }
0150
0151
0152 static const int BUGLINE = __LINE__ + 1;
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 IOSize DCacheFile::read(void *into, IOSize n) {
0168 IOSize done = 0;
0169 while (done < n) {
0170 dc_errno = 0;
0171 ssize_t s = dc_read(m_fd, (char *)into + done, n - done);
0172 if (s == -1) {
0173 edm::Exception ex(edm::errors::FileReadError);
0174 ex << "dc_read(name='" << m_name << "', n=" << (n - done) << ") failed with error '" << dc_strerror(dc_errno)
0175 << "' (dc_errno=" << dc_errno << ")";
0176 ex.addContext("Calling DCacheFile::read()");
0177 throw ex;
0178 } else if (s == 0)
0179
0180 break;
0181 else if (s < ssize_t(n - done))
0182 edm::LogInfo("DCacheFileWarning") << "dc_read(name='" << m_name << "', n=" << (n - done)
0183 << ") returned a short read of " << s << " bytes; "
0184 << "please report a bug in dCache referencing the "
0185 << "comment on line " << BUGLINE << " of " << __FILE__;
0186 done += s;
0187 }
0188
0189 return done;
0190 }
0191
0192 IOSize DCacheFile::write(const void *from, IOSize n) {
0193 IOSize done = 0;
0194 while (done < n) {
0195 dc_errno = 0;
0196 ssize_t s = dc_write(m_fd, (const char *)from + done, n - done);
0197 if (s == -1) {
0198 edm::Exception ex(edm::errors::FileWriteError);
0199 ex << "dc_write(name='" << m_name << "', n=" << (n - done) << ") failed with error '" << dc_strerror(dc_errno)
0200 << "' (dc_errno=" << dc_errno << ")";
0201 ex.addContext("Calling DCacheFile::write()");
0202 throw ex;
0203 } else if (s < ssize_t(n - done))
0204 edm::LogInfo("DCacheFileWarning") << "dc_write(name='" << m_name << "', n=" << (n - done)
0205 << ") returned a short write of " << s << " bytes; "
0206 << "please report a bug in dCache referencing the "
0207 << "comment on line " << BUGLINE << " of " << __FILE__;
0208 done += s;
0209 }
0210
0211 return done;
0212 }
0213
0214 IOSize DCacheFile::readv(IOBuffer *into, IOSize buffers) {
0215 assert(!buffers || into);
0216
0217
0218 if (!buffers)
0219 return 0;
0220
0221
0222 std::vector<iovec> bufs(buffers);
0223 for (IOSize i = 0; i < buffers; ++i) {
0224 bufs[i].iov_len = into[i].size();
0225 bufs[i].iov_base = (caddr_t)into[i].data();
0226 }
0227
0228
0229 dc_errno = 0;
0230 ssize_t n = dc_readv(m_fd, &bufs[0], buffers);
0231
0232
0233 if (n == -1) {
0234 edm::Exception ex(edm::errors::FileReadError);
0235 ex << "dc_readv(name='" << m_name << "', iov[" << buffers << "]) failed with error '" << dc_strerror(dc_errno)
0236 << "' (dc_errno=" << dc_errno << ")";
0237 ex.addContext("Calling DCacheFile::readv()");
0238 throw ex;
0239 }
0240
0241
0242 return n;
0243 }
0244
0245 IOSize DCacheFile::readv(IOPosBuffer *into, IOSize buffers) {
0246 assert(!buffers || into);
0247
0248
0249 if (!buffers)
0250 return 0;
0251
0252
0253 std::vector<iovec2> bufs(buffers);
0254 IOSize total = 0;
0255 for (IOSize i = 0; i < buffers; ++i) {
0256 bufs[i].offset = into[i].offset();
0257 bufs[i].len = into[i].size();
0258 bufs[i].buf = (char *)into[i].data();
0259 total += into[i].size();
0260 }
0261
0262
0263 dc_errno = 0;
0264 ssize_t n = dc_readv2(m_fd, &bufs[0], buffers);
0265
0266
0267 if (n == -1) {
0268 edm::Exception ex(edm::errors::FileReadError);
0269 ex << "dc_readv2(name='" << m_name << "', iov2[" << buffers << "]) failed with error '" << dc_strerror(dc_errno)
0270 << "' (dc_errno=" << dc_errno << ")";
0271 ex.addContext("Calling DCacheFile::readv()");
0272 throw ex;
0273 }
0274
0275 return (n == 0) ? total : 0;
0276 }
0277
0278
0279
0280
0281 IOOffset DCacheFile::position(IOOffset offset, Relative whence ) {
0282 if (m_fd == EDM_IOFD_INVALID) {
0283 cms::Exception ex("FilePositionError");
0284 ex << "DCacheFile::position() called on a closed file";
0285 throw ex;
0286 }
0287 if (whence != CURRENT && whence != SET && whence != END) {
0288 cms::Exception ex("FilePositionError");
0289 ex << "DCacheFile::position() called with incorrect 'whence' parameter";
0290 throw ex;
0291 }
0292 IOOffset result;
0293 int mywhence = (whence == SET ? SEEK_SET : whence == CURRENT ? SEEK_CUR : SEEK_END);
0294
0295 dc_errno = 0;
0296 if ((result = dc_lseek64(m_fd, offset, mywhence)) == -1) {
0297 cms::Exception ex("FilePositionError");
0298 ex << "dc_lseek64(name='" << m_name << "', offset=" << offset << ", whence=" << mywhence << ") failed with error '"
0299 << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")";
0300 ex.addContext("Calling DCacheFile::position()");
0301 throw ex;
0302 }
0303
0304
0305 if (whence == SEEK_END && (result = dc_lseek64(m_fd, result, SEEK_SET)) == -1) {
0306 cms::Exception ex("FilePositionError");
0307 ex << "dc_lseek64(name='" << m_name << "', offset=" << offset << ", whence=" << SEEK_SET << ") failed with error '"
0308 << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")";
0309 ex.addContext("Calling DCacheFile::position()");
0310 throw ex;
0311 }
0312 return result;
0313 }
0314
0315 void DCacheFile::resize(IOOffset ) {
0316 cms::Exception ex("FileResizeError");
0317 ex << "DCacheFile::resize(name='" << m_name << "') not implemented";
0318 throw ex;
0319 }