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); }
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()); }
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."); } } } }
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); }