{-# LANGUAGE RankNTypes, DeriveGeneric, DeriveDataTypeable #-}

-- |
-- Module     : Simulation.Aivika.Distributed.Optimistic.Internal.Message
-- Copyright  : Copyright (c) 2015-2017, David Sorokin <david.sorokin@gmail.com>
-- License    : BSD3
-- Maintainer : David Sorokin <david.sorokin@gmail.com>
-- Stability  : experimental
-- Tested with: GHC 7.10.3
--
-- This module defines a message.
--
module Simulation.Aivika.Distributed.Optimistic.Internal.Message
       (Message(..),
        antiMessage,
        antiMessages,
        AcknowledgementMessage(..),
        acknowledgementMessage,
        LogicalProcessMessage(..),
        TimeServerMessage(..),
        InboxProcessMessage(..),
        GeneralMessage(..)) where

import GHC.Generics

import Data.Typeable
import Data.Binary
import Data.Word

import qualified Control.Distributed.Process as DP
import Control.Distributed.Process.Serializable

import Simulation.Aivika.Distributed.Optimistic.State

-- | Represents a message.
data Message =
  Message { Message -> Word64
messageSequenceNo :: Word64,
            -- ^ The sequence number.
            Message -> Double
messageSendTime :: Double,
            -- ^ The send time.
            Message -> Double
messageReceiveTime :: Double,
            -- ^ The receive time.
            Message -> ProcessId
messageSenderId :: DP.ProcessId,
            -- ^ The sender of the message.
            Message -> ProcessId
messageReceiverId :: DP.ProcessId,
            -- ^ The receiver of the message.
            Message -> Bool
messageAntiToggle :: Bool,
            -- ^ Whether this is an anti-message.
            Message -> Message
messageData :: DP.Message
            -- ^ The message data.
          } deriving (Int -> Message -> ShowS
[Message] -> ShowS
Message -> String
(Int -> Message -> ShowS)
-> (Message -> String) -> ([Message] -> ShowS) -> Show Message
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Message -> ShowS
showsPrec :: Int -> Message -> ShowS
$cshow :: Message -> String
show :: Message -> String
$cshowList :: [Message] -> ShowS
showList :: [Message] -> ShowS
Show, Typeable, (forall x. Message -> Rep Message x)
-> (forall x. Rep Message x -> Message) -> Generic Message
forall x. Rep Message x -> Message
forall x. Message -> Rep Message x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Message -> Rep Message x
from :: forall x. Message -> Rep Message x
$cto :: forall x. Rep Message x -> Message
to :: forall x. Rep Message x -> Message
Generic)

instance Binary Message

-- | Return an anti-message.
antiMessage :: Message -> Message
antiMessage :: Message -> Message
antiMessage Message
x = Message
x { messageAntiToggle = not (messageAntiToggle x) }

-- | Whether two messages are anti-messages.
antiMessages :: Message -> Message -> Bool
antiMessages :: Message -> Message -> Bool
antiMessages Message
x Message
y =
  (Message -> Word64
messageSequenceNo Message
x Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> Word64
messageSequenceNo Message
y) Bool -> Bool -> Bool
&&
  (Message -> Double
messageSendTime Message
x Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> Double
messageSendTime Message
y) Bool -> Bool -> Bool
&&
  (Message -> Double
messageReceiveTime Message
x Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> Double
messageReceiveTime Message
y) Bool -> Bool -> Bool
&&
  (Message -> ProcessId
messageSenderId Message
x ProcessId -> ProcessId -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> ProcessId
messageSenderId Message
y) Bool -> Bool -> Bool
&&
  (Message -> ProcessId
messageReceiverId Message
x ProcessId -> ProcessId -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> ProcessId
messageReceiverId Message
y) Bool -> Bool -> Bool
&&
  (Message -> Bool
messageAntiToggle Message
x Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= Message -> Bool
messageAntiToggle Message
y)

instance Eq Message where

  Message
x == :: Message -> Message -> Bool
== Message
y =
    (Message -> Word64
messageSequenceNo Message
x Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> Word64
messageSequenceNo Message
y) Bool -> Bool -> Bool
&&
    (Message -> Double
messageSendTime Message
x Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> Double
messageSendTime Message
y) Bool -> Bool -> Bool
&&
    (Message -> Double
messageReceiveTime Message
x Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> Double
messageReceiveTime Message
y) Bool -> Bool -> Bool
&&
    (Message -> ProcessId
messageSenderId Message
x ProcessId -> ProcessId -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> ProcessId
messageSenderId Message
y) Bool -> Bool -> Bool
&&
    (Message -> ProcessId
messageReceiverId Message
x ProcessId -> ProcessId -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> ProcessId
messageReceiverId Message
y) Bool -> Bool -> Bool
&&
    (Message -> Bool
messageAntiToggle Message
x Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Message -> Bool
messageAntiToggle Message
y)

-- | Represents an acknowledgement message.
data AcknowledgementMessage =
  AcknowledgementMessage { AcknowledgementMessage -> Word64
acknowledgementSequenceNo :: Word64,
                           -- ^ The sequence number.
                           AcknowledgementMessage -> Double
acknowledgementSendTime :: Double,
                           -- ^ The send time.
                           AcknowledgementMessage -> Double
acknowledgementReceiveTime :: Double,
                           -- ^ The receive time.
                           AcknowledgementMessage -> ProcessId
acknowledgementSenderId :: DP.ProcessId,
                           -- ^ The sender of the source message.
                           AcknowledgementMessage -> ProcessId
acknowledgementReceiverId :: DP.ProcessId,
                           -- ^ The receiver of the source message.
                           AcknowledgementMessage -> Bool
acknowledgementAntiToggle :: Bool,
                           -- ^ Whether this is an anti-message acknowledgement.
                           AcknowledgementMessage -> Bool
acknowledgementMarked :: Bool
                           -- ^ Whether the acknowledgement is marked.
                         } deriving (AcknowledgementMessage -> AcknowledgementMessage -> Bool
(AcknowledgementMessage -> AcknowledgementMessage -> Bool)
-> (AcknowledgementMessage -> AcknowledgementMessage -> Bool)
-> Eq AcknowledgementMessage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
== :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
$c/= :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
/= :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
Eq, Eq AcknowledgementMessage
Eq AcknowledgementMessage =>
(AcknowledgementMessage -> AcknowledgementMessage -> Ordering)
-> (AcknowledgementMessage -> AcknowledgementMessage -> Bool)
-> (AcknowledgementMessage -> AcknowledgementMessage -> Bool)
-> (AcknowledgementMessage -> AcknowledgementMessage -> Bool)
-> (AcknowledgementMessage -> AcknowledgementMessage -> Bool)
-> (AcknowledgementMessage
    -> AcknowledgementMessage -> AcknowledgementMessage)
-> (AcknowledgementMessage
    -> AcknowledgementMessage -> AcknowledgementMessage)
-> Ord AcknowledgementMessage
AcknowledgementMessage -> AcknowledgementMessage -> Bool
AcknowledgementMessage -> AcknowledgementMessage -> Ordering
AcknowledgementMessage
-> AcknowledgementMessage -> AcknowledgementMessage
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: AcknowledgementMessage -> AcknowledgementMessage -> Ordering
compare :: AcknowledgementMessage -> AcknowledgementMessage -> Ordering
$c< :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
< :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
$c<= :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
<= :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
$c> :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
> :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
$c>= :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
>= :: AcknowledgementMessage -> AcknowledgementMessage -> Bool
$cmax :: AcknowledgementMessage
-> AcknowledgementMessage -> AcknowledgementMessage
max :: AcknowledgementMessage
-> AcknowledgementMessage -> AcknowledgementMessage
$cmin :: AcknowledgementMessage
-> AcknowledgementMessage -> AcknowledgementMessage
min :: AcknowledgementMessage
-> AcknowledgementMessage -> AcknowledgementMessage
Ord, Int -> AcknowledgementMessage -> ShowS
[AcknowledgementMessage] -> ShowS
AcknowledgementMessage -> String
(Int -> AcknowledgementMessage -> ShowS)
-> (AcknowledgementMessage -> String)
-> ([AcknowledgementMessage] -> ShowS)
-> Show AcknowledgementMessage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AcknowledgementMessage -> ShowS
showsPrec :: Int -> AcknowledgementMessage -> ShowS
$cshow :: AcknowledgementMessage -> String
show :: AcknowledgementMessage -> String
$cshowList :: [AcknowledgementMessage] -> ShowS
showList :: [AcknowledgementMessage] -> ShowS
Show, Typeable, (forall x. AcknowledgementMessage -> Rep AcknowledgementMessage x)
-> (forall x.
    Rep AcknowledgementMessage x -> AcknowledgementMessage)
-> Generic AcknowledgementMessage
forall x. Rep AcknowledgementMessage x -> AcknowledgementMessage
forall x. AcknowledgementMessage -> Rep AcknowledgementMessage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. AcknowledgementMessage -> Rep AcknowledgementMessage x
from :: forall x. AcknowledgementMessage -> Rep AcknowledgementMessage x
$cto :: forall x. Rep AcknowledgementMessage x -> AcknowledgementMessage
to :: forall x. Rep AcknowledgementMessage x -> AcknowledgementMessage
Generic)

instance Binary AcknowledgementMessage

-- | Create an acknowledgement message specifying whether it will be marked.
acknowledgementMessage :: Bool -> Message -> AcknowledgementMessage
acknowledgementMessage :: Bool -> Message -> AcknowledgementMessage
acknowledgementMessage Bool
marked Message
x =
  AcknowledgementMessage { acknowledgementSequenceNo :: Word64
acknowledgementSequenceNo = Message -> Word64
messageSequenceNo Message
x,
                           acknowledgementSendTime :: Double
acknowledgementSendTime = Message -> Double
messageSendTime Message
x,
                           acknowledgementReceiveTime :: Double
acknowledgementReceiveTime = Message -> Double
messageReceiveTime Message
x,
                           acknowledgementSenderId :: ProcessId
acknowledgementSenderId = Message -> ProcessId
messageSenderId Message
x,
                           acknowledgementReceiverId :: ProcessId
acknowledgementReceiverId = Message -> ProcessId
messageReceiverId Message
x,
                           acknowledgementAntiToggle :: Bool
acknowledgementAntiToggle = Message -> Bool
messageAntiToggle Message
x,
                           acknowledgementMarked :: Bool
acknowledgementMarked = Bool
marked
                         }

-- | The message sent to the logical process.
data LogicalProcessMessage = QueueMessage Message
                             -- ^ the message has come from the remote process
                           | QueueMessageBulk [Message]
                             -- ^ a bulk of messages that have come from the remote process
                           | AcknowledgementQueueMessage AcknowledgementMessage
                             -- ^ the acknowledgement message has come from the remote process
                           | AcknowledgementQueueMessageBulk [AcknowledgementMessage]
                             -- ^ a bulk of acknowledgement messages that have come from the remote process
                           | ComputeLocalTimeMessage
                             -- ^ the time server requests for a local minimum time
                           | GlobalTimeMessage Double
                             -- ^ the time server sent a global time
                           | ProcessMonitorNotificationMessage DP.ProcessMonitorNotification
                             -- ^ the process monitor notification
                           | ReconnectProcessMessage DP.ProcessId
                             -- ^ finish reconnecting to the specified process
                           | ProvideLogicalProcessStateMessage DP.ProcessId
                             -- ^ provide the logical process state
                           | AbortSimulationMessage
                             -- ^ abort the simulation
                           | DisconnectProcessMessage DP.ProcessId
                             -- ^ the specified process has been disconnected
                           deriving (Int -> LogicalProcessMessage -> ShowS
[LogicalProcessMessage] -> ShowS
LogicalProcessMessage -> String
(Int -> LogicalProcessMessage -> ShowS)
-> (LogicalProcessMessage -> String)
-> ([LogicalProcessMessage] -> ShowS)
-> Show LogicalProcessMessage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LogicalProcessMessage -> ShowS
showsPrec :: Int -> LogicalProcessMessage -> ShowS
$cshow :: LogicalProcessMessage -> String
show :: LogicalProcessMessage -> String
$cshowList :: [LogicalProcessMessage] -> ShowS
showList :: [LogicalProcessMessage] -> ShowS
Show, Typeable, (forall x. LogicalProcessMessage -> Rep LogicalProcessMessage x)
-> (forall x. Rep LogicalProcessMessage x -> LogicalProcessMessage)
-> Generic LogicalProcessMessage
forall x. Rep LogicalProcessMessage x -> LogicalProcessMessage
forall x. LogicalProcessMessage -> Rep LogicalProcessMessage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. LogicalProcessMessage -> Rep LogicalProcessMessage x
from :: forall x. LogicalProcessMessage -> Rep LogicalProcessMessage x
$cto :: forall x. Rep LogicalProcessMessage x -> LogicalProcessMessage
to :: forall x. Rep LogicalProcessMessage x -> LogicalProcessMessage
Generic)

instance Binary LogicalProcessMessage

-- | The time server message.
data TimeServerMessage = RegisterLogicalProcessMessage DP.ProcessId
                         -- ^ register the logical process in the time server
                       | UnregisterLogicalProcessMessage DP.ProcessId
                         -- ^ unregister the logical process from the time server
                       | TerminateTimeServerMessage DP.ProcessId
                         -- ^ the logical process asked to terminate the time server
                       | ComputeLocalTimeAcknowledgementMessage DP.ProcessId
                         -- ^ the acknowledgement message after the server asked to compute the local time
                       | RequestGlobalTimeMessage DP.ProcessId
                         -- ^ the logical process requested for the global minimum time
                       | LocalTimeMessage DP.ProcessId Double
                         -- ^ the logical process sent its local minimum time
                       | ProvideTimeServerStateMessage DP.ProcessId
                         -- ^ send the time server monitoring state message
                       deriving (TimeServerMessage -> TimeServerMessage -> Bool
(TimeServerMessage -> TimeServerMessage -> Bool)
-> (TimeServerMessage -> TimeServerMessage -> Bool)
-> Eq TimeServerMessage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TimeServerMessage -> TimeServerMessage -> Bool
== :: TimeServerMessage -> TimeServerMessage -> Bool
$c/= :: TimeServerMessage -> TimeServerMessage -> Bool
/= :: TimeServerMessage -> TimeServerMessage -> Bool
Eq, Int -> TimeServerMessage -> ShowS
[TimeServerMessage] -> ShowS
TimeServerMessage -> String
(Int -> TimeServerMessage -> ShowS)
-> (TimeServerMessage -> String)
-> ([TimeServerMessage] -> ShowS)
-> Show TimeServerMessage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TimeServerMessage -> ShowS
showsPrec :: Int -> TimeServerMessage -> ShowS
$cshow :: TimeServerMessage -> String
show :: TimeServerMessage -> String
$cshowList :: [TimeServerMessage] -> ShowS
showList :: [TimeServerMessage] -> ShowS
Show, Typeable, (forall x. TimeServerMessage -> Rep TimeServerMessage x)
-> (forall x. Rep TimeServerMessage x -> TimeServerMessage)
-> Generic TimeServerMessage
forall x. Rep TimeServerMessage x -> TimeServerMessage
forall x. TimeServerMessage -> Rep TimeServerMessage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TimeServerMessage -> Rep TimeServerMessage x
from :: forall x. TimeServerMessage -> Rep TimeServerMessage x
$cto :: forall x. Rep TimeServerMessage x -> TimeServerMessage
to :: forall x. Rep TimeServerMessage x -> TimeServerMessage
Generic)

instance Binary TimeServerMessage

-- | The message destined directly for the inbox process.
data InboxProcessMessage = MonitorProcessMessage DP.ProcessId
                           -- ^ monitor the logical process by its inbox process identifier
                         | TrySendProcessKeepAliveMessage
                           -- ^ try to send a keep alive message
                         | SendQueueMessage DP.ProcessId Message
                           -- ^ send a queue message via the inbox process
                         | SendQueueMessageBulk DP.ProcessId [Message]
                           -- ^ send a bulk of queue messages via the inbox process
                         | SendAcknowledgementQueueMessage DP.ProcessId AcknowledgementMessage
                           -- ^ send an acknowledgement message via the inbox process
                         | SendAcknowledgementQueueMessageBulk DP.ProcessId [AcknowledgementMessage]
                           -- ^ send a bulk of acknowledgement messages via the inbox process
                         | SendLocalTimeMessage DP.ProcessId DP.ProcessId Double
                           -- ^ send the local time message to the time server
                         | SendRequestGlobalTimeMessage DP.ProcessId DP.ProcessId
                           -- ^ send the request for the global virtual time
                         | SendRegisterLogicalProcessMessage DP.ProcessId DP.ProcessId
                           -- ^ register the logical process in the time server
                         | SendUnregisterLogicalProcessMessage DP.ProcessId DP.ProcessId
                           -- ^ unregister the logical process from the time server
                         | SendTerminateTimeServerMessage DP.ProcessId DP.ProcessId
                           -- ^ the logical process asked to terminate the time server
                         | RegisterLogicalProcessAcknowledgementMessage DP.ProcessId
                           -- ^ after registering the logical process in the time server
                         | UnregisterLogicalProcessAcknowledgementMessage DP.ProcessId
                           -- ^ after unregistering the logical process from the time server
                         | TerminateTimeServerAcknowledgementMessage DP.ProcessId
                           -- ^ after started terminating the time server
                         | TerminateInboxProcessMessage
                           -- ^ terminate the inbox process
                         deriving (InboxProcessMessage -> InboxProcessMessage -> Bool
(InboxProcessMessage -> InboxProcessMessage -> Bool)
-> (InboxProcessMessage -> InboxProcessMessage -> Bool)
-> Eq InboxProcessMessage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: InboxProcessMessage -> InboxProcessMessage -> Bool
== :: InboxProcessMessage -> InboxProcessMessage -> Bool
$c/= :: InboxProcessMessage -> InboxProcessMessage -> Bool
/= :: InboxProcessMessage -> InboxProcessMessage -> Bool
Eq, Int -> InboxProcessMessage -> ShowS
[InboxProcessMessage] -> ShowS
InboxProcessMessage -> String
(Int -> InboxProcessMessage -> ShowS)
-> (InboxProcessMessage -> String)
-> ([InboxProcessMessage] -> ShowS)
-> Show InboxProcessMessage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InboxProcessMessage -> ShowS
showsPrec :: Int -> InboxProcessMessage -> ShowS
$cshow :: InboxProcessMessage -> String
show :: InboxProcessMessage -> String
$cshowList :: [InboxProcessMessage] -> ShowS
showList :: [InboxProcessMessage] -> ShowS
Show, Typeable, (forall x. InboxProcessMessage -> Rep InboxProcessMessage x)
-> (forall x. Rep InboxProcessMessage x -> InboxProcessMessage)
-> Generic InboxProcessMessage
forall x. Rep InboxProcessMessage x -> InboxProcessMessage
forall x. InboxProcessMessage -> Rep InboxProcessMessage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. InboxProcessMessage -> Rep InboxProcessMessage x
from :: forall x. InboxProcessMessage -> Rep InboxProcessMessage x
$cto :: forall x. Rep InboxProcessMessage x -> InboxProcessMessage
to :: forall x. Rep InboxProcessMessage x -> InboxProcessMessage
Generic)

instance Binary InboxProcessMessage

-- | The general message type.
data GeneralMessage = KeepAliveMessage
                      -- ^ the keel-alive message.
                    deriving (GeneralMessage -> GeneralMessage -> Bool
(GeneralMessage -> GeneralMessage -> Bool)
-> (GeneralMessage -> GeneralMessage -> Bool) -> Eq GeneralMessage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: GeneralMessage -> GeneralMessage -> Bool
== :: GeneralMessage -> GeneralMessage -> Bool
$c/= :: GeneralMessage -> GeneralMessage -> Bool
/= :: GeneralMessage -> GeneralMessage -> Bool
Eq, Int -> GeneralMessage -> ShowS
[GeneralMessage] -> ShowS
GeneralMessage -> String
(Int -> GeneralMessage -> ShowS)
-> (GeneralMessage -> String)
-> ([GeneralMessage] -> ShowS)
-> Show GeneralMessage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> GeneralMessage -> ShowS
showsPrec :: Int -> GeneralMessage -> ShowS
$cshow :: GeneralMessage -> String
show :: GeneralMessage -> String
$cshowList :: [GeneralMessage] -> ShowS
showList :: [GeneralMessage] -> ShowS
Show, Typeable, (forall x. GeneralMessage -> Rep GeneralMessage x)
-> (forall x. Rep GeneralMessage x -> GeneralMessage)
-> Generic GeneralMessage
forall x. Rep GeneralMessage x -> GeneralMessage
forall x. GeneralMessage -> Rep GeneralMessage x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. GeneralMessage -> Rep GeneralMessage x
from :: forall x. GeneralMessage -> Rep GeneralMessage x
$cto :: forall x. Rep GeneralMessage x -> GeneralMessage
to :: forall x. Rep GeneralMessage x -> GeneralMessage
Generic)

instance Binary GeneralMessage