* ``connection_user_data`` is a pointer to user data.
* ``connection_user_data`` is a pointer to user data.
* ``peer_is_self`` is boolean indicating that this is the current server's server index.
* ``peer_is_self`` is boolean indicating that this is the current server's server index.
* ``node_id`` is the unique integer ID of the node. Peers use this to identify themselves.
.. [#] AKA "Raft peer"
.. [#] AKA "Raft peer"
.. [#] We have to also include the Raft server itself in the raft_add_node calls. When we call raft_add_node for the Raft server, we set peer_is_self to 1.
.. [#] We have to also include the Raft server itself in the raft_add_node calls. When we call raft_add_node for the Raft server, we set peer_is_self to 1.
...
@@ -98,7 +99,7 @@ We call ``raft_recv_entry`` when we want to append the entry to the log.
...
@@ -98,7 +99,7 @@ We call ``raft_recv_entry`` when we want to append the entry to the log.
.. code-block:: c
.. code-block:: c
msg_entry_response_t response;
msg_entry_response_t response;
e = raft_recv_entry(raft, node_idx, &entry, &response);
e = raft_recv_entry(raft, &entry, &response);
You should populate the ``entry`` struct with the log entry the client has sent. After the call completes the ``response`` parameter is populated and can be used by the ``raft_msg_entry_response_committed`` function to check if the log entry has been committed or not.
You should populate the ``entry`` struct with the log entry the client has sent. After the call completes the ``response`` parameter is populated and can be used by the ``raft_msg_entry_response_committed`` function to check if the log entry has been committed or not.
...
@@ -114,7 +115,7 @@ The ``raft_recv_entry`` function does not block! This means you will need to imp
...
@@ -114,7 +115,7 @@ The ``raft_recv_entry`` function does not block! This means you will need to imp
msg_entry_response_t response;
msg_entry_response_t response;
e = raft_recv_entry(sv->raft, sv->node_idx, &entry, &response);
e = raft_recv_entry(sv->raft, &entry, &response);
if (0 != e)
if (0 != e)
return h2oh_respond_with_error(req, 500, "BAD");
return h2oh_respond_with_error(req, 500, "BAD");
...
@@ -142,14 +143,14 @@ The ``raft_recv_entry`` function does not block! This means you will need to imp
...
@@ -142,14 +143,14 @@ The ``raft_recv_entry`` function does not block! This means you will need to imp
.. code-block:: c
.. code-block:: c
e = raft_recv_appendentries_response(sv->raft, conn->node_idx, &m.aer);
e = raft_recv_appendentries_response(sv->raft, conn->node, &m.aer);
uv_cond_signal(&sv->appendentries_received);
uv_cond_signal(&sv->appendentries_received);
**Redirecting the client to the leader**
**Redirecting the client to the leader**
When we receive an entry log from the client it's possible we might not be a leader.
When we receive an entry log from the client it's possible we might not be a leader.
If we aren't currently the leader of the raft cluster, we MUST send a redirect error message to the client. This is so that the client can connect directly to the leader in future connections. This enables future requests to be faster until the leader changes.
If we aren't currently the leader of the raft cluster, we MUST send a redirect error message to the client. This is so that the client can connect directly to the leader in future connections. This enables future requests to be faster (ie. no redirects are required after the first redirect until the leader changes).
We use the ``raft_get_current_leader`` function to check who is the current leader.
We use the ``raft_get_current_leader`` function to check who is the current leader.
...
@@ -158,16 +159,15 @@ We use the ``raft_get_current_leader`` function to check who is the current lead
...
@@ -158,16 +159,15 @@ We use the ``raft_get_current_leader`` function to check who is the current lead
@@ -247,7 +246,7 @@ For this callback we have to serialize a ``msg_requestvote_t`` struct, and then
...
@@ -247,7 +246,7 @@ For this callback we have to serialize a ``msg_requestvote_t`` struct, and then
**send_appendentries()**
**send_appendentries()**
For this callback we have to serialize a ``msg_appendentries_t`` struct, and then send it to the peer identified by ``node_idx``. This struct is more complicated to serialize because the ``m->entries`` array might be populated.
For this callback we have to serialize a ``msg_appendentries_t`` struct, and then send it to the peer identified by ``node``. This struct is more complicated to serialize because the ``m->entries`` array might be populated.
*Example from ticketd showing how the callback is implemented:*
*Example from ticketd showing how the callback is implemented:*
...
@@ -256,13 +255,12 @@ For this callback we have to serialize a ``msg_appendentries_t`` struct, and the
...
@@ -256,13 +255,12 @@ For this callback we have to serialize a ``msg_appendentries_t`` struct, and the