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>
            /// Build a new matrix
            /// </summary>
            /// <param name="venueState"></param>
            public ConnectivityMatrix(VenueState venueState)
            {
                // Aggregate total sender packet rates for each unique sender cname, and
                // compile a mapping of sender ssrc to cname which we will use for merging receiver reports.
                Dictionary <string, Row>  matrix     = new Dictionary <string, Row>();
                Dictionary <uint, string> ssrc2cname = new Dictionary <uint, string>();

                lock (venueState.SenderData) {
                    foreach (uint ssrc in venueState.SenderData.Keys)
                    {
                        SenderData sd = venueState.SenderData[ssrc];
                        //Debug.WriteLine("  Building Matrix SenderData.cname=" + sd.CName + ";ssrc=" + ssrc.ToString());
                        if (matrix.ContainsKey(sd.CName))
                        {
                            matrix[sd.CName].SenderPacketRate += sd.PacketRate;
                        }
                        else
                        {
                            matrix.Add(sd.CName, new Row(sd.CName, sd.PacketRate));
                        }
                        ssrc2cname.Add(ssrc, sd.CName);
                    }
                }

                ////Test code:  Create and remove a bogus sender to test missing participant functionality.
                //if (DateTime.Now.Second < 30) {
                //    matrix.Add("*****@*****.**", new Row("*****@*****.**", 50.15));
                //}
                ////End test code

                // Create the NxN matrix with row and column for each cname
                foreach (Row r in matrix.Values)
                {
                    r.CreateCells(matrix.Values);
                }

                lock (venueState.ReceiverData) {
                    // For each receiver summary, find the sender cname and update the appropriate sender's row.
                    foreach (ReceiverData rd in venueState.ReceiverData.Values)
                    {
                        foreach (ReceiverSummary rs in rd.ReceiverSummaries)
                        {
                            if (ssrc2cname.ContainsKey(rs.SSRC))
                            {
                                string senderCname = ssrc2cname[rs.SSRC];
                                if (matrix.ContainsKey(senderCname))
                                {
                                    matrix[senderCname].UpdateReceiver(rd.CName, rs.PacketRate);
                                }
                            }
                        }
                    }
                }

                //Commit: copy to serialized arrays
                foreach (Row r in matrix.Values)
                {
                    r.CommitRow();
                }
                Rows = new Row[matrix.Count];
                matrix.Values.CopyTo(Rows, 0);

                CreationTime = DateTime.Now;
            }