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
58 [[nodiscard]] ccf::View view_at(ccf::kv::Version idx) const
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
71 [[nodiscard]] ccf::kv::Version start_of_view(ccf::View view) const
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
88 [[nodiscard]] ccf::kv::Version end_of_view(ccf::View view) const
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 [[nodiscard]] std::vector<ccf::kv::Version> get_history_until(
108 ccf::kv::Version idx = std::numeric_limits<ccf::kv::Version>::max()) const
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 [[nodiscard]] std::vector<ccf::kv::Version> get_history_since(
115 uint64_t view) const
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
133 struct State
134 {
135 State(ccf::NodeId node_id_, bool pre_vote_enabled_ = true) :
136 node_id(std::move(node_id_)),
137 pre_vote_enabled(pre_vote_enabled_)
138 {}
139 State() = default;
140
142
148
149 // Indices that are eligible for global commit, from a Node's perspective
150 std::deque<Index> committable_indices;
151
152 // Replicas start in leadership state Follower. Apart from a single forced
153 // transition from Follower to Leader on the initial node at startup,
154 // the state machine is made up of the following transitions:
155 //
156 // Follower -> Candidate, when election timeout expires
157 // Follower -> Retired, when commit advances past the last config containing
158 // the node
159 // Candidate -> Leader, upon collecting enough votes
160 // Leader -> Retired, when commit advances past the last config containing
161 // the node
162 // Leader -> Follower, when receiving entries for a newer term
163 // Candidate -> Follower, when receiving entries for a newer term
167
168 std::optional<ccf::kv::RetirementPhase> retirement_phase = std::nullopt;
169 // Index at which this node observes its retirement
170 std::optional<ccf::SeqNo> retirement_idx = std::nullopt;
171 // Earliest index at which this node's retirement can be committed
172 std::optional<ccf::SeqNo> retirement_committable_idx = std::nullopt;
173 // Index at which this node observes its retired_committed, only set when
174 // that index itself is committed
175 std::optional<ccf::SeqNo> retired_committed_idx = std::nullopt;
176
177 bool pre_vote_enabled = true;
178 };
181 State,
182 node_id,
183 current_view,
184 last_idx,
185 commit_idx,
186 leadership_state,
187 membership_state,
188 pre_vote_enabled);
190 State,
191 retirement_phase,
192 retirement_idx,
193 retirement_committable_idx,
194 retired_committed_idx);
195}
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:124
std::vector< ccf::kv::Version > get_history_until(ccf::kv::Version idx=std::numeric_limits< ccf::kv::Version >::max()) const
Definition state.h:107
ccf::kv::Version end_of_view(ccf::View view) const
Definition state.h:88
ccf::kv::Version start_of_view(ccf::View view) const
Definition state.h:71
static constexpr ccf::View InvalidView
Definition state.h:24
void initialise(const std::vector< ccf::kv::Version > &terms_)
Definition state.h:26
std::vector< ccf::kv::Version > get_history_since(uint64_t view) const
Definition state.h:114
ccf::View view_at(ccf::kv::Version idx) const
Definition state.h:58
#define LOG_DEBUG_FMT
Definition internal_logger.h:14
#define DECLARE_JSON_REQUIRED_FIELDS(TYPE,...)
Definition json.h:736
#define DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(TYPE)
Definition json.h:712
#define DECLARE_JSON_OPTIONAL_FIELDS(TYPE,...)
Definition json.h:811
Definition state.h:17
uint64_t Version
Definition version.h:10
MembershipState
Definition kv_types.h:125
LeadershipState
Definition kv_types.h:108
std::mutex Mutex
Definition locking.h:12
constexpr View VIEW_UNKNOWN
Definition tx_id.h:26
uint64_t View
Definition tx_id.h:23
STL namespace.
Definition state.h:134
ccf::NodeId node_id
Definition state.h:143
ccf::kv::Version last_idx
Definition state.h:145
bool pre_vote_enabled
Definition state.h:177
ccf::pal::Mutex lock
Definition state.h:141
std::optional< ccf::SeqNo > retirement_idx
Definition state.h:170
ccf::kv::LeadershipState leadership_state
Definition state.h:164
std::optional< ccf::kv::RetirementPhase > retirement_phase
Definition state.h:168
std::optional< ccf::SeqNo > retired_committed_idx
Definition state.h:175
ccf::View current_view
Definition state.h:144
State(ccf::NodeId node_id_, bool pre_vote_enabled_=true)
Definition state.h:135
std::deque< Index > committable_indices
Definition state.h:150
ccf::kv::MembershipState membership_state
Definition state.h:165
ccf::kv::Version commit_idx
Definition state.h:146
ViewHistory view_history
Definition state.h:147
std::optional< ccf::SeqNo > retirement_committable_idx
Definition state.h:172
State()=default