]>
Commit | Line | Data |
---|---|---|
1b1d2e6d BP |
1 | /* |
2 | * Copyright (c) 2017, 2018 Nicira, Inc. | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | ||
17 | #ifndef RAFT_RPC_H | |
18 | #define RAFT_RPC_H 1 | |
19 | ||
20 | /* Data structures used internally by Raft implementation for JSON-RPC. */ | |
21 | ||
22 | #include <stdbool.h> | |
23 | #include <stdint.h> | |
24 | #include "openvswitch/uuid.h" | |
25 | #include "raft.h" | |
26 | #include "raft-private.h" | |
27 | #include "sset.h" | |
28 | ||
29 | struct ds; | |
30 | ||
31 | #define RAFT_RPC_TYPES \ | |
32 | /* Hello RPC. */ \ | |
33 | RAFT_RPC(RAFT_RPC_HELLO_REQUEST, hello_request) \ | |
34 | \ | |
35 | /* AppendEntries RPC. */ \ | |
36 | RAFT_RPC(RAFT_RPC_APPEND_REQUEST, append_request) \ | |
37 | RAFT_RPC(RAFT_RPC_APPEND_REPLY, append_reply) \ | |
38 | \ | |
39 | /* RequestVote RPC. */ \ | |
40 | RAFT_RPC(RAFT_RPC_VOTE_REQUEST, vote_request) \ | |
41 | RAFT_RPC(RAFT_RPC_VOTE_REPLY, vote_reply) \ | |
42 | \ | |
43 | /* AddServer RPC. */ \ | |
44 | RAFT_RPC(RAFT_RPC_ADD_SERVER_REQUEST, add_server_request) \ | |
45 | RAFT_RPC(RAFT_RPC_ADD_SERVER_REPLY, add_server_reply) \ | |
46 | \ | |
47 | /* RemoveServer RPC. */ \ | |
48 | RAFT_RPC(RAFT_RPC_REMOVE_SERVER_REQUEST, remove_server_request) \ | |
49 | RAFT_RPC(RAFT_RPC_REMOVE_SERVER_REPLY, remove_server_reply) \ | |
50 | \ | |
51 | /* InstallSnapshot RPC. */ \ | |
52 | RAFT_RPC(RAFT_RPC_INSTALL_SNAPSHOT_REQUEST, install_snapshot_request) \ | |
53 | RAFT_RPC(RAFT_RPC_INSTALL_SNAPSHOT_REPLY, install_snapshot_reply) \ | |
54 | \ | |
55 | /* BecomeLeader RPC. */ \ | |
56 | RAFT_RPC(RAFT_RPC_BECOME_LEADER, become_leader) \ | |
57 | \ | |
58 | /* ExecuteCommand RPC. */ \ | |
59 | RAFT_RPC(RAFT_RPC_EXECUTE_COMMAND_REQUEST, execute_command_request) \ | |
60 | RAFT_RPC(RAFT_RPC_EXECUTE_COMMAND_REPLY, execute_command_reply) | |
61 | ||
62 | enum raft_rpc_type { | |
63 | #define RAFT_RPC(ENUM, NAME) ENUM, | |
64 | RAFT_RPC_TYPES | |
65 | #undef RAFT_RPC | |
66 | }; | |
67 | ||
68 | const char *raft_rpc_type_to_string(enum raft_rpc_type); | |
69 | bool raft_rpc_type_from_string(const char *, enum raft_rpc_type *); | |
70 | \f | |
71 | struct raft_rpc_common { | |
72 | enum raft_rpc_type type; /* Message type. */ | |
73 | struct uuid sid; /* Peer server (source or destination). */ | |
74 | char *comment; /* Human-friendly additional text. */ | |
75 | }; | |
76 | ||
77 | struct raft_hello_request { | |
78 | struct raft_rpc_common common; | |
79 | char *address; /* Sender's address. */ | |
80 | }; | |
81 | ||
82 | struct raft_append_request { | |
83 | struct raft_rpc_common common; | |
84 | uint64_t term; /* Leader's term. */ | |
85 | uint64_t prev_log_index; /* Log entry just before new ones. */ | |
86 | uint64_t prev_log_term; /* Term of prev_log_index entry. */ | |
87 | uint64_t leader_commit; /* Leader's commit_index. */ | |
88 | ||
89 | /* The append request includes 0 or more log entries. entries[0] is for | |
90 | * log entry 'prev_log_index + 1', and so on. | |
91 | * | |
92 | * A heartbeat append_request has no terms. */ | |
93 | struct raft_entry *entries; | |
94 | unsigned int n_entries; | |
95 | }; | |
96 | ||
97 | enum raft_append_result { | |
98 | RAFT_APPEND_OK, /* Success. */ | |
99 | RAFT_APPEND_INCONSISTENCY, /* Failure due to log inconsistency. */ | |
100 | RAFT_APPEND_IO_ERROR, /* Failure due to I/O error. */ | |
101 | }; | |
102 | ||
103 | const char *raft_append_result_to_string(enum raft_append_result); | |
104 | bool raft_append_result_from_string(const char *, enum raft_append_result *); | |
105 | ||
106 | struct raft_append_reply { | |
107 | struct raft_rpc_common common; | |
108 | ||
109 | /* Copied from the state machine of the reply's sender. */ | |
110 | uint64_t term; /* Current term, for leader to update itself. */ | |
111 | uint64_t log_end; /* To allow capping next_index, see 4.2.1. */ | |
112 | ||
113 | /* Copied from request. */ | |
114 | uint64_t prev_log_index; /* Log entry just before new ones. */ | |
115 | uint64_t prev_log_term; /* Term of prev_log_index entry. */ | |
116 | unsigned int n_entries; | |
117 | ||
118 | /* Result. */ | |
119 | enum raft_append_result result; | |
120 | }; | |
121 | ||
122 | struct raft_vote_request { | |
123 | struct raft_rpc_common common; | |
124 | uint64_t term; /* Candidate's term. */ | |
125 | uint64_t last_log_index; /* Index of candidate's last log entry. */ | |
126 | uint64_t last_log_term; /* Term of candidate's last log entry. */ | |
127 | bool leadership_transfer; /* True to override minimum election timeout. */ | |
128 | }; | |
129 | ||
130 | struct raft_vote_reply { | |
131 | struct raft_rpc_common common; | |
132 | uint64_t term; /* Current term, for candidate to update itself. */ | |
133 | struct uuid vote; /* Server ID of vote. */ | |
134 | }; | |
135 | ||
136 | struct raft_add_server_request { | |
137 | struct raft_rpc_common common; | |
138 | char *address; /* Address of new server. */ | |
139 | }; | |
140 | ||
141 | struct raft_remove_server_request { | |
142 | struct raft_rpc_common common; | |
143 | struct uuid sid; /* Server to remove. */ | |
144 | ||
145 | /* Nonnull if request was received via unixctl. */ | |
146 | struct unixctl_conn *requester_conn; | |
147 | }; | |
148 | ||
149 | /* The operation committed and is now complete. */ | |
150 | #define RAFT_SERVER_COMPLETED "completed" | |
151 | ||
152 | /* The operation could not be initiated because this server is not the current | |
153 | * leader. Only the leader can add or remove servers. */ | |
154 | #define RAFT_SERVER_NOT_LEADER "not leader" | |
155 | ||
156 | /* An operation to add a server succeeded without any change because the server | |
157 | * was already part of the cluster. */ | |
158 | #define RAFT_SERVER_ALREADY_PRESENT "already in cluster" | |
159 | ||
160 | /* An operation to remove a server succeeded without any change because the | |
161 | * server was not part of the cluster. */ | |
162 | #define RAFT_SERVER_ALREADY_GONE "already not in cluster" | |
163 | ||
164 | /* The operation could not be initiated because an identical | |
165 | * operation was already in progress. */ | |
166 | #define RAFT_SERVER_IN_PROGRESS "in progress" | |
167 | ||
168 | /* Adding a server failed because of a timeout. This could mean that the | |
169 | * server was entirely unreachable, or that it became unreachable partway | |
170 | * through populating it with an initial copy of the log. In the latter case, | |
171 | * retrying the operation should resume where it left off. */ | |
172 | #define RAFT_SERVER_TIMEOUT "timeout" | |
173 | ||
174 | /* The operation was initiated but it later failed because this server lost | |
175 | * cluster leadership. The operation may be retried against the new cluster | |
176 | * leader. For adding a server, if the log was already partially copied to the | |
177 | * new server, retrying the operation should resume where it left off. */ | |
178 | #define RAFT_SERVER_LOST_LEADERSHIP "lost leadership" | |
179 | ||
180 | /* Adding a server was canceled by submission of an operation to remove the | |
181 | * same server, or removing a server was canceled by submission of an operation | |
182 | * to add the same server. */ | |
183 | #define RAFT_SERVER_CANCELED "canceled" | |
184 | ||
185 | /* Adding or removing a server could not be initiated because the operation to | |
186 | * remove or add the server, respectively, has been logged but not committed. | |
187 | * The new operation may be retried once the former operation commits. */ | |
188 | #define RAFT_SERVER_COMMITTING "committing" | |
189 | ||
190 | /* Adding or removing a server was canceled because the leader shut down. */ | |
191 | #define RAFT_SERVER_SHUTDOWN "shutdown" | |
192 | ||
193 | /* Removing a server could not be initiated because, taken together with any | |
194 | * other scheduled server removals, the cluster would be empty. (This | |
195 | * calculation ignores scheduled or uncommitted add server operations because | |
196 | * of the possibility that they could fail.) */ | |
197 | #define RAFT_SERVER_EMPTY "empty" | |
198 | ||
199 | struct raft_add_server_reply { | |
200 | struct raft_rpc_common common; | |
201 | bool success; | |
202 | struct sset remote_addresses; | |
203 | }; | |
204 | ||
205 | struct raft_remove_server_reply { | |
206 | struct raft_rpc_common common; | |
207 | bool success; | |
17bd4149 BP |
208 | |
209 | /* SID of the removed server, but all-zeros if it is the same as the | |
210 | * destination of the RPC. (Older ovsdb-server did not have 'target_sid' | |
211 | * and assumed that the destination was always the target, so by omitting | |
212 | * 'target_sid' when this is the case we can preserve a small amount of | |
213 | * inter-version compatibility.) */ | |
214 | struct uuid target_sid; | |
1b1d2e6d BP |
215 | }; |
216 | ||
217 | struct raft_install_snapshot_request { | |
218 | struct raft_rpc_common common; | |
219 | ||
220 | uint64_t term; /* Leader's term. */ | |
221 | ||
222 | uint64_t last_index; /* Covers everything up & including this. */ | |
223 | uint64_t last_term; /* Term of last_index. */ | |
224 | struct uuid last_eid; /* Last entry ID. */ | |
225 | struct json *last_servers; | |
8e354614 | 226 | uint64_t election_timer; |
1b1d2e6d BP |
227 | |
228 | /* Data. */ | |
229 | struct json *data; | |
230 | }; | |
231 | ||
232 | struct raft_install_snapshot_reply { | |
233 | struct raft_rpc_common common; | |
234 | ||
235 | uint64_t term; /* For leader to update itself. */ | |
236 | ||
237 | /* Repeated from the install_snapshot request. */ | |
238 | uint64_t last_index; | |
239 | uint64_t last_term; | |
240 | }; | |
241 | ||
242 | struct raft_become_leader { | |
243 | struct raft_rpc_common common; | |
244 | ||
245 | uint64_t term; /* Leader's term. */ | |
246 | }; | |
247 | ||
248 | struct raft_execute_command_request { | |
249 | struct raft_rpc_common common; | |
250 | ||
251 | struct json *data; | |
252 | struct uuid prereq; | |
253 | struct uuid result; | |
254 | }; | |
255 | ||
256 | struct raft_execute_command_reply { | |
257 | struct raft_rpc_common common; | |
258 | ||
259 | struct uuid result; | |
260 | enum raft_command_status status; | |
261 | uint64_t commit_index; | |
262 | }; | |
263 | ||
264 | union raft_rpc { | |
265 | enum raft_rpc_type type; | |
266 | struct raft_rpc_common common; | |
267 | #define RAFT_RPC(ENUM, NAME) struct raft_##NAME NAME; | |
268 | RAFT_RPC_TYPES | |
269 | #undef RAFT_RPC | |
270 | }; | |
271 | ||
272 | #define RAFT_RPC(ENUM, NAME) \ | |
273 | static inline const struct raft_##NAME * \ | |
274 | raft_##NAME##_cast(const union raft_rpc *rpc) \ | |
275 | { \ | |
276 | ovs_assert(rpc->type == ENUM); \ | |
277 | return &rpc->NAME; \ | |
278 | } | |
279 | RAFT_RPC_TYPES | |
280 | #undef RAFT_RPC | |
281 | ||
282 | void raft_rpc_uninit(union raft_rpc *); | |
283 | union raft_rpc *raft_rpc_clone(const union raft_rpc *); | |
284 | ||
285 | struct jsonrpc_msg *raft_rpc_to_jsonrpc(const struct uuid *cid, | |
286 | const struct uuid *sid, | |
287 | const union raft_rpc *); | |
288 | struct ovsdb_error *raft_rpc_from_jsonrpc(struct uuid *cid, | |
289 | const struct uuid *sid, | |
290 | const struct jsonrpc_msg *, | |
291 | union raft_rpc *) | |
292 | OVS_WARN_UNUSED_RESULT; | |
293 | ||
294 | void raft_rpc_format(const union raft_rpc *, struct ds *); | |
295 | ||
296 | uint64_t raft_rpc_get_term(const union raft_rpc *); | |
297 | const struct uuid *raft_rpc_get_vote(const union raft_rpc *); | |
298 | uint64_t raft_rpc_get_min_sync_index(const union raft_rpc *); | |
299 | ||
300 | #endif /* lib/raft-rpc.h */ |