Skip to content

Commit a39d287

Browse files
Randall FlaggRandall Flagg
authored andcommitted
Changed the LogFileReader constructor in order to better encapsulate fields.
Fixed some warnings. Changed type LogLine from class to record.
1 parent 3d46e96 commit a39d287

9 files changed

Lines changed: 73 additions & 106 deletions

File tree

src/LogExpert.Core/Classes/Log/LogfileReader.cs

Lines changed: 64 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

src/LogExpert.Tests/BufferShiftTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void TestShiftBuffers1 ()
4242
};
4343

4444
PluginRegistry.PluginRegistry.Instance.Create(TestDirectory.FullName, 500);
45-
LogfileReader reader = new(files.Last.Value, encodingOptions, true, 40, 50, options, PluginRegistry.PluginRegistry.Instance);
45+
LogfileReader reader = new(files.Last.Value, encodingOptions, true, 40, 50, options, false, PluginRegistry.PluginRegistry.Instance);
4646
reader.ReadFiles();
4747

4848
IList<ILogFileInfo> lil = reader.GetLogFileInfoList();

src/LogExpert.Tests/CSVColumnizerTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public void Instantiat_CSVFile_BuildCorrectColumnizer (string filename, string[]
1515
{
1616
CsvColumnizer.CsvColumnizer csvColumnizer = new();
1717
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filename);
18-
LogfileReader reader = new(path, new EncodingOptions(), false, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance);
18+
LogfileReader reader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), false, PluginRegistry.PluginRegistry.Instance);
1919
reader.ReadFiles();
2020
ILogLine line = reader.GetLogLine(0);
2121
IColumnizedLogLine logline = new ColumnizedLogLine();

src/LogExpert.Tests/ColumnizerPickerTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void FindReplacementForAutoColumnizer_ValidTextFile_ReturnCorrectColumniz
6767
string fileName, Type columnizerType)
6868
{
6969
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
70-
LogfileReader reader = new(path, new EncodingOptions(), false, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance);
70+
LogfileReader reader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), false, PluginRegistry.PluginRegistry.Instance);
7171
reader.ReadFiles();
7272

7373
Mock<ILogLineColumnizer> autoColumnizer = new();

src/LogExpert.Tests/JsonColumnizerTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public void GetColumnNames_HappyFile_ColumnNameMatches (string fileName, string
1313
{
1414
var jsonColumnizer = new JsonColumnizer.JsonColumnizer();
1515
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
16-
LogfileReader reader = new(path, new EncodingOptions(), false, 40, 50, new MultiFileOptions(), PluginRegistry.PluginRegistry.Instance);
16+
LogfileReader reader = new(path, new EncodingOptions(), true, 40, 50, new MultiFileOptions(), false, PluginRegistry.PluginRegistry.Instance);
1717
reader.ReadFiles();
1818

1919
ILogLine line = reader.GetLogLine(0);

0 commit comments

Comments
 (0)