int noit_check_schedule_next(noit_module_t *self, struct timeval *last_check, noit_check_t *check, struct timeval *now, dispatch_func_t dispatch, noit_check_t *cause) { eventer_t newe; struct timeval period, earliest; recur_closure_t *rcl; assert(cause == NULL); assert(check->fire_event == NULL); if(check->period == 0) return 0; if(NOIT_CHECK_DISABLED(check) || NOIT_CHECK_KILLED(check)) { if(!(check->flags & NP_TRANSIENT)) check_slots_dec_tv(last_check); return 0; } /* If we have an event, we know when we intended it to fire. This means * we should schedule that point + period. */ if(now) memcpy(&earliest, now, sizeof(earliest)); else gettimeofday(&earliest, NULL); /* If the check is unconfigured and needs resolving, we'll set the * period down a bit lower so we can pick up the resolution quickly. */ if(!NOIT_CHECK_RESOLVED(check) && NOIT_CHECK_SHOULD_RESOLVE(check) && check->period > 1000) { period.tv_sec = 1; period.tv_usec = 0; } else { period.tv_sec = check->period / 1000; period.tv_usec = (check->period % 1000) * 1000; } newe = eventer_alloc(); memcpy(&newe->whence, last_check, sizeof(*last_check)); add_timeval(newe->whence, period, &newe->whence); if(compare_timeval(newe->whence, earliest) < 0) memcpy(&newe->whence, &earliest, sizeof(earliest)); newe->mask = EVENTER_TIMER; newe->callback = noit_check_recur_handler; rcl = calloc(1, sizeof(*rcl)); rcl->self = self; rcl->check = check; rcl->cause = cause; rcl->dispatch = dispatch; newe->closure = rcl; eventer_add(newe); check->fire_event = newe; return 0; }
int noit_check_schedule_next(noit_module_t *self, struct timeval *last_check, noit_check_t *check, struct timeval *now, dispatch_func_t dispatch, noit_check_t *cause) { eventer_t newe; struct timeval period, earliest, diff; int64_t diffms, periodms, offsetms; recur_closure_t *rcl; int initial = last_check ? 1 : 0; assert(cause == NULL); assert(check->fire_event == NULL); if(check->period == 0) return 0; /* if last_check is not passed, we use the initial_schedule_time * otherwise, we set the initial_schedule_time */ if(!last_check) last_check = &check->initial_schedule_time; else memcpy(&check->initial_schedule_time, last_check, sizeof(*last_check)); if(NOIT_CHECK_DISABLED(check) || NOIT_CHECK_KILLED(check)) { if(!(check->flags & NP_TRANSIENT)) check_slots_dec_tv(last_check); memset(&check->initial_schedule_time, 0, sizeof(struct timeval)); return 0; } /* If we have an event, we know when we intended it to fire. This means * we should schedule that point + period. */ if(now) memcpy(&earliest, now, sizeof(earliest)); else gettimeofday(&earliest, NULL); /* If the check is unconfigured and needs resolving, we'll set the * period down a bit lower so we can pick up the resolution quickly. * The one exception is if this is the initial run. */ if(!initial && !NOIT_CHECK_RESOLVED(check) && NOIT_CHECK_SHOULD_RESOLVE(check) && check->period > 1000) { period.tv_sec = 1; period.tv_usec = 0; } else { period.tv_sec = check->period / 1000; period.tv_usec = (check->period % 1000) * 1000; } periodms = period.tv_sec * 1000 + period.tv_usec / 1000; newe = eventer_alloc(); /* calculate the differnet between the initial schedule time and "now" */ if(compare_timeval(earliest, *last_check) >= 0) { sub_timeval(earliest, *last_check, &diff); diffms = (int64_t)diff.tv_sec * 1000 + diff.tv_usec / 1000; } else { noitL(noit_error, "time is going backwards. abort.\n"); abort(); } /* determine the offset from initial schedule time that would place * us at the next period-aligned point past "now" */ offsetms = ((diffms / periodms) + 1) * periodms; diff.tv_sec = offsetms / 1000; diff.tv_usec = (offsetms % 1000) * 1000; memcpy(&newe->whence, last_check, sizeof(*last_check)); add_timeval(newe->whence, diff, &newe->whence); sub_timeval(newe->whence, earliest, &diff); diffms = (int64_t)diff.tv_sec * 1000 + (int)diff.tv_usec / 1000; assert(compare_timeval(newe->whence, earliest) > 0); newe->mask = EVENTER_TIMER; newe->callback = noit_check_recur_handler; rcl = calloc(1, sizeof(*rcl)); rcl->self = self; rcl->check = check; rcl->cause = cause; rcl->dispatch = dispatch; newe->closure = rcl; eventer_add(newe); check->fire_event = newe; return diffms; }