summaryrefslogtreecommitdiffstats
path: root/src/crimson/osd/osd_operations/background_recovery.h
blob: 17f2cd57a305af359b27ac893c7d2a5d48481c0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#pragma once

#include <boost/statechart/event_base.hpp>

#include "crimson/net/Connection.h"
#include "crimson/osd/osd_operation.h"
#include "crimson/osd/recovery_backend.h"
#include "crimson/common/type_helpers.h"
#include "crimson/osd/osd_operations/peering_event.h"
#include "crimson/osd/pg.h"

namespace crimson::osd {
class PG;
class ShardServices;

template <class T>
class BackgroundRecoveryT : public PhasedOperationT<T> {
public:
  static constexpr OperationTypeCode type = OperationTypeCode::background_recovery;

  BackgroundRecoveryT(
    Ref<PG> pg,
    ShardServices &ss,
    epoch_t epoch_started,
    crimson::osd::scheduler::scheduler_class_t scheduler_class, float delay = 0);

  virtual void print(std::ostream &) const;
  seastar::future<> start();

protected:
  Ref<PG> pg;
  const epoch_t epoch_started;
  float delay = 0;

private:
  virtual void dump_detail(Formatter *f) const;
  crimson::osd::scheduler::params_t get_scheduler_params() const {
    return {
      1, // cost
      0, // owner
      scheduler_class
    };
  }
  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;
};

/// represent a recovery initiated for serving a client request
///
/// unlike @c PglogBasedRecovery and @c BackfillRecovery,
/// @c UrgentRecovery is not throttled by the scheduler. and it
/// utilizes @c RecoveryBackend directly to recover the unreadable
/// object.
class UrgentRecovery final : public BackgroundRecoveryT<UrgentRecovery> {
public:
  UrgentRecovery(
    const hobject_t& soid,
    const eversion_t& need,
    Ref<PG> pg,
    ShardServices& ss,
    epoch_t epoch_started);
  void print(std::ostream&) const final;

  std::tuple<
    OperationThrottler::BlockingEvent,
    RecoveryBackend::RecoveryBlockingEvent
  > tracking_events;

private:
  void dump_detail(Formatter* f) const final;
  interruptible_future<bool> do_recovery() override;
  const hobject_t soid;
  const eversion_t need;
};

class PglogBasedRecovery final : public BackgroundRecoveryT<PglogBasedRecovery> {
public:
  PglogBasedRecovery(
    Ref<PG> pg,
    ShardServices &ss,
    epoch_t epoch_started,
    float delay = 0);

  std::tuple<
    OperationThrottler::BlockingEvent,
    RecoveryBackend::RecoveryBlockingEvent
  > tracking_events;

private:
  interruptible_future<bool> do_recovery() override;
};

class BackfillRecovery final : public BackgroundRecoveryT<BackfillRecovery> {
public:

  template <class EventT>
  BackfillRecovery(
    Ref<PG> pg,
    ShardServices &ss,
    epoch_t epoch_started,
    const EventT& evt);

  PipelineHandle& get_handle() { return handle; }

  std::tuple<
    OperationThrottler::BlockingEvent,
    PGPeeringPipeline::Process::BlockingEvent
  > tracking_events;

private:
  boost::intrusive_ptr<const boost::statechart::event_base> evt;
  PipelineHandle handle;

  static PGPeeringPipeline &peering_pp(PG &pg);
  interruptible_future<bool> do_recovery() override;
};

template <class EventT>
BackfillRecovery::BackfillRecovery(
  Ref<PG> pg,
  ShardServices &ss,
  const epoch_t epoch_started,
  const EventT& evt)
  : BackgroundRecoveryT(
      std::move(pg),
      ss,
      epoch_started,
      crimson::osd::scheduler::scheduler_class_t::background_best_effort),
    evt(evt.intrusive_from_this())
{}

}

#if FMT_VERSION >= 90000
template <> struct fmt::formatter<crimson::osd::BackfillRecovery> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::osd::PglogBasedRecovery> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::osd::UrgentRecovery> : fmt::ostream_formatter {};
template <class T> struct fmt::formatter<crimson::osd::BackgroundRecoveryT<T>> : fmt::ostream_formatter {};
#endif