mkDaemonHandle :: FilePath
               -> ConfigState
               -> GanetiLockWaiting
               -> TempResState
               -> (IO ConfigState -> [AsyncWorker () ()]
                                  -> ResultG (AsyncWorker Any ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- saves the configuration to the master file.
               -> (IO ConfigState -> ResultG (AsyncWorker () ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- distributes the configuration to master candidates
               -> (IO ConfigState -> ResultG (AsyncWorker () ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- distributes SSConf to nodes
               -> (IO GanetiLockWaiting -> ResultG (AsyncWorker () ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- saves the lock allocation state.
               -> (IO TempResState -> ResultG (AsyncWorker () ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- saves the temporary reservations state.
               -> Livelock
               -> ResultG DaemonHandle
mkDaemonHandle cpath cstat lstat trstat
               saveWorkerFn distMCsWorkerFn distSSConfWorkerFn
               saveLockWorkerFn saveTempResWorkerFn livelock = do
  ds <- newIORef $ DaemonState cstat lstat trstat
  let readConfigIO = dsConfigState `liftM` readIORef ds :: IO ConfigState

  ssconfWorker <- distSSConfWorkerFn readConfigIO
  distMCsWorker <- distMCsWorkerFn readConfigIO
  saveWorker <- saveWorkerFn readConfigIO [ distMCsWorker
                                          , ssconfWorker ]

  saveLockWorker <- saveLockWorkerFn $ dsLockWaiting `liftM` readIORef ds

  saveTempResWorker <- saveTempResWorkerFn $ dsTempRes `liftM` readIORef ds

  return $ DaemonHandle ds cpath saveWorker saveLockWorker saveTempResWorker
                        livelock

-- * The monad and its instances

-- | A type alias for easier referring to the actual content of the monad
-- when implementing its instances.
mkDaemonHandle :: FilePath
               -> ConfigState
               -> GanetiLockWaiting
               -> TempResState
               -> (IO ConfigState -> [AsyncWorker () ()]
                                  -> ResultG (AsyncWorker Any ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- saves the configuration to the master file.
               -> (IO ConfigState -> ResultG (AsyncWorker () ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- distributes the configuration to master candidates
               -> (IO ConfigState -> ResultG (AsyncWorker () ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- distributes SSConf to nodes
               -> (IO GanetiLockWaiting -> ResultG (AsyncWorker () ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- saves the lock allocation state.
               -> (IO TempResState -> ResultG (AsyncWorker () ()))
                  -- ^ A function that creates a worker that asynchronously
                  -- saves the temporary reservations state.
               -> Livelock
               -> ResultG DaemonHandle
mkDaemonHandle cpath cstat lstat trstat
               saveWorkerFn distMCsWorkerFn distSSConfWorkerFn
               saveLockWorkerFn saveTempResWorkerFn livelock = do
  ds <- newIORef $ DaemonState cstat lstat trstat
  let readConfigIO = dsConfigState `liftM` readIORef ds :: IO ConfigState

  ssconfWorker <- distSSConfWorkerFn readConfigIO
  distMCsWorker <- distMCsWorkerFn readConfigIO
  saveWorker <- saveWorkerFn readConfigIO [ distMCsWorker
                                          , ssconfWorker ]

  saveLockWorker <- saveLockWorkerFn $ dsLockWaiting `liftM` readIORef ds

  saveTempResWorker <- saveTempResWorkerFn $ dsTempRes `liftM` readIORef ds

  return $ DaemonHandle ds cpath saveWorker saveLockWorker saveTempResWorker
                        livelock

-- * The monad and its instances

-- | A type alias for easier referring to the actual content of the monad
-- when implementing its instances.
mkDaemonHandle cpath cstat lstat trstat
               saveWorkerFn distMCsWorkerFn distSSConfWorkerFn
               saveLockWorkerFn saveTempResWorkerFn livelock = do
  ds <- newIORef $ DaemonState cstat lstat trstat
  let readConfigIO = dsConfigState `liftM` readIORef ds :: IO ConfigState

  ssconfWorker <- distSSConfWorkerFn readConfigIO
  distMCsWorker <- distMCsWorkerFn readConfigIO
  saveWorker <- saveWorkerFn readConfigIO [ distMCsWorker
                                          , ssconfWorker ]

  saveLockWorker <- saveLockWorkerFn $ dsLockWaiting `liftM` readIORef ds

  saveTempResWorker <- saveTempResWorkerFn $ dsTempRes `liftM` readIORef ds

  return $ DaemonHandle ds cpath saveWorker saveLockWorker saveTempResWorker
                        livelock

-- * The monad and its instances

-- | A type alias for easier referring to the actual content of the monad
-- when implementing its instances.