Skip to content

Commit eb22a6f

Browse files
committed
osd/scrub: decoupling the FSM from the scrubber
The scrubber FSM has always been accessing the PgScrubber object via an abstract interface (ScrubMachineListener). But the reverse was not true: the PgScrubber owned a unique_ptr directly to an instance of Scrubber::ScrubMachine. This PR introduces a new interface, ScrubFsmIf, that is implemented by the ScrubMachine. This simplifies unit-testing the PgScrubber, as we can now inject a mock implementation of the FSM interface. Signed-off-by: Ronen Friedman <[email protected]>
1 parent 345911e commit eb22a6f

File tree

3 files changed

+77
-9
lines changed

3 files changed

+77
-9
lines changed

src/osd/scrubber/pg_scrubber.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Main Scrubber interfaces:
8484
#include "osd_scrub_sched.h"
8585
#include "scrub_backend.h"
8686
#include "scrub_machine_lstnr.h"
87+
#include "scrub_machine_if.h"
8788
#include "scrub_reservations.h"
8889

8990
namespace Scrub {
@@ -693,7 +694,7 @@ class PgScrubber : public ScrubPgIF,
693694
hobject_t end,
694695
bool deep);
695696

696-
std::unique_ptr<Scrub::ScrubMachine> m_fsm;
697+
std::unique_ptr<Scrub::ScrubFsmIf> m_fsm;
697698
/// the FSM state, as a string for logging
698699
const char* m_fsm_state_name{nullptr};
699700
const spg_t m_pg_id; ///< a local copy of m_pg->pg_id

src/osd/scrubber/scrub_machine.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// vim: ts=8 sw=2 smarttab
33
#pragma once
44

5+
#include <cassert>
56
#include <optional>
67
#include <string>
78

@@ -23,6 +24,7 @@
2324
#include "messages/MOSDRepScrubMap.h"
2425
#include "osd/scrubber_common.h"
2526

27+
#include "scrub_machine_if.h"
2628
#include "scrub_machine_lstnr.h"
2729
#include "scrub_reservations.h"
2830

@@ -278,28 +280,34 @@ struct ReplicaWaitUpdates;
278280
struct ReplicaBuildingMap;
279281

280282

281-
class ScrubMachine : public sc::state_machine<ScrubMachine, NotActive> {
283+
class ScrubMachine : public ScrubFsmIf, public sc::state_machine<ScrubMachine, NotActive> {
282284
public:
283285
friend class PgScrubber;
284286

285287
public:
286288
explicit ScrubMachine(PG* pg, ScrubMachineListener* pg_scrub);
287-
~ScrubMachine();
289+
virtual ~ScrubMachine();
288290

289291
spg_t m_pg_id;
290292
ScrubMachineListener* m_scrbr;
291293
std::ostream& gen_prefix(std::ostream& out) const;
292294

293-
void assert_not_in_session() const;
294-
[[nodiscard]] bool is_reserving() const;
295-
[[nodiscard]] bool is_accepting_updates() const;
296-
[[nodiscard]] bool is_primary_idle() const;
295+
void assert_not_in_session() const final;
296+
[[nodiscard]] bool is_reserving() const final;
297+
[[nodiscard]] bool is_accepting_updates() const final;
298+
[[nodiscard]] bool is_primary_idle() const final;
297299

298300
/// elapsed time for the currently active scrub.session
299-
ceph::timespan get_time_scrubbing() const;
301+
ceph::timespan get_time_scrubbing() const final;
300302

301303
/// replica reservation process status
302-
std::optional<pg_scrubbing_status_t> get_reservation_status() const;
304+
std::optional<pg_scrubbing_status_t> get_reservation_status() const final;
305+
306+
void initiate() final { sc::state_machine<ScrubMachine, NotActive>::initiate(); }
307+
308+
void process_event(const boost::statechart::event_base& evt) final {
309+
sc::state_machine<ScrubMachine, NotActive>::process_event(evt);
310+
}
303311

304312
// ///////////////// aux declarations & functions //////////////////////// //
305313

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2+
// vim: ts=8 sw=2 smarttab
3+
4+
#pragma once
5+
/**
6+
* \file the FSM API used by the scrubber
7+
*/
8+
#include <boost/statechart/event.hpp>
9+
#include <boost/statechart/event_base.hpp>
10+
#include <boost/statechart/simple_state.hpp>
11+
#include <boost/statechart/state.hpp>
12+
#include <boost/statechart/state_machine.hpp>
13+
14+
#include "osd/scrubber_common.h"
15+
16+
namespace Scrub {
17+
18+
namespace sc = ::boost::statechart;
19+
20+
21+
/// the FSM API used by the scrubber
22+
class ScrubFsmIf {
23+
public:
24+
virtual ~ScrubFsmIf() = default;
25+
26+
virtual void process_event(const sc::event_base& evt) = 0;
27+
28+
/// 'true' if the FSM state is PrimaryActive/PrimaryIdle
29+
[[nodiscard]] virtual bool is_primary_idle() const = 0;
30+
31+
/// 'true' if the FSM state is PrimaryActive/Session/ReservingReplicas
32+
[[nodiscard]] virtual bool is_reserving() const = 0;
33+
34+
/// 'true' if the FSM state is PrimaryActive/Session/Act/WaitLastUpdate
35+
[[nodiscard]] virtual bool is_accepting_updates() const = 0;
36+
37+
/// verify state is not any substate of PrimaryActive/Session
38+
virtual void assert_not_in_session() const = 0;
39+
40+
/**
41+
* time passed since entering the current scrubbing session.
42+
* Specifically - since the Session ctor has completed.
43+
*/
44+
virtual ceph::timespan get_time_scrubbing() const = 0;
45+
46+
/**
47+
* if we are in the ReservingReplicas state - fetch the reservation status.
48+
* The returned data names the last request sent to the replicas, and
49+
* how many replicas responded / are yet expected to respond.
50+
*/
51+
virtual std::optional<pg_scrubbing_status_t> get_reservation_status()
52+
const = 0;
53+
54+
/// "initiate" the state machine (an internal state_chart function)
55+
virtual void initiate() = 0;
56+
};
57+
58+
} // namespace Scrub
59+

0 commit comments

Comments
 (0)