#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"
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;
}
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);
struct cookie_secrets;
struct fast_reload_thread;
struct fast_reload_printq;
+struct auth_load_general_info;
#include "dnstap/dnstap_config.h"
#ifdef USE_DNSTAP
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;
};
/**
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);
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;
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);
}
/* 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);
+}
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.
*/
/** 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 */
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! */