From 61d6c0e766556f1613c1c830061f747280601655 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Tue, 7 Jul 2026 17:21:16 +0200 Subject: [PATCH] - auth-load-thread, implement active thread counter for auth load threads. --- daemon/daemon.c | 13 ++++++++++ daemon/daemon.h | 3 +++ services/authload.c | 58 +++++++++++++++++++++++++++++++++++++++++++-- services/authload.h | 36 ++++++++++++++++++++++++++++ services/authzone.c | 23 +++++++++++------- 5 files changed, 122 insertions(+), 11 deletions(-) diff --git a/daemon/daemon.c b/daemon/daemon.c index 80cb37ff7..aa90535f7 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -85,6 +85,7 @@ #include "services/view.h" #include "services/modstack.h" #include "services/authzone.h" +#include "services/authload.h" #include "util/module.h" #include "util/random.h" #include "util/tube.h" @@ -589,6 +590,17 @@ daemon_init(void) free(daemon); return NULL; } + if(!(daemon->auth_load_info = auth_load_info_create())) { + edns_strings_delete(daemon->env->edns_strings); + auth_zones_delete(daemon->env->auth_zones); + acl_list_delete(daemon->acl_interface); + acl_list_delete(daemon->acl); + tcl_list_delete(daemon->tcl); + edns_known_options_delete(daemon->env); + free(daemon->env); + free(daemon); + return NULL; + } return daemon; } @@ -1258,6 +1270,7 @@ daemon_delete(struct daemon* daemon) edns_strings_delete(daemon->env->edns_strings); auth_zones_delete(daemon->env->auth_zones); } + auth_load_info_delete(daemon->auth_load_info); ub_randfree(daemon->rand); alloc_clear(&daemon->superalloc); acl_list_delete(daemon->acl); diff --git a/daemon/daemon.h b/daemon/daemon.h index 20386d7fc..9965ed558 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -62,6 +62,7 @@ struct doq_table; struct cookie_secrets; struct fast_reload_thread; struct fast_reload_printq; +struct auth_load_general_info; #include "dnstap/dnstap_config.h" #ifdef USE_DNSTAP @@ -188,6 +189,8 @@ struct daemon { int fast_reload_tcl_has_changes; /** config file name */ char* cfgfile; + /** Auth load threads, the number of active threads. */ + struct auth_load_general_info* auth_load_info; }; /** diff --git a/services/authload.c b/services/authload.c index 6ce62853b..01ccd9430 100644 --- a/services/authload.c +++ b/services/authload.c @@ -672,7 +672,7 @@ worker_auth_load_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), ssize_t ret; struct auth_xfer* xfr; struct auth_chunk* chunk_list; - struct module_env* env; + struct module_env* env = &thr->task->worker->env; int ixfr_fail; log_assert(thr->commpair[0] >= 0); @@ -719,11 +719,11 @@ worker_auth_load_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), lock_rw_unlock(&thr->task->worker->env.auth_zones->lock); verbose(VERB_ALGO, "auth load: xfr is gone"); auth_load_thread_delete(thr); + auth_load_info_release_thread(env); return; } lock_basic_lock(&xfr->lock); lock_rw_unlock(&thr->task->worker->env.auth_zones->lock); - env = &thr->task->worker->env; ixfr_fail = thr->task->ixfr_fail; if(thr->task->on_http) { chunk_list = thr->task->chunks_first; @@ -734,6 +734,7 @@ worker_auth_load_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), chunk_list = NULL; } auth_load_thread_delete(thr); + auth_load_info_release_thread(env); xfr_process_load_end_transfer(xfr, env, recv_item, ixfr_fail, chunk_list); } @@ -815,3 +816,56 @@ int auth_load_add_task_xfr(struct auth_xfer* xfr, struct worker* worker) /* Make wait item */ return 0; } + +struct auth_load_general_info* auth_load_info_create(void) +{ + struct auth_load_general_info* auth_load_info = + (struct auth_load_general_info*)calloc(1, + sizeof(*auth_load_info)); + if(!auth_load_info) { + log_err("malloc failure"); + return NULL; + } + lock_basic_init(&auth_load_info->lock); + lock_protect(&auth_load_info->lock, + &auth_load_info->num_auth_load_threads, + sizeof(auth_load_info->num_auth_load_threads)); + return auth_load_info; +} + +void auth_load_info_delete(struct auth_load_general_info* auth_load_info) +{ + if(!auth_load_info) + return; + lock_basic_destroy(&auth_load_info->lock); + free(auth_load_info); +} + +int auth_load_info_grab_thread(struct module_env* env) +{ + struct auth_load_general_info* auth_load_info = + env->worker->daemon->auth_load_info; + struct config_file* cfg = env->cfg; + int ret = 0; + lock_basic_lock(&auth_load_info->lock); + if(auth_load_info->num_auth_load_threads < cfg->auth_task_threads) { + ret = 1; + auth_load_info->num_auth_load_threads++; + } + lock_basic_unlock(&auth_load_info->lock); + return ret; +} + +void auth_load_info_release_thread(struct module_env* env) +{ + struct auth_load_general_info* auth_load_info = + env->worker->daemon->auth_load_info; + lock_basic_lock(&auth_load_info->lock); + if(auth_load_info->num_auth_load_threads == 0) { + verbose(VERB_ALGO, "release of auth load thread, but " + "num_auth_load_threads not > 0."); + } else { + auth_load_info->num_auth_load_threads--; + } + lock_basic_unlock(&auth_load_info->lock); +} diff --git a/services/authload.h b/services/authload.h index 7b884f933..718cb5d0d 100644 --- a/services/authload.h +++ b/services/authload.h @@ -49,6 +49,16 @@ struct auth_xfer; struct module_env; struct auth_load_task; +/** + * General information for auth load threads. The number of active threads. + */ +struct auth_load_general_info { + /** lock on this structure */ + lock_basic_type lock; + /** The number of active auth load threads. */ + int num_auth_load_threads; +}; + /** * The types of notifications that the auth load thread sends around. */ @@ -159,4 +169,30 @@ int auth_load_add_task_xfr(struct auth_xfer* xfr, struct worker* worker); /** See if there is a quit signal, true if so. */ int auth_load_thread_poll_for_quit(struct auth_load_thread* thr); +/** + * Create auth load info structure. + * @return NULL on failure. + */ +struct auth_load_general_info* auth_load_info_create(void); + +/** + * Delete auth load info structure. + * @param auth_load_info: to delete. + */ +void auth_load_info_delete(struct auth_load_general_info* auth_load_info); + +/** + * Grab a new thread from the auth load count. + * @param env: with auth_load_info with the active thread count. + * and config file, with configured maximum. + * @return false on failure, like too many active, true if successful. + */ +int auth_load_info_grab_thread(struct module_env* env); + +/** + * Release thread from auth load count. It is done. + * @param env: with auth_load_info with the active thread count. + */ +void auth_load_info_release_thread(struct module_env* env); + #endif /* SERVICES_AUTHLOAD_H */ diff --git a/services/authzone.c b/services/authzone.c index 64fc39100..503347440 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -6391,15 +6391,20 @@ static void process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env) { int ixfr_fail = 0; - if(env->cfg->auth_task_threads != 0 /* auth load enabled */ ) { - /* Create auth load thread task to process the data. */ - if(auth_load_add_task_xfr(xfr, env->worker)) { - /* Task is created, wait for it to be done. The worker - * is signalled with the result. */ - /* When it is done, the xfr_process_load_end_transfer - * routine is called. */ - lock_basic_unlock(&xfr->lock); - return; + if(env->cfg->auth_task_threads != 0 /* auth load enabled */) { + if(auth_load_info_grab_thread(env)) { + /* Create auth load thread task to process the data. */ + if(auth_load_add_task_xfr(xfr, env->worker)) { + /* Task is created, wait for it to be done. The worker + * is signalled with the result. */ + /* When it is done, the xfr_process_load_end_transfer + * routine is called. */ + lock_basic_unlock(&xfr->lock); + return; + } + auth_load_info_release_thread(env); + } else { + verbose(VERB_ALGO, "Auth load threads at capacity, not creating a new thread"); } } else if(xfr_process_chunk_list(xfr, env, &ixfr_fail)) { /* it worked! */ -- 2.47.3