1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
6 #include <boost/statechart/custom_reaction.hpp>
7 #include <boost/statechart/event.hpp>
8 #include <boost/statechart/simple_state.hpp>
9 #include <boost/statechart/state.hpp>
10 #include <boost/statechart/state_machine.hpp>
11 #include <boost/statechart/transition.hpp>
12 #include <boost/statechart/event_base.hpp>
16 #include "include/ceph_assert.h"
17 #include "include/common_fwd.h"
20 #include "PGStateUtils.h"
21 #include "PGPeeringEvent.h"
22 #include "osd_types.h"
23 #include "os/ObjectStore.h"
25 #include "MissingLoc.h"
26 #include "osd/osd_perf_counters.h"
27 #include "common/ostream_temp.h"
36 SnapContext snapc
; // the default pool snapc, ready to go.
38 PGPool(CephContext
* cct
, OSDMapRef map
, int64_t i
, const pg_pool_t
& info
,
41 cached_epoch(map
->get_epoch()),
45 snapc
= info
.get_snap_context();
48 void update(CephContext
*cct
, OSDMapRef map
);
50 ceph::timespan
get_readable_interval() const {
52 if (info
.opts
.get(pool_opts_t::READ_LEASE_INTERVAL
, &v
)) {
53 return ceph::make_timespan(v
);
55 auto hbi
= cct
->_conf
->osd_heartbeat_grace
;
56 auto fac
= cct
->_conf
->osd_pool_default_read_lease_ratio
;
57 return ceph::make_timespan(hbi
* fac
);
64 // [primary only] content recovery state
65 struct BufferedRecoveryMessages
{
66 ceph_release_t require_osd_release
;
67 map
<int, vector
<MessageRef
>> message_map
;
69 BufferedRecoveryMessages(ceph_release_t r
)
70 : require_osd_release(r
) {
72 BufferedRecoveryMessages(ceph_release_t r
, PeeringCtx
&ctx
);
74 void accept_buffered_messages(BufferedRecoveryMessages
&m
) {
75 for (auto &[target
, ls
] : m
.message_map
) {
76 auto &ovec
= message_map
[target
];
77 // put buffered messages in front
78 ls
.reserve(ls
.size() + ovec
.size());
79 ls
.insert(ls
.end(), ovec
.begin(), ovec
.end());
85 void send_osd_message(int target
, MessageRef m
) {
86 message_map
[target
].push_back(std::move(m
));
88 void send_notify(int to
, const pg_notify_t
&n
);
89 void send_query(int to
, spg_t spgid
, const pg_query_t
&q
);
90 void send_info(int to
, spg_t to_spgid
,
91 epoch_t min_epoch
, epoch_t cur_epoch
,
92 const pg_info_t
&info
,
93 std::optional
<pg_lease_t
> lease
= {},
94 std::optional
<pg_lease_ack_t
> lease_ack
= {});
97 struct HeartbeatStamps
: public RefCountedObject
{
98 mutable ceph::mutex lock
= ceph::make_mutex("HeartbeatStamps::lock");
102 // we maintain an upper and lower bound on the delta between our local
103 // mono_clock time (minus the startup_time) to the peer OSD's mono_clock
104 // time (minus its startup_time).
106 // delta is (remote_clock_time - local_clock_time), so that
107 // local_time + delta -> peer_time, and peer_time - delta -> local_time.
109 // we have an upper and lower bound value on this delta, meaning the
110 // value of the remote clock is somewhere between [my_time + lb, my_time + ub]
112 // conversely, if we have a remote timestamp T, then that is
113 // [T - ub, T - lb] in terms of the local clock. i.e., if you are
114 // substracting the delta, then take care that you swap the role of the
117 /// lower bound on peer clock - local clock
118 std::optional
<ceph::signedspan
> peer_clock_delta_lb
;
120 /// upper bound on peer clock - local clock
121 std::optional
<ceph::signedspan
> peer_clock_delta_ub
;
123 /// highest up_from we've seen from this rank
126 void print(ostream
& out
) const {
127 std::lock_guard
l(lock
);
128 out
<< "hbstamp(osd." << osd
<< " up_from " << up_from
129 << " peer_clock_delta [";
130 if (peer_clock_delta_lb
) {
131 out
<< *peer_clock_delta_lb
;
134 if (peer_clock_delta_ub
) {
135 out
<< *peer_clock_delta_ub
;
140 void sent_ping(std::optional
<ceph::signedspan
> *delta_ub
) {
141 std::lock_guard
l(lock
);
142 // the non-primaries need a lower bound on remote clock - local clock. if
143 // we assume the transit for the last ping_reply was
144 // instantaneous, that would be (the negative of) our last
145 // peer_clock_delta_lb value.
146 if (peer_clock_delta_lb
) {
147 *delta_ub
= - *peer_clock_delta_lb
;
151 void got_ping(epoch_t this_up_from
,
152 ceph::signedspan now
,
153 ceph::signedspan peer_send_stamp
,
154 std::optional
<ceph::signedspan
> delta_ub
,
155 ceph::signedspan
*out_delta_ub
) {
156 std::lock_guard
l(lock
);
157 if (this_up_from
< up_from
) {
160 if (this_up_from
> up_from
) {
161 up_from
= this_up_from
;
163 peer_clock_delta_lb
= peer_send_stamp
- now
;
164 peer_clock_delta_ub
= delta_ub
;
165 *out_delta_ub
= - *peer_clock_delta_lb
;
168 void got_ping_reply(ceph::signedspan now
,
169 ceph::signedspan peer_send_stamp
,
170 std::optional
<ceph::signedspan
> delta_ub
) {
171 std::lock_guard
l(lock
);
172 peer_clock_delta_lb
= peer_send_stamp
- now
;
173 peer_clock_delta_ub
= delta_ub
;
177 FRIEND_MAKE_REF(HeartbeatStamps
);
178 HeartbeatStamps(int o
)
179 : RefCountedObject(NULL
),
182 using HeartbeatStampsRef
= ceph::ref_t
<HeartbeatStamps
>;
184 inline ostream
& operator<<(ostream
& out
, const HeartbeatStamps
& hb
)
191 struct PeeringCtx
: BufferedRecoveryMessages
{
192 ObjectStore::Transaction transaction
;
193 HBHandle
* handle
= nullptr;
195 PeeringCtx(ceph_release_t r
)
196 : BufferedRecoveryMessages(r
) {}
198 PeeringCtx(const PeeringCtx
&) = delete;
199 PeeringCtx
&operator=(const PeeringCtx
&) = delete;
201 PeeringCtx(PeeringCtx
&&) = default;
202 PeeringCtx
&operator=(PeeringCtx
&&) = default;
204 void reset_transaction() {
205 transaction
= ObjectStore::Transaction();
210 * Wraps PeeringCtx to hide the difference between buffering messages to
211 * be sent after flush or immediately.
213 struct PeeringCtxWrapper
{
215 BufferedRecoveryMessages
&msgs
;
216 ObjectStore::Transaction
&transaction
;
217 HBHandle
* const handle
= nullptr;
219 PeeringCtxWrapper(PeeringCtx
&wrapped
) :
221 transaction(wrapped
.transaction
),
222 handle(wrapped
.handle
) {}
224 PeeringCtxWrapper(BufferedRecoveryMessages
&buf
, PeeringCtx
&wrapped
)
226 transaction(wrapped
.transaction
),
227 handle(wrapped
.handle
) {}
229 PeeringCtxWrapper(PeeringCtxWrapper
&&ctx
) = default;
231 void send_osd_message(int target
, MessageRef m
) {
232 msgs
.send_osd_message(target
, std::move(m
));
234 void send_notify(int to
, const pg_notify_t
&n
) {
235 msgs
.send_notify(to
, n
);
237 void send_query(int to
, spg_t spgid
, const pg_query_t
&q
) {
238 msgs
.send_query(to
, spgid
, q
);
240 void send_info(int to
, spg_t to_spgid
,
241 epoch_t min_epoch
, epoch_t cur_epoch
,
242 const pg_info_t
&info
,
243 std::optional
<pg_lease_t
> lease
= {},
244 std::optional
<pg_lease_ack_t
> lease_ack
= {}) {
245 msgs
.send_info(to
, to_spgid
, min_epoch
, cur_epoch
, info
,
250 /* Encapsulates PG recovery process */
251 class PeeringState
: public MissingLoc::MappingInfo
{
253 struct PeeringListener
: public EpochSource
{
254 /// Prepare t with written information
255 virtual void prepare_write(
257 pg_info_t
&last_written_info
,
258 PastIntervals
&past_intervals
,
262 bool need_write_epoch
,
263 ObjectStore::Transaction
&t
) = 0;
265 /// Notify that info/history changed (generally to update scrub registration)
266 virtual void on_info_history_change() = 0;
267 /// Notify that a scrub has been requested
268 virtual void scrub_requested(bool deep
, bool repair
, bool need_auto
= false) = 0;
270 /// Return current snap_trimq size
271 virtual uint64_t get_snap_trimq_size() const = 0;
273 /// Send cluster message to osd
274 virtual void send_cluster_message(
275 int osd
, Message
*m
, epoch_t epoch
, bool share_map_update
=false) = 0;
276 /// Send pg_created to mon
277 virtual void send_pg_created(pg_t pgid
) = 0;
279 virtual ceph::signedspan
get_mnow() = 0;
280 virtual HeartbeatStampsRef
get_hb_stamps(int peer
) = 0;
281 virtual void schedule_renew_lease(epoch_t plr
, ceph::timespan delay
) = 0;
282 virtual void queue_check_readable(epoch_t lpr
, ceph::timespan delay
) = 0;
283 virtual void recheck_readable() = 0;
285 virtual unsigned get_target_pg_log_entries() const = 0;
287 // ============ Flush state ==================
289 * try_flush_or_schedule_async()
291 * If true, caller may assume all past operations on this pg
292 * have been flushed. Else, caller will receive an on_flushed()
293 * call once the flush has completed.
295 virtual bool try_flush_or_schedule_async() = 0;
296 /// Arranges for a commit on t to call on_flushed() once flushed.
297 virtual void start_flush_on_transaction(
298 ObjectStore::Transaction
&t
) = 0;
299 /// Notification that all outstanding flushes for interval have completed
300 virtual void on_flushed() = 0;
302 //============= Recovery ====================
303 /// Arrange for even to be queued after delay
304 virtual void schedule_event_after(
305 PGPeeringEventRef event
,
308 * request_local_background_io_reservation
310 * Request reservation at priority with on_grant queued on grant
311 * and on_preempt on preempt
313 virtual void request_local_background_io_reservation(
315 PGPeeringEventRef on_grant
,
316 PGPeeringEventRef on_preempt
) = 0;
317 /// Modify pending local background reservation request priority
318 virtual void update_local_background_io_priority(
319 unsigned priority
) = 0;
320 /// Cancel pending local background reservation request
321 virtual void cancel_local_background_io_reservation() = 0;
324 * request_remote_background_io_reservation
326 * Request reservation at priority with on_grant queued on grant
327 * and on_preempt on preempt
329 virtual void request_remote_recovery_reservation(
331 PGPeeringEventRef on_grant
,
332 PGPeeringEventRef on_preempt
) = 0;
333 /// Cancel pending remote background reservation request
334 virtual void cancel_remote_recovery_reservation() = 0;
336 /// Arrange for on_commit to be queued upon commit of t
337 virtual void schedule_event_on_commit(
338 ObjectStore::Transaction
&t
,
339 PGPeeringEventRef on_commit
) = 0;
341 //============================ HB =============================
342 /// Update hb set to peers
343 virtual void update_heartbeat_peers(set
<int> peers
) = 0;
345 /// Set targets being probed in this interval
346 virtual void set_probe_targets(const set
<pg_shard_t
> &probe_set
) = 0;
347 /// Clear targets being probed in this interval
348 virtual void clear_probe_targets() = 0;
350 /// Queue for a pg_temp of wanted
351 virtual void queue_want_pg_temp(const vector
<int> &wanted
) = 0;
352 /// Clear queue for a pg_temp of wanted
353 virtual void clear_want_pg_temp() = 0;
355 /// Arrange for stats to be shipped to mon to be updated for this pg
356 virtual void publish_stats_to_osd() = 0;
357 /// Clear stats to be shipped to mon for this pg
358 virtual void clear_publish_stats() = 0;
360 /// Notification to check outstanding operation targets
361 virtual void check_recovery_sources(const OSDMapRef
& newmap
) = 0;
362 /// Notification to check outstanding blacklist
363 virtual void check_blacklisted_watchers() = 0;
364 /// Notification to clear state associated with primary
365 virtual void clear_primary_state() = 0;
367 // =================== Event notification ====================
368 virtual void on_pool_change() = 0;
369 virtual void on_role_change() = 0;
370 virtual void on_change(ObjectStore::Transaction
&t
) = 0;
371 virtual void on_activate(interval_set
<snapid_t
> to_trim
) = 0;
372 virtual void on_activate_complete() = 0;
373 virtual void on_new_interval() = 0;
374 virtual Context
*on_clean() = 0;
375 virtual void on_activate_committed() = 0;
376 virtual void on_active_exit() = 0;
378 // ====================== PG deletion =======================
379 /// Notification of removal complete, t must be populated to complete removal
380 virtual void on_removal(ObjectStore::Transaction
&t
) = 0;
381 /// Perform incremental removal work
382 virtual void do_delete_work(ObjectStore::Transaction
&t
) = 0;
384 // ======================= PG Merge =========================
385 virtual void clear_ready_to_merge() = 0;
386 virtual void set_not_ready_to_merge_target(pg_t pgid
, pg_t src
) = 0;
387 virtual void set_not_ready_to_merge_source(pg_t pgid
) = 0;
388 virtual void set_ready_to_merge_target(eversion_t lu
, epoch_t les
, epoch_t lec
) = 0;
389 virtual void set_ready_to_merge_source(eversion_t lu
) = 0;
391 // ==================== Map notifications ===================
392 virtual void on_active_actmap() = 0;
393 virtual void on_active_advmap(const OSDMapRef
&osdmap
) = 0;
394 virtual epoch_t
oldest_stored_osdmap() = 0;
396 // ============ recovery reservation notifications ==========
397 virtual void on_backfill_reserved() = 0;
398 virtual void on_backfill_canceled() = 0;
399 virtual void on_recovery_reserved() = 0;
401 // ================recovery space accounting ================
402 virtual bool try_reserve_recovery_space(
403 int64_t primary_num_bytes
, int64_t local_num_bytes
) = 0;
404 virtual void unreserve_recovery_space() = 0;
406 // ================== Peering log events ====================
407 /// Get handler for rolling forward/back log entries
408 virtual PGLog::LogEntryHandlerRef
get_log_handler(
409 ObjectStore::Transaction
&t
) = 0;
411 // ============ On disk representation changes ==============
412 virtual void rebuild_missing_set_with_deletes(PGLog
&pglog
) = 0;
414 // ======================= Logging ==========================
415 virtual PerfCounters
&get_peering_perf() = 0;
416 virtual PerfCounters
&get_perf_logger() = 0;
417 virtual void log_state_enter(const char *state
) = 0;
418 virtual void log_state_exit(
419 const char *state_name
, utime_t enter_time
,
420 uint64_t events
, utime_t event_dur
) = 0;
421 virtual void dump_recovery_info(Formatter
*f
) const = 0;
423 virtual OstreamTemp
get_clog_info() = 0;
424 virtual OstreamTemp
get_clog_error() = 0;
425 virtual OstreamTemp
get_clog_debug() = 0;
427 virtual ~PeeringListener() {}
430 struct QueryState
: boost::statechart::event
< QueryState
> {
432 explicit QueryState(Formatter
*f
) : f(f
) {}
433 void print(std::ostream
*out
) const {
438 struct AdvMap
: boost::statechart::event
< AdvMap
> {
441 vector
<int> newup
, newacting
;
442 int up_primary
, acting_primary
;
444 OSDMapRef osdmap
, OSDMapRef lastmap
,
445 vector
<int>& newup
, int up_primary
,
446 vector
<int>& newacting
, int acting_primary
):
447 osdmap(osdmap
), lastmap(lastmap
),
449 newacting(newacting
),
450 up_primary(up_primary
),
451 acting_primary(acting_primary
) {}
452 void print(std::ostream
*out
) const {
457 struct ActMap
: boost::statechart::event
< ActMap
> {
458 ActMap() : boost::statechart::event
< ActMap
>() {}
459 void print(std::ostream
*out
) const {
463 struct Activate
: boost::statechart::event
< Activate
> {
464 epoch_t activation_epoch
;
465 explicit Activate(epoch_t q
) : boost::statechart::event
< Activate
>(),
466 activation_epoch(q
) {}
467 void print(std::ostream
*out
) const {
468 *out
<< "Activate from " << activation_epoch
;
471 struct ActivateCommitted
: boost::statechart::event
< ActivateCommitted
> {
473 epoch_t activation_epoch
;
474 explicit ActivateCommitted(epoch_t e
, epoch_t ae
)
475 : boost::statechart::event
< ActivateCommitted
>(),
477 activation_epoch(ae
) {}
478 void print(std::ostream
*out
) const {
479 *out
<< "ActivateCommitted from " << activation_epoch
480 << " processed at " << epoch
;
484 struct UnfoundBackfill
: boost::statechart::event
<UnfoundBackfill
> {
485 explicit UnfoundBackfill() {}
486 void print(std::ostream
*out
) const {
487 *out
<< "UnfoundBackfill";
490 struct UnfoundRecovery
: boost::statechart::event
<UnfoundRecovery
> {
491 explicit UnfoundRecovery() {}
492 void print(std::ostream
*out
) const {
493 *out
<< "UnfoundRecovery";
497 struct RequestScrub
: boost::statechart::event
<RequestScrub
> {
500 explicit RequestScrub(bool d
, bool r
) : deep(d
), repair(r
) {}
501 void print(std::ostream
*out
) const {
502 *out
<< "RequestScrub(" << (deep
? "deep" : "shallow")
503 << (repair
? " repair" : "");
507 TrivialEvent(Initialize
)
508 TrivialEvent(GotInfo
)
509 TrivialEvent(NeedUpThru
)
510 TrivialEvent(Backfilled
)
511 TrivialEvent(LocalBackfillReserved
)
512 TrivialEvent(RejectTooFullRemoteReservation
)
513 TrivialEvent(RequestBackfill
)
514 TrivialEvent(RemoteRecoveryPreempted
)
515 TrivialEvent(RemoteBackfillPreempted
)
516 TrivialEvent(BackfillTooFull
)
517 TrivialEvent(RecoveryTooFull
)
519 TrivialEvent(MakePrimary
)
520 TrivialEvent(MakeStray
)
521 TrivialEvent(NeedActingChange
)
522 TrivialEvent(IsIncomplete
)
525 TrivialEvent(AllReplicasRecovered
)
526 TrivialEvent(DoRecovery
)
527 TrivialEvent(LocalRecoveryReserved
)
528 TrivialEvent(AllRemotesReserved
)
529 TrivialEvent(AllBackfillsReserved
)
530 TrivialEvent(GoClean
)
532 TrivialEvent(AllReplicasActivated
)
534 TrivialEvent(IntervalFlush
)
536 TrivialEvent(DeleteStart
)
537 TrivialEvent(DeleteSome
)
539 TrivialEvent(SetForceRecovery
)
540 TrivialEvent(UnsetForceRecovery
)
541 TrivialEvent(SetForceBackfill
)
542 TrivialEvent(UnsetForceBackfill
)
544 TrivialEvent(DeleteReserved
)
545 TrivialEvent(DeleteInterrupted
)
547 TrivialEvent(CheckReadable
)
549 void start_handle(PeeringCtx
*new_ctx
);
551 void begin_block_outgoing();
552 void end_block_outgoing();
553 void clear_blocked_outgoing();
558 class PeeringMachine
: public boost::statechart::state_machine
< PeeringMachine
, Initial
> {
561 PGStateHistory
*state_history
;
564 DoutPrefixProvider
*dpp
;
568 uint64_t event_count
;
570 void clear_event_counters() {
571 event_time
= utime_t();
575 void log_enter(const char *state_name
);
576 void log_exit(const char *state_name
, utime_t duration
);
579 PeeringState
*state
, CephContext
*cct
,
581 DoutPrefixProvider
*dpp
,
583 PGStateHistory
*state_history
) :
585 state_history(state_history
),
586 cct(cct
), spgid(spgid
),
590 /* Accessor functions for state methods */
591 ObjectStore::Transaction
& get_cur_transaction() {
592 ceph_assert(state
->rctx
);
593 return state
->rctx
->transaction
;
596 PeeringCtxWrapper
&get_recovery_ctx() {
598 return *(state
->rctx
);
601 void send_notify(int to
, const pg_notify_t
&n
) {
602 ceph_assert(state
->rctx
);
603 state
->rctx
->send_notify(to
, n
);
605 void send_query(int to
, const pg_query_t
&query
) {
606 state
->rctx
->send_query(
608 spg_t(spgid
.pgid
, query
.to
),
612 friend class PeeringMachine
;
632 // WaitRemoteBackfillReserved
633 // WaitLocalBackfillReserved
637 // WaitRemoteRecoveryReserved
638 // WaitLocalRecoveryReserved
642 // RepWaitBackfillReserved
643 // RepWaitRecoveryReserved
646 // WaitDeleteReserved
650 struct Crashed
: boost::statechart::state
< Crashed
, PeeringMachine
>, NamedState
{
651 explicit Crashed(my_context ctx
);
656 struct Initial
: boost::statechart::state
< Initial
, PeeringMachine
>, NamedState
{
657 explicit Initial(my_context ctx
);
660 typedef boost::mpl::list
<
661 boost::statechart::transition
< Initialize
, Reset
>,
662 boost::statechart::custom_reaction
< NullEvt
>,
663 boost::statechart::transition
< boost::statechart::event_base
, Crashed
>
666 boost::statechart::result
react(const MNotifyRec
&);
667 boost::statechart::result
react(const MInfoRec
&);
668 boost::statechart::result
react(const MLogRec
&);
669 boost::statechart::result
react(const boost::statechart::event_base
&) {
670 return discard_event();
674 struct Reset
: boost::statechart::state
< Reset
, PeeringMachine
>, NamedState
{
675 explicit Reset(my_context ctx
);
678 typedef boost::mpl::list
<
679 boost::statechart::custom_reaction
< QueryState
>,
680 boost::statechart::custom_reaction
< AdvMap
>,
681 boost::statechart::custom_reaction
< ActMap
>,
682 boost::statechart::custom_reaction
< NullEvt
>,
683 boost::statechart::custom_reaction
< IntervalFlush
>,
684 boost::statechart::transition
< boost::statechart::event_base
, Crashed
>
686 boost::statechart::result
react(const QueryState
& q
);
687 boost::statechart::result
react(const AdvMap
&);
688 boost::statechart::result
react(const ActMap
&);
689 boost::statechart::result
react(const IntervalFlush
&);
690 boost::statechart::result
react(const boost::statechart::event_base
&) {
691 return discard_event();
697 struct Started
: boost::statechart::state
< Started
, PeeringMachine
, Start
>, NamedState
{
698 explicit Started(my_context ctx
);
701 typedef boost::mpl::list
<
702 boost::statechart::custom_reaction
< QueryState
>,
703 boost::statechart::custom_reaction
< AdvMap
>,
704 boost::statechart::custom_reaction
< IntervalFlush
>,
706 boost::statechart::custom_reaction
< NullEvt
>,
707 boost::statechart::custom_reaction
<SetForceRecovery
>,
708 boost::statechart::custom_reaction
<UnsetForceRecovery
>,
709 boost::statechart::custom_reaction
<SetForceBackfill
>,
710 boost::statechart::custom_reaction
<UnsetForceBackfill
>,
711 boost::statechart::custom_reaction
<RequestScrub
>,
712 boost::statechart::custom_reaction
<CheckReadable
>,
714 boost::statechart::transition
< boost::statechart::event_base
, Crashed
>
716 boost::statechart::result
react(const QueryState
& q
);
717 boost::statechart::result
react(const AdvMap
&);
718 boost::statechart::result
react(const IntervalFlush
&);
719 boost::statechart::result
react(const boost::statechart::event_base
&) {
720 return discard_event();
727 struct Start
: boost::statechart::state
< Start
, Started
>, NamedState
{
728 explicit Start(my_context ctx
);
731 typedef boost::mpl::list
<
732 boost::statechart::transition
< MakePrimary
, Primary
>,
733 boost::statechart::transition
< MakeStray
, Stray
>
738 struct WaitActingChange
;
742 struct Primary
: boost::statechart::state
< Primary
, Started
, Peering
>, NamedState
{
743 explicit Primary(my_context ctx
);
746 typedef boost::mpl::list
<
747 boost::statechart::custom_reaction
< ActMap
>,
748 boost::statechart::custom_reaction
< MNotifyRec
>,
749 boost::statechart::custom_reaction
<SetForceRecovery
>,
750 boost::statechart::custom_reaction
<UnsetForceRecovery
>,
751 boost::statechart::custom_reaction
<SetForceBackfill
>,
752 boost::statechart::custom_reaction
<UnsetForceBackfill
>,
753 boost::statechart::custom_reaction
<RequestScrub
>
755 boost::statechart::result
react(const ActMap
&);
756 boost::statechart::result
react(const MNotifyRec
&);
757 boost::statechart::result
react(const SetForceRecovery
&);
758 boost::statechart::result
react(const UnsetForceRecovery
&);
759 boost::statechart::result
react(const SetForceBackfill
&);
760 boost::statechart::result
react(const UnsetForceBackfill
&);
761 boost::statechart::result
react(const RequestScrub
&);
764 struct WaitActingChange
: boost::statechart::state
< WaitActingChange
, Primary
>,
766 typedef boost::mpl::list
<
767 boost::statechart::custom_reaction
< QueryState
>,
768 boost::statechart::custom_reaction
< AdvMap
>,
769 boost::statechart::custom_reaction
< MLogRec
>,
770 boost::statechart::custom_reaction
< MInfoRec
>,
771 boost::statechart::custom_reaction
< MNotifyRec
>
773 explicit WaitActingChange(my_context ctx
);
774 boost::statechart::result
react(const QueryState
& q
);
775 boost::statechart::result
react(const AdvMap
&);
776 boost::statechart::result
react(const MLogRec
&);
777 boost::statechart::result
react(const MInfoRec
&);
778 boost::statechart::result
react(const MNotifyRec
&);
785 struct Peering
: boost::statechart::state
< Peering
, Primary
, GetInfo
>, NamedState
{
786 PastIntervals::PriorSet prior_set
;
787 bool history_les_bound
; //< need osd_find_best_info_ignore_history_les
789 explicit Peering(my_context ctx
);
792 typedef boost::mpl::list
<
793 boost::statechart::custom_reaction
< QueryState
>,
794 boost::statechart::transition
< Activate
, Active
>,
795 boost::statechart::custom_reaction
< AdvMap
>
797 boost::statechart::result
react(const QueryState
& q
);
798 boost::statechart::result
react(const AdvMap
&advmap
);
801 struct WaitLocalRecoveryReserved
;
803 struct Active
: boost::statechart::state
< Active
, Primary
, Activating
>, NamedState
{
804 explicit Active(my_context ctx
);
807 const set
<pg_shard_t
> remote_shards_to_reserve_recovery
;
808 const set
<pg_shard_t
> remote_shards_to_reserve_backfill
;
809 bool all_replicas_activated
;
811 typedef boost::mpl::list
<
812 boost::statechart::custom_reaction
< QueryState
>,
813 boost::statechart::custom_reaction
< ActMap
>,
814 boost::statechart::custom_reaction
< AdvMap
>,
815 boost::statechart::custom_reaction
< MInfoRec
>,
816 boost::statechart::custom_reaction
< MNotifyRec
>,
817 boost::statechart::custom_reaction
< MLogRec
>,
818 boost::statechart::custom_reaction
< MTrim
>,
819 boost::statechart::custom_reaction
< Backfilled
>,
820 boost::statechart::custom_reaction
< ActivateCommitted
>,
821 boost::statechart::custom_reaction
< AllReplicasActivated
>,
822 boost::statechart::custom_reaction
< DeferRecovery
>,
823 boost::statechart::custom_reaction
< DeferBackfill
>,
824 boost::statechart::custom_reaction
< UnfoundRecovery
>,
825 boost::statechart::custom_reaction
< UnfoundBackfill
>,
826 boost::statechart::custom_reaction
< RemoteReservationRevokedTooFull
>,
827 boost::statechart::custom_reaction
< RemoteReservationRevoked
>,
828 boost::statechart::custom_reaction
< DoRecovery
>,
829 boost::statechart::custom_reaction
< RenewLease
>,
830 boost::statechart::custom_reaction
< MLeaseAck
>,
831 boost::statechart::custom_reaction
< CheckReadable
>
833 boost::statechart::result
react(const QueryState
& q
);
834 boost::statechart::result
react(const ActMap
&);
835 boost::statechart::result
react(const AdvMap
&);
836 boost::statechart::result
react(const MInfoRec
& infoevt
);
837 boost::statechart::result
react(const MNotifyRec
& notevt
);
838 boost::statechart::result
react(const MLogRec
& logevt
);
839 boost::statechart::result
react(const MTrim
& trimevt
);
840 boost::statechart::result
react(const Backfilled
&) {
841 return discard_event();
843 boost::statechart::result
react(const ActivateCommitted
&);
844 boost::statechart::result
react(const AllReplicasActivated
&);
845 boost::statechart::result
react(const RenewLease
&);
846 boost::statechart::result
react(const MLeaseAck
&);
847 boost::statechart::result
react(const DeferRecovery
& evt
) {
848 return discard_event();
850 boost::statechart::result
react(const DeferBackfill
& evt
) {
851 return discard_event();
853 boost::statechart::result
react(const UnfoundRecovery
& evt
) {
854 return discard_event();
856 boost::statechart::result
react(const UnfoundBackfill
& evt
) {
857 return discard_event();
859 boost::statechart::result
react(const RemoteReservationRevokedTooFull
&) {
860 return discard_event();
862 boost::statechart::result
react(const RemoteReservationRevoked
&) {
863 return discard_event();
865 boost::statechart::result
react(const DoRecovery
&) {
866 return discard_event();
868 boost::statechart::result
react(const CheckReadable
&);
869 void all_activated_and_committed();
872 struct Clean
: boost::statechart::state
< Clean
, Active
>, NamedState
{
873 typedef boost::mpl::list
<
874 boost::statechart::transition
< DoRecovery
, WaitLocalRecoveryReserved
>,
875 boost::statechart::custom_reaction
<SetForceRecovery
>,
876 boost::statechart::custom_reaction
<SetForceBackfill
>
878 explicit Clean(my_context ctx
);
880 boost::statechart::result
react(const boost::statechart::event_base
&) {
881 return discard_event();
885 struct Recovered
: boost::statechart::state
< Recovered
, Active
>, NamedState
{
886 typedef boost::mpl::list
<
887 boost::statechart::transition
< GoClean
, Clean
>,
888 boost::statechart::transition
< DoRecovery
, WaitLocalRecoveryReserved
>,
889 boost::statechart::custom_reaction
< AllReplicasActivated
>
891 explicit Recovered(my_context ctx
);
893 boost::statechart::result
react(const AllReplicasActivated
&) {
894 post_event(GoClean());
895 return forward_event();
899 struct Backfilling
: boost::statechart::state
< Backfilling
, Active
>, NamedState
{
900 typedef boost::mpl::list
<
901 boost::statechart::custom_reaction
< Backfilled
>,
902 boost::statechart::custom_reaction
< DeferBackfill
>,
903 boost::statechart::custom_reaction
< UnfoundBackfill
>,
904 boost::statechart::custom_reaction
< RemoteReservationRejectedTooFull
>,
905 boost::statechart::custom_reaction
< RemoteReservationRevokedTooFull
>,
906 boost::statechart::custom_reaction
< RemoteReservationRevoked
>
908 explicit Backfilling(my_context ctx
);
909 boost::statechart::result
react(const RemoteReservationRejectedTooFull
& evt
) {
910 // for compat with old peers
911 post_event(RemoteReservationRevokedTooFull());
912 return discard_event();
914 void backfill_release_reservations();
915 boost::statechart::result
react(const Backfilled
& evt
);
916 boost::statechart::result
react(const RemoteReservationRevokedTooFull
& evt
);
917 boost::statechart::result
react(const RemoteReservationRevoked
& evt
);
918 boost::statechart::result
react(const DeferBackfill
& evt
);
919 boost::statechart::result
react(const UnfoundBackfill
& evt
);
920 void cancel_backfill();
924 struct WaitRemoteBackfillReserved
: boost::statechart::state
< WaitRemoteBackfillReserved
, Active
>, NamedState
{
925 typedef boost::mpl::list
<
926 boost::statechart::custom_reaction
< RemoteBackfillReserved
>,
927 boost::statechart::custom_reaction
< RemoteReservationRejectedTooFull
>,
928 boost::statechart::custom_reaction
< RemoteReservationRevoked
>,
929 boost::statechart::transition
< AllBackfillsReserved
, Backfilling
>
931 set
<pg_shard_t
>::const_iterator backfill_osd_it
;
932 explicit WaitRemoteBackfillReserved(my_context ctx
);
935 boost::statechart::result
react(const RemoteBackfillReserved
& evt
);
936 boost::statechart::result
react(const RemoteReservationRejectedTooFull
& evt
);
937 boost::statechart::result
react(const RemoteReservationRevoked
& evt
);
940 struct WaitLocalBackfillReserved
: boost::statechart::state
< WaitLocalBackfillReserved
, Active
>, NamedState
{
941 typedef boost::mpl::list
<
942 boost::statechart::transition
< LocalBackfillReserved
, WaitRemoteBackfillReserved
>,
943 boost::statechart::custom_reaction
< RemoteBackfillReserved
>
945 explicit WaitLocalBackfillReserved(my_context ctx
);
946 boost::statechart::result
react(const RemoteBackfillReserved
& evt
) {
948 return discard_event();
953 struct NotBackfilling
: boost::statechart::state
< NotBackfilling
, Active
>, NamedState
{
954 typedef boost::mpl::list
<
955 boost::statechart::transition
< RequestBackfill
, WaitLocalBackfillReserved
>,
956 boost::statechart::custom_reaction
< RemoteBackfillReserved
>,
957 boost::statechart::custom_reaction
< RemoteReservationRejectedTooFull
>
959 explicit NotBackfilling(my_context ctx
);
961 boost::statechart::result
react(const RemoteBackfillReserved
& evt
);
962 boost::statechart::result
react(const RemoteReservationRejectedTooFull
& evt
);
965 struct NotRecovering
: boost::statechart::state
< NotRecovering
, Active
>, NamedState
{
966 typedef boost::mpl::list
<
967 boost::statechart::transition
< DoRecovery
, WaitLocalRecoveryReserved
>,
968 boost::statechart::custom_reaction
< DeferRecovery
>,
969 boost::statechart::custom_reaction
< UnfoundRecovery
>
971 explicit NotRecovering(my_context ctx
);
972 boost::statechart::result
react(const DeferRecovery
& evt
) {
974 return discard_event();
976 boost::statechart::result
react(const UnfoundRecovery
& evt
) {
978 return discard_event();
984 struct RepNotRecovering
;
985 struct ReplicaActive
: boost::statechart::state
< ReplicaActive
, Started
, RepNotRecovering
>, NamedState
{
986 explicit ReplicaActive(my_context ctx
);
989 typedef boost::mpl::list
<
990 boost::statechart::custom_reaction
< QueryState
>,
991 boost::statechart::custom_reaction
< ActMap
>,
992 boost::statechart::custom_reaction
< MQuery
>,
993 boost::statechart::custom_reaction
< MInfoRec
>,
994 boost::statechart::custom_reaction
< MLogRec
>,
995 boost::statechart::custom_reaction
< MTrim
>,
996 boost::statechart::custom_reaction
< Activate
>,
997 boost::statechart::custom_reaction
< ActivateCommitted
>,
998 boost::statechart::custom_reaction
< DeferRecovery
>,
999 boost::statechart::custom_reaction
< DeferBackfill
>,
1000 boost::statechart::custom_reaction
< UnfoundRecovery
>,
1001 boost::statechart::custom_reaction
< UnfoundBackfill
>,
1002 boost::statechart::custom_reaction
< RemoteBackfillPreempted
>,
1003 boost::statechart::custom_reaction
< RemoteRecoveryPreempted
>,
1004 boost::statechart::custom_reaction
< RecoveryDone
>,
1005 boost::statechart::transition
<DeleteStart
, ToDelete
>,
1006 boost::statechart::custom_reaction
< MLease
>
1008 boost::statechart::result
react(const QueryState
& q
);
1009 boost::statechart::result
react(const MInfoRec
& infoevt
);
1010 boost::statechart::result
react(const MLogRec
& logevt
);
1011 boost::statechart::result
react(const MTrim
& trimevt
);
1012 boost::statechart::result
react(const ActMap
&);
1013 boost::statechart::result
react(const MQuery
&);
1014 boost::statechart::result
react(const Activate
&);
1015 boost::statechart::result
react(const ActivateCommitted
&);
1016 boost::statechart::result
react(const MLease
&);
1017 boost::statechart::result
react(const RecoveryDone
&) {
1018 return discard_event();
1020 boost::statechart::result
react(const DeferRecovery
& evt
) {
1021 return discard_event();
1023 boost::statechart::result
react(const DeferBackfill
& evt
) {
1024 return discard_event();
1026 boost::statechart::result
react(const UnfoundRecovery
& evt
) {
1027 return discard_event();
1029 boost::statechart::result
react(const UnfoundBackfill
& evt
) {
1030 return discard_event();
1032 boost::statechart::result
react(const RemoteBackfillPreempted
& evt
) {
1033 return discard_event();
1035 boost::statechart::result
react(const RemoteRecoveryPreempted
& evt
) {
1036 return discard_event();
1040 struct RepRecovering
: boost::statechart::state
< RepRecovering
, ReplicaActive
>, NamedState
{
1041 typedef boost::mpl::list
<
1042 boost::statechart::transition
< RecoveryDone
, RepNotRecovering
>,
1043 // for compat with old peers
1044 boost::statechart::transition
< RemoteReservationRejectedTooFull
, RepNotRecovering
>,
1045 boost::statechart::transition
< RemoteReservationCanceled
, RepNotRecovering
>,
1046 boost::statechart::custom_reaction
< BackfillTooFull
>,
1047 boost::statechart::custom_reaction
< RemoteRecoveryPreempted
>,
1048 boost::statechart::custom_reaction
< RemoteBackfillPreempted
>
1050 explicit RepRecovering(my_context ctx
);
1051 boost::statechart::result
react(const RemoteRecoveryPreempted
&evt
);
1052 boost::statechart::result
react(const BackfillTooFull
&evt
);
1053 boost::statechart::result
react(const RemoteBackfillPreempted
&evt
);
1057 struct RepWaitBackfillReserved
: boost::statechart::state
< RepWaitBackfillReserved
, ReplicaActive
>, NamedState
{
1058 typedef boost::mpl::list
<
1059 boost::statechart::custom_reaction
< RemoteBackfillReserved
>,
1060 boost::statechart::custom_reaction
< RejectTooFullRemoteReservation
>,
1061 boost::statechart::custom_reaction
< RemoteReservationRejectedTooFull
>,
1062 boost::statechart::custom_reaction
< RemoteReservationCanceled
>
1064 explicit RepWaitBackfillReserved(my_context ctx
);
1066 boost::statechart::result
react(const RemoteBackfillReserved
&evt
);
1067 boost::statechart::result
react(const RejectTooFullRemoteReservation
&evt
);
1068 boost::statechart::result
react(const RemoteReservationRejectedTooFull
&evt
);
1069 boost::statechart::result
react(const RemoteReservationCanceled
&evt
);
1072 struct RepWaitRecoveryReserved
: boost::statechart::state
< RepWaitRecoveryReserved
, ReplicaActive
>, NamedState
{
1073 typedef boost::mpl::list
<
1074 boost::statechart::custom_reaction
< RemoteRecoveryReserved
>,
1075 // for compat with old peers
1076 boost::statechart::custom_reaction
< RemoteReservationRejectedTooFull
>,
1077 boost::statechart::custom_reaction
< RemoteReservationCanceled
>
1079 explicit RepWaitRecoveryReserved(my_context ctx
);
1081 boost::statechart::result
react(const RemoteRecoveryReserved
&evt
);
1082 boost::statechart::result
react(const RemoteReservationRejectedTooFull
&evt
) {
1083 // for compat with old peers
1084 post_event(RemoteReservationCanceled());
1085 return discard_event();
1087 boost::statechart::result
react(const RemoteReservationCanceled
&evt
);
1090 struct RepNotRecovering
: boost::statechart::state
< RepNotRecovering
, ReplicaActive
>, NamedState
{
1091 typedef boost::mpl::list
<
1092 boost::statechart::custom_reaction
< RequestRecoveryPrio
>,
1093 boost::statechart::custom_reaction
< RequestBackfillPrio
>,
1094 boost::statechart::custom_reaction
< RejectTooFullRemoteReservation
>,
1095 boost::statechart::transition
< RemoteReservationRejectedTooFull
, RepNotRecovering
>,
1096 boost::statechart::transition
< RemoteReservationCanceled
, RepNotRecovering
>,
1097 boost::statechart::custom_reaction
< RemoteRecoveryReserved
>,
1098 boost::statechart::custom_reaction
< RemoteBackfillReserved
>,
1099 boost::statechart::transition
< RecoveryDone
, RepNotRecovering
> // for compat with pre-reservation peers
1101 explicit RepNotRecovering(my_context ctx
);
1102 boost::statechart::result
react(const RequestRecoveryPrio
&evt
);
1103 boost::statechart::result
react(const RequestBackfillPrio
&evt
);
1104 boost::statechart::result
react(const RemoteBackfillReserved
&evt
) {
1105 // my reservation completion raced with a RELEASE from primary
1106 return discard_event();
1108 boost::statechart::result
react(const RemoteRecoveryReserved
&evt
) {
1109 // my reservation completion raced with a RELEASE from primary
1110 return discard_event();
1112 boost::statechart::result
react(const RejectTooFullRemoteReservation
&evt
);
1116 struct Recovering
: boost::statechart::state
< Recovering
, Active
>, NamedState
{
1117 typedef boost::mpl::list
<
1118 boost::statechart::custom_reaction
< AllReplicasRecovered
>,
1119 boost::statechart::custom_reaction
< DeferRecovery
>,
1120 boost::statechart::custom_reaction
< UnfoundRecovery
>,
1121 boost::statechart::custom_reaction
< RequestBackfill
>
1123 explicit Recovering(my_context ctx
);
1125 void release_reservations(bool cancel
= false);
1126 boost::statechart::result
react(const AllReplicasRecovered
&evt
);
1127 boost::statechart::result
react(const DeferRecovery
& evt
);
1128 boost::statechart::result
react(const UnfoundRecovery
& evt
);
1129 boost::statechart::result
react(const RequestBackfill
&evt
);
1132 struct WaitRemoteRecoveryReserved
: boost::statechart::state
< WaitRemoteRecoveryReserved
, Active
>, NamedState
{
1133 typedef boost::mpl::list
<
1134 boost::statechart::custom_reaction
< RemoteRecoveryReserved
>,
1135 boost::statechart::transition
< AllRemotesReserved
, Recovering
>
1137 set
<pg_shard_t
>::const_iterator remote_recovery_reservation_it
;
1138 explicit WaitRemoteRecoveryReserved(my_context ctx
);
1139 boost::statechart::result
react(const RemoteRecoveryReserved
&evt
);
1143 struct WaitLocalRecoveryReserved
: boost::statechart::state
< WaitLocalRecoveryReserved
, Active
>, NamedState
{
1144 typedef boost::mpl::list
<
1145 boost::statechart::transition
< LocalRecoveryReserved
, WaitRemoteRecoveryReserved
>,
1146 boost::statechart::custom_reaction
< RecoveryTooFull
>
1148 explicit WaitLocalRecoveryReserved(my_context ctx
);
1150 boost::statechart::result
react(const RecoveryTooFull
&evt
);
1153 struct Activating
: boost::statechart::state
< Activating
, Active
>, NamedState
{
1154 typedef boost::mpl::list
<
1155 boost::statechart::transition
< AllReplicasRecovered
, Recovered
>,
1156 boost::statechart::transition
< DoRecovery
, WaitLocalRecoveryReserved
>,
1157 boost::statechart::transition
< RequestBackfill
, WaitLocalBackfillReserved
>
1159 explicit Activating(my_context ctx
);
1163 struct Stray
: boost::statechart::state
< Stray
, Started
>,
1165 explicit Stray(my_context ctx
);
1168 typedef boost::mpl::list
<
1169 boost::statechart::custom_reaction
< MQuery
>,
1170 boost::statechart::custom_reaction
< MLogRec
>,
1171 boost::statechart::custom_reaction
< MInfoRec
>,
1172 boost::statechart::custom_reaction
< ActMap
>,
1173 boost::statechart::custom_reaction
< RecoveryDone
>,
1174 boost::statechart::transition
<DeleteStart
, ToDelete
>
1176 boost::statechart::result
react(const MQuery
& query
);
1177 boost::statechart::result
react(const MLogRec
& logevt
);
1178 boost::statechart::result
react(const MInfoRec
& infoevt
);
1179 boost::statechart::result
react(const ActMap
&);
1180 boost::statechart::result
react(const RecoveryDone
&) {
1181 return discard_event();
1185 struct WaitDeleteReserved
;
1186 struct ToDelete
: boost::statechart::state
<ToDelete
, Started
, WaitDeleteReserved
>, NamedState
{
1187 unsigned priority
= 0;
1188 typedef boost::mpl::list
<
1189 boost::statechart::custom_reaction
< ActMap
>,
1190 boost::statechart::custom_reaction
< ActivateCommitted
>,
1191 boost::statechart::custom_reaction
< DeleteSome
>
1193 explicit ToDelete(my_context ctx
);
1194 boost::statechart::result
react(const ActMap
&evt
);
1195 boost::statechart::result
react(const DeleteSome
&evt
) {
1196 // happens if we drop out of Deleting due to reprioritization etc.
1197 return discard_event();
1199 boost::statechart::result
react(const ActivateCommitted
&) {
1200 // Can happens if we were activated as a stray but not actually pulled
1201 // from prior to the pg going clean and sending a delete.
1202 return discard_event();
1208 struct WaitDeleteReserved
: boost::statechart::state
<WaitDeleteReserved
,
1209 ToDelete
>, NamedState
{
1210 typedef boost::mpl::list
<
1211 boost::statechart::transition
<DeleteReserved
, Deleting
>
1213 explicit WaitDeleteReserved(my_context ctx
);
1217 struct Deleting
: boost::statechart::state
<Deleting
,
1218 ToDelete
>, NamedState
{
1219 typedef boost::mpl::list
<
1220 boost::statechart::custom_reaction
< DeleteSome
>,
1221 boost::statechart::transition
<DeleteInterrupted
, WaitDeleteReserved
>
1223 explicit Deleting(my_context ctx
);
1224 boost::statechart::result
react(const DeleteSome
&evt
);
1230 struct GetInfo
: boost::statechart::state
< GetInfo
, Peering
>, NamedState
{
1231 set
<pg_shard_t
> peer_info_requested
;
1233 explicit GetInfo(my_context ctx
);
1237 typedef boost::mpl::list
<
1238 boost::statechart::custom_reaction
< QueryState
>,
1239 boost::statechart::transition
< GotInfo
, GetLog
>,
1240 boost::statechart::custom_reaction
< MNotifyRec
>,
1241 boost::statechart::transition
< IsDown
, Down
>
1243 boost::statechart::result
react(const QueryState
& q
);
1244 boost::statechart::result
react(const MNotifyRec
& infoevt
);
1247 struct GotLog
: boost::statechart::event
< GotLog
> {
1248 GotLog() : boost::statechart::event
< GotLog
>() {}
1251 struct GetLog
: boost::statechart::state
< GetLog
, Peering
>, NamedState
{
1252 pg_shard_t auth_log_shard
;
1253 boost::intrusive_ptr
<MOSDPGLog
> msg
;
1255 explicit GetLog(my_context ctx
);
1258 typedef boost::mpl::list
<
1259 boost::statechart::custom_reaction
< QueryState
>,
1260 boost::statechart::custom_reaction
< MLogRec
>,
1261 boost::statechart::custom_reaction
< GotLog
>,
1262 boost::statechart::custom_reaction
< AdvMap
>,
1263 boost::statechart::transition
< NeedActingChange
, WaitActingChange
>,
1264 boost::statechart::transition
< IsIncomplete
, Incomplete
>
1266 boost::statechart::result
react(const AdvMap
&);
1267 boost::statechart::result
react(const QueryState
& q
);
1268 boost::statechart::result
react(const MLogRec
& logevt
);
1269 boost::statechart::result
react(const GotLog
&);
1274 struct GetMissing
: boost::statechart::state
< GetMissing
, Peering
>, NamedState
{
1275 set
<pg_shard_t
> peer_missing_requested
;
1277 explicit GetMissing(my_context ctx
);
1280 typedef boost::mpl::list
<
1281 boost::statechart::custom_reaction
< QueryState
>,
1282 boost::statechart::custom_reaction
< MLogRec
>,
1283 boost::statechart::transition
< NeedUpThru
, WaitUpThru
>
1285 boost::statechart::result
react(const QueryState
& q
);
1286 boost::statechart::result
react(const MLogRec
& logevt
);
1289 struct WaitUpThru
: boost::statechart::state
< WaitUpThru
, Peering
>, NamedState
{
1290 explicit WaitUpThru(my_context ctx
);
1293 typedef boost::mpl::list
<
1294 boost::statechart::custom_reaction
< QueryState
>,
1295 boost::statechart::custom_reaction
< ActMap
>,
1296 boost::statechart::custom_reaction
< MLogRec
>
1298 boost::statechart::result
react(const QueryState
& q
);
1299 boost::statechart::result
react(const ActMap
& am
);
1300 boost::statechart::result
react(const MLogRec
& logrec
);
1303 struct Down
: boost::statechart::state
< Down
, Peering
>, NamedState
{
1304 explicit Down(my_context ctx
);
1305 typedef boost::mpl::list
<
1306 boost::statechart::custom_reaction
< QueryState
>,
1307 boost::statechart::custom_reaction
< MNotifyRec
>
1309 boost::statechart::result
react(const QueryState
& q
);
1310 boost::statechart::result
react(const MNotifyRec
& infoevt
);
1314 struct Incomplete
: boost::statechart::state
< Incomplete
, Peering
>, NamedState
{
1315 typedef boost::mpl::list
<
1316 boost::statechart::custom_reaction
< AdvMap
>,
1317 boost::statechart::custom_reaction
< MNotifyRec
>,
1318 boost::statechart::custom_reaction
< QueryState
>
1320 explicit Incomplete(my_context ctx
);
1321 boost::statechart::result
react(const AdvMap
&advmap
);
1322 boost::statechart::result
react(const MNotifyRec
& infoevt
);
1323 boost::statechart::result
react(const QueryState
& q
);
1327 PGStateHistory state_history
;
1330 DoutPrefixProvider
*dpp
;
1331 PeeringListener
*pl
;
1333 /// context passed in by state machine caller
1334 PeeringCtx
*orig_ctx
;
1336 /// populated if we are buffering messages pending a flush
1337 std::optional
<BufferedRecoveryMessages
> messages_pending_flush
;
1340 * populated between start_handle() and end_handle(), points into
1341 * the message lists for messages_pending_flush while blocking messages
1342 * or into orig_ctx otherwise
1344 std::optional
<PeeringCtxWrapper
> rctx
;
1349 OSDMapRef osdmap_ref
; ///< Reference to current OSDMap
1350 PGPool pool
; ///< Current pool state
1351 epoch_t last_persisted_osdmap
= 0; ///< Last osdmap epoch persisted
1355 * Peering state information
1357 int role
= -1; ///< 0 = primary, 1 = replica, -1=none.
1358 uint64_t state
= 0; ///< PG_STATE_*
1360 pg_shard_t primary
; ///< id/shard of primary
1361 pg_shard_t pg_whoami
; ///< my id/shard
1362 pg_shard_t up_primary
; ///< id/shard of primary of up set
1363 vector
<int> up
; ///< crush mapping without temp pgs
1364 set
<pg_shard_t
> upset
; ///< up in set form
1365 vector
<int> acting
; ///< actual acting set for the current interval
1366 set
<pg_shard_t
> actingset
; ///< acting in set form
1368 /// union of acting, recovery, and backfill targets
1369 set
<pg_shard_t
> acting_recovery_backfill
;
1371 vector
<HeartbeatStampsRef
> hb_stamps
;
1373 ceph::signedspan readable_interval
= ceph::signedspan::zero();
1375 /// how long we can service reads in this interval
1376 ceph::signedspan readable_until
= ceph::signedspan::zero();
1378 /// upper bound on any acting OSDs' readable_until in this interval
1379 ceph::signedspan readable_until_ub
= ceph::signedspan::zero();
1381 /// upper bound from prior interval(s)
1382 ceph::signedspan prior_readable_until_ub
= ceph::signedspan::zero();
1384 /// pg instances from prior interval(s) that may still be readable
1385 set
<int> prior_readable_down_osds
;
1387 /// [replica] upper bound we got from the primary (primary's clock)
1388 ceph::signedspan readable_until_ub_from_primary
= ceph::signedspan::zero();
1390 /// [primary] last upper bound shared by primary to replicas
1391 ceph::signedspan readable_until_ub_sent
= ceph::signedspan::zero();
1393 /// [primary] readable ub acked by acting set members
1394 vector
<ceph::signedspan
> acting_readable_until_ub
;
1396 bool send_notify
= false; ///< True if a notify needs to be sent to the primary
1398 bool dirty_info
= false; ///< small info structu on disk out of date
1399 bool dirty_big_info
= false; ///< big info structure on disk out of date
1401 pg_info_t info
; ///< current pg info
1402 pg_info_t last_written_info
; ///< last written info
1403 PastIntervals past_intervals
; ///< information about prior pg mappings
1404 PGLog pg_log
; ///< pg log
1406 epoch_t last_peering_reset
= 0; ///< epoch of last peering reset
1408 /// last_update that has committed; ONLY DEFINED WHEN is_active()
1409 eversion_t last_update_ondisk
;
1410 eversion_t last_complete_ondisk
; ///< last_complete that has committed.
1411 eversion_t last_update_applied
; ///< last_update readable
1412 /// last version to which rollback_info trimming has been applied
1413 eversion_t last_rollback_info_trimmed_to_applied
;
1415 /// Counter to determine when pending flushes have completed
1416 unsigned flushes_in_progress
= 0;
1421 set
<pg_shard_t
> stray_set
; ///< non-acting osds that have PG data.
1422 map
<pg_shard_t
, pg_info_t
> peer_info
; ///< info from peers (stray or prior)
1423 map
<pg_shard_t
, int64_t> peer_bytes
; ///< Peer's num_bytes from peer_info
1424 set
<pg_shard_t
> peer_purged
; ///< peers purged
1425 map
<pg_shard_t
, pg_missing_t
> peer_missing
; ///< peer missing sets
1426 set
<pg_shard_t
> peer_log_requested
; ///< logs i've requested (and start stamps)
1427 set
<pg_shard_t
> peer_missing_requested
; ///< missing sets requested
1429 /// features supported by all peers
1430 uint64_t peer_features
= CEPH_FEATURES_SUPPORTED_DEFAULT
;
1431 /// features supported by acting set
1432 uint64_t acting_features
= CEPH_FEATURES_SUPPORTED_DEFAULT
;
1433 /// features supported by up and acting
1434 uint64_t upacting_features
= CEPH_FEATURES_SUPPORTED_DEFAULT
;
1436 /// most recently consumed osdmap's require_osd_version
1437 ceph_release_t last_require_osd_release
= ceph_release_t::unknown
;
1439 vector
<int> want_acting
; ///< non-empty while peering needs a new acting set
1441 // acting_recovery_backfill contains shards that are acting,
1442 // async recovery targets, or backfill targets.
1443 map
<pg_shard_t
,eversion_t
> peer_last_complete_ondisk
;
1445 /// up: min over last_complete_ondisk, peer_last_complete_ondisk
1446 eversion_t min_last_complete_ondisk
;
1447 /// point to which the log should be trimmed
1448 eversion_t pg_trim_to
;
1450 set
<int> blocked_by
; ///< osds we are blocked by (for pg stats)
1452 bool need_up_thru
= false; ///< true if osdmap with updated up_thru needed
1454 /// I deleted these strays; ignore racing PGInfo from them
1455 set
<pg_shard_t
> peer_activated
;
1457 set
<pg_shard_t
> backfill_targets
; ///< osds to be backfilled
1458 set
<pg_shard_t
> async_recovery_targets
; ///< osds to be async recovered
1460 /// osds which might have objects on them which are unfound on the primary
1461 set
<pg_shard_t
> might_have_unfound
;
1463 bool deleting
= false; /// true while in removing or OSD is shutting down
1464 std::atomic
<bool> deleted
= {false}; /// true once deletion complete
1466 MissingLoc missing_loc
; ///< information about missing objects
1468 bool backfill_reserved
= false;
1469 bool backfill_reserving
= false;
1471 PeeringMachine machine
;
1473 void update_osdmap_ref(OSDMapRef newmap
) {
1474 osdmap_ref
= std::move(newmap
);
1477 void update_heartbeat_peers();
1478 bool proc_replica_info(
1479 pg_shard_t from
, const pg_info_t
&oinfo
, epoch_t send_epoch
);
1480 void remove_down_peer_info(const OSDMapRef
&osdmap
);
1481 void check_recovery_sources(const OSDMapRef
& map
);
1482 void set_last_peering_reset();
1483 void check_full_transition(OSDMapRef lastmap
, OSDMapRef osdmap
);
1484 bool should_restart_peering(
1486 int newactingprimary
,
1487 const vector
<int>& newup
,
1488 const vector
<int>& newacting
,
1491 void start_peering_interval(
1492 const OSDMapRef lastmap
,
1493 const vector
<int>& newup
, int up_primary
,
1494 const vector
<int>& newacting
, int acting_primary
,
1495 ObjectStore::Transaction
&t
);
1496 void on_new_interval();
1497 void clear_recovery_state();
1498 void clear_primary_state();
1499 void check_past_interval_bounds() const;
1500 bool set_force_recovery(bool b
);
1501 bool set_force_backfill(bool b
);
1503 /// clip calculated priority to reasonable range
1504 int clamp_recovery_priority(int prio
, int pool_recovery_prio
, int max
);
1505 /// get log recovery reservation priority
1506 unsigned get_recovery_priority();
1507 /// get backfill reservation priority
1508 unsigned get_backfill_priority();
1509 /// get priority for pg deletion
1510 unsigned get_delete_priority();
1512 bool check_prior_readable_down_osds(const OSDMapRef
& map
);
1514 bool adjust_need_up_thru(const OSDMapRef osdmap
);
1515 PastIntervals::PriorSet
build_prior();
1517 void reject_reservation();
1520 map
<pg_shard_t
, pg_info_t
>::const_iterator
find_best_info(
1521 const map
<pg_shard_t
, pg_info_t
> &infos
,
1522 bool restrict_to_up_acting
,
1523 bool *history_les_bound
) const;
1524 static void calc_ec_acting(
1525 map
<pg_shard_t
, pg_info_t
>::const_iterator auth_log_shard
,
1527 const vector
<int> &acting
,
1528 const vector
<int> &up
,
1529 const map
<pg_shard_t
, pg_info_t
> &all_info
,
1530 bool restrict_to_up_acting
,
1532 set
<pg_shard_t
> *backfill
,
1533 set
<pg_shard_t
> *acting_backfill
,
1535 static void calc_replicated_acting(
1536 map
<pg_shard_t
, pg_info_t
>::const_iterator auth_log_shard
,
1537 uint64_t force_auth_primary_missing_objects
,
1539 const vector
<int> &acting
,
1540 const vector
<int> &up
,
1541 pg_shard_t up_primary
,
1542 const map
<pg_shard_t
, pg_info_t
> &all_info
,
1543 bool restrict_to_up_acting
,
1545 set
<pg_shard_t
> *backfill
,
1546 set
<pg_shard_t
> *acting_backfill
,
1547 const OSDMapRef osdmap
,
1549 void choose_async_recovery_ec(
1550 const map
<pg_shard_t
, pg_info_t
> &all_info
,
1551 const pg_info_t
&auth_info
,
1553 set
<pg_shard_t
> *async_recovery
,
1554 const OSDMapRef osdmap
) const;
1555 void choose_async_recovery_replicated(
1556 const map
<pg_shard_t
, pg_info_t
> &all_info
,
1557 const pg_info_t
&auth_info
,
1559 set
<pg_shard_t
> *async_recovery
,
1560 const OSDMapRef osdmap
) const;
1562 bool recoverable(const vector
<int> &want
) const;
1563 bool choose_acting(pg_shard_t
&auth_log_shard
,
1564 bool restrict_to_up_acting
,
1565 bool *history_les_bound
,
1566 bool request_pg_temp_change_only
= false);
1568 bool search_for_missing(
1569 const pg_info_t
&oinfo
, const pg_missing_t
&omissing
,
1571 PeeringCtxWrapper
&rctx
);
1572 void build_might_have_unfound();
1573 void log_weirdness();
1575 ObjectStore::Transaction
& t
,
1576 epoch_t activation_epoch
,
1577 PeeringCtxWrapper
&ctx
);
1579 void rewind_divergent_log(ObjectStore::Transaction
& t
, eversion_t newhead
);
1581 ObjectStore::Transaction
& t
, pg_info_t
&oinfo
,
1582 pg_log_t
&olog
, pg_shard_t from
);
1584 void proc_primary_info(ObjectStore::Transaction
&t
, const pg_info_t
&info
);
1585 void proc_master_log(ObjectStore::Transaction
& t
, pg_info_t
&oinfo
,
1586 pg_log_t
&olog
, pg_missing_t
& omissing
,
1588 void proc_replica_log(pg_info_t
&oinfo
, const pg_log_t
&olog
,
1589 pg_missing_t
& omissing
, pg_shard_t from
);
1591 void calc_min_last_complete_ondisk() {
1592 eversion_t min
= last_complete_ondisk
;
1593 ceph_assert(!acting_recovery_backfill
.empty());
1594 for (set
<pg_shard_t
>::iterator i
= acting_recovery_backfill
.begin();
1595 i
!= acting_recovery_backfill
.end();
1597 if (*i
== get_primary()) continue;
1598 if (peer_last_complete_ondisk
.count(*i
) == 0)
1599 return; // we don't have complete info
1600 eversion_t a
= peer_last_complete_ondisk
[*i
];
1604 if (min
== min_last_complete_ondisk
)
1606 min_last_complete_ondisk
= min
;
1611 pg_shard_t from
, const pg_query_t
&query
,
1612 pair
<pg_shard_t
, pg_info_t
> ¬ify_info
);
1614 pg_shard_t from
, const pg_query_t
&query
, epoch_t query_epoch
);
1615 void fulfill_query(const MQuery
& q
, PeeringCtxWrapper
&rctx
);
1617 void try_mark_clean();
1619 void update_blocked_by();
1620 void update_calc_stats();
1622 void add_log_entry(const pg_log_entry_t
& e
, bool applied
);
1624 void calc_trim_to();
1625 void calc_trim_to_aggressive();
1630 pg_shard_t pg_whoami
,
1634 DoutPrefixProvider
*dpp
,
1635 PeeringListener
*pl
);
1638 void handle_event(const boost::statechart::event_base
&evt
,
1641 machine
.process_event(evt
);
1646 void handle_event(PGPeeringEventRef evt
,
1649 machine
.process_event(evt
->get_event());
1653 /// Init fresh instance of PG
1656 const vector
<int>& newup
, int new_up_primary
,
1657 const vector
<int>& newacting
, int new_acting_primary
,
1658 const pg_history_t
& history
,
1659 const PastIntervals
& pi
,
1661 ObjectStore::Transaction
&t
);
1663 /// Init pg instance from disk state
1664 template <typename F
>
1665 auto init_from_disk_state(
1666 pg_info_t
&&info_from_disk
,
1667 PastIntervals
&&past_intervals_from_disk
,
1669 info
= std::move(info_from_disk
);
1670 last_written_info
= info
;
1671 past_intervals
= std::move(past_intervals_from_disk
);
1672 auto ret
= pg_log_init(pg_log
);
1677 /// Set initial primary/acting
1678 void init_primary_up_acting(
1679 const vector
<int> &newup
,
1680 const vector
<int> &newacting
,
1682 int new_acting_primary
);
1683 void init_hb_stamps();
1685 /// Set initial role
1686 void set_role(int r
) {
1690 /// Set predicates used for determining readable and recoverable
1691 void set_backend_predicates(
1692 IsPGReadablePredicate
*is_readable
,
1693 IsPGRecoverablePredicate
*is_recoverable
) {
1694 missing_loc
.set_backend_predicates(is_readable
, is_recoverable
);
1697 /// Send current pg_info to peers
1698 void share_pg_info();
1700 /// Get stats for child pgs
1701 void start_split_stats(
1702 const set
<spg_t
>& childpgs
, vector
<object_stat_sum_t
> *out
);
1704 /// Update new child with stats
1705 void finish_split_stats(
1706 const object_stat_sum_t
& stats
, ObjectStore::Transaction
&t
);
1708 /// Split state for child_pgid into *child
1710 pg_t child_pgid
, PeeringState
*child
, unsigned split_bits
);
1712 /// Merge state from sources
1714 map
<spg_t
,PeeringState
*>& sources
,
1716 unsigned split_bits
,
1717 const pg_merge_meta_t
& last_pg_merge_meta
);
1719 /// Permit stray replicas to purge now unnecessary state
1720 void purge_strays();
1725 * Mechanism for updating stats and/or history. Pass t to mark
1726 * dirty and write out. Return true if stats should be published
1730 std::function
<bool(pg_history_t
&, pg_stat_t
&)> f
,
1731 ObjectStore::Transaction
*t
= nullptr);
1734 * adjust_purged_snaps
1736 * Mechanism for updating purged_snaps. Marks dirty_info, big_dirty_info.
1738 void adjust_purged_snaps(
1739 std::function
<void(interval_set
<snapid_t
> &snaps
)> f
);
1741 /// Updates info.hit_set to hset_history, does not dirty
1742 void update_hset(const pg_hit_set_history_t
&hset_history
);
1747 * Merges new_history into info.history clearing past_intervals and
1748 * dirtying as needed.
1750 * Calls PeeringListener::on_info_history_change()
1752 void update_history(const pg_history_t
& new_history
);
1755 * prepare_stats_for_publish
1757 * Returns updated pg_stat_t if stats have changed since
1758 * pg_stats_publish adding in unstable_stats.
1760 std::optional
<pg_stat_t
> prepare_stats_for_publish(
1761 bool pg_stats_publish_valid
,
1762 const pg_stat_t
&pg_stats_publish
,
1763 const object_stat_collection_t
&unstable_stats
);
1766 * Merge entries updating missing as necessary on all
1767 * acting_recovery_backfill logs and missings (also missing_loc)
1769 bool append_log_entries_update_missing(
1770 const mempool::osd_pglog::list
<pg_log_entry_t
> &entries
,
1771 ObjectStore::Transaction
&t
,
1772 std::optional
<eversion_t
> trim_to
,
1773 std::optional
<eversion_t
> roll_forward_to
);
1776 * Updates local log to reflect new write from primary.
1779 const vector
<pg_log_entry_t
>& logv
,
1781 eversion_t roll_forward_to
,
1782 eversion_t min_last_complete_ondisk
,
1783 ObjectStore::Transaction
&t
,
1784 bool transaction_applied
,
1788 * Updates local log/missing to reflect new oob log update from primary
1790 void merge_new_log_entries(
1791 const mempool::osd_pglog::list
<pg_log_entry_t
> &entries
,
1792 ObjectStore::Transaction
&t
,
1793 std::optional
<eversion_t
> trim_to
,
1794 std::optional
<eversion_t
> roll_forward_to
);
1796 /// Update missing set to reflect e (TODOSAM: not sure why this is needed)
1797 void add_local_next_event(const pg_log_entry_t
& e
) {
1798 pg_log
.missing_add_next_entry(e
);
1801 /// Update log trim boundary
1802 void update_trim_to() {
1803 bool hard_limit
= (get_osdmap()->test_flag(CEPH_OSDMAP_PGLOG_HARDLIMIT
));
1805 calc_trim_to_aggressive();
1810 /// Pre-process pending update on hoid represented by logv
1812 const hobject_t
&hoid
,
1813 const vector
<pg_log_entry_t
>& logv
,
1814 eversion_t at_version
);
1816 /// Signal that oid has been locally recovered to version v
1818 const hobject_t
&oid
, eversion_t v
,
1820 ObjectStore::Transaction
&t
);
1822 /// Signal that oid has been recovered on peer to version
1823 void on_peer_recover(
1825 const hobject_t
&soid
,
1826 const eversion_t
&version
);
1828 /// Notify that soid is being recovered on peer
1829 void begin_peer_recover(
1831 const hobject_t soid
);
1833 /// Pull missing sets from all candidate peers
1834 bool discover_all_missing(
1835 BufferedRecoveryMessages
&rctx
);
1837 /// Notify that hoid has been fully recocovered
1838 void object_recovered(
1839 const hobject_t
&hoid
,
1840 const object_stat_sum_t
&stat_diff
) {
1841 info
.stats
.stats
.sum
.add(stat_diff
);
1842 missing_loc
.recovered(hoid
);
1845 /// Update info/stats to reflect backfill progress
1846 void update_backfill_progress(
1847 const hobject_t
&updated_backfill
,
1848 const pg_stat_t
&updated_stats
,
1849 bool preserve_local_num_bytes
,
1850 ObjectStore::Transaction
&t
);
1852 /// Update info/stats to reflect completed backfill on hoid
1853 void update_complete_backfill_object_stats(
1854 const hobject_t
&hoid
,
1855 const pg_stat_t
&stats
);
1857 /// Update last_backfill for peer to new_last_backfill
1858 void update_peer_last_backfill(
1860 const hobject_t
&new_last_backfill
);
1862 /// Update info.stats with delta_stats for operation on soid
1863 void apply_op_stats(
1864 const hobject_t
&soid
,
1865 const object_stat_sum_t
&delta_stats
);
1868 * force_object_missing
1870 * Force oid on peer to be missing at version. If the object does not
1871 * currently need recovery, either candidates if provided or the remainder
1872 * of the acting set will be deemed to have the object.
1874 void force_object_missing(
1875 const pg_shard_t
&peer
,
1876 const hobject_t
&oid
,
1877 eversion_t version
) {
1878 force_object_missing(set
<pg_shard_t
>{peer
}, oid
, version
);
1880 void force_object_missing(
1881 const set
<pg_shard_t
> &peer
,
1882 const hobject_t
&oid
,
1883 eversion_t version
);
1885 /// Update state prior to backfilling soid on targets
1886 void prepare_backfill_for_missing(
1887 const hobject_t
&soid
,
1888 const eversion_t
&version
,
1889 const vector
<pg_shard_t
> &targets
);
1891 /// Set targets with the right version for revert (see recover_primary)
1892 void set_revert_with_targets(
1893 const hobject_t
&soid
,
1894 const set
<pg_shard_t
> &good_peers
);
1896 /// Update lcod for fromosd
1897 void update_peer_last_complete_ondisk(
1900 peer_last_complete_ondisk
[fromosd
] = lcod
;
1904 void update_last_complete_ondisk(
1906 last_complete_ondisk
= lcod
;
1909 /// Update state to reflect recovery up to version
1910 void recovery_committed_to(eversion_t version
);
1912 /// Mark recovery complete
1913 void local_recovery_complete() {
1914 info
.last_complete
= info
.last_update
;
1917 /// Update last_requested pointer to v
1918 void set_last_requested(version_t v
) {
1919 pg_log
.set_last_requested(v
);
1922 /// Write dirty state to t
1923 void write_if_dirty(ObjectStore::Transaction
& t
);
1925 /// Mark write completed to v with persisted lc
1926 void complete_write(eversion_t v
, eversion_t lc
);
1928 /// Update local write applied pointer
1929 void local_write_applied(eversion_t v
) {
1930 last_update_applied
= v
;
1933 /// Updates peering state with new map
1935 OSDMapRef osdmap
, ///< [in] new osdmap
1936 OSDMapRef lastmap
, ///< [in] prev osdmap
1937 vector
<int>& newup
, ///< [in] new up set
1938 int up_primary
, ///< [in] new up primary
1939 vector
<int>& newacting
, ///< [in] new acting
1940 int acting_primary
, ///< [in] new acting primary
1941 PeeringCtx
&rctx
///< [out] recovery context
1944 /// Activates most recently updated map
1946 PeeringCtx
&rctx
///< [out] recovery context
1949 /// resets last_persisted_osdmap
1950 void reset_last_persisted() {
1951 last_persisted_osdmap
= 0;
1953 dirty_big_info
= true;
1956 /// Signal shutdown beginning
1961 /// Signal shutdown complete
1962 void set_delete_complete() {
1966 /// Dirty info and write out
1967 void force_write_state(ObjectStore::Transaction
&t
) {
1969 dirty_big_info
= true;
1973 /// Get current interval's readable_until
1974 ceph::signedspan
get_readable_until() const {
1975 return readable_until
;
1978 /// Get prior intervals' readable_until upper bound
1979 ceph::signedspan
get_prior_readable_until_ub() const {
1980 return prior_readable_until_ub
;
1983 /// Get prior intervals' readable_until down OSDs of note
1984 const set
<int>& get_prior_readable_down_osds() const {
1985 return prior_readable_down_osds
;
1988 /// Reset prior intervals' readable_until upper bound (e.g., bc it passed)
1989 void clear_prior_readable_until_ub() {
1990 prior_readable_until_ub
= ceph::signedspan::zero();
1991 prior_readable_down_osds
.clear();
1994 void renew_lease(ceph::signedspan now
) {
1995 bool was_min
= (readable_until_ub
== readable_until
);
1996 readable_until_ub_sent
= now
+ readable_interval
;
1998 recalc_readable_until();
2003 void schedule_renew_lease();
2005 pg_lease_t
get_lease() {
2006 return pg_lease_t(readable_until
, readable_until_ub_sent
, readable_interval
);
2009 void proc_lease(const pg_lease_t
& l
);
2010 void proc_lease_ack(int from
, const pg_lease_ack_t
& la
);
2011 void proc_renew_lease();
2013 pg_lease_ack_t
get_lease_ack() {
2014 return pg_lease_ack_t(readable_until_ub_from_primary
);
2017 /// [primary] recalc readable_until[_ub] for the current interval
2018 void recalc_readable_until();
2020 //============================ const helpers ================================
2021 const char *get_current_state() const {
2022 return state_history
.get_current_state();
2024 epoch_t
get_last_peering_reset() const {
2025 return last_peering_reset
;
2027 eversion_t
get_last_rollback_info_trimmed_to_applied() const {
2028 return last_rollback_info_trimmed_to_applied
;
2030 /// Returns stable reference to internal pool structure
2031 const PGPool
&get_pool() const {
2034 /// Returns reference to current osdmap
2035 const OSDMapRef
&get_osdmap() const {
2036 ceph_assert(osdmap_ref
);
2039 /// Returns epoch of current osdmap
2040 epoch_t
get_osdmap_epoch() const {
2041 return get_osdmap()->get_epoch();
2044 bool is_ec_pg() const override
{
2045 return pool
.info
.is_erasure();
2047 int get_pg_size() const override
{
2048 return pool
.info
.size
;
2050 bool is_deleting() const {
2053 bool is_deleted() const {
2056 const set
<pg_shard_t
> &get_upset() const override
{
2059 bool is_acting_recovery_backfill(pg_shard_t osd
) const {
2060 return acting_recovery_backfill
.count(osd
);
2062 bool is_acting(pg_shard_t osd
) const {
2063 return has_shard(pool
.info
.is_erasure(), acting
, osd
);
2065 bool is_up(pg_shard_t osd
) const {
2066 return has_shard(pool
.info
.is_erasure(), up
, osd
);
2068 static bool has_shard(bool ec
, const vector
<int>& v
, pg_shard_t osd
) {
2070 return v
.size() > (unsigned)osd
.shard
&& v
[osd
.shard
] == osd
.osd
;
2072 return std::find(v
.begin(), v
.end(), osd
.osd
) != v
.end();
2075 const PastIntervals
& get_past_intervals() const {
2076 return past_intervals
;
2078 /// acting osd that is not the primary
2079 bool is_nonprimary() const {
2080 return role
>= 0 && pg_whoami
!= primary
;
2083 bool is_primary() const {
2084 return pg_whoami
== primary
;
2086 bool pg_has_reset_since(epoch_t e
) const {
2087 return deleted
|| e
< get_last_peering_reset();
2090 int get_role() const {
2093 const vector
<int> &get_acting() const {
2096 const set
<pg_shard_t
> &get_actingset() const {
2099 int get_acting_primary() const {
2102 pg_shard_t
get_primary() const {
2105 const vector
<int> &get_up() const {
2108 int get_up_primary() const {
2109 return up_primary
.osd
;
2112 bool is_backfill_target(pg_shard_t osd
) const {
2113 return backfill_targets
.count(osd
);
2115 const set
<pg_shard_t
> &get_backfill_targets() const {
2116 return backfill_targets
;
2118 bool is_async_recovery_target(pg_shard_t peer
) const {
2119 return async_recovery_targets
.count(peer
);
2121 const set
<pg_shard_t
> &get_async_recovery_targets() const {
2122 return async_recovery_targets
;
2124 const set
<pg_shard_t
> &get_acting_recovery_backfill() const {
2125 return acting_recovery_backfill
;
2128 const PGLog
&get_pg_log() const {
2132 bool state_test(uint64_t m
) const { return (state
& m
) != 0; }
2133 void state_set(uint64_t m
) { state
|= m
; }
2134 void state_clear(uint64_t m
) { state
&= ~m
; }
2136 bool is_complete() const { return info
.last_complete
== info
.last_update
; }
2137 bool should_send_notify() const { return send_notify
; }
2139 uint64_t get_state() const { return state
; }
2140 bool is_active() const { return state_test(PG_STATE_ACTIVE
); }
2141 bool is_activating() const { return state_test(PG_STATE_ACTIVATING
); }
2142 bool is_peering() const { return state_test(PG_STATE_PEERING
); }
2143 bool is_down() const { return state_test(PG_STATE_DOWN
); }
2144 bool is_recovery_unfound() const {
2145 return state_test(PG_STATE_RECOVERY_UNFOUND
);
2147 bool is_backfill_unfound() const {
2148 return state_test(PG_STATE_BACKFILL_UNFOUND
);
2150 bool is_incomplete() const { return state_test(PG_STATE_INCOMPLETE
); }
2151 bool is_clean() const { return state_test(PG_STATE_CLEAN
); }
2152 bool is_degraded() const { return state_test(PG_STATE_DEGRADED
); }
2153 bool is_undersized() const { return state_test(PG_STATE_UNDERSIZED
); }
2154 bool is_remapped() const { return state_test(PG_STATE_REMAPPED
); }
2155 bool is_peered() const {
2156 return state_test(PG_STATE_ACTIVE
) || state_test(PG_STATE_PEERED
);
2158 bool is_recovering() const { return state_test(PG_STATE_RECOVERING
); }
2159 bool is_premerge() const { return state_test(PG_STATE_PREMERGE
); }
2160 bool is_repair() const { return state_test(PG_STATE_REPAIR
); }
2161 bool is_empty() const { return info
.last_update
== eversion_t(0,0); }
2163 bool get_need_up_thru() const {
2164 return need_up_thru
;
2167 bool is_forced_recovery_or_backfill() const {
2168 return get_state() & (PG_STATE_FORCED_RECOVERY
| PG_STATE_FORCED_BACKFILL
);
2171 bool is_backfill_reserved() const {
2172 return backfill_reserved
;
2175 bool is_backfill_reserving() const {
2176 return backfill_reserving
;
2179 ceph_release_t
get_last_require_osd_release() const {
2180 return last_require_osd_release
;
2183 const pg_info_t
&get_info() const {
2187 const decltype(peer_info
) &get_peer_info() const {
2190 const decltype(peer_missing
) &get_peer_missing() const {
2191 return peer_missing
;
2193 const pg_missing_const_i
&get_peer_missing(const pg_shard_t
&peer
) const {
2194 if (peer
== pg_whoami
) {
2195 return pg_log
.get_missing();
2197 assert(peer_missing
.count(peer
));
2198 return peer_missing
.find(peer
)->second
;
2201 const pg_info_t
&get_peer_info(pg_shard_t peer
) const {
2202 assert(peer_info
.count(peer
));
2203 return peer_info
.find(peer
)->second
;
2205 bool has_peer_info(pg_shard_t peer
) const {
2206 return peer_info
.count(peer
);
2209 bool needs_recovery() const;
2210 bool needs_backfill() const;
2213 * Returns whether a particular object can be safely read on this replica
2215 bool can_serve_replica_read(const hobject_t
&hoid
) {
2216 ceph_assert(!is_primary());
2217 return !pg_log
.get_log().has_write_since(
2218 hoid
, get_min_last_complete_ondisk());
2222 * Returns whether all peers which might have unfound objects have been
2223 * queried or marked lost.
2225 bool all_unfound_are_queried_or_lost(const OSDMapRef osdmap
) const;
2226 bool all_missing_unfound() const {
2227 const auto& missing
= pg_log
.get_missing();
2228 if (!missing
.have_missing())
2230 for (auto& m
: missing
.get_items()) {
2231 if (!missing_loc
.is_unfound(m
.first
))
2237 bool perform_deletes_during_peering() const {
2238 return !(get_osdmap()->test_flag(CEPH_OSDMAP_RECOVERY_DELETES
));
2242 bool have_unfound() const {
2243 return missing_loc
.have_unfound();
2245 uint64_t get_num_unfound() const {
2246 return missing_loc
.num_unfound();
2249 bool have_missing() const {
2250 return pg_log
.get_missing().num_missing() > 0;
2252 unsigned int get_num_missing() const {
2253 return pg_log
.get_missing().num_missing();
2256 const MissingLoc
&get_missing_loc() const {
2260 const MissingLoc::missing_by_count_t
&get_missing_by_count() const {
2261 return missing_loc
.get_missing_by_count();
2264 eversion_t
get_min_last_complete_ondisk() const {
2265 return min_last_complete_ondisk
;
2268 eversion_t
get_pg_trim_to() const {
2272 eversion_t
get_last_update_applied() const {
2273 return last_update_applied
;
2276 bool debug_has_dirty_state() const {
2277 return dirty_info
|| dirty_big_info
;
2280 std::string
get_pg_state_string() const {
2281 return pg_state_string(state
);
2284 /// Dump representation of past_intervals to out
2285 void print_past_intervals(ostream
&out
) const {
2286 out
<< "[" << past_intervals
.get_bounds()
2287 << ")/" << past_intervals
.size();
2290 void dump_history(Formatter
*f
) const {
2291 state_history
.dump(f
);
2294 /// Dump formatted peering status
2295 void dump_peering_state(Formatter
*f
);
2298 /// Mask feature vector with feature set from new peer
2299 void apply_peer_features(uint64_t f
) { peer_features
&= f
; }
2301 /// Reset feature vector to default
2302 void reset_min_peer_features() {
2303 peer_features
= CEPH_FEATURES_SUPPORTED_DEFAULT
;
2306 /// Get feature vector common to all known peers with this pg
2307 uint64_t get_min_peer_features() const { return peer_features
; }
2309 /// Get feature vector common to acting set
2310 uint64_t get_min_acting_features() const { return acting_features
; }
2312 /// Get feature vector common to up/acting set
2313 uint64_t get_min_upacting_features() const { return upacting_features
; }
2316 // Flush control interface
2319 * Start additional flush (blocks needs_flush/activation until
2320 * complete_flush is called once for each start_flush call as
2321 * required by start_flush_on_transaction).
2323 void start_flush(ObjectStore::Transaction
&t
) {
2324 flushes_in_progress
++;
2325 pl
->start_flush_on_transaction(t
);
2328 /// True if there are outstanding flushes
2329 bool needs_flush() const {
2330 return flushes_in_progress
> 0;
2332 /// Must be called once per start_flush
2333 void complete_flush();
2335 friend ostream
&operator<<(ostream
&out
, const PeeringState
&ps
);
2338 ostream
&operator<<(ostream
&out
, const PeeringState
&ps
);