]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: peers: Save date of the last update to wake the peer applet
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 14 Oct 2025 12:02:05 +0000 (14:02 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 21 Oct 2025 13:11:24 +0000 (15:11 +0200)
Instead of looking for new updates in each updates lists to wake a peer
applet up, we now only detect that some updates should have been inserted by
comparing the date of the last update inserted in the list and the last
update sent to the peer.

It is not 100% accurrate of course. Some extra wakeups may be observed. But
this should not lead to any spinning loop because the operation is performed
by the sync task. This task is woken up when a timeout is fired or when an
update was inserted. However, this saves several loops on the updates lists.

include/haproxy/peers-t.h
include/haproxy/stick_table-t.h
src/peers.c
src/stick_table.c

index fd5da5f251c32c5b4778873cd1d0de249dccf441..067d711d45967cdc066f9650f56ee08bef6fb4c6 100644 (file)
@@ -164,6 +164,7 @@ struct peer {
        unsigned int heartbeat;       /* next heartbeat timer */
        unsigned int confirm;         /* confirm message counter */
        unsigned int last_hdshk;      /* Date of the last handshake. */
+       unsigned int last_update;     /* Date of last update sent */
        uint32_t rx_hbt;              /* received heartbeats counter */
        uint32_t tx_hbt;              /* transmitted heartbeats counter */
        uint32_t no_hbt;              /* no received heartbeat counter */
index 64ace526d2c19b44286b1bd10920b0189484497f..fc2f0d1e9c83c4010155314b6f47df1c4af94e20 100644 (file)
@@ -231,7 +231,7 @@ struct stktable {
                                    attached to this table */
        unsigned int current;     /* number of sticky sessions currently in table */
        THREAD_ALIGN(64);
-
+       unsigned int   last_update; /* Date of the last update inserted in the list */
        struct mt_list updates;     /* list of sticky updates sequence */
        struct mt_list *pend_updts; /* list of updates to be added to the update sequence list, one per thread-group */
        struct tasklet *updt_task;/* tasklet responsible for pushing the pending updates into the tree */
index 3ef6052fafc28940d81db58908a4e9de6c618396..41e3585245ccf347fe13a2ad239f00f326146e8e 100644 (file)
@@ -1634,6 +1634,7 @@ int peer_send_teachmsgs(struct appctx *appctx, struct peer *p, struct shared_tab
                p->last.id = st->update_id;
                st->update_id++;
                p->flags &= ~PEER_F_SYNCHED;
+               p->last_update = now_ms;
 
                /* identifier may not needed in next update message */
                new_pushed = 0;
@@ -3521,18 +3522,9 @@ static void __process_running_peer_sync(struct task *task, struct peers *peers,
 
                                        /* Awake session if there is data to push */
                                        for (st = peer->tables; st ; st = st->next) {
-                                               struct stksess *ts;
-                                               struct mt_list back;
-
-                                               // TODO: may be handled via an atomic flags ?
-                                               MT_LIST_FOR_EACH_ENTRY_LOCKED(ts, &st->last->upd, upd, back) {
-                                                       if (&ts->upd == &st->table->updates)
-                                                               break;
-                                                       if (&ts->upd != &st->table->updates && ts->updt_type == STKSESS_UPDT_LOCAL) {
-                                                               update_to_push = 1;
-                                                               break;
-                                                       }
-                                               }
+                                               if (tick_is_le(peer->last_update, st->table->last_update))
+                                                       update_to_push = 1;
+
                                                if (update_to_push == 1) {
                                                        /* wake up the peer handler to push local updates */
                                                        /* There is no need to send a heartbeat message
@@ -3721,17 +3713,7 @@ static void __process_stopping_peer_sync(struct task *task, struct peers *peers,
                /* current peer connection is active and established
                 * wake up all peer handlers to push remaining local updates */
                for (st = peer->tables; st ; st = st->next) {
-                       struct stksess *ts;
-                       struct mt_list back;
-                       int wakeup = 0;
-
-                       MT_LIST_FOR_EACH_ENTRY_LOCKED(ts, &st->last->upd, upd, back) {
-                               if (&ts->upd != &st->table->updates && ts->updt_type == STKSESS_UPDT_LOCAL) {
-                                       wakeup = 1;
-                                       break;
-                               }
-                       }
-                       if (wakeup) {
+                       if (tick_is_le(peer->last_update, st->table->last_update)) {
                                appctx_wakeup(peer->appctx);
                                break;
                        }
index b5a90c8eeef45a9dea31d36ef6173d9cb47abaa9..0d18ebe04fc60739c1c7b35ace02b06a973333d3 100644 (file)
@@ -868,6 +868,7 @@ struct task *stktable_add_pend_updates(struct task *t, void *ctx, unsigned int s
 
        if (i > 0) {
                /* We did at least one update, let's wake the sync task */
+               table->last_update = now_ms;
                task_wakeup(table->sync_task, TASK_WOKEN_MSG);
        }
        return t;
@@ -1187,6 +1188,7 @@ int stktable_init(struct stktable *t, char **err_msg)
        for (i = 0; i < global.nbtgroups; i++)
                MT_LIST_INIT(&t->pend_updts[i]);
        t->updt_task = tasklet_new();
+       t->last_update = TICK_ETERNITY;
        if (!t->updt_task)
                goto mem_error;
        t->updt_task->context = t;