void schedule_purge(schedule_type* schedule) { ldns_rbnode_t* node; if (!schedule || !schedule->tasks) return; pthread_mutex_lock(&schedule->schedule_lock); /* don't attempt to free payload, still referenced by other tree*/ while ((node = ldns_rbtree_first(schedule->tasks)) != LDNS_RBTREE_NULL) { node = ldns_rbtree_delete(schedule->tasks, node->data); if (node == 0) break; free(node); } /* also clean up name tree */ while ((node = ldns_rbtree_first(schedule->tasks_by_name)) != LDNS_RBTREE_NULL) { node = ldns_rbtree_delete(schedule->tasks_by_name, node->data); if (node == 0) break; task_cleanup((task_type*) node->data); free(node); } pthread_mutex_unlock(&schedule->schedule_lock); }
static task_type * keystate_ds_retract_task_perform(task_type *task) { perform_keystate_ds_retract(-1,(engineconfig_type *)task->context,NULL,NULL, 1); task_cleanup(task); return NULL; }
void Scheduler::operator()(){ //get the bit patterns and sort by node id (like the available algos) std::vector<state_type> bits = compute_dependencies(); // some book keeping vectors size_t size = algos_->size(); std::vector<EventState*> event_states(0); //TODO - has to move to init do { // BEGIN TODO: replace by thread safe code in start event // loop through all events that need to be started bool queue_full(false); do { unsigned int event_number(0); queue_full = new_events_queue_.try_pop(event_number); if (queue_full){ Context* context(0); bool whiteboard_available = wb_.get_context(context); if (whiteboard_available){ EventState* event_state = new EventState(size); event_states.push_back(event_state); event_state->context = context; context->write(event_number, "event","event"); } } } while(queue_full); for (unsigned int algo = 0; algo < size; ++algo) { // loop through all currently active events for (unsigned int event_id = 0; event_id < event_states.size() ; ++event_id) { EventState*& event_state = event_states[event_id]; // extract event_id specific quantities state_type& current_event_bits = event_state->state; // check whether all dependencies for the algorithm are fulfilled... state_type tmp = (current_event_bits & bits[algo]) ^ bits[algo]; /// ...whether all required products are there... // ... and whether the algo was previously started std::vector<AlgoState>& algo_states = event_state->algo_states; if ((tmp==0) && (algo_states[algo] == NOT_RUN)) { tryRunAlgo ( event_state, algo_states, algo ); } } } task_cleanup(); // check for finished events and clean up for (std::vector<EventState*>::iterator i = event_states.begin(), end = event_states.end(); i != end; ++i){ if ((*i)->state == termination_requirement_) { Context*& context = (*i)->context; wb_.release_context(context); loop_manager_->finished_event(); delete (*i); i = event_states.erase(i); } } std::this_thread::yield(); } while (not has_to_stop_); return; };
static task_type * enforce_task_perform(task_type *task) { engine_type *engine = ((struct enf_task_ctx *)task->context)->engine; int enforce_all = ((struct enf_task_ctx *)task->context)->enforce_all; int return_time = perform_enforce_lock(-1, engine, enforce_all, task, task->dbconn); enforcer_context.enforce_all = 0; if (return_time != -1) return task; task_cleanup(task); return NULL; }
/** * Internal task cleanup function. * */ static void task_delfunc(ldns_rbnode_t* elem, int del_payload) { task_type* task; if (elem && elem != LDNS_RBTREE_NULL) { task = (task_type*) elem->data; task_delfunc(elem->left, del_payload); task_delfunc(elem->right, del_payload); if (del_payload) task_cleanup(task); free((void*)elem); } }
/*---------------------------------------------------------------------------*/ void task_idle (void) { tcb_t *task ; printf ("Akalon: In Idle Task\n") ; /* We are in the Idle Task. Now let the BSP create the rest of */ /* the System's resources (tasks, sems, init routines, etc) by */ /* calling bsp_post_init(). However, interrupts should never be */ /* enabled in bsp_post_init(). Also, note that any new task */ /* that's created in bsp_post_init() will not switch out the */ /* Idle Task because it is running at the highest priority. */ bsp_post_init () ; kernel.int_mode = NO ; /* Remove this HACK !!! <--- DO */ /* All System Resources have now been created. Lower the Idle */ /* Task's priority to the lowest. */ task_rm_from_q (kernel.task_idle) ; kernel.task_idle->priority = -1 ; task_add_to_q (kernel.task_idle) ; /* Get the highest priority task and run it. Interrupts will be */ /* enabled when the task is run by task_start(). */ task = task_ready_get() ; if (task != kernel.task_idle) { kernel.task_idle->state = TASK_READY ; task_run_next (kernel.task_idle) ; } /* Interrupts were never enabled when the idle task was run. So */ /* enable interrupts and start spinning until another task gets */ /* into the ready state, which can happen becuase an interrupt. */ /* If an interrupt never happens (for what ever reason), then */ /* to code will be stuck in the following while(1) loop. */ cpu_enable_ints() ; while (1) { /* Check if any task needs to be deleted */ task_cleanup() ; } } /* End of function task_idle() */
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; }
/** * Try to recover from the backup files. * */ static ods_status engine_recover(engine_type* engine) { ldns_rbnode_t* node = LDNS_RBTREE_NULL; zone_type* zone = NULL; ods_status status = ODS_STATUS_OK; ods_status result = ODS_STATUS_UNCHANGED; if (!engine || !engine->zonelist || !engine->zonelist->zones) { ods_log_error("[%s] cannot recover zones: no engine or zonelist", engine_str); return ODS_STATUS_ERR; /* no need to update zones */ } ods_log_assert(engine); ods_log_assert(engine->zonelist); ods_log_assert(engine->zonelist->zones); lock_basic_lock(&engine->zonelist->zl_lock); /* [LOCK] zonelist */ node = ldns_rbtree_first(engine->zonelist->zones); while (node && node != LDNS_RBTREE_NULL) { zone = (zone_type*) node->data; ods_log_assert(zone->zl_status == ZONE_ZL_ADDED); status = zone_recover2(zone); if (status == ODS_STATUS_OK) { ods_log_assert(zone->task); ods_log_assert(zone->db); ods_log_assert(zone->signconf); /* notify nameserver */ if (engine->config->notify_command && !zone->notify_ns) { set_notify_ns(zone, engine->config->notify_command); } /* schedule task */ lock_basic_lock(&engine->taskq->schedule_lock); /* [LOCK] schedule */ status = schedule_task(engine->taskq, (task_type*) zone->task, 0); /* [UNLOCK] schedule */ lock_basic_unlock(&engine->taskq->schedule_lock); if (status != ODS_STATUS_OK) { ods_log_crit("[%s] unable to schedule task for zone %s: %s", engine_str, zone->name, ods_status2str(status)); task_cleanup((task_type*) zone->task); zone->task = NULL; result = ODS_STATUS_OK; /* will trigger update zones */ } else { ods_log_debug("[%s] recovered zone %s", engine_str, zone->name); /* recovery done */ zone->zl_status = ZONE_ZL_OK; } } else { if (status != ODS_STATUS_UNCHANGED) { ods_log_warning("[%s] unable to recover zone %s from backup," " performing full sign", engine_str, zone->name); } result = ODS_STATUS_OK; /* will trigger update zones */ } node = ldns_rbtree_next(node); } /* [UNLOCK] zonelist */ lock_basic_unlock(&engine->zonelist->zl_lock); return result; }
/** * Update zones. * */ void engine_update_zones(engine_type* engine, ods_status zl_changed) { ldns_rbnode_t* node = LDNS_RBTREE_NULL; zone_type* zone = NULL; zone_type* delzone = NULL; task_type* task = NULL; ods_status status = ODS_STATUS_OK; unsigned wake_up = 0; int warnings = 0; time_t now = 0; if (!engine || !engine->zonelist || !engine->zonelist->zones) { return; } now = time_now(); ods_log_debug("[%s] commit zone list changes", engine_str); lock_basic_lock(&engine->zonelist->zl_lock); node = ldns_rbtree_first(engine->zonelist->zones); while (node && node != LDNS_RBTREE_NULL) { zone = (zone_type*) node->data; task = NULL; /* reset task */ if (zone->zl_status == ZONE_ZL_REMOVED) { node = ldns_rbtree_next(node); lock_basic_lock(&zone->zone_lock); delzone = zonelist_del_zone(engine->zonelist, zone); if (delzone) { lock_basic_lock(&engine->taskq->schedule_lock); task = unschedule_task(engine->taskq, (task_type*) zone->task); lock_basic_unlock(&engine->taskq->schedule_lock); } task_cleanup(task); task = NULL; lock_basic_unlock(&zone->zone_lock); netio_remove_handler(engine->xfrhandler->netio, &zone->xfrd->handler); zone_cleanup(zone); zone = NULL; continue; } else if (zone->zl_status == ZONE_ZL_ADDED) { lock_basic_lock(&zone->zone_lock); ods_log_assert(!zone->task); /* set notify nameserver command */ if (engine->config->notify_command && !zone->notify_ns) { set_notify_ns(zone, engine->config->notify_command); } /* create task */ task = task_create(TASK_SIGNCONF, now, zone); lock_basic_unlock(&zone->zone_lock); if (!task) { ods_log_crit("[%s] unable to create task for zone %s: " "task_create() failed", engine_str, zone->name); node = ldns_rbtree_next(node); continue; } } /* load adapter config */ status = adapter_load_config(zone->adinbound); if (status != ODS_STATUS_OK) { ods_log_error("[%s] unable to load config for inbound adapter " "for zone %s: %s", engine_str, zone->name, ods_status2str(status)); } status = adapter_load_config(zone->adoutbound); if (status != ODS_STATUS_OK) { ods_log_error("[%s] unable to load config for outbound adapter " "for zone %s: %s", engine_str, zone->name, ods_status2str(status)); } /* for dns adapters */ warnings += dnsconfig_zone(engine, zone); if (zone->zl_status == ZONE_ZL_ADDED) { ods_log_assert(task); lock_basic_lock(&zone->zone_lock); zone->task = task; lock_basic_unlock(&zone->zone_lock); lock_basic_lock(&engine->taskq->schedule_lock); status = schedule_task(engine->taskq, task, 0); lock_basic_unlock(&engine->taskq->schedule_lock); } else if (zl_changed == ODS_STATUS_OK) { /* always try to update signconf */ lock_basic_lock(&zone->zone_lock); status = zone_reschedule_task(zone, engine->taskq, TASK_SIGNCONF); lock_basic_unlock(&zone->zone_lock); } if (status != ODS_STATUS_OK) { ods_log_crit("[%s] unable to schedule task for zone %s: %s", engine_str, zone->name, ods_status2str(status)); } else { wake_up = 1; zone->zl_status = ZONE_ZL_OK; } node = ldns_rbtree_next(node); } lock_basic_unlock(&engine->zonelist->zl_lock); if (engine->dnshandler) { dnshandler_fwd_notify(engine->dnshandler, (uint8_t*) ODS_SE_NOTIFY_CMD, strlen(ODS_SE_NOTIFY_CMD)); } else if (warnings) { ods_log_warning("[%s] no dnshandler/listener configured, but zones " "are configured with dns adapters: notify and zone transfer " "requests will not work properly", engine_str); } if (wake_up) { engine_wakeup_workers(engine); } return; }