private void ConstructFileTable()

in src/Utilities/TrackedDependencies/FlatTrackingData.cs [400:554]


        private void ConstructFileTable()
        {
            string tLogRootingMarker = null;
            try
            {
                // construct a rooting marker from the tlog files
                tLogRootingMarker = DependencyTableCache.FormatNormalizedTlogRootingMarker(_tlogFiles);
            }
            catch (ArgumentException e)
            {
                FileTracker.LogWarningWithCodeFromResources(_log, "Tracking_RebuildingDueToInvalidTLog", e.Message);
                return;
            }
            if (!_tlogsAvailable)
            {
                lock (DependencyTableCache.DependencyTable)
                {
                    // The tracking logs are not available, they may have been deleted at some point.
                    // Be safe and remove any references from the cache.
                    if (DependencyTableCache.DependencyTable.ContainsKey(tLogRootingMarker))
                    {
                        DependencyTableCache.DependencyTable.Remove(tLogRootingMarker);
                    }
                }
                return;
            }

            DependencyTableCacheEntry cachedEntry = null;

            lock (DependencyTableCache.DependencyTable)
            {
                // Look in the dependency table cache to see if its available and up to date
                cachedEntry = DependencyTableCache.GetCachedEntry(tLogRootingMarker);
            }

            // We have an up to date cached entry
            if (cachedEntry != null)
            {
                _dependencyTable = (IDictionary<string, DateTime>)cachedEntry.DependencyTable;

                // We may have stored the dependency table in the cache, but all the other information
                // (newest file time, number of missing files, etc.) has been reset to default.  Refresh
                // the data.  
                this.UpdateFileEntryDetails();

                // Log information about what we're using
                FileTracker.LogMessageFromResources(_log, MessageImportance.Low, "Tracking_TrackingCached");
                foreach (ITaskItem tlogItem in cachedEntry.TlogFiles)
                {
                    FileTracker.LogMessage(_log, MessageImportance.Low, "\t{0}", tlogItem.ItemSpec);
                }
                return;
            }

            FileTracker.LogMessageFromResources(_log, MessageImportance.Low, "Tracking_TrackingLogs");
            // Now we need to construct the rest of the table from the TLOG files
            // If there are any errors in the tlogs, we want to warn, stop parsing tlogs, and empty 
            // out the dependency table, essentially forcing a rebuild.  
            bool encounteredInvalidTLogContents = false;
            bool exceptionCaught = false;
            string invalidTLogName = null;
            foreach (ITaskItem tlogFileName in _tlogFiles)
            {
                try
                {
                    FileTracker.LogMessage(_log, MessageImportance.Low, "\t{0}", tlogFileName.ItemSpec);

                    DateTime tlogLastWriteTimeUtc = NativeMethodsShared.GetLastWriteFileUtcTime(tlogFileName.ItemSpec);
                    if (tlogLastWriteTimeUtc > _newestTLogTimeUtc)
                    {
                        _newestTLogTimeUtc = tlogLastWriteTimeUtc;
                        _newestTLogFileName = tlogFileName.ItemSpec;
                    }

                    using (StreamReader tlog = File.OpenText(tlogFileName.ItemSpec))
                    {
                        string tlogEntry = tlog.ReadLine();

                        while (tlogEntry != null)
                        {
                            if (tlogEntry.Length == 0) // empty lines are a sign that something has gone wrong
                            {
                                encounteredInvalidTLogContents = true;
                                invalidTLogName = tlogFileName.ItemSpec;
                                break;
                            }
                            // Preprocessing for the line entry
                            else if (tlogEntry[0] == '#') // a comment marker should be skipped
                            {
                                tlogEntry = tlog.ReadLine();
                                continue;
                            }
                            else if (tlogEntry[0] == '^' && TreatRootMarkersAsEntries && tlogEntry.IndexOf('|') < 0) // This is a rooting non composite record, and we should keep it
                            {
                                tlogEntry = tlogEntry.Substring(1);

                                if (tlogEntry.Length == 0)
                                {
                                    encounteredInvalidTLogContents = true;
                                    invalidTLogName = tlogFileName.ItemSpec;
                                    break;
                                }
                            }
                            else if (tlogEntry[0] == '^') // root marker is not being treated as an entry, skip it
                            {
                                tlogEntry = tlog.ReadLine();
                                continue;
                            }

                            // If we haven't seen this file before, then record it
                            if (!_dependencyTable.ContainsKey(tlogEntry))
                            {
                                // It may be that this is one of the locations that we should ignore
                                if (!FileTracker.FileIsExcludedFromDependencies(tlogEntry))
                                {
                                    RecordEntryDetails(tlogEntry, true);
                                }
                            }
                            tlogEntry = tlog.ReadLine();
                        }
                    }
                }
                catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e))
                {
                    FileTracker.LogWarningWithCodeFromResources(_log, "Tracking_RebuildingDueToInvalidTLog", e.Message);
                    break;
                }

                if (encounteredInvalidTLogContents)
                {
                    FileTracker.LogWarningWithCodeFromResources(_log, "Tracking_RebuildingDueToInvalidTLogContents", invalidTLogName);
                    break;
                }
            }

            lock (DependencyTableCache.DependencyTable)
            {
                // There were problems with the tracking logs -- we've already warned or errored; now we want to make 
                // sure that we essentially force a rebuild of this particular root. 
                if (encounteredInvalidTLogContents || exceptionCaught)
                {
                    if (DependencyTableCache.DependencyTable.ContainsKey(tLogRootingMarker))
                    {
                        DependencyTableCache.DependencyTable.Remove(tLogRootingMarker);
                    }

                    _dependencyTable = new Dictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase);
                }
                else
                {
                    // Record the newly built dependency table in the cache
                    DependencyTableCache.DependencyTable[tLogRootingMarker] = new DependencyTableCacheEntry(_tlogFiles, (IDictionary)_dependencyTable);
                }
            }
        }