////////////////////////////////////////////////////////////////////////////////////////////////////
        /// \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;
            }
        }
        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
            });
        }
        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());
            }
        }
        private void MarkerArrived(BaseMessage marker, ChandyLamportChannel channel)
        {
            // Add the weight of the message to the weight of the process
            double messageWeight = marker.GetField(ChandyLamportMessage.FieldKeys.Weight).Value;

            OperationResults.Value[OperationResultKeys.Weight].Value += messageWeight;

            TakeSnapshot(marker);

            // Termination condition
            channel[ElementDictionaries.OperationResults].Value[ChandyLamportChannel.OperationResultKeys.MarkerArrived].Value = true;

            if (InChannels().All(c => c[ElementDictionaries.OperationResults].Value[ChandyLamportChannel.OperationResultKeys.MarkerArrived].Value))
            {
                bool initiator = ElementAttributes.Value[BaseProcess.ElementAttributeKeys.Initiator].Value;
                if (!initiator)
                {
                    Report();
                }
            }
        }
        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;
                }
            }
        }