static void adjust_squeue_for_time_change(squeue_t **q, int delta) { timed_event *event; squeue_t *sq_new; /* * this is pretty inefficient in terms of free() + malloc(), * but it should be pretty rare that we have to adjust times * so we go with the well-tested codepath. */ sq_new = squeue_create(squeue_size(*q)); while ((event = squeue_pop(*q))) { if (event->compensate_for_time_change == TRUE) { if (event->timing_func) { time_t (*timingfunc)(void); timingfunc = event->timing_func; event->run_time = timingfunc(); } else { event->run_time += delta; } } if (event->priority) { event->sq_event = squeue_add_usec(sq_new, event->run_time, event->priority - 1, event); } else { event->sq_event = squeue_add(sq_new, event->run_time, event); } } squeue_destroy(*q, 0); *q = sq_new; }
/* add an event to list ordered by execution time */ void add_event(squeue_t *sq, timed_event *event) { log_debug_info(DEBUGL_FUNCTIONS, 0, "add_event()\n"); if (event->sq_event) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Adding %s event that seems to already be scheduled\n", EVENT_TYPE_STR(event->event_type)); remove_event(sq, event); } if (event->priority) { event->sq_event = squeue_add_usec(sq, event->run_time, event->priority - 1, event); } else { event->sq_event = squeue_add(sq, event->run_time, event); } if (!event->sq_event) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to add event to squeue '%p' with prio %u: %s\n", sq, event->priority, strerror(errno)); } if (sq == nagios_squeue) track_events(event->event_type, +1); #ifdef USE_EVENT_BROKER else { /* send event data to broker */ broker_timed_event(NEBTYPE_TIMEDEVENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, event, NULL); } #endif return; }
squeue_event *squeue_add_msec(squeue_t *q, time_t when, time_t msec, void *data) { return squeue_add_usec(q, when, msec * 1000, data); }
int main(int argc, char **argv) { squeue_t *sq; struct timeval tv; sq_test_event a, b, c, d, *x; t_set_colors(0); t_start("squeue tests"); a.id = 1; b.id = 2; c.id = 3; d.id = 4; gettimeofday(&tv, NULL); /* Order in is a, b, c, d, but we should get b, c, d, a out. */ srand(tv.tv_usec ^ tv.tv_sec); t((sq = squeue_create(1024)) != NULL); t(squeue_size(sq) == 0); /* we fill and empty the squeue completely once before testing */ sq_test_random(sq); t(squeue_size(sq) == 0, "Size should be 0 after first sq_test_random"); t((a.evt = squeue_add(sq, time(NULL) + 9, &a)) != NULL); t(squeue_size(sq) == 1); t((b.evt = squeue_add(sq, time(NULL) + 3, &b)) != NULL); t(squeue_size(sq) == 2); t((c.evt = squeue_add_msec(sq, time(NULL) + 5, 0, &c)) != NULL); t(squeue_size(sq) == 3); t((d.evt = squeue_add_usec(sq, time(NULL) + 5, 1, &d)) != NULL); t(squeue_size(sq) == 4); /* add and remove lots. remainder should be what we have above */ sq_test_random(sq); /* testing squeue_peek() */ t((x = (sq_test_event *)squeue_peek(sq)) != NULL); t(x == &b, "x: %p; a: %p; b: %p; c: %p; d: %p\n", x, &a, &b, &c, &d); t(x->id == b.id); t(squeue_size(sq) == 4); /* testing squeue_remove() and re-add */ t(squeue_remove(sq, b.evt) == 0); t(squeue_size(sq) == 3); t((x = squeue_peek(sq)) != NULL); t(x == &c); t((b.evt = squeue_add(sq, time(NULL) + 3, &b)) != NULL); t(squeue_size(sq) == 4); /* peek should now give us the &b event (again) */ t((x = squeue_peek(sq)) != NULL); if (x != &b) { printf("about to fail pretty f*****g hard...\n"); printf("ea: %p; &b: %p; &c: %p; ed: %p; x: %p\n", &a, &b, &c, &d, x); } t(x == &b); t(x->id == b.id); t(squeue_size(sq) == 4); /* testing squeue_pop(), lifo manner */ t((x = squeue_pop(sq)) != NULL); t(squeue_size(sq) == 3, "squeue_size(sq) = %d\n", squeue_size(sq)); t(x == &b, "x: %p; &b: %p\n", x, &b); t(x->id == b.id, "x->id: %lu; d.id: %lu\n", x->id, d.id); /* Test squeue_pop() */ t((x = squeue_pop(sq)) != NULL); t(squeue_size(sq) == 2); t(x == &c, "x->id: %lu; c.id: %lu\n", x->id, c.id); t(x->id == c.id, "x->id: %lu; c.id: %lu\n", x->id, c.id); /* this should fail gracefully (-1 return from squeue_remove()) */ t(squeue_remove(NULL, NULL) == -1); t(squeue_remove(NULL, a.evt) == -1); squeue_foreach(sq, sq_walker, NULL); /* clean up to prevent false valgrind positives */ squeue_destroy(sq, 0); return t_end(); }