/Users/deen/code/yugabyte-db/src/yb/consensus/consensus_meta.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | #ifndef YB_CONSENSUS_CONSENSUS_META_H_ |
33 | | #define YB_CONSENSUS_CONSENSUS_META_H_ |
34 | | |
35 | | #include <stdint.h> |
36 | | |
37 | | #include <atomic> |
38 | | #include <string> |
39 | | |
40 | | #include "yb/common/common_types.pb.h" |
41 | | #include "yb/common/entity_ids_types.h" |
42 | | |
43 | | #include "yb/consensus/metadata.pb.h" |
44 | | |
45 | | #include "yb/gutil/macros.h" |
46 | | |
47 | | #include "yb/util/status_fwd.h" |
48 | | |
49 | | namespace yb { |
50 | | |
51 | | class FsManager; |
52 | | class ServerRegistrationPB; |
53 | | |
54 | | namespace consensus { |
55 | | |
56 | | // Provides methods to read, write, and persist consensus-related metadata. |
57 | | // This partly corresponds to Raft Figure 2's "Persistent state on all servers". |
58 | | // |
59 | | // In addition to the persistent state, this class also provides access to some |
60 | | // transient state. This includes the peer that this node considers to be the |
61 | | // leader of the configuration, as well as the "pending" configuration, if any. |
62 | | // |
63 | | // Conceptually, a pending configuration is one that has been proposed via a config |
64 | | // change operation (AddServer or RemoveServer from Chapter 4 of Diego Ongaro's |
65 | | // Raft thesis) but has not yet been committed. According to the above spec, |
66 | | // as soon as a server hears of a new cluster membership configuration, it must |
67 | | // be adopted (even prior to be committed). |
68 | | // |
69 | | // The data structure difference between a committed configuration and a pending one |
70 | | // is that opid_index (the index in the log of the committed config change |
71 | | // operation) is always set in a committed configuration, while it is always unset in |
72 | | // a pending configuration. |
73 | | // |
74 | | // Finally, this class exposes the concept of an "active" configuration, which means |
75 | | // the pending configuration if a pending configuration is set, otherwise the committed |
76 | | // configuration. |
77 | | // |
78 | | // This class is not thread-safe and requires external synchronization. |
79 | | class ConsensusMetadata { |
80 | | public: |
81 | | // Create a ConsensusMetadata object with provided initial state. |
82 | | // Encoded PB is flushed to disk before returning. |
83 | | static CHECKED_STATUS Create(FsManager* fs_manager, |
84 | | const std::string& tablet_id, |
85 | | const std::string& peer_uuid, |
86 | | const RaftConfigPB& config, |
87 | | int64_t current_term, |
88 | | std::unique_ptr<ConsensusMetadata>* cmeta); |
89 | | |
90 | | // Load a ConsensusMetadata object from disk. |
91 | | // Returns Status::NotFound if the file could not be found. May return other |
92 | | // Status codes if unable to read the file. |
93 | | static CHECKED_STATUS Load(FsManager* fs_manager, |
94 | | const std::string& tablet_id, |
95 | | const std::string& peer_uuid, |
96 | | std::unique_ptr<ConsensusMetadata>* cmeta); |
97 | | |
98 | | // Delete the ConsensusMetadata file associated with the given tablet from |
99 | | // disk. |
100 | | static CHECKED_STATUS DeleteOnDiskData(FsManager* fs_manager, const std::string& tablet_id); |
101 | | |
102 | | // Accessors for current term. |
103 | | int64_t current_term() const; |
104 | | void set_current_term(int64_t term); |
105 | | |
106 | | // Accessors for voted_for. |
107 | | bool has_voted_for() const; |
108 | | const std::string& voted_for() const; |
109 | | void clear_voted_for(); |
110 | | void set_voted_for(const std::string& uuid); |
111 | | |
112 | | // Accessors for committed configuration. |
113 | | const RaftConfigPB& committed_config() const; |
114 | | void set_committed_config(const RaftConfigPB& config); |
115 | | |
116 | | // Accessors for split_parent_tablet_id. |
117 | | bool has_split_parent_tablet_id() const; |
118 | | const TabletId& split_parent_tablet_id() const; |
119 | | void set_split_parent_tablet_id(const TabletId& split_parent_tablet_id); |
120 | | |
121 | | // Returns whether a pending configuration is set. |
122 | | bool has_pending_config() const; |
123 | | |
124 | | // Returns the pending configuration if one is set. Otherwise, fires a DCHECK. |
125 | | const RaftConfigPB& pending_config() const; |
126 | | |
127 | | // Set & clear the pending configuration. |
128 | | void clear_pending_config(); |
129 | | void set_pending_config(const RaftConfigPB& config); |
130 | | |
131 | | // If a pending configuration is set, return it. |
132 | | // Otherwise, return the committed configuration. |
133 | | const RaftConfigPB& active_config() const; |
134 | | |
135 | | // Accessors for setting the active leader. |
136 | | const std::string& leader_uuid() const; |
137 | | void set_leader_uuid(const std::string& uuid); |
138 | | void clear_leader_uuid(); |
139 | | |
140 | 71 | const TabletId& tablet_id() { return tablet_id_; } |
141 | | |
142 | 135 | void set_tablet_id(const TabletId& tablet_id) { tablet_id_ = tablet_id; } |
143 | | |
144 | | // Returns the currently active role of the current node. |
145 | | PeerRole active_role() const; |
146 | | |
147 | | // Copy the stored state into a ConsensusStatePB object. |
148 | | // To get the active configuration, specify 'type' = ACTIVE. |
149 | | // Otherwise, 'type' = COMMITTED will return a version of the |
150 | | // ConsensusStatePB using only the committed configuration. In this case, if the |
151 | | // current leader is not a member of the committed configuration, then the |
152 | | // leader_uuid field of the returned ConsensusStatePB will be cleared. |
153 | | ConsensusStatePB ToConsensusStatePB(ConsensusConfigType type) const; |
154 | | |
155 | | // Merge the committed consensus state from the source node during remote |
156 | | // bootstrap. |
157 | | // |
158 | | // This method will clear any pending config change, replace the committed |
159 | | // consensus config with the one in 'committed_cstate', and clear the |
160 | | // currently tracked leader. |
161 | | // |
162 | | // It will also check whether the current term passed in 'committed_cstate' |
163 | | // is greater than the currently recorded one. If so, it will update the |
164 | | // local current term to match the passed one and it will clear the voting |
165 | | // record for this node. If the current term in 'committed_cstate' is less |
166 | | // than the locally recorded term, the locally recorded term and voting |
167 | | // record are not changed. |
168 | | void MergeCommittedConsensusStatePB(const ConsensusStatePB& committed_cstate); |
169 | | |
170 | | // Persist current state of the protobuf to disk. |
171 | | CHECKED_STATUS Flush(); |
172 | | |
173 | | // The on-disk size of the consensus metadata, as of the last call to Load() or Flush(). |
174 | 8.07k | int64_t on_disk_size() const { |
175 | 8.07k | return on_disk_size_.load(std::memory_order_acquire); |
176 | 8.07k | } |
177 | | |
178 | | // A lock-free way to read role and term atomically. |
179 | | std::pair<PeerRole, int64_t> GetRoleAndTerm() const; |
180 | | |
181 | | // Used internally for storing the role + term combination atomically. |
182 | | using PackedRoleAndTerm = uint64; |
183 | | |
184 | | private: |
185 | | ConsensusMetadata(FsManager* fs_manager, std::string tablet_id, |
186 | | std::string peer_uuid); |
187 | | |
188 | | std::string LogPrefix() const; |
189 | | |
190 | | // Updates the cached active role. |
191 | | void UpdateActiveRole(); |
192 | | |
193 | | // Updates the cached on-disk size of the consensus metadata. |
194 | | Status UpdateOnDiskSize(); |
195 | | |
196 | | void UpdateRoleAndTermCache(); |
197 | | |
198 | | // Transient fields. |
199 | | // Constants: |
200 | | FsManager* const fs_manager_; |
201 | | std::string tablet_id_; |
202 | | const std::string peer_uuid_; |
203 | | // Mutable: |
204 | | std::string leader_uuid_; // Leader of the current term (term == pb_.current_term). |
205 | | bool has_pending_config_; // Indicates whether there is an as-yet uncommitted |
206 | | // configuration change pending. |
207 | | // RaftConfig used by the peers when there is a pending config change operation. |
208 | | RaftConfigPB pending_config_; |
209 | | |
210 | | // Cached role of the peer_uuid_ within the active configuration. |
211 | | PeerRole active_role_; |
212 | | |
213 | | // Durable fields. |
214 | | ConsensusMetadataPB pb_; |
215 | | |
216 | | // The on-disk size of the consensus metadata, as of the last call to Load() or Flush(). |
217 | | std::atomic<uint64_t> on_disk_size_; |
218 | | |
219 | | // Active role and term. Stored as a separate atomic field for fast read-only access. This is |
220 | | // still only modified under the lock. |
221 | | std::atomic<PackedRoleAndTerm> role_and_term_cache_; |
222 | | |
223 | | DISALLOW_COPY_AND_ASSIGN(ConsensusMetadata); |
224 | | }; |
225 | | |
226 | | const HostPortPB& DesiredHostPort(const RaftPeerPB& peer, const CloudInfoPB& from); |
227 | | void TakeRegistration(ServerRegistrationPB* source, RaftPeerPB* dest); |
228 | | void CopyRegistration(ServerRegistrationPB source, RaftPeerPB* dest); |
229 | | |
230 | | } // namespace consensus |
231 | | } // namespace yb |
232 | | |
233 | | #endif // YB_CONSENSUS_CONSENSUS_META_H_ |