]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: initcall: allow to register mutiple post_section_parser per section
authorWilliam Lallemand <wlallemand@haproxy.com>
Mon, 10 Feb 2025 14:07:05 +0000 (15:07 +0100)
committerWilliam Lallemand <wlallemand@haproxy.com>
Wed, 12 Feb 2025 11:52:41 +0000 (12:52 +0100)
Before this patch, REGISTER_CONFIG_SECTION() allowed to register one and only
one callback (<post>) called after the parsing of a section.

It was limitating because you couldn't register a post callback from anywhere
else in the code.

This patch introduces the new REGISTER_CONFIG_SECTION_POST() macros which allows
to register a new post callback for a section keyword from anywhere.

This patch introduces the feature by allowing `struct cfg_section` entries that
does not have a `section_parser`, and then iterating on all cfg_section with a
post_section_parser for a keyword.

doc/internals/api/initcalls.txt
include/haproxy/cfgparse.h
src/cfgparse.c

index a341edc1dba4bdae9af0e36997fcf310ed1da734..c599640ef57542f2c6ef9e9a460921dec8a0fa34 100644 (file)
@@ -314,6 +314,16 @@ alphanumerically ordered:
   call to cfg_register_section() with the three arguments at stage
   STG_REGISTER.
 
+  You can only register a section once, but you can register post callbacks
+  multiple time for this section with REGISTER_CONFIG_SECTION_POST().
+
+- REGISTER_CONFIG_SECTION_POST(name, post)
+
+  Registers a function which will be called after a section is parsed. This is
+  the same as the <post> argument in REGISTER_CONFIG_SECTION(), the difference
+  is that it allows to register multiple <post> callbacks and to register them
+  elsewhere in the code.
+
 - REGISTER_PER_THREAD_ALLOC(fct)
 
   Registers a call to register_per_thread_alloc(fct) at stage STG_REGISTER.
index 7b89b7a1f40c686f46cc9b52dc20d108110223a9..89be1fb797256616154b8704bb7fa051cac1a3d2 100644 (file)
@@ -151,6 +151,10 @@ ssize_t load_cfg_in_mem(char* filename, char** cfg_content);
 #define REGISTER_CONFIG_SECTION(name, parse, post)                            \
        INITCALL3(STG_REGISTER, cfg_register_section, (name), (parse), (post))
 
+/* simplified way to define a post section parser */
+#define REGISTER_CONFIG_POST_SECTION(name, post)                              \
+       INITCALL3(STG_REGISTER, cfg_register_section, (name), NULL, (post))
+
 #define REGISTER_CONFIG_POSTPARSER(name, parser)                              \
        INITCALL2(STG_REGISTER, cfg_register_postparser, (name), (parser))
 
index bf8bd14e82c7478b1b27883bacc0996a5c0721da..acd581058f383ad6a6494a7f5aa2ef5d632692f3 100644 (file)
@@ -2052,7 +2052,10 @@ next_line:
 
                                /* if a word is in sections list, is_sect = 1 */
                                list_for_each_entry(sect, &sections, list) {
-                                       if (strcmp(args[0], sect->section_name) == 0) {
+                                       /* look for a section_name, but also a section_parser, because there might be
+                                        * only a post_section_parser */
+                                       if (strcmp(args[0], sect->section_name) == 0 &&
+                                           sect->section_parser) {
                                                is_sect = 1;
                                                break;
                                        }
@@ -2562,7 +2565,7 @@ next_line:
 
                /* detect section start */
                list_for_each_entry(ics, &sections, list) {
-                       if (strcmp(args[0], ics->section_name) == 0) {
+                       if (strcmp(args[0], ics->section_name) == 0 && ics->section_parser) {
                                cursection = ics->section_name;
                                pcs = cs;
                                cs = ics;
@@ -2573,20 +2576,29 @@ next_line:
                        }
                }
 
-               if (pcs && pcs->post_section_parser) {
+               if (pcs) {
+                       struct cfg_section *psect;
                        int status;
 
-                       /* don't call post_section_parser in MODE_DISCOVERY */
-                       if (global.mode & MODE_DISCOVERY)
-                               goto section_parser;
 
-                       status = pcs->post_section_parser();
-                       err_code |= status;
-                       if (status & ERR_FATAL)
-                               fatal++;
+                       /* look for every post_section_parser for the previous section name */
+                       list_for_each_entry(psect, &sections, list) {
+                               if (strcmp(pcs->section_name, psect->section_name) == 0 &&
+                                               psect->post_section_parser) {
 
-                       if (err_code & ERR_ABORT)
-                               goto err;
+                                       /* don't call post_section_parser in MODE_DISCOVERY */
+                                       if (global.mode & MODE_DISCOVERY)
+                                               goto section_parser;
+
+                                       status = psect->post_section_parser();
+                                       err_code |= status;
+                                       if (status & ERR_FATAL)
+                                               fatal++;
+
+                                       if (err_code & ERR_ABORT)
+                                               goto err;
+                               }
+                       }
                }
                pcs = NULL;
 
@@ -2625,10 +2637,19 @@ section_parser:
        ha_free(&global.cfg_curr_section);
 
        /* call post_section_parser of the last section when there is no more lines */
-       if (cs && cs->post_section_parser) {
+       if (cs) {
+               struct cfg_section *psect;
+
                /* don't call post_section_parser in MODE_DISCOVERY */
-               if (!(global.mode & MODE_DISCOVERY))
-                       err_code |= cs->post_section_parser();
+               if (!(global.mode & MODE_DISCOVERY)) {
+                       list_for_each_entry(psect, &sections, list) {
+                               if (strcmp(cs->section_name, psect->section_name) == 0 &&
+                                    psect->post_section_parser) {
+
+                                       err_code |= cs->post_section_parser();
+                               }
+                       }
+               }
        }
 
        if (nested_cond_lvl) {
@@ -4722,10 +4743,13 @@ int cfg_register_section(char *section_name,
 {
        struct cfg_section *cs;
 
-       list_for_each_entry(cs, &sections, list) {
-               if (strcmp(cs->section_name, section_name) == 0) {
-                       ha_alert("register section '%s': already registered.\n", section_name);
-                       return 0;
+       if (section_parser) {
+               /* only checks if we register a section parser, not a post section callback */
+               list_for_each_entry(cs, &sections, list) {
+                       if (strcmp(cs->section_name, section_name) == 0 && cs->section_parser) {
+                               ha_alert("register section '%s': already registered.\n", section_name);
+                               return 0;
+                       }
                }
        }