]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: pattern: publish event_hdl events on pat_ref updates
authorAurelien DARRAGON <adarragon@haproxy.com>
Fri, 18 Oct 2024 16:40:41 +0000 (18:40 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Fri, 29 Nov 2024 06:22:25 +0000 (07:22 +0100)
Now that PAT_REF events were defined in previous commit, let's actually
publish them from pattern API where relevant. Unlike server events,
pattern reference events are only published in the pat_ref subscriber's
list on purpose, because in some setups patref updates (updates performed
on a map for instance from action or cli) are very frequent, and we don't
want to impact pattern API performance just for that.

Moreover, as the main use case is to be able to subscribe to maps updates
from Lua, allowing a per-pattern reference registration is already enough.

No additional data is provided for such events (also for performance reason)

Care was taken not to publish events when the update doesn't affect the
live subset (the one targeted by curr_gen).

include/haproxy/pattern-t.h
include/haproxy/pattern.h
src/pattern.c

index b84c7e71e433a059192411893c04316220c2eb01..35c4fd0956de95976eac6cde80f98968d76479f0 100644 (file)
@@ -25,6 +25,7 @@
 #include <import/ebtree-t.h>
 
 #include <haproxy/api-t.h>
+#include <haproxy/event_hdl-t.h>
 #include <haproxy/regex-t.h>
 #include <haproxy/sample_data-t.h>
 #include <haproxy/thread-t.h>
@@ -116,6 +117,7 @@ struct pat_ref {
        unsigned long long entry_cnt; /* the total number of entries */
        THREAD_ALIGN(64);
        __decl_thread(HA_RWLOCK_T lock); /* Lock used to protect pat ref elements */
+       event_hdl_sub_list e_subs;       /* event_hdl: pat_ref's subscribers list (atomically updated) */
 };
 
 /* This is a part of struct pat_ref. Each entry contains one pattern and one
index 283eb5b0860994b958076f47b900b96682705ecc..2b1235853ccb8d4ba5e547f8345567c2f0bcd58a 100644 (file)
@@ -25,6 +25,7 @@
 #include <string.h>
 
 #include <haproxy/api.h>
+#include <haproxy/event_hdl.h>
 #include <haproxy/pattern-t.h>
 #include <haproxy/sample-t.h>
 
@@ -238,8 +239,10 @@ static inline void pat_ref_giveup(struct pat_ref *ref, unsigned int gen)
  */
 static inline int pat_ref_commit(struct pat_ref *ref, unsigned int gen)
 {
-       if ((int)(gen - ref->curr_gen) > 0)
+       if ((int)(gen - ref->curr_gen) > 0) {
                ref->curr_gen = gen;
+               event_hdl_publish(&ref->e_subs, EVENT_HDL_SUB_PAT_REF_COMMIT, NULL);
+       }
        return gen - ref->curr_gen;
 }
 
index 2c1a4834243514902f3a6b40fb11beb7b7c6bcea..59deced0c239e65a3d58c9f7a8bf968efdf902c1 100644 (file)
@@ -1606,6 +1606,7 @@ int pat_ref_delete_by_id(struct pat_ref *ref, struct pat_ref_elt *refelt)
        /* delete pattern from reference */
        list_for_each_entry_safe(elt, safe, &ref->head, list) {
                if (elt == refelt) {
+                       event_hdl_publish(&ref->e_subs, EVENT_HDL_SUB_PAT_REF_DEL, NULL);
                        pat_ref_delete_by_ptr(ref, elt);
                        return 1;
                }
@@ -1636,6 +1637,9 @@ int pat_ref_gen_delete(struct pat_ref *ref, unsigned int gen_id, const char *key
                found = 1;
        }
 
+       if (found)
+               event_hdl_publish(&ref->e_subs, EVENT_HDL_SUB_PAT_REF_DEL, NULL);
+
        return found;
 }
 
@@ -1815,6 +1819,10 @@ static int pat_ref_set_from_node(struct pat_ref *ref, struct ebmb_node *node, co
                memprintf(err, "entry not found");
                return 0;
        }
+
+       if (gen == ref->curr_gen) // gen cannot be uninitialized here
+               event_hdl_publish(&ref->e_subs, EVENT_HDL_SUB_PAT_REF_SET, NULL);
+
        return 1;
 }
 
@@ -1887,6 +1895,7 @@ static struct pat_ref *_pat_ref_new(const char *display, unsigned int flags)
        ref->ebmb_root = EB_ROOT;
        LIST_INIT(&ref->pat);
        HA_RWLOCK_INIT(&ref->lock);
+       event_hdl_sub_list_init(&ref->e_subs);
 
        return ref;
 }
@@ -1896,6 +1905,7 @@ static void pat_ref_free(struct pat_ref *ref)
 {
        ha_free(&ref->reference);
        ha_free(&ref->display);
+       event_hdl_sub_list_destroy(&ref->e_subs);
        free(ref);
 }
 
@@ -2095,6 +2105,10 @@ struct pat_ref_elt *pat_ref_load(struct pat_ref *ref, unsigned int gen,
        } else
                memprintf(err, "out of memory error");
 
+       /* ignore if update requires committing to be seen */
+       if (elt && gen == ref->curr_gen)
+               event_hdl_publish(&ref->e_subs, EVENT_HDL_SUB_PAT_REF_ADD, NULL);
+
        return elt;
 }
 
@@ -2167,6 +2181,12 @@ int pat_ref_purge_range(struct pat_ref *ref, uint from, uint to, int budget)
        list_for_each_entry(expr, &ref->pat, list)
                HA_RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
 
+       /* only publish when we're done and if curr_gen was impacted by the
+        * purge
+        */
+       if (done && ref->curr_gen - from <= to - from)
+               event_hdl_publish(&ref->e_subs, EVENT_HDL_SUB_PAT_REF_CLEAR, NULL);
+
        return done;
 }