Skip to content

Commit 5bb3251

Browse files
Randall FlaggRandall Flagg
authored andcommitted
Need to check this changes
1 parent 08d76e9 commit 5bb3251

File tree

4 files changed

+115
-50
lines changed

4 files changed

+115
-50
lines changed

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

Lines changed: 110 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class LogfileReader : IAutoLogLineColumnizerCallback, IDisposable
1414
{
1515
#region Fields
1616

17-
private static readonly ILogger _logger = LogManager.GetCurrentClassLogger();
17+
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
1818

1919
private readonly string _fileName;
2020
private readonly int _max_buffers;
@@ -386,7 +386,7 @@ public int ShiftBuffers ()
386386

387387
public ILogLine GetLogLine (int lineNum)
388388
{
389-
return GetLogLineInternal(lineNum).Result;
389+
return GetLogLineInternal(lineNum, _cts.Token).Result; //TODO: Is this token correct?
390390
}
391391

392392
/// <summary>
@@ -406,36 +406,70 @@ public ILogLine GetLogLine (int lineNum)
406406
/// <returns></returns>
407407
public async Task<ILogLine> GetLogLineWithWait (int lineNum)
408408
{
409-
const int WAIT_TIME = 1000;
410-
411-
ILogLine result = null;
409+
const int WAIT_MS = 1000;
412410

411+
// If we’re not in fast-fail mode, try once with timeout
413412
if (!_isFastFailOnGetLogLine)
414413
{
415-
var task = Task.Run(() => GetLogLineInternal(lineNum));
416-
if (task.Wait(WAIT_TIME))
414+
using var cts = new CancellationTokenSource();
415+
cts.CancelAfter(WAIT_MS);
416+
417+
try
417418
{
418-
result = task.Result;
419+
// Offload the read so UI never blocks
420+
var line = await GetLogLineInternal(lineNum, cts.Token).ConfigureAwait(false);
421+
422+
// Completed successfully in time
419423
_isFastFailOnGetLogLine = false;
424+
return line;
420425
}
421-
else
426+
catch (OperationCanceledException)
422427
{
428+
// Timed out
423429
_isFastFailOnGetLogLine = true;
424-
_logger.Debug(CultureInfo.InvariantCulture, "No result after {0}ms. Returning <null>.", WAIT_TIME);
430+
_logger.Debug(CultureInfo.InvariantCulture, "Timeout after {0}ms. Returning <null>.", WAIT_MS);
431+
TriggerBackgroundRecovery(lineNum);
432+
return null;
425433
}
426-
}
427-
else
428-
{
429-
_logger.Debug(CultureInfo.InvariantCulture, "Fast failing GetLogLine()");
430-
if (!_isFailModeCheckCallPending)
434+
catch (Exception ex)
431435
{
432-
_isFailModeCheckCallPending = true;
433-
var logLine = await GetLogLineInternal(lineNum);
434-
GetLineFinishedCallback(logLine);
436+
// Real error—flip fast-fail and rethrow
437+
_isFastFailOnGetLogLine = true;
438+
_logger.Error(ex, "Exception in GetLogLineInternal for line {0}.", lineNum);
439+
throw;
435440
}
436441
}
437442

438-
return result;
443+
// Fast-fail path: immediate null, kick off a background refresh
444+
_logger.Debug(CultureInfo.InvariantCulture, "Fast failing GetLogLine()");
445+
TriggerBackgroundRecovery(lineNum);
446+
return null;
447+
}
448+
449+
private void TriggerBackgroundRecovery (int lineNum)
450+
{
451+
if (_isFailModeCheckCallPending)
452+
return;
453+
454+
_isFailModeCheckCallPending = true;
455+
456+
// Fire-and-forget check (no UI thread marshalling needed)
457+
_ = Task.Run(async () =>
458+
{
459+
try
460+
{
461+
var line = await GetLogLineInternal(lineNum, CancellationToken.None).ConfigureAwait(false);
462+
GetLineFinishedCallback(line);
463+
}
464+
catch (Exception ex)
465+
{
466+
_logger.Error(ex, "Deferred GetLogLineInternal failed.");
467+
}
468+
finally
469+
{
470+
_isFailModeCheckCallPending = false;
471+
}
472+
});
439473
}
440474

441475
/// <summary>
@@ -745,43 +779,74 @@ private ILogFileInfo AddFile (string fileName)
745779
return info;
746780
}
747781

748-
private Task<ILogLine> GetLogLineInternal (int lineNum)
782+
private Task<ILogLine> GetLogLineInternal (int lineNum, CancellationToken ct)
749783
{
784+
// Run all the heavy work off the UI thread,
785+
// and honor the cancellation token
786+
return Task.Run(() => GetLogLineInternalCore(lineNum, ct), ct);
787+
}
788+
789+
private ILogLine GetLogLineInternalCore (int lineNum, CancellationToken ct)
790+
{
791+
ct.ThrowIfCancellationRequested();
792+
750793
if (_isDeleted)
751794
{
752-
_logger.Debug(CultureInfo.InvariantCulture, "Returning null for line {0} because file is deleted.", lineNum);
795+
_logger.Debug(
796+
CultureInfo.InvariantCulture,
797+
"Returning null for line {0} because file is deleted.",
798+
lineNum);
753799

754-
// fast fail if dead file was detected. Prevents repeated lags in GUI thread caused by callbacks from control (e.g. repaint)
755800
return null;
756801
}
757802

758-
AcquireBufferListReaderLock();
759-
LogBuffer logBuffer = GetBufferForLine(lineNum);
760-
if (logBuffer == null)
803+
AcquireBufferListReaderLock(); // blocking call off UI
804+
try
761805
{
762-
ReleaseBufferListReaderLock();
763-
_logger.Error("Cannot find buffer for line {0}, file: {1}{2}", lineNum, _fileName, IsMultiFile ? " (MultiFile)" : "");
764-
return null;
765-
}
806+
ct.ThrowIfCancellationRequested();
766807

767-
// disposeLock prevents that the garbage collector is disposing just in the moment we use the buffer
768-
_disposeLock.AcquireReaderLock(Timeout.Infinite);
769-
if (logBuffer.IsDisposed)
770-
{
771-
LockCookie cookie = _disposeLock.UpgradeToWriterLock(Timeout.Infinite);
772-
lock (logBuffer.FileInfo)
808+
var logBuffer = GetBufferForLine(lineNum);
809+
if (logBuffer == null)
773810
{
774-
ReReadBuffer(logBuffer);
811+
_logger.Error("Cannot find buffer for line {0}, file: {1}{2}", lineNum, _fileName, IsMultiFile ? " (MultiFile)" : "");
812+
return null;
775813
}
776814

777-
_disposeLock.DowngradeFromWriterLock(ref cookie);
778-
}
815+
_disposeLock.AcquireReaderLock(Timeout.Infinite);
816+
try
817+
{
818+
ct.ThrowIfCancellationRequested();
779819

780-
ILogLine line = logBuffer.GetLineOfBlock(lineNum - logBuffer.StartLine);
781-
_disposeLock.ReleaseReaderLock();
782-
ReleaseBufferListReaderLock();
820+
if (logBuffer.IsDisposed)
821+
{
822+
var cookie = _disposeLock.UpgradeToWriterLock(Timeout.Infinite);
823+
try
824+
{
825+
lock (logBuffer.FileInfo)
826+
{
827+
ReReadBuffer(logBuffer);
828+
}
783829

784-
return Task.FromResult(line);
830+
ct.ThrowIfCancellationRequested();
831+
}
832+
finally
833+
{
834+
_disposeLock.DowngradeFromWriterLock(ref cookie);
835+
}
836+
}
837+
838+
// Actual line extraction
839+
return logBuffer.GetLineOfBlock(lineNum - logBuffer.StartLine);
840+
}
841+
finally
842+
{
843+
_disposeLock.ReleaseReaderLock();
844+
}
845+
}
846+
finally
847+
{
848+
ReleaseBufferListReaderLock();
849+
}
785850
}
786851

787852
private void InitLruBuffers ()
@@ -1775,13 +1840,13 @@ private void DumpBufferInfos (LogBuffer buffer)
17751840

17761841
#endregion
17771842

1778-
public void Dispose()
1843+
public void Dispose ()
17791844
{
17801845
Dispose(true);
17811846
GC.SuppressFinalize(this); // Suppress finalization (not needed but best practice)
17821847
}
17831848

1784-
protected virtual void Dispose(bool disposing)
1849+
protected virtual void Dispose (bool disposing)
17851850
{
17861851
if (!_disposed)
17871852
{
@@ -1798,7 +1863,7 @@ protected virtual void Dispose(bool disposing)
17981863
//TODO: Seems that this can be deleted. Need to verify.
17991864
~LogfileReader ()
18001865
{
1801-
Dispose (false);
1866+
Dispose(false);
18021867
}
18031868

18041869
protected virtual void OnFileSizeChanged (LogEventArgs e)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,6 @@ private void LoadingFinished ()
598598
dataGridView.SuspendLayout();
599599
dataGridView.RowCount = _logFileReader.LineCount;
600600
dataGridView.CurrentCellChanged += OnDataGridViewCurrentCellChanged;
601-
dataGridView.Enabled = true;
602601
dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
603602
dataGridView.ResumeLayout();
604603
_progressEventArgs.Visible = false;
@@ -622,6 +621,7 @@ private void LoadingFinished ()
622621

623622
PreferencesChanged(fontName, fontSize, setLastColumnWidth, lastColumnWidth, true, SettingsFlags.All);
624623
//LoadPersistenceData();
624+
dataGridView.Enabled = true;
625625
}
626626

627627
private void LogEventWorker ()

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,11 @@ public void CellPainting (BufferedDataGridView gridView, int rowIndex, DataGridV
404404
if (rowIndex < 0 || e.ColumnIndex < 0)
405405
{
406406
e.Handled = false;
407-
return;
407+
//return;
408408
}
409409

410-
ILogLine line = _logFileReader.GetLogLineWithWait(rowIndex).Result;
411-
410+
//ILogLine line = _logFileReader.GetLogLineWithWait(rowIndex).Result;
411+
ILogLine line = null;
412412
if (line != null)
413413
{
414414
HighlightEntry entry = FindFirstNoWordMatchHilightEntry(line);

src/LogExpert.UI/Dialogs/LogTabWindow/SettingsDialog.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private void FillDialog ()
165165
FillMultifileSettings();
166166
FillEncodingList();
167167

168-
var temp = Encoding.GetEncoding(Preferences.DefaultEncoding);
168+
//var temp = Encoding.GetEncoding(Preferences.DefaultEncoding);//TODO: Delete
169169

170170
comboBoxEncoding.SelectedItem = Encoding.GetEncoding(Preferences.DefaultEncoding);
171171
checkBoxMaskPrio.Checked = Preferences.MaskPrio;

0 commit comments

Comments
 (0)