Пример #1
0
/**
 * Convert task to string.
 *
 */
char*
task2str(task_type* task, char* buftask)
{
    char* strtime = NULL;
    char* strtask = NULL;

    if (task) {
        strtime = ctime(&task->when);
        if (strtime) {
            strtime[strlen(strtime)-1] = '\0';
        }
        if (buftask) {
            (void)snprintf(buftask, ODS_SE_MAXLINE, "%s %s I will %s zone %s"
                "\n", task->flush?"Flush":"On", strtime?strtime:"(null)",
                task_what2str(task->what), task_who2str(task));
            return buftask;
        } else {
            strtask = (char*) calloc(ODS_SE_MAXLINE, sizeof(char));
            snprintf(strtask, ODS_SE_MAXLINE, "%s %s I will %s zone %s\n",
                task->flush?"Flush":"On", strtime?strtime:"(null)",
                task_what2str(task->what), task_who2str(task));
            return strtask;
        }
    }
    return NULL;
}
Пример #2
0
/**
 * Log task.
 *
 */
void
task_log(task_type* task)
{
    char* strtime = NULL;

    if (task) {
        strtime = ctime(&task->when);
        if (strtime) {
            strtime[strlen(strtime)-1] = '\0';
        }
        ods_log_debug("[%s] %s %s I will %s zone %s", task_str,
            task->flush?"Flush":"On", strtime?strtime:"(null)",
            task_what2str(task->what), task_who2str(task));
    }
    return;
}
Пример #3
0
/**
 * Print task.
 *
 */
void
task_print(FILE* out, task_type* task)
{
    char* strtime = NULL;

    if (out && task) {
        strtime = ctime(&task->when);
        if (strtime) {
            strtime[strlen(strtime)-1] = '\0';
        }
        fprintf(out, "%s %s I will %s zone %s\n",
            task->flush?"Flush":"On", strtime?strtime:"(null)",
            task_what2str(task->what), task_who2str(task));
    }
    return;
}
Пример #4
0
/**
 * Perform task.
 *
 */
static void
worker_perform_task(worker_type* worker)
{
    task_type* task = NULL;

    if (!worker || !worker->task || !worker->task->context || !worker->engine) {
        return;
    }
    ods_log_assert(worker);
    ods_log_assert(worker->task);
    ods_log_assert(worker->task->context);

    task = (task_type*) worker->task;
    ods_log_debug("[worker[%i]]: perform task [%s] for %s at %u",
       worker->thread_num, task_what2str(task->what),
       task_who2str(task->who), (uint32_t) worker->clock_in);

	worker->task = task_perform(task);
}
Пример #5
0
/**
 * Perform task.
 *
 */
static void
worker_perform_task(worker_type* worker)
{
    task_type* task;

    if (!worker || !worker->task || !worker->task->context || !worker->engine) {
        return;
    }

    task = (task_type*) worker->task;
    ods_log_debug("[worker[%i]]: perform task [%s] for %s",
       worker->thread_num, task_what2str(task->what),
       task_who2str(task->who));

    /* We temporarily assign the database connection to the task so
     * it is accessable from the task function */
    task->dbconn = worker->dbconn;
    worker->task = task_perform(task);
    if (worker->task) task->dbconn = NULL;
}
Пример #6
0
/**
 * Perform task.
 *
 */
static void
worker_perform_task(worker_type* worker)
{
    engine_type* engine = NULL;
    zone_type* zone = NULL;
    task_type* task = NULL;
    task_id what = TASK_NONE;
    time_t when = 0;
    time_t never = (3600*24*365);
    ods_status status = ODS_STATUS_OK;
    int backup = 0;
    time_t start = 0;
    time_t end = 0;

    if (!worker || !worker->task || !worker->task->zone || !worker->engine) {
        return;
    }
    engine = (engine_type*) worker->engine;
    task = (task_type*) worker->task;
    zone = (zone_type*) worker->task->zone;
    ods_log_debug("[%s[%i]] perform task %s for zone %s at %u",
       worker2str(worker->type), worker->thread_num, task_what2str(task->what),
       task_who2str(task), (uint32_t) worker->clock_in);
    /* do what you have been told to do */
    switch (task->what) {
        case TASK_SIGNCONF:
            /* perform 'load signconf' task */
            worker_working_with(worker, TASK_SIGNCONF, TASK_READ,
                "configure", task_who2str(task), &what, &when);
            status = tools_signconf(zone);
            if (status == ODS_STATUS_UNCHANGED) {
                if (!zone->signconf->last_modified) {
                    ods_log_debug("[%s[%i]] no signconf.xml for zone %s yet",
                        worker2str(worker->type), worker->thread_num,
                        task_who2str(task));
                    status = ODS_STATUS_ERR;
                }
            }
            if (status == ODS_STATUS_UNCHANGED) {
                if (task->halted != TASK_NONE && task->halted != TASK_SIGNCONF) {
                    goto task_perform_continue;
                }
                status = ODS_STATUS_OK;
            } else if (status == ODS_STATUS_OK) {
                task->interrupt = TASK_NONE;
                task->halted = TASK_NONE;
            } else {
                if (task->halted == TASK_NONE) {
                    goto task_perform_fail;
                }
                goto task_perform_continue;
            }
            /* break; */
        case TASK_READ:
            /* perform 'read input adapter' task */
            worker_working_with(worker, TASK_READ, TASK_SIGN,
                "read", task_who2str(task), &what, &when);
            task->what = TASK_READ;
            if (!zone->signconf->last_modified) {
                ods_log_debug("[%s[%i]] no signconf.xml for zone %s yet",
                    worker2str(worker->type), worker->thread_num,
                    task_who2str(task));
                status = ODS_STATUS_ERR;
            } else {
                lhsm_check_connection((void*)engine);
                status = tools_input(zone);
            }

            if (status == ODS_STATUS_UNCHANGED) {
                ods_log_verbose("[%s[%i]] zone %s unsigned data not changed, "
                    "continue", worker2str(worker->type), worker->thread_num,
                    task_who2str(task));
                status = ODS_STATUS_OK;
            }
            if (status == ODS_STATUS_OK) {
                if (task->interrupt > TASK_SIGNCONF) {
                    task->interrupt = TASK_NONE;
                    task->halted = TASK_NONE;
                }
            } else {
                if (task->halted == TASK_NONE) {
                    goto task_perform_fail;
                }
                goto task_perform_continue;
            }
            /* break; */
        case TASK_SIGN:
            /* perform 'sign' task */
            worker_working_with(worker, TASK_SIGN, TASK_WRITE,
                "sign", task_who2str(task), &what, &when);
            task->what = TASK_SIGN;
            status = zone_update_serial(zone);
            if (status == ODS_STATUS_OK) {
                if (task->interrupt > TASK_SIGNCONF) {
                    task->interrupt = TASK_NONE;
                    task->halted = TASK_NONE;
                }
            } else {
                ods_log_error("[%s[%i]] unable to sign zone %s: "
                    "failed to increment serial",
                    worker2str(worker->type), worker->thread_num,
                    task_who2str(task));
                if (task->halted == TASK_NONE) {
                    goto task_perform_fail;
                }
                goto task_perform_continue;
            }

            /* start timer */
            start = time(NULL);
            if (zone->stats) {
                lock_basic_lock(&zone->stats->stats_lock);
                if (!zone->stats->start_time) {
                    zone->stats->start_time = start;
                }
                zone->stats->sig_count = 0;
                zone->stats->sig_soa_count = 0;
                zone->stats->sig_reuse = 0;
                zone->stats->sig_time = 0;
                lock_basic_unlock(&zone->stats->stats_lock);
            }
            /* check the HSM connection before queuing sign operations */
            lhsm_check_connection((void*)engine);
            /* queue menial, hard signing work */
            worker_queue_zone(worker, engine->signq, zone);
            ods_log_deeebug("[%s[%i]] wait until drudgers are finished "
                "signing zone %s", worker2str(worker->type), worker->thread_num,
                task_who2str(task));
            /* sleep until work is done */
            worker_sleep_unless(worker, 0);
            /* stop timer */
            end = time(NULL);
            status = worker_check_jobs(worker, task);
            worker_clear_jobs(worker);
            if (status == ODS_STATUS_OK && zone->stats) {
                lock_basic_lock(&zone->stats->stats_lock);
                zone->stats->sig_time = (end-start);
                lock_basic_unlock(&zone->stats->stats_lock);
            }
            if (status != ODS_STATUS_OK) {
                if (task->halted == TASK_NONE) {
                    goto task_perform_fail;
                }
                goto task_perform_continue;
            } else {
                if (task->interrupt > TASK_SIGNCONF) {
                    task->interrupt = TASK_NONE;
                    task->halted = TASK_NONE;
                }
            }
            /* break; */
        case TASK_WRITE:
            /* perform 'write to output adapter' task */
            worker_working_with(worker, TASK_WRITE, TASK_SIGN,
                "write", task_who2str(task), &what, &when);
            task->what = TASK_WRITE;
            status = tools_output(zone, engine);
            if (status == ODS_STATUS_OK) {
                if (task->interrupt > TASK_SIGNCONF) {
                    task->interrupt = TASK_NONE;
                    task->halted = TASK_NONE;
                }
            } else {
                /* clear signatures? */
                if (task->halted == TASK_NONE) {
                    goto task_perform_fail;
                }
                goto task_perform_continue;
            }
            zone->db->is_processed = 1;
            if (zone->signconf &&
                duration2time(zone->signconf->sig_resign_interval)) {
                what = TASK_SIGN;
                when = worker->clock_in +
                    duration2time(zone->signconf->sig_resign_interval);
            } else {
                ods_log_error("[%s[%i]] unable to retrieve resign interval "
                    "for zone %s: duration2time() failed",
                    worker2str(worker->type), worker->thread_num,
                    task_who2str(task));
                ods_log_info("[%s[%i]] defaulting to 1H resign interval for "
                    "zone %s", worker2str(worker->type), worker->thread_num,
                    task_who2str(task));
                what = TASK_SIGN;
                when = worker->clock_in + 3600;
            }
            backup = 1;
            break;
        case TASK_NONE:
            worker->working_with = TASK_NONE;
            /* no task */
            ods_log_warning("[%s[%i]] none task for zone %s",
                worker2str(worker->type), worker->thread_num,
                task_who2str(task));
            when = time_now() + never;
            break;
        default:
            worker->working_with = TASK_NONE;
            /* unknown task */
            ods_log_warning("[%s[%i]] unknown task, trying full sign zone %s",
                worker2str(worker->type), worker->thread_num,
                task_who2str(task));
            what = TASK_SIGNCONF;
            when = time_now();
            break;
    }
    /* no error */
    task->backoff = 0;
    if (task->interrupt != TASK_NONE && task->interrupt != what) {
        ods_log_debug("[%s[%i]] interrupt task %s for zone %s",
            worker2str(worker->type), worker->thread_num,
            task_what2str(what), task_who2str(task));
        task->halted = what;
        task->halted_when = when;
        task->what = task->interrupt;
        task->when = time_now();
    } else {
        ods_log_debug("[%s[%i]] next task %s for zone %s",
            worker2str(worker->type), worker->thread_num,
            task_what2str(what), task_who2str(task));
        task->what = what;
        task->when = when;
        task->interrupt = TASK_NONE;
        task->halted = TASK_NONE;
        task->halted_when = 0;
    }
    /* backup the last successful run */
    if (backup) {
        status = zone_backup2(zone);
        if (status != ODS_STATUS_OK) {
            ods_log_warning("[%s[%i]] unable to backup zone %s: %s",
            worker2str(worker->type), worker->thread_num,
            task_who2str(task), ods_status2str(status));
            /* just a warning */
            status = ODS_STATUS_OK;
        }
        backup = 0;
    }
    return;

task_perform_fail:
    if (status != ODS_STATUS_XFR_NOT_READY) {
        /* other statuses is critical, and we know it is not ODS_STATUS_OK */
        ods_log_crit("[%s[%i]] CRITICAL: failed to sign zone %s: %s",
            worker2str(worker->type), worker->thread_num,
            task_who2str(task), ods_status2str(status));
    }
    /* in case of failure, also mark zone processed (for single run usage) */
    zone->db->is_processed = 1;
    if (task->backoff) {
        task->backoff *= 2;
    } else {
        task->backoff = 60;
    }
    if (task->backoff > ODS_SE_MAX_BACKOFF) {
        task->backoff = ODS_SE_MAX_BACKOFF;
    }
    ods_log_info("[%s[%i]] backoff task %s for zone %s with %u seconds",
        worker2str(worker->type), worker->thread_num,
        task_what2str(task->what), task_who2str(task), task->backoff);
    task->when = time_now() + task->backoff;
    return;

task_perform_continue:
    ods_log_info("[%s[%i]] continue task %s for zone %s",
        worker2str(worker->type), worker->thread_num,
        task_what2str(task->halted), task_who2str(task));
    task->what = task->halted;
    task->when = task->halted_when;
    task->interrupt = TASK_NONE;
    task->halted = TASK_NONE;
    task->halted_when = 0;
    return;
}
Пример #7
0
ods_status
schedule_task(schedule_type* schedule, task_type* task)
{
    ldns_rbnode_t *node1, *node2;
    ods_status status;
    task_type* task2;

    if (!task) {
        ods_log_error("[%s] unable to schedule task: no task", schedule_str);
        return ODS_STATUS_ERR;
    }
    task->flush = 0;
    if (!schedule || !schedule->tasks) {
        ods_log_error("[%s] unable to schedule task: no schedule",
            schedule_str);
        return ODS_STATUS_ERR;
    }

    ods_log_debug("[%s] schedule task [%s] for %s", schedule_str,
        task_what2str(task->what), task_who2str(task->who));

    pthread_mutex_lock(&schedule->schedule_lock);
        status = ODS_STATUS_ERR;
        if ((node1 = task2node(task))) {
            if (ldns_rbtree_insert(schedule->tasks_by_name, node1)) {
                if ((node2 = task2node(task))) {
                    if(ldns_rbtree_insert(schedule->tasks, node2)) {
                        /* success inserting in two trees */
                        set_alarm(schedule);
                        status = ODS_STATUS_OK;
                    } else { /* insert in tasks tree failed */
                        ods_log_error("[%s] unable to schedule task [%s] for %s: "
                            " already present", schedule_str, task_what2str(task->what),
                            task_who2str(task->who));
                        /* this will free node1 */
                        free(ldns_rbtree_delete(schedule->tasks_by_name, node1));
                        free(node2);
                    }
                } else { /* could not alloc node2 */
                    /* this will free node1 */
                    free(ldns_rbtree_delete(schedule->tasks_by_name, node1));
                }

            } else {/* insert in name tree failed */
                free(node1);
                /**
                 * Task is already in tasks_by_name queue, so we must
                 * update it in tasks queue
                 */
                /* still in lock guaranteed to succeed. */
                node1 = ldns_rbtree_search(schedule->tasks_by_name, task);
                /* This copy of 'task' is referenced by both trees */
                task2 = (task_type*)node1->key;
                node1 = ldns_rbtree_delete(schedule->tasks, task2);
                if (task->when < task2->when)
                    task2->when = task->when;
                if (task2->context && task2->clean_context) {
                    task2->clean_context(task2);
                }
                task2->context = task->context;
                task2->clean_context = task->clean_context;
                task->context = NULL;
                task_cleanup(task);
                (void) ldns_rbtree_insert(schedule->tasks, node1);
                /* node1 now owned by tree */
                node1 = NULL;
                set_alarm(schedule);
                status = ODS_STATUS_OK;
            }
        } /* else {failure) */
    pthread_mutex_unlock(&schedule->schedule_lock);
    return status;
}