# C-Raft

C-Raft is a fully asynchronous C implementation of the Raft consensus protocol.

## Design

The library has modular design: its core part implements only the core Raft algorithm logic, in a fully platform independent way. On top of that, a pluggable interface defines the I/O implementation for networking and disk persistence.

A stock implementation of the I/O interface is provided when building the library with default options. It is based on libuv and should fit the vast majority of use cases.

## Features

C-Raft implements all the basic features described in the Raft dissertation:

- Leader election

- Log replication

- Log compaction

- Membership changes

It also includes a few optional enhancements:

- Optimistic pipelining to reduce log replication latency

- Writing to leader’s disk in parallel

- Automatic stepping down when the leader loses quorum

- Leadership transfer extension

- Non-voting servers

## Quick start

Make sure that libuv is installed on your system, then run:

    1
    2
    3

    autoreconf -i
    ./configure --enable-example
    make

Then create a `main.c` file with this simple test program that just runs a single raft server and implements a basic state machine for incrementing a counter:

     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

    #include <raft.h>
    #include <raft/uv.h>

    static raft_id id = 12345;
    static const char *address = "127.0.0.1:8080";
    static const char *dir = "/tmp/raft-quick-start";
    static struct uv_loop_s loop;
    static struct raft_uv_transport transport;
    static struct raft_io io;
    static struct raft_fsm fsm;
    static struct raft raft;
    static struct raft_configuration conf;
    static struct uv_timer_s timer;
    static struct raft_apply apply;
    static unsigned counter = 0;
    static uint64_t command;

    static int applyCommand(struct raft_fsm *fsm,
                            const struct raft_buffer *buf,
                            void **result) {
        counter += *(uint64_t *)buf->base;
        printf("counter: %u\n", counter);
        return 0;
    }

    static void submitCommand(uv_timer_t *timer) {
        struct raft_buffer buf;
        command = uv_now(timer->loop) % 10;
        buf.len = sizeof command;
        buf.base = &command;
        raft_apply(&raft, &apply, &buf, 1, NULL);
    }

    int main() {
        mkdir(dir, 0755);
        uv_loop_init(&loop);
        raft_uv_tcp_init(&transport, &loop);
        raft_uv_init(&io, &loop, dir, &transport);
        fsm.apply = applyCommand;
        raft_init(&raft, &io, &fsm, id, address);
        raft_configuration_init(&conf);
        raft_configuration_add(&conf, id, address, RAFT_VOTER);
        raft_bootstrap(&raft, &conf);
        raft_start(&raft);
        uv_timer_init(&loop, &timer);
        uv_timer_start(&timer, submitCommand, 0, 1000);
        uv_run(&loop, UV_RUN_DEFAULT);
    }

You can compile and run it with:

    1

    cc main.c -o main -lraft -luv && ./main

## Licence

This raft C library is released under a slightly modified version of LGPLv3, that includes a copiright exception letting users to statically link the library code in their project and release the final work under their own terms. See the full license text.

### toc

- C-Raft
- Getting started
- API reference