@@ -14,38 +14,33 @@ public class LogfileReader : IAutoLogLineColumnizerCallback, IDisposable
1414{
1515 #region Fields
1616
17- private static readonly ILogger _logger = LogManager . GetCurrentClassLogger ( ) ;
18-
19- private readonly GetLogLineFx _logLineFx ;
17+ private static readonly Logger _logger = LogManager . GetCurrentClassLogger ( ) ;
2018
2119 private readonly string _fileName ;
2220 private readonly int _max_buffers ;
2321 private readonly int _maxLinesPerBuffer ;
24-
2522 private readonly object _monitor = new ( ) ;
2623 private readonly MultiFileOptions _multiFileOptions ;
2724 private readonly IPluginRegistry _pluginRegistry ;
25+ private readonly CancellationTokenSource _cts = new ( ) ;
26+ private readonly bool _useNewReader ;
27+
2828 private IList < LogBuffer > _bufferList ;
2929 private ReaderWriterLock _bufferListLock ;
3030 private bool _contentDeleted ;
3131 private int _currLineCount ;
3232 private ReaderWriterLock _disposeLock ;
3333 private EncodingOptions _encodingOptions ;
3434 private long _fileLength ;
35-
3635 private Task _garbageCollectorTask ;
3736 private Task _monitorTask ;
38- private readonly CancellationTokenSource _cts = new ( ) ;
39-
4037 private bool _isDeleted ;
4138 private bool _isFailModeCheckCallPending ;
4239 private bool _isFastFailOnGetLogLine ;
4340 private bool _isLineCountDirty = true ;
4441 private IList < ILogFileInfo > _logFileInfoList = [ ] ;
4542 private Dictionary < int , LogBufferCacheEntry > _lruCacheDict ;
46-
4743 private ReaderWriterLock _lruCacheDictLock ;
48-
4944 private bool _shouldStop ;
5045 private bool _disposed ;
5146 private ILogFileInfo _watchedILogFileInfo ;
@@ -54,85 +49,66 @@ public class LogfileReader : IAutoLogLineColumnizerCallback, IDisposable
5449
5550 #region cTor
5651
57- public LogfileReader ( string fileName , EncodingOptions encodingOptions , bool multiFile , int bufferCount , int linesPerBuffer , MultiFileOptions multiFileOptions , IPluginRegistry pluginRegistry )
52+ /// Public constructor for single file.
53+ public LogfileReader ( string fileName , EncodingOptions encodingOptions , bool multiFile , int bufferCount , int linesPerBuffer , MultiFileOptions multiFileOptions , bool useNewReader , IPluginRegistry pluginRegistry )
54+ : this ( [ fileName ] , encodingOptions , multiFile , bufferCount , linesPerBuffer , multiFileOptions , useNewReader , pluginRegistry )
5855 {
59- if ( fileName == null )
60- {
61- return ;
62- }
63-
64- _fileName = fileName ;
65- EncodingOptions = encodingOptions ;
66- IsMultiFile = multiFile ;
67- _max_buffers = bufferCount ;
68- _maxLinesPerBuffer = linesPerBuffer ;
69- _multiFileOptions = multiFileOptions ;
70- _pluginRegistry = pluginRegistry ;
71- _logLineFx = GetLogLineInternal ;
72- _disposed = false ;
73-
74- InitLruBuffers ( ) ;
75-
76- if ( multiFile )
77- {
78- var info = GetLogFileInfo ( fileName ) ;
79- RolloverFilenameHandler rolloverHandler = new ( info , _multiFileOptions ) ;
80- var nameList = rolloverHandler . GetNameList ( _pluginRegistry ) ;
81-
82- ILogFileInfo fileInfo = null ;
83- foreach ( var name in nameList )
84- {
85- fileInfo = AddFile ( name ) ;
86- }
87-
88- _watchedILogFileInfo = fileInfo ; // last added file in the list is the watched file
89- }
90- else
91- {
92- _watchedILogFileInfo = AddFile ( fileName ) ;
93- }
56+ }
9457
95- StartGCThread ( ) ;
58+ /// Public constructor for multiple files.
59+ public LogfileReader ( string [ ] fileNames , EncodingOptions encodingOptions , int bufferCount , int linesPerBuffer , MultiFileOptions multiFileOptions , bool useNewReader , IPluginRegistry pluginRegistry )
60+ : this ( fileNames , encodingOptions , true , bufferCount , linesPerBuffer , multiFileOptions , useNewReader , pluginRegistry )
61+ {
62+ // In this overload, we assume multiFile is always true.
9663 }
9764
98- public LogfileReader ( string [ ] fileNames , EncodingOptions encodingOptions , int bufferCount , int linesPerBuffer , MultiFileOptions multiFileOptions , IPluginRegistry pluginRegistry )
65+ // Single private constructor that contains the common initialization logic.
66+ private LogfileReader ( string [ ] fileNames , EncodingOptions encodingOptions , bool multiFile , int bufferCount , int linesPerBuffer , MultiFileOptions multiFileOptions , bool useNewReader , IPluginRegistry pluginRegistry )
9967 {
68+ // Validate input: at least one file must be provided.
10069 if ( fileNames == null || fileNames . Length < 1 )
10170 {
102- return ;
71+ throw new ArgumentException ( "Must provide at least one file." , nameof ( fileNames ) ) ;
10372 }
10473
74+ _useNewReader = useNewReader ;
10575 EncodingOptions = encodingOptions ;
106- IsMultiFile = true ;
10776 _max_buffers = bufferCount ;
10877 _maxLinesPerBuffer = linesPerBuffer ;
10978 _multiFileOptions = multiFileOptions ;
11079 _pluginRegistry = pluginRegistry ;
111- _logLineFx = GetLogLineInternal ;
11280 _disposed = false ;
11381
11482 InitLruBuffers ( ) ;
11583
11684 ILogFileInfo fileInfo = null ;
117- foreach ( var name in fileNames )
85+
86+ IsMultiFile = multiFile || fileNames . Length == 1 ;
87+ _fileName = fileNames [ 0 ] ;
88+
89+ IEnumerable < string > names = IsMultiFile
90+ // For multi-file rollover mode: get rollover names.
91+ ? new RolloverFilenameHandler ( GetLogFileInfo ( _fileName ) , _multiFileOptions ) . GetNameList ( _pluginRegistry )
92+ : [ _fileName ] ;
93+
94+ foreach ( var name in names )
11895 {
11996 fileInfo = AddFile ( name ) ;
12097 }
12198
99+ if ( IsMultiFile )
100+ {
101+ // Use the full name of the last file as _fileName.
102+ _fileName = fileInfo . FullName ;
103+ }
104+
122105 _watchedILogFileInfo = fileInfo ;
123- _fileName = fileInfo . FullName ;
124106
125107 StartGCThread ( ) ;
126108 }
127109
128110 #endregion
129111
130- #region Delegates
131-
132- private delegate Task < ILogLine > GetLogLineFx ( int lineNum ) ;
133-
134- #endregion
135-
136112 #region Events
137113
138114 public event EventHandler < LogEventArgs > FileSizeChanged ;
@@ -165,7 +141,7 @@ public int LineCount
165141
166142 return _currLineCount ;
167143 }
168- set => _currLineCount = value ;
144+ private set => _currLineCount = value ;
169145 }
170146
171147 public bool IsMultiFile { get ; }
@@ -174,13 +150,15 @@ public int LineCount
174150
175151 public long FileSize { get ; private set ; }
176152
153+ //TODO: Change to private field. No need for a property.
177154 public bool IsXmlMode { get ; set ; }
178155
156+ //TODO: Change to private field. No need for a property.
179157 public IXmlLogConfiguration XmlLogConfig { get ; set ; }
180158
181159 public IPreProcessColumnizer PreProcessColumnizer { get ; set ; }
182160
183- public EncodingOptions EncodingOptions
161+ private EncodingOptions EncodingOptions
184162 {
185163 get => _encodingOptions ;
186164 set
@@ -195,15 +173,14 @@ public EncodingOptions EncodingOptions
195173 }
196174 }
197175
198- public bool UseNewReader { get ; set ; }
199-
200176 #endregion
201177
202178 #region Public methods
203179
204180 /// <summary>
205181 /// Public for unit test reasons
206182 /// </summary>
183+ //TODO: Make this private
207184 public void ReadFiles ( )
208185 {
209186 FileSize = 0 ;
@@ -254,6 +231,7 @@ public void ReadFiles ()
254231 /// Public for unit tests.
255232 /// </summary>
256233 /// <returns></returns>
234+ //TODO: Make this private
257235 public int ShiftBuffers ( )
258236 {
259237 _logger . Info ( CultureInfo . InvariantCulture , "ShiftBuffers() begin for {0}{1}" , _fileName , IsMultiFile ? " (MultiFile)" : "" ) ;
@@ -335,10 +313,10 @@ public int ShiftBuffers ()
335313 if ( lostILogFileInfoList . Count > 0 )
336314 {
337315 _logger . Info ( CultureInfo . InvariantCulture , "Deleting buffers for lost files" ) ;
338- foreach ( var ILogFileInfo in lostILogFileInfoList )
316+ foreach ( var logFileInfo in lostILogFileInfoList )
339317 {
340- //this.ILogFileInfoList.Remove(ILogFileInfo );
341- var lastBuffer = DeleteBuffersForInfo ( ILogFileInfo , false ) ;
318+ //this.ILogFileInfoList.Remove(logFileInfo );
319+ var lastBuffer = DeleteBuffersForInfo ( logFileInfo , false ) ;
342320 if ( lastBuffer != null )
343321 {
344322 offset += lastBuffer . StartLine + lastBuffer . LineCount ;
@@ -366,7 +344,7 @@ public int ShiftBuffers ()
366344 foreach ( var ILogFileInfo in readNewILogFileInfoList )
367345 {
368346 DeleteBuffersForInfo ( ILogFileInfo , true ) ;
369- //this.ILogFileInfoList.Remove(ILogFileInfo );
347+ //this.ILogFileInfoList.Remove(logFileInfo );
370348 }
371349
372350 _logger . Info ( CultureInfo . InvariantCulture , "Deleting buffers for the watched file" ) ;
@@ -375,9 +353,9 @@ public int ShiftBuffers ()
375353 _logger . Info ( CultureInfo . InvariantCulture , "Re-Reading files" ) ;
376354 foreach ( var ILogFileInfo in readNewILogFileInfoList )
377355 {
378- //ILogFileInfo .OpenFile();
356+ //logFileInfo .OpenFile();
379357 ReadToBufferList ( ILogFileInfo , 0 , LineCount ) ;
380- //this.ILogFileInfoList.Add(ILogFileInfo );
358+ //this.ILogFileInfoList.Add(logFileInfo );
381359 newFileInfoList . Add ( ILogFileInfo ) ;
382360 }
383361
@@ -422,7 +400,7 @@ public async Task<ILogLine> GetLogLineWithWait (int lineNum)
422400
423401 if ( ! _isFastFailOnGetLogLine )
424402 {
425- var task = Task . Run ( ( ) => _logLineFx ( lineNum ) ) ;
403+ var task = Task . Run ( ( ) => GetLogLineInternal ( lineNum ) ) ;
426404 if ( task . Wait ( WAIT_TIME ) )
427405 {
428406 result = task . Result ;
@@ -440,7 +418,7 @@ public async Task<ILogLine> GetLogLineWithWait (int lineNum)
440418 if ( ! _isFailModeCheckCallPending )
441419 {
442420 _isFailModeCheckCallPending = true ;
443- var logLine = await _logLineFx ( lineNum ) ;
421+ var logLine = await GetLogLineInternal ( lineNum ) ;
444422 GetLineFinishedCallback ( logLine ) ;
445423 }
446424 }
@@ -927,7 +905,7 @@ private void ReadToBufferList (ILogFileInfo logFileInfo, long filePos, int start
927905 using var fileStream = logFileInfo . OpenStream ( ) ;
928906 try
929907 {
930- using var reader = GetLogStreamReader ( fileStream , EncodingOptions , UseNewReader ) ;
908+ using var reader = GetLogStreamReader ( fileStream , EncodingOptions , _useNewReader ) ;
931909 reader . Position = filePos ;
932910 _fileLength = logFileInfo . Length ;
933911
@@ -980,7 +958,6 @@ private void ReadToBufferList (ILogFileInfo logFileInfo, long filePos, int start
980958
981959 while ( ReadLine ( reader , logBuffer . StartLine + logBuffer . LineCount , logBuffer . StartLine + logBuffer . LineCount + droppedLines , out var line ) )
982960 {
983- LogLine logLine = new ( ) ;
984961 if ( _shouldStop )
985962 {
986963 Monitor . Exit ( logBuffer ) ;
@@ -1011,8 +988,7 @@ private void ReadToBufferList (ILogFileInfo logFileInfo, long filePos, int start
1011988 lineCount = 1 ;
1012989 }
1013990
1014- logLine . FullLine = line ;
1015- logLine . LineNumber = logBuffer . StartLine + logBuffer . LineCount ;
991+ LogLine logLine = new ( line , logBuffer . StartLine + logBuffer . LineCount ) ;
1016992
1017993 logBuffer . AddLine ( logLine , filePos ) ;
1018994 filePos = reader . Position ;
@@ -1319,7 +1295,7 @@ private void ReReadBuffer (LogBuffer logBuffer)
13191295
13201296 try
13211297 {
1322- var reader = GetLogStreamReader ( fileStream , EncodingOptions , UseNewReader ) ;
1298+ var reader = GetLogStreamReader ( fileStream , EncodingOptions , _useNewReader ) ;
13231299
13241300 var filePos = logBuffer . StartPos ;
13251301 reader . Position = logBuffer . StartPos ;
@@ -1341,11 +1317,7 @@ private void ReReadBuffer (LogBuffer logBuffer)
13411317 continue ;
13421318 }
13431319
1344- LogLine logLine = new ( )
1345- {
1346- FullLine = line ,
1347- LineNumber = logBuffer . StartLine + logBuffer . LineCount
1348- } ;
1320+ LogLine logLine = new ( line , logBuffer . StartLine + logBuffer . LineCount ) ;
13491321
13501322 logBuffer . AddLine ( logLine , filePos ) ;
13511323 filePos = reader . Position ;
@@ -1578,7 +1550,6 @@ private void FireChangeEvent ()
15781550 if ( IsMultiFile )
15791551 {
15801552 var offset = ShiftBuffers ( ) ;
1581- //this.currFileSize = newSize; // removed because ShiftBuffers() calls ReadToBuffer() which will set the actual read size
15821553 args . FileSize = newSize ;
15831554 args . LineCount = LineCount ;
15841555 args . IsRollover = true ;
@@ -1785,6 +1756,8 @@ private void DumpBufferInfos (LogBuffer buffer)
17851756
17861757 #endregion
17871758
1759+ #region IDisposable Support
1760+
17881761 public void Dispose ( )
17891762 {
17901763 Dispose ( true ) ;
@@ -1811,6 +1784,9 @@ protected virtual void Dispose (bool disposing)
18111784 Dispose ( false ) ;
18121785 }
18131786
1787+ #endregion IDisposable Support
1788+
1789+ #region Event Handlers
18141790 protected virtual void OnFileSizeChanged ( LogEventArgs e )
18151791 {
18161792 FileSizeChanged ? . Invoke ( this , e ) ;
@@ -1842,16 +1818,12 @@ protected virtual void OnRespawned ()
18421818 Respawned ? . Invoke ( this , EventArgs . Empty ) ;
18431819 }
18441820
1845- private class LogLine : ILogLine
1846- {
1847- #region Properties
1848-
1849- public string FullLine { get ; set ; }
1821+ #endregion Event Handlers
18501822
1851- public int LineNumber { get ; set ; }
1852-
1853- string ITextValue . Text => FullLine ;
1854-
1855- #endregion
1823+ #region Records
1824+ private record LogLine ( string FullLine , int LineNumber ) : ILogLine
1825+ {
1826+ public string Text => FullLine ;
18561827 }
1857- }
1828+ #endregion Records
1829+ }
0 commit comments