2019-05-30 23:19:26 +03:00
|
|
|
module Vere.Pier where
|
|
|
|
|
|
|
|
import ClassyPrelude
|
2019-06-19 01:38:24 +03:00
|
|
|
|
2019-07-02 05:51:26 +03:00
|
|
|
import Noun
|
2019-07-12 00:41:09 +03:00
|
|
|
import Pill
|
2019-05-30 23:19:26 +03:00
|
|
|
import Vere.Pier.Types
|
2019-06-19 01:38:24 +03:00
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
import qualified Vere.Log as Log
|
|
|
|
import qualified Vere.Persist as Persist
|
|
|
|
import qualified Vere.Serf as Serf
|
2019-05-30 23:19:26 +03:00
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
import Vere.Serf (Serf, EventId)
|
2019-06-18 02:47:20 +03:00
|
|
|
|
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
--------------------------------------------------------------------------------
|
2019-06-18 02:47:20 +03:00
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
ioDrivers = [] :: [IODriver]
|
2019-06-18 02:47:20 +03:00
|
|
|
|
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
--------------------------------------------------------------------------------
|
2019-06-19 01:38:24 +03:00
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
-- This is called to make a freshly booted pier. It assigns an identity to an
|
|
|
|
-- event log and takes a chill pill.
|
|
|
|
boot :: Pill -> FilePath -> LogIdentity -> IO (Serf, EventLog, EventId, Mug)
|
|
|
|
boot pill top id = do
|
2019-05-30 23:19:26 +03:00
|
|
|
let logPath = top <> "/log"
|
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
log <- Log.open logPath
|
2019-05-30 23:19:26 +03:00
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
Log.writeIdent log id
|
2019-05-30 23:19:26 +03:00
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
serf <- Serf.startSerfProcess top
|
|
|
|
(e, m) <- Serf.bootSerf serf id pill
|
2019-06-18 02:47:20 +03:00
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
pure (serf, log, e, m)
|
2019-06-19 01:38:24 +03:00
|
|
|
|
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
{-
|
|
|
|
What we really want to do is write the log identity and then do
|
|
|
|
normal startup, but writeIdent requires a full log state
|
|
|
|
including input/output queues.
|
|
|
|
-}
|
|
|
|
resume :: FilePath -> IO (Serf, EventLog, EventId, Mug)
|
|
|
|
resume top = do
|
|
|
|
log <- Log.open (top <> "/.urb/log")
|
|
|
|
ident <- Log.readIdent log
|
|
|
|
lastEv <- Log.latestEventNumber log
|
|
|
|
serf <- Serf.startSerfProcess top
|
|
|
|
(e, m) <- Serf.replay serf ident lastEv (Log.readEvents log)
|
2019-06-19 01:38:24 +03:00
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
pure (serf, log, e, m)
|
2019-06-19 01:38:24 +03:00
|
|
|
|
2019-06-29 04:46:33 +03:00
|
|
|
|
|
|
|
-- Run Pier --------------------------------------------------------------------
|
|
|
|
|
|
|
|
{-
|
|
|
|
/* _pier_work_save(): tell worker to save checkpoint.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_pier_work_save(u3_pier* pir_u)
|
|
|
|
{
|
|
|
|
u3_controller* god_u = pir_u->god_u;
|
|
|
|
u3_disk* log_u = pir_u->log_u;
|
|
|
|
u3_save* sav_u = pir_u->sav_u;
|
|
|
|
|
|
|
|
c3_assert( god_u->dun_d == sav_u->req_d );
|
|
|
|
c3_assert( log_u->com_d >= god_u->dun_d );
|
|
|
|
|
|
|
|
{
|
|
|
|
u3_noun mat = u3ke_jam(u3nc(c3__save, u3i_chubs(1, &god_u->dun_d)));
|
|
|
|
u3_newt_write(&god_u->inn_u, mat, 0);
|
|
|
|
|
|
|
|
// XX wait on some report of success before updating?
|
|
|
|
//
|
|
|
|
sav_u->dun_d = sav_u->req_d;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we're gracefully shutting down, do so now
|
|
|
|
//
|
|
|
|
if ( u3_psat_done == pir_u->sat_e ) {
|
|
|
|
_pier_exit_done(pir_u);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
{-
|
|
|
|
performCommonPierStartup :: Serf.Serf
|
2019-06-19 03:04:57 +03:00
|
|
|
-> TQueue Ovum
|
2019-06-19 01:38:24 +03:00
|
|
|
-> TQueue (Writ [Eff])
|
|
|
|
-> TQueue (Writ [Eff])
|
|
|
|
-> LogState
|
|
|
|
-> IO Pier
|
2019-06-25 04:10:41 +03:00
|
|
|
performCommonPierStartup serf computeQ persistQ releaseQ logState = do
|
2019-06-19 01:38:24 +03:00
|
|
|
for ioDrivers $ \x -> do
|
|
|
|
bootMessage <- bornEvent x
|
2019-06-25 04:10:41 +03:00
|
|
|
atomically $ writeTQueue computeQ bootMessage
|
2019-06-01 01:55:21 +03:00
|
|
|
|
2019-06-19 01:38:24 +03:00
|
|
|
driverThreads <- for ioDrivers $ \x -> do
|
2019-06-25 04:10:41 +03:00
|
|
|
startDriver x (writeTQueue computeQ)
|
2019-06-19 01:38:24 +03:00
|
|
|
|
|
|
|
-- TODO: Don't do a bunch of extra work; we send all events to all drivers
|
|
|
|
portingThread <- async $ do
|
|
|
|
forever $ do
|
2019-06-25 04:10:41 +03:00
|
|
|
r <- atomically (readTQueue releaseQ)
|
2019-06-19 01:38:24 +03:00
|
|
|
for_ driverThreads $ \(_, k) ->
|
|
|
|
for_ (payload r) $ \eff ->
|
|
|
|
k eff
|
|
|
|
|
2019-06-25 04:10:41 +03:00
|
|
|
Serf.workerThread serf (readTQueue computeQ) undefined
|
2019-06-19 01:38:24 +03:00
|
|
|
|
|
|
|
pure (Pier{..})
|
2019-06-25 04:10:41 +03:00
|
|
|
-}
|