]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: pattern: store a generation number in the reference patterns
authorWilly Tarreau <w@1wt.eu>
Wed, 28 Oct 2020 10:43:49 +0000 (11:43 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 5 Nov 2020 18:27:09 +0000 (19:27 +0100)
Right now it's not possible to perform a safe reload because we don't
know what patterns were recently added or were already present. This
patch adds a generation counter to the reference patterns so that it
is possible to know what generation of the reference they were loaded
with. A reference now has two generations, the current one, used for
all additions, and the next one, allocated to those wishing to update
the contents. The generation wraps at 2^32 so comparisons must be made
relative to the current position.

The idea will be that upon full reload, the caller will first get a new
generation ID, will insert all new patterns using it, will then switch
the current ID to the new one, and will delete all entries older than
the current ID. This has the benefit of supporting chunked updates that
remain consistent and that won't block the whole process for ages like
pat_ref_reload() currently does.

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

index 477b2bbc6a40e043c203e46b93307a4954727291..30ff999b516eeaaf7e075a5f52dc674df8611c16 100644 (file)
@@ -106,6 +106,8 @@ struct pat_ref {
        struct list head; /* The head of the list of struct pat_ref_elt. */
        struct list pat; /* The head of the list of struct pattern_expr. */
        unsigned int flags; /* flags PAT_REF_*. */
+       unsigned int curr_gen; /* current generation number (anything below can be removed) */
+       unsigned int next_gen; /* next generation number (insertions use this one) */
        int unique_id; /* Each pattern reference have unique id. */
        unsigned long long revision; /* updated for each update */
        __decl_thread(HA_SPINLOCK_T lock); /* Lock used to protect pat ref elements */
@@ -122,6 +124,7 @@ struct pat_ref_elt {
        struct list tree_head; /* all pattern_tree derived from this reference */
        char *pattern;
        char *sample;
+       unsigned int gen_id; /* generation of pat_ref this was made for */
        int line;
 };
 
index 7f4f44958b8148d44a112e9e555b7bc7ee72d984..7b4d876e2f99641c1b85e376809ca5613b2fa361 100644 (file)
@@ -1756,6 +1756,8 @@ struct pat_ref *pat_ref_newid(int unique_id, const char *display, unsigned int f
 
        ref->reference = NULL;
        ref->flags = flags;
+       ref->curr_gen = 0;
+       ref->next_gen = 0;
        ref->unique_id = unique_id;
        LIST_INIT(&ref->head);
        LIST_INIT(&ref->pat);
@@ -1767,7 +1769,8 @@ struct pat_ref *pat_ref_newid(int unique_id, const char *display, unsigned int f
 
 /* This function adds entry to <ref>. It can fail on memory error. It returns
  * the newly added element on success, or NULL on failure. The PATREF_LOCK on
- * <ref> must be held.
+ * <ref> must be held. It sets the newly created pattern's generation number
+ * to the same value as the reference's.
  */
 struct pat_ref_elt *pat_ref_append(struct pat_ref *ref, const char *pattern, const char *sample, int line)
 {
@@ -1777,6 +1780,7 @@ struct pat_ref_elt *pat_ref_append(struct pat_ref *ref, const char *pattern, con
        if (!elt)
                goto fail;
 
+       elt->gen_id = ref->curr_gen;
        elt->line = line;
 
        elt->pattern = strdup(pattern);