}
ceph_assert(peering_state().get_backfill_targets().size());
ceph_assert(!backfill_state().last_backfill_started.is_max());
+ backfill_state().replicas_in_backfill =
+ peering_state().get_backfill_targets().size();
}
boost::statechart::result
backfill_state().backfill_info,
backfill_state().peer_backfill_info)) {
return transit<Enqueuing>();
- } else if (backfill_state().progress_tracker->tracked_objects_completed()) {
- return transit<Done>();
} else {
// we still have something to wait on
logger().debug("Waiting::react() on ObjectPushed; still waiting");
struct Triggered : sc::event<Triggered> {
};
+ struct RequestDone : sc::event<RequestDone> {
+ };
+
private:
// internal events
struct RequestPrimaryScanning : sc::event<RequestPrimaryScanning> {
struct RequestWaiting : sc::event<RequestWaiting> {
};
- struct RequestDone : sc::event<RequestDone> {
- };
-
class ProgressTracker;
public:
sc::transition<RequestPrimaryScanning, PrimaryScanning>,
sc::transition<RequestReplicasScanning, ReplicasScanning>,
sc::transition<RequestWaiting, Waiting>,
- sc::transition<RequestDone, Done>,
sc::transition<sc::event_base, Crashed>>;
explicit Enqueuing(my_context);
using reactions = boost::mpl::list<
sc::custom_reaction<ObjectPushed>,
sc::custom_reaction<PrimaryScanned>,
+ sc::transition<RequestDone, Done>,
sc::transition<sc::event_base, Crashed>>;
explicit PrimaryScanning(my_context);
sc::result react(ObjectPushed);
using reactions = boost::mpl::list<
sc::custom_reaction<ObjectPushed>,
sc::custom_reaction<ReplicaScanned>,
+ sc::transition<RequestDone, Done>,
sc::transition<sc::event_base, Crashed>>;
explicit ReplicasScanning(my_context);
// collect scanning result; if all results are collected, transition
StateHelper<Waiting> {
using reactions = boost::mpl::list<
sc::custom_reaction<ObjectPushed>,
+ sc::transition<RequestDone, Done>,
sc::transition<sc::event_base, Crashed>>;
explicit Waiting(my_context);
sc::result react(ObjectPushed);
hobject_t get_last_backfill_started() const {
return last_backfill_started;
}
+
+ void backfill_target_done() {
+ ceph_assert(replicas_in_backfill > 0);
+ replicas_in_backfill--;
+ if (!replicas_in_backfill) {
+ backfill_machine.process_event(RequestDone{});
+ }
+ }
private:
hobject_t last_backfill_started;
BackfillInterval backfill_info;
std::map<pg_shard_t, BackfillInterval> peer_backfill_info;
BackfillMachine backfill_machine;
std::unique_ptr<ProgressTracker> progress_tracker;
+ size_t replicas_in_backfill = 0;
};
// BackfillListener -- an interface used by the backfill FSM to request
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
#include <algorithm>
#include <cstdlib>
#include <deque>
void BackfillFixture::update_peers_last_backfill(
const hobject_t& new_last_backfill)
{
+ if (new_last_backfill.is_max()) {
+ schedule_event(crimson::osd::BackfillState::RequestDone{});
+ }
}
bool BackfillFixture::budget_available() const
reference_store.objs
).get_result();
+ cluster_fixture.next_round();
cluster_fixture.next_round();
EXPECT_CALL(cluster_fixture, backfilled);
cluster_fixture.next_round();
cluster_fixture.next_round();
cluster_fixture.next_round();
cluster_fixture.next_round(2);
+ cluster_fixture.next_round();
EXPECT_CALL(cluster_fixture, backfilled);
cluster_fixture.next_round();
EXPECT_TRUE(cluster_fixture.all_stores_look_like(reference_store));