Skip to content

Commit d644b03

Browse files
Randall FlaggRandall Flagg
Randall Flagg
authored and
Randall Flagg
committed
Removed the thread that watches file changes.
Handle local file and file:// URI. SFTP not working.
1 parent 8fba5b8 commit d644b03

File tree

2 files changed

+148
-94
lines changed

2 files changed

+148
-94
lines changed

src/LogExpert/Classes/Log/LogfileReader.cs

Lines changed: 147 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
using LogExpert.Entities;
33
using LogExpert.Entities.EventArgs;
44
using LogExpert.Interface;
5-
65
using NLog;
7-
86
using System;
97
using System.Collections.Generic;
108
using System.IO;
@@ -22,7 +20,17 @@ public class LogfileReader : IAutoLogLineColumnizerCallback
2220

2321
private readonly GetLogLineFx _logLineFx;
2422

25-
private readonly string _fileName;
23+
private string FileName
24+
{
25+
get; init
26+
{
27+
var uri = new Uri(value);
28+
if (uri.IsFile)
29+
{
30+
field = uri.LocalPath; // Convert the URI to a local file path
31+
}
32+
}
33+
}
2634
private readonly int _MAX_BUFFERS = 10;
2735
private readonly int _MAX_LINES_PER_BUFFER = 100;
2836

@@ -39,7 +47,6 @@ public class LogfileReader : IAutoLogLineColumnizerCallback
3947
private long _fileLength;
4048

4149
private Task _garbageCollectorTask;
42-
private Task _monitorTask;
4350
private readonly CancellationTokenSource cts = new();
4451

4552
private bool _isDeleted;
@@ -51,7 +58,7 @@ public class LogfileReader : IAutoLogLineColumnizerCallback
5158

5259
private ReaderWriterLock _lruCacheDictLock;
5360

54-
61+
private FileSystemWatcher _watcher;
5562
private bool _shouldStop;
5663
private ILogFileInfo _watchedILogFileInfo;
5764

@@ -66,7 +73,7 @@ public LogfileReader(string fileName, EncodingOptions encodingOptions, bool mult
6673
return;
6774
}
6875

69-
_fileName = fileName;
76+
FileName = fileName;
7077
EncodingOptions = encodingOptions;
7178
IsMultiFile = multiFile;
7279
_MAX_BUFFERS = bufferCount;
@@ -120,7 +127,7 @@ public LogfileReader(string[] fileNames, EncodingOptions encodingOptions, int bu
120127
}
121128

122129
_watchedILogFileInfo = fileInfo;
123-
_fileName = fileInfo.FullName;
130+
FileName = fileInfo.FullName;
124131

125132
StartGCThread();
126133
}
@@ -268,7 +275,7 @@ public void ReadFiles()
268275
/// <returns></returns>
269276
public int ShiftBuffers()
270277
{
271-
_logger.Info("ShiftBuffers() begin for {0}{1}", _fileName, IsMultiFile ? " (MultiFile)" : "");
278+
_logger.Info("ShiftBuffers() begin for {0}{1}", FileName, IsMultiFile ? " (MultiFile)" : "");
272279
AcquireBufferListWriterLock();
273280
int offset = 0;
274281
_isLineCountDirty = true;
@@ -571,28 +578,142 @@ public int GetRealLineNumForVirtualLineNum(int lineNum)
571578
return result;
572579
}
573580

574-
public void StartMonitoring()
581+
public async Task StartMonitoring()
575582
{
576-
_logger.Info("startMonitoring()");
577-
_monitorTask = Task.Run(MonitorThreadProc, cts.Token);
583+
_logger.Info("StartMonitoring() for file ${_watchedILogFileInfo.FullName}");
584+
585+
await Task.Run(() =>
586+
{
587+
_logger.Info("MonitorThreadProc() for file {0}", _watchedILogFileInfo.FullName);
588+
589+
long oldSize = 0;
590+
try
591+
{
592+
OnLoadingStarted(new LoadFileEventArgs(FileName, 0, false, 0, false));
593+
ReadFiles();
594+
if (!_isDeleted)
595+
{
596+
oldSize = _fileLength;
597+
OnLoadingFinished();
598+
}
599+
}
600+
catch (Exception e)
601+
{
602+
_logger.Error(e);
603+
}
604+
});
605+
606+
try
607+
{
608+
_watcher = new FileSystemWatcher
609+
{
610+
NotifyFilter = //NotifyFilters.Attributes
611+
//| NotifyFilters.CreationTime
612+
//| NotifyFilters.DirectoryName
613+
//|
614+
NotifyFilters.FileName
615+
//| NotifyFilters.LastAccess
616+
| NotifyFilters.LastWrite
617+
//| NotifyFilters.Security
618+
| NotifyFilters.Size,
619+
620+
Path = Path.GetDirectoryName(FileName) ?? throw new ArgumentException("Invalid file path"),
621+
Filter = Path.GetFileName(FileName), // Sets filter to the specific
622+
EnableRaisingEvents = true
623+
};
624+
}
625+
catch (UnauthorizedAccessException ex)
626+
{
627+
Console.WriteLine($"Access denied: {ex.Message}");
628+
}
629+
catch (ArgumentException ex)
630+
{
631+
Console.WriteLine($"Invalid argument: {ex.Message}");
632+
}
633+
catch (Exception ex)
634+
{
635+
Console.WriteLine($"An error occurred: {ex.Message}");
636+
}
637+
638+
_watcher.Error += (sender, e) =>
639+
{
640+
Console.WriteLine($"Error occurred: {e.GetException().Message}");
641+
Task.Delay(5000).ContinueWith(_ =>
642+
{
643+
try
644+
{
645+
Console.WriteLine("Attempting to restart the watcher...");
646+
_watcher.EnableRaisingEvents = true;
647+
}
648+
catch (Exception ex)
649+
{
650+
Console.WriteLine($"Failed to restart the watcher: {ex.Message}");
651+
}
652+
});
653+
};
654+
_watcher.Changed += OnFileChanged;
655+
_watcher.Created += OnCreated;
656+
_watcher.Deleted += OnFileDeleted;
657+
_watcher.Renamed += OnFileRenamed;
658+
_watcher.Error += OnFileError;
659+
578660
_shouldStop = false;
579661
}
580662

663+
private void OnFileError(object sender, ErrorEventArgs e)
664+
{
665+
throw new NotImplementedException();
666+
}
667+
668+
private void OnFileRenamed(object sender, RenamedEventArgs e)
669+
{
670+
throw new NotImplementedException();
671+
}
672+
673+
private void OnCreated(object sender, FileSystemEventArgs e)
674+
{
675+
//TODO: This should be deleted before merge?
676+
throw new NotImplementedException();
677+
}
678+
679+
private void OnFileDeleted(object sender, FileSystemEventArgs e)
680+
{
681+
MonitoredFileNotFound();
682+
}
683+
684+
private void OnFileChanged(object sender, FileSystemEventArgs e)
685+
{
686+
try
687+
{
688+
_watchedILogFileInfo.FileHasChanged();
689+
_fileLength = _watchedILogFileInfo.Length;
690+
FileChanged();
691+
}
692+
catch (FileNotFoundException ex)
693+
{
694+
MonitoredFileNotFound();
695+
}
696+
catch (Exception ex)
697+
{
698+
throw new NotImplementedException();
699+
}
700+
}
701+
581702
public void StopMonitoring()
582703
{
583704
_logger.Info("stopMonitoring()");
584705
_shouldStop = true;
585706

586-
Thread.Sleep(_watchedILogFileInfo.PollInterval); // leave time for the threads to stop by themselves
587-
588-
if (_monitorTask != null)
707+
if (_watcher != null)
589708
{
590-
if (_monitorTask.Status == TaskStatus.Running) // if thread has not finished, abort it
591-
{
592-
cts.Cancel();
593-
}
709+
_watcher.EnableRaisingEvents = false; // Stop watching
710+
_watcher.Dispose(); // Release resources
711+
_watcher = null; // Clear the reference
712+
594713
}
595714

715+
Thread.Sleep(_watchedILogFileInfo.PollInterval); // leave time for the threads to stop by themselves
716+
596717
if (_garbageCollectorTask.IsCanceled == false)
597718
{
598719
if (_garbageCollectorTask.Status == TaskStatus.Running) // if thread has not finished, abort it
@@ -630,11 +751,11 @@ public void DeleteAllContent()
630751
{
631752
if (_contentDeleted)
632753
{
633-
_logger.Debug("Buffers for {0} already deleted.", Util.GetNameFromPath(_fileName));
754+
_logger.Debug("Buffers for {0} already deleted.", Util.GetNameFromPath(FileName));
634755
return;
635756
}
636757

637-
_logger.Info("Deleting all log buffers for {0}. Used mem: {1:N0}", Util.GetNameFromPath(_fileName), GC.GetTotalMemory(true)); //TODO [Z] uh GC collect calls creepy
758+
_logger.Info("Deleting all log buffers for {0}. Used mem: {1:N0}", Util.GetNameFromPath(FileName), GC.GetTotalMemory(true)); //TODO [Z] uh GC collect calls creepy
638759
AcquireBufferListWriterLock();
639760
_lruCacheDictLock.AcquireWriterLock(Timeout.Infinite);
640761
_disposeLock.AcquireWriterLock(Timeout.Infinite);
@@ -701,7 +822,7 @@ internal void LogBufferInfoForLine(int lineNum)
701822
if (buffer == null)
702823
{
703824
ReleaseBufferListReaderLock();
704-
_logger.Error("Cannot find buffer for line {0}, file: {1}{2}", lineNum, _fileName, IsMultiFile ? " (MultiFile)" : "");
825+
_logger.Error("Cannot find buffer for line {0}, file: {1}{2}", lineNum, FileName, IsMultiFile ? " (MultiFile)" : "");
705826
return;
706827
}
707828

@@ -726,7 +847,7 @@ internal void LogBufferDiagnostic()
726847
_lruCacheDictLock.ReleaseReaderLock();
727848

728849
AcquireBufferListReaderLock();
729-
_logger.Info("File: {0}\r\nBuffer count: {1}\r\nDisposed buffers: {2}", _fileName, _bufferList.Count, _bufferList.Count - cacheCount);
850+
_logger.Info("File: {0}\r\nBuffer count: {1}\r\nDisposed buffers: {2}", FileName, _bufferList.Count, _bufferList.Count - cacheCount);
730851
int lineNum = 0;
731852
long disposeSum = 0;
732853
long maxDispose = 0;
@@ -782,7 +903,7 @@ private Task<ILogLine> GetLogLineInternal(int lineNum)
782903
if (logBuffer == null)
783904
{
784905
ReleaseBufferListReaderLock();
785-
_logger.Error("Cannot find buffer for line {0}, file: {1}{2}", lineNum, _fileName, IsMultiFile ? " (MultiFile)" : "");
906+
_logger.Error("Cannot find buffer for line {0}, file: {1}{2}", lineNum, FileName, IsMultiFile ? " (MultiFile)" : "");
786907
return null;
787908
}
788909

@@ -1147,7 +1268,7 @@ private void GarbageCollectLruCache()
11471268
#if DEBUG
11481269
if (diff > 0)
11491270
{
1150-
_logger.Info("Removing {0} entries from LRU cache for {1}", diff, Util.GetNameFromPath(_fileName));
1271+
_logger.Info("Removing {0} entries from LRU cache for {1}", diff, Util.GetNameFromPath(FileName));
11511272
}
11521273
#endif
11531274
SortedList<long, int> useSorterList = [];
@@ -1464,74 +1585,6 @@ private LogBuffer GetFirstBufferForFileByLogBuffer(LogBuffer logBuffer)
14641585
return resultBuffer;
14651586
}
14661587

1467-
private void MonitorThreadProc()
1468-
{
1469-
Thread.CurrentThread.Name = "MonitorThread";
1470-
//IFileSystemPlugin fs = PluginRegistry.GetInstance().FindFileSystemForUri(this.watchedILogFileInfo.FullName);
1471-
_logger.Info("MonitorThreadProc() for file {0}", _watchedILogFileInfo.FullName);
1472-
1473-
long oldSize = 0;
1474-
try
1475-
{
1476-
OnLoadingStarted(new LoadFileEventArgs(_fileName, 0, false, 0, false));
1477-
ReadFiles();
1478-
if (!_isDeleted)
1479-
{
1480-
oldSize = _fileLength;
1481-
OnLoadingFinished();
1482-
}
1483-
}
1484-
catch (Exception e)
1485-
{
1486-
_logger.Error(e);
1487-
}
1488-
1489-
while (!_shouldStop)
1490-
{
1491-
try
1492-
{
1493-
int pollInterval = _watchedILogFileInfo.PollInterval;
1494-
//#if DEBUG
1495-
// if (_logger.IsDebug)
1496-
// {
1497-
// _logger.logDebug("Poll interval for " + this.fileName + ": " + pollInterval);
1498-
// }
1499-
//#endif
1500-
Thread.Sleep(pollInterval);
1501-
}
1502-
catch (Exception e)
1503-
{
1504-
_logger.Error(e);
1505-
}
1506-
1507-
if (_shouldStop)
1508-
{
1509-
return;
1510-
}
1511-
1512-
try
1513-
{
1514-
if (_watchedILogFileInfo.FileHasChanged())
1515-
{
1516-
_fileLength = _watchedILogFileInfo.Length;
1517-
if (_fileLength == -1)
1518-
{
1519-
MonitoredFileNotFound();
1520-
}
1521-
else
1522-
{
1523-
oldSize = _fileLength;
1524-
FileChanged();
1525-
}
1526-
}
1527-
}
1528-
catch (FileNotFoundException)
1529-
{
1530-
MonitoredFileNotFound();
1531-
}
1532-
}
1533-
}
1534-
15351588
private void MonitoredFileNotFound()
15361589
{
15371590
long oldSize;
@@ -1563,7 +1616,7 @@ private void FileChanged()
15631616
long newSize = _fileLength;
15641617
//if (this.currFileSize != newSize)
15651618
{
1566-
_logger.Info("file size changed. new size={0}, file: {1}", newSize, _fileName);
1619+
_logger.Info("file size changed. new size={0}, file: {1}", newSize, FileName);
15671620
FireChangeEvent();
15681621
}
15691622
}
@@ -1586,7 +1639,7 @@ private void FireChangeEvent()
15861639
{
15871640
// ReloadBufferList(); // removed because reloading is triggered by owning LogWindow
15881641
// Trigger "new file" handling (reload)
1589-
OnLoadFile(new LoadFileEventArgs(_fileName, 0, true, _fileLength, true));
1642+
OnLoadFile(new LoadFileEventArgs(FileName, 0, true, _fileLength, true));
15901643

15911644
if (_isDeleted)
15921645
{

src/LogExpert/LogExpert.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode>
2020
<ForceDesignerDPIUnaware>true</ForceDesignerDPIUnaware>
2121
<NoWarn>CS1591;</NoWarn>
22+
<LangVersion>preview</LangVersion>
2223
</PropertyGroup>
2324
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
2425
<Optimize>False</Optimize>

0 commit comments

Comments
 (0)