summaryrefslogtreecommitdiff
path: root/ovsdb/raft-private.h
blob: 48c6df511f3fdf5277fe8c93393c6ed6854d19eb (plain)
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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/*
 * Copyright (c) 2017, 2018 Nicira, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef RAFT_PRIVATE_H
#define RAFT_PRIVATE_H 1

/* Data structures for use internally within the Raft implementation. */

#include "raft.h"
#include <stdint.h>
#include "openvswitch/hmap.h"
#include "openvswitch/uuid.h"
#include "sset.h"

struct ds;
struct ovsdb_parser;
struct raft_install_snapshot_request;

/* Formatting server IDs and cluster IDs for use in human-readable logs.  Do
 * not use these in cases where the whole server or cluster ID is needed; use
 * UUID_FMT and UUID_ARGS in that case.*/

#define SID_FMT "%04x"
#define SID_ARGS(SID) uuid_prefix(SID, 4)
#define SID_LEN 4

#define CID_FMT "%04x"
#define CID_ARGS(CID) uuid_prefix(CID, 4)
#define CID_LEN 4

struct ovsdb_error *raft_address_validate(const char *address)
    OVS_WARN_UNUSED_RESULT;
struct ovsdb_error *raft_addresses_from_json(const struct json *,
                                             struct sset *addresses)
    OVS_WARN_UNUSED_RESULT;
struct json *raft_addresses_to_json(const struct sset *addresses);

char *raft_address_to_nickname(const char *address, const struct uuid *sid);

enum raft_server_phase {
    RAFT_PHASE_STABLE,          /* Not being changed. */

    /* Phases for servers being added. */
    RAFT_PHASE_CATCHUP,         /* Populating new server's log. */
    RAFT_PHASE_CAUGHT_UP,       /* Waiting for prev configuration to commit. */
    RAFT_PHASE_COMMITTING,      /* Waiting for new configuration to commit. */

    /* Phases for servers to be removed. */
    RAFT_PHASE_REMOVE,          /* To be removed. */
};

const char *raft_server_phase_to_string(enum raft_server_phase);

/* Information about a server in a Raft cluster.
 *
 * Often within struct raft's 'servers' or 'add_servers' hmap. */
struct raft_server {
    struct hmap_node hmap_node; /* Hashed based on 'sid'. */

    struct uuid sid;            /* Unique Server ID. */
    char *address;              /* "(tcp|ssl):1.2.3.4:5678" */
    char *nickname;             /* "1ab3(s3)" */

    /* Volatile state on candidates.  Reinitialized at start of election. */
    struct uuid vote;           /* Server ID of vote, or all-zeros. */

    /* Volatile state on leaders.  Reinitialized after election. */
    uint64_t next_index;     /* Index of next log entry to send this server. */
    uint64_t match_index;    /* Index of max log entry server known to have. */
    enum raft_server_phase phase;
    bool replied;            /* Reply to append_request was received from this
                                node during current election_timeout interval.
                                */
    /* install_snapshot_request has been sent, but there is no response yet. */
    bool install_snapshot_request_in_progress;

    /* For use in adding and removing servers: */
    struct uuid requester_sid;  /* Nonzero if requested via RPC. */
    struct unixctl_conn *requester_conn; /* Only if requested via unixctl. */

    long long int last_msg_ts; /* Last received msg timestamp in ms. */
};

void raft_server_destroy(struct raft_server *);
void raft_servers_destroy(struct hmap *servers);
struct raft_server *raft_server_add(struct hmap *servers,
                                    const struct uuid *sid,
                                    const char *address);
struct raft_server *raft_server_find(const struct hmap *servers,
                                     const struct uuid *sid);
const char *raft_servers_get_nickname__(const struct hmap *servers,
                                        const struct uuid *sid);
const char *raft_servers_get_nickname(const struct hmap *servers,
                                      const struct uuid *sid,
                                      char buf[SID_LEN + 1], size_t bufsize);
struct ovsdb_error *raft_servers_from_json(const struct json *,
                                           struct hmap *servers)
    OVS_WARN_UNUSED_RESULT;
struct ovsdb_error *raft_servers_validate_json(const struct json *);
    OVS_WARN_UNUSED_RESULT
struct json *raft_servers_to_json(const struct hmap *servers);
void raft_servers_format(const struct hmap *servers, struct ds *ds);

/* A raft_entry is an in-memory data structure that represents a Raft log
 * entry.  */
struct raft_entry {
    uint64_t term;
    struct {
        struct json *full_json;   /* Fully parsed JSON object. */
        struct json *serialized;  /* JSON_SERIALIZED_OBJECT version of data. */
    } data;
    struct uuid eid;
    struct json *servers;
    uint64_t election_timer;
};

void raft_entry_clone(struct raft_entry *, const struct raft_entry *);
void raft_entry_uninit(struct raft_entry *);
struct json *raft_entry_to_json(const struct raft_entry *);
struct ovsdb_error *raft_entry_from_json(struct json *, struct raft_entry *)
    OVS_WARN_UNUSED_RESULT;
bool raft_entry_equals(const struct raft_entry *, const struct raft_entry *);
bool raft_entry_has_data(const struct raft_entry *);
void raft_entry_set_parsed_data(struct raft_entry *, const struct json *);
void raft_entry_set_parsed_data_nocopy(struct raft_entry *, struct json *);
struct json *raft_entry_steal_parsed_data(struct raft_entry *)
    OVS_WARN_UNUSED_RESULT;
const struct json *raft_entry_get_parsed_data(const struct raft_entry *);
const struct json *raft_entry_get_serialized_data(const struct raft_entry *);

/* On disk data serialization and deserialization. */

/* First record in a Raft log. */
struct raft_header {
    /* All servers. */
    struct uuid sid;            /* Server ID. */
    struct uuid cid;            /* Cluster ID.  May be zero if 'joining'. */
    char *name;                 /* Database name. */
    char *local_address;        /* Address for Raft server to listen. */
    bool joining;               /* True iff cluster not joined yet. */

    /* Only for servers that haven't joined the cluster yet. */
    struct sset remote_addresses; /* Address of other Raft servers. */

    /* Only for servers that have joined the cluster. */
    uint64_t snap_index;        /* Snapshot's index. */
    struct raft_entry snap;     /* Snapshot. */
};

void raft_header_uninit(struct raft_header *);
struct ovsdb_error *raft_header_from_json(struct raft_header *,
                                          const struct json *)
    OVS_WARN_UNUSED_RESULT;
struct json *raft_header_to_json(const struct raft_header *);

enum raft_record_type {
    /* Record types that match those in the Raft specification. */
    RAFT_REC_ENTRY,             /* A log entry. */
    RAFT_REC_TERM,              /* A new term. */
    RAFT_REC_VOTE,              /* A vote. */

    /* Extensions. */
    RAFT_REC_NOTE,              /* A note about some significant event. */
    RAFT_REC_COMMIT_INDEX,      /* An update to the local commit_index. */
    RAFT_REC_LEADER,            /* A server has become leader for this term. */
};

/* Type used for the second and subsequent records in a Raft log. */
struct raft_record {
    enum raft_record_type type;
    char *comment;

    /* Valid in RAFT_REC_ENTRY, RAFT_REC_TERM, RAFT_REC_LEADER, and
     * RAFT_REC_VOTE, and otherwise 0. */
    uint64_t term;

    union {
        char *note;             /* RAFT_REC_NOTE. */

        uint64_t commit_index;  /* RAFT_REC_COMMIT_INDEX. */

        struct uuid sid;        /* RAFT_REC_VOTE, RAFT_REC_LEADER. */

        struct {                /* RAFT_REC_ENTRY. */
            uint64_t index;
            struct json *data;
            struct json *servers;
            uint64_t election_timer;
            struct uuid eid;
        } entry;
    };
};

void raft_record_uninit(struct raft_record *);
struct ovsdb_error *raft_record_from_json(struct raft_record *,
                                          const struct json *)
    OVS_WARN_UNUSED_RESULT;
struct json *raft_record_to_json(const struct raft_record *);

void raft_put_uint64(struct json *object, const char *name, uint64_t integer);
uint64_t raft_parse_optional_uint64(struct ovsdb_parser *, const char *name);
uint64_t raft_parse_required_uint64(struct ovsdb_parser *, const char *name);

bool raft_parse_required_boolean(struct ovsdb_parser *, const char *name);
int raft_parse_optional_boolean(struct ovsdb_parser *, const char *name);
const char *raft_parse_required_string(struct ovsdb_parser *,
                                           const char *name);
const char *raft_parse_optional_string(struct ovsdb_parser *,
                                           const char *name);
bool raft_parse_uuid(struct ovsdb_parser *, const char *name, bool optional,
                     struct uuid *);
struct uuid raft_parse_required_uuid(struct ovsdb_parser *, const char *name);
bool raft_parse_optional_uuid(struct ovsdb_parser *, const char *name,
                         struct uuid *);

#endif /* raft-private.h */