2 * Copyright (c) 2017, 2018 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 /* Data structures used internally by Raft implementation for JSON-RPC. */
24 #include "openvswitch/uuid.h"
26 #include "raft-private.h"
31 #define RAFT_RPC_TYPES \
33 RAFT_RPC(RAFT_RPC_HELLO_REQUEST, hello_request) \
35 /* AppendEntries RPC. */ \
36 RAFT_RPC(RAFT_RPC_APPEND_REQUEST, append_request) \
37 RAFT_RPC(RAFT_RPC_APPEND_REPLY, append_reply) \
39 /* RequestVote RPC. */ \
40 RAFT_RPC(RAFT_RPC_VOTE_REQUEST, vote_request) \
41 RAFT_RPC(RAFT_RPC_VOTE_REPLY, vote_reply) \
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) \
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) \
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) \
55 /* BecomeLeader RPC. */ \
56 RAFT_RPC(RAFT_RPC_BECOME_LEADER, become_leader) \
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)
63 #define RAFT_RPC(ENUM, NAME) ENUM,
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
*);
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. */
77 struct raft_hello_request
{
78 struct raft_rpc_common common
;
79 char *address
; /* Sender's address. */
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. */
89 /* The append request includes 0 or more log entries. entries[0] is for
90 * log entry 'prev_log_index + 1', and so on.
92 * A heartbeat append_request has no terms. */
93 struct raft_entry
*entries
;
94 unsigned int n_entries
;
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. */
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
*);
106 struct raft_append_reply
{
107 struct raft_rpc_common common
;
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. */
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
;
119 enum raft_append_result result
;
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. */
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. */
136 struct raft_add_server_request
{
137 struct raft_rpc_common common
;
138 char *address
; /* Address of new server. */
141 struct raft_remove_server_request
{
142 struct raft_rpc_common common
;
143 struct uuid sid
; /* Server to remove. */
145 /* Nonnull if request was received via unixctl. */
146 struct unixctl_conn
*requester_conn
;
149 /* The operation committed and is now complete. */
150 #define RAFT_SERVER_COMPLETED "completed"
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"
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"
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"
164 /* The operation could not be initiated because an identical
165 * operation was already in progress. */
166 #define RAFT_SERVER_IN_PROGRESS "in progress"
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"
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"
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"
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"
190 /* Adding or removing a server was canceled because the leader shut down. */
191 #define RAFT_SERVER_SHUTDOWN "shutdown"
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"
199 struct raft_add_server_reply
{
200 struct raft_rpc_common common
;
202 struct sset remote_addresses
;
205 struct raft_remove_server_reply
{
206 struct raft_rpc_common common
;
210 struct raft_install_snapshot_request
{
211 struct raft_rpc_common common
;
213 uint64_t term
; /* Leader's term. */
215 uint64_t last_index
; /* Covers everything up & including this. */
216 uint64_t last_term
; /* Term of last_index. */
217 struct uuid last_eid
; /* Last entry ID. */
218 struct json
*last_servers
;
224 struct raft_install_snapshot_reply
{
225 struct raft_rpc_common common
;
227 uint64_t term
; /* For leader to update itself. */
229 /* Repeated from the install_snapshot request. */
234 struct raft_become_leader
{
235 struct raft_rpc_common common
;
237 uint64_t term
; /* Leader's term. */
240 struct raft_execute_command_request
{
241 struct raft_rpc_common common
;
248 struct raft_execute_command_reply
{
249 struct raft_rpc_common common
;
252 enum raft_command_status status
;
253 uint64_t commit_index
;
257 enum raft_rpc_type type
;
258 struct raft_rpc_common common
;
259 #define RAFT_RPC(ENUM, NAME) struct raft_##NAME NAME;
264 #define RAFT_RPC(ENUM, NAME) \
265 static inline const struct raft_##NAME * \
266 raft_##NAME##_cast(const union raft_rpc *rpc) \
268 ovs_assert(rpc->type == ENUM); \
274 void raft_rpc_uninit(union raft_rpc
*);
275 union raft_rpc
*raft_rpc_clone(const union raft_rpc
*);
277 struct jsonrpc_msg
*raft_rpc_to_jsonrpc(const struct uuid
*cid
,
278 const struct uuid
*sid
,
279 const union raft_rpc
*);
280 struct ovsdb_error
*raft_rpc_from_jsonrpc(struct uuid
*cid
,
281 const struct uuid
*sid
,
282 const struct jsonrpc_msg
*,
284 OVS_WARN_UNUSED_RESULT
;
286 void raft_rpc_format(const union raft_rpc
*, struct ds
*);
288 uint64_t raft_rpc_get_term(const union raft_rpc
*);
289 const struct uuid
*raft_rpc_get_vote(const union raft_rpc
*);
290 uint64_t raft_rpc_get_min_sync_index(const union raft_rpc
*);
292 #endif /* lib/raft-rpc.h */