[exim-cvs] linked-lists for driver info structs

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] linked-lists for driver info structs
Gitweb: https://git.exim.org/exim.git/commitdiff/bec360ab3e1060187724480d109884e56f912b0a
Commit:     bec360ab3e1060187724480d109884e56f912b0a
Parent:     4d10782e6dc0928b4b9ac6f3980f71f3b05383f6
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Mon Aug 12 16:08:33 2024 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Wed Aug 14 09:01:27 2024 +0100


    linked-lists for driver info structs
---
 src/src/drtables.c  | 20 +++++++++++++-----
 src/src/exim.c      |  3 ++-
 src/src/globals.h   |  9 +++++---
 src/src/readconf.c  | 61 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 src/src/route.c     | 24 +++++++++++++++++----
 src/src/structs.h   |  2 ++
 src/src/transport.c | 25 ++++++++++++++++------
 test/confs/0000     |  2 ++
 8 files changed, 122 insertions(+), 24 deletions(-)


diff --git a/src/src/drtables.c b/src/src/drtables.c
index 19a70ab8b..2782323c3 100644
--- a/src/src/drtables.c
+++ b/src/src/drtables.c
@@ -61,7 +61,8 @@ set to NULL for those that are not compiled into the binary. */
#include "auths/tls.h"
#endif

-auth_info auths_available[] = {
+auth_info * auths_available_newlist = NULL;
+auth_info auths_available_oldarray[] = {

/* Checking by an expansion condition on plain text */

@@ -282,9 +283,11 @@ exim binary. */
#endif


+router_info * routers_available_newlist = NULL;
+
/* Now set up the structures, terminated by an entry with a null name. */

-router_info routers_available[] = {
+router_info routers_available_oldarray[] = {
 #ifdef ROUTER_ACCEPT
   {
   .drinfo = {
@@ -369,6 +372,9 @@ router_info routers_available[] = {
     .options_block =    &queryprogram_router_option_defaults,
     .options_len =    sizeof(queryprogram_router_options_block),
     .init =        queryprogram_router_init,
+# if ROUTER_QUIRYPROGRAM==2
+    .dynamic =        TRUE,
+# endif
     },
   .code =        queryprogram_router_entry,
   .tidyup =        NULL,     /* no tidyup entry */
@@ -395,7 +401,8 @@ router_info routers_available[] = {




-transport_info transports_available[] = {
+transport_info * transports_available_newlist = NULL;
+transport_info transports_available_oldarray[] = {
 #ifdef TRANSPORT_APPENDFILE
   {
   .drinfo = {
@@ -501,7 +508,9 @@ gstring *
 auth_show_supported(gstring * g)
 {
 g = string_cat(g, US"Authenticators:");
-for (auth_info * ai = auths_available; ai->drinfo.driver_name[0]; ai++)
+/*XXX these run off the static list as we want them before the conf is read */
+/*XXX Could possibly check for dyn flag + file presence */
+for (auth_info * ai = auths_available_oldarray; ai->drinfo.driver_name[0]; ai++)
            g = string_fmt_append(g, " %s", ai->drinfo.driver_name);
 return string_cat(g, US"\n");
 }
@@ -510,7 +519,8 @@ gstring *
 route_show_supported(gstring * g)
 {
 g = string_cat(g, US"Routers:");
-for (router_info * rr = routers_available; rr->drinfo.driver_name[0]; rr++)
+/*XXX these run off the static list as we want them before the conf is read */
+for (router_info * rr = routers_available_oldarray; rr->drinfo.driver_name[0]; rr++)
            g = string_fmt_append(g, " %s", rr->drinfo.driver_name);
 return string_cat(g, US"\n");
 }
diff --git a/src/src/exim.c b/src/src/exim.c
index d86625f92..8eb602a17 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -1382,7 +1382,8 @@ g = show_db_version(g);
 show_string(is_stdout, g);
 g = NULL;


-for (auth_info * ai= auths_available; *ai->drinfo.driver_name != '\0'; ai++)
+//for (auth_info * ai= auths_available; *ai->drinfo.driver_name != '\0'; ai++)
+for (auth_info * ai = auths_available_newlist; ai; ai = (auth_info *)ai->drinfo.next)
   if (ai->version_report)
     g = (*ai->version_report)(g);


diff --git a/src/src/globals.h b/src/src/globals.h
index 8e75f7f93..817c940ed 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -374,7 +374,8 @@ extern uschar *authenticated_sender;   /* From AUTH on MAIL */
 extern BOOL    authentication_failed;  /* TRUE if AUTH was tried and failed */
 extern uschar *authenticator_name;     /* for debug and error messages */
 extern uschar *auth_advertise_hosts;   /* Only advertise to these */
-extern auth_info auths_available[];    /* Vector of available auth mechanisms */
+extern auth_info auths_available_oldarray[];    /* Vector of available auth mechanisms */
+extern auth_info * auths_available_newlist;
 extern auth_instance *auths;           /* Chain of instantiated auths */
 extern auth_instance auth_defaults;    /* Default values */
 extern uschar *auth_defer_msg;         /* Error message for log */
@@ -946,7 +947,8 @@ extern int     rfc1413_query_timeout;  /* Timeout on RFC 1413 calls */
 /* extern BOOL    rfc821_domains;  */       /* If set, syntax is 821, not 822 => being abolished */
 extern uid_t   root_gid;               /* The gid for root */
 extern uid_t   root_uid;               /* The uid for root */
-extern router_info routers_available[];/* Vector of available routers */
+extern router_info routers_available_oldarray[];/* Vector of available routers */
+extern router_info *routers_available_newlist;
 extern router_instance *routers;       /* Chain of instantiated routers */
 extern router_instance router_defaults;/* Default values */
 extern const uschar *router_name;      /* Name of router last started */
@@ -1110,7 +1112,8 @@ extern int     transport_newlines;     /* Accurate count of number of newline ch
 extern const uschar **transport_filter_argv; /* For on-the-fly filtering */
 extern int     transport_filter_timeout; /* Timeout for same */


-extern transport_info transports_available[]; /* Vector of available transports */
+extern transport_info transports_available_oldarray[]; /* Vector of available transports */
+extern transport_info * transports_available_newlist;
extern transport_instance *transports; /* Chain of instantiated transports */
extern transport_instance transport_defaults; /* Default values */

diff --git a/src/src/readconf.c b/src/src/readconf.c
index d8f9a53e4..f22ff700e 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -435,9 +435,13 @@ uschar buf[EXIM_DRIVERNAME_MAX];
options_from_list(optionlist_auths, optionlist_auths_size,
US"AUTHENTICATORS", NULL);

+#ifdef old
 for (struct auth_info * ai = auths_available; ai->drinfo.driver_name[0]; ai++)
+#endif
+for (driver_info * di = (driver_info *)auths_available_newlist; di; di = di->next)
   {
-  driver_info * di = &ai->drinfo;
+  auth_info * ai = (auth_info *)di;
+
   spf(buf, sizeof(buf), US"_DRIVER_AUTHENTICATOR_%T", di->driver_name);
   builtin_macro_create(buf);
   options_from_list(di->options, (unsigned)*di->options_count,
@@ -3718,9 +3722,42 @@ static driver_info *
 init_driver(driver_instance * d, driver_info * drivers_available,
   int size_of_info, const uschar * class)
 {
-/*XXX this is walking the old-array */
-for (driver_info * dd = drivers_available; *dd->driver_name;
+/*XXX if dynamic, the _info entry will be here but code may or may not
+be loaded.  How to tell?  What's the entry point?  init call?
+Currently that is IN the _info entry.
+
+For lookups it does it by pulling the info entry out of the dlopen()d
+file (for dynamic) or direct from the lookup .o file (for static).
+It builds a linked-list with those two classes,
+then an array sorted by (? name) and discards the list.
+The array is the _info list.
+
+We'd rather not have to do two passes over the config file(s) section.
+With the number of drivers I see no point in sorting,
+so we could stick with a one-pass build of an _info linked-list.
+This does mean converting any code using the current array.
+
+DONE:
+Rename the array to old.  For now, walk it once and build a linked-list.
+Find and convert all the uses,
+
+Move all the element defns to driver code files.
+Change the init/build to scan them.
+
+Move the scan to the place-of-use reading the config,
+only load if not already on linked-list.
+
+Add the build-dynamic wrapper,
+and scan from dlopen if marked dynamic.
+*/
+
+#ifdef old
+/*XXX walk the old array */
+for (driver_info * dd = drivers_available; dd->driver_name[0] != 0;
      dd = (driver_info *)((US dd) + size_of_info))
+#endif
+
+for (driver_info * dd = drivers_available; dd; dd = dd->next)
   if (Ustrcmp(d->driver_name, dd->driver_name) == 0)
     {
     int len = dd->options_len;
@@ -3784,7 +3821,7 @@ Returns:                     nothing
 void
 readconf_driver_init(
   driver_instance ** anchor,
-  driver_info * drivers_available,
+  driver_info * drivers_available,    /*XXX now list not array */
   int size_of_info,
   void * instance_default,
   int  instance_size,
@@ -4245,8 +4282,21 @@ auths_init(void)
 int nauths = 0;
 #endif


+/*XXX temp loop just copying the old array to build the new list.
+Will replace with haul from either static build file or dyn module
+done by readconf_driver_init() */
+for (auth_info * tblent = auths_available_oldarray;
+    *tblent->drinfo.driver_name; tblent++)
+  {
+  driver_info * listent = store_get(sizeof(auth_info), tblent);
+  memcpy(listent, tblent, sizeof(auth_info));
+  listent->next = (driver_info *)auths_available_newlist;
+  auths_available_newlist = (auth_info *)listent;
+  }
+
+
 readconf_driver_init((driver_instance **)&auths,      /* chain anchor */
-  (driver_info *)auths_available,    /* available drivers */
+  (driver_info *)auths_available_newlist,    /* available drivers */
   sizeof(auth_info),                 /* size of info block */
   &auth_defaults,                    /* default values for generic options */
   sizeof(auth_instance),             /* size of instance block */
@@ -4430,6 +4480,7 @@ while(next_section[0] != 0)
   int mid = last/2;
   int n = Ustrlen(next_section);


+ READCONF_DEBUG fprintf(stderr, "%s: %s\n", __FUNCTION__, next_section);
if (tolower(next_section[n-1]) != 's') Ustrcpy(next_section+n, US"s");

for (;;)
diff --git a/src/src/route.c b/src/src/route.c
index 0c7de556d..c0cc1fee9 100644
--- a/src/src/route.c
+++ b/src/src/route.c
@@ -159,12 +159,15 @@ uschar buf[64];

options_from_list(optionlist_routers, nelem(optionlist_routers), US"ROUTERS", NULL);

+#ifdef old
 for (router_info * ri = routers_available; ri->drinfo.driver_name[0]; ri++)
+#endif
+for (driver_info * di = (driver_info *)routers_available_newlist; di; di = di->next)
   {
-  spf(buf, sizeof(buf), US"_DRIVER_ROUTER_%T", ri->drinfo.driver_name);
+  spf(buf, sizeof(buf), US"_DRIVER_ROUTER_%T", di->driver_name);
   builtin_macro_create(buf);
-  options_from_list(ri->drinfo.options, (unsigned)*ri->drinfo.options_count,
-            US"ROUTER", ri->drinfo.driver_name);
+  options_from_list(di->options, (unsigned)*di->options_count,
+            US"ROUTER", di->driver_name);
   }
 }


@@ -227,8 +230,21 @@ function. */
 void
 route_init(void)
 {
+/*XXX temp loop just copying the old array to build the new list.
+Will replace with haul from either static build file or dyn module
+done by readconf_driver_init() */
+
+for (router_info * tblent = routers_available_oldarray;
+    *tblent->drinfo.driver_name; tblent++)
+  {
+  driver_info * listent = store_get(sizeof(router_info), tblent);
+  memcpy(listent, tblent, sizeof(router_info));
+  listent->next = (driver_info *)routers_available_newlist;
+  routers_available_newlist = (router_info *)listent;
+  }
+
 readconf_driver_init((driver_instance **)&routers,     /* chain anchor */
-  (driver_info *)routers_available,   /* available drivers */
+  (driver_info *)routers_available_newlist,   /* available drivers */
   sizeof(router_info),                /* size of info blocks */
   &router_defaults,                   /* default values for generic options */
   sizeof(router_instance),            /* size of instance block */
diff --git a/src/src/structs.h b/src/src/structs.h
index ee312a44e..392a4a08c 100644
--- a/src/src/structs.h
+++ b/src/src/structs.h
@@ -141,6 +141,7 @@ typedef struct driver_instance {
 } driver_instance;


 typedef struct driver_info {
+  struct driver_info * next;
   uschar *driver_name;            /* Name of driver */


   optionlist *options;            /* Table of private options names */
@@ -149,6 +150,7 @@ typedef struct driver_info {
   int     options_len;            /* Length of same in bytes */
   void  (*init)(                  /* Initialization entry point */
       struct driver_instance *);
+  BOOL      dynamic;          /* Built as dynamic-load module */
 } driver_info;



diff --git a/src/src/transport.c b/src/src/transport.c
index febe7c117..e92541bbf 100644
--- a/src/src/transport.c
+++ b/src/src/transport.c
@@ -102,12 +102,13 @@ uschar buf[64];

options_from_list(optionlist_transports, nelem(optionlist_transports), US"TRANSPORTS", NULL);

-for (transport_info * ti= transports_available; ti->drinfo.driver_name[0]; ti++)
+//for (transport_info * ti= transports_available; ti->drinfo.driver_name[0]; ti++)
+for (driver_info * di= (driver_info *)transports_available_newlist; di; di = di->next)
   {
-  spf(buf, sizeof(buf), US"_DRIVER_TRANSPORT_%T", ti->drinfo.driver_name);
+  spf(buf, sizeof(buf), US"_DRIVER_TRANSPORT_%T", di->driver_name);
   builtin_macro_create(buf);
-  options_from_list(ti->drinfo.options, (unsigned)*ti->drinfo.options_count,
-            US"TRANSPORT", ti->drinfo.driver_name);
+  options_from_list(di->options, (unsigned)*di->options_count,
+            US"TRANSPORT", di->driver_name);
   }
 }


@@ -145,10 +146,22 @@ the work. */
 void
 transport_init(void)
 {
+/*XXX temp loop just copying the old array to build the new list.
+Will replace with haul from either static build file or dyn module
+done by readconf_driver_init() */
+for (transport_info * tblent = transports_available_oldarray;
+    *tblent->drinfo.driver_name; tblent++)
+  {
+  driver_info * listent = store_get(sizeof(transport_info), tblent);
+  memcpy(listent, tblent, sizeof(transport_info));
+  listent->next = (driver_info *)transports_available_newlist;
+  transports_available_newlist = (transport_info *)listent;
+  }
+
 readconf_driver_init((driver_instance **)&transports,     /* chain anchor */
-  (driver_info *)transports_available,   /* available drivers */
+  (driver_info *)transports_available_newlist,   /* available drivers */
   sizeof(transport_info),                /* size of info block */
-  &transport_defaults,                   /* default values for generic options*/
+  &transport_defaults,                   /* default values for generic options */
   sizeof(transport_instance),            /* size of instance block */
   optionlist_transports,                 /* generic options */
   optionlist_transports_size,
diff --git a/test/confs/0000 b/test/confs/0000
index 12c91fda1..795701bd7 100644
--- a/test/confs/0000
+++ b/test/confs/0000
@@ -10,4 +10,6 @@ gecos_name = CALLER_NAME
 tls_advertise_hosts =
 keep_environment =


+begin routers
+
# End

--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/