mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-10-14 12:35:11 +02:00
- auth-load-thread, add num auth transfers and wait_transfer list.
This commit is contained in:
@@ -880,6 +880,15 @@ struct auth_load_general_info* auth_load_info_create(void)
|
||||
lock_protect(&auth_load_info->lock,
|
||||
&auth_load_info->num_auth_load_threads,
|
||||
sizeof(auth_load_info->num_auth_load_threads));
|
||||
lock_protect(&auth_load_info->lock,
|
||||
&auth_load_info->num_auth_transfers,
|
||||
sizeof(auth_load_info->num_auth_transfers));
|
||||
lock_protect(&auth_load_info->lock,
|
||||
&auth_load_info->wait_transfer_list,
|
||||
sizeof(auth_load_info->wait_transfer_list));
|
||||
lock_protect(&auth_load_info->lock,
|
||||
&auth_load_info->wait_transfer_last,
|
||||
sizeof(auth_load_info->wait_transfer_last));
|
||||
return auth_load_info;
|
||||
}
|
||||
|
||||
@@ -919,3 +928,122 @@ void auth_load_info_release_thread(struct module_env* env)
|
||||
}
|
||||
lock_basic_unlock(&auth_load_info->lock);
|
||||
}
|
||||
|
||||
int auth_load_info_grab_transfer_in_progress(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_transfers < cfg->auth_task_threads) {
|
||||
ret = 1;
|
||||
auth_load_info->num_auth_transfers++;
|
||||
}
|
||||
lock_basic_unlock(&auth_load_info->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void auth_load_info_release_transfer_in_progress(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_transfers == 0) {
|
||||
verbose(VERB_ALGO, "release of auth load transfer, but "
|
||||
"num_auth_transfers not > 0.");
|
||||
} else {
|
||||
auth_load_info->num_auth_transfers--;
|
||||
}
|
||||
lock_basic_unlock(&auth_load_info->lock);
|
||||
}
|
||||
|
||||
int
|
||||
xfr_transfer_grab_active(struct auth_xfer* xfr)
|
||||
{
|
||||
if(xfr->task_transfer->active_transfer) {
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
log_err("task transfer already active when activated transfer "
|
||||
"%s", zname);
|
||||
return 1;
|
||||
}
|
||||
xfr->task_transfer->active_transfer = 1;
|
||||
return auth_load_info_grab_transfer_in_progress(
|
||||
xfr->task_transfer->env);
|
||||
}
|
||||
|
||||
/** Schedule pick up of waiting transfers. */
|
||||
static void
|
||||
xfr_transfer_schedule_waiting_pickup(struct auth_xfer* xfr)
|
||||
{
|
||||
struct auth_load_general_info* auth_load_info =
|
||||
env->worker->daemon->auth_load_info;
|
||||
int waiting = 0;
|
||||
lock_basic_lock(&auth_load_info->lock);
|
||||
if(auth_load_info->wait_transfer_list)
|
||||
waiting = 1;
|
||||
lock_basic_unlock(&auth_load_info->lock);
|
||||
|
||||
if(waiting) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xfr_transfer_release_active(struct auth_xfer* xfr)
|
||||
{
|
||||
if(!xfr->task_transfer->active_transfer)
|
||||
return;
|
||||
auth_load_info_release_transfer_in_progress(xfr->task_transfer->env);
|
||||
xfr->task_transfer->active_transfer = 0;
|
||||
|
||||
/* Since a transfer is no longer in progress, see if there are
|
||||
* waiting transfers. If so, schedule them to get picked up. */
|
||||
xfr_transfer_schedule_waiting_pickup(xfr);
|
||||
}
|
||||
|
||||
void
|
||||
xfr_transfer_wait_active(struct auth_xfer* xfr)
|
||||
{
|
||||
struct auth_load_general_info* auth_load_info =
|
||||
xfr->task_transfer->env->worker->daemon->auth_load_info;
|
||||
if(xfr->task_transfer->on_wait_transfer_list)
|
||||
return;
|
||||
lock_basic_lock(&auth_load_info->lock);
|
||||
xfr->task_transfer->wait_transfer_prev =
|
||||
auth_load_info->wait_transfer_last;
|
||||
xfr->task_transfer->wait_transfer_next = NULL;
|
||||
if(auth_load_info->wait_transfer_last)
|
||||
auth_load_info->wait_transfer_last->task_transfer->
|
||||
wait_transfer_next = xfr;
|
||||
else auth_load_info->wait_transfer_list = xfr;
|
||||
auth_load_info->wait_transfer_last = xfr;
|
||||
lock_basic_unlock(&auth_load_info->lock);
|
||||
xfr->task_transfer->on_wait_transfer_list = 1;
|
||||
}
|
||||
|
||||
void
|
||||
xfr_transfer_remove_wait_transfer_list(struct auth_xfer* xfr)
|
||||
{
|
||||
struct auth_load_general_info* auth_load_info =
|
||||
xfr->task_transfer->env->worker->daemon->auth_load_info;
|
||||
if(!xfr->task_transfer->on_wait_transfer_list)
|
||||
return;
|
||||
lock_basic_lock(&auth_load_info->lock);
|
||||
if(xfr->task_transfer->wait_transfer_prev)
|
||||
xfr->task_transfer->wait_transfer_prev->task_transfer->
|
||||
wait_transfer_next =
|
||||
xfr->task_transfer->wait_transfer_next;
|
||||
else auth_load_info->wait_transfer_list =
|
||||
xfr->task_transfer->wait_transfer_next;
|
||||
if(xfr->task_transfer->wait_transfer_next)
|
||||
xfr->task_transfer->wait_transfer_next->task_transfer->
|
||||
wait_transfer_prev =
|
||||
xfr->task_transfer->wait_transfer_prev;
|
||||
else auth_load_info->wait_transfer_last =
|
||||
xfr->task_transfer->wait_transfer_prev;
|
||||
lock_basic_unlock(&auth_load_info->lock);
|
||||
xfr->task_transfer->wait_transfer_prev = NULL;
|
||||
xfr->task_transfer->wait_transfer_next = NULL;
|
||||
xfr->task_transfer->on_wait_transfer_list = 0;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,14 @@ struct auth_load_general_info {
|
||||
lock_basic_type lock;
|
||||
/** The number of active auth load threads. */
|
||||
int num_auth_load_threads;
|
||||
/** The number of active downloads, zone transfers in progress.
|
||||
* These are going to need an auth load thread when done. The counter
|
||||
* is decremented when the thread and transfer have completed. */
|
||||
int num_auth_transfers;
|
||||
/** The auth zone xfer transfer wait list */
|
||||
struct auth_xfer* wait_transfer_list;
|
||||
/** The last item of the wait_transfer list. */
|
||||
struct auth_xfer* wait_transfer_last;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -200,4 +208,43 @@ int auth_load_info_grab_thread(struct module_env* env);
|
||||
*/
|
||||
void auth_load_info_release_thread(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Grab a new transfer in progress, this is limited by the auth load count.
|
||||
* @param env: with auth_load_info with the active transfer number.
|
||||
* and config file, with configured maximum.
|
||||
* @return false on failure, like too many active, true if successful.
|
||||
*/
|
||||
int auth_load_info_grab_transfer_in_progress(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Release transfer from active count. It is done.
|
||||
* @param env: with auth_load_info with the active transfer count.
|
||||
*/
|
||||
void auth_load_info_release_transfer_in_progress(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Make transfer active in the in progress transfer count.
|
||||
* @param xfr: the xfr is in progress
|
||||
* @return false if not possible.
|
||||
*/
|
||||
int xfr_transfer_grab_active(struct auth_xfer* xfr);
|
||||
|
||||
/**
|
||||
* Release active transfer from in progress transfer count.
|
||||
* @param xfr: the xfr is no longer in progress.
|
||||
*/
|
||||
void xfr_transfer_release_active(struct auth_xfer* xfr);
|
||||
|
||||
/**
|
||||
* Add transfer to wait_transfer list. It can not become active right now.
|
||||
* @param xfr: the xfr is put on the wait_transfer list.
|
||||
*/
|
||||
void xfr_transfer_wait_active(struct auth_xfer* xfr);
|
||||
|
||||
/**
|
||||
* Remove xfr from wait_transfer list
|
||||
* @param xfr: the xfr is removed from the wait_transfer list.
|
||||
*/
|
||||
void xfr_transfer_remove_wait_transfer_list(struct auth_xfer* xfr);
|
||||
|
||||
#endif /* SERVICES_AUTHLOAD_H */
|
||||
|
||||
@@ -5716,6 +5716,8 @@ xfr_transfer_disown(struct auth_xfer* xfr)
|
||||
xfr->task_transfer->lookup_aaaa, xfr->dclass,
|
||||
xfr->task_transfer->env->mesh,
|
||||
&auth_xfer_transfer_lookup_callback, xfr);
|
||||
xfr_transfer_remove_wait_transfer_list(xfr);
|
||||
xfr_transfer_release_active(xfr);
|
||||
/* we don't own this item anymore */
|
||||
xfr->task_transfer->worker = NULL;
|
||||
xfr->task_transfer->env = NULL;
|
||||
@@ -5934,11 +5936,26 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
/* and set timeout on it */
|
||||
while(!xfr_transfer_end_of_list(xfr)) {
|
||||
xfr->task_transfer->master = xfr_transfer_current_master(xfr);
|
||||
if(xfr->task_transfer->master &&
|
||||
!xfr->task_transfer->master->allow_notify &&
|
||||
env->cfg->auth_task_threads != 0) {
|
||||
if(!xfr_transfer_grab_active(xfr)) {
|
||||
/* Can not get another transfer to have in
|
||||
* progress, wait to do this later, when other
|
||||
* transfers are done. */
|
||||
xfr_transfer_wait_active(xfr);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(xfr_transfer_init_fetch(xfr, env)) {
|
||||
/* successfully started, wait for callback */
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return;
|
||||
}
|
||||
xfr_transfer_remove_wait_transfer_list(xfr);
|
||||
xfr_transfer_release_active(xfr);
|
||||
|
||||
/* failed to fetch, next master */
|
||||
xfr_transfer_nextmaster(xfr);
|
||||
}
|
||||
@@ -6522,6 +6539,8 @@ process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env)
|
||||
}
|
||||
/* when done, delete data from list */
|
||||
auth_chunks_delete(xfr->task_transfer);
|
||||
xfr_transfer_remove_wait_transfer_list(xfr);
|
||||
xfr_transfer_release_active(xfr);
|
||||
xfr_process_transfer_failed(xfr, env, ixfr_fail);
|
||||
}
|
||||
|
||||
@@ -6674,6 +6693,8 @@ void xfr_process_load_end_transfer(struct auth_xfer* xfr,
|
||||
/* the zone is gone from the authzones. */
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
auth_chunks_delete(xfr->task_transfer);
|
||||
xfr_transfer_remove_wait_transfer_list(xfr);
|
||||
xfr_transfer_release_active(xfr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -6689,6 +6710,8 @@ void xfr_process_load_end_transfer(struct auth_xfer* xfr,
|
||||
}
|
||||
/* The transfer failed */
|
||||
verbose(VERB_ALGO, "xfr_process_load_end_transfer: failed");
|
||||
xfr_transfer_remove_wait_transfer_list(xfr);
|
||||
xfr_transfer_release_active(xfr);
|
||||
xfr_process_transfer_failed(xfr, env, ixfr_fail);
|
||||
}
|
||||
|
||||
@@ -6785,6 +6808,8 @@ auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
|
||||
auth_chunks_delete(xfr->task_transfer);
|
||||
comm_point_delete(xfr->task_transfer->cp);
|
||||
xfr->task_transfer->cp = NULL;
|
||||
xfr_transfer_remove_wait_transfer_list(xfr);
|
||||
xfr_transfer_release_active(xfr);
|
||||
if(gonextonfail)
|
||||
xfr_transfer_nextmaster(xfr);
|
||||
xfr_transfer_nexttarget_or_end(xfr, env);
|
||||
|
||||
@@ -405,6 +405,15 @@ struct auth_transfer {
|
||||
size_t chunks_total;
|
||||
/** start time of the transfer */
|
||||
struct timeval start_time;
|
||||
/** if the transfer is active and in the in progress count. */
|
||||
int active_transfer;
|
||||
/** if the transfer is on the wait_transfer list (it waits to
|
||||
* become active). */
|
||||
int on_wait_transfer_list;
|
||||
/** If on the wait_transfer list, the previous list item. */
|
||||
struct auth_xfer* wait_transfer_prev;
|
||||
/** If on the wait_transfer list, the next list item. */
|
||||
struct auth_xfer* wait_transfer_next;
|
||||
|
||||
/** list of upstream masters for this zone, from config */
|
||||
struct auth_master* masters;
|
||||
|
||||
Reference in New Issue
Block a user