/// <summary> /// Merge two existing receiver summaries into one /// </summary> /// <param name="r1"></param> /// <param name="r2"></param> public ReceiverSummary(ReceiverSummary r1, ReceiverSummary r2) { this.ssrc = 0; // this value should not be used after merging two summaries... this.packetRate = r1.PacketRate + r2.PacketRate; this.totalLosses = r1.TotalLosses + r2.TotalLosses; this.totalPacketsReceived = r1.TotalPacketsReceived + r2.TotalPacketsReceived; // XXX Is simple averaging the right thing to do? this.LossRate = (r1.LossRate + r2.LossRate) / 2; }
private void BuildBasicReceiverTables(VenueState venueState, out DataTable thptTable, out DataTable lossTable, IDictionary <IPEndPoint, SenderData> senderSummaries) { thptTable = new DataTable(); lossTable = new DataTable(); thptTable.Columns.Add("Receiver IP", Type.GetType("System.String")); thptTable.Columns.Add("CName", Type.GetType("System.String")); lossTable.Columns.Add("Receiver IP", Type.GetType("System.String")); lossTable.Columns.Add("CName", Type.GetType("System.String")); // add a column for each sender... foreach (IPEndPoint endPoint in senderSummaries.Keys) { thptTable.Columns.Add(endPoint.ToString(), Type.GetType("System.String")); lossTable.Columns.Add(endPoint.ToString(), Type.GetType("System.String")); } lock (venueState.ReceiverData) { // add a row for each receiver foreach (IPEndPoint receiverEndpoint in getSortedReceivers(venueState)) { ReceiverData receiverData = venueState.ReceiverData[receiverEndpoint]; if (receiverData == null) { continue; // shouldn't happen... } // process receiver summaries ICollection <ReceiverSummary> summaries = receiverData.ReceiverSummaries; if (summaries == null || summaries.Count == 0) { continue; } DataRow thptRow = thptTable.NewRow(); DataRow lossRow = lossTable.NewRow(); thptRow["Receiver IP"] = receiverEndpoint.ToString(); thptRow["CName"] = receiverData.CName; lossRow["Receiver IP"] = receiverEndpoint.ToString(); lossRow["CName"] = receiverData.CName; // initialize sender columns... foreach (IPEndPoint endPoint in senderSummaries.Keys) { lossRow[endPoint.ToString()] = "no data"; thptRow[endPoint.ToString()] = "no data"; } // process receiver summaries, while merging data from co-located data streams // thus, we should end up with one column per sending host, regardless of its // number of output streams... IDictionary <IPEndPoint, ReceiverSummary> mergedReceiverSummaries = new Dictionary <IPEndPoint, ReceiverSummary>(); // this is the merge phase... foreach (ReceiverSummary summary in summaries) { SenderData senderData; if (!venueState.SenderData.TryGetValue(summary.SSRC, out senderData)) { continue; // no sender data for this receiver summary } IPEndPoint senderEndpoint = senderData.Source; if (senderEndpoint == null) { continue; } if (mergedReceiverSummaries.ContainsKey(senderEndpoint)) { // merge the summary data with existing data from this sender ReceiverSummary existingSummary = mergedReceiverSummaries[senderEndpoint]; ReceiverSummary updatedSummary = new ReceiverSummary(existingSummary, summary); mergedReceiverSummaries[senderEndpoint] = updatedSummary; } else { // otherwise, create a new summary entry for this EndPoint mergedReceiverSummaries[senderEndpoint] = summary; } } // At this point, we have merged data from co-located data streams. Populate // the columns corresponding to source IP addreses. foreach (IPEndPoint senderEndpoint in mergedReceiverSummaries.Keys) { if (thptTable.Columns.Contains(senderEndpoint.ToString())) { ReceiverSummary summary = mergedReceiverSummaries[senderEndpoint]; SenderData senderData = senderSummaries[senderEndpoint]; double throughputDifferential = summary.PacketRate - senderData.PacketRate; try { thptRow[senderEndpoint.ToString()] = String.Format("{0:N} pk/sec", throughputDifferential); //String.Format("{1:N} - {2:N} = {0:N} pk/sec", throughputDifferential, //summary.PacketRate , senderData.PacketRate); lossRow[senderEndpoint.ToString()] = String.Format("{0:P}", summary.LossRate); } catch (Exception) { // these operations can fail when sender and receiver tables are out of sync } } } // mark "loopback" data as such try { thptRow[receiverEndpoint.ToString()] = "loopback"; lossRow[receiverEndpoint.ToString()] = "loopback"; } catch (Exception) { // these operations can fail if sender, receiver tables are out of sync... } thptTable.Rows.Add(thptRow); lossTable.Rows.Add(lossRow); } // for each receiver in the venue } // venue.receiverData lock }
public void updateReceiverState(ArrayList receiverReports, long when, VenueState venueState) { IDictionary <uint, ReceiverSummary> newSummaries = new Dictionary <uint, ReceiverSummary>(); if (when <= lastReceiverStateUpdate) { return; // duplicate information } String timeString = DateTime.Now.ToString("s"); foreach (ReceiverReport receiverReport in receiverReports) { ReceiverSummary summary = null; if (receiverSummaries.ContainsKey(receiverReport.SSRC) && lastReceiverStateUpdate > 0) { /// We have an existing receiver summary: update session statistics summary = receiverSummaries[receiverReport.SSRC]; double packetsReceivedThisInterval = receiverReport.ExtendedHighestSequence - summary.TotalPacketsReceived; double lossesThisInterval = ((ulong)receiverReport.PacketsLost) - summary.TotalLosses; double seconds = ((double)(when - lastReceiverStateUpdate)) / TimeSpan.TicksPerSecond; summary.PacketRate = packetsReceivedThisInterval / seconds; if (lossesThisInterval + packetsReceivedThisInterval == 0) { summary.LossRate = 0.0; //This can happen because some capabilities don't send much data. } else { summary.LossRate = lossesThisInterval / (lossesThisInterval + packetsReceivedThisInterval); } if (venueState.UseLogging) { SenderData senderState = venueState.GetSenderState(receiverReport.SSRC); venueState.WriteLog(timeString + " " + endpoint + " " + senderState.Source + "/" + receiverReport.SSRC + " " + summary.PacketRate + " " + lossesThisInterval); } } else { /// create a new summary summary = new ReceiverSummary(receiverReport.SSRC); } /// in either case, update the session statistics summary.TotalLosses = (ulong)receiverReport.PacketsLost; /// Note: we use EHS as total packets received! summary.TotalPacketsReceived = receiverReport.ExtendedHighestSequence; newSummaries[receiverReport.SSRC] = summary; } // for each receiver report... this.receiverSummaries = newSummaries; lastReceiverStateUpdate = when; }
public void updateReceiverState(ArrayList receiverReports, long when,VenueState venueState) { IDictionary<uint, ReceiverSummary> newSummaries = new Dictionary<uint, ReceiverSummary>(); if (when <= lastReceiverStateUpdate) return; // duplicate information String timeString = DateTime.Now.ToString("s"); foreach (ReceiverReport receiverReport in receiverReports) { ReceiverSummary summary = null; if (receiverSummaries.ContainsKey(receiverReport.SSRC) && lastReceiverStateUpdate > 0) { /// We have an existing receiver summary: update session statistics summary = receiverSummaries[receiverReport.SSRC]; double packetsReceivedThisInterval = receiverReport.ExtendedHighestSequence - summary.TotalPacketsReceived; double lossesThisInterval = ((ulong) receiverReport.PacketsLost) - summary.TotalLosses; double seconds = ((double)(when - lastReceiverStateUpdate)) / TimeSpan.TicksPerSecond; summary.PacketRate = packetsReceivedThisInterval / seconds; if (lossesThisInterval + packetsReceivedThisInterval == 0) { summary.LossRate = 0.0; //This can happen because some capabilities don't send much data. } else { summary.LossRate = lossesThisInterval / (lossesThisInterval + packetsReceivedThisInterval); } if (venueState.UseLogging) { SenderData senderState = venueState.GetSenderState(receiverReport.SSRC); venueState.WriteLog(timeString + " " + endpoint + " " + senderState.Source + "/" + receiverReport.SSRC + " " + summary.PacketRate + " " + lossesThisInterval); } } else { /// create a new summary summary = new ReceiverSummary(receiverReport.SSRC); } /// in either case, update the session statistics summary.TotalLosses = (ulong)receiverReport.PacketsLost; /// Note: we use EHS as total packets received! summary.TotalPacketsReceived = receiverReport.ExtendedHighestSequence; newSummaries[receiverReport.SSRC] = summary; } // for each receiver report... this.receiverSummaries = newSummaries; lastReceiverStateUpdate = when; }