Exemplo n.º 1
0
        /// <summary>
        /// Analyzes counts and churn of fingerprints, input lists, and optionally
        /// content sizes of sessions in the cache.
        /// </summary>
        /// <param name="sessionNameRegex">Acts as a filter for which sessions to include in the analysis.</param>
        /// <param name="analyzeContent">When true, analysis will include content sizing for each session.</param>
        /// <returns>SessionChurnInfo object for every session analyzed</returns>
        public IEnumerable <SessionChurnInfo> Analyze(Regex sessionNameRegex, bool analyzeContent)
        {
            Contract.Assume(sessionNameRegex != null);

            m_numSessions         = 0;
            m_numSessionsAnalyzed = 0;

            // Used to store every unique strong fingerprint for all sessions
            HashSet <StrongFingerprint> allStrongFingerprints = new HashSet <StrongFingerprint>();

            // Used to store strong fingerprints for a given session
            HashSet <StrongFingerprint> sessionStrongFingerprints = new HashSet <StrongFingerprint>();

            HashSet <WeakFingerprintHash> allWeakFingerprints = new HashSet <WeakFingerprintHash>();

            // Used to store every unique cas element for all sessions
            HashSet <CasHash> allCasHashes = new HashSet <CasHash>();

            // Used to store every unique cas entry for all sessions
            HashSet <CasHash> allCasEntries = new HashSet <CasHash>();

            IEnumerable <Task <string> > unorderedSessionNames = m_cache.EnumerateCompletedSessions();

            IOrderedEnumerable <string> orderedSessionNames = unorderedSessionNames.Select(stringTask => stringTask.Result)
                                                              .Where((sessionName) =>
            {
                m_numSessions++;
                if (sessionNameRegex.IsMatch(sessionName))
                {
                    m_numSessionsAnalyzed++;
                    return(true);
                }
                else
                {
                    return(false);
                }
            })
                                                              .OrderBy(sessionName => sessionName);

            // Dictionary of CAS entry sizes
            Dictionary <CasHash, long> contentSizeTable = new Dictionary <CasHash, long>();

            // Analyze each session in order
            foreach (string sessionName in orderedSessionNames)
            {
                Console.Error.WriteLine("Analyzing session {0}", sessionName);

                // Initialize counters for the current session
                int totalNumberStrongFingerprints  = 0;
                int numberUniqueWeakFingerprints   = 0;
                int numberUniqueStrongFingerprints = 0;
                int numberUniqueCasHashesOverTime  = 0;
                int numberCasHashNoItemsForSession = 0;
                int contentErrors = 0;

                // Clear the set of strong fingerprints in this next session.
                sessionStrongFingerprints.Clear();

                // Contains every unique cas hash for the current session
                HashSet <CasHash> sessionCasHashes = new HashSet <CasHash>();

                IEnumerable <Task <StrongFingerprint> > strongFingerprints = m_cache.EnumerateSessionStrongFingerprints(sessionName).Result;

                // Analyze each strong fingerprint
                foreach (Task <StrongFingerprint> strongFingerprintTask in strongFingerprints.OutOfOrderTasks())
                {
                    totalNumberStrongFingerprints++;

                    StrongFingerprint strongFingerprint = strongFingerprintTask.Result;

                    sessionStrongFingerprints.Add(strongFingerprint);

                    // Check if strong fingerprint has never been seen before
                    if (allStrongFingerprints.Add(strongFingerprint))
                    {
                        // New strong fingerprint so increment counter and add to collection
                        numberUniqueStrongFingerprints++;
                    }

                    if (allWeakFingerprints.Add(strongFingerprint.WeakFingerprint))
                    {
                        numberUniqueWeakFingerprints++;
                    }

                    CasHash casElement = strongFingerprint.CasElement;

                    // Check if the cas hash is the special no item value
                    if (casElement.Equals(CasHash.NoItem))
                    {
                        numberCasHashNoItemsForSession++;
                    }

                    // Collect unique CAS elements in the session
                    sessionCasHashes.Add(casElement);

                    // Check if cas hash has never been seen before for the whole cache
                    if (allCasHashes.Add(casElement))
                    {
                        numberUniqueCasHashesOverTime++;
                    }
                }

                SessionContentInfo sessionContentInfo = null;

                if (analyzeContent)
                {
                    // Contains every unique cash entry hash for the current session
                    var sessionCasEntries = new HashSet <CasHash>();

                    // Accumulate all the CasEntries for the session
                    foreach (var task in m_session.GetCacheEntries(sessionStrongFingerprints).OutOfOrderTasks(32))
                    {
                        var possibleCasEntries = task.Result;
                        if (possibleCasEntries.Succeeded)
                        {
                            var casEntries = possibleCasEntries.Result;
                            sessionCasEntries.UnionWith(casEntries);
                        }
                        else
                        {
                            Console.Error.WriteLine("Unable to get CasEntries: {0}", possibleCasEntries.Failure.DescribeIncludingInnerFailures());
                            ++contentErrors;
                        }
                    }

                    // Retrieve the content size for each new CasEntry.
                    foreach (var task in m_session.GetContentSizes(sessionCasEntries.Except(allCasEntries)).OutOfOrderTasks(32))
                    {
                        var tuple = task.Result;
                        contentSizeTable[tuple.Item1] = tuple.Item2;
                    }

                    // Accumulate the size of content we've already seen.
                    long totalContentSize = 0;
                    long newContentSize   = 0;
                    var  newContentCount  = 0;

                    foreach (var e in sessionCasEntries)
                    {
                        long length;

                        if (contentSizeTable.TryGetValue(e, out length))
                        {
                            if (ValidContentSize(length))
                            {
                                totalContentSize += length;

                                if (!allCasEntries.Contains(e))
                                {
                                    newContentSize  += length;
                                    newContentCount += 1;
                                    allCasEntries.Add(e);
                                }
                            }
                            else
                            {
                                Console.Error.WriteLine("Unable to find content length ({0}) for {1}", (ContentError)length, e);
                                ++contentErrors;
                            }
                        }
                        else
                        {
#pragma warning disable CA2201 // Do not raise reserved exception types
                            throw new ApplicationException($"No content length for {e}");
#pragma warning restore CA2201 // Do not raise reserved exception types
                        }
                    }

                    sessionContentInfo = new SessionContentInfo(
                        sessionCasEntries.Count,
                        totalContentSize,
                        newContentCount,
                        newContentSize,
                        contentErrors);
                }

                // Aggregate the counters and return the session's data
                SessionStrongFingerprintChurnInfo sessionStrongFingerprintChurnInfo =
                    new SessionStrongFingerprintChurnInfo(totalNumberStrongFingerprints, numberUniqueStrongFingerprints, numberUniqueWeakFingerprints);

                SessionInputListChurnInfo sessionInputListChurnInfo =
                    new SessionInputListChurnInfo(totalNumberStrongFingerprints, sessionCasHashes.Count, numberUniqueCasHashesOverTime, numberCasHashNoItemsForSession);

                yield return(new SessionChurnInfo(sessionName, sessionStrongFingerprintChurnInfo, sessionInputListChurnInfo, sessionContentInfo));
            }
        }