packages feed

AutoForms-0.4.0: src/Examples/HCron/Daemon2ndRecurring.hs

module Daemon2ndRecurring where

import List(sort, insert)
import System(system)
import Control.Concurrent(threadDelay)
import Maybe(mapMaybe)

import Entry2ndRecurring

main = do putStrLn "The HCron daemon"
          spec                             <- readFile specLocation
          calTime                          <- getCalendarTime
          (TOD currentSecondsSinceEpoch _) <- getClockTime
          let entries    = (read spec)::[Entry Time]
              entries'   = sort $ mapMaybe renewAndPrune $ map toSeconds entries
              renewAndPrune e@(Entry t recur _) =
                  case (t > currentSecondsSinceEpoch, recur) of
                    (True, _)            -> Just e
                    (False, Nothing)     -> Nothing
                    (False, Just (TimeDiff 0 0 0 0 0 0 0)) -> Nothing
                    (False, Just recur') -> renewAndPrune $ addTimeDiff recur' e
              toSeconds x         = x { when = timeToSeconds calTime (when x) }
          putStrLn "Successfully read entries. Starting daemon."
          putStrLn $ unlines $ map show entries
          putStrLn "After pruning:"
          putStrLn $ unlines $ map show entries'
          daemon entries'

daemon :: [Entry Integer] -> IO()
daemon [] = return ()
daemon (x@(Entry time recur command'):xs) =
    do (TOD clockTime _) <- getClockTime
       delaySeconds $ max 0 (time - clockTime)
       system command'
       let xs' = case recur of
                   Nothing     -> xs
                   Just recur' -> insert (addTimeDiff recur' x) xs
       daemon xs'

addTimeDiff :: TimeDiff -> Entry Integer -> Entry Integer
addTimeDiff diff e = e { when = let (TOD t _ ) = addToClockTime diff (TOD (when e) 0)
                                in t
                       }

getCalendarTime :: IO CalendarTime
getCalendarTime =
    do clockTime <- getClockTime
       toCalendarTime clockTime

timeToSeconds :: CalendarTime -> Time -> Integer
timeToSeconds calTime t =
       let t' = calTime { ctYear = year t, ctMonth = month t, ctDay = day t
                        , ctHour = hour t, ctMin = minute t, ctSec = 0, ctPicosec = 0 }
           (TOD time _) = (toClockTime t')
       in time

delaySeconds :: Integer -> IO ()
delaySeconds seconds = delayMicro (seconds * 1)   -- FIXME: multiple by 10^6
    where
      delayMicro ms | ms <= 0   = return ()
                    | otherwise = do let d = min (toInteger (maxBound::Int)) ms
                                     print (d `div` 10^6)
                                     threadDelay (fromInteger d)
                                     delayMicro (ms - d)