internal static bool GetBackupFileTimestamp(string backupFileName, out EtwEventTimestamp dataTimestamp)
        {
            dataTimestamp                = new EtwEventTimestamp();
            dataTimestamp.Timestamp      = DateTime.MinValue;
            dataTimestamp.Differentiator = 0;

            string fileNameWithoutExtension = Path.ChangeExtension(
                backupFileName,
                null);
            string timestampAsString = fileNameWithoutExtension.Remove(
                0,
                BackupFilePrefix.Length);

            string[] timestampParts = timestampAsString.Split('_');
            if (timestampParts.Length != (int)TimestampParts.Count)
            {
                Utility.TraceSource.WriteError(
                    TraceType,
                    "Timestamp information {0} in file name {1} is not in the correct format.",
                    timestampAsString,
                    backupFileName);
                return(false);
            }

            long timestampAsBinary;

            if (false == long.TryParse(
                    timestampParts[(int)TimestampParts.Timestamp],
                    out timestampAsBinary))
            {
                Utility.TraceSource.WriteError(
                    TraceType,
                    "Unable to parse {0} in file name {1} as a long integer.",
                    timestampParts[(int)TimestampParts.Timestamp],
                    backupFileName);
                return(false);
            }

            DateTime timestamp = DateTime.FromBinary(timestampAsBinary);

            int differentiator;

            if (false == int.TryParse(
                    timestampParts[(int)TimestampParts.Differentiator],
                    out differentiator))
            {
                Utility.TraceSource.WriteError(
                    TraceType,
                    "Unable to parse {0} in file name {1} as a long integer.",
                    timestampParts[(int)TimestampParts.Differentiator],
                    backupFileName);
                return(false);
            }

            dataTimestamp.Timestamp      = timestamp;
            dataTimestamp.Differentiator = differentiator;
            return(true);
        }
        internal bool Read()
        {
            // Get the backup files
            // Note: There might be more than one backup file if we encountered
            // errors during previous attempts to delete one or more files.
            string backupFilePattern = string.Concat(
                BackupFilePrefix,
                "*.",
                BackupFileExt);
            DirectoryInfo dirInfo = new DirectoryInfo(this.backupDirectory);

            FileInfo[] backupFiles = dirInfo.GetFiles(backupFilePattern);

            // If we didn't find any backup files, then return immediately
            if (backupFiles.Length == 0)
            {
                Utility.TraceSource.WriteInfo(
                    TraceType,
                    "No backup files found in directory {0}",
                    this.backupDirectory);
                return(true);
            }

            // Get the latest backup file. We only care about the latest.
            Array.Sort(backupFiles, this.CompareFileLastWriteTimes);
            FileInfo backupFile = backupFiles[0];

            // Get the timestamp up to which up to which the backup file is valid.
            EtwEventTimestamp dataTimestamp;

            if (false == GetBackupFileTimestamp(
                    backupFile.Name,
                    out dataTimestamp))
            {
                return(false);
            }

            this.LatestBackupTime = dataTimestamp;

            Utility.TraceSource.WriteInfo(
                TraceType,
                "Backup file {0} is valid up to {1} ({2}, {3}).",
                backupFile.FullName,
                dataTimestamp.Timestamp,
                dataTimestamp.Timestamp.Ticks,
                dataTimestamp.Differentiator);

            Utility.TraceSource.WriteInfo(
                TraceType,
                "Reading backup file {0} ...",
                backupFile.FullName);

            // Read data from the backup file
            return(this.ReadFromBackupFile(backupFile.FullName, dataTimestamp));
        }
        internal ServicePackageTableBackup(
            string directory,
            ServicePackageTableManager.AddOrUpdateHandler addOrUpdateServicePackageHandler)
        {
            this.backupDirectory = directory;
            this.addOrUpdateServicePackageHandler = addOrUpdateServicePackageHandler;
            EtwEventTimestamp etwEventTimestamp = new EtwEventTimestamp();

            etwEventTimestamp.Timestamp      = DateTime.MinValue;
            etwEventTimestamp.Differentiator = 0;
            this.LatestBackupTime            = etwEventTimestamp;
        }
        private void ProcessServicePackageInactiveEvent(
            EventRecord eventRecord,
            string taskName,
            string eventName,
            EtwEventTimestamp eventTimestamp,
            bool implicitlyInactive)
        {
            ApplicationDataReader reader = new ApplicationDataReader(
                eventRecord.UserData,
                eventRecord.UserDataLength);

            // Verify event version
            int eventVersion = reader.ReadInt32();

            if (eventVersion > MaxServicePackageDeactivatedEventVersion)
            {
                Utility.TraceSource.WriteError(
                    TraceType,
                    "Unexpected version {0} encountered for event name {1}. Event will be ignored.",
                    eventVersion,
                    eventName);
                return;
            }

            // Get the node name
            string nodeName = reader.ReadUnicodeString();

            // Get the application instance ID
            string appInstanceId = reader.ReadUnicodeString();

            // Get the service package name
            string servicePackageName = reader.ReadUnicodeString();

            Utility.TraceSource.WriteInfo(
                TraceType,
                "ETW event received. Task {0}, event {1}, node name: {2}, application instance ID: {3}, service package name: {4}.",
                taskName,
                eventName,
                nodeName,
                appInstanceId,
                servicePackageName);

            // Delete record from service package table
            this.RemoveServicePackageHandler(nodeName, appInstanceId, servicePackageName, eventTimestamp, true, implicitlyInactive);
        }
Пример #5
0
        internal int CompareTo(EtwEventTimestamp otherTimestamp)
        {
            int dateTimeCompareResult = this.Timestamp.CompareTo(otherTimestamp.Timestamp);

            if (dateTimeCompareResult != 0)
            {
                return(dateTimeCompareResult);
            }

            if (this.Differentiator < otherTimestamp.Differentiator)
            {
                return(-1);
            }
            else if (this.Differentiator == otherTimestamp.Differentiator)
            {
                return(0);
            }
            else
            {
                return(1);
            }
        }
        private void ProcessTableRecord(string tableRecord, string backupFilePath, EtwEventTimestamp dataTimestamp)
        {
            string[] tableRecordParts = tableRecord.Split(',');
            if (tableRecordParts.Length != (int)TableRecordParts.Count)
            {
                Utility.TraceSource.WriteError(
                    TraceType,
                    "Table record {0} in backup file {1} is not in the correct format.",
                    tableRecord,
                    backupFilePath);
                return;
            }

            string nodeName              = tableRecordParts[(int)TableRecordParts.NodeName].Trim();
            string appInstanceId         = tableRecordParts[(int)TableRecordParts.ApplicationInstanceId].Trim();
            string appRolloutVersion     = tableRecordParts[(int)TableRecordParts.ApplicationRolloutVersion].Trim();
            string servicePackageName    = tableRecordParts[(int)TableRecordParts.ServicePackageName].Trim();
            string serviceRolloutVersion = tableRecordParts[(int)TableRecordParts.ServiceRolloutVersion].Trim();
            string runLayoutRoot         = tableRecordParts[(int)TableRecordParts.RunLayoutRoot].Trim();

            ServicePackageTableRecord record = new ServicePackageTableRecord(
                nodeName,
                appInstanceId,
                appRolloutVersion,
                servicePackageName,
                serviceRolloutVersion,
                runLayoutRoot,
                default(DateTime));

            this.addOrUpdateServicePackageHandler(
                nodeName,
                appInstanceId,
                DateTime.MaxValue, // service package activation time unknown
                servicePackageName,
                record,
                dataTimestamp,
                false);
        }
        private bool ReadFromBackupFile(string backupFilePath, EtwEventTimestamp dataTimestamp)
        {
            // Open the backup file
            StreamReader reader = null;

            try
            {
                Utility.PerformIOWithRetries(
                    () =>
                {
                    FileStream file = FabricFile.Open(backupFilePath, FileMode.Open, FileAccess.Read);
#if !DotNetCoreClrLinux
                    Helpers.SetIoPriorityHint(file.SafeFileHandle, Kernel32Types.PRIORITY_HINT.IoPriorityHintVeryLow);
#endif
                    reader = new StreamReader(file);
                });
            }
            catch (Exception e)
            {
                Utility.TraceSource.WriteExceptionAsError(
                    TraceType,
                    e,
                    "Unable to open backup file {0}",
                    backupFilePath);
                return(false);
            }

            try
            {
                // Get the version line
                string versionLine = string.Empty;
                try
                {
                    Utility.PerformIOWithRetries(
                        () =>
                    {
                        versionLine = reader.ReadLine();
                    });
                }
                catch (Exception e)
                {
                    Utility.TraceSource.WriteExceptionAsError(
                        TraceType,
                        e,
                        "Unable to read version line from backup file {0}",
                        backupFilePath);
                    return(false);
                }

                if (null == versionLine)
                {
                    Utility.TraceSource.WriteError(
                        TraceType,
                        "Backup file {0} does not contain a version line.",
                        backupFilePath);
                    return(false);
                }

                // Ensure that the version line is compatible
                if (false == versionLine.Equals(
                        BackupFileVersionString,
                        StringComparison.Ordinal))
                {
                    Utility.TraceSource.WriteError(
                        TraceType,
                        "Backup file {0} has incompatible file version '{1}'.",
                        backupFilePath,
                        versionLine);
                    return(false);
                }

                // Read the service package table rows from the file
                string tableRecord = null;
                for (;;)
                {
                    tableRecord = string.Empty;
                    try
                    {
                        Utility.PerformIOWithRetries(
                            () =>
                        {
                            tableRecord = reader.ReadLine();
                        });
                    }
                    catch (Exception e)
                    {
                        Utility.TraceSource.WriteExceptionAsError(
                            TraceType,
                            e,
                            "Unable to retrieve table record from backup file {0}",
                            backupFilePath);
                        return(false);
                    }

                    if (null == tableRecord)
                    {
                        // Reached end of file
                        Utility.TraceSource.WriteInfo(
                            TraceType,
                            "Reached end of backup file {0}",
                            backupFilePath);
                        break;
                    }

                    this.ProcessTableRecord(tableRecord, backupFilePath, dataTimestamp);
                }
            }
            finally
            {
                reader.Dispose();
            }

            return(true);
        }
        internal bool Update(Dictionary <string, ServicePackageTableRecord> servicePackageTable, EtwEventTimestamp latestDataTimestamp)
        {
            // Create a new temp file
            string tempFilePath = Utility.GetTempFileName();

            string backupFilePath = string.Empty;

            try
            {
                // Open the temp file
                StreamWriter writer = null;
                try
                {
                    Utility.PerformIOWithRetries(
                        () =>
                    {
                        FileStream file = FabricFile.Open(tempFilePath, FileMode.Create, FileAccess.Write);
#if !DotNetCoreClrLinux
                        Helpers.SetIoPriorityHint(file.SafeFileHandle, Kernel32Types.PRIORITY_HINT.IoPriorityHintVeryLow);
#endif
                        writer = new StreamWriter(file);
                    });
                }
                catch (Exception e)
                {
                    Utility.TraceSource.WriteExceptionAsError(
                        TraceType,
                        e,
                        "Failed to open temp file {0}.",
                        tempFilePath);
                    return(false);
                }

                try
                {
                    // Write the version information to the backup file
                    try
                    {
                        Utility.PerformIOWithRetries(
                            () =>
                        {
                            writer.WriteLine(BackupFileVersionString);
                        });
                    }
                    catch (Exception e)
                    {
                        Utility.TraceSource.WriteExceptionAsError(
                            TraceType,
                            e,
                            "Failed to write version information to temp file {0}.",
                            tempFilePath);
                        return(false);
                    }

                    // Write the table records to the backup file
                    foreach (string tableKey in servicePackageTable.Keys)
                    {
                        string tableRecord = string.Concat(
                            servicePackageTable[tableKey].NodeName,
                            ", ",
                            servicePackageTable[tableKey].ApplicationInstanceId,
                            ", ",
                            servicePackageTable[tableKey].ApplicationRolloutVersion,
                            ", ",
                            servicePackageTable[tableKey].ServicePackageName,
                            ", ",
                            servicePackageTable[tableKey].ServiceRolloutVersion,
                            ", ",
                            servicePackageTable[tableKey].RunLayoutRoot);

                        try
                        {
                            Utility.PerformIOWithRetries(
                                () =>
                            {
                                writer.WriteLine(tableRecord);
                            });
                        }
                        catch (Exception e)
                        {
                            Utility.TraceSource.WriteExceptionAsError(
                                TraceType,
                                e,
                                "Failed to write record {0} to temp file {1}",
                                tableRecord,
                                tempFilePath);
                            return(false);
                        }
                    }
                }
                finally
                {
                    writer.Dispose();
                }

                // Compute the name of the backup file
                long   timstampBinary = latestDataTimestamp.Timestamp.ToBinary();
                string fileName       = string.Concat(
                    BackupFilePrefix,
                    timstampBinary.ToString("D20", CultureInfo.InvariantCulture),
                    "_",
                    latestDataTimestamp.Differentiator.ToString("D10", CultureInfo.InvariantCulture),
                    ".",
                    BackupFileExt);
                backupFilePath = Path.Combine(this.backupDirectory, fileName);

                // Copy the temp file as the new backup file
                try
                {
                    Utility.PerformIOWithRetries(
                        () =>
                    {
                        FabricFile.Copy(tempFilePath, backupFilePath, true);
                    });
                }
                catch (Exception e)
                {
                    Utility.TraceSource.WriteExceptionAsError(
                        TraceType,
                        e,
                        "Failed to copy file {0} to {1}",
                        tempFilePath,
                        backupFilePath);
                    return(false);
                }

                Utility.TraceSource.WriteInfo(
                    TraceType,
                    "Backup file {0} created. The backup file is valid up to timestamp {1} ({2}, {3}).",
                    backupFilePath,
                    latestDataTimestamp.Timestamp,
                    latestDataTimestamp.Timestamp.Ticks,
                    latestDataTimestamp.Differentiator);
            }
            finally
            {
                try
                {
                    Utility.PerformIOWithRetries(
                        () =>
                    {
                        FabricFile.Delete(tempFilePath);
                    });
                }
                catch (Exception e)
                {
                    Utility.TraceSource.WriteExceptionAsError(
                        TraceType,
                        e,
                        "Failed to delete temp file {0}",
                        tempFilePath);
                }
            }

            // Update the latest backup time
            this.LatestBackupTime = latestDataTimestamp;

            // Delete older backup files
            string backupFilePattern = string.Concat(
                BackupFilePrefix,
                "*.",
                BackupFileExt);
            string[] backupFiles = FabricDirectory.GetFiles(
                this.backupDirectory,
                backupFilePattern);
            foreach (string fileToDelete in backupFiles)
            {
                if (fileToDelete.Equals(
                        backupFilePath,
                        StringComparison.OrdinalIgnoreCase))
                {
                    // Don't delete the current backup file
                    continue;
                }

                try
                {
                    Utility.PerformIOWithRetries(
                        () =>
                    {
                        FabricFile.Delete(fileToDelete);
                    });
                }
                catch (Exception e)
                {
                    // Deletion is on a best-effort basis. Log an error and
                    // continue.
                    Utility.TraceSource.WriteExceptionAsError(
                        TraceType,
                        e,
                        "Failed to delete old backup file {0}",
                        fileToDelete);
                }
            }

            return(true);
        }
        protected void OnEtwEventReceived(object sender, EventRecordEventArgs e)
        {
            if (this.Stopping)
            {
                // DCA is stopping. Don't process any more events.
                return;
            }

            DateTime          eventDateTime  = DateTime.FromFileTimeUtc(e.Record.EventHeader.TimeStamp);
            EtwEventTimestamp eventTimestamp = new EtwEventTimestamp();

            eventTimestamp.Timestamp = eventDateTime;
            if (eventDateTime.Equals(this.MostRecentEtwEventTimestamp.Timestamp))
            {
                // This event has the same timestamp as the previous one. Increment the
                // differentiator so that we can keep track of how far we've read.
                eventTimestamp.Differentiator = this.MostRecentEtwEventTimestamp.Differentiator + 1;
            }
            else
            {
                // This event has a later timestamp than the previous one. Initialize
                // the differentiator to 0.
                Debug.Assert(
                    eventDateTime.CompareTo(
                        this.MostRecentEtwEventTimestamp.Timestamp) > 0,
                    "Event timestamps should only move forward in time.");
                eventTimestamp.Differentiator = 0;
            }

            Utility.TraceSource.WriteInfo(
                TraceType,
                "ETW event received. Timestamp: {0} ({1}, {2}).",
                eventTimestamp.Timestamp,
                eventTimestamp.Timestamp.Ticks,
                eventTimestamp.Differentiator);

            if (eventTimestamp.CompareTo(this.LatestProcessedEtwEventTimestamp) > 0)
            {
                // This event occurred after our last processed event. So we need to
                // process it.
                this.ProcessEtwEvent(e.Record, eventTimestamp);

                // Update our latest processed event
                this.LatestProcessedEtwEventTimestamp = eventTimestamp;
                Utility.TraceSource.WriteInfo(
                    TraceType,
                    "The latest timestamp upto which we have processed ETW events is {0} ({1}, {2}).",
                    this.LatestProcessedEtwEventTimestamp.Timestamp,
                    this.LatestProcessedEtwEventTimestamp.Timestamp.Ticks,
                    this.LatestProcessedEtwEventTimestamp.Differentiator);
            }
            else
            {
                Utility.TraceSource.WriteInfo(
                    TraceType,
                    "Ignoring an ETW event because its timestamp {0} ({1}, {2}) is older than the latest timestamp {3} ({4}, {5}) that we have already processed. Ignored event ID: {6}.",
                    eventTimestamp.Timestamp,
                    eventTimestamp.Timestamp.Ticks,
                    eventTimestamp.Differentiator,
                    this.LatestProcessedEtwEventTimestamp.Timestamp,
                    this.LatestProcessedEtwEventTimestamp.Timestamp.Ticks,
                    this.LatestProcessedEtwEventTimestamp.Differentiator,
                    e.Record.EventHeader.EventDescriptor.Id);
            }

            this.MostRecentEtwEventTimestamp = eventTimestamp;
        }
        private void ProcessServicePackageActiveEvent(EventRecord eventRecord, string taskName, string eventName, EtwEventTimestamp eventTimestamp, int maxVersion)
        {
            ApplicationDataReader reader = new ApplicationDataReader(
                eventRecord.UserData,
                eventRecord.UserDataLength);

            // Verify event version
            int eventVersion = reader.ReadInt32();

            if (eventVersion > maxVersion)
            {
                Utility.TraceSource.WriteError(
                    TraceType,
                    "Unexpected version {0} encountered for event name {1}. Event will be ignored.",
                    eventVersion,
                    eventName);
                return;
            }

            // Get the node name
            string nodeName = reader.ReadUnicodeString();

            // Get the root directory for the run layout
            string runLayoutRoot = reader.ReadUnicodeString();

            // Get the application instance ID
            string appInstanceId = reader.ReadUnicodeString();

            // Get the application rollout version
            string appRolloutVersion = reader.ReadUnicodeString();

            // Get the service package name
            string servicePackageName = reader.ReadUnicodeString();

            // Get the service package rollout version
            string serviceRolloutVersion = reader.ReadUnicodeString();

            // Create a record for the application data table
            ServicePackageTableRecord record = new ServicePackageTableRecord(
                nodeName,
                appInstanceId,
                appRolloutVersion,
                servicePackageName,
                serviceRolloutVersion,
                runLayoutRoot,
                default(DateTime));

            Utility.TraceSource.WriteInfo(
                TraceType,
                "ETW event received. Task {0}, event {1}, node name: {2}, application instance ID: {3}, application rollout version: {4}, service package name: {5}, service rollout version: {6}.",
                taskName,
                eventName,
                nodeName,
                record.ApplicationInstanceId,
                record.ApplicationRolloutVersion,
                record.ServicePackageName,
                record.ServiceRolloutVersion);

            // Add or update record in service package table
            this.AddOrUpdateServicePackageHandler(
                nodeName,
                appInstanceId,
                eventTimestamp.Timestamp,
                servicePackageName,
                record,
                eventTimestamp,
                true);
        }
        private void ProcessEtwEvent(EventRecord eventRecord, EtwEventTimestamp eventTimestamp)
        {
            try
            {
                // Get the event definition
                EventDefinition eventDefinition = this.manifestCache.GetEventDefinition(
                    eventRecord);

                // Ignore event source manifests and heartbeat events
                if ((eventDefinition == null && eventRecord.EventHeader.EventDescriptor.Id == 0) ||
                    EventSourceHelper.CheckForDynamicManifest(eventRecord.EventHeader.EventDescriptor))
                {
                    return;
                }

                bool unexpectedEvent = false;
                if (eventDefinition.TaskName.Equals(HostingTaskName))
                {
                    // Verify event name
                    if (eventDefinition.EventName.Equals(ServicePackageActivatedEventName))
                    {
                        this.ProcessServicePackageActiveEvent(
                            eventRecord,
                            eventDefinition.TaskName,
                            eventDefinition.EventName,
                            eventTimestamp,
                            MaxServicePackageActivatedEventVersion);
                    }
                    else if (eventDefinition.EventName.Equals(ServicePackageUpgradedEventName))
                    {
                        this.ProcessServicePackageActiveEvent(
                            eventRecord,
                            eventDefinition.TaskName,
                            eventDefinition.EventName,
                            eventTimestamp,
                            MaxServicePackageUpgradedEventVersion);
                    }
                    else if (eventDefinition.EventName.Equals(ServicePackageDeactivatedEventName))
                    {
                        this.ProcessServicePackageInactiveEvent(
                            eventRecord,
                            eventDefinition.TaskName,
                            eventDefinition.EventName,
                            eventTimestamp,
                            false);
                    }
                    else
                    {
                        unexpectedEvent = true;
                    }
                }
                else if (eventDefinition.TaskName.Equals(DcaTaskName))
                {
                    if (eventDefinition.EventName.Equals(ServicePackageInactiveEventName))
                    {
                        this.ProcessServicePackageInactiveEvent(
                            eventRecord,
                            eventDefinition.TaskName,
                            eventDefinition.EventName,
                            eventTimestamp,
                            true);
                    }
                    else
                    {
                        unexpectedEvent = true;
                    }
                }
                else
                {
                    unexpectedEvent = true;
                }

                if (unexpectedEvent)
                {
                    Utility.TraceSource.WriteWarning(
                        TraceType,
                        "Unexpected event (task name {0}, event name {1}) encountered. Event will be ignored.",
                        eventDefinition.TaskName,
                        eventDefinition.EventName);
                }
            }
            catch (Exception e)
            {
                Utility.TraceSource.WriteError(
                    TraceType,
                    "Exception encountered while processing event with ID {0}, Task {1}. Exception information: {2}.",
                    eventRecord.EventHeader.EventDescriptor.Id,
                    eventRecord.EventHeader.EventDescriptor.Task,
                    e);
            }
        }
        private void Read(object state)
        {
            this.LatestProcessedEtwEventTimestamp = this.tableBackup.LatestBackupTime;
            this.ResetMostRecentEtwEventTimestamp();

            // Get all files in the ETL directory that match the pattern
            Utility.TraceSource.WriteInfo(
                TraceType,
                "Searching for ETL files whose names match '{0}' in directory '{1}'.",
                EtlFilePattern,
                this.etlDirectory);

            DirectoryInfo dirInfo = new DirectoryInfo(this.etlDirectory);

            FileInfo[] etlFiles = dirInfo.GetFiles(EtlFilePattern);

            Utility.TraceSource.WriteInfo(
                TraceType,
                "Found {0} ETL files whose names match '{1}' in directory '{2}'.",
                etlFiles.Length,
                EtlFilePattern,
                this.etlDirectory);

            // Sort the files such that the file with the oldest creation
            // time comes first.
            Array.Sort(etlFiles, this.CompareFileCreationTimesOldFirst);

            // We read events that are old enough to have been flushed to disk
            var      etlFileFlushInterval = this.GetEtlFileFlushInterval();
            DateTime endTime = DateTime.UtcNow.AddSeconds(-2 * etlFileFlushInterval.TotalSeconds);

            foreach (FileInfo etlFile in etlFiles)
            {
                Utility.TraceSource.WriteInfo(
                    TraceType,
                    "Processing ETL file: {0}. Events with timestamp between {1} ({2}) and {3} ({4}) will be read from it.",
                    etlFile.Name,
                    this.LatestProcessedEtwEventTimestamp.Timestamp,
                    this.LatestProcessedEtwEventTimestamp.Timestamp.Ticks,
                    endTime,
                    endTime.Ticks);

                // Note the timestamp of the event we received most recently before we start
                // processing this ETL file. In case we retry the processing of this ETL file,
                // we need to revert back to this timestamp.
                this.mostRecentEtwEventTimestampBeforeCurrentEtl = this.MostRecentEtwEventTimestamp;

                try
                {
                    Utility.PerformWithRetries(
                        ctx =>
                    {
                        // Create a ETL file reader
                        using (var eventReader = new TraceFileEventReader(etlFile.FullName))
                        {
                            var traceSessionMetadata = eventReader.ReadTraceSessionMetadata();
                            FabricEvents.Events.TraceSessionStats(
                                traceSessionMetadata.TraceSessionName,
                                traceSessionMetadata.EventsLostCount,
                                traceSessionMetadata.StartTime,
                                traceSessionMetadata.EndTime);

                            // Register our ETW event processing callback
                            eventReader.EventRead += this.OnEtwEventReceived;

                            // Read ETW events from the ETL file
                            eventReader.ReadEvents(
                                this.LatestProcessedEtwEventTimestamp.Timestamp,
                                endTime);
                        }
                    },
                        (object)null,
                        new RetriableOperationExceptionHandler(this.ReadEventsExceptionHandler));

                    Utility.TraceSource.WriteInfo(
                        TraceType,
                        "Finished processing ETL file: {0}.",
                        etlFile.Name);
                }
                catch (Exception e)
                {
                    Utility.TraceSource.WriteExceptionAsError(
                        TraceType,
                        e,
                        "Failed to read some or all of the events from ETL file {0}.",
                        etlFile.FullName);
                }

                if (this.Stopping)
                {
                    Utility.TraceSource.WriteInfo(
                        TraceType,
                        "The DCA is stopping, so no more ETL files will be processed.");
                    break;
                }
            }

            // Update the timestamp up to which ETW events can be read
            Utility.ApplicationEtwTracesEndTime = this.LatestProcessedEtwEventTimestamp.Timestamp;

            // Schedule the next pass, unless the DCA is being stopped
            this.etlReadTimer.Start(this.GetEtlReadInterval());
        }
Пример #13
0
        private void RemoveServicePackage(
            string nodeName,
            string applicationInstanceId,
            string servicePackageName,
            EtwEventTimestamp dataTimestamp,
            bool updateBackupFile,
            bool removeDueToInactivity)
        {
            try
            {
                // Check if the service package already exists in the service package table
                string uniqueAppId     = string.Concat(nodeName, applicationInstanceId);
                string uniqueServiceId = string.Concat(uniqueAppId, servicePackageName);
                List <ServicePackageTableRecord> records = this.servicePackageTable.GetRecordsForAppInstance(
                    nodeName,
                    applicationInstanceId);
                ServicePackageTableRecord record = (null == records) ?
                                                   null :
                                                   records.FirstOrDefault(s => s.ServicePackageName.Equals(
                                                                              servicePackageName,
                                                                              StringComparison.Ordinal));
                if (null != record)
                {
                    // Service package exists in the service package table
                    bool skipRemove = false;

                    if (removeDueToInactivity)
                    {
                        // We are removing this service package not because it was explicitly
                        // deactivated by hosting, but because we recently did not receive any
                        // notification from hosting that this service package is still active.
                        // However, if some activity occurred on the service package since our
                        // last check, then don't remove this service package.
                        DateTime cutoffTime = DateTime.UtcNow.AddSeconds(-1 * this.maxServicePackageInactiveTimeSeconds);
                        if (record.LatestNotificationTimestamp.CompareTo(cutoffTime) >= 0)
                        {
                            Utility.TraceSource.WriteInfo(
                                TraceType,
                                "Skipping removal of entry from service package table because recent activity was detected. Node name: {0}, application instance ID: {1}, service package name: {2}.",
                                nodeName,
                                applicationInstanceId,
                                servicePackageName);
                            skipRemove = true;
                        }
                    }

                    if (false == skipRemove)
                    {
                        if (records.Count > 1)
                        {
                            // There are other service packages for this application instance
                            this.applicationInstanceManager.RemoveServiceFromApplicationInstance(uniqueAppId, servicePackageName);
                        }
                        else
                        {
                            // This is the last service package for its application instance
                            // Delete the data collector for this application instance
                            this.applicationInstanceManager.DeleteApplicationInstance(
                                uniqueAppId);
                        }

                        // Delete the service package information from our table
                        this.servicePackageTable.RemoveRecord(uniqueServiceId);

                        Utility.TraceSource.WriteInfo(
                            TraceType,
                            "Entry removed from service package table: Node name: {0}, application instance ID: {1}, service package name: {2}.",
                            nodeName,
                            applicationInstanceId,
                            servicePackageName);
                    }
                }
                else
                {
                    Utility.TraceSource.WriteInfo(
                        TraceType,
                        "Deactivation of unknown service package ignored. Node name: {0}, application instance ID: {1}, service package name: {2}.",
                        nodeName,
                        applicationInstanceId,
                        servicePackageName);
                }
            }
            finally
            {
                // If necessary, update the backup file on disk to reflect this change
                if (updateBackupFile)
                {
                    if (false == this.tableBackup.Update(
                            this.servicePackageTable.GetAllRecords(),
                            dataTimestamp))
                    {
                        Utility.TraceSource.WriteError(
                            TraceType,
                            "Unable to make backup of service package table to a file on disk.");
                    }
                }
            }
        }
Пример #14
0
        private void AddOrUpdateServicePackage(
            string nodeName,
            string applicationInstanceId,
            DateTime servicePackageActivationTime,
            string servicePackageName,
            ServicePackageTableRecord serviceRecord,
            EtwEventTimestamp dataTimestamp,
            bool updateBackupFile)
        {
            try
            {
                // Create the object that wraps the application configuration
                AppConfig appConfig;
                try
                {
                    appConfig = new AppConfig(
                        nodeName,
                        serviceRecord.RunLayoutRoot,
                        applicationInstanceId,
                        serviceRecord.ApplicationRolloutVersion);
                }
                catch (InvalidOperationException)
                {
                    return;
                }

                // Create the object that wraps the service configuration
                ServiceConfig serviceConfig;
                try
                {
                    serviceConfig = new ServiceConfig(
                        serviceRecord.RunLayoutRoot,
                        applicationInstanceId,
                        servicePackageName,
                        serviceRecord.ServiceRolloutVersion);
                }
                catch (InvalidOperationException)
                {
                    return;
                }

                // Check if the service package already exists in the service package table
                string uniqueAppId     = string.Concat(nodeName, applicationInstanceId);
                string uniqueServiceId = string.Concat(uniqueAppId, servicePackageName);
                List <ServicePackageTableRecord> records = this.servicePackageTable.GetRecordsForAppInstance(
                    nodeName,
                    applicationInstanceId);
                ServicePackageTableRecord record = (null == records) ?
                                                   null :
                                                   records.FirstOrDefault(s => s.ServicePackageName.Equals(
                                                                              servicePackageName,
                                                                              StringComparison.Ordinal));
                if (null != record)
                {
                    // Service package already exists. Check if needs to be updated.
                    if ((false == record.ApplicationRolloutVersion.Equals(serviceRecord.ApplicationRolloutVersion)) ||
                        (false == record.ServiceRolloutVersion.Equals(serviceRecord.ServiceRolloutVersion)))
                    {
                        this.applicationInstanceManager.AddServiceToApplicationInstance(
                            uniqueAppId,
                            appConfig,
                            servicePackageName,
                            serviceConfig);
                    }
                    else
                    {
                        Utility.TraceSource.WriteInfo(
                            TraceType,
                            "Service package activation did not require the data collector to be restarted. Node name: {0}, application instance ID: {1}, app rollout version: {2}, service package name: {3}, service rollout version: {4}.",
                            nodeName,
                            applicationInstanceId,
                            serviceRecord.ApplicationRolloutVersion,
                            servicePackageName,
                            serviceRecord.ServiceRolloutVersion);
                    }
                }
                else
                {
                    // Service package does not exist yet. Check whether any other service packages
                    // exist for the same app instance
                    if (records.Count > 0)
                    {
                        // Other service packages exist for this application instance.
                        this.applicationInstanceManager.AddServiceToApplicationInstance(
                            uniqueAppId,
                            appConfig,
                            servicePackageName,
                            serviceConfig);
                    }
                    else
                    {
                        // No service packages exist for this application instance.
                        // Create a new data collector for this application instance.
                        this.applicationInstanceManager.CreateApplicationInstance(
                            uniqueAppId,
                            servicePackageActivationTime,
                            appConfig,
                            servicePackageName,
                            serviceConfig);
                    }
                }

                // Store information about this service package in our table
                this.servicePackageTable.AddOrUpdateRecord(uniqueServiceId, serviceRecord);
            }
            finally
            {
                // If necessary, update the backup file on disk to reflect this change
                if (updateBackupFile)
                {
                    if (false == this.tableBackup.Update(
                            this.servicePackageTable.GetAllRecords(),
                            dataTimestamp))
                    {
                        Utility.TraceSource.WriteError(
                            TraceType,
                            "Unable to make backup of service package table to a file on disk.");
                    }
                }
            }

            Utility.TraceSource.WriteInfo(
                TraceType,
                "Entry added to/updated in service package table: Node name: {0}, application instance ID: {1}, app rollout version: {2}, service package name: {3}, service rollout version: {4}.",
                nodeName,
                applicationInstanceId,
                serviceRecord.ApplicationRolloutVersion,
                servicePackageName,
                serviceRecord.ServiceRolloutVersion);
        }