diff --git a/include/haproxy/peers-t.h b/include/haproxy/peers-t.h index 19619d0a1..ee48d73da 100644 --- a/include/haproxy/peers-t.h +++ b/include/haproxy/peers-t.h @@ -106,7 +106,8 @@ static forceinline char *peers_show_flags(char *buf, size_t len, const char *del #define PEER_F_ALIVE 0x00000020 /* Used to flag a peer a alive. */ #define PEER_F_HEARTBEAT 0x00000040 /* Heartbeat message to send. */ #define PEER_F_DWNGRD 0x00000080 /* When this flag is enabled, we must downgrade the supported version announced during peer sessions. */ -/* unused 0x00000100..0x00080000 */ +#define PEER_F_SYNCHED 0x00000100 /* Remote peer is synchronized with the local peer */ +/* unused 0x00000200..0x00080000 */ #define PEER_F_DBG_RESYNC_REQUESTED 0x00100000 /* A resnyc was explicitly requested at least once (for debugging purpose) */ #define PEER_TEACH_FLAGS (PEER_F_TEACH_PROCESS|PEER_F_TEACH_FINISHED) @@ -124,7 +125,7 @@ static forceinline char *peer_show_flags(char *buf, size_t len, const char *deli _(PEER_F_TEACH_PROCESS, _(PEER_F_TEACH_FINISHED, _(PEER_F_LOCAL_TEACH_COMPLETE, _(PEER_F_LEARN_NOTUP2DATE, _(PEER_F_WAIT_SYNCTASK_ACK, _(PEER_F_ALIVE, _(PEER_F_HEARTBEAT, _(PEER_F_DWNGRD, - _(PEER_F_DBG_RESYNC_REQUESTED))))))))); + _(PEER_F_SYNCHED ,_(PEER_F_DBG_RESYNC_REQUESTED)))))))))); /* epilogue */ _(~0U); return buf; @@ -174,6 +175,10 @@ struct peer { struct shared_table *last_local_table; /* Last table that emit update messages during a teach process */ struct shared_table *stop_local_table; /* last evaluated table, used as restart point for the next teach process */ struct shared_table *tables; + struct { + struct shared_table *table; + unsigned int id; + } last; struct server *srv; struct dcache *dcache; /* dictionary cache */ struct peers *peers; /* associated peer section */ diff --git a/src/cfgparse.c b/src/cfgparse.c index a36e88983..edaaa70e6 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -636,6 +636,7 @@ static struct peer *cfg_peers_add_peer(struct peers *peers, /* the peers are linked backwards first */ peers->count++; p->peers = peers; + p->flags |= PEER_F_SYNCHED; p->next = peers->remote; peers->remote = p; p->conf.file = strdup(file); diff --git a/src/peers.c b/src/peers.c index aadc6af5d..30783f9f8 100644 --- a/src/peers.c +++ b/src/peers.c @@ -1693,6 +1693,9 @@ int peer_send_teachmsgs(struct appctx *appctx, struct peer *p, break; st->last_pushed = updateid; + p->last.table = st; + p->last.id = updateid; + p->flags &= ~PEER_F_SYNCHED; /* identifier may not needed in next update message */ new_pushed = 0; @@ -2236,6 +2239,10 @@ static inline int peer_treat_ackmsg(struct appctx *appctx, struct peer *p, break; } } + if (table_id == p->last.table->local_id && update == p->last.id) { + TRACE_STATE("Peer synched again", PEERS_EV_SESS_IO|PEERS_EV_RX_MSG|PEERS_EV_PROTO_ACK, appctx, p); + p->flags |= PEER_F_SYNCHED; + } end: TRACE_LEAVE(PEERS_EV_SESS_IO|PEERS_EV_RX_MSG|PEERS_EV_PROTO_ACK, appctx, p, st); @@ -2618,6 +2625,7 @@ static inline int peer_treat_awaited_msg(struct appctx *appctx, struct peer *pee TRACE_STATE("process stopping, stop any resync", PEERS_EV_SESS_IO|PEERS_EV_RX_MSG|PEERS_EV_PROTO_CTRL, appctx, peer); return 0; } + peer->flags |= PEER_F_SYNCHED; for (st = peer->tables; st; st = st->next) { st->update = st->last_pushed = st->teaching_origin; st->flags = 0; @@ -2964,8 +2972,10 @@ static inline void init_connected_peer(struct peer *peer, struct peers *peers) * Here a partial fix consist to set st->update at * the max past value. */ - if ((int)(st->table->localupdate - st->update) < 0) + if (!(peer->flags & PEER_F_SYNCHED) || (int)(st->table->localupdate - st->update) < 0) { st->update = st->table->localupdate + (2147483648U); + peer->flags &= ~PEER_F_SYNCHED; + } st->teaching_origin = st->last_pushed = st->update; st->flags = 0; @@ -2986,6 +2996,7 @@ static inline void init_connected_peer(struct peer *peer, struct peers *peers) * on the frontend side), flag it to start to teach lesson. */ peer->flags |= PEER_F_TEACH_PROCESS; + peer->flags &= ~PEER_F_SYNCHED; TRACE_STATE("peer elected to teach lesson to lacal peer", PEERS_EV_SESS_NEW, NULL, peer); }