summaryrefslogtreecommitdiffstats
path: root/src/crimson/osd/state.h
blob: f0676a4ec4b8d9e0aaefa8d19f6fee4a5ae2ef4f (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
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#pragma once

#include <string_view>
#include <ostream>

#include <seastar/core/shared_future.hh>

class OSDMap;

namespace crimson::osd {

// seastar::sharded puts start_single on core 0
constexpr core_id_t PRIMARY_CORE = 0;

/**
 * OSDState
 *
 * Maintains state representing the OSD's progress from booting through
 * shutdown.
 *
 * Shards other than PRIMARY_CORE may use their local instance to check
 * on ACTIVE and STOPPING.  All other methods are restricted to
 * PRIMARY_CORE (such methods start with an assert to this effect).
 */
class OSDState : public seastar::peering_sharded_service<OSDState> {

  enum class State {
    INITIALIZING,
    PREBOOT,
    BOOTING,
    ACTIVE,
    PRESTOP,
    STOPPING,
    WAITING_FOR_HEALTHY,
  };

  State state = State::INITIALIZING;
  mutable seastar::shared_promise<> wait_for_active;

  /// Sets local instance state to active, called from set_active
  void _set_active() {
    state = State::ACTIVE;
    wait_for_active.set_value();
    wait_for_active = {};
  }
  /// Sets local instance state to stopping, called from set_stopping
  void _set_stopping() {
    state = State::STOPPING;
    wait_for_active.set_exception(crimson::common::system_shutdown_exception{});
    wait_for_active = {};
  }
public:
  bool is_initializing() const {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    return state == State::INITIALIZING;
  }
  bool is_preboot() const {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    return state == State::PREBOOT;
  }
  bool is_booting() const {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    return state == State::BOOTING;
  }
  bool is_active() const {
    return state == State::ACTIVE;
  }
  seastar::future<> when_active() const {
    return is_active() ? seastar::now()
                       : wait_for_active.get_shared_future();
  };
  bool is_prestop() const {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    return state == State::PRESTOP;
  }
  bool is_stopping() const {
    return state == State::STOPPING;
  }
  bool is_waiting_for_healthy() const {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    return state == State::WAITING_FOR_HEALTHY;
  }
  void set_preboot() {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    state = State::PREBOOT;
  }
  void set_booting() {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    state = State::BOOTING;
  }
  /// Sets all shards to active
  seastar::future<> set_active() {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    return container().invoke_on_all([](auto& osd_state) {
      osd_state._set_active();
    });
  }
  void set_prestop() {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    state = State::PRESTOP;
  }
  /// Sets all shards to stopping
  seastar::future<> set_stopping() {
    ceph_assert(seastar::this_shard_id() == PRIMARY_CORE);
    return container().invoke_on_all([](auto& osd_state) {
      osd_state._set_stopping();
    });
  }
  std::string_view to_string() const {
    switch (state) {
    case State::INITIALIZING: return "initializing";
    case State::PREBOOT: return "preboot";
    case State::BOOTING: return "booting";
    case State::ACTIVE: return "active";
    case State::PRESTOP: return "prestop";
    case State::STOPPING: return "stopping";
    case State::WAITING_FOR_HEALTHY: return "waiting_for_healthy";
    default: return "???";
    }
  }
};

inline std::ostream&
operator<<(std::ostream& os, const OSDState& s) {
  return os << s.to_string();
}
}