-
Notifications
You must be signed in to change notification settings - Fork 1
/
raft_if.h
195 lines (152 loc) · 5.28 KB
/
raft_if.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#ifndef RAFT_C_IF_H
#define RAFT_C_IF_H
/*
* libraft, C interface to Hashicorp's Raft implementation.
* Copyright (C) 2015 Clayton Wheeler
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
/** @file
* C interface to Raft consensus system.
*
* This wraps Hashicorp's Go implementation of Raft. It runs the Raft
* code in a child process, using shared memory to for communication.
*
* To use Raft, a program must call raft_apply() to send commands to
* Raft, and implement a finite state machine to be driven by the
* functions defined in the RaftFSM struct.
*
* raft_init() starts the Raft process and registers the FSM code.
*
* \sa http://en.wikipedia.org/wiki/Consensus_(computer_science)
* \sa https://github.com/hashicorp/raft
* \sa https://ramcloud.stanford.edu/wiki/download/attachments/11370504/raft.pdf
*/
#include <stdbool.h>
#include <stdint.h>
#include "raft_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* See raft_defs.h for struct definitions.
*/
typedef struct raft_fsm RaftFSM;
typedef void* raft_future;
// Top half; client side
pid_t raft_init(RaftFSM *fsm, const RaftConfig *cfg);
void raft_default_config(RaftConfig *cfg);
void raft_cleanup();
// getopt_long support for Raft options
const struct option* raft_getopt_long_opts();
bool is_raft_option(int optval);
int raft_apply_option(RaftConfig *cfg, int option, const char* arg);
bool raft_is_leader();
/**
* Apply a command to the Raft FSM, blocking until it completes.
*
* @param cmd Opaque command buffer, allocated with alloc_raft_buffer().
* @param cmd_len Length of the command (may be smaller than the buffer
* itself).
* @param timeout_ns Timeout in nanoseconds to wait for Raft.
* @param res [out] Location to store result pointer.
* @retval error Error from Raft; 0 on success.
*/
RaftError raft_apply_sync(char* cmd, size_t cmd_len, uint64_t timeout_ns,
void **res);
raft_future raft_apply(char* cmd, size_t cmd_len, uint64_t timeout_ns);
raft_future raft_barrier(uint64_t timeout_ns);
raft_future raft_verify_leader();
/**
* Return the state Raft is currently in.
*
* Synchronous.
*
* @retval State, or 0 (RAFT_INVALID_STATE) on error.
*/
RaftState raft_state();
/**
* Return the time of last contact by a leader.
*
* This only makes sense if we are currently a follower. Synchronous.
*
* @retval Time of last contact; 0 on error.
*/
time_t raft_last_contact();
/**
* Return the last index in stable storage.
*
* This is either from the last log or from the last
* snapshot. Synchronous.
*
* @retval Index, or 0 on error.
*/
RaftIndex raft_last_index();
/**
* Return the current leader of the cluster.
*
* @param [out] buf A pointer to a C string containing the leader's
* address will be placed in the destination of buf. The caller is
* responsible for freeing this string via free_raft_buffer().
*
* @retval RAFT_SUCCESS on success. RAFT_E_UNKNOWN_PEER if there is no
* current leader or the leader is unknown.
*/
RaftError raft_leader(char** buf);
raft_future raft_snapshot();
raft_future raft_add_peer(const char *host, uint16_t port);
raft_future raft_remove_peer(const char *host, uint16_t port);
raft_future raft_stats();
raft_future raft_shutdown();
RaftError raft_future_wait(raft_future f);
bool raft_future_poll(raft_future f);
bool raft_future_wait_for(raft_future f, uint64_t wait_ms);
RaftError raft_future_get_fsm_reply(raft_future f, void** value_ptr);
RaftError raft_future_get_stats(raft_future f, const char** value_ptr);
void raft_print_stats(const char *stats);
/**
* Dispose of resources held by a raft_future.
*/
void raft_future_dispose(raft_future f);
// Bottom half; FSM side
typedef void* raft_snapshot_req;
// AKA RaftFSM
struct raft_fsm {
void* (*apply)(uint64_t index, uint64_t term, RaftLogType type,
char *cmd, size_t len);
void (*begin_snapshot)(const char *path, raft_snapshot_req s);
int (*restore)(const char *path);
};
void raft_fsm_snapshot_complete(raft_snapshot_req s, bool success);
// Optional snapshot support
typedef void* raft_fsm_snapshot_handle;
/**
* Callback function for writing a snapshot from the state handle.
*
* Must not close the supplied sink.
*/
typedef int (*raft_fsm_snapshot_func)(raft_fsm_snapshot_handle handle, FILE* sink);
void raft_fsm_take_snapshot(raft_snapshot_req req,
raft_fsm_snapshot_handle h,
raft_fsm_snapshot_func f);
char* alloc_raft_buffer(size_t len);
void free_raft_buffer(const char* buf);
const char* raft_err_msg(RaftError err);
#ifdef __cplusplus
}
#endif
#endif /* RAFT_C_IF_H */