/** * Handle signals. * */ void * signal_handler(sig_atomic_t sig) { switch (sig) { case SIGHUP: ods_log_debug("[%s] SIGHUP received", signal_str); signal_hup_recvd++; if (signal_engine) { lock_basic_lock(&signal_engine->signal_lock); /* [LOCK] signal */ lock_basic_alarm(&signal_engine->signal_cond); /* [UNLOCK] signal */ lock_basic_unlock(&signal_engine->signal_lock); } break; case SIGINT: case SIGTERM: ods_log_debug("[%s] SIGTERM received", signal_str); signal_term_recvd++; if (signal_engine) { lock_basic_lock(&signal_engine->signal_lock); /* [LOCK] signal */ lock_basic_alarm(&signal_engine->signal_cond); /* [UNLOCK] signal */ lock_basic_unlock(&signal_engine->signal_lock); } break; default: break; } return NULL; }
/** * Notify a worker. * */ void worker_notify(lock_basic_type* lock, cond_basic_type* condition) { lock_basic_lock(lock); lock_basic_alarm(condition); lock_basic_unlock(lock); return; }
/** * Notify a worker. * */ void worker_notify(lock_basic_type* lock, cond_basic_type* condition) { lock_basic_lock(lock); /* [LOCK] lock */ lock_basic_alarm(condition); /* [UNLOCK] lock */ lock_basic_unlock(lock); return; }
/** * Wake up worker. * */ void worker_wakeup(worker_type* worker) { ods_log_assert(worker); if (worker && worker->sleeping && !worker->waiting) { ods_log_debug("[%s[%i]] wake up", worker2str(worker->type), worker->thread_num); lock_basic_lock(&worker->worker_lock); lock_basic_alarm(&worker->worker_alarm); worker->sleeping = 0; lock_basic_unlock(&worker->worker_lock); } return; }
/** * Wake up worker. * */ void worker_wakeup(worker_type* worker) { ods_log_assert(worker); if (worker && worker->sleeping && !worker->waiting) { ods_log_debug("[worker[%i]] wake up", worker->thread_num); lock_basic_lock(&worker->worker_lock); /* [LOCK] worker */ lock_basic_alarm(&worker->worker_alarm); worker->sleeping = 0; /* [UNLOCK] worker */ lock_basic_unlock(&worker->worker_lock); } return; }
/** * Work. * */ static void worker_work(worker_type* worker) { time_t now = 0; time_t timeout = 1; engine_type* engine = NULL; zone_type* zone = NULL; ods_status status = ODS_STATUS_OK; ods_log_assert(worker); ods_log_assert(worker->type == WORKER_WORKER); engine = (engine_type*) worker->engine; while (worker->need_to_exit == 0) { ods_log_debug("[%s[%i]] report for duty", worker2str(worker->type), worker->thread_num); now = time_now(); lock_basic_lock(&engine->taskq->schedule_lock); worker->task = schedule_pop_task(engine->taskq); if (worker->task) { worker->working_with = worker->task->what; lock_basic_unlock(&engine->taskq->schedule_lock); zone = (zone_type*) worker->task->zone; lock_basic_lock(&zone->zone_lock); ods_log_debug("[%s[%i]] start working on zone %s", worker2str(worker->type), worker->thread_num, zone->name); worker->clock_in = time(NULL); worker_perform_task(worker); zone->task = worker->task; ods_log_debug("[%s[%i]] finished working on zone %s", worker2str(worker->type), worker->thread_num, zone->name); lock_basic_lock(&engine->taskq->schedule_lock); worker->task = NULL; worker->working_with = TASK_NONE; status = schedule_task(engine->taskq, zone->task, 1); if (status != ODS_STATUS_OK) { ods_log_error("[%s[%i]] unable to schedule task for zone %s: " "%s", worker2str(worker->type), worker->thread_num, zone->name, ods_status2str(status)); } lock_basic_unlock(&engine->taskq->schedule_lock); lock_basic_unlock(&zone->zone_lock); timeout = 1; /** Do we need to tell the engine that we require a reload? */ lock_basic_lock(&engine->signal_lock); if (engine->need_to_reload) { lock_basic_alarm(&engine->signal_cond); } lock_basic_unlock(&engine->signal_lock); } else { ods_log_debug("[%s[%i]] nothing to do", worker2str(worker->type), worker->thread_num); worker->task = schedule_get_first_task(engine->taskq); lock_basic_unlock(&engine->taskq->schedule_lock); if (worker->task && !engine->taskq->loading) { timeout = (worker->task->when - now); } else { timeout *= 2; } if (timeout > ODS_SE_MAX_BACKOFF) { timeout = ODS_SE_MAX_BACKOFF; } worker->task = NULL; worker_sleep(worker, timeout); } } return; }