/// <summary> /// Perform the roll for the next date. /// </summary> /// <param name="rollDateTime">The roll date.</param> internal void PerformRoll(DateTime rollDateTime) { string actualFileName = ((FileStream)((StreamWriter)this.owner.writer).BaseStream).Name; if (this.owner.rollFileExistsBehavior == RollFileExistsBehavior.Overwrite && string.IsNullOrEmpty(this.owner.timestampPattern)) { // no roll will be actually performed: no timestamp pattern is available, and // the roll behavior is overwrite, so the original file will be truncated this.owner.writer.Close(); File.WriteAllText(actualFileName, string.Empty); } else { // calculate archive name string archiveFileName = this.ComputeArchiveFileName(actualFileName, rollDateTime); // close file this.owner.writer.Close(); // move file SafeMove(actualFileName, archiveFileName, rollDateTime); // purge if necessary this.PurgeArchivedFiles(actualFileName); } this.owner.writer.Dispose(); this.owner.writer = new TallyKeepingFileStreamWriter(this.owner.file.Open(FileMode.Append, FileAccess.Write, FileShare.Read)); this.managedWriter = null; this.nextRollDateTime = null; this.UpdateRollingInformationIfNecessary(); }
public void InitializesTallyForNewFile() { using (var writer = new TallyKeepingFileStreamWriter(File.Open(fileName, FileMode.Append, FileAccess.Write, FileShare.Read))) { Assert.AreEqual(0L, writer.Tally); } }
/// <summary> /// Updates book keeping information necessary for rolling, as required by the specified rolling configuration. /// </summary> /// <returns>true if update was successful, false if an error occurred.</returns> public bool UpdateRollingInformationIfNecessary() { StreamWriter currentWriter = null; // replace writer with the tally keeping version if necessary for size rolling if (this.owner.rollSizeInBytes > 0 && this.managedWriter == null) { currentWriter = this.owner.writer as StreamWriter; if (currentWriter == null) { // TWTL couldn't acquire the writer - abort return(false); } var actualFileName = ((FileStream)currentWriter.BaseStream).Name; currentWriter.Close(); FileStream fileStream = null; try { fileStream = File.Open(actualFileName, FileMode.Append, FileAccess.Write, FileShare.Read); this.managedWriter = new TallyKeepingFileStreamWriter(fileStream, GetEncodingWithFallback()); } catch (IOException) { // there's a slight chance of error here - abort if this occurs and just let TWTL handle it without attempting to roll return(false); } this.owner.writer = this.managedWriter; } // compute the next roll date if necessary if (this.owner.rollInterval != RollInterval.None && this.nextRollDateTime == null) { try { // casting should be safe at this point - only file stream writers can be the writers for the owner trace listener. // it should also happen rarely this.nextRollDateTime = this.CalculateNextRollDate(File.GetCreationTime(((FileStream)((StreamWriter)this.owner.writer).BaseStream).Name)); } catch (IOException) { this.nextRollDateTime = DateTime.MaxValue; // disable rolling if no date could be retrieved. // there's a slight chance of error here - abort if this occurs and just let TWTL handle it without attempting to roll return(false); } } return(true); }
public void WritingToFileUpdatesTally() { using (var writer = new TallyKeepingFileStreamWriter(File.Open(fileName, FileMode.Append, FileAccess.Write, FileShare.Read))) { writer.Write("12345"); writer.Flush(); Assert.AreEqual(5L, writer.Tally); } }
/// <summary> /// Initializes a new instance of the <see cref="RollingFlatFileSink"/> class with the specified values. /// </summary> /// <param name="fileName">The filename where the entries will be logged.</param> /// <param name="rollSizeKB">The maximum file size (KB) before rolling.</param> /// <param name="timestampPattern">The date format that will be appended to the new roll file.</param> /// <param name="rollFileExistsBehavior">Expected behavior that will be used when the roll file has to be created.</param> /// <param name="rollInterval">The time interval that makes the file to be rolled.</param> /// <param name="maxArchivedFiles">The maximum number of archived files to keep.</param> /// <param name="formatter">The event entry formatter.</param> /// <param name="isAsync">Specifies if the writing should be done asynchronously, or synchronously with a blocking call.</param> public RollingFlatFileSink(string fileName, int rollSizeKB, string timestampPattern, RollFileExistsBehavior rollFileExistsBehavior, RollInterval rollInterval, int maxArchivedFiles, IEventTextFormatter formatter, bool isAsync) { Guard.ArgumentNotNull(formatter, "formatter"); this.file = FileUtil.ProcessFileNameForLogging(fileName); this.formatter = formatter; if (rollInterval == RollInterval.None) { if (!string.IsNullOrWhiteSpace(timestampPattern)) { Guard.ValidateTimestampPattern(timestampPattern, "timestampPattern"); } } else { Guard.ValidateTimestampPattern(timestampPattern, "timestampPattern"); } this.writer = new TallyKeepingFileStreamWriter(this.file.Open(FileMode.Append, FileAccess.Write, FileShare.Read)); this.rollSizeInBytes = rollSizeKB * 1024L; this.timestampPattern = timestampPattern; this.rollFileExistsBehavior = rollFileExistsBehavior; this.rollInterval = rollInterval; this.maxArchivedFiles = maxArchivedFiles; this.isAsync = isAsync; this.rollingHelper = new StreamWriterRollingHelper(this); if (rollInterval == RollInterval.Midnight && !isAsync) { var now = this.rollingHelper.DateTimeProvider.CurrentDateTime; var midnight = now.AddDays(1).Date; var callback = new TimerCallback(delegate { lock (this.lockObject) { this.rollingHelper.RollIfNecessary(); } }); this.timer = new Timer(callback, null, midnight.Subtract(now), TimeSpan.FromDays(1)); } this.flushSource.SetResult(true); if (isAsync) { this.cancellationTokenSource = new CancellationTokenSource(); this.pendingEntries = new BlockingCollection <EventEntry>(); this.asyncProcessorTask = Task.Factory.StartNew(this.WriteEntries, TaskCreationOptions.LongRunning); } }
public void WritingToFileWithEncodingUpdatesTally() { using (var writer = new TallyKeepingFileStreamWriter(File.Open(fileName, FileMode.Append, FileAccess.Write, FileShare.Read), Encoding.UTF32)) { writer.Write("12345"); writer.Flush(); Assert.AreEqual(20L, writer.Tally); // BOM is not part of tally - minimal fidelity loss on new files. } }
public void InitializesTallyForExistingFile() { File.WriteAllText(fileName, "12345"); using (var writer = new TallyKeepingFileStreamWriter(File.Open(fileName, FileMode.Append, FileAccess.Write, FileShare.Read))) { Assert.AreEqual(5L, writer.Tally); } File.WriteAllText(fileName, "12345"); using (var writer = new TallyKeepingFileStreamWriter(File.Open(fileName, FileMode.Create, FileAccess.Write, FileShare.Read))) { Assert.AreEqual(0L, writer.Tally); } File.WriteAllText(fileName, "12345"); using (var writer = new TallyKeepingFileStreamWriter(File.Open(fileName, FileMode.Truncate, FileAccess.Write, FileShare.Read))) { Assert.AreEqual(0L, writer.Tally); } }
/// <summary> /// Updates book keeping information necessary for rolling, as required by the specified rolling configuration. /// </summary> /// <returns>true if update was successful, false if an error occurred.</returns> public bool UpdateRollingInformationIfNecessary() { StreamWriter currentWriter = null; // replace writer with the tally keeping version if necessary for size rolling if (this.owner.rollSizeInBytes > 0 && this.managedWriter == null) { currentWriter = this.owner.writer as StreamWriter; if (currentWriter == null) { // TWTL couldn't acquire the writer - abort return false; } var actualFileName = ((FileStream)currentWriter.BaseStream).Name; currentWriter.Close(); FileStream fileStream = null; try { fileStream = File.Open(actualFileName, FileMode.Append, FileAccess.Write, FileShare.Read); this.managedWriter = new TallyKeepingFileStreamWriter(fileStream, GetEncodingWithFallback()); } catch (IOException) { // there's a slight chance of error here - abort if this occurs and just let TWTL handle it without attempting to roll return false; } this.owner.writer = this.managedWriter; } // compute the next roll date if necessary if (this.owner.rollInterval != RollInterval.None && this.nextRollDateTime == null) { try { // casting should be safe at this point - only file stream writers can be the writers for the owner trace listener. // it should also happen rarely this.nextRollDateTime = this.CalculateNextRollDate(File.GetCreationTime(((FileStream)((StreamWriter)this.owner.writer).BaseStream).Name)); } catch (IOException) { this.nextRollDateTime = DateTime.MaxValue; // disable rolling if no date could be retrieved. // there's a slight chance of error here - abort if this occurs and just let TWTL handle it without attempting to roll return false; } } return true; }