/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
FWStorage/DCacheAdaptor/src/DCacheFile.cc
319 строк
11 KB
Chris Jones
Moved Utilities/DCacheAdaptor to FWStorage/DCacheAdaptor
10 дек 2025, 18:30
10 дек 2025, 18:30
c3949be
Код
Авторство
О чём код?
#include "FWStorage/DCacheAdaptor/interface/DCacheFile.h" #include "FWCore/Utilities/interface/Exception.h" #include "FWCore/Utilities/interface/EDMException.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include <cassert> #include <vector> #include <unistd.h> #include <fcntl.h> #include <dcap.h> using namespace edm::storage; DCacheFile::DCacheFile(void) : m_fd(EDM_IOFD_INVALID), m_close(false) {} DCacheFile::DCacheFile(IOFD fd) : m_fd(fd), m_close(true) {} DCacheFile::DCacheFile(const char *name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) : m_fd(EDM_IOFD_INVALID), m_close(false) { open(name, flags, perms); } DCacheFile::DCacheFile(const std::string &name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) : m_fd(EDM_IOFD_INVALID), m_close(false) { open(name.c_str(), flags, perms); } DCacheFile::~DCacheFile(void) { if (m_close) edm::LogError("DCacheFileError") << "Destructor called on dCache file '" << m_name << "' but the file is still open"; } ////////////////////////////////////////////////////////////////////// void DCacheFile::create(const char *name, bool exclusive /* = false */, int perms /* = 066 */) { open(name, (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate | (exclusive ? IOFlags::OpenExclusive : 0)), perms); } void DCacheFile::create(const std::string &name, bool exclusive /* = false */, int perms /* = 066 */) { open(name.c_str(), (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate | (exclusive ? IOFlags::OpenExclusive : 0)), perms); } void DCacheFile::open(const std::string &name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) { open(name.c_str(), flags, perms); } void DCacheFile::open(const char *name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) { // Actual open if ((name == nullptr) || (*name == 0)) { edm::Exception ex(edm::errors::FileOpenError); ex << "Cannot open a file without a name"; ex.addContext("Calling DCacheFile::open()"); throw ex; } if ((flags & (IOFlags::OpenRead | IOFlags::OpenWrite)) == 0) { edm::Exception ex(edm::errors::FileOpenError); ex << "Must open file '" << name << "' at least for read or write"; ex.addContext("Calling DCacheFile::open()"); throw ex; } // If I am already open, close old file first if (m_fd != EDM_IOFD_INVALID && m_close) close(); // Translate our flags to system flags int openflags = 0; if ((flags & IOFlags::OpenRead) && (flags & IOFlags::OpenWrite)) openflags |= O_RDWR; else if (flags & IOFlags::OpenRead) openflags |= O_RDONLY; else if (flags & IOFlags::OpenWrite) openflags |= O_WRONLY; if (flags & IOFlags::OpenNonBlock) openflags |= O_NONBLOCK; if (flags & IOFlags::OpenAppend) openflags |= O_APPEND; if (flags & IOFlags::OpenCreate) openflags |= O_CREAT; if (flags & IOFlags::OpenExclusive) openflags |= O_EXCL; if (flags & IOFlags::OpenTruncate) openflags |= O_TRUNC; IOFD newfd = EDM_IOFD_INVALID; dc_errno = 0; if ((newfd = dc_open(name, openflags, perms)) == -1) { edm::Exception ex(edm::errors::FileOpenError); ex << "dc_open(name='" << name << "', flags=0x" << std::hex << openflags << ", permissions=0" << std::oct << perms << std::dec << ") => error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")"; ex.addContext("Calling DCacheFile::open()"); throw ex; } m_name = name; m_fd = newfd; // Turn off read-ahead, or adjust read-ahead size depending on // whether buffering has been requested. This is a very tricky // balance here. Without read-ahead data processing appears to // become exceedingly slow, and with default (1MB) read-ahead // it appears to saturate disk servers and network. Try tread // reasonable middle ground here. if (flags & IOFlags::OpenUnbuffered) dc_noBuffering(m_fd); else dc_setBufferSize(m_fd, 64000); m_close = true; edm::LogInfo("DCacheFileInfo") << "Opened " << m_name; } void DCacheFile::close(void) { if (m_fd == EDM_IOFD_INVALID) { edm::LogError("DCacheFileError") << "DCacheFile::close(name='" << m_name << "') called but the file is not open"; m_close = false; return; } dc_errno = 0; if (dc_close(m_fd) == -1) edm::LogWarning("DCacheFileWarning") << "dc_close(name='" << m_name << "') failed with error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")"; m_close = false; m_fd = EDM_IOFD_INVALID; // Caused hang. Will be added back after problem is fixed. // edm::LogInfo("DCacheFileInfo") << "Closed " << m_name; } void DCacheFile::abort(void) { if (m_fd != EDM_IOFD_INVALID) dc_close(m_fd); m_close = false; m_fd = EDM_IOFD_INVALID; } ////////////////////////////////////////////////////////////////////// static const int BUGLINE = __LINE__ + 1; // Apparently dc_read can return short reads; I don't know if dc_write // will also return short writes. This is a bug in dCache. POSIX, // apparently contrary to the understanding of dCache authors, does // not allow reads from files to return short, and in fact no network // file system returns short reads. For more details please refer to // http://www.opengroup.org/onlinepubs/000095399/functions/read.html: // The value returned may be less than nbyte if the number of // bytes left in the file is less than nbyte, if the read() // request was interrupted by a signal, or if the file is a // pipe or FIFO or special file and has fewer than nbyte bytes // immediately available for reading. // (In other words, barring signals (which should use SA_RESTART and // in any case should not affect dCache) the only way a read from a // file can return short is when there is nothing left to read.) IOSize DCacheFile::read(void *into, IOSize n) { IOSize done = 0; while (done < n) { dc_errno = 0; ssize_t s = dc_read(m_fd, (char *)into + done, n - done); if (s == -1) { edm::Exception ex(edm::errors::FileReadError); ex << "dc_read(name='" << m_name << "', n=" << (n - done) << ") failed with error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")"; ex.addContext("Calling DCacheFile::read()"); throw ex; } else if (s == 0) // end of file break; else if (s < ssize_t(n - done)) edm::LogInfo("DCacheFileWarning") << "dc_read(name='" << m_name << "', n=" << (n - done) << ") returned a short read of " << s << " bytes; " << "please report a bug in dCache referencing the " << "comment on line " << BUGLINE << " of " << __FILE__; done += s; } return done; } IOSize DCacheFile::write(const void *from, IOSize n) { IOSize done = 0; while (done < n) { dc_errno = 0; ssize_t s = dc_write(m_fd, (const char *)from + done, n - done); if (s == -1) { edm::Exception ex(edm::errors::FileWriteError); ex << "dc_write(name='" << m_name << "', n=" << (n - done) << ") failed with error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")"; ex.addContext("Calling DCacheFile::write()"); throw ex; } else if (s < ssize_t(n - done)) edm::LogInfo("DCacheFileWarning") << "dc_write(name='" << m_name << "', n=" << (n - done) << ") returned a short write of " << s << " bytes; " << "please report a bug in dCache referencing the " << "comment on line " << BUGLINE << " of " << __FILE__; done += s; } return done; } IOSize DCacheFile::readv(IOBuffer *into, IOSize buffers) { assert(!buffers || into); // readv may not support zero buffers. if (!buffers) return 0; // Convert the buffers to system format. std::vector<iovec> bufs(buffers); for (IOSize i = 0; i < buffers; ++i) { bufs[i].iov_len = into[i].size(); bufs[i].iov_base = (caddr_t)into[i].data(); } // Read as long as signals cancel the read before doing anything. dc_errno = 0; ssize_t n = dc_readv(m_fd, &bufs[0], buffers); // If it was serious error, throw it. if (n == -1) { edm::Exception ex(edm::errors::FileReadError); ex << "dc_readv(name='" << m_name << "', iov[" << buffers << "]) failed with error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")"; ex.addContext("Calling DCacheFile::readv()"); throw ex; } // Return the number of bytes actually read. return n; } IOSize DCacheFile::readv(IOPosBuffer *into, IOSize buffers) { assert(!buffers || into); // readv may not support zero buffers. if (!buffers) return 0; // Convert the buffers to system format. std::vector<iovec2> bufs(buffers); IOSize total = 0; for (IOSize i = 0; i < buffers; ++i) { bufs[i].offset = into[i].offset(); bufs[i].len = into[i].size(); bufs[i].buf = (char *)into[i].data(); total += into[i].size(); } // Read as long as signals cancel the read before doing anything. dc_errno = 0; ssize_t n = dc_readv2(m_fd, &bufs[0], buffers); // If it was serious error, throw it. if (n == -1) { edm::Exception ex(edm::errors::FileReadError); ex << "dc_readv2(name='" << m_name << "', iov2[" << buffers << "]) failed with error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")"; ex.addContext("Calling DCacheFile::readv()"); throw ex; } // dc_readv2 returns 0 on success. return (n == 0) ? total : 0; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// IOOffset DCacheFile::position(IOOffset offset, Relative whence /* = SET */) { if (m_fd == EDM_IOFD_INVALID) { cms::Exception ex("FilePositionError"); ex << "DCacheFile::position() called on a closed file"; throw ex; } if (whence != CURRENT && whence != SET && whence != END) { cms::Exception ex("FilePositionError"); ex << "DCacheFile::position() called with incorrect 'whence' parameter"; throw ex; } IOOffset result; int mywhence = (whence == SET ? SEEK_SET : whence == CURRENT ? SEEK_CUR : SEEK_END); dc_errno = 0; if ((result = dc_lseek64(m_fd, offset, mywhence)) == -1) { cms::Exception ex("FilePositionError"); ex << "dc_lseek64(name='" << m_name << "', offset=" << offset << ", whence=" << mywhence << ") failed with error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")"; ex.addContext("Calling DCacheFile::position()"); throw ex; } // FIXME: dCache returns incorrect value on SEEK_END. // Remove this hack when dcap has been fixed. if (whence == SEEK_END && (result = dc_lseek64(m_fd, result, SEEK_SET)) == -1) { cms::Exception ex("FilePositionError"); ex << "dc_lseek64(name='" << m_name << "', offset=" << offset << ", whence=" << SEEK_SET << ") failed with error '" << dc_strerror(dc_errno) << "' (dc_errno=" << dc_errno << ")"; ex.addContext("Calling DCacheFile::position()"); throw ex; } return result; } void DCacheFile::resize(IOOffset /* size */) { cms::Exception ex("FileResizeError"); ex << "DCacheFile::resize(name='" << m_name << "') not implemented"; throw ex; }