-- Locations -- includes API for error and debug messages -- -- Author: Rob Stewart, Patrick Maier ----------------------------------------------------------------------------- module Control.Parallel.HdpH.Internal.Location ( -- * node IDs (and their constitutent parts) NodeId, -- instances: Eq, Ord, Show, NFData, Serialize -- * reading all node IDs and this node's own node ID allNodes, -- :: IO [NodeId] myNode, -- :: IO NodeId myNode', -- :: IO (Maybe NodeId) MyNodeException(..), -- instances: Exception, Show, Typeable -- * error messages tagged by emitting node error, -- :: String -> a -- * debug messages tagged by emitting node debug, -- :: Int -> String -> IO () -- * debug levels dbgNone, -- :: Int dbgStats, -- :: Int dbgStaticTab, -- :: Int dbgSpark, -- :: Int dbgMsgSend, -- :: Int dbgMsgRcvd, -- :: Int dbgGIVar, -- :: Int dbgIVar, -- :: Int dbgGRef, -- :: Int dbgFailure -- :: Int ) where import Prelude hiding (catch, error) import qualified Prelude (error) import Control.DeepSeq (NFData) import Control.Exception (catch, evaluate) import Control.Monad (when) import Data.Functor ((<$>)) import Data.IORef (readIORef) import Data.Serialize (Serialize) import System.IO (stderr, hPutStrLn) import System.IO.Unsafe (unsafePerformIO) import Control.Parallel.HdpH.Internal.State.Location (myNodeRef, allNodesRef, debugRef) import Control.Parallel.HdpH.Internal.Type.Location (NodeId, MyNodeException(NodeIdUnset)) ----------------------------------------------------------------------------- -- reading this node's own node ID -- Return this node's node ID; -- raises 'NodeIdUnset :: MyNodeException' if node ID has not yet been set -- (by module HdpH.Internal.Comm). myNode :: IO NodeId myNode = readIORef myNodeRef -- Return 'Just' this node's node ID, or 'Nothing' if ID has not yet been set. myNode' :: IO (Maybe NodeId) myNode' = catch (Just <$> (evaluate =<< myNode)) (const $ return Nothing :: MyNodeException -> IO (Maybe NodeId)) -- Return list of all nodes (with main node being head of the list), -- provided the list has been initialised (by module HdpH.Internal.Comm); -- otherwise returns the empty list. allNodes :: IO [NodeId] allNodes = readIORef allNodesRef ----------------------------------------------------------------------------- -- error messages tagged by emitting node -- Abort with error 'message'. error :: String -> a error message = case unsafePerformIO myNode' of Just node -> Prelude.error (show node ++ " " ++ message) Nothing -> Prelude.error message ----------------------------------------------------------------------------- -- debug messages tagged by emitting node -- Output a debug 'message' to 'stderr' if the given 'level' is less than -- or equal to the system level; 'level' should be positive. debug :: Int -> String -> IO () debug level message = do sysLevel <- readIORef debugRef when (level <= sysLevel) $ do maybe_this <- myNode' case maybe_this of Just this -> hPutStrLn stderr $ show this ++ " " ++ message Nothing -> hPutStrLn stderr $ " " ++ message -- debug levels dbgNone = 0 :: Int -- no debug output dbgStats = 1 :: Int -- print final stats dbgStaticTab = 2 :: Int -- on main node, print Static table dbgSpark = 3 :: Int -- spark created or converted dbgMsgSend = 4 :: Int -- message to be sent dbgMsgRcvd = 5 :: Int -- message being handled dbgGIVar = 6 :: Int -- op on a GIVar (globalising or writing to) dbgIVar = 7 :: Int -- blocking/unblocking on IVar (only log event type) dbgGRef = 8 :: Int -- registry update (globalise or free) dbgFailure = 9 :: Int -- e.g. Node failure