Skip to content

Commit a039252

Browse files
author
BRUNER Patrick
committed
Merge branch 'new_reader' of https://github.com/LogExperts/LogExpert into new_reader
2 parents f163dab + 262fab1 commit a039252

9 files changed

Lines changed: 88 additions & 31 deletions

File tree

src/ColumnizerLib/ILogLine.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,33 @@ public interface ILogLine : ITextValue
1111
#endregion
1212
}
1313

14+
/// <summary>
15+
/// Represents a single log line, including its full text and line number.
16+
/// </summary>
17+
/// <remarks>
18+
/// <para>
19+
/// <b>Purpose:</b> <br/>
20+
/// The <c>LogLine</c> struct encapsulates the content and line number of a log entry. It is used throughout the
21+
/// columnizer and log processing infrastructure to provide a strongly-typed, immutable representation of a log line.
22+
/// </para>
23+
/// <para>
24+
/// <b>Usage:</b> <br/>
25+
/// This struct implements the <see cref="ILogLine"/> interface, allowing it to be used wherever an <c>ILogLine</c>
26+
/// is expected. It provides value semantics and is intended to be lightweight and efficiently passed by value.
27+
/// </para>
28+
/// <para>
29+
/// <b>Relationship to ILogLine:</b> <br/>
30+
/// <c>LogLine</c> is a concrete, immutable implementation of the <see cref="ILogLine"/> interface, providing
31+
/// properties for the full line text and its line number.
32+
/// </para>
33+
/// <para>
34+
/// <b>Why struct instead of record:</b> <br/>
35+
/// A <c>struct</c> is preferred over a <c>record</c> here to avoid heap allocations and to provide value-type
36+
/// semantics, which are beneficial for performance when processing large numbers of log lines. The struct is
37+
/// immutable (readonly), ensuring thread safety and predictability. The previous <c>record</c> implementation
38+
/// was replaced to better align with these performance and semantic requirements.
39+
/// </para>
40+
/// </remarks>
1441
public readonly struct LogLine (string fullLine, int lineNumber) : ILogLine
1542
{
1643
public string FullLine { get; } = fullLine;

src/ColumnizerLib/ILogLineSpanColumnizer.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
namespace ColumnizerLib;
22

3-
// ColumnizerLib/ILogLineSpanColumnizer.cs
43
public interface ILogLineSpanColumnizer : ILogLineColumnizer
54
{
65
/// <summary>

src/ColumnizerLib/ITextValue.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public interface ITextValue
1414

1515
public static class TextValueExtensions
1616
{
17-
[Obsolete("Use FullLine property directly")]
17+
[Obsolete("Use ILogLine.FullLine property directly instead of this extension method")]
1818
public static string GetText (this ILogLine logLine) => logLine.FullLine;
1919

2020
[Obsolete("Use DisplayValue property directly")]

src/LogExpert.Benchmarks/StreamReaderBenchmarks.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,6 @@ public static class Program
183183
{
184184
public static void Main (string[] args)
185185
{
186-
var summary = BenchmarkRunner.Run<StreamReaderBenchmarks>();
186+
_ = BenchmarkRunner.Run<StreamReaderBenchmarks>();
187187
}
188188
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public class LogBuffer
2424

2525
//public LogBuffer() { }
2626

27-
//Dont use Primary Constructor, MAX_LINES will not be initialized correctly
27+
// Don't use a primary constructor here: field initializers (like MAX_LINES) run before primary constructor parameters are assigned,
28+
// so MAX_LINES would always be set to its default value before the constructor body can assign it. Use a regular constructor instead.
2829
public LogBuffer (ILogFileInfo fileInfo, int maxLines)
2930
{
3031
FileInfo = fileInfo;

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ protected override void Dispose (bool disposing)
157157
{
158158
segment.Dispose();
159159
}
160+
160161
_lineQueue.Dispose();
161162
}
162163

@@ -200,6 +201,13 @@ private void RestartPipeline (long newPosition)
200201
}
201202
}
202203

204+
/// <summary>
205+
/// Cancels the current pipeline operation and releases associated resources. This method should be called while
206+
/// holding the appropriate lock to ensure thread safety.
207+
/// </summary>
208+
/// <remarks>This method cancels any ongoing producer task, marks the internal queue as complete to
209+
/// unblock waiting consumers, and disposes of pipeline resources. It is intended for internal use and must be
210+
/// invoked only when the pipeline is in a valid state for cancellation.</remarks>
203211
private void CancelPipelineLocked ()
204212
{
205213
if (_cts == null)
@@ -226,7 +234,7 @@ private void CancelPipelineLocked ()
226234
}
227235
finally
228236
{
229-
_cts?.Dispose();
237+
_cts.Dispose();
230238
_cts = null;
231239
}
232240

@@ -444,15 +452,12 @@ private void EnqueueLine (LineSegment segment)
444452
}
445453

446454
// If still no space, force process current content as truncated line
447-
if (charsInBuffer >= _charBufferSize - 100)
455+
if (charsInBuffer >= _charBufferSize - 100 && charsInBuffer > 0)
448456
{
449-
if (charsInBuffer > 0)
450-
{
451-
var segment = CreateSegment(charBuffer, 0, charsInBuffer, 0, byteOffset);
452-
byteOffset += segment.ByteLength;
453-
EnqueueLine(segment);
454-
charsInBuffer = 0;
455-
}
457+
var segment = CreateSegment(charBuffer, 0, charsInBuffer, 0, byteOffset);
458+
byteOffset += segment.ByteLength;
459+
EnqueueLine(segment);
460+
charsInBuffer = 0;
456461
}
457462

458463
charsAvailable = _charBufferSize - charsInBuffer;
Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
11
namespace LogExpert.Core.Interface;
22

3-
internal interface ILogStreamReaderSpan : ILogStreamReader
3+
public interface ILogStreamReaderSpan : ILogStreamReader
44
{
55

6+
/// <summary>
7+
/// Attempts to read the next line from the stream.
8+
/// </summary>
9+
/// <param name="lineMemory">
10+
/// When this method returns <c>true</c>, contains a <see cref="ReadOnlyMemory{Char}"/> representing the next line read from the stream.
11+
/// The memory is only valid until the next call to <see cref="TryReadLine"/> or until <see cref="ReturnMemory"/> is called.
12+
/// </param>
13+
/// <returns>
14+
/// <c>true</c> if a line was successfully read; <c>false</c> if the end of the stream has been reached or no more lines are available.
15+
/// </returns>
16+
/// <remarks>
17+
/// The returned memory is only valid until the next call to <see cref="TryReadLine"/> or until <see cref="ReturnMemory"/> is called.
18+
/// This method is not guaranteed to be thread-safe; concurrent access should be synchronized externally.
19+
/// </remarks>
620
bool TryReadLine (out ReadOnlyMemory<char> lineMemory);
721

22+
/// <summary>
23+
/// Returns the memory buffer previously obtained from <see cref="TryReadLine"/> to the underlying pool or resource manager.
24+
/// </summary>
25+
/// <param name="memory">
26+
/// The <see cref="ReadOnlyMemory{Char}"/> instance previously obtained from <see cref="TryReadLine"/>.
27+
/// </param>
28+
/// <remarks>
29+
/// Call this method when you are done processing the memory returned by <see cref="TryReadLine"/> to avoid memory leaks or resource retention.
30+
/// Failing to call this method may result in increased memory usage.
31+
/// It is safe to call this method multiple times for the same memory, but only the first call will have an effect.
32+
/// </remarks>
833
void ReturnMemory (ReadOnlyMemory<char> memory);
934
}

src/LogExpert.UI/Controls/LogWindow/LogWindow.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7934,7 +7934,7 @@ public void RefreshLogView ()
79347934
RefreshAllGrids();
79357935
}
79367936

7937-
//Replace any digit, to normalize numbers
7937+
//Replace any digit, to normalize numbers.
79387938
[GeneratedRegex("\\d")]
79397939
private static partial Regex ReplaceDigit ();
79407940

src/PluginRegistry/PluginHashGenerator.Generated.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,35 @@ public static partial class PluginValidator
1010
{
1111
/// <summary>
1212
/// Gets pre-calculated SHA256 hashes for built-in plugins.
13-
/// Generated: 2025-12-03 10:17:08 UTC
13+
/// Generated: 2025-12-06 09:27:13 UTC
1414
/// Configuration: Release
1515
/// Plugin count: 21
1616
/// </summary>
1717
public static Dictionary<string, string> GetBuiltInPluginHashes()
1818
{
1919
return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
2020
{
21-
["AutoColumnizer.dll"] = "DEFEE4450E0B6EC0848902A7BEEC141AAE89DE8B71F92F9EBD2206632D96F17A",
21+
["AutoColumnizer.dll"] = "5B32841702FD32BEABC182E07DD22EE80C1AF57B4F79C8A8DFEFA48DE98A7580",
2222
["BouncyCastle.Cryptography.dll"] = "E5EEAF6D263C493619982FD3638E6135077311D08C961E1FE128F9107D29EBC6",
2323
["BouncyCastle.Cryptography.dll (x86)"] = "E5EEAF6D263C493619982FD3638E6135077311D08C961E1FE128F9107D29EBC6",
24-
["CsvColumnizer.dll"] = "46827846AD2C2A1BDF6600A5BD7080BC8799B54C81329CDFB23015BDCBF7A480",
25-
["CsvColumnizer.dll (x86)"] = "46827846AD2C2A1BDF6600A5BD7080BC8799B54C81329CDFB23015BDCBF7A480",
26-
["DefaultPlugins.dll"] = "B6DC411F1394D7C2A83B242990E2E4356B0EF523CB518B9FF5658BBC2E05BF5F",
27-
["FlashIconHighlighter.dll"] = "70545A26BB7D433EE3B2735AC38DE233CB5BF4B1F0623E716323C9C95242072B",
28-
["GlassfishColumnizer.dll"] = "FEB269CB14C068698F19ABE3B93C4F5E2DC11116713509FD718C1A0929CDE716",
29-
["JsonColumnizer.dll"] = "99E86FC39F0DF73550E184D50939BB468EB11930E72CBE78353DC9733B9D7365",
30-
["JsonCompactColumnizer.dll"] = "630ED6696B8976596EC2A20228D5F8E9EC6FA94CB544936196C8E9849F692F5A",
31-
["Log4jXmlColumnizer.dll"] = "EB1DF83134242B6A38A354ED50AC16EC25EB9AF02123620CB89209A46CDD0102",
32-
["LogExpert.Core.dll"] = "16AF8E6719D60D5C4B3FFDB63FAA9F81478C1A2445070185E28B3259C5AC0786",
24+
["CsvColumnizer.dll"] = "A6759EE1723545C2FB380C77840F08908DCC68AE4ACEBF74BF706398A431E998",
25+
["CsvColumnizer.dll (x86)"] = "A6759EE1723545C2FB380C77840F08908DCC68AE4ACEBF74BF706398A431E998",
26+
["DefaultPlugins.dll"] = "17D5B3D9D1EDB46BABA354A851F4C85036C17ACF1EA3AC1B5B59DCB96B62DBE9",
27+
["FlashIconHighlighter.dll"] = "859E6BA2D268966FBE9C474FD7AC3DC1963838EAFFB5B7ACC01DD5D749FB9617",
28+
["GlassfishColumnizer.dll"] = "D3EE363792399A7183EFC616F632297E149CC1414EDD3E61272248F3C7F73112",
29+
["JsonColumnizer.dll"] = "523D17BC9340CC2AA47F88564D7D1654088D9E2AE979458B93FCD54935D6E410",
30+
["JsonCompactColumnizer.dll"] = "20B1AED3C2CD9DC45593D2729FD1171A212B2F7B7BBC9A26B2A553750E11FA6A",
31+
["Log4jXmlColumnizer.dll"] = "A3E27F2B4A3892FF1237346BC2174FB00132790422FCD7A131393749A59B05E2",
32+
["LogExpert.Core.dll"] = "C112EB8FA9356670628BA9E6907A9F485E4397F01AA7A4B5D7654DF7568B662C",
3333
["Microsoft.Extensions.DependencyInjection.Abstractions.dll"] = "67FA4325000DB017DC0C35829B416F024F042D24EFB868BCF17A895EE6500A93",
3434
["Microsoft.Extensions.DependencyInjection.Abstractions.dll (x86)"] = "67FA4325000DB017DC0C35829B416F024F042D24EFB868BCF17A895EE6500A93",
3535
["Microsoft.Extensions.Logging.Abstractions.dll"] = "BB853130F5AFAF335BE7858D661F8212EC653835100F5A4E3AA2C66A4D4F685D",
3636
["Microsoft.Extensions.Logging.Abstractions.dll (x86)"] = "BB853130F5AFAF335BE7858D661F8212EC653835100F5A4E3AA2C66A4D4F685D",
37-
["RegexColumnizer.dll"] = "98E8A88829BA43CE7E763D197145F1A0863D891F6F274528B8EFE6EF64443063",
38-
["SftpFileSystem.dll"] = "C98EA0176B51E21F685F53EF0CD6CA3B2B4108700EEC19BC0A85019B32BB6067",
39-
["SftpFileSystem.dll (x86)"] = "F65FBD5E63A7D4E801366B5BE043FDA1B12762C21668B8B00ADA3727E469DF9F",
40-
["SftpFileSystem.Resources.dll"] = "B9AF09F4B77E6CD439240DFC94332AD909500478963BFB049BAD6D30A3842113",
41-
["SftpFileSystem.Resources.dll (x86)"] = "B9AF09F4B77E6CD439240DFC94332AD909500478963BFB049BAD6D30A3842113",
37+
["RegexColumnizer.dll"] = "BCF84A9BF5FA11B2842F9E8BB08F91697C6139F6E2748108A748265E377BD5F6",
38+
["SftpFileSystem.dll"] = "37149960232EC87DCE0CA208D6F08CB852A81546297E6879BC63E63677BB490A",
39+
["SftpFileSystem.dll (x86)"] = "C46E4C25C429E8E1F44F8E5B0C707411E0E674355C4B97D4589B6F7CA859C80F",
40+
["SftpFileSystem.Resources.dll"] = "53F44F2DD6D7D77ED5F4A5789FF264025E2D99C04972A1AED4C8939193D57D38",
41+
["SftpFileSystem.Resources.dll (x86)"] = "53F44F2DD6D7D77ED5F4A5789FF264025E2D99C04972A1AED4C8939193D57D38",
4242

4343
};
4444
}

0 commit comments

Comments
 (0)