]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: pattern: turn the pattern chaining to single-linked list
authorWilly Tarreau <w@1wt.eu>
Tue, 3 Nov 2020 13:50:29 +0000 (14:50 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 5 Nov 2020 18:27:09 +0000 (19:27 +0100)
It does not require heavy deletion from the expr anymore, so we can now
turn this to a single-linked list since most of the time we want to delete
all instances of a given pattern from the head. By doing so we save 32 bytes
of memory per pattern. The pat_unlink_from_head() function was adjusted
accordingly.

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

index 30ff999b516eeaaf7e075a5f52dc674df8611c16..0cd9af0ae95bf37f441d2b962ba0059711a8b238 100644 (file)
@@ -120,8 +120,8 @@ struct pat_ref {
 struct pat_ref_elt {
        struct list list; /* Used to chain elements. */
        struct list back_refs; /* list of users tracking this pat ref */
-       struct list list_head; /* all pattern_list derived from this reference */
-       struct list tree_head; /* all pattern_tree derived from this reference */
+       void *list_head; /* all &pattern_list->from_ref derived from this reference, ends with NULL */
+       void *tree_head; /* all &pattern_tree->from_ref derived from this reference, ends with NULL */
        char *pattern;
        char *sample;
        unsigned int gen_id; /* generation of pat_ref this was made for */
@@ -132,7 +132,7 @@ struct pat_ref_elt {
  * "sample" with a tree entry. It is used with maps.
  */
 struct pattern_tree {
-       struct list from_ref;      // pattern_tree linked from pat_ref_elt
+       void *from_ref;    // pattern_tree linked from pat_ref_elt, ends with NULL
        struct sample_data *data;
        struct pat_ref_elt *ref;
        struct ebmb_node node;
@@ -177,7 +177,7 @@ struct pattern {
 
 /* This struct is just used for chaining patterns */
 struct pattern_list {
-       struct list from_ref;      // pattern_tree linked from pat_ref_elt
+       void *from_ref;    // pattern_tree linked from pat_ref_elt, ends with NULL
        struct list list;
        struct pattern pat;
 };
index 612abca8e902a4bf4eba2c20858c04893c10a5b2..88e760cc052f70514d00e5b3f289577c7aadd5fe 100644 (file)
@@ -1123,17 +1123,14 @@ struct pattern *pat_match_ip(struct sample *smp, struct pattern_expr *expr, int
 /* finds the pattern holding <list> from list head <head> and deletes it.
  * This is made for use for pattern removal within an expression.
  */
-static void pat_unlink_from_head(struct list *head, struct list *list)
+static void pat_unlink_from_head(void **head, void **list)
 {
-       struct list *next;
-
-       next = head->n;
-       while (next != head) {
-               if (next == list) {
-                       LIST_DEL(list);
+       while (*head) {
+               if (*head == list) {
+                       *head = *list;
                        return;
                }
-               next = next->n;
+               head = *head;
        }
 }
 
@@ -1198,7 +1195,8 @@ int pat_idx_list_val(struct pattern_expr *expr, struct pattern *pat, char **err)
        /* chain pattern in the expression */
        LIST_ADDQ(&expr->patterns, &patl->list);
        /* and from the reference */
-       LIST_ADDQ(&pat->ref->list_head, &patl->from_ref);
+       patl->from_ref = pat->ref->list_head;
+       pat->ref->list_head = &patl->from_ref;
        expr->ref->revision = rdtsc();
 
        /* that's ok */
@@ -1229,7 +1227,8 @@ int pat_idx_list_ptr(struct pattern_expr *expr, struct pattern *pat, char **err)
        /* chain pattern in the expression */
        LIST_ADDQ(&expr->patterns, &patl->list);
        /* and from the reference */
-       LIST_ADDQ(&pat->ref->list_head, &patl->from_ref);
+       patl->from_ref = pat->ref->list_head;
+       pat->ref->list_head = &patl->from_ref;
        expr->ref->revision = rdtsc();
 
        /* that's ok */
@@ -1261,7 +1260,8 @@ int pat_idx_list_str(struct pattern_expr *expr, struct pattern *pat, char **err)
        /* chain pattern in the expression */
        LIST_ADDQ(&expr->patterns, &patl->list);
        /* and from the reference */
-       LIST_ADDQ(&pat->ref->list_head, &patl->from_ref);
+       patl->from_ref = pat->ref->list_head;
+       pat->ref->list_head = &patl->from_ref;
        expr->ref->revision = rdtsc();
 
        /* that's ok */
@@ -1293,7 +1293,8 @@ int pat_idx_list_reg_cap(struct pattern_expr *expr, struct pattern *pat, int cap
        /* chain pattern in the expression */
        LIST_ADDQ(&expr->patterns, &patl->list);
        /* and from the reference */
-       LIST_ADDQ(&pat->ref->list_head, &patl->from_ref);
+       patl->from_ref = pat->ref->list_head;
+       pat->ref->list_head = &patl->from_ref;
        expr->ref->revision = rdtsc();
 
        /* that's ok */
@@ -1343,7 +1344,8 @@ int pat_idx_tree_ip(struct pattern_expr *expr, struct pattern *pat, char **err)
 
                        /* Insert the entry. */
                        ebmb_insert_prefix(&expr->pattern_tree, &node->node, 4);
-                       LIST_ADDQ(&pat->ref->tree_head, &node->from_ref);
+                       node->from_ref = pat->ref->tree_head;
+                       pat->ref->tree_head = &node->from_ref;
                        expr->ref->revision = rdtsc();
 
                        /* that's ok */
@@ -1372,7 +1374,8 @@ int pat_idx_tree_ip(struct pattern_expr *expr, struct pattern *pat, char **err)
 
                /* Insert the entry. */
                ebmb_insert_prefix(&expr->pattern_tree_2, &node->node, 16);
-               LIST_ADDQ(&pat->ref->tree_head, &node->from_ref);
+               node->from_ref = pat->ref->tree_head;
+               pat->ref->tree_head = &node->from_ref;
                expr->ref->revision = rdtsc();
 
                /* that's ok */
@@ -1417,7 +1420,8 @@ int pat_idx_tree_str(struct pattern_expr *expr, struct pattern *pat, char **err)
 
        /* index the new node */
        ebst_insert(&expr->pattern_tree, &node->node);
-       LIST_ADDQ(&pat->ref->tree_head, &node->from_ref);
+       node->from_ref = pat->ref->tree_head;
+       pat->ref->tree_head = &node->from_ref;
        expr->ref->revision = rdtsc();
 
        /* that's ok */
@@ -1460,7 +1464,8 @@ int pat_idx_tree_pfx(struct pattern_expr *expr, struct pattern *pat, char **err)
 
        /* index the new node */
        ebmb_insert_prefix(&expr->pattern_tree, &node->node, len);
-       LIST_ADDQ(&pat->ref->tree_head, &node->from_ref);
+       node->from_ref = pat->ref->tree_head;
+       pat->ref->tree_head = &node->from_ref;
        expr->ref->revision = rdtsc();
 
        /* that's ok */
@@ -1472,27 +1477,29 @@ int pat_idx_tree_pfx(struct pattern_expr *expr, struct pattern *pat, char **err)
  */
 void pat_delete_gen(struct pat_ref *ref, struct pat_ref_elt *elt)
 {
-       struct pattern_tree *tree, *tree_bck;
-       struct pattern_list *pat, *pat_bck;
+       struct pattern_tree *tree;
+       struct pattern_list *pat;
+       void **node;
 
        /* delete all known tree nodes. They are all allocated inline */
-       list_for_each_entry_safe(tree, tree_bck, &elt->tree_head, from_ref) {
+       for (node = elt->tree_head; node;) {
+               tree = container_of(node, struct pattern_tree, from_ref);
+               node = *node;
                BUG_ON(tree->ref != elt);
 
                ebmb_delete(&tree->node);
-               LIST_DEL(&tree->from_ref);
                free(tree->data);
                free(tree);
        }
 
        /* delete all list nodes and free their pattern entries (str/reg) */
-       list_for_each_entry_safe(pat, pat_bck, &elt->list_head, from_ref) {
-               /* Check equality. */
+       for (node = elt->list_head; node;) {
+               pat = container_of(node, struct pattern_list, from_ref);
+               node = *node;
                BUG_ON(pat->pat.ref != elt);
 
                /* Delete and free entry. */
                LIST_DEL(&pat->list);
-               LIST_DEL(&pat->from_ref);
                if (pat->pat.sflags & PAT_SF_REGFREE)
                        regex_free(pat->pat.ptr.reg);
                else
@@ -1503,6 +1510,8 @@ void pat_delete_gen(struct pat_ref *ref, struct pat_ref_elt *elt)
 
        /* update revision number to refresh the cache */
        ref->revision = rdtsc();
+       elt->tree_head = NULL;
+       elt->list_head = NULL;
 }
 
 void pattern_init_expr(struct pattern_expr *expr)
@@ -1876,8 +1885,8 @@ struct pat_ref_elt *pat_ref_append(struct pat_ref *ref, const char *pattern, con
        }
 
        LIST_INIT(&elt->back_refs);
-       LIST_INIT(&elt->list_head);
-       LIST_INIT(&elt->tree_head);
+       elt->list_head = NULL;
+       elt->tree_head = NULL;
        LIST_ADDQ(&ref->head, &elt->list);
        return elt;
  fail: