diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 281c4142365c706e7ad4dc9b3581354ce81090cd..0e8227921e27de580476181eb00bafc279c4e242 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -16,6 +16,7 @@ - cta/CTA#547 - Fix repack backpressure mechanism not requeueing repack requests - cta/CTA#562 - CTA Frontend should reject files with owner_uid=0 - cta/CTA#572 - Do not set the 'queueTrimRequired' flag as true when 'doCleanup' is required +- cta/CTA#584 - Refactors exception::Errnum class ### Continuous Integration - cta/CTA#278 - Updating system tests for new EOS evict command diff --git a/common/exception/Errnum.cpp b/common/exception/Errnum.cpp index 62134701eac67a07528e48a894c4d3dcf0a86e5d..89f105682af054cd8991e9ab323fcb3258c78410 100644 --- a/common/exception/Errnum.cpp +++ b/common/exception/Errnum.cpp @@ -18,54 +18,33 @@ #include "common/exception/Errnum.hpp" #include "common/utils/utils.hpp" -#include <errno.h> -#include <string.h> +namespace cta::exception { -using namespace cta::exception; - -Errnum::Errnum(std::string what):Exception("") { - m_errnum = errno; - ErrnumConstructorBottomHalf(what); +Errnum::Errnum(int err, std::string_view what) : Exception(), + m_errnum(err), + m_strerror(utils::errnoToString(err)) { + std::stringstream whatWithErrnum; + whatWithErrnum << what << (what.empty() ? "" : " ") + << "Errno=" << m_errnum << ": " << m_strerror; + getMessage() << whatWithErrnum.str(); } -Errnum::Errnum(int err, std::string what):Exception("") { - m_errnum = err; - ErrnumConstructorBottomHalf(what); -} +Errnum::Errnum(std::string_view what) : Errnum(errno, what) { } -void Errnum::ErrnumConstructorBottomHalf(const std::string & what) { - m_strerror = utils::errnoToString(m_errnum); - std::stringstream w2; - if (what.size()) - w2 << what << " "; - w2 << "Errno=" << m_errnum << ": " << m_strerror; - getMessage() << w2.str(); +void Errnum::throwOnReturnedErrno(int err, std::string_view context) { + if(err) throw Errnum(err, context); } -void Errnum::throwOnReturnedErrno (const int err, const std::string &context) { - if (err) throw Errnum(err, context); +void Errnum::throwOnNonZero(int status, std::string_view context) { + if(status) throw Errnum(context); } -void Errnum::throwOnNonZero(const int status, const std::string &context) { - if (status) throw Errnum(context); +void Errnum::throwOnNull(const void* const ptr, std::string_view context) { + if(nullptr == ptr) throw Errnum(context); } -void Errnum::throwOnZero(const int status, const std::string &context) { - if (!status) throw Errnum(context); +void Errnum::throwOnMinusOne(ssize_t ret, std::string_view context) { + if(ret == -1) throw Errnum(context); } -void Errnum::throwOnNull(const void *const f, const std::string &context) { - if (nullptr == f) throw Errnum(context); -} - -void Errnum::throwOnNegative(const int ret, const std::string &context) { - if (ret < 0) throw Errnum(context); -} - -void Errnum::throwOnMinusOne(const int ret, const std::string &context) { - if (-1 == ret) throw Errnum(context); -} - -void Errnum::throwOnNegativeErrnoIfNegative(const int ret, const std::string& context) { - if (ret < 0) throw Errnum(-ret, context); -} +} // namespace cta::exception diff --git a/common/exception/Errnum.hpp b/common/exception/Errnum.hpp index 3f94ec4794dcba337c617a47b3af68307c137806..16bffe5b2a198cbb35f8292b69ddccd7e1d05440 100644 --- a/common/exception/Errnum.hpp +++ b/common/exception/Errnum.hpp @@ -17,42 +17,26 @@ #pragma once -#include "Exception.hpp" -#include <functional> -#include <system_error> +#include "common/exception/Exception.hpp" namespace cta::exception { - class Errnum: public cta::exception::Exception { - public: - explicit Errnum(std::string what = ""); - Errnum(int err, std::string what = ""); - virtual ~Errnum() = default; - int errorNumber() const { return m_errnum; } - std::string strError() const { return m_strerror; } - static void throwOnReturnedErrno(const int err, const std::string &context = ""); - template <typename F> - static void throwOnReturnedErrnoOrThrownStdException (F f, const std::string &context = "") { - try { - throwOnReturnedErrno(f(), context); - } catch (Errnum &) { - throw; // Let the exception of throwOnReturnedErrno pass through. - } catch (std::error_code & ec) { - throw Errnum(ec.value(), context + " Got an std::error_code: " + ec.message()); - } catch (std::exception & ex) { - throw Exception(context + " Got a standard exception: " + ex.what()); - } - } - static void throwOnNonZero(const int status, const std::string &context = ""); - static void throwOnZero(const int status, const std::string &context = ""); - static void throwOnNull(const void *const f, const std::string &context = ""); - static void throwOnNegative(const int ret, const std::string &context = ""); - static void throwOnMinusOne(const int ret, const std::string &context = ""); - static void throwOnNegativeErrnoIfNegative(const int ret, const std::string &context = ""); - protected: - void ErrnumConstructorBottomHalf(const std::string & what); - int m_errnum; - std::string m_strerror; - }; +class Errnum : public Exception { +public: + explicit Errnum(std::string_view what = ""); + Errnum(int err, std::string_view what = ""); + virtual ~Errnum() = default; + + int errorNumber() const { return m_errnum; } + + static void throwOnReturnedErrno(int err, std::string_view context = ""); + static void throwOnNonZero(int status, std::string_view context = ""); + static void throwOnNull(const void *const f, std::string_view context = ""); + static void throwOnMinusOne(ssize_t ret, const std::string_view context = ""); + +private: + int m_errnum; + std::string m_strerror; +}; } // namespace cta::exception diff --git a/common/exception/ExceptionTest.cpp b/common/exception/ExceptionTest.cpp index bf209f8449a751d56c0a48810de8d0b71a0eb700..c7fe6cfea95a8df54a6f0c1fbf7a0be1ae5d16b8 100644 --- a/common/exception/ExceptionTest.cpp +++ b/common/exception/ExceptionTest.cpp @@ -83,46 +83,21 @@ namespace unitTests { TEST(cta_exceptions, Errnum_throwers) { /* throwOnReturnedErrno */ ASSERT_NO_THROW(cta::exception::Errnum::throwOnReturnedErrno(0, "Context")); - ASSERT_THROW(cta::exception::Errnum::throwOnReturnedErrno(ENOSPC, "Context"), - cta::exception::Errnum); - - ASSERT_NO_THROW(cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([](){ return 0; }, "Context")); - ASSERT_THROW(cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([](){ return ENOSPC; }, "Context"), - cta::exception::Errnum); - ASSERT_THROW(cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([](){ throw std::error_code(ENOSPC, std::system_category()); return 0; }, "Context"), - cta::exception::Errnum); - ASSERT_THROW(cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([](){ throw std::exception(); return 0; }, "Context"), - cta::exception::Exception); - + ASSERT_THROW(cta::exception::Errnum::throwOnReturnedErrno(ENOSPC, "Context"), cta::exception::Errnum); /* throwOnNonZero */ errno = ENOENT; ASSERT_NO_THROW(cta::exception::Errnum::throwOnNonZero(0, "Context")); - ASSERT_THROW(cta::exception::Errnum::throwOnNonZero(-1, "Context"), - cta::exception::Errnum); + ASSERT_THROW(cta::exception::Errnum::throwOnNonZero(-1, "Context"), cta::exception::Errnum); /* throwOnMinusOne */ errno = ENOENT; ASSERT_NO_THROW(cta::exception::Errnum::throwOnMinusOne(0, "Context")); - ASSERT_THROW(cta::exception::Errnum::throwOnMinusOne(-1, "Context"), - cta::exception::Errnum); - - /* throwOnNegative */ - errno = ENOENT; - ASSERT_NO_THROW(cta::exception::Errnum::throwOnNegative(0, "Context")); - ASSERT_THROW(cta::exception::Errnum::throwOnNegative(-1, "Context"), - cta::exception::Errnum); + ASSERT_THROW(cta::exception::Errnum::throwOnMinusOne(-1, "Context"), cta::exception::Errnum); /* throwOnNull */ errno = ENOENT; ASSERT_NO_THROW(cta::exception::Errnum::throwOnNull(this, "Context")); - ASSERT_THROW(cta::exception::Errnum::throwOnNull(nullptr, "Context"), - cta::exception::Errnum); - - /* throwOnZero */ - errno = ENOENT; - ASSERT_NO_THROW(cta::exception::Errnum::throwOnZero(1, "Context")); - ASSERT_THROW(cta::exception::Errnum::throwOnZero(0, "Context"), - cta::exception::Errnum); + ASSERT_THROW(cta::exception::Errnum::throwOnNull(nullptr, "Context"), cta::exception::Errnum); } } diff --git a/common/exception/XrootCl.cpp b/common/exception/XrootCl.cpp index 52b79c3a904bae1a31912d263114553b4ecd08a7..dad93074df532f52e4873b3a12db94c522d5619a 100644 --- a/common/exception/XrootCl.cpp +++ b/common/exception/XrootCl.cpp @@ -22,8 +22,8 @@ namespace cta::exception { -XrootCl::XrootCl(const XrdCl::XRootDStatus& status, const std::string & what) { - if (!what.empty()) { +XrootCl::XrootCl(const XrdCl::XRootDStatus& status, std::string_view what) { + if(!what.empty()) { getMessage() << what << " "; } getMessage() << status.ToStr().c_str(); @@ -32,8 +32,8 @@ XrootCl::XrootCl(const XrdCl::XRootDStatus& status, const std::string & what) { << " status:" << status.status; } -void XrootCl::throwOnError(const XrdCl::XRootDStatus& status, const std::string& context) { - if (!status.IsOK()) { +void XrootCl::throwOnError(const XrdCl::XRootDStatus& status, std::string_view context) { + if(!status.IsOK()) { throw XrootCl(status, context); } } diff --git a/common/exception/XrootCl.hpp b/common/exception/XrootCl.hpp index 57b42807e1270b656eaa6f47f9ce6017156bd1e5..02f7c8da4789b0211a9b63da03ebd25947a22afb 100644 --- a/common/exception/XrootCl.hpp +++ b/common/exception/XrootCl.hpp @@ -17,25 +17,23 @@ #pragma once -#include <string> - -#include "Exception.hpp" - #include <xrootd/XrdCl/XrdClXRootDResponses.hh> +#include "common/exception/Exception.hpp" namespace cta::exception { /** - * A class turning the XrootCl (xroot 4 object client) error codes - * into castor exceptions. + * A class turning the XrootCl (xroot 4 object client) error codes into CTA exceptions */ -class XrootCl : public cta::exception::Exception { - public: - XrootCl(const XrdCl::XRootDStatus & status, const std::string & context); +class XrootCl : public Exception { +public: + XrootCl(const XrdCl::XRootDStatus& status, std::string_view context); virtual ~XrootCl() = default; const XrdCl::XRootDStatus & xRootDStatus() const { return m_status; } - static void throwOnError(const XrdCl::XRootDStatus & status, const std::string& context = ""); - protected: + static void throwOnError(const XrdCl::XRootDStatus& status, std::string_view context = ""); + +private: XrdCl::XRootDStatus m_status; }; + } // namespace cta::exception diff --git a/common/threading/Daemon.cpp b/common/threading/Daemon.cpp index 4182133502e1f9c16bcb93bb1ff7f93b510932fd..3973b96e96a17d48ad398e3b140d8ba958ecd4e4 100644 --- a/common/threading/Daemon.cpp +++ b/common/threading/Daemon.cpp @@ -69,7 +69,7 @@ void cta::server::Daemon::daemonizeIfNotRunInForegroundAndSetUserAndGroup(const { pid_t pid = 0; - cta::exception::Errnum::throwOnNegative(pid = fork(), + cta::exception::Errnum::throwOnMinusOne(pid = fork(), "Failed to daemonize: Failed to fork"); // If we got a good PID, then we can exit the parent process if (0 < pid) { @@ -85,7 +85,7 @@ void cta::server::Daemon::daemonizeIfNotRunInForegroundAndSetUserAndGroup(const umask(0177); // Run the daemon in a new session - cta::exception::Errnum::throwOnNegative(setsid(), + cta::exception::Errnum::throwOnMinusOne(setsid(), "Failed to daemonize: Failed to run daemon is a new session"); // Redirect standard files to /dev/null diff --git a/common/utils/utils.cpp b/common/utils/utils.cpp index 90b5e1d7abb3788acfc494511359c7d84596d4bb..ec4d0241caa330c516d908688c7fd3b9207c2ca3 100644 --- a/common/utils/utils.cpp +++ b/common/utils/utils.cpp @@ -21,6 +21,7 @@ #include "common/utils/strerror_r_wrapper.hpp" #include "common/utils/utils.hpp" +#include <algorithm> #include <attr/xattr.h> #include <limits> #include <memory> diff --git a/disk/DiskFileImplementations.hpp b/disk/DiskFileImplementations.hpp index d230397affdd83bc9dbb5dbe261ed8efa99edd9e..d5d0f03fcac6f7eb9e636e59ab9dd33d65352034 100644 --- a/disk/DiskFileImplementations.hpp +++ b/disk/DiskFileImplementations.hpp @@ -27,7 +27,6 @@ #include <radosstriper/libradosstriper.hpp> namespace cta::disk { - /** * Namespace managing the reading and writing of files to and from disk. */ @@ -60,15 +59,6 @@ namespace cta::disk { bool m_closeTried; }; - //============================================================================== - // CRYPTOPP SIGNER - //============================================================================== - struct CryptoPPSigner { - static std::string sign(const std::string msg, - const CryptoPP::RSA::PrivateKey & privateKey); - static cta::threading::Mutex s_mutex; - }; - //============================================================================== // XROOT FILES //============================================================================== @@ -248,5 +238,4 @@ namespace cta::disk { std::string m_truncatedDirectoryURL; // root://.../ part of the path is removed const uint16_t c_xrootTimeout = 15; }; - } // namespace cta::disk diff --git a/objectstore/BackendRados.cpp b/objectstore/BackendRados.cpp index 52441bb1d7599c9f90277d09341ab5c6e471b41d..d3086938f18d0e17ad20e05a465fb7a9a6ac2d8d 100644 --- a/objectstore/BackendRados.cpp +++ b/objectstore/BackendRados.cpp @@ -90,22 +90,22 @@ BackendRados::BackendRados(log::Logger& logger, const std::string& userId, const m_logger(logger), m_user(userId), m_pool(pool), m_namespace(radosNameSpace) { log::LogContext lc(logger); - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this, &userId]() { return -m_cluster.init(userId.c_str()); }, "In BackendRados::BackendRados, failed to m_cluster.init"); try { RadosTimeoutLogger rtl; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this]() { return -m_cluster.conf_read_file(nullptr); }, "In BackendRados::BackendRados, failed to m_cluster.conf_read_file"); rtl.logIfNeeded("In BackendRados::BackendRados(): m_cluster.conf_read_file()", "no object"); rtl.reset(); - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this]() { return -m_cluster.conf_parse_env(nullptr);}, "In BackendRados::BackendRados, failed to m_cluster.conf_parse_env"); rtl.logIfNeeded("In BackendRados::BackendRados(): m_cluster.conf_parse_env()", "no object"); rtl.reset(); - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this]() { return -m_cluster.connect();}, "In BackendRados::BackendRados, failed to m_cluster.connect"); rtl.logIfNeeded("In BackendRados::BackendRados(): m_cluster.connect()", "no object"); @@ -116,7 +116,7 @@ BackendRados::BackendRados(log::Logger& logger, const std::string& userId, const params.add("contextId", i); lc.log(log::DEBUG, "BackendRados::BackendRados() about to create a new context"); rtl.reset(); - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this, &pool]() { return -m_cluster.ioctx_create(pool.c_str(), m_radosCtxPool.back()); }, "In BackendRados::BackendRados, failed to m_cluster.ioctx_create"); rtl.logIfNeeded("In BackendRados::BackendRados(): m_cluster.ioctx_create()", "no object"); @@ -130,7 +130,7 @@ BackendRados::BackendRados(log::Logger& logger, const std::string& userId, const lc.log(log::DEBUG, "BackendRados::BackendRados() namespace set. About to test access."); // Try to read a non-existing object through the newly created context, in hope this will protect against // race conditions(?) when creating the contexts in a tight loop. - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this, &bl, &rtl]() { auto rc = m_radosCtxPool.back().read("TestObjectThatDoesNotNeedToExist", bl, 1, 0); rtl.logIfNeeded("In BackendRados::BackendRados(): m_radosCtxPool.back().read()", "TestObjectThatDoesNotNeedToExist"); @@ -215,7 +215,7 @@ void BackendRados::create(const std::string& name, const std::string& content) { { RadosTimeoutLogger rtl; try { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this, &name, &wop]() { return -getRadosCtx().operate(name, &wop); }, @@ -261,7 +261,7 @@ void BackendRados::atomicOverwrite(const std::string& name, const std::string& c bl.append(content.c_str(), content.size()); wop.write_full(bl); RadosTimeoutLogger rtl; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this, &name, &wop]() { return -getRadosCtx().operate(name, &wop); }, std::string("In BackendRados::atomicOverwrite, failed to assert existence or write: ") + name); rtl.logIfNeeded("In BackendRados::atomicOverwrite(): m_radosCtx.operate(assert_exists+write_full)", name); @@ -272,7 +272,7 @@ std::string BackendRados::read(const std::string& name) { librados::bufferlist bl; RadosTimeoutLogger rtl; try { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this, &name, &bl]() { auto rc = getRadosCtx().read(name, bl, std::numeric_limits<int32_t>::max(), 0); return rc < 0 ? rc : 0; @@ -295,7 +295,7 @@ std::string BackendRados::read(const std::string& name) { void BackendRados::remove(const std::string& name) { RadosTimeoutLogger rtl; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this, &name]() { return -getRadosCtx().remove(name); }); rtl.logIfNeeded("In BackendRados::remove(): m_radosCtx.remove()", name); } @@ -305,7 +305,7 @@ bool BackendRados::exists(const std::string& name) { time_t date; RadosTimeoutLogger rtl; int statRet; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [this, &statRet, &name, &size, &date]() { statRet = getRadosCtx().stat(name, &size, &date); return 0; @@ -327,19 +327,19 @@ std::list<std::string> BackendRados::list() { std::list<std::string> ret; auto& ctx = getRadosCtx(); decltype(ctx.nobjects_begin()) o; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [&o, &ctx]() { o = ctx.nobjects_begin(); return 0; }, "In BackendRados::list(): failed to ctx.nobjects_begin()"); bool go; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [&go, &o, &ctx]() { go = (o != ctx.nobjects_end()); return 0; }, "In BackendRados::list(): failed ctx.nobjects_end()"); while(go) { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException( + throwOnReturnedErrnoOrThrownStdException( [&ret, &o, &go, &ctx]() { ret.push_back(o->get_oid()); o++; @@ -367,7 +367,7 @@ void BackendRados::ScopedLock::releaseNotify() { // we hence overlook the ENOENT errors. TIMESTAMPEDPRINT("Pre-release"); RadosTimeoutLogger rtl1; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([this, &rtl1]() { + throwOnReturnedErrnoOrThrownStdException([this, &rtl1]() { int rc=m_context.unlock(m_oid, "lock", m_clientId); rtl1.logIfNeeded("In BackendRados::ScopedLock::releaseNotify(): m_context.unlock()", m_oid); return rc==-ENOENT?0:-rc; @@ -381,7 +381,7 @@ void BackendRados::ScopedLock::releaseNotify() { // We use a fire and forget aio call. librados::AioCompletion * completion = librados::Rados::aio_create_completion(nullptr, nullptr, nullptr); RadosTimeoutLogger rtl2; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([this, &completion, &bl]() { return -m_context.aio_notify(m_oid, completion, bl, 10000, nullptr);}, + throwOnReturnedErrnoOrThrownStdException([this, &completion, &bl]() { return -m_context.aio_notify(m_oid, completion, bl, 10000, nullptr);}, "In BackendRados::ScopedLock::releaseNotify(): failed to aio_notify()"); rtl2.logIfNeeded("In BackendRados::ScopedLock::releaseNotify(): m_context.aio_notify()", m_oid); completion->release(); @@ -397,7 +397,7 @@ void BackendRados::ScopedLock::releaseBackoff() { TIMESTAMPEDPRINT("Pre-release"); RadosTimeoutLogger rtl1; int rc; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([this, &rc]() { + throwOnReturnedErrnoOrThrownStdException([this, &rc]() { rc=m_context.unlock(m_oid, "lock", m_clientId); return 0; }, "In BackendRados::ScopedLock::releaseBackoff(): failed m_context.unlock()"); @@ -437,7 +437,7 @@ BackendRados::LockWatcher::LockWatcher(librados::IoCtx& context, const std::stri m_internal->m_future = m_internal->m_promise.get_future(); TIMESTAMPEDPRINT("Pre-watch2"); RadosTimeoutLogger rtl; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([this, &name]() { return -m_context.watch2(name, &m_watchHandle, m_internal.get());}, + throwOnReturnedErrnoOrThrownStdException([this, &name]() { return -m_context.watch2(name, &m_watchHandle, m_internal.get());}, "In BackendRados::LockWatcher::LockWatcher(): failed m_context.watch2()"); rtl.logIfNeeded("In BackendRados::LockWatcher::LockWatcher(): m_context.watch2()", name); TIMESTAMPEDPRINT("Post-watch2"); @@ -472,7 +472,7 @@ BackendRados::LockWatcher::~LockWatcher() { librados::AioCompletion *completion = librados::Rados::aio_create_completion(m_internal.release(), nullptr, Internal::deleter); RadosTimeoutLogger rtl; try { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([this, &completion]() { + throwOnReturnedErrnoOrThrownStdException([this, &completion]() { m_context.aio_unwatch(m_watchHandle, completion); return 0; }, "In BackendRados::LockWatcher::~LockWatcher(): failed m_context.aio_unwatch()"); @@ -526,13 +526,13 @@ void BackendRados::lockNotify(const std::string& name, uint64_t timeout_us, Lock TIMESTAMPEDPRINT(lockType==LockType::Shared?"Pre-lock (shared)":"Pre-lock (exclusive)"); RadosTimeoutLogger rtl; if(lockType==LockType::Shared) { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &tv]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &tv]() { rc = radosCtx.lock_shared(name, "lock", clientId, "", "", &tv, 0); return 0; }, "In BackendRados::lockNotify: failed radosCtx.lock_shared()"); rtl.logIfNeeded("In BackendRados::lockNotify(): m_radosCtx.lock_shared()", name); } else { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &tv]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &tv]() { rc = radosCtx.lock_exclusive(name, "lock", clientId, "", &tv, 0); return 0; }, "In BackendRados::lockNotify: failed radosCtx.lock_exclusive()"); @@ -553,13 +553,13 @@ void BackendRados::lockNotify(const std::string& name, uint64_t timeout_us, Lock // We need to retry the lock after establishing the watch: it could have been released during that time. rtl.reset(); if (lockType==LockType::Shared) { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &tv]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &tv]() { rc = radosCtx.lock_shared(name, "lock", clientId, "", "", &tv, 0); return 0; }, "In BackendRados::lockNotify: failed radosCtx.lock_shared()(2)"); rtl.logIfNeeded("In BackendRados::lockNotify(): m_radosCtx.lock_shared()", name); } else { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &tv]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &tv]() { rc = radosCtx.lock_exclusive(name, "lock", clientId, "", &tv, 0); return 0; }, "In BackendRados::lockNotify: failed radosCtx.lock_shared()(2)"); @@ -595,12 +595,12 @@ void BackendRados::lockNotify(const std::string& name, uint64_t timeout_us, Lock // Get the size: uint64_t size; time_t date; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException ([&radosCtx, &name, &size, &date]() { return -radosCtx.stat(name, &size, &date); }, + throwOnReturnedErrnoOrThrownStdException ([&radosCtx, &name, &size, &date]() { return -radosCtx.stat(name, &size, &date); }, std::string("In BackendRados::lock, failed to librados::IoCtx::stat: ") + name + "/" + "lock" + "/" + clientId + "//"); if (!size) { // The object has a zero size: we probably created it by attempting the locking. - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException ([&radosCtx, &name]() { return -radosCtx.remove(name);}, + throwOnReturnedErrnoOrThrownStdException ([&radosCtx, &name]() { return -radosCtx.remove(name);}, std::string("In BackendRados::lock, failed to librados::IoCtx::remove: ") + name + "//"); throw cta::exception::NoSuchObject(std::string("In BackendRados::lockWatch(): " @@ -749,14 +749,14 @@ void BackendRados::lockBackoff(const std::string& name, uint64_t timeout_us, Loc TIMESTAMPEDPRINT(lockType==LockType::Shared?"Pre-lock (shared)":"Pre-lock (exclusive)"); RadosTimeoutLogger rtl; if (lockType==LockType::Shared) { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &radosLockExpirationTime, &timingMeasurements, &t, &timeoutTimer]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &radosLockExpirationTime, &timingMeasurements, &t, &timeoutTimer]() { rc = radosCtx.lock_shared(name, "lock", clientId, "", "", &radosLockExpirationTime, 0); timingMeasurements.addSuccess(t.secs(), timeoutTimer.secs()); return 0; }, "In BackendRados::lockBackoff(): failed radosCtx.lock_shared()"); rtl.logIfNeeded("In BackendRados::lockBackoff(): radosCtx.lock_shared()", name); } else { - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &radosLockExpirationTime, &timingMeasurements, &t, &timeoutTimer]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &radosCtx, &name, &clientId, &radosLockExpirationTime, &timingMeasurements, &t, &timeoutTimer]() { rc = radosCtx.lock_exclusive(name, "lock", clientId, "", &radosLockExpirationTime, 0); timingMeasurements.addSuccess(t.secs(), timeoutTimer.secs()); return 0; @@ -800,12 +800,12 @@ void BackendRados::lockBackoff(const std::string& name, uint64_t timeout_us, Loc // Get the size: uint64_t size; time_t date; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException ([&radosCtx, &name, &size, &date]() { return -radosCtx.stat(name, &size, &date); }, + throwOnReturnedErrnoOrThrownStdException ([&radosCtx, &name, &size, &date]() { return -radosCtx.stat(name, &size, &date); }, std::string("In BackendRados::lockBackoff, failed to librados::IoCtx::stat: ") + name + "/" + "lock" + "/" + clientId + "//"); if (!size) { // The object has a zero size: we probably created it by attempting the locking. - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException ([&radosCtx, &name]() { return -radosCtx.remove(name); }, + throwOnReturnedErrnoOrThrownStdException ([&radosCtx, &name]() { return -radosCtx.remove(name); }, std::string("In BackendRados::lockBackoff, failed to librados::IoCtx::remove: ") + name + "//"); throw cta::exception::NoSuchObject(std::string("In BackendRados::lockBackoff(): " @@ -871,7 +871,7 @@ m_backend(be), m_name(name), m_value(value), m_job(), m_jobFuture(m_job.get_futu m_radosTimeoutLogger.reset(); RadosTimeoutLogger rtl; int rc; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([this, &rc, &aioc, &wop]() { + throwOnReturnedErrnoOrThrownStdException([this, &rc, &aioc, &wop]() { rc=m_backend.getRadosCtx().aio_operate(m_name, aioc, &wop); return 0; }, "In BackendRados::AsyncCreator::AsyncCreator(): failed m_backend.getRadosCtx().aio_operate()"); @@ -903,7 +903,7 @@ void BackendRados::AsyncCreator::createExclusiveCallback(librados::completion_t RadosTimeoutLogger rtl; int rc; librados::AioCompletion * aioc = librados::Rados::aio_create_completion(pThis, statCallback, nullptr); - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &ac, &aioc]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &ac, &aioc]() { rc=ac.m_backend.getRadosCtx().aio_stat(ac.m_name, aioc, &ac.m_size, &ac.m_time); return 0; }, "In BackendRados::AsyncCreator::createExclusiveCallback(): failed m_backend.getRadosCtx().aio_operate()"); @@ -940,7 +940,7 @@ void BackendRados::AsyncCreator::statCallback(librados::completion_t completion, ac.m_radosTimeoutLogger.reset(); RadosTimeoutLogger rtl; int rc; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &ac, &aioc, &wop]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &ac, &aioc, &wop]() { rc=ac.m_backend.getRadosCtx().aio_operate(ac.m_name, aioc, &wop); return 0; }, "In BackendRados::AsyncCreator::statCallback(): failed m_backend.getRadosCtx().aio_operate()"); @@ -976,7 +976,7 @@ void BackendRados::AsyncCreator::statCallback(librados::completion_t completion, RadosTimeoutLogger rtl; int rc; librados::AioCompletion * aioc = librados::Rados::aio_create_completion(pThis, statCallback, nullptr); - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &ac, &aioc]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &ac, &aioc]() { rc=ac.m_backend.getRadosCtx().aio_stat(ac.m_name, aioc, &ac.m_size, &ac.m_time); return 0; }, "In BackendRados::AsyncCreator::statCallback(): failed m_backend.getRadosCtx().aio_operate()"); @@ -1019,7 +1019,7 @@ BackendRados::AsyncUpdater::AsyncUpdater(BackendRados& be, const std::string& na RadosTimeoutLogger rtl; m_radosTimeoutLogger.reset(); int rc; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([this, &rc, &aioc]() { + throwOnReturnedErrnoOrThrownStdException([this, &rc, &aioc]() { rc=m_backend.getRadosCtx().aio_read(m_name, aioc, &m_radosBufferList, std::numeric_limits<int32_t>::max(), 0); return 0; }, std::string("In AsyncUpdater::AsyncUpdater::lock_lambda(): failed getRadosCtx().aio_read(): ")+m_name); @@ -1136,7 +1136,7 @@ void BackendRados::AsyncUpdater::UpdateJob::execute() { RadosTimeoutLogger rtl; au.m_radosTimeoutLogger.reset(); int rc; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &au, &aioc]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &au, &aioc]() { rc=au.m_backend.getRadosCtx().aio_write_full(au.m_name, aioc, au.m_radosBufferList); return 0; }, "In BackendRados::AsyncUpdater::UpdateJob::execute(): failed m_backend.getRadosCtx().aio_write_full()"); @@ -1169,7 +1169,7 @@ void BackendRados::AsyncUpdater::commitCallback(librados::completion_t completio au.m_radosTimeoutLogger.reset(); RadosTimeoutLogger rtl; int rc; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &au, &aioc]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &au, &aioc]() { rc=au.m_backend.getRadosCtx().aio_unlock(au.m_name, "lock", au.m_lockClient, aioc); return 0; }, "In BackendRados::AsyncUpdater::commitCallback(): failed to m_backend.getRadosCtx().aio_unlock()"); @@ -1234,7 +1234,7 @@ BackendRados::AsyncDeleter::AsyncDeleter(BackendRados& be, const std::string& na m_radosTimeoutLogger.reset(); RadosTimeoutLogger rtl; int rc; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([this, &rc, &aioc]() { + throwOnReturnedErrnoOrThrownStdException([this, &rc, &aioc]() { rc=m_backend.getRadosCtx().aio_remove(m_name, aioc); return 0; }, "In BackendRados::AsyncDeleter::AsyncDeleter(): failed m_backend.getRadosCtx().aio_remove()"); @@ -1300,7 +1300,7 @@ void BackendRados::AsyncLockfreeFetcher::AioReadPoster::execute() { RadosTimeoutLogger rtl; au.m_radosTimeoutLogger.reset(); int rc; - cta::exception::Errnum::throwOnReturnedErrnoOrThrownStdException([&rc, &au, &aioc]() { + throwOnReturnedErrnoOrThrownStdException([&rc, &au, &aioc]() { rc=au.m_backend.getRadosCtx().aio_read(au.m_name, aioc, &au.m_radosBufferList, std::numeric_limits<int32_t>::max(), 0); return 0; }, "In BackendRados::AsyncLockfreeFetcher::AioReadPoster::execute(): failed m_backend.getRadosCtx().aio_read()"); diff --git a/objectstore/BackendRados.hpp b/objectstore/BackendRados.hpp index e171d710b1b796b429ebb15e97fa98e143f8f100..71a7865bfe4e07f7bebb258ba05a80e4d459d912 100644 --- a/objectstore/BackendRados.hpp +++ b/objectstore/BackendRados.hpp @@ -112,6 +112,21 @@ public: static const size_t c_backoffFraction; static const uint64_t c_maxWait; + // This method was originally part of cta::exception::Errnum. As it is only used in the BackupRados class, + // it has been moved here. + template <typename F> + static void throwOnReturnedErrnoOrThrownStdException(F f, std::string_view context = "") { + try { + exception::Errnum::throwOnReturnedErrno(f(), context); + } catch(exception::Errnum&) { + throw; // Let the exception of throwOnReturnedErrno pass through + } catch(std::error_code& ec) { + throw exception::Errnum(ec.value(), std::string(context) + " Got a std::error_code: " + ec.message()); + } catch(std::exception& ex) { + throw exception::Exception(std::string(context) + " Got a std::exception: " + ex.what()); + } + } + private: static std::string createUniqueClientId(); /** This function will lock or die (actually throw, that is) */ diff --git a/objectstore/BackendTest.cpp b/objectstore/BackendTest.cpp index db47f803da0ae5dff33652cd823eb1974d9a9293..65312c8142a5ebd88e585dc38162f2228d286d86 100644 --- a/objectstore/BackendTest.cpp +++ b/objectstore/BackendTest.cpp @@ -222,6 +222,13 @@ TEST_P(BackendAbstractTest, ParametersInterface) { //std::cout << params->toStr() << std::endl; } +TEST(BackendAbstractTest, Errnum_throwers) { + ASSERT_NO_THROW(cta::objectstore::BackendRados::throwOnReturnedErrnoOrThrownStdException([](){ return 0; }, "Context")); + ASSERT_THROW(cta::objectstore::BackendRados::throwOnReturnedErrnoOrThrownStdException([](){ return ENOSPC; }, "Context"), cta::exception::Errnum); + ASSERT_THROW(cta::objectstore::BackendRados::throwOnReturnedErrnoOrThrownStdException([](){ throw std::error_code(ENOSPC, std::system_category()); return 0; }, "Context"), cta::exception::Errnum); + ASSERT_THROW(cta::objectstore::BackendRados::throwOnReturnedErrnoOrThrownStdException([](){ throw std::exception(); return 0; }, "Context"), cta::exception::Exception); +} + static cta::objectstore::BackendVFS osVFS(__LINE__, __FILE__); #ifdef TEST_RADOS static cta::log::DummyLogger dl("", "");