/**
 * Queue RRset for signing.
 *
 */
static void
worker_queue_rrset(worker_type* worker, fifoq_type* q, rrset_type* rrset)
{
    ods_status status = ODS_STATUS_UNCHANGED;
    int tries = 0;
    ods_log_assert(worker);
    ods_log_assert(q);
    ods_log_assert(rrset);

    lock_basic_lock(&q->q_lock);
    status = fifoq_push(q, (void*) rrset, worker, &tries);
    while (status == ODS_STATUS_UNCHANGED) {
        tries++;
        if (worker->need_to_exit) {
            lock_basic_unlock(&q->q_lock);
            return;
        }
        /**
         * Apparently the queue is full. Lets take a small break to not hog CPU.
         * The worker will release the signq lock while sleeping and will
         * automatically grab the lock when the queue is nonfull.
         * Queue is nonfull at 10% of the queue size.
         */
        lock_basic_sleep(&q->q_nonfull, &q->q_lock, 5);
        status = fifoq_push(q, (void*) rrset, worker, &tries);
    }
    lock_basic_unlock(&q->q_lock);

    ods_log_assert(status == ODS_STATUS_OK);
    lock_basic_lock(&worker->worker_lock);
    worker->jobs_appointed += 1;
    lock_basic_unlock(&worker->worker_lock);
    return;
}
/**
 * Worker waiting.
 *
 */
void
worker_wait_timeout(lock_basic_type* lock, cond_basic_type* condition,
    time_t timeout)
{
    lock_basic_lock(lock);
    lock_basic_sleep(condition, lock, timeout);
    lock_basic_unlock(lock);
    return;
}
Beispiel #3
0
/**
 * Worker waiting.
 *
 */
void
worker_wait(lock_basic_type* lock, cond_basic_type* condition)
{
    lock_basic_lock(lock);
    /* [LOCK] worker */
    lock_basic_sleep(condition, lock, 0);
    /* [UNLOCK] worker */
    lock_basic_unlock(lock);
    return;
}
/**
 * Put worker to sleep.
 *
 */
void
worker_sleep(worker_type* worker, time_t timeout)
{
    ods_log_assert(worker);
    lock_basic_lock(&worker->worker_lock);
    worker->sleeping = 1;
    lock_basic_sleep(&worker->worker_alarm, &worker->worker_lock,
        timeout);
    lock_basic_unlock(&worker->worker_lock);
    return;
}
/**
 * Run engine, run!.
 *
 */
static void
engine_run(engine_type* engine, int single_run)
{
    if (!engine) {
        return;
    }
    engine_start_workers(engine);
    engine_start_drudgers(engine);

    lock_basic_lock(&engine->signal_lock);
    engine->signal = SIGNAL_RUN;
    lock_basic_unlock(&engine->signal_lock);

    while (!engine->need_to_exit && !engine->need_to_reload) {
        lock_basic_lock(&engine->signal_lock);
        engine->signal = signal_capture(engine->signal);
        switch (engine->signal) {
            case SIGNAL_RUN:
                ods_log_assert(1);
                break;
            case SIGNAL_RELOAD:
                engine->need_to_reload = 1;
                break;
            case SIGNAL_SHUTDOWN:
                engine->need_to_exit = 1;
                break;
            default:
                ods_log_warning("[%s] invalid signal %d captured, "
                    "keep running", engine_str, signal);
                engine->signal = SIGNAL_RUN;
                break;
        }
        lock_basic_unlock(&engine->signal_lock);

        if (single_run) {
           engine->need_to_exit = engine_all_zones_processed(engine);
        }
        lock_basic_lock(&engine->signal_lock);
        if (engine->signal == SIGNAL_RUN && !single_run) {
           ods_log_debug("[%s] taking a break", engine_str);
           lock_basic_sleep(&engine->signal_cond, &engine->signal_lock, 3600);
        }
        lock_basic_unlock(&engine->signal_lock);
    }
    ods_log_debug("[%s] signer halted", engine_str);
    engine_stop_drudgers(engine);
    engine_stop_workers(engine);
    (void)lhsm_reopen(engine->config->cfg_filename);
    return;
}
Beispiel #6
0
/**
 * Put worker to sleep unless worker has measured up to all appointed jobs.
 *
 */
void
worker_sleep_unless(worker_type* worker, time_t timeout)
{
    ods_log_assert(worker);
    lock_basic_lock(&worker->worker_lock);
    /* [LOCK] worker */
    if (!worker->need_to_exit && !worker_fulfilled(worker)) {
        worker->sleeping = 1;
        lock_basic_sleep(&worker->worker_alarm, &worker->worker_lock,
            timeout);
    }
    /* [UNLOCK] worker */
    lock_basic_unlock(&worker->worker_lock);
    return;
}
/**
 * Put worker to sleep unless worker has measured up to all appointed jobs.
 *
 */
void
worker_sleep_unless(worker_type* worker, time_t timeout)
{
    ods_log_assert(worker);
    lock_basic_lock(&worker->worker_lock);
    while (!worker->need_to_exit && !worker_fulfilled(worker)) {
        worker->sleeping = 1;
        lock_basic_sleep(&worker->worker_alarm, &worker->worker_lock,
            timeout);
        ods_log_debug("[%s[%i]] somebody poked me, check completed jobs %u "
           "appointed, %u completed, %u failed", worker2str(worker->type),
           worker->thread_num, worker->jobs_appointed, worker->jobs_completed,
           worker->jobs_failed);
    }
    lock_basic_unlock(&worker->worker_lock);
    return;
}
Beispiel #8
0
/**
 * Put worker to sleep.
 *
 */
void
worker_sleep(worker_type* worker, time_t timeout)
{
    ods_log_assert(worker);
    lock_basic_lock(&worker->worker_lock);
    /* [LOCK] worker */
    /** need_to_exit may be set after check in worker start
     * and alarm might be fired before worker_lock. This check
     * prevents possible deadlock */
    if (!worker->need_to_exit) {
        worker->sleeping = 1;
        lock_basic_sleep(&worker->worker_alarm, &worker->worker_lock,
            timeout);
    }
    /* [UNLOCK] worker */
    lock_basic_unlock(&worker->worker_lock);
    return;
}
/**
 * Drudge.
 *
 */
static void
worker_drudge(worker_type* worker)
{
    engine_type* engine = NULL;
    zone_type* zone = NULL;
    task_type* task = NULL;
    rrset_type* rrset = NULL;
    ods_status status = ODS_STATUS_OK;
    worker_type* superior = NULL;
    hsm_ctx_t* ctx = NULL;

    ods_log_assert(worker);
    ods_log_assert(worker->engine);
    ods_log_assert(worker->type == WORKER_DRUDGER);

    engine = (engine_type*) worker->engine;
    while (worker->need_to_exit == 0) {
        ods_log_deeebug("[%s[%i]] report for duty", worker2str(worker->type),
            worker->thread_num);
        /* initialize */
        superior = NULL;
        zone = NULL;
        task = NULL;
        /* get item */
        lock_basic_lock(&engine->signq->q_lock);
        rrset = (rrset_type*) fifoq_pop(engine->signq, &superior);
        if (!rrset) {
            ods_log_deeebug("[%s[%i]] nothing to do, wait",
                worker2str(worker->type), worker->thread_num);
            /**
             * Apparently the queue is empty. Wait until new work is queued.
             * The drudger will release the signq lock while sleeping and
             * will automatically grab the lock when the threshold is reached.
             * Threshold is at 1 and MAX (after a number of tries).
             */
            lock_basic_sleep(&engine->signq->q_threshold,
                &engine->signq->q_lock, 0);
            rrset = (rrset_type*) fifoq_pop(engine->signq, &superior);
        }
        lock_basic_unlock(&engine->signq->q_lock);
        /* do some work */
        if (rrset) {
            ods_log_assert(superior);
            if (!ctx) {
                ods_log_debug("[%s[%i]] create hsm context",
                    worker2str(worker->type), worker->thread_num);
                ctx = hsm_create_context();
            }
            if (!ctx) {
                ods_log_crit("[%s[%i]] error creating libhsm context",
                    worker2str(worker->type), worker->thread_num);
                engine->need_to_reload = 1;
                lock_basic_lock(&superior->worker_lock);
                superior->jobs_failed++;
                lock_basic_unlock(&superior->worker_lock);
            } else {
                ods_log_assert(ctx);
                lock_basic_lock(&superior->worker_lock);
                task = superior->task;
                ods_log_assert(task);
                zone = task->zone;
                lock_basic_unlock(&superior->worker_lock);
                ods_log_assert(zone);
                ods_log_assert(zone->apex);
                ods_log_assert(zone->signconf);
                worker->clock_in = time(NULL);
                status = rrset_sign(ctx, rrset, superior->clock_in);
                lock_basic_lock(&superior->worker_lock);
                if (status == ODS_STATUS_OK) {
                    superior->jobs_completed++;
                } else {
                    superior->jobs_failed++;
                }
                lock_basic_unlock(&superior->worker_lock);
            }
            if (worker_fulfilled(superior) && superior->sleeping) {
                ods_log_deeebug("[%s[%i]] wake up superior[%u], work is "
                    "done", worker2str(worker->type), worker->thread_num,
                    superior->thread_num);
                worker_wakeup(superior);
            }
            superior = NULL;
            rrset = NULL;
        }
        /* done work */
    }
    /* wake up superior */
    if (superior && superior->sleeping) {
        ods_log_deeebug("[%s[%i]] wake up superior[%u], i am exiting",
            worker2str(worker->type), worker->thread_num, superior->thread_num);
         worker_wakeup(superior);
    }
    /* cleanup open HSM sessions */
    if (ctx) {
        hsm_destroy_context(ctx);
    }
    return;
}
Beispiel #10
0
/**
 * Run engine, run!.
 *
 */
static void
engine_run(engine_type* engine, start_cb_t start, int single_run)
{
    if (!engine) {
        return;
    }
    ods_log_assert(engine);

    engine_start_workers(engine);
    engine_start_drudgers(engine);

    lock_basic_lock(&engine->signal_lock);
    /* [LOCK] signal */
    engine->signal = SIGNAL_RUN;
    /* [UNLOCK] signal */
    lock_basic_unlock(&engine->signal_lock);

    /* call the external start callback function */
    start(engine);
    
    while (!engine->need_to_exit && !engine->need_to_reload) {
        lock_basic_lock(&engine->signal_lock);
        /* [LOCK] signal */
        engine->signal = signal_capture(engine->signal);
        switch (engine->signal) {
            case SIGNAL_RUN:
                ods_log_assert(1);
                break;
            case SIGNAL_RELOAD:
                engine->need_to_reload = 1;
                break;
            case SIGNAL_SHUTDOWN:
                engine->need_to_exit = 1;
                break;
            default:
                ods_log_warning("[%s] invalid signal captured: %d, "
                    "keep running", engine_str, signal);
                engine->signal = SIGNAL_RUN;
                break;
        }
        /* [UNLOCK] signal */
        lock_basic_unlock(&engine->signal_lock);

        if (single_run) {
            engine->need_to_exit = 1;
            /* FIXME: all tasks need to terminate, then set need_to_exit to 1 */
        }

        lock_basic_lock(&engine->signal_lock);
        /* [LOCK] signal */
        if (engine->signal == SIGNAL_RUN && !single_run) {
           ods_log_debug("[%s] taking a break", engine_str);
           lock_basic_sleep(&engine->signal_cond, &engine->signal_lock, 3600);
        }
        /* [UNLOCK] signal */
        lock_basic_unlock(&engine->signal_lock);
    }
    ods_log_debug("[%s] enforcer halted", engine_str);
    engine_stop_drudgers(engine);
    engine_stop_workers(engine);
    return;
}