]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: peers: support of any stick-table data-types for sync
authorEmeric Brun <ebrun@haproxy.com>
Thu, 11 Jun 2015 16:25:54 +0000 (18:25 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 16 Jun 2015 14:11:59 +0000 (16:11 +0200)
It is possible to propagate entries of any data-types in stick-tables between
several haproxy instances over TCP connections in a multi-master fashion. Each
instance pushes its local updates and insertions to remote peers. The pushed
values overwrite remote ones without aggregation. Interrupted exchanges are
automatically detected and recovered from the last known point.

doc/configuration.txt
src/peers.c

index 4b28383228169b7793a24d9213145a4f1a97ff9f..f22ee152f92f8c38ee3008b21d6e2cd24fabb76e 100644 (file)
@@ -1381,17 +1381,18 @@ user <username> [password|insecure-password <password>]
 
 3.5. Peers
 ----------
-It is possible to synchronize server entries in stick tables between several
-haproxy instances over TCP connections in a multi-master fashion. Each instance
-pushes its local updates and insertions to remote peers. Server IDs are used to
-identify servers remotely, so it is important that configurations look similar
-or at least that the same IDs are forced on each server on all participants.
-Interrupted exchanges are automatically detected and recovered from the last
-known point. In addition, during a soft restart, the old process connects to
-the new one using such a TCP connection to push all its entries before the new
-process tries to connect to other peers. That ensures very fast replication
-during a reload, it typically takes a fraction of a second even for large
-tables.
+It is possible to propagate entries of any data-types in stick-tables between
+several haproxy instances over TCP connections in a multi-master fashion. Each
+instance pushes its local updates and insertions to remote peers. The pushed
+values overwrite remote ones without aggregation. Interrupted exchanges are
+automatically detected and recovered from the last known point.
+In addition, during a soft restart, the old process connects to the new one
+using such a TCP connection to push all its entries before the new process
+tries to connect to other peers. That ensures very fast replication during a
+reload, it typically takes a fraction of a second even for large tables.
+Note that Server IDs are used to identify servers remotely, so it is important
+that configurations look similar or at least that the same IDs are forced on
+each server on all participants.
 
 peers <peersect>
   Creates a new peer list with name <peersect>. It is an independent section,
index d05d653469a0c7e3aa01cdf9b01cffa550143bec..d447a92cc1ec0716bfb52cd5e3d81256430884bb 100644 (file)
@@ -242,6 +242,8 @@ static int peer_prepare_updatemsg(struct stksess *ts, struct shared_table *st, c
        uint32_t netinteger;
        unsigned short datalen;
        char *cursor, *datamsg;
+       unsigned int data_type;
+       void *data_ptr;
 
        cursor = datamsg = msg + 1 + 5;
 
@@ -278,11 +280,43 @@ static int peer_prepare_updatemsg(struct stksess *ts, struct shared_table *st, c
        }
 
        /* encode values */
-       if (stktable_data_ptr(st->table, ts, STKTABLE_DT_SERVER_ID)) {
-               int srvid;
+       for (data_type = 0 ; data_type < STKTABLE_DATA_TYPES ; data_type++) {
 
-               srvid = stktable_data_cast(stktable_data_ptr(st->table, ts, STKTABLE_DT_SERVER_ID), server_id);
-               intencode(srvid, &cursor);
+               data_ptr = stktable_data_ptr(st->table, ts, data_type);
+               if (data_ptr) {
+                       switch (stktable_data_types[data_type].std_type) {
+                               case STD_T_SINT: {
+                                       int data;
+
+                                       data = stktable_data_cast(data_ptr, std_t_sint);
+                                       intencode(data, &cursor);
+                                       break;
+                               }
+                               case STD_T_UINT: {
+                                       unsigned int data;
+
+                                       data = stktable_data_cast(data_ptr, std_t_uint);
+                                       intencode(data, &cursor);
+                                       break;
+                               }
+                               case STD_T_ULL: {
+                                       unsigned long long data;
+
+                                       data = stktable_data_cast(data_ptr, std_t_ull);
+                                       intencode(data, &cursor);
+                                       break;
+                               }
+                               case STD_T_FRQP: {
+                                       struct freq_ctr_period *frqp;
+
+                                       frqp = &stktable_data_cast(data_ptr, std_t_frqp);
+                                       intencode((unsigned int)(now_ms - frqp->curr_tick), &cursor);
+                                       intencode(frqp->curr_ctr, &cursor);
+                                       intencode(frqp->prev_ctr, &cursor);
+                                       break;
+                               }
+                       }
+               }
        }
 
        /* Compute datalen */
@@ -317,6 +351,7 @@ static int peer_prepare_switchmsg(struct shared_table *st, char *msg, size_t siz
        unsigned short datalen;
        char *cursor, *datamsg;
        uint64_t data = 0;
+       unsigned int data_type;
 
        cursor = datamsg = msg + 2 + 5;
 
@@ -338,9 +373,18 @@ static int peer_prepare_switchmsg(struct shared_table *st, char *msg, size_t siz
        /* encode table key size */
        intencode(st->table->key_size, &cursor);
 
-       /* encode available data types in table */
-       if (st->table->data_ofs[STKTABLE_DT_SERVER_ID]) {
-               data |= 1 << STKTABLE_DT_SERVER_ID;
+       /* encode available known data types in table */
+       for (data_type = 0 ; data_type < STKTABLE_DATA_TYPES ; data_type++) {
+               if (st->table->data_ofs[data_type]) {
+                       switch (stktable_data_types[data_type].std_type) {
+                               case STD_T_SINT:
+                               case STD_T_UINT:
+                               case STD_T_ULL:
+                               case STD_T_FRQP:
+                                       data |= 1 << data_type;
+                                       break;
+                       }
+               }
        }
        intencode(data, &cursor);
 
@@ -959,6 +1003,8 @@ switchstate:
                                                 || msg_head[1] == PEER_MSG_STKT_INCUPDATE) {
                                                struct shared_table *st = curpeer->remote_table;
                                                uint32_t update;
+                                               unsigned int data_type;
+                                               void *data_ptr;
 
                                                /* Here we have data message */
                                                if (!st)
@@ -1052,18 +1098,83 @@ switchstate:
                                                        }
                                                }
 
-                                               if ((1 << STKTABLE_DT_SERVER_ID) & st->remote_data) {
-                                                       int srvid;
+                                               for (data_type = 0 ; data_type < STKTABLE_DATA_TYPES ; data_type++) {
 
-                                                       srvid = intdecode(&msg_cur, msg_end);
-                                                       if (!msg_cur) {
-                                                               /* malformed message */
-                                                               appctx->st0 = PEER_SESS_ST_ERRPROTO;
-                                                               goto switchstate;
-                                                       }
+                                                       if ((1 << data_type) & st->remote_data) {
+                                                               switch (stktable_data_types[data_type].std_type) {
+                                                                       case STD_T_SINT: {
+                                                                               int data;
+
+                                                                               data = intdecode(&msg_cur, msg_end);
+                                                                               if (!msg_cur) {
+                                                                                       /* malformed message */
+                                                                                       appctx->st0 = PEER_SESS_ST_ERRPROTO;
+                                                                                       goto switchstate;
+                                                                               }
+
+                                                                               data_ptr = stktable_data_ptr(st->table, ts, data_type);
+                                                                               if (data_ptr)
+                                                                                       stktable_data_cast(data_ptr, std_t_sint) = data;
+                                                                               break;
+                                                                       }
+                                                                       case STD_T_UINT: {
+                                                                               unsigned int data;
+
+                                                                               data = intdecode(&msg_cur, msg_end);
+                                                                               if (!msg_cur) {
+                                                                                       /* malformed message */
+                                                                                       appctx->st0 = PEER_SESS_ST_ERRPROTO;
+                                                                                       goto switchstate;
+                                                                               }
+
+                                                                               data_ptr = stktable_data_ptr(st->table, ts, data_type);
+                                                                               if (data_ptr)
+                                                                                       stktable_data_cast(data_ptr, std_t_uint) = data;
+                                                                               break;
+                                                                       }
+                                                                       case STD_T_ULL: {
+                                                                               unsigned long long  data;
+
+                                                                               data = intdecode(&msg_cur, msg_end);
+                                                                               if (!msg_cur) {
+                                                                                       /* malformed message */
+                                                                                       appctx->st0 = PEER_SESS_ST_ERRPROTO;
+                                                                                       goto switchstate;
+                                                                               }
+
+                                                                               data_ptr = stktable_data_ptr(st->table, ts, data_type);
+                                                                               if (data_ptr)
+                                                                                       stktable_data_cast(data_ptr, std_t_ull) = data;
+                                                                               break;
+                                                                       }
+                                                                       case STD_T_FRQP: {
+                                                                               struct freq_ctr_period data;
+
+                                                                               data.curr_tick = tick_add(now_ms, intdecode(&msg_cur, msg_end));
+                                                                               if (!msg_cur) {
+                                                                                       /* malformed message */
+                                                                                       appctx->st0 = PEER_SESS_ST_ERRPROTO;
+                                                                                       goto switchstate;
+                                                                               }
+                                                                               data.curr_ctr = intdecode(&msg_cur, msg_end);
+                                                                               if (!msg_cur) {
+                                                                                       /* malformed message */
+                                                                                       appctx->st0 = PEER_SESS_ST_ERRPROTO;
+                                                                                       goto switchstate;
+                                                                               }
+                                                                               data.prev_ctr = intdecode(&msg_cur, msg_end);
+                                                                               if (!msg_cur) {
+                                                                                       /* malformed message */
+                                                                                       appctx->st0 = PEER_SESS_ST_ERRPROTO;
+                                                                                       goto switchstate;
+                                                                               }
 
-                                                       if (stktable_data_ptr(st->table, ts, STKTABLE_DT_SERVER_ID)) {
-                                                               stktable_data_cast(stktable_data_ptr(st->table, ts, STKTABLE_DT_SERVER_ID), server_id) = srvid;
+                                                                               data_ptr = stktable_data_ptr(st->table, ts, data_type);
+                                                                               if (data_ptr)
+                                                                                       stktable_data_cast(data_ptr, std_t_frqp) = data;
+                                                                               break;
+                                                                       }
+                                                               }
                                                        }
                                                }
                                        }