diff --git a/include/haproxy/pattern-t.h b/include/haproxy/pattern-t.h index b84c7e71e..35c4fd095 100644 --- a/include/haproxy/pattern-t.h +++ b/include/haproxy/pattern-t.h @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -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 diff --git a/include/haproxy/pattern.h b/include/haproxy/pattern.h index 283eb5b08..2b1235853 100644 --- a/include/haproxy/pattern.h +++ b/include/haproxy/pattern.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -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; } diff --git a/src/pattern.c b/src/pattern.c index 2c1a48342..59deced0c 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -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; }