module HAppS.State.TxControl
    ( runTxSystem
    , shutdownSystem
    ) where

import System.Log.Logger
import System.IO
import Control.Monad
import Control.Exception
import Control.Concurrent

import HAppS.State.Checkpoint
import HAppS.State.Saver
import HAppS.State.Transaction
import HAppS.State.Types
import HAppS.State.ComponentSystem
import HAppS.Data.Proxy

logMM = logM "HAppS.State.TxControl"


-- | Run a transaction system 
runTxSystem :: (Methods st, Component st) => Saver -> Proxy st -> IO (MVar TxControl)
runTxSystem saver stateProxy =
    do logMM NOTICE "Initializing system control."
       ctl <- createTxControl saver stateProxy
       logMM NOTICE "Creating event mapper."
       initEventMap ctl stateProxy
       logMM NOTICE "Restoring state."
       restoreState ctl
       let ioActions = componentIO stateProxy
       logMM NOTICE "Forking children."
       children <- forM ioActions $ \action -> do mv <- newEmptyMVar
                                                  tid <- forkIO (action `finally` putMVar mv ())
                                                  return (tid,mv)
       modifyMVar_ ctl $ \ctl -> return ctl{ctlChildren = children}
       return ctl

shutdownSystem :: MVar TxControl -> IO ()
shutdownSystem ctl
    = do logMM NOTICE "Shutting down."
         children <- liftM ctlChildren $ readMVar ctl
         logMM NOTICE "Killing children."
         mapM_ (killThread . fst) children
         mapM_ (takeMVar . snd) children -- FIXME: Use a timeout.
         logMM NOTICE "Shutdown complete"
         closeTxControl ctl