/// <summary> /// Compare the participants in the connectivity matrix with known venue participants. /// Compare the missing participants with those that were missing last time we checked, and /// queue events for any changes. /// </summary> /// <param name="connectivityMatrix"></param> /// <param name="events"></param> private void CheckMissingParticipants(ConnectivityMatrix connectivityMatrix, List <DiagnosticUpdateEventArgs> events) { //Make the current list of missing participants. List <string> missingParticipants = new List <string>(); foreach (Row r in connectivityMatrix.Rows) { if ((!r.SenderCname.Equals(m_LocalCname)) && (!m_Participants.Contains(r.SenderCname))) { missingParticipants.Add(r.SenderCname); } } //Compare missingParticipants with m_PreviousMissingParticipants foreach (string s in missingParticipants) { if (!m_PreviousMissingParticipants.Contains(s)) { //Queue event for new missing participant events.Add(new DiagnosticUpdateEventArgs(DiagnosticEventType.MissingParticipantAdded, s)); } } foreach (string s in m_PreviousMissingParticipants) { if (!missingParticipants.Contains(s)) { //Queue event for resolution of missing participant events.Add(new DiagnosticUpdateEventArgs(DiagnosticEventType.MissingParticipantRemoved, s)); } } //Save the current list of missing participants for next time. m_PreviousMissingParticipants = missingParticipants; }
public ConnectivityMatrix GetMatrix(string venue) { if ((Global.venueStateMap!= null) && (Global.venueStateMap.ContainsKey(venue))) { VenueState venueState = Global.venueStateMap[venue]; //The VenueState.ParticipantChange flag indicates that a participant left the venue since we checked last. if ((!venueState.ParticipantChange) && (DiagnosticWebService.ConnectivityMatrixCache.ContainsKey(venue))) { //Here we have a cached value, check for timeout. if (DateTime.Now - DiagnosticWebService.ConnectivityMatrixCache[venue].CreationTime < TimeSpan.FromSeconds(DiagnosticWebService.CONNECTIVITY_MATRIX_TIMEOUT)) { //Debug.WriteLine("Returned Cached Matrix."); return DiagnosticWebService.ConnectivityMatrixCache[venue]; } else { //cache timeout DiagnosticWebService.ConnectivityMatrixCache.Remove(venue); } } ConnectivityMatrix cm = new ConnectivityMatrix(venueState); if (DiagnosticWebService.ConnectivityMatrixCache.ContainsKey(venue)) { DiagnosticWebService.ConnectivityMatrixCache.Remove(venue); } DiagnosticWebService.ConnectivityMatrixCache.Add(venue, cm); //Debug.WriteLine("Built new matrix: " + cm.ToString()); return cm; } else { return null; } }
public ConnectivityMatrix GetMatrix(string venue) { if ((Global.venueStateMap != null) && (Global.venueStateMap.ContainsKey(venue))) { VenueState venueState = Global.venueStateMap[venue]; //The VenueState.ParticipantChange flag indicates that a participant left the venue since we checked last. if ((!venueState.ParticipantChange) && (DiagnosticWebService.ConnectivityMatrixCache.ContainsKey(venue))) { //Here we have a cached value, check for timeout. if (DateTime.Now - DiagnosticWebService.ConnectivityMatrixCache[venue].CreationTime < TimeSpan.FromSeconds(DiagnosticWebService.CONNECTIVITY_MATRIX_TIMEOUT)) { //Debug.WriteLine("Returned Cached Matrix."); return(DiagnosticWebService.ConnectivityMatrixCache[venue]); } else { //cache timeout DiagnosticWebService.ConnectivityMatrixCache.Remove(venue); } } ConnectivityMatrix cm = new ConnectivityMatrix(venueState); if (DiagnosticWebService.ConnectivityMatrixCache.ContainsKey(venue)) { DiagnosticWebService.ConnectivityMatrixCache.Remove(venue); } DiagnosticWebService.ConnectivityMatrixCache.Add(venue, cm); //Debug.WriteLine("Built new matrix: " + cm.ToString()); return(cm); } else { return(null); } }
/// <summary> /// Check each cell in the connectivity matrix for throughput numbers that are above the warning threshold. /// If the list changed since last time we checked, queue events. /// </summary> /// <param name="connectivityMatrix"></param> /// <param name="events"></param> private void CheckThroughput(ConnectivityMatrix connectivityMatrix, List <DiagnosticUpdateEventArgs> events) { /// Note: The sender and receiver numbers have been observed occasionally to be off by up to 20% /// when there are no apparent throughput problems. This is probably just due to the fact that /// the reporting intervals are not aligned. It seems rare however for the numbers to be off by /// more than 10% on consecutive intervals. Given the inaccuracy, probably the best approach will /// be to use a weighted average. The simple approach taken here is to average the current value /// with the previous average. List <SenderReceiverPair> currentPairs = new List <SenderReceiverPair>(); //Update throughput averages foreach (Row r in connectivityMatrix.Rows) { foreach (Cell c in r.Cells) { SenderReceiverPair srp = new SenderReceiverPair(r.SenderCname, c.ReceiverCname); currentPairs.Add(srp); if (!m_ThroughputAverages.ContainsKey(srp)) { //Give every new SenderReceiverPair a zero to start and ignore the first set of data //since we can sometimes get big throughput differentials during the join. m_ThroughputAverages.Add(srp, 0.0); //Trace.WriteLine("Created a new throughput average for this pair. Ignoring current interval. " + srp.Sender + "/" + srp.Receiver ); continue; } if (c.ThroughputDifferential < 0) { //Negative ThroughputDifferential means more packets were received than sent. Count it as zero. m_ThroughputAverages[srp] = (m_ThroughputAverages[srp] / 2.0); //Trace.WriteLine("Differential for this interval is a negative number; counting as zero"); //Trace.WriteLine("Throughput average for " + srp.Sender + "/" + srp.Receiver + " is " + m_ThroughputAverages[srp].ToString()); continue; } if (r.SenderPacketRate == 0) { //Trace.WriteLine("Sender packet rate is zero."); continue; } //Average current and previous values double normalizedThroughputDifferential = c.ThroughputDifferential / r.SenderPacketRate; m_ThroughputAverages[srp] = (m_ThroughputAverages[srp] + normalizedThroughputDifferential) / 2.0; //Trace.WriteLine("Differential for this interval is " + normalizedThroughputDifferential.ToString()); //Trace.WriteLine("Throughput average for " + srp.Sender + "/" + srp.Receiver + " is " + m_ThroughputAverages[srp].ToString()); } } //Purge averages for pairs that do not appear in the current matrix. These probably left the venue. Dictionary <SenderReceiverPair, double> newAverages = new Dictionary <SenderReceiverPair, double>(); foreach (SenderReceiverPair srp in m_ThroughputAverages.Keys) { if (currentPairs.Contains(srp)) { newAverages.Add(srp, m_ThroughputAverages[srp]); } else { //Trace.WriteLine("Purging pair: " + srp.Sender + "/" + srp.Receiver); } } m_ThroughputAverages = newAverages; //Look for averages above the warning threshold, and add warning events. List <SenderReceiverPair> currentThroughputWarnings = new List <SenderReceiverPair>(); foreach (SenderReceiverPair srp in m_ThroughputAverages.Keys) { if (m_ThroughputAverages[srp] > DiagnosticMonitor.ThroughputThreshold) { currentThroughputWarnings.Add(srp); //Add event only if it is not already in the warning state if (!m_PreviousThroughputWarnings.Contains(srp)) { events.Add(new DiagnosticUpdateEventArgs(DiagnosticEventType.ThroughputWarningAdded, srp.Sender, srp.Receiver)); } } } //Look for pairs in the previous list but not in the current list and add event to remove the warning. foreach (SenderReceiverPair srp in m_PreviousThroughputWarnings) { if (!currentThroughputWarnings.Contains(srp)) { events.Add(new DiagnosticUpdateEventArgs(DiagnosticEventType.ThroughputWarningRemoved, srp.Sender, srp.Receiver)); } } //Save the current list for next time. m_PreviousThroughputWarnings = currentThroughputWarnings; }