#include "util/log.h"
#include "util/ub_event.h"
+/** Auth load notification to string, for descriptive purposes. */
+static const char*
+auth_load_notification_to_string(enum auth_load_notification_type status)
+{
+ switch(status) {
+ case auth_load_notification_exit:
+ return "auth_load_notification_exit";
+ default:
+ break;
+ }
+ return "unknown_auth_load_notification_value";
+}
+
/** delete chunks */
static void
auth_chunk_list_delete(struct auth_chunk* first)
static int
auth_load_thread_poll_for_quit(struct auth_load_thread* thr)
{
- (void)thr;
+ int inevent, loopexit = 0;
+ uint8_t cmd;
+ ssize_t ret;
+
+ if(thr->need_to_quit)
+ return 1;
+ /* Is there data? */
+ if(!sock_poll_timeout(thr->commpair[1], 0, 1, 0, &inevent)) {
+ log_err("auth_load_thread_poll_for_quit: poll failed");
+ return 0;
+ }
+ if(!inevent)
+ return 0;
+
+ /* Read the data */
+ while(1) {
+ if(++loopexit > 200) {
+ log_err("auth_load_thread_poll_for_quit: recv loops %s",
+ sock_strerror(errno));
+ return 0;
+ }
+ ret = recv(thr->commpair[1], ((char*)&cmd), sizeof(cmd), 0);
+ if(ret == -1) {
+ if(
+#ifndef USE_WINSOCK
+ errno == EINTR || errno == EAGAIN
+# ifdef EWOULDBLOCK
+ || errno == EWOULDBLOCK
+# endif
+#else
+ WSAGetLastError() == WSAEINTR ||
+ WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAEWOULDBLOCK
+#endif
+ )
+ continue; /* Try again. */
+ log_err("auth_load_thread_poll_for_quit: recv: %s",
+ sock_strerror(errno));
+ return 0;
+ } else if(ret == 0) {
+ log_err("auth_load_thread_poll_for_quit: recv: EOF");
+ return 0;
+ }
+ break;
+ }
+ if(cmd == auth_load_notification_exit) {
+ thr->need_to_quit = 1;
+ verbose(VERB_ALGO, "auth load: exit notification received");
+ return 1;
+ }
+ log_err("auth_load_thread_poll_for_quit: unknown notification status "
+ "received: %d %s", cmd, auth_load_notification_to_string(cmd));
return 0;
}
uint8_t recv_item;
ssize_t ret;
struct auth_xfer* xfr;
+ struct module_env* env;
+ int ixfr_fail;
log_assert(thr->commpair[0] >= 0);
ret = recv(thr->commpair[0], &recv_item, 1, 0);
return; /* Continue later. */
#ifdef USE_WINSOCK
if(WSAGetLastError() == WSAEWOULDBLOCK) {
- ub_winsock_tcp_wouldblock(fr->service_event,
+ ub_winsock_tcp_wouldblock(thr->service_event,
UB_EV_READ);
return; /* Continue later. */
}
}
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;
auth_load_thread_delete(thr);
- xfr_process_load_end_transfer(xfr, recv_item);
+ xfr_process_load_end_transfer(xfr, env, recv_item, ixfr_fail);
}
/** Attach worker to the auth load thread. */
return 1;
}
+/** task transfer, process the failure to process the zone transfer.
+ * It continues with the task transfer, possibly. */
+static void
+xfr_process_transfer_failed(struct auth_xfer* xfr, struct module_env* env,
+ int ixfr_fail)
+{
+ /* processing failed */
+ if(ixfr_fail) {
+ xfr->task_transfer->ixfr_fail = 1;
+ } else {
+ xfr_transfer_nextmaster(xfr);
+ }
+ xfr_transfer_nexttarget_or_end(xfr, env);
+}
+
+/** task transfer, process the success to process the zone transfer.
+ * It continues with the task probe, possibly, due to notify. Or nextprobe. */
+static void
+xfr_process_transfer_success(struct auth_xfer* xfr, struct module_env* env)
+{
+ /* we fetched the zone, move to wait task */
+ xfr_transfer_disown(xfr);
+
+ if(xfr->notify_received && (!xfr->notify_has_serial ||
+ (xfr->notify_has_serial &&
+ xfr_serial_means_update(xfr, xfr->notify_serial)))) {
+ uint32_t sr = xfr->notify_serial;
+ int has_sr = xfr->notify_has_serial;
+ /* we received a notify while probe/transfer was
+ * in progress. start a new probe and transfer */
+ xfr->notify_received = 0;
+ xfr->notify_has_serial = 0;
+ xfr->notify_serial = 0;
+ if(!xfr_start_probe(xfr, env, NULL)) {
+ /* if we couldn't start it, already in
+ * progress; restore notify serial,
+ * while xfr still locked */
+ xfr->notify_received = 1;
+ xfr->notify_has_serial = has_sr;
+ xfr->notify_serial = sr;
+ lock_basic_unlock(&xfr->lock);
+ }
+ return;
+ } else {
+ /* pick up the nextprobe task and wait (normail wait time) */
+ if(xfr->task_nextprobe->worker == NULL)
+ xfr_set_timeout(xfr, env, 0, 0);
+ }
+ lock_basic_unlock(&xfr->lock);
+}
+
/** task transfer. the list of data is complete. process it and if failed
* move to next master, if succeeded, end the task transfer */
static void
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. */
return;
}
} else if(xfr_process_chunk_list(xfr, env, &ixfr_fail)) {
/* it worked! */
auth_chunks_delete(xfr->task_transfer);
-
- /* we fetched the zone, move to wait task */
- xfr_transfer_disown(xfr);
-
- if(xfr->notify_received && (!xfr->notify_has_serial ||
- (xfr->notify_has_serial &&
- xfr_serial_means_update(xfr, xfr->notify_serial)))) {
- uint32_t sr = xfr->notify_serial;
- int has_sr = xfr->notify_has_serial;
- /* we received a notify while probe/transfer was
- * in progress. start a new probe and transfer */
- xfr->notify_received = 0;
- xfr->notify_has_serial = 0;
- xfr->notify_serial = 0;
- if(!xfr_start_probe(xfr, env, NULL)) {
- /* if we couldn't start it, already in
- * progress; restore notify serial,
- * while xfr still locked */
- xfr->notify_received = 1;
- xfr->notify_has_serial = has_sr;
- xfr->notify_serial = sr;
- lock_basic_unlock(&xfr->lock);
- }
- return;
- } else {
- /* pick up the nextprobe task and wait (normail wait time) */
- if(xfr->task_nextprobe->worker == NULL)
- xfr_set_timeout(xfr, env, 0, 0);
- }
- lock_basic_unlock(&xfr->lock);
+ xfr_process_transfer_success(xfr, env);
return;
}
- /* processing failed */
/* when done, delete data from list */
auth_chunks_delete(xfr->task_transfer);
- if(ixfr_fail) {
- xfr->task_transfer->ixfr_fail = 1;
- } else {
- xfr_transfer_nextmaster(xfr);
- }
- xfr_transfer_nexttarget_or_end(xfr, env);
+ xfr_process_transfer_failed(xfr, env, ixfr_fail);
}
-void xfr_process_load_end_transfer(struct auth_xfer* xfr, uint8_t status)
+void xfr_process_load_end_transfer(struct auth_xfer* xfr,
+ struct module_env* env, uint8_t status, int ixfr_fail)
{
if(status) {
/* it worked! */
- /* we fetched the zone, move to wait task */
- xfr_transfer_disown(xfr);
-
- lock_basic_unlock(&xfr->lock);
+ xfr_process_transfer_success(xfr, env);
return;
}
/* The transfer failed */
- lock_basic_unlock(&xfr->lock);
+ xfr_process_transfer_failed(xfr, env, ixfr_fail);
}
/** callback for the task_transfer timer */