CCF
Loading...
Searching...
No Matches
state.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
6#include "ccf/pal/locking.h"
7#include "ccf/tx_status.h"
10#include "kv/kv_types.h"
11
12#include <deque>
13#include <map>
14#include <set>
15
16namespace aft
17{
19 {
20 // Entry i stores the first version in view i+1
21 std::vector<ccf::kv::Version> views;
22
23 public:
25
26 void initialise(const std::vector<ccf::kv::Version>& terms_)
27 {
28 views.clear();
29 for (size_t i = 0; i < terms_.size(); ++i)
30 {
31 update(terms_[i], i + 1);
32 }
33 LOG_DEBUG_FMT("Initialised views: {}", fmt::join(views, ", "));
34 }
35
37 {
38 LOG_DEBUG_FMT("Updating view to: {} at version: {}", view, idx);
39 if (!views.empty())
40 {
41 const auto current_latest_index = views.back();
42 if (idx < current_latest_index)
43 {
44 throw std::logic_error(fmt::format(
45 "version must not move backwards ({} < {})",
46 idx,
47 current_latest_index));
48 }
49 }
50
51 for (ccf::View i = views.size(); i < view; ++i)
52 {
53 views.push_back(idx);
54 }
55 LOG_DEBUG_FMT("Resulting views: {}", fmt::join(views, ", "));
56 }
57
59 {
60 auto it = upper_bound(views.begin(), views.end(), idx);
61
62 // Indices before the version of the first view are unknown
63 if (it == views.begin())
64 {
65 return InvalidView;
66 }
67
68 return (it - views.begin());
69 }
70
72 {
73 if (view > views.size() || view == InvalidView)
74 {
75 return ccf::kv::NoVersion;
76 }
77
78 // NB: If views == {5, 10, 10}, then view 2 doesn't start at 10. View 2
79 // contains no transactions, and view 3 starts at 10
80 const auto tentative = views[view - 1];
81 if (view + 1 <= views.size() && views[view] == tentative)
82 {
83 return ccf::kv::NoVersion;
84 }
85 return tentative;
86 }
87
89 {
90 // If this view has no start (potentially because it contains no
91 // transactions), then it can't have an end
92 if (start_of_view(view) == ccf::kv::NoVersion)
93 {
94 return ccf::kv::NoVersion;
95 }
96
97 if (view >= views.size() || view == InvalidView)
98 {
99 return ccf::kv::NoVersion;
100 }
101
102 // Otherwise the end of this view is the transaction before (- 1) the
103 // start of the next view (views[view])
104 return views[view] - 1;
105 }
106
107 std::vector<ccf::kv::Version> get_history_until(
108 ccf::kv::Version idx = std::numeric_limits<ccf::kv::Version>::max())
109 {
110 return {views.begin(), std::upper_bound(views.begin(), views.end(), idx)};
111 }
112
113 // view should be non-zero as views start at one in here
114 std::vector<ccf::kv::Version> get_history_since(uint64_t view)
115 {
116 if (view > views.size())
117 {
118 return {};
119 }
120 return {views.begin() + view - 1, views.end()};
121 }
122
124 {
125 auto it = upper_bound(views.begin(), views.end(), idx);
126 views.erase(it, views.end());
128 "Resulting views from rollback: {}", fmt::join(views, ", "));
129 }
130 };
131
133 {
134 public:
135 Replica(ccf::NodeId id_, const std::vector<uint8_t>& cert_) :
136 id(std::move(id_)),
137 verifier(ccf::crypto::make_unique_verifier(cert_))
138 {}
139
140 [[nodiscard]] ccf::NodeId get_id() const
141 {
142 return id;
143 }
144
145 private:
146 ccf::NodeId id;
148 };
149
150 struct State
151 {
152 State(ccf::NodeId node_id_, bool pre_vote_enabled_ = true) :
153 node_id(std::move(node_id_)),
154 pre_vote_enabled(pre_vote_enabled_)
155 {}
156 State() = default;
157
159
165
166 // Indices that are eligible for global commit, from a Node's perspective
167 std::deque<Index> committable_indices;
168
169 // Replicas start in leadership state Follower. Apart from a single forced
170 // transition from Follower to Leader on the initial node at startup,
171 // the state machine is made up of the following transitions:
172 //
173 // Follower -> Candidate, when election timeout expires
174 // Follower -> Retired, when commit advances past the last config containing
175 // the node
176 // Candidate -> Leader, upon collecting enough votes
177 // Leader -> Retired, when commit advances past the last config containing
178 // the node
179 // Leader -> Follower, when receiving entries for a newer term
180 // Candidate -> Follower, when receiving entries for a newer term
184
185 std::optional<ccf::kv::RetirementPhase> retirement_phase = std::nullopt;
186 // Index at which this node observes its retirement
187 std::optional<ccf::SeqNo> retirement_idx = std::nullopt;
188 // Earliest index at which this node's retirement can be committed
189 std::optional<ccf::SeqNo> retirement_committable_idx = std::nullopt;
190 // Index at which this node observes its retired_committed, only set when
191 // that index itself is committed
192 std::optional<ccf::SeqNo> retired_committed_idx = std::nullopt;
193
194 bool pre_vote_enabled = true;
195 };
198 State,
199 node_id,
200 current_view,
201 last_idx,
202 commit_idx,
203 leadership_state,
204 membership_state,
205 pre_vote_enabled);
207 State,
208 retirement_phase,
209 retirement_idx,
210 retirement_committable_idx,
211 retired_committed_idx);
212}
Definition state.h:133
ccf::NodeId get_id() const
Definition state.h:140
Replica(ccf::NodeId id_, const std::vector< uint8_t > &cert_)
Definition state.h:135
Definition state.h:19
void update(ccf::kv::Version idx, ccf::View view)
Definition state.h:36
void rollback(ccf::kv::Version idx)
Definition state.h:123
std::vector< ccf::kv::Version > get_history_until(ccf::kv::Version idx=std::numeric_limits< ccf::kv::Version >::max())
Definition state.h:107
static constexpr ccf::View InvalidView
Definition state.h:24
ccf::kv::Version end_of_view(ccf::View view)
Definition state.h:88
void initialise(const std::vector< ccf::kv::Version > &terms_)
Definition state.h:26
ccf::kv::Version start_of_view(ccf::View view)
Definition state.h:71
std::vector< ccf::kv::Version > get_history_since(uint64_t view)
Definition state.h:114
ccf::View view_at(ccf::kv::Version idx)
Definition state.h:58
#define LOG_DEBUG_FMT
Definition internal_logger.h:14
#define DECLARE_JSON_REQUIRED_FIELDS(TYPE,...)
Definition json.h:718
#define DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(TYPE)
Definition json.h:694
#define DECLARE_JSON_OPTIONAL_FIELDS(TYPE,...)
Definition json.h:790
Definition state.h:17
std::unique_ptr< Verifier > VerifierUniquePtr
Definition verifier.h:168
uint64_t Version
Definition version.h:8
MembershipState
Definition kv_types.h:122
LeadershipState
Definition kv_types.h:105
std::mutex Mutex
Definition locking.h:12
Definition app_interface.h:14
constexpr View VIEW_UNKNOWN
Definition tx_id.h:26
uint64_t View
Definition tx_id.h:23
STL namespace.
Definition state.h:151
ccf::NodeId node_id
Definition state.h:160
ccf::kv::Version last_idx
Definition state.h:162
bool pre_vote_enabled
Definition state.h:194
ccf::pal::Mutex lock
Definition state.h:158
std::optional< ccf::SeqNo > retirement_idx
Definition state.h:187
ccf::kv::LeadershipState leadership_state
Definition state.h:181
std::optional< ccf::kv::RetirementPhase > retirement_phase
Definition state.h:185
std::optional< ccf::SeqNo > retired_committed_idx
Definition state.h:192
ccf::View current_view
Definition state.h:161
State(ccf::NodeId node_id_, bool pre_vote_enabled_=true)
Definition state.h:152
std::deque< Index > committable_indices
Definition state.h:167
ccf::kv::MembershipState membership_state
Definition state.h:182
ccf::kv::Version commit_idx
Definition state.h:163
ViewHistory view_history
Definition state.h:164
std::optional< ccf::SeqNo > retirement_committable_idx
Definition state.h:189
State()=default