#include "common/version.h"
#include "include/Context.h"
+#include "osd/scrubber_common.h"
#include "scrub_machine_lstnr.h"
-#include "osd/scrubber_common.h"
-using namespace std::string_literals;
+/// a wrapper that sets the FSM state description used by the
+/// PgScrubber
+/// \todo consider using the full NamedState as in Peering
+struct NamedSimply {
+ explicit NamedSimply(ScrubMachineListener* scrubber, const char* name);
+};
class PG; // holding a pointer to that one - just for testing
class PgScrubber;
+
namespace Scrub {
namespace sc = ::boost::statechart;
std::string_view print() const { return #E; } \
};
-MEV(RemotesReserved) ///< all replicas have granted our reserve request
+/// all replicas have granted our reserve request
+MEV(RemotesReserved)
-MEV(ReservationFailure) ///< a reservation request has failed
+/// a reservation request has failed
+MEV(ReservationFailure)
-MEV(StartScrub) ///< initiate a new scrubbing session (relevant if we are a Primary)
+/// initiate a new scrubbing session (relevant if we are a Primary)
+MEV(StartScrub)
-MEV(AfterRepairScrub) ///< initiate a new scrubbing session. Only triggered at Recovery
- ///< completion.
+/// initiate a new scrubbing session. Only triggered at Recovery completion
+MEV(AfterRepairScrub)
-MEV(Unblocked) ///< triggered when the PG unblocked an object that was marked for
- ///< scrubbing. Via the PGScrubUnblocked op
+/// triggered when the PG unblocked an object that was marked for scrubbing.
+/// Via the PGScrubUnblocked op
+MEV(Unblocked)
MEV(InternalSchedScrub)
MEV(ChunkIsBusy)
-MEV(ActivePushesUpd) ///< Update to active_pushes. 'active_pushes' represents recovery
- ///< that is in-flight to the local ObjectStore
+/// Update to active_pushes. 'active_pushes' represents recovery that
+/// is in-flight to the local ObjectStore
+MEV(ActivePushesUpd)
-MEV(UpdatesApplied) ///< (Primary only) all updates are committed
+/// (Primary only) all updates are committed
+MEV(UpdatesApplied)
-MEV(InternalAllUpdates) ///< the internal counterpart of UpdatesApplied
+/// the internal counterpart of UpdatesApplied
+MEV(InternalAllUpdates)
-MEV(GotReplicas) ///< got a map from a replica
+/// got a map from a replica
+MEV(GotReplicas)
-MEV(IntBmPreempted) ///< internal - BuildMap preempted. Required, as detected within the
- ///< ctor
+/// internal - BuildMap preempted. Required, as detected within the ctor
+MEV(IntBmPreempted)
MEV(InternalError)
MEV(IntLocalMapDone)
-MEV(DigestUpdate) ///< external. called upon success of a MODIFY op. See
- ///< scrub_snapshot_metadata()
-
-MEV(MapsCompared) ///< maps_compare_n_cleanup() transactions are done
+/// external. called upon success of a MODIFY op. See
+/// scrub_snapshot_metadata()
+MEV(DigestUpdate)
-MEV(StartReplica) ///< initiating replica scrub.
+/// initiating replica scrub
+MEV(StartReplica)
-MEV(StartReplicaNoWait) ///< 'start replica' when there are no pending updates
+/// 'start replica' when there are no pending updates
+MEV(StartReplicaNoWait)
MEV(SchedReplica)
-MEV(ReplicaPushesUpd) ///< Update to active_pushes. 'active_pushes' represents recovery
- ///< that is in-flight to the local ObjectStore
+/// Update to active_pushes. 'active_pushes' represents recovery
+/// that is in-flight to the local ObjectStore
+MEV(ReplicaPushesUpd)
-MEV(FullReset) ///< guarantee that the FSM is in the quiescent state (i.e. NotActive)
+/// guarantee that the FSM is in the quiescent state (i.e. NotActive)
+MEV(FullReset)
-MEV(NextChunk) ///< finished handling this chunk. Go get the next one
+/// finished handling this chunk. Go get the next one
+MEV(NextChunk)
-MEV(ScrubFinished) ///< all chunks handled
+/// all chunks handled
+MEV(ScrubFinished)
+//
+// STATES
+//
struct NotActive; ///< the quiescent state. No active scrubbing.
struct ReservingReplicas; ///< securing scrub resources from replicas' OSDs
struct ActiveScrubbing; ///< the active state for a Primary. A sub-machine.
-struct ReplicaWaitUpdates; ///< an active state for a replica. Waiting for all active
- ///< operations to finish.
+struct ReplicaWaitUpdates; ///< an active state for a replica. Waiting for all
+ ///< active operations to finish.
struct ActiveReplica; ///< an active state for a replica.
ScrubMachineListener* m_scrbr;
std::ostream& gen_prefix(std::ostream& out) const;
- std::string current_states_desc() const;
void assert_not_active() const;
[[nodiscard]] bool is_reserving() const;
[[nodiscard]] bool is_accepting_updates() const;
/**
* The Scrubber's base (quiescent) state.
* Scrubbing is triggered by one of the following events:
- * - (standard scenario for a Primary): 'StartScrub'. Initiates the OSDs resources
- * reservation process. Will be issued by PG::scrub(), following a
+ *
+ * - (standard scenario for a Primary): 'StartScrub'. Initiates the OSDs
+ * resources reservation process. Will be issued by PG::scrub(), following a
* queued "PGScrub" op.
- * - a special end-of-recovery Primary scrub event ('AfterRepairScrub') that is
- * not required to reserve resources.
- * - (for a replica) 'StartReplica' or 'StartReplicaNoWait', triggered by an incoming
- * MOSDRepScrub message.
*
- * note (20.8.21): originally, AfterRepairScrub was triggering a scrub without waiting
- * for replica resources to be acquired. But once replicas started using the
- * resource-request to identify and tag the scrub session, this bypass cannot be
- * supported anymore.
+ * - a special end-of-recovery Primary scrub event ('AfterRepairScrub').
+ *
+ * - (for a replica) 'StartReplica' or 'StartReplicaNoWait', triggered by
+ * an incoming MOSDRepScrub message.
+ *
+ * note (20.8.21): originally, AfterRepairScrub was triggering a scrub without
+ * waiting for replica resources to be acquired. But once replicas started
+ * using the resource-request to identify and tag the scrub session, this
+ * bypass cannot be supported anymore.
*/
-struct NotActive : sc::state<NotActive, ScrubMachine> {
+struct NotActive : sc::state<NotActive, ScrubMachine>, NamedSimply {
explicit NotActive(my_context ctx);
- using reactions = mpl::list<sc::custom_reaction<StartScrub>,
- // a scrubbing that was initiated at recovery completion
- sc::custom_reaction<AfterRepairScrub>,
- sc::transition<StartReplica, ReplicaWaitUpdates>,
- sc::transition<StartReplicaNoWait, ActiveReplica>>;
+ using reactions =
+ mpl::list<sc::custom_reaction<StartScrub>,
+ // a scrubbing that was initiated at recovery completion:
+ sc::custom_reaction<AfterRepairScrub>,
+ sc::transition<StartReplica, ReplicaWaitUpdates>,
+ sc::transition<StartReplicaNoWait, ActiveReplica>>;
sc::result react(const StartScrub&);
sc::result react(const AfterRepairScrub&);
};
-struct ReservingReplicas : sc::state<ReservingReplicas, ScrubMachine> {
+struct ReservingReplicas : sc::state<ReservingReplicas, ScrubMachine>,
+ NamedSimply {
explicit ReservingReplicas(my_context ctx);
~ReservingReplicas();
// the "active" sub-states
-struct RangeBlocked; ///< the objects range is blocked
-struct PendingTimer; ///< either delaying the scrub by some time and requeuing, or just
- ///< requeue
-struct NewChunk; ///< select a chunk to scrub, and verify its availability
+/// the objects range is blocked
+struct RangeBlocked;
+
+/// either delaying the scrub by some time and requeuing, or just requeue
+struct PendingTimer;
+
+/// select a chunk to scrub, and verify its availability
+struct NewChunk;
+
struct WaitPushes;
struct WaitLastUpdate;
struct BuildMap;
-struct DrainReplMaps; ///< a problem during BuildMap. Wait for all replicas to report,
- ///< then restart.
-struct WaitReplicas; ///< wait for all replicas to report
+
+/// a problem during BuildMap. Wait for all replicas to report, then restart.
+struct DrainReplMaps;
+
+/// wait for all replicas to report
+struct WaitReplicas;
+
struct WaitDigestUpdate;
-struct ActiveScrubbing : sc::state<ActiveScrubbing, ScrubMachine, PendingTimer> {
+struct ActiveScrubbing
+ : sc::state<ActiveScrubbing, ScrubMachine, PendingTimer>, NamedSimply {
explicit ActiveScrubbing(my_context ctx);
~ActiveScrubbing();
- using reactions = mpl::list<
- sc::custom_reaction<InternalError>,
- sc::custom_reaction<FullReset>>;
+ using reactions = mpl::list<sc::custom_reaction<InternalError>,
+ sc::custom_reaction<FullReset>>;
sc::result react(const FullReset&);
sc::result react(const InternalError&);
};
-struct RangeBlocked : sc::state<RangeBlocked, ActiveScrubbing> {
+struct RangeBlocked : sc::state<RangeBlocked, ActiveScrubbing>, NamedSimply {
explicit RangeBlocked(my_context ctx);
using reactions = mpl::list<sc::transition<Unblocked, PendingTimer>>;
Scrub::BlockedRangeWarning m_timeout;
};
-struct PendingTimer : sc::state<PendingTimer, ActiveScrubbing> {
+struct PendingTimer : sc::state<PendingTimer, ActiveScrubbing>, NamedSimply {
explicit PendingTimer(my_context ctx);
using reactions = mpl::list<sc::transition<InternalSchedScrub, NewChunk>>;
};
-struct NewChunk : sc::state<NewChunk, ActiveScrubbing> {
+struct NewChunk : sc::state<NewChunk, ActiveScrubbing>, NamedSimply {
explicit NewChunk(my_context ctx);
* initiate the update process for this chunk
*
* Wait fo 'active_pushes' to clear.
- * 'active_pushes' represents recovery that is in-flight to the local Objectstore, hence
- * scrub waits until the correct data is readable (in-flight data to the Objectstore is
- * not readable until written to disk, termed 'applied' here)
+ * 'active_pushes' represents recovery that is in-flight to the local
+ * Objectstore, hence scrub waits until the correct data is readable
+ * (in-flight data to the Objectstore is not readable until written to
+ * disk, termed 'applied' here)
*/
-struct WaitPushes : sc::state<WaitPushes, ActiveScrubbing> {
+struct WaitPushes : sc::state<WaitPushes, ActiveScrubbing>, NamedSimply {
explicit WaitPushes(my_context ctx);
sc::result react(const ActivePushesUpd&);
};
-struct WaitLastUpdate : sc::state<WaitLastUpdate, ActiveScrubbing> {
+struct WaitLastUpdate : sc::state<WaitLastUpdate, ActiveScrubbing>,
+ NamedSimply {
explicit WaitLastUpdate(my_context ctx);
void on_new_updates(const UpdatesApplied&);
- using reactions = mpl::list<sc::custom_reaction<InternalAllUpdates>,
- sc::in_state_reaction<UpdatesApplied,
- WaitLastUpdate,
- &WaitLastUpdate::on_new_updates>>;
+ using reactions =
+ mpl::list<sc::custom_reaction<InternalAllUpdates>,
+ sc::in_state_reaction<UpdatesApplied,
+ WaitLastUpdate,
+ &WaitLastUpdate::on_new_updates>>;
sc::result react(const InternalAllUpdates&);
};
-struct BuildMap : sc::state<BuildMap, ActiveScrubbing> {
+struct BuildMap : sc::state<BuildMap, ActiveScrubbing>, NamedSimply {
explicit BuildMap(my_context ctx);
// possible error scenarios:
// handled by our parent state;
// - if preempted, we switch to DrainReplMaps, where we will wait for all
// replicas to send their maps before acknowledging the preemption;
- // - an interval change will be handled by the relevant 'send-event' functions,
- // and will translated into a 'FullReset' event.
- using reactions =
- mpl::list<sc::transition<IntBmPreempted, DrainReplMaps>,
- sc::transition<InternalSchedScrub, BuildMap>, // looping, waiting
- // for the backend to
- // finish
- sc::custom_reaction<IntLocalMapDone>>;
+ // - an interval change will be handled by the relevant 'send-event'
+ // functions, and will translated into a 'FullReset' event.
+ using reactions = mpl::list<sc::transition<IntBmPreempted, DrainReplMaps>,
+ // looping, waiting for the backend to finish:
+ sc::transition<InternalSchedScrub, BuildMap>,
+ sc::custom_reaction<IntLocalMapDone>>;
sc::result react(const IntLocalMapDone&);
};
/*
* "drain" scrub-maps responses from replicas
*/
-struct DrainReplMaps : sc::state<DrainReplMaps, ActiveScrubbing> {
+struct DrainReplMaps : sc::state<DrainReplMaps, ActiveScrubbing>, NamedSimply {
explicit DrainReplMaps(my_context ctx);
using reactions =
- mpl::list<sc::custom_reaction<GotReplicas> // all replicas are accounted for
- >;
+ // all replicas are accounted for:
+ mpl::list<sc::custom_reaction<GotReplicas>>;
sc::result react(const GotReplicas&);
};
-struct WaitReplicas : sc::state<WaitReplicas, ActiveScrubbing> {
+struct WaitReplicas : sc::state<WaitReplicas, ActiveScrubbing>, NamedSimply {
explicit WaitReplicas(my_context ctx);
- using reactions =
- mpl::list<sc::custom_reaction<GotReplicas>, // all replicas are accounted for
- sc::transition<MapsCompared, WaitDigestUpdate>,
- sc::custom_reaction<DigestUpdate>
- >;
+ using reactions = mpl::list<
+ // all replicas are accounted for:
+ sc::custom_reaction<GotReplicas>,
+ sc::custom_reaction<DigestUpdate>>;
sc::result react(const GotReplicas&);
sc::result react(const DigestUpdate&);
bool all_maps_already_called{false}; // see comment in react code
};
-struct WaitDigestUpdate : sc::state<WaitDigestUpdate, ActiveScrubbing> {
+struct WaitDigestUpdate : sc::state<WaitDigestUpdate, ActiveScrubbing>,
+ NamedSimply {
explicit WaitDigestUpdate(my_context ctx);
using reactions = mpl::list<sc::custom_reaction<DigestUpdate>,
- sc::custom_reaction<ScrubFinished>,
- sc::transition<NextChunk, PendingTimer>>;
+ sc::custom_reaction<ScrubFinished>,
+ sc::transition<NextChunk, PendingTimer>>;
sc::result react(const DigestUpdate&);
sc::result react(const ScrubFinished&);
};
-// ----------------------------- the "replica active" states -----------------------
+// ----------------------------- the "replica active" states
/*
* Waiting for 'active_pushes' to complete
* - the details of the Primary's request were internalized by PgScrubber;
* - 'active' scrubbing is set
*/
-struct ReplicaWaitUpdates : sc::state<ReplicaWaitUpdates, ScrubMachine> {
+struct ReplicaWaitUpdates : sc::state<ReplicaWaitUpdates, ScrubMachine>,
+ NamedSimply {
explicit ReplicaWaitUpdates(my_context ctx);
- using reactions =
- mpl::list<sc::custom_reaction<ReplicaPushesUpd>, sc::custom_reaction<FullReset>>;
+ using reactions = mpl::list<sc::custom_reaction<ReplicaPushesUpd>,
+ sc::custom_reaction<FullReset>>;
sc::result react(const ReplicaPushesUpd&);
sc::result react(const FullReset&);
};
-struct ActiveReplica : sc::state<ActiveReplica, ScrubMachine> {
+struct ActiveReplica : sc::state<ActiveReplica, ScrubMachine>, NamedSimply {
explicit ActiveReplica(my_context ctx);
using reactions = mpl::list<sc::custom_reaction<SchedReplica>,
- sc::custom_reaction<FullReset>,
- sc::transition<ScrubFinished, NotActive>>;
+ sc::custom_reaction<FullReset>>;
sc::result react(const SchedReplica&);
sc::result react(const FullReset&);