#include <netdb.h>
#include <stdio.h>
#include <syslog.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
// Path
const char* path;
+ // Parallel
+ unsigned long parallel;
+
// Flags
enum {
SECURE = (1 << 0),
unsigned int num_zones;
// How many transfers are running?
- unsigned int running;
+ unsigned long running;
+ unsigned long processed;
// Memory Context
isc_mem_t* memctx;
// Create the context
static ctx_t ctx = {
.log_level = LOG_INFO,
+ .parallel = 1,
.path = DEFAULT_PATH,
.transport = DNS_TRANSPORT_NONE,
};
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)
// Decrement the number of running zones
ctx.running--;
+ // Launch some more work
+ do_work();
+
// Terminate if we are all done
maybe_shutdown();
}
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;
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
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 },
};
}
static error_t parse(int key, char* arg, struct argp_state* state) {
+ char* e = NULL;
int r;
switch (key) {
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;