From: Casey Bodley Date: Wed, 24 May 2023 17:14:55 +0000 (-0400) Subject: common: FaultInjector supports InjectDelay X-Git-Tag: v18.1.3~10^2~7 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=9627f87bb956e3cea35b89d20d0a35a4230fc824;p=ceph-ci.git common: FaultInjector supports InjectDelay instead of injecting an error code or assertion failure, InjectDelay just injects an artificial delay before returning success Signed-off-by: Casey Bodley (cherry picked from commit 86cb15d3a53cff6f562baa9461f79549c6b82b88) --- diff --git a/src/common/fault_injector.h b/src/common/fault_injector.h index 53b247e08b0..b1ea52a57b4 100644 --- a/src/common/fault_injector.h +++ b/src/common/fault_injector.h @@ -14,11 +14,13 @@ #pragma once +#include #include #include #include #include #include "include/ceph_assert.h" +#include "common/ceph_time.h" #include "common/dout.h" /// @file @@ -34,13 +36,20 @@ struct InjectError { const DoutPrefixProvider* dpp = nullptr; }; +/// Injects a delay before returning success. +struct InjectDelay { + /// duration of the delay + ceph::timespan duration; + /// an optional log channel to print a message + const DoutPrefixProvider* dpp = nullptr; +}; + /** @class FaultInjector * @brief Used to instrument a code path with deterministic fault injection * by making one or more calls to check(). * * A default-constructed FaultInjector contains no failure. It can also be - * constructed with a failure of type InjectAbort or InjectError, along with - * a location to inject that failure. + * constructed with a failure type and a location to inject that failure. * * The contained failure can be overwritten with a call to inject() or clear(). * This is not thread-safe with respect to other member functions on the same @@ -67,6 +76,10 @@ class FaultInjector { constexpr FaultInjector(Key location, InjectError e) : location(std::move(location)), failure(e) {} + /// Construct with an injected delay at the given location. + constexpr FaultInjector(Key location, InjectDelay d) + : location(std::move(location)), failure(d) {} + /// Inject an assertion failure at the given location. void inject(Key location, InjectAbort a) { this->location = std::move(location); @@ -79,6 +92,12 @@ class FaultInjector { this->failure = e; } + /// Injecte a delay at the given location. + void inject(Key location, InjectDelay d) { + this->location = std::move(location); + this->failure = d; + } + /// Clear any injected failure. void clear() { this->failure = Empty{}; @@ -110,6 +129,14 @@ class FaultInjector { } return 0; } + int operator()(const InjectDelay& e) const { + if (check_location == this_location) { + ldpp_dout(e.dpp, -1) << "Injecting delay=" << e.duration + << " at location=" << this_location << dendl; + std::this_thread::sleep_for(e.duration); + } + return 0; + } }; return std::visit(visitor{location, this->location}, failure); } @@ -131,5 +158,5 @@ class FaultInjector { using Empty = std::monostate; // empty state for std::variant - std::variant failure; + std::variant failure; };