#include "crimson/osd/pg.h"
#include "crimson/osd/shard_services.h"
#include "common/Formatter.h"
+#include "crimson/osd/osd_operation_external_tracking.h"
#include "crimson/osd/osd_operations/background_recovery.h"
namespace {
namespace crimson::osd {
-BackgroundRecovery::BackgroundRecovery(
+template <class T>
+BackgroundRecoveryT<T>::BackgroundRecoveryT(
Ref<PG> pg,
ShardServices &ss,
epoch_t epoch_started,
scheduler_class(scheduler_class)
{}
-void BackgroundRecovery::print(std::ostream &lhs) const
+template <class T>
+void BackgroundRecoveryT<T>::print(std::ostream &lhs) const
{
lhs << "BackgroundRecovery(" << pg->get_pgid() << ")";
}
-void BackgroundRecovery::dump_detail(Formatter *f) const
+template <class T>
+void BackgroundRecoveryT<T>::dump_detail(Formatter *f) const
{
f->dump_stream("pgid") << pg->get_pgid();
f->open_object_section("recovery_detail");
f->close_section();
}
-seastar::future<> BackgroundRecovery::start()
+template <class T>
+seastar::future<> BackgroundRecoveryT<T>::start()
{
logger().debug("{}: start", *this);
- IRef ref = this;
+ typename T::IRef ref = static_cast<T*>(this);
auto maybe_delay = seastar::now();
if (delay) {
maybe_delay = seastar::sleep(
return maybe_delay.then([ref, this] {
return ss.throttler.with_throttle_while(
this, get_scheduler_params(), [this] {
- return interruptor::with_interruption([this] {
+ return T::interruptor::with_interruption([this] {
return do_recovery();
}, [](std::exception_ptr) {
return seastar::make_ready_future<bool>(false);
Ref<PG> pg,
ShardServices& ss,
epoch_t epoch_started)
- : BackgroundRecovery{pg, ss, epoch_started,
- crimson::osd::scheduler::scheduler_class_t::immediate},
+ : BackgroundRecoveryT{pg, ss, epoch_started,
+ crimson::osd::scheduler::scheduler_class_t::immediate},
soid{soid}, need(need)
{
}
ShardServices &ss,
const epoch_t epoch_started,
float delay)
- : BackgroundRecovery(
+ : BackgroundRecoveryT(
std::move(pg),
ss,
epoch_started,
return seastar::make_ready_future<bool>(false);
}
// TODO: limits
- return with_blocking_future_interruptible<interruptor::condition>(
+ return enter_stage<interruptor>(
// process_event() of our boost::statechart machine is non-reentrant.
// with the backfill_pipeline we protect it from a second entry from
// the implementation of BackfillListener.
// additionally, this stage serves to synchronize with PeeringEvent.
- handle.enter(bp(*pg).process)
+ bp(*pg).process
).then_interruptible([this] {
pg->get_recovery_handler()->dispatch_backfill_event(std::move(evt));
return seastar::make_ready_future<bool>(false);
});
}
+template class BackgroundRecoveryT<UrgentRecovery>;
+template class BackgroundRecoveryT<PglogBasedRecovery>;
+template class BackgroundRecoveryT<BackfillRecovery>;
+
} // namespace crimson::osd
class PG;
class ShardServices;
-class BackgroundRecovery : public TrackableOperationT<BackgroundRecovery> {
+template <class T>
+class BackgroundRecoveryT : public PhasedOperationT<T> {
public:
static constexpr OperationTypeCode type = OperationTypeCode::background_recovery;
- BackgroundRecovery(
+ BackgroundRecoveryT(
Ref<PG> pg,
ShardServices &ss,
epoch_t epoch_started,
scheduler_class
};
}
- virtual interruptible_future<bool> do_recovery() = 0;
+ using do_recovery_ret_t = typename PhasedOperationT<T>::template interruptible_future<bool>;
+ virtual do_recovery_ret_t do_recovery() = 0;
ShardServices &ss;
const crimson::osd::scheduler::scheduler_class_t scheduler_class;
};
/// @c UrgentRecovery is not throttled by the scheduler. and it
/// utilizes @c RecoveryBackend directly to recover the unreadable
/// object.
-class UrgentRecovery final : public BackgroundRecovery {
+class UrgentRecovery final : public BackgroundRecoveryT<UrgentRecovery> {
public:
UrgentRecovery(
const hobject_t& soid,
const eversion_t need;
};
-class PglogBasedRecovery final : public BackgroundRecovery {
+class PglogBasedRecovery final : public BackgroundRecoveryT<PglogBasedRecovery> {
public:
PglogBasedRecovery(
Ref<PG> pg,
interruptible_future<bool> do_recovery() override;
};
-class BackfillRecovery final : public BackgroundRecovery {
+class BackfillRecovery final : public BackgroundRecoveryT<BackfillRecovery> {
public:
class BackfillRecoveryPipeline {
struct Process : OrderedExclusivePhaseT<Process> {
static BackfillRecoveryPipeline &bp(PG &pg);
+ std::tuple<
+ BackfillRecoveryPipeline::Process::BlockingEvent
+ > tracking_events;
+
private:
boost::intrusive_ptr<const boost::statechart::event_base> evt;
PipelineHandle handle;
ShardServices &ss,
const epoch_t epoch_started,
const EventT& evt)
- : BackgroundRecovery(
+ : BackgroundRecoveryT(
std::move(pg),
ss,
epoch_started,