/// <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();
            }
            /// <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);
            }
Exemple #3
0
        /// <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);
            }
        }