2019-05-30 23:19:26 +03:00
|
|
|
module Vere.Pier where
|
|
|
|
|
|
|
|
import ClassyPrelude
|
2019-06-19 01:38:24 +03:00
|
|
|
|
|
|
|
import Data.Noun
|
|
|
|
import Data.Noun.Pill
|
|
|
|
import Vere
|
2019-05-30 23:19:26 +03:00
|
|
|
import Vere.Pier.Types
|
2019-06-19 01:38:24 +03:00
|
|
|
|
2019-05-30 23:19:26 +03:00
|
|
|
import qualified Vere.Log as Log
|
2019-06-19 01:38:24 +03:00
|
|
|
import qualified Vere.Worker as Worker
|
2019-05-30 23:19:26 +03:00
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
ioDrivers = [] :: [IODriver]
|
2019-06-18 02:47:20 +03:00
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
-- This is called to make a freshly booted pier. It assigns an identity to an
|
|
|
|
-- event log and takes a chill pill.
|
|
|
|
newPier :: Pill -> FilePath -> LogIdentity -> IO Pier
|
|
|
|
newPier pill top id = do
|
2019-06-18 02:47:20 +03:00
|
|
|
let logPath = top <> "/log"
|
|
|
|
|
|
|
|
computeQueue <- newTQueueIO
|
|
|
|
persistQueue <- newTQueueIO
|
|
|
|
releaseQueue <- newTQueueIO
|
|
|
|
|
|
|
|
-- What we really want to do is write the log identity and then do normal
|
|
|
|
-- startup, but writeLogIdentity requires a full log state including
|
|
|
|
-- input/output queues.
|
|
|
|
logState <- Log.init logPath persistQueue (writeTQueue releaseQueue)
|
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
-- In first boot, we need to write this!
|
2019-06-18 02:47:20 +03:00
|
|
|
Log.writeLogIdentity logState id
|
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
let logLatestEventNumber = 0
|
|
|
|
let getEvents = Log.readEvents logState
|
|
|
|
|
|
|
|
workerState <- Worker.startWorkerProcess
|
|
|
|
|
|
|
|
Worker.bootWorker workerState id pill
|
2019-06-18 02:47:20 +03:00
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
performCommonPierStartup workerState computeQueue persistQueue releaseQueue logState
|
2019-06-18 02:47:20 +03:00
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
|
|
|
|
-- This reads in a pier
|
|
|
|
runPierFromDisk :: FilePath -> IO Pier
|
|
|
|
runPierFromDisk top = do
|
2019-05-30 23:19:26 +03:00
|
|
|
let logPath = top <> "/log"
|
|
|
|
|
|
|
|
computeQueue <- newTQueueIO
|
|
|
|
persistQueue <- newTQueueIO
|
|
|
|
releaseQueue <- newTQueueIO
|
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
-- What we really want to do is write the log identity and then do normal
|
|
|
|
-- startup, but writeLogIdentity requires a full log state including
|
|
|
|
-- input/output queues.
|
2019-05-30 23:19:26 +03:00
|
|
|
logState <- Log.init logPath persistQueue (writeTQueue releaseQueue)
|
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
-- In first boot, we need to write this!
|
|
|
|
id <- Log.readLogIdentity logState
|
|
|
|
logLatestEventNumber <- Log.latestEventNumber logState
|
2019-06-18 02:47:20 +03:00
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
let getEvents = Log.readEvents logState
|
|
|
|
|
|
|
|
workerState <- Worker.startWorkerProcess
|
|
|
|
Worker.resumeWorker workerState id logLatestEventNumber getEvents
|
|
|
|
|
|
|
|
performCommonPierStartup workerState computeQueue persistQueue releaseQueue logState
|
|
|
|
|
|
|
|
|
|
|
|
performCommonPierStartup :: Worker.Worker
|
|
|
|
-> TQueue Noun
|
|
|
|
-> TQueue (Writ [Eff])
|
|
|
|
-> TQueue (Writ [Eff])
|
|
|
|
-> LogState
|
|
|
|
-> IO Pier
|
|
|
|
performCommonPierStartup workerState computeQueue persistQueue releaseQueue logState = do
|
|
|
|
for ioDrivers $ \x -> do
|
|
|
|
bootMessage <- bornEvent x
|
|
|
|
atomically $ writeTQueue computeQueue bootMessage
|
2019-06-01 01:55:21 +03:00
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
driverThreads <- for ioDrivers $ \x -> do
|
|
|
|
startDriver x (writeTQueue computeQueue)
|
|
|
|
|
|
|
|
-- TODO: Don't do a bunch of extra work; we send all events to all drivers
|
|
|
|
portingThread <- async $ do
|
|
|
|
forever $ do
|
|
|
|
r <- atomically (readTQueue releaseQueue)
|
|
|
|
for_ driverThreads $ \(_, k) ->
|
|
|
|
for_ (payload r) $ \eff ->
|
|
|
|
k eff
|
|
|
|
|
|
|
|
Worker.workerThread workerState
|
|
|
|
|
|
|
|
pure (Pier{..})
|