struct RequestDone : sc::event<RequestDone> {
};
+ struct CancelBackfill : sc::event<CancelBackfill> {
+ };
+
private:
// internal events
struct RequestPrimaryScanning : sc::event<RequestPrimaryScanning> {
explicit Crashed();
};
+ struct Cancelled : sc::simple_state<Cancelled, BackfillMachine>,
+ StateHelper<Cancelled> {
+ explicit Cancelled();
+ };
+
struct Initial : sc::state<Initial, BackfillMachine>,
StateHelper<Initial> {
using reactions = boost::mpl::list<
sc::custom_reaction<Triggered>,
+ sc::transition<CancelBackfill, Cancelled>,
sc::transition<sc::event_base, Crashed>>;
explicit Initial(my_context);
// initialize after triggering backfill by on_activate_complete().
struct Enqueuing : sc::state<Enqueuing, BackfillMachine>,
StateHelper<Enqueuing> {
using reactions = boost::mpl::list<
+ sc::transition<CancelBackfill, Cancelled>,
sc::transition<RequestPrimaryScanning, PrimaryScanning>,
sc::transition<RequestReplicasScanning, ReplicasScanning>,
sc::transition<RequestWaiting, Waiting>,
sc::custom_reaction<ObjectPushed>,
sc::custom_reaction<PrimaryScanned>,
sc::transition<RequestDone, Done>,
+ sc::transition<CancelBackfill, Cancelled>,
sc::transition<sc::event_base, Crashed>>;
explicit PrimaryScanning(my_context);
sc::result react(ObjectPushed);
sc::custom_reaction<ObjectPushed>,
sc::custom_reaction<ReplicaScanned>,
sc::transition<RequestDone, Done>,
+ sc::transition<CancelBackfill, Cancelled>,
sc::transition<sc::event_base, Crashed>>;
explicit ReplicasScanning(my_context);
// collect scanning result; if all results are collected, transition
using reactions = boost::mpl::list<
sc::custom_reaction<ObjectPushed>,
sc::transition<RequestDone, Done>,
+ sc::transition<CancelBackfill, Cancelled>,
sc::transition<sc::event_base, Crashed>>;
explicit Waiting(my_context);
sc::result react(ObjectPushed);
PeeringState::Backfilled{});
}
+void PGRecovery::backfill_cancelled()
+{
+ // We are not creating a new BackfillRecovery request here, as we
+ // need to cancel the backfill synchronously (before this method returns).
+ using BackfillState = crimson::osd::BackfillState;
+ backfill_state->process_event(
+ BackfillState::CancelBackfill{}.intrusive_from_this());
+ backfill_state.reset();
+}
+
void PGRecovery::dispatch_backfill_event(
boost::intrusive_ptr<const boost::statechart::event_base> evt)
{
logger().debug("{}", __func__);
- backfill_state->process_event(evt);
+ if (backfill_state) {
+ backfill_state->process_event(evt);
+ } else {
+ // TODO: Do we need to worry about cases in which the pg has
+ // been through both backfill cancellations and backfill
+ // restarts between the sendings and replies of
+ // ReplicaScan/ObjectPush requests? Seems classic OSDs
+ // doesn't handle these cases.
+ logger().debug("{}, backfill cancelled, dropping evt");
+ }
}
void PGRecovery::on_backfill_reserved()