+(* Schedule the next every-statement job to run, if there is one. We
+ * look at the every jobs, work out the time that each must run at,
+ * pick the job(s) which must run soonest, and schedule a timer to run
+ * them. When the timer fires, it runs those jobs, then call this
+ * function again. 'last_t' is the base time used for scheduling (or
+ * the time that the file was last reloaded).
+ *)
+and schedule_next_everyjob () =
+ (* Get only everyjobs. *)
+ let jobs = StringMap.values !jobs in
+ let jobs = filter_map (
+ function
+ | { job_cond = Every_job period } as job -> Some (job, period)
+ | { job_cond = When_job _ } -> None
+ ) jobs in
+
+ (* Map everyjob to next time it must run. *)
+ let jobs = List.map (
+ fun (job, period) ->
+ let t' = next_periodexpr !last_t period in
+ assert (t' > !last_t); (* serious bug in next_periodexpr if false *)
+ job, t'
+ ) jobs in
+
+ (* Sort, soonest first. *)
+ let jobs = List.sort (fun (_,a) (_,b) -> compare a b) jobs in
+
+ if !debug then (
+ List.iter (
+ fun (job, t) ->
+ Syslog.notice "%s: next scheduled run at %s"
+ job.job_name (string_of_time_t t)
+ ) jobs
+ );
+
+ (* Pick the job(s) which run soonest. *)
+ let rec pick = function
+ | [] -> 0., []
+ | [j, t] -> t, [j]
+ | (j1, t) :: (j2, t') :: _ when t < t' -> t, [j1]
+ | (j1, t) :: (((j2, t') :: _) as rest) -> t, (j1 :: snd (pick rest))