////////////////////////////////////////////////////////////////////////////////////////////////////
        /// \fn private bool IsTrue(EventTriggerType trigger, BaseMessage message)
        ///
        /// \brief Query if 'trigger' is true.
        ///
        /// \par Description.
        ///      -  Check other triggers type (not the Initialize trigger)
        ///
        /// \par Algorithm.
        ///      -  Get the MessageType of the message and the round of the message
        ///      -  Calculate the other end of the message according to the trigger
        ///         -   For Send events the other end is the target of the message
        ///         -   For Receive events the other end is the source of the message
        ///      -  Check if all the parameters retrieved from the message are equal to the
        ///         EventTrigger members
        ///
        /// \par Usage Notes.
        ///
        /// \author Ilanh
        /// \date 09/05/2018
        ///
        /// \param trigger  (EventTriggerType) - The trigger.
        /// \param message  (BaseMessage) - The message.
        ///
        /// \return True if true, false if not.
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        private bool IsTrue(EventTriggerType trigger, BaseMessage message)
        {
            // Get the data of the message that caused the event
            int     messageRound = message.GetHeaderField(bm.pak.Round);
            dynamic messageType  = message.GetHeaderField(bm.pak.MessageType);

            // Get the other end of the message that caused the event:
            // For a sending event this is the destination of the message
            // For a receive event this is the source of the message
            int messageOtherEnd;

            if (trigger == EventTriggerType.AfterSendMessage || trigger == EventTriggerType.BeforeSendMessage)
            {
                messageOtherEnd = message.GetHeaderField(bm.pak.DestProcess);
            }
            else
            {
                messageOtherEnd = message.GetHeaderField(bm.pak.SourceProcess);
            }

            if (this[Comps.Trigger] == trigger &&
                this[Comps.Round] == messageRound &&
                TypesUtility.CompareDynamics(this[Comps.MessageType], messageType) &&
                this[Comps.OtherEnd] == messageOtherEnd)
            {
                return(true);
            }
            return(false);
        }
        //protected override void RunAlgorithm()
        //{

        //    // For this test fully functioning
        //    // 1. Declare S1 in the process (Operating results)
        //    // 2. Declare Type in the channel (Operating results) (must be inserted manually  to the defs because
        //    //      The program does not allow duplications
        //    // 3. Declare Cs1 in the channel (Private Attributes)
        //    // 4. Declare Cs2 in the channel (Private Attributes)
        //    // 5. Declare Cs3 in the channel (Operation results)

        //    TestChannel channel = (TestChannel)InChannels[0];

        //    // No string key exist
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "No string key exist" });
        //        MessageRouter.MessageBox(new List<string> { channel[s1].ToString() }, "No string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "No string key exist - generated exception" });
        //    }

        //    // Duplicate string key exist
        //    try
        //    {
        //        channel.or.Add(c.ork.Type, "Read from Operation results");
        //    }
        //    catch
        //    { }
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Duplicate string key exist" });
        //        MessageRouter.MessageBox(new List<string> { channel[type].ToString() }, "Duplicate string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Duplicate string key exist - generated exception" });
        //    }

        //    // Single string key exist
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Single string key exist" });
        //        channel[cs3] = "String taken from channel[cs3]";
        //        MessageRouter.MessageBox(new List<string> { channel[cs3].ToString() }, "Single string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Single string key exist - generated exception" });
        //    }

        //    // No key exist
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "No key exist" });
        //        MessageRouter.MessageBox(new List<string> { channel[p.ork.S1].ToString() }, "No key exist");
        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "No key exist - generated exception" });
        //    }

        //    // Duplicate key exist
        //    try
        //    {
        //        channel.or.Add(c.pak.Cs2, "Value taken from or");
        //    }
        //    catch { }
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Duplicate key exist" });
        //        MessageRouter.MessageBox(new List<string> { channel[c.pak.Cs2].ToString() }, "Duplicate string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Duplicate key exist - generated exception" });
        //    }

        //    // Single key exist
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Single key exist" });
        //        channel[c.ork.Cs3] = "Value taken from channel[c.pak.Cs3]";
        //        MessageRouter.MessageBox(new List<string> { channel[c.ork.Cs3].ToString() }, "Single string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Single key exist - generated exception" });
        //    }

        //    // Acess by index
        //    try
        //    {
        //        channel.Cs3 = "Access to channel.Cs3 by index ok";
        //        MessageRouter.MessageBox(new List<string> { channel.Cs3 });
        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Access to channel.Cs3 by index - generated exception" });
        //    }

        //    // BaseMessageKey
        //    TestMessage message = new TestMessage(network, m.MessageTypes.Message1, MessageDataFor_Message1(bm.PrmSource.Prms, null, false), channel, "MessageName");
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message attribute access message.SourcePort" });
        //        message.SourcePort = 123;
        //        MessageRouter.MessageBox(new List<string> { message.SourcePort.ToString() }, "Base message attribute access");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message attribute access message.SourcePort - generated exception" });
        //    }

        //    //BaseMessage index access
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message index access message[_SourcePort ]" });
        //        message[sourcePort] = 456;
        //        MessageRouter.MessageBox(new List<string> { message[sourcePort].ToString() }, "Base message index access");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message index access message[_SourcePort ] - generated exception" });
        //    }

        //    //Message index access
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message index access message[_PrevAttr ]" });
        //        message[prevAttr ] = true;
        //        MessageRouter.MessageBox(new List<string> { message[prevAttr].ToString() }, "Base message index access");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message index access message[_PrevAttr ] - generated exception" });
        //    }

        //    //Check MessageType
        //    try
        //    {
        //        if (TypesUtility.CompareDynamics(message.MessageType, Message1))
        //        {
        //            MessageRouter.MessageBox(new List<string> { "TypesUtility.CompareDynamics(message.MessageType, Message1) returned True" });
        //        }
        //        else
        //        {
        //            MessageRouter.MessageBox(new List<string> { "TypesUtility.CompareDynamics(message.MessageType, Message1) returned False" });
        //        }
        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "TypesUtility.CompareDynamics(message.MessageType, Message1) - generated exception" });
        //    }
        //}

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// \fn public override void ReceiveHandling(BaseMessage message)
        ///
        /// \brief Receive handling.
        ///
        /// \par Description.
        /// -#  This method is activated when a new message arrived to the process
        /// -#  The method processing is done according to their arrival order
        /// -#  If you want to change the order of processing use the ArrangeMessageQ
        ///
        /// \par Algorithm.
        ///
        /// \par Usage Notes.
        /// Usually the algorithm of this method is:
        /// -#  if message type is ... perform ...
        /// -#  if message type is ... perform ...
        ///
        /// \author Ilan Hindy
        /// \date 26/01/2017
        ///
        /// \param message The message.
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public override void ReceiveHandling(BaseMessage message)
        {
            if (ea[ne.eak.Id] == 1)
            {
                int x = 1;
            }
            int round = message.GetHeaderField(bm.pak.Round);

            if (message.GetHeaderField(bm.pak.MessageType) == m.MessageTypes.AlgorithmMessage)
            {
                if (ea[bp.eak.Initiator])
                {
                    round++;
                    if (round == pa[p.pak.MaxRound])
                    {
                        Terminate();
                    }
                    else
                    {
                        or[bp.ork.Round]++;
                        SendAlgorithmMessage(null, SelectingMethod.Exclude, null, round, 0);
                    }
                }
                else
                {
                    SendAlgorithmMessage(null, SelectingMethod.Exclude, null, round, 0);
                }
            }
        }
        //protected override void RunAlgorithm()
        //{

        //    // For this test fully functioning
        //    // 1. Declare S1 in the process (Operating results)
        //    // 2. Declare Type in the channel (Operating results) (must be inserted manually  to the defs because
        //    //      The program does not allow duplications
        //    // 3. Declare Cs1 in the channel (Private Attributes)
        //    // 4. Declare Cs2 in the channel (Private Attributes)
        //    // 5. Declare Cs3 in the channel (Operation results)

        //    TestChannel channel = (TestChannel)InChannels[0];

        //    // No string key exist
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "No string key exist" });
        //        MessageRouter.MessageBox(new List<string> { channel[s1].ToString() }, "No string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "No string key exist - generated exception" });
        //    }

        //    // Duplicate string key exist
        //    try
        //    {
        //        channel.or.Add(c.ork.Type, "Read from Operation results");
        //    }
        //    catch
        //    { }
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Duplicate string key exist" });
        //        MessageRouter.MessageBox(new List<string> { channel[type].ToString() }, "Duplicate string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Duplicate string key exist - generated exception" });
        //    }

        //    // Single string key exist
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Single string key exist" });
        //        channel[cs3] = "String taken from channel[cs3]";
        //        MessageRouter.MessageBox(new List<string> { channel[cs3].ToString() }, "Single string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Single string key exist - generated exception" });
        //    }

        //    // No key exist
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "No key exist" });
        //        MessageRouter.MessageBox(new List<string> { channel[p.ork.S1].ToString() }, "No key exist");
        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "No key exist - generated exception" });
        //    }

        //    // Duplicate key exist
        //    try
        //    {
        //        channel.or.Add(c.pak.Cs2, "Value taken from or");
        //    }
        //    catch { }
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Duplicate key exist" });
        //        MessageRouter.MessageBox(new List<string> { channel[c.pak.Cs2].ToString() }, "Duplicate string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Duplicate key exist - generated exception" });
        //    }

        //    // Single key exist
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Single key exist" });
        //        channel[c.ork.Cs3] = "Value taken from channel[c.pak.Cs3]";
        //        MessageRouter.MessageBox(new List<string> { channel[c.ork.Cs3].ToString() }, "Single string key exist");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Single key exist - generated exception" });
        //    }

        //    // Acess by index
        //    try
        //    {
        //        channel.Cs3 = "Access to channel.Cs3 by index ok";
        //        MessageRouter.MessageBox(new List<string> { channel.Cs3 });
        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Access to channel.Cs3 by index - generated exception" });
        //    }

        //    // BaseMessageKey
        //    TestMessage message = new TestMessage(network, m.MessageTypes.Message1, MessageDataFor_Message1(bm.PrmSource.Prms, null, false), channel, "MessageName");
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message attribute access message.SourcePort" });
        //        message.SourcePort = 123;
        //        MessageRouter.MessageBox(new List<string> { message.SourcePort.ToString() }, "Base message attribute access");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message attribute access message.SourcePort - generated exception" });
        //    }

        //    //BaseMessage index access
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message index access message[_SourcePort ]" });
        //        message[sourcePort] = 456;
        //        MessageRouter.MessageBox(new List<string> { message[sourcePort].ToString() }, "Base message index access");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message index access message[_SourcePort ] - generated exception" });
        //    }

        //    //Message index access
        //    try
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message index access message[_PrevAttr ]" });
        //        message[prevAttr ] = true;
        //        MessageRouter.MessageBox(new List<string> { message[prevAttr].ToString() }, "Base message index access");

        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "Base message index access message[_PrevAttr ] - generated exception" });
        //    }

        //    //Check MessageType
        //    try
        //    {
        //        if (TypesUtility.CompareDynamics(message.MessageType, Message1))
        //        {
        //            MessageRouter.MessageBox(new List<string> { "TypesUtility.CompareDynamics(message.MessageType, Message1) returned True" });
        //        }
        //        else
        //        {
        //            MessageRouter.MessageBox(new List<string> { "TypesUtility.CompareDynamics(message.MessageType, Message1) returned False" });
        //        }
        //    }
        //    catch
        //    {
        //        MessageRouter.MessageBox(new List<string> { "TypesUtility.CompareDynamics(message.MessageType, Message1) - generated exception" });
        //    }
        //}

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// \fn public override void ReceiveHandling(BaseMessage message)
        ///
        /// \brief Receive handling.
        ///
        /// \par Description.
        /// -#  This method is activated when a new message arrived to the process
        /// -#  The method processing is done according to their arrival order
        /// -#  If you want to change the order of processing use the ArrangeMessageQ
        ///
        /// \par Algorithm.
        ///
        /// \par Usage Notes.
        /// Usually the algorithm of this method is:
        /// -#  if message type is ... perform ...
        /// -#  if message type is ... perform ...
        ///
        /// \author Ilan Hindy
        /// \date 26/01/2017
        ///
        /// \param message The message.
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public override void ReceiveHandling(BaseMessage message)
        {
            if (message.GetHeaderField(bm.pak.MessageType) == m.MessageTypes.AlgorithmMessage)
            {
                if (ea[bp.eak.Initiator])
                {
                    if (message.GetHeaderField(bm.pak.Round) < or[bp.ork.Round])
                    {
                        return;
                    }
                    or[bp.ork.Round]++;
                    if (ea[bp.eak.Initiator] && or[bp.ork.Round] == pa[p.pak.MaxRound])
                    {
                        Terminate();
                        return;
                    }
                }
                else
                {
                    if (message.GetHeaderField(bm.pak.Round) <= or[bp.ork.Round])
                    {
                        return;
                    }
                    or[bp.ork.Round]++;
                }
                pp[bp.ppk.Text] = "Id = " + ea[ne.eak.Id].ToString() + "\n Round = " + or[bp.ork.Round].ToString();
                SendAlgorithmMessage(null, SelectingMethod.Exclude, null, or[bp.ork.Round], 0);
            }
        }
        public void AddMessage(BaseMessage message)
        {
            AttributeList channelMessages = OperationResults.Value[OperationResultKeys.ChannelMessages].Value;
            string        messageString   = message.GetField(BaseMessage.FieldKeys.MessageName).Value + ":" +
                                            message.GetHeaderField(BaseMessage.HeaderFieldKeys.SourceProcess).Value.ToString() + "->" +
                                            message.GetHeaderField(BaseMessage.HeaderFieldKeys.DestProcess).Value.ToString();

            channelMessages.Add(new Attribute {
                Value = messageString
            });
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// \fn public override void ReceiveHandling(BaseMessage message)
        ///
        /// \brief Receive handling.
        ///
        /// \par Description.
        /// -#  This method is activated when a new message arrived to the process
        /// -#  The method processing is done according to their arrival order
        /// -#  If you want to change the order of processing use the ArrangeMessageQ
        ///
        /// \par Algorithm.
        ///
        /// \par Usage Notes.
        /// Usually the algorithm of this method is:
        /// -#  if message type is ... perform ...
        /// -#  if message type is ... perform ...
        ///
        /// \author Ilan Hindy
        /// \date 26/01/2017
        ///
        /// \param message The message.
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public override void ReceiveHandling(BaseMessage message)
        {
            LaiYoung_OneRoundChannel channel = (LaiYoung_OneRoundChannel)ChannelFrom(message);

            switch (message.GetHeaderField(bm.pak.MessageType))
            {
            case m.MessageTypes.BaseMessage:
                if (message.GetField(m.baseMessage.Flag))
                {
                    TakeSnapshot();
                }
                else
                {
                    channel.or[c.ork.Arrived] += 1;
                    if (or[p.ork.Recordered])
                    {
                        channel.or[c.ork.State].Add(message.GetField(m.baseMessage.Message));
                    }
                    if (Finished())
                    {
                        PrintResults();
                    }
                }
                break;

            case m.MessageTypes.Presnp:
                channel.or[c.ork.Expected] = message.GetField(m.presnp.NumMsg);
                TakeSnapshot();
                if (Finished())
                {
                    PrintResults();
                }
                break;
            }
        }
        /*
         * Send message report
         * If the process has no record create a record as initiator (because it sended a message without
         *      recieving a message)
         * Increase the number of childrens
         */
        /**********************************************************************************************/
        /**
         * Message send report.
         *
         * \author  Ilan Hindy
         * \date    29/09/2016
         *
         * \param   sendingProcess  The sending process.
         * \param   message         The message.

         **************************************************************************************************/
        public void MessageSendReport(BaseProcess sendingProcess, BaseMessage message)
        {
            int messageSourceProcess = message.GetHeaderField(bm.pak.SourceProcess);
            int messageDestProcess = message.GetHeaderField(bm.pak.DestProcess);
            if (!processesData.ContainsKey(messageSourceProcess))
            {
                ProcessData processData = new ProcessData()
                {
                    initiator = true,
                    numberOfChilds = 1,
                    process = sendingProcess
                };
                processesData.Add(messageSourceProcess, processData);
            }
            else
            {
                processesData[messageSourceProcess].numberOfChilds++;
            }
        }
        /*
         * ReceiveHandling
         * This method is responssible to devide the data received to packets and call
         * the ReceiveHandling method of the process
         * Note that there no connection from the way the data is sent to the way it is
         * Received. That meens that a several packets can be received in one Receive and
         * There is no garentee that the last packet in the data will end.
         * The packets (messages) are send with '#' termination flag
         * The received data is collected in state.buffer
         * Then it is copied to state.sb . The role of this variable is to hold all the
         *      data that was not processed
         * Then it converted to string
         * Then it is devided to packets
         * Then each packet except the last packet is handled
         * Then the last packet is checked :
         *      If the data received ends with '#' - do nothing because that meens that the last
         *          packet is empty
         *      else clear the state.data and fill it with the unterminated last packet to be joined
         *          by the next receive data
         * The following is the handling of a complete packet
         * 1. Generate a message object from the message data
         * 2. If the MessageType attribute of the message is "Terminate" set the termnateFlag and return
         * 3. wait untill the ReceiveHandling method of the process is not locked by another
         *      AsynchronousReader object
         * 4. Activate the ReceiveHandling method of the process with the data.
         */

        /**********************************************************************************************//**
        * Receive handling.
        *
        * \author  Ilan Hindy
        * \date    29/09/2016
        *
        * \param   bytesReceived   The bytes received.
        *
        **************************************************************************************************/

        public void ReceiveHandling(int bytesReceived)
        {
            String content = String.Empty;

            // There  might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(
                                state.buffer, 0, bytesReceived));

            //Convert the data to string
            content = state.sb.ToString();

            // Get the process
            BaseProcess process = state.process;

            //If any end of packets was received
            if (content.IndexOf("#") > -1)
            {
                //Devide the data to packets
                string[] packets = Regex.Split(content, "#");

                //Packet handling
                for (int idx = 0; idx < packets.Length - 1; idx++)
                {
                    //Create message from the packet
                    //BaseMessage message = new BaseMessage(packets[idx]);
                    string processName = "Process_" + process.ea[ne.eak.Id].ToString();
                    Logger.Log(Logger.LogMode.MainLogAndProcessLog, processName, "Receive", "Received message - packets[idx]", packets[idx], "ProcessReceive");
                    BaseMessage message = BaseMessage.CreateMessage(process.Network, packets[idx]);


                    if (TypesUtility.CompareDynamics(message.GetHeaderField(bm.pak.MessageType), bm.MessageTypes.Terminate))
                    {
                        terminateFlag = true;
                    }
                    process.MessageQHandling(ref message, MessageQOperation.AddMessage);
                    MessageRouter.ReportMessageReceive(process, new object[] { message });
                    //Logger.Log(Logger.LogMode.MainLogAndProcessLog, process.ToString(), "Receive", "Received message", message);
                }

                //If there is a unfinished packet
                if (content[content.Length - 1] != '#')
                {
                    //This is the last packet received and it is fregmented with the next package
                    state.sb.Clear();
                    state.sb.Append(packets[packets.Length - 1]);
                }
                else
                {
                    state.sb.Clear();
                }
            }
        }
 /*
  * Receive message report
  * If the process has no record create a record as none initiator (because it received a message
  *      before it seneded a message)
  *      There is a possibility that the process is in sttopped status there for a termination has to be check starting the process
  * Else (If a recored exist for the receiving process)
  *      Decrease the number of childrens in the sending process
  *      Check if the sending process should terminate because the number of it's childrens might be 0
  *
  * Else decrease the number of children in the sending process
  */
 /**********************************************************************************************/
 /**
  * Message receive report.
  *
  * \author  Ilan Hindy
  * \date    29/09/2016
  *
  * \param   recivingProcess The reciving process.
  * \param   message         The message.
  * \param   network         The network.
  *
  * \return  true if it succeeds, false if it fails.
  .
  **************************************************************************************************/
 public bool MessageReceiveReport(BaseProcess recivingProcess, BaseMessage message, BaseNetwork network)
 {
     int messageSourceProcess = message.GetHeaderField(bm.pak.SourceProcess);
     int messageDestProcess = message.GetHeaderField(bm.pak.DestProcess);
     if (!processesData.ContainsKey(messageDestProcess))
     {
         ProcessData processData = new ProcessData()
         {
             initiator = false,
             numberOfChilds = 0,
             parentId = messageSourceProcess,
             process = recivingProcess
         };
         processesData.Add(messageDestProcess, processData);
         return CheckTermination(recivingProcess, network);
     }
     else
     {
         processesData[messageSourceProcess].numberOfChilds --;
         BaseProcess process = network.Processes.First(p => p.ea[ne.eak.Id] == messageSourceProcess);
         return CheckTermination(process, network);
     }
 }
Esempio n. 9
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// \fn protected virtual void BeforeSendOperation(BaseMessage message)
        ///
        /// \brief Before send operation.
        ///
        /// \par Description.
        ///      This method is used for algorithm specific actions before a send of a message
        ///
        /// \par Algorithm.
        ///
        /// \par Usage Notes.
        ///
        /// \author Ilanh
        /// \date 05/04/2017
        ///
        /// \param message  (BaseMessage) - The message.
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        protected override void BeforeSendOperation(BaseMessage message)
        {
            LaiYoung_OneRoundChannel channel = (LaiYoung_OneRoundChannel)ChannelTo(message);

            channel.or[c.ork.Sent]++;
            switch (message.GetHeaderField(bm.pak.MessageType))
            {
            case m.MessageTypes.BaseMessage:
                message.AddField(m.baseMessage.Flag, or[p.ork.Recordered]);
                break;

            case m.MessageTypes.Presnp:
                message.AddField(m.presnp.NumMsg, channel.or[c.ork.Sent]);
                break;
            }
        }
        private void TakeSnapshot(BaseMessage message)
        {
            bool   recorded = OperationResults.Value[OperationResultKeys.Recorded].Value;
            double weight   = message.GetField(ChandyLamportMessage.FieldKeys.Weight).Value;
            int    round    = message.GetHeaderField(BaseMessage.HeaderFieldKeys.Round).Value;

            if (!recorded)
            {
                OperationResults.Value[OperationResultKeys.Recorded].Value = true;
                double messageWeight = weight / (2 * (OutGoingChannels.Count - 1));
                message.GetField(ChandyLamportMessage.FieldKeys.Weight).Value = messageWeight;
                OperationResults.Value[OperationResultKeys.RoundNum].Value    = round;
                SendToNeighbours(message, null);
                OperationResults.Value[OperationResultKeys.Snapshot].Value           = round;
                OperationResults.Value[OperationResultKeys.Weight].Value             = weight / 2;
                OperationResults.Value[OperationResultKeys.ReceivedReportFrom].Value = new AttributeDictionary();
                OperationResults.Value[OperationResultKeys.MessagesReceived].Value   = new AttributeDictionary();
                InChannels().ForEach(c => ((ChandyLamportChannel)c).ClearMessages());
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// \fn protected void Button_Breakpoints_Click(object sender, RoutedEventArgs e)
        ///
        /// \brief Event handler. Called by Button_Breakpoints for click events.
        ///
        /// \par Description.
        ///
        /// \par Algorithm.
        ///
        /// \par Usage Notes.
        ///
        /// \author Ilanh
        /// \date 04/07/2017
        ///
        /// \param sender (object) - Source of the event.
        /// \param e      (RoutedEventArgs) - Routed event information.
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        protected void Button_Breakpoints_Click(object sender, RoutedEventArgs e)
        {
            BaseProcess           process      = (BaseProcess)networkElements[0];
            BaseNetwork           network      = process.Network;
            BaseChannel           channel      = null;
            BaseMessage           message      = null;
            AttributeList         messageQueue = process.or[bp.ork.MessageQ];
            List <NetworkElement> breakpoints  = new List <NetworkElement>();

            breakpoints.Add(network.op[bn.opk.Breakpoints]);
            breakpoints.Add(process.ea[bp.eak.Breakpoints]);
            if (messageQueue.Count > 0)
            {
                message = messageQueue[0];
                channel = process.IncommingChannels.First(c => c.ea[bc.eak.SourceProcess]
                                                          == message.GetHeaderField(bm.pak.SourceProcess));
                breakpoints.Add(channel.op[bn.opk.Breakpoints]);
                breakpoints.Add(message.ea[bp.eak.Breakpoints]);
            }
            //BreakpointWindow breakpointWindow = new BreakpointWindow(BreakpointWindow.ProgramStatus.Running, breakpoints, network, process, channel, message);
            //breakpointWindow.Show();
        }
        private void ReportArrived(BaseMessage report)
        {
            // Get attributes of the process
            AttributeDictionary receivedReportFrom = OperationResults.Value[OperationResultKeys.ReceivedReportFrom].Value;
            bool   initiator       = ElementAttributes.Value[BaseProcess.ElementAttributeKeys.Initiator].Value;
            int    maxRound        = PrivateAttributes.Value[PrivateAttributeKeys.NumberOfRounds].Value;
            int    processId       = ElementAttributes.Value[NetworkElement.ElementAttributeKeys.Id].Value;
            int    processSnapshot = OperationResults.Value[OperationResultKeys.Snapshot].Value;
            int    processRound    = OperationResults.Value[OperationResultKeys.RoundNum].Value;
            double processWeight   = OperationResults.Value[OperationResultKeys.Weight].Value;
            AttributeDictionary processMessagesArived = OperationResults.Value[OperationResultKeys.MessagesReceived].Value;

            // Get attributes of the message
            double        messageWeight         = report.GetField(ChandyLamportMessage.FieldKeys.Weight).Value;
            int           messageId             = report.GetField(ChandyLamportMessage.FieldKeys.Id).Value;
            int           messageSnapshot       = report.GetField(ChandyLamportMessage.FieldKeys.Snapshots).Value;
            int           messageRound          = report.GetHeaderField(BaseMessage.HeaderFieldKeys.Round).Value;
            AttributeList listOfMessagesArrived = report.GetField(ChandyLamportMessage.FieldKeys.MessageSnapshot).Value;

            // The algorithm
            // If a message from the process arrived (in this round)
            // or the round advanced (which mees that the initiator got report from al the processor
            // throw the message
            if (!receivedReportFrom.Keys.Any(key => key == messageId) && processRound == messageRound)
            {
                receivedReportFrom.Add(messageId, new Attribute {
                    Value = messageSnapshot
                });
                processMessagesArived.Add(messageId, new Attribute {
                    Value = listOfMessagesArrived
                });
                if (initiator)
                {
                    processWeight += messageWeight;
                    if (processWeight == 1)
                    {
                        // Add the initiator's snapshot to the snapshot list
                        receivedReportFrom.Add(processId, new Attribute {
                            Value = processSnapshot
                        });
                        // Collect the messages from the channels
                        AttributeList messages = new AttributeList();
                        foreach (ChandyLamportChannel channel in InChannels())
                        {
                            messages.Concat(channel.ReportChannelMessages());
                        }
                        processMessagesArived.Add(processId, new Attribute {
                            Value = messages
                        });

                        // Report the snapshots
                        PrintSnapshot(processRound, receivedReportFrom, processMessagesArived);

                        // Start a new round
                        processRound++;
                        if (processRound < maxRound)
                        {
                            InitNewRound(processRound);
                        }
                        else
                        {
                            Terminate();
                        }
                    }
                    else
                    {
                        // Set the attributes for the initiator
                        OperationResults.Value[OperationResultKeys.Weight].Value             = processWeight;
                        OperationResults.Value[OperationResultKeys.ReceivedReportFrom].Value = receivedReportFrom;
                    }
                }
                else
                {
                    SendToNeighbours(report, null);
                    OperationResults.Value[OperationResultKeys.ReceivedReportFrom].Value = receivedReportFrom;
                }
            }
        }