//////////////////////////////////////////////////////////////////////////////////////////////////// /// \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); } }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// \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; } } }