struct list list; /* Used to chain refs. */
char *reference; /* The reference name. */
char *display; /* String displayed to identify the pattern origin. */
+ struct ceb_root *gen_root; /* The tree mapping generation IDs to pattern reference elements */
struct list head; /* The head of the list of struct pat_ref_elt. */
struct ceb_root *ceb_root; /* The tree where pattern reference elements are attached. */
struct list pat; /* The head of the list of struct pattern_expr. */
event_hdl_sub_list e_subs; /* event_hdl: pat_ref's subscribers list (atomically updated) */
};
+/* This struct represents all the elements in a pattern reference generation. The tree
+ * is used most of the time, but we also maintain a list for when order matters.
+ */
+struct pat_ref_gen {
+ struct list head; /* The head of the list of struct pat_ref_elt. */
+ struct ceb_root *elt_root; /* The tree where pattern reference elements are attached. */
+ struct ceb_node gen_node; /* Linkage for the gen_root cebtree in struct pat_ref */
+ unsigned int gen_id;
+};
+
/* This is a part of struct pat_ref. Each entry contains one pattern and one
* associated value as original string. All derivative forms (via exprs) are
* accessed from list_head or tree_head. Be careful, it's variable-sized!
struct pat_ref_elt *pat_ref_gen_find_elt(struct pat_ref *ref, unsigned int gen_id, const char *key);
struct pat_ref_elt *pat_ref_append(struct pat_ref *ref, const char *pattern, const char *sample, int line);
struct pat_ref_elt *pat_ref_load(struct pat_ref *ref, unsigned int gen, const char *pattern, const char *sample, int line, char **err);
+struct pat_ref_gen *pat_ref_gen_new(struct pat_ref *ref, unsigned int gen_id);
+struct pat_ref_gen *pat_ref_gen_get(struct pat_ref *ref, unsigned int gen_id);
int pat_ref_push(struct pat_ref_elt *elt, struct pattern_expr *expr, int patflags, char **err);
int pat_ref_add(struct pat_ref *ref, const char *pattern, const char *sample, char **err);
int pat_ref_set(struct pat_ref *ref, const char *pattern, const char *sample, char **err);
unsigned int display_flags;
unsigned int curr_gen; /* current/latest generation, for show/clear */
unsigned int prev_gen; /* prev generation, for clear */
+ struct pat_ref_gen *gen; /* link to the generation being displayed, for show */
enum {
STATE_INIT = 0, /* initialize list and backrefs */
STATE_LIST, /* list entries */
#include <errno.h>
#include <import/cebs_tree.h>
+#include <import/ceb32_tree.h>
#include <import/ebistree.h>
#include <import/ebpttree.h>
#include <import/ebsttree.h>
#include <haproxy/xxhash.h>
+/* Convenience macros for iterating over generations. */
+#define pat_ref_gen_foreach(gen, ref) \
+ for (gen = cebu32_item_first(&ref->gen_root, gen_node, gen_id, struct pat_ref_gen); \
+ gen; \
+ gen = cebu32_item_next(&ref->gen_root, gen_node, gen_id, gen))
+
+/* Safe variant that allows deleting an entry in the body of the loop. */
+#define pat_ref_gen_foreach_safe(gen, next, ref) \
+ for (gen = cebu32_item_first(&ref->gen_root, gen_node, gen_id, struct pat_ref_gen); \
+ gen && (next = cebu32_item_next(&ref->gen_root, gen_node, gen_id, gen), 1); \
+ gen = next)
+
const char *const pat_match_names[PAT_MATCH_NUM] = {
[PAT_MATCH_FOUND] = "found",
[PAT_MATCH_BOOL] = "bool",
return 0;
}
+/* Create a new generation object.
+ *
+ * Returns NULL in case of memory allocation failure.
+ */
+struct pat_ref_gen *pat_ref_gen_new(struct pat_ref *ref, unsigned int gen_id)
+{
+ struct pat_ref_gen *gen, *old;
+
+ gen = calloc(1, sizeof(struct pat_ref_gen));
+ if (!gen)
+ return NULL;
+
+ LIST_INIT(&gen->head);
+ ceb_init_root(&gen->elt_root);
+ gen->gen_id = gen_id;
+
+ old = cebu32_item_insert(&ref->gen_root, gen_node, gen_id, gen);
+ BUG_ON(old != gen, "Generation ID already exists");
+
+ return gen;
+}
+
+/* Find the generation <gen_id> in the pattern reference <ref>.
+ *
+ * Returns NULL if the generation cannot be found.
+ */
+struct pat_ref_gen *pat_ref_gen_get(struct pat_ref *ref, unsigned int gen_id)
+{
+ return cebu32_item_lookup(&ref->gen_root, gen_node, gen_id, gen_id, struct pat_ref_gen);
+}
+
/* This function removes all elements belonging to <gen_id> and matching <key>
* from the reference <ref>.
* This function returns 1 if the deletion is done and returns 0 if