2014-01-17 23:30:19 +04:00
|
|
|
/* v/raft.c
|
|
|
|
**
|
|
|
|
** This file is in the public domain.
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <uv.h>
|
|
|
|
|
|
|
|
#include "all.h"
|
|
|
|
#include "v/vere.h"
|
|
|
|
|
2014-01-18 00:13:46 +04:00
|
|
|
|
|
|
|
/* _raft_election_rand(): pseudorandom component of election timeout.
|
|
|
|
*/
|
|
|
|
static c3_w
|
|
|
|
_raft_election_rand()
|
|
|
|
{
|
|
|
|
return ((float) rand() / RAND_MAX) * 150;
|
|
|
|
}
|
|
|
|
|
2014-01-17 23:30:19 +04:00
|
|
|
/* _raft_readname(): parse a raft host:port peer name.
|
|
|
|
*/
|
2014-01-18 00:13:46 +04:00
|
|
|
static u2_bean
|
2014-01-17 23:30:19 +04:00
|
|
|
_raft_readname(u2_ropt* rop_u, const c3_c* str_c, c3_w siz_w)
|
|
|
|
{
|
|
|
|
u2_rnam* nam_u = malloc(sizeof(*nam_u));
|
|
|
|
c3_c* col_c;
|
|
|
|
c3_w por_w;
|
|
|
|
c3_w nam_w;
|
|
|
|
|
|
|
|
nam_u->str_c = malloc(siz_w + 1);
|
|
|
|
strncpy(nam_u->str_c, str_c, siz_w);
|
|
|
|
nam_u->str_c[siz_w] = '\0';
|
|
|
|
//fprintf(stderr, "raft: peer %s\n", nam_u->str_c);
|
|
|
|
|
|
|
|
if ( 0 == (col_c = strchr(nam_u->str_c, ':')) ) {
|
|
|
|
fprintf(stderr, "raft: invalid name %s\n", str_c);
|
|
|
|
return u2_no;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nam_w = col_c - nam_u->str_c;
|
|
|
|
nam_u->nam_c = malloc(nam_w + 1);
|
|
|
|
strncpy(nam_u->nam_c, nam_u->str_c, nam_w);
|
|
|
|
nam_u->nam_c[nam_w] = '\0';
|
|
|
|
|
|
|
|
por_w = atol(col_c + 1);
|
|
|
|
if ( !(por_w > 0 && por_w < 65536) ) {
|
|
|
|
fprintf(stderr, "raft: invalid port '%s'\n", col_c + 1);
|
|
|
|
return u2_no;
|
|
|
|
}
|
|
|
|
else nam_u->por_s = por_w;
|
|
|
|
//fprintf(stderr, "raft: peer %s:%d\n", nam_u->nam_c, nam_u->por_s);
|
|
|
|
|
|
|
|
nam_u->nex_u = rop_u->nam_u;
|
|
|
|
rop_u->nam_u = nam_u;
|
|
|
|
return u2_yes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u2_bean
|
|
|
|
u2_raft_readopt(u2_ropt* rop_u, const c3_c* arg_c)
|
|
|
|
{
|
|
|
|
c3_c* com_c;
|
|
|
|
|
|
|
|
while ( 0 != (com_c = strchr(arg_c, ',')) ) {
|
|
|
|
if ( u2_no == _raft_readname(rop_u, arg_c, com_c - arg_c) ) {
|
|
|
|
return u2_no;
|
|
|
|
} else arg_c = com_c + 1;
|
|
|
|
}
|
|
|
|
return _raft_readname(rop_u, arg_c, strlen(arg_c));
|
|
|
|
}
|
2014-01-18 00:13:46 +04:00
|
|
|
|
|
|
|
static void
|
|
|
|
_raft_listen_cb(uv_stream_t* wax_u, c3_i sas_i)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_raft_time_cb(uv_timer_t* tim_u, c3_i sas_i)
|
|
|
|
{
|
|
|
|
u2_raft* raf_u = tim_u->data;
|
|
|
|
//uL(fprintf(uH, "raft: time\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* _raft_foll_init(): begin, follower mode.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_raft_foll_init(u2_raft* raf_u)
|
|
|
|
{
|
|
|
|
uL(fprintf(uH, "raft: starting follower\n"));
|
|
|
|
|
|
|
|
if ( 0 != uv_tcp_init(u2L, &raf_u->wax_u) ) {
|
|
|
|
uL(fprintf(uH, "raft: init: %s\n", uv_strerror(uv_last_error(u2L))));
|
|
|
|
c3_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bind the listener.
|
|
|
|
{
|
|
|
|
struct sockaddr_in add_u;
|
|
|
|
|
|
|
|
memset(&add_u, 0, sizeof(add_u));
|
|
|
|
add_u.sin_family = AF_INET;
|
|
|
|
add_u.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
add_u.sin_port = htons(u2_Host.ops_u.rop_u.por_s);
|
|
|
|
|
|
|
|
if ( 0 != uv_tcp_bind(&raf_u->wax_u, add_u) ) {
|
|
|
|
uL(fprintf(uH, "raft: bind: %s\n", uv_strerror(uv_last_error(u2L))));
|
|
|
|
c3_assert(0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ( 0 != uv_listen((uv_stream_t*)&raf_u->wax_u, 16, _raft_listen_cb) ) {
|
|
|
|
uL(fprintf(uH, "raft: listen: %s\n", uv_strerror(uv_last_error(u2L))));
|
|
|
|
c3_assert(0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
uL(fprintf(uH, "raft: on TCP %d\n", u2_Host.ops_u.rop_u.por_s));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start the initial election timeout.
|
|
|
|
{
|
|
|
|
uv_timer_init(u2L, &raf_u->tim_u);
|
|
|
|
raf_u->tim_u.data = raf_u;
|
|
|
|
uv_timer_start(&raf_u->tim_u, _raft_time_cb, _raft_election_rand(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* _raft_lone_init(): begin, single-instance mode.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_raft_lone_init(u2_raft* raf_u)
|
|
|
|
{
|
|
|
|
uL(fprintf(uH, "raft: single-instance mode\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
u2_raft_io_init()
|
|
|
|
{
|
2014-02-11 06:04:50 +04:00
|
|
|
u2_raft* raf_u = u2R;
|
2014-01-18 00:13:46 +04:00
|
|
|
|
|
|
|
if ( 0 == u2_Host.ops_u.rop_u.por_s ) {
|
|
|
|
_raft_lone_init(raf_u);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_raft_foll_init(raf_u);
|
|
|
|
}
|
|
|
|
}
|
2014-02-11 06:04:50 +04:00
|
|
|
|
|
|
|
c3_w
|
|
|
|
u2_raft_push(u2_raft* raf_u, c3_w* bob_w, c3_w len_w)
|
|
|
|
{
|
|
|
|
uL(fprintf(uH, "raft: pushing\n"));
|
|
|
|
return 0;
|
|
|
|
}
|