private static IDcaInMemoryConsumer CreateEtlToInMemoryBufferWriter(string logDirectory, bool?slow) { EventIndex globalLastEventIndexProcessed = default(EventIndex); globalLastEventIndexProcessed.Set(DateTime.MinValue, -1); InternalFileSink fileSink = new InternalFileSink(Utility.TraceSource, LogSourceId); EventIndex lastEventIndexProcessed = default(EventIndex); var onProcessingPeriodStartActionForFastWriter = new Action <string, bool, string>((traceFileName, isActiveEtl, traceFileSubFolder) => { fileSink.Initialize(); lastEventIndexProcessed.Set(DateTime.MinValue, -1); }); var maxIndexAlreadyProcessedForFastWriter = new Func <string, EventIndex>((traceFileSubFolder) => { return(globalLastEventIndexProcessed); }); var consumerProcessTraceEventActionForFastWriter = new Action <DecodedEventWrapper, string>((decodedEventWrapper, traceFileSubFolder) => { string etwEvent = decodedEventWrapper.StringRepresentation.Replace("\r\n", "\r\t").Replace("\n", "\t"); fileSink.WriteEvent(etwEvent); lastEventIndexProcessed.Set(decodedEventWrapper.Timestamp, decodedEventWrapper.TimestampDifferentiator); }); var onProcessingPeriodStopActionForFastWriter = new Action <string, bool, string>((traceFileName, isActiveEtl, traceFileSubFolder) => { if (slow.HasValue && slow.Value) { Thread.Sleep(2000); } fileSink.Close(); if (fileSink.WriteStatistics.EventsWritten > 0) { var additionalSuffix = (slow.HasValue) ? (slow.Value ? "_slow" : "_fast") : (string.Empty); var destFileName = CreateDestinationFileName(traceFileName, additionalSuffix, isActiveEtl, lastEventIndexProcessed); File.Move(fileSink.TempFileName, Path.Combine(logDirectory, "output", destFileName)); globalLastEventIndexProcessed.Set(lastEventIndexProcessed.Timestamp, lastEventIndexProcessed.TimestampDifferentiator); } else { fileSink.Delete(); } }); var dcaInMemoryConsumer = TestUtility.MockRepository.Create <IDcaInMemoryConsumer>(); dcaInMemoryConsumer.Setup(c => c.ConsumerProcessTraceEventAction) .Returns(consumerProcessTraceEventActionForFastWriter); dcaInMemoryConsumer.Setup(c => c.MaxIndexAlreadyProcessed) .Returns(maxIndexAlreadyProcessedForFastWriter); dcaInMemoryConsumer.Setup(c => c.OnProcessingPeriodStart(It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <string>())) .Callback((string traceFileName, bool isActiveEtl, string traceFileSubFolder) => onProcessingPeriodStartActionForFastWriter(traceFileName, isActiveEtl, traceFileSubFolder)); dcaInMemoryConsumer.Setup(c => c.OnProcessingPeriodStop(It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <string>())) .Callback((string traceFileName, bool isActiveEtl, string traceFileSubFolder) => onProcessingPeriodStopActionForFastWriter(traceFileName, isActiveEtl, traceFileSubFolder)); return(dcaInMemoryConsumer.Object); }
/// <summary> /// Retrieves the last event index processed. /// </summary> /// <param name="bookmarkFolder"></param> /// <param name="bytesRead"></param> /// <returns></returns> internal EventIndex ReadBookmarkFile( string bookmarkFolder, out long bytesRead) { bytesRead = 0; EventIndex lastEventIndex = new EventIndex(); lastEventIndex.Set(DateTime.MinValue, -1); string bookmarkFile = Path.Combine(bookmarkFolder, BookmarkFileName); if (false == FabricFile.Exists(bookmarkFile)) { // Bookmark file doesn't exist return(lastEventIndex); } StreamReader reader = null; try { // Open the file try { Utility.PerformIOWithRetries( () => { FileStream fileStream = FabricFile.Open(bookmarkFile, FileMode.Open, FileAccess.Read); Helpers.SetIoPriorityHint(fileStream.SafeFileHandle, Kernel32Types.PRIORITY_HINT.IoPriorityHintVeryLow); reader = new StreamReader(fileStream); }, this.methodExecutionInitialRetryIntervalMs, this.methodExecutionMaxRetryCount, this.methodExecutionMaxRetryIntervalMs); } catch (Exception e) { this.traceSource.WriteExceptionAsError( this.logSourceId, e, "Unable to open bookmark file {0}.", bookmarkFile); return(lastEventIndex); } long localBytesRead = 0; // Get the version string versionString = string.Empty; try { Utility.PerformIOWithRetries( () => { versionString = reader.ReadLine(); localBytesRead += versionString.Length + 2; }, this.methodExecutionInitialRetryIntervalMs, this.methodExecutionMaxRetryCount, this.methodExecutionMaxRetryIntervalMs); } catch (Exception e) { this.traceSource.WriteExceptionAsError( this.logSourceId, e, "Unable to read version information from bookmark file {0}.", bookmarkFile); return(lastEventIndex); } // Check the version if (false == versionString.Equals(BookmarkFileFormatVersionString, StringComparison.Ordinal)) { this.traceSource.WriteError( this.logSourceId, "Unexpected version string {0} encountered in bookmark file {1}.", versionString, bookmarkFile); return(lastEventIndex); } // Get information about the last event that we read string infoLine = string.Empty; try { Utility.PerformIOWithRetries( () => { infoLine = reader.ReadLine(); localBytesRead += infoLine.Length + 2; }, this.methodExecutionInitialRetryIntervalMs, this.methodExecutionMaxRetryCount, this.methodExecutionMaxRetryIntervalMs); } catch (Exception e) { this.traceSource.WriteExceptionAsError( this.logSourceId, e, "Unable to read information about last event read from bookmark file {0}.", bookmarkFile); return(lastEventIndex); } string[] infoLineParts = infoLine.Split(','); if (infoLineParts.Length != (int)LastEventReadInfoParts.Count) { this.traceSource.WriteError( this.logSourceId, "The information in bookmark file {0} about the last event read is not in the expected format. {1}", bookmarkFile, infoLine); return(lastEventIndex); } string lastEventTimestampString = infoLineParts[(int)LastEventReadInfoParts.LastEventTimestampLong].Trim(); long lastEventTimestampBinary; if (false == long.TryParse(lastEventTimestampString, out lastEventTimestampBinary)) { this.traceSource.WriteError( this.logSourceId, "Unable to retrieve timestamp of last event from bookmark file {0}.", bookmarkFile); return(lastEventIndex); } DateTime lastEventTimestamp = DateTime.FromBinary(lastEventTimestampBinary); string lastEventTimestampDifferentiatorString = infoLineParts[(int)LastEventReadInfoParts.LastEventIndex].Trim(); int lastEventTimestampDifferentiator; if (false == int.TryParse(lastEventTimestampDifferentiatorString, out lastEventTimestampDifferentiator)) { this.traceSource.WriteError( this.logSourceId, "Unable to retrieve timestamp differentiator of last event from bookmark file {0}.", bookmarkFile); return(lastEventIndex); } // record bytes read bytesRead = localBytesRead; lastEventIndex.Set(lastEventTimestamp, lastEventTimestampDifferentiator); } finally { if (null != reader) { reader.Dispose(); } } return(lastEventIndex); }