1{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE DeriveGeneric #-}
3{-# LANGUAGE StandaloneDeriving #-}
4{-# LANGUAGE ExistentialQuantification #-}
5{-# LANGUAGE ScopedTypeVariables #-}
6{-# LANGUAGE PatternGuards #-}
7{-# LANGUAGE RecordWildCards #-}
8{-# LANGUAGE FlexibleInstances #-}
9{-# LANGUAGE UndecidableInstances #-}
11-----------------------------------------------------------------------------
13-- Module : Control.Distributed.Process.Management
14-- Copyright : (c) Well-Typed / Tim Watson
15-- License : BSD3 (see the file LICENSE)
17-- Maintainer : Tim Watson <watson.timothy@gmail.com>
18-- Stability : experimental
19-- Portability : non-portable (requires concurrency)
21-- /Management Extensions/ for Cloud Haskell.
23-- This module provides a standard API for receiving and/or responding to
24-- system events in a Cloud Haskell node.
26-- [Architecture Overview]
28-- /Management Extensions/ can be used by infrastructure or application code
29-- to provide access to runtime instrumentation data, expose control planes
30-- and/or provide remote access to external clients.
32-- The management infrastructure is broken down into three components, which
33-- roughly correspond to the modules it exposes:
35-- 1. @Agent@ - registration and management of /Management Agents/
36-- 2. @Instrumentation@ - provides an API for publishing /instrumentation data/
37-- 3. @Remote@ - provides an API for remote management and administration
40-----------------------------------------------------------------------------
41module Control.Distributed.Process.Management
45 -- * Firing /mx events/
47 -- * Constructing Agents
56 -- * Management Data API
62import Control.Applicative ((<$>))
63import Control.Concurrent.STM (atomically)
64import Control.Concurrent.STM.TChan
67import Control.Distributed.Process.Internal.Primitives
73import Control.Distributed.Process.Internal.Types
80 , unsafeCreateUnencodedMessage
82import Control.Distributed.Process.Management.Bus (publishEvent)
83import qualified Control.Distributed.Process.Management.Table as Table
84import Control.Distributed.Process.Management.Types
90import Control.Distributed.Process.Serializable (Serializable)
91import Control.Monad.IO.Class (liftIO)
92import Control.Monad.Reader (ask)
93import qualified Control.Monad.State as ST
103 MxAgentDeactivate !String
106-- | Publishes an arbitrary @Serializable@ message to the management event bus.
107-- Note that /no attempt is made to force the argument/, therefore it is very
108-- important that you do not pass unevaluated thunks that might crash the
109-- receiving process via this API, since /all/ registered agents will gain
110-- access to the data structure once it is broadcast by the agent controller.
111mxNotify :: (Serializable a) => a -> Process ()
113 bus <- localEventBus . processNode <$> ask
114 liftIO $ publishEvent bus $ unsafeCreateUnencodedMessage msg
116-- | Publish an arbitrary @Message@ as a property in the management database.
118-- For publishing @Serializable@ data, use 'mxSet' instead. For publishing
119-- properties efficiently within an agent, use 'mxAgentPublish' instead,
120-- since it will be more efficient in that context.
121mxPublish :: MxAgentId -> String -> Message -> Process ()
122mxPublish a k v = Table.set k v (Table.MxForAgent a)
124-- | Sets an arbitrary @Serializable@ datum against a key in the management
125-- database. Note that /no attempt is made to force the argument/, therefore
126-- it is very important that you do not pass unevaluated thunks that might
127-- crash some other, arbitrary process (or management agent!) that obtains
128-- and attempts to force the value later on.
130mxSet :: Serializable a => MxAgentId -> String -> a -> Process ()
132 Table.set key (unsafeCreateUnencodedMessage msg) (Table.MxForAgent mxId)
134-- | Fetches a property from the management database for the given key.
135-- If the property is not set, or does not match the expected type when
136-- typechecked (at runtime), returns @Nothing@.
137mxGet :: Serializable a => MxAgentId -> String -> Process (Maybe a)
138mxGet mxId = Table.fetch (Table.MxForAgent mxId)
140--------------------------------------------------------------------------------
141-- API for writing user defined management extensions (i.e., agents) --
142--------------------------------------------------------------------------------
144mxAgentPublish = undefined
146mxAgentDeactivate :: forall s. String -> MxAgent s MxAction
147mxAgentDeactivate = return . MxAgentDeactivate
149mxAgentReady :: forall s. MxAgent s MxAction
150mxAgentReady = return MxAgentReady
152liftP :: Process a -> MxAgent s a
153liftP p = MxAgent $ ST.lift p
155mxSetLocal :: s -> MxAgent s ()
156mxSetLocal s = ST.modify $ \st -> st { mxLocalState = s }
158mxGetLocal :: MxAgent s s
159mxGetLocal = ST.get >>= return . mxLocalState
161-- | Activates a new agent.
165 -> (Message -> MxAgent s MxAction)
167mxAgent mxId initState handler = do
168 node <- processNode <$> ask
169 pid <- liftIO $ mxNew (localEventBus node) $ start
174 nsend Table.mxTableCoordinator (MxAgentStart sp mxId)
175 tablePid <- receiveWait [ matchChan rp (\(p :: ProcessId) -> return p) ]
176 runAgent handler chan $ MxAgentState mxId tablePid initState
179 msg <- (liftIO $ atomically $ readTChan c)
180 (action, state) <- runAgentST s $ h msg
182 MxAgentReady -> runAgent h c state
183 MxAgentDeactivate _ -> {- TODO: log r -} return ()
184-- MxAgentBecome h' -> runAgent h' c state
186 runAgentST :: MxAgentState s
187 -> MxAgent s MxAction
188 -> Process (MxAction, MxAgentState s)
189 runAgentST state proc = ST.runStateT (unAgent proc) state
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list