/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
FWStorage/DavixAdaptor/src/DavixFile.cc
377 строк
13 KB
Christopher Jones
Moved Utilities/DavixAdaptor to FWStorage/DavixAdaptor
10 дек 2025, 23:12
10 дек 2025, 23:12
e5282f2
Код
Авторство
О чём код?
#include "FWStorage/DavixAdaptor/interface/DavixFile.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "FWCore/Utilities/interface/EDMException.h" #include "FWCore/Utilities/interface/Exception.h" #include <cassert> #include <davix.hpp> #include <cerrno> #include <fcntl.h> #include <cstdlib> #include <unistd.h> #include <vector> #include <mutex> static std::once_flag davixDebugInit; using namespace Davix; using namespace edm::storage; DavixFile::DavixFile(void) {} DavixFile::DavixFile(const char *name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) { open(name, flags, perms); } DavixFile::DavixFile(const std::string &name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) { open(name.c_str(), flags, perms); } DavixFile::~DavixFile(void) { close(); return; } void DavixFile::close(void) { if (m_davixPosix && m_fd) { auto davixPosix = std::move(m_davixPosix); DavixError *err = nullptr; davixPosix->close(m_fd, &err); m_fd = nullptr; if (err) { std::unique_ptr<DavixError> davixErrManaged(err); cms::Exception ex("FileCloseError"); ex << "Davix::close(name='" << m_name << ") failed with error " << err->getErrMsg().c_str() << " and error code " << err->getStatus(); ex.addContext("Calling DavixFile::close()"); throw ex; } } return; } void DavixFile::abort(void) { if (m_davixPosix && m_fd) { DavixError *err = nullptr; m_davixPosix->close(m_fd, &err); if (err) { std::unique_ptr<DavixError> davixErrManaged(err); cms::Exception ex("FileAbortError"); ex << "Davix::abort(name='" << m_name << ") failed with error " << err->getErrMsg().c_str() << " and error code " << err->getStatus(); ex.addContext("Calling DavixFile::abort()"); throw ex; } } return; } void DavixFile::configureDavixLogLevel() { long logLevel = 0; char *logptr = nullptr; char const *const davixDebug = std::getenv("Davix_Debug"); if (davixDebug != nullptr) { logLevel = strtol(davixDebug, &logptr, 0); if (errno) { edm::LogWarning("DavixFile") << "Got error while converting " << "Davix_Debug env variable to integer. " "Will use default log level 0"; logLevel = 0; } if (logptr == davixDebug) { edm::LogWarning("DavixFile") << "Failed to convert to integer " << "Davix_Debug env variable; Will use default log level 0"; logLevel = 0; } else if (*logptr != '\0') { edm::LogWarning("DavixFile") << "Failed to parse extra junk " << "from Davix_Debug env variable. Will use default log level 0"; logLevel = 0; } } switch (logLevel) { case 0: std::call_once(davixDebugInit, davix_set_log_level, 0); break; case 1: std::call_once(davixDebugInit, davix_set_log_level, DAVIX_LOG_WARNING); break; case 2: std::call_once(davixDebugInit, davix_set_log_level, DAVIX_LOG_VERBOSE); break; case 3: std::call_once(davixDebugInit, davix_set_log_level, DAVIX_LOG_DEBUG); break; default: std::call_once(davixDebugInit, davix_set_log_level, DAVIX_LOG_ALL); break; } } static int X509Authentication(void *userdata, const SessionInfo &info, X509Credential *cert, DavixError **davixErr) { std::string ucert, ukey; char default_proxy[64]; snprintf(default_proxy, sizeof(default_proxy), "/tmp/x509up_u%d", geteuid()); // X509_USER_PROXY if (std::getenv("X509_USER_PROXY")) { edm::LogInfo("DavixFile") << "X509_USER_PROXY found in environment." << " Will use it for authentication"; ucert = ukey = std::getenv("X509_USER_PROXY"); } // Default proxy location else if (access(default_proxy, R_OK) == 0) { edm::LogInfo("DavixFile") << "Found proxy in default location " << default_proxy << " Will use it for authentication"; ucert = ukey = default_proxy; } // X509_USER_CERT else if (std::getenv("X509_USER_CERT")) { ucert = std::getenv("X509_USER_CERT"); } // X509_USER_KEY only if X509_USER_CERT was found if (!ucert.empty() && std::getenv("X509_USER_KEY")) { edm::LogInfo("DavixFile") << "X509_USER_{CERT|KEY} found in environment" << " Will use it for authentication"; ukey = std::getenv("X509_USER_KEY"); } // Check if vars are set... if (ucert.empty() || ukey.empty()) { edm::LogWarning("DavixFile") << "Was not able to find proxy in $X509_USER_PROXY, " << "X509_USER_{CERT|KEY} or default proxy creation location. " << "Will try without authentication"; return -1; } return cert->loadFromFilePEM(ukey, ucert, "", davixErr); } void DavixFile::create(const char *name, bool exclusive /* = false */, int perms /* = 066 */) { open(name, (IOFlags::OpenCreate | IOFlags::OpenWrite | IOFlags::OpenTruncate | (exclusive ? IOFlags::OpenExclusive : 0)), perms); } void DavixFile::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 DavixFile::open(const std::string &name, int flags /* = IOFlags::OpenRead */, int perms /* = 066 */) { open(name.c_str(), flags, perms); } void DavixFile::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 name"; ex.addContext("Calling DavixFile::open()"); throw ex; } m_name = name; if ((flags & IOFlags::OpenRead) == 0) { edm::Exception ex(edm::errors::FileOpenError); ex << "Must open file '" << name << "' at least for read"; ex.addContext("Calling DavixFile::open()"); throw ex; } if (m_davixPosix && m_fd) { edm::Exception ex(edm::errors::FileOpenError); ex << "Davix::open(name='" << m_name << "') failed on already open file"; ex.addContext("Calling DavixFile::open()"); throw ex; } configureDavixLogLevel(); // Translate our flags to system flags int openflags = 0; if (flags & IOFlags::OpenRead) openflags |= O_RDONLY; DavixError *davixErr = nullptr; RequestParams davixReqParams; // Set up X509 authentication davixReqParams.setClientCertCallbackX509(&X509Authentication, nullptr); // Set also CERT_DIR if it is set in envinroment, otherwise use default const char *cert_dir = nullptr; if ((cert_dir = std::getenv("X509_CERT_DIR")) == nullptr) cert_dir = "/etc/grid-security/certificates"; davixReqParams.addCertificateAuthorityPath(cert_dir); m_davixPosix = std::make_unique<DavPosix>(new Context()); m_fd = m_davixPosix->open(&davixReqParams, name, openflags, &davixErr); // Check Davix Error if (davixErr) { std::unique_ptr<DavixError> davixErrManaged(davixErr); edm::Exception ex(edm::errors::FileOpenError); ex << "Davix::open(name='" << m_name << "') failed with " << "error '" << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus(); ex.addContext("Calling DavixFile::open()"); throw ex; } if (!m_fd) { edm::Exception ex(edm::errors::FileOpenError); ex << "Davix::open(name='" << m_name << "') failed as fd is NULL"; ex.addContext("Calling DavixFile::open()"); throw ex; } } IOSize DavixFile::readv(IOBuffer *into, IOSize buffers) { assert(!buffers || into); // Davix does not support 0 buffers; if (buffers == 0) return 0; DavixError *davixErr = nullptr; std::vector<DavIOVecInput> input_vector(buffers); std::vector<DavIOVecOuput> output_vector(buffers); IOSize total = 0; // Total requested bytes for (IOSize i = 0; i < buffers; ++i) { input_vector[i].diov_size = into[i].size(); input_vector[i].diov_buffer = static_cast<char *>(into[i].data()); total += into[i].size(); } ssize_t s = m_davixPosix->preadVec(m_fd, input_vector.data(), output_vector.data(), buffers, &davixErr); if (davixErr) { std::unique_ptr<DavixError> davixErrManaged(davixErr); edm::Exception ex(edm::errors::FileReadError); ex << "Davix::readv(name='" << m_name << "', buffers=" << (buffers) << ") failed with error " << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus() << " and call returned " << s << " bytes"; ex.addContext("Calling DavixFile::readv()"); throw ex; } // Davix limits number of requests sent to the server // to improve performance and it does range coalescing. // So we can`t check what preadVec returns with what was requested. // Example: If two ranges are overlapping, [10, 20] and [20, 30] which is // coalesced into [10, 30] and it will contain one less byte than was requested. // Only check if returned val <= 0 and make proper actions. if (s < 0) { edm::Exception ex(edm::errors::FileReadError); ex << "Davix::readv(name='" << m_name << "') failed and call returned " << s; ex.addContext("Calling DavixFile::readv()"); throw ex; } else if (s == 0) { // end of file return 0; } return total; } IOSize DavixFile::readv(IOPosBuffer *into, IOSize buffers) { assert(!buffers || into); // Davix does not support 0 buffers; if (buffers == 0) return 0; DavixError *davixErr = nullptr; std::vector<DavIOVecInput> input_vector(buffers); std::vector<DavIOVecOuput> output_vector(buffers); IOSize total = 0; for (IOSize i = 0; i < buffers; ++i) { input_vector[i].diov_offset = into[i].offset(); input_vector[i].diov_size = into[i].size(); input_vector[i].diov_buffer = static_cast<char *>(into[i].data()); total += into[i].size(); } ssize_t s = m_davixPosix->preadVec(m_fd, input_vector.data(), output_vector.data(), buffers, &davixErr); if (davixErr) { std::unique_ptr<DavixError> davixErrManaged(davixErr); edm::Exception ex(edm::errors::FileReadError); ex << "Davix::readv(name='" << m_name << "', n=" << buffers << ") failed with error " << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus() << " and call returned " << s << " bytes"; ex.addContext("Calling DavixFile::readv()"); throw ex; } // Davix limits number of requests sent to the server // to improve performance and it does range coalescing. // So we can`t check what preadVec returns with what was requested. // Example: If two ranges are overlapping, [10, 20] and [20, 30] which is // coalesced into [10, 30] and it will contain one less byte than was requested. // Only check if returned val <= 0 and make proper actions. if (s < 0) { edm::Exception ex(edm::errors::FileReadError); ex << "Davix::readv(name='" << m_name << "', n=" << buffers << ") failed and call returned " << s; ex.addContext("Calling DavixFile::readv()"); throw ex; } else if (s == 0) { // end of file return 0; } return total; } IOSize DavixFile::read(void *into, IOSize n) { DavixError *davixErr = nullptr; m_davixPosix->fadvise(m_fd, 0, n, AdviseRandom); IOSize done = 0; while (done < n) { ssize_t s = m_davixPosix->read(m_fd, (char *)into + done, n - done, &davixErr); if (davixErr) { std::unique_ptr<DavixError> davixErrManaged(davixErr); edm::Exception ex(edm::errors::FileReadError); ex << "Davix::read(name='" << m_name << "', n=" << (n - done) << ") failed with error " << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus() << " and call returned " << s << " bytes"; ex.addContext("Calling DavixFile::read()"); throw ex; } if (s < 0) { edm::Exception ex(edm::errors::FileReadError); ex << "Davix::read(name='" << m_name << "', n=" << (n - done) << ") failed and call returned " << s; ex.addContext("Calling DavixFile::read()"); throw ex; } else if (s == 0) { // end of file break; } done += s; } return done; } IOSize DavixFile::write(const void *from, IOSize n) { edm::Exception ex(edm::errors::FileWriteError); ex << "DavixFile::write(name='" << m_name << "') not implemented"; ex.addContext("Calling DavixFile::write()"); throw ex; } IOOffset DavixFile::position(IOOffset offset, Relative whence /* = SET */) { DavixError *davixErr = nullptr; if (whence != CURRENT && whence != SET && whence != END) { cms::Exception ex("FilePositionError"); ex << "DavixFile::position() called with incorrect 'whence' parameter"; ex.addContext("Calling DavixFile::position()"); throw ex; } IOOffset result; size_t mywhence = (whence == SET ? SEEK_SET : whence == CURRENT ? SEEK_CUR : SEEK_END); if ((result = m_davixPosix->lseek(m_fd, offset, mywhence, &davixErr)) == -1) { cms::Exception ex("FilePositionError"); ex << "Davix::lseek(name='" << m_name << "', offset=" << offset << ", whence=" << mywhence << ") failed with error " << davixErr->getErrMsg().c_str() << " and error code " << davixErr->getStatus() << " and " << "call returned " << result; ex.addContext("Calling DavixFile::position()"); throw ex; } return result; } void DavixFile::resize(IOOffset /* size */) { cms::Exception ex("FileResizeError"); ex << "DavixFile::resize(name='" << m_name << "') not implemented"; ex.addContext("Calling DavixFile::resize()"); throw ex; }