From e35c7f8c374d442a596835c62fe85d88722ced5c Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Thu, 21 May 2026 16:21:52 +0000 Subject: [PATCH] main: Add the option to run multiple zones at the same time By default, zone-sync is parsing one zone, then updating it, and so on. The main reason is that loading following zones could block the event loop which means that an ongoing transfer can time out for no aparent reason. Signed-off-by: Michael Tremer --- main.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/main.c b/main.c index 02a4db2..38c6991 100644 --- a/main.c +++ b/main.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -60,6 +61,9 @@ typedef struct ctx { // Path const char* path; + // Parallel + unsigned long parallel; + // Flags enum { SECURE = (1 << 0), @@ -81,7 +85,8 @@ typedef struct ctx { unsigned int num_zones; // How many transfers are running? - unsigned int running; + unsigned long running; + unsigned long processed; // Memory Context isc_mem_t* memctx; @@ -111,6 +116,7 @@ typedef struct ctx { // Create the context static ctx_t ctx = { .log_level = LOG_INFO, + .parallel = 1, .path = DEFAULT_PATH, .transport = DNS_TRANSPORT_NONE, }; @@ -239,6 +245,8 @@ static zone_ctx* find_zone(dns_zone_t* z) { return NULL; } +static int do_work(void); + static void maybe_shutdown(void) { // Don't shut down if there is something left running if (ctx.running) @@ -269,6 +277,9 @@ static void zone_done(dns_zone_t* z) { // Decrement the number of running zones ctx.running--; + // Launch some more work + do_work(); + // Terminate if we are all done maybe_shutdown(); } @@ -479,6 +490,22 @@ ERROR: zone_done(zone->zone); } +/* + Called to start some more work to do +*/ +static int do_work(void) { + while (!ctx.parallel || (ctx.running < ctx.parallel)) { + // We are done if all zones have been processed + if (ctx.processed >= ctx.num_zones) + break; + + // Launch the next zone + do_zone(&ctx.zones[ctx.processed++]); + } + + return 0; +} + static int configure_transports(void) { dns_transport_type_t type = DNS_TRANSPORT_TCP; dns_name_t* name = NULL; @@ -546,9 +573,8 @@ static void run_loop(void* data) { goto ERROR; } - // Process all zones - for (unsigned int i = 0; i < ctx.num_zones; i++) - do_zone(&ctx.zones[i]); + // Do some work + do_work(); ERROR: // Potentially shut down if there is nothing to do @@ -585,19 +611,21 @@ const char* argp_program_version = PACKAGE_VERSION; static const char* args_doc = "ZONE [ZONE...]"; enum { - OPT_DEBUG = 1, - OPT_QUIET = 2, - OPT_PATH = 3, - OPT_PRIMARY = 4, - OPT_SECURE = 5, + OPT_DEBUG = 1, + OPT_QUIET = 2, + OPT_PATH = 3, + OPT_PARALLEL = 4, + OPT_PRIMARY = 5, + OPT_SECURE = 6, }; static struct argp_option options[] = { - { "debug", OPT_DEBUG, NULL, 0, "Run in debug mode", 0 }, - { "quiet", OPT_QUIET, NULL, 0, "Run in quiet mode", 0 }, - { "path", OPT_PATH, "PATH", 1, "Path where to store the zones", 0 }, - { "primary", OPT_PRIMARY, "HOSTNAME", 1, "The hostname of the primary to fetch from", 0 }, - { "secure", OPT_SECURE , NULL, 0, "Use a secure transport to transfer the zone", 0 }, + { "debug", OPT_DEBUG, NULL, 0, "Run in debug mode", 0 }, + { "quiet", OPT_QUIET, NULL, 0, "Run in quiet mode", 0 }, + { "path", OPT_PATH, "PATH", 1, "Path where to store the zones", 0 }, + { "parallel", OPT_PARALLEL, "N", 1, "How many zones to process simultaneously", 0 }, + { "primary", OPT_PRIMARY, "HOSTNAME", 1, "The hostname of the primary to fetch from", 0 }, + { "secure", OPT_SECURE , NULL, 0, "Use a secure transport to transfer the zone", 0 }, { NULL }, }; @@ -644,6 +672,7 @@ ERROR: } static error_t parse(int key, char* arg, struct argp_state* state) { + char* e = NULL; int r; switch (key) { @@ -663,6 +692,17 @@ static error_t parse(int key, char* arg, struct argp_state* state) { ctx.primary = arg; break; + case OPT_PARALLEL: + // Parse the number + ctx.parallel = strtoul(arg, &e, 10); + + // Check if we could parse the number + if ((e && *e) || (ctx.parallel == ULONG_MAX)) { + argp_failure(state, EXIT_FAILURE, 0, "Could not parse number: %s", arg); + return ARGP_ERR_UNKNOWN; + } + break; + case OPT_SECURE: ctx.flags |= SECURE; break; -- 2.47.3