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