-
-
Notifications
You must be signed in to change notification settings - Fork 246
/
Copy pathBackgroundCompactor.vb
143 lines (102 loc) · 5.53 KB
/
BackgroundCompactor.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
Imports System.Collections.ObjectModel
Imports System.Runtime
Imports System.Threading
Public Class BackgroundCompactor
Public Property IsCompactorActive As Boolean = False
Private cancellationTokenSource As New CancellationTokenSource()
Private isCompacting As Boolean = False
Private isCompactingPaused As Boolean = False ' Track if compacting is paused
Private isSystemIdle As Boolean = False
Private _compactor As Core.Compactor
Private _excludedFileTypes As String()
Private Const LAST_SYSTEM_MODIFIED_TIME_THRESHOLD As Integer = 300 ' 5 minutes
Public Sub New(excludedFileTypes As String())
_excludedFileTypes = excludedFileTypes
AddHandler IdleDetector.IsIdle, AddressOf OnSystemIdle
AddHandler IdleDetector.IsNotIdle, AddressOf OnSystemNotIdle
End Sub
Private Sub OnSystemIdle(sender As Object, e As EventArgs)
If Not isSystemIdle Then Debug.WriteLine("SYSTEM IDLE!")
isSystemIdle = True
' Attempt to resume only if compacting was paused due to system activity
If isCompactingPaused AndAlso Not isCompacting Then
ResumeCompacting()
End If
End Sub
Private Sub OnSystemNotIdle(sender As Object, e As EventArgs)
If isSystemIdle Then Debug.WriteLine("SYSTEM NOT IDLE!")
isSystemIdle = False
' Attempt to pause only if compacting is currently active and not already paused
If isCompacting AndAlso Not isCompactingPaused Then
PauseCompacting()
End If
End Sub
Public Function BeginCompacting(folder As String, compressionLevel As Core.CompressionAlgorithm) As Task(Of Boolean)
If compressionLevel = Core.CompressionAlgorithm.NO_COMPRESSION Then Return Task.FromResult(False)
_compactor = New Core.Compactor(folder, compressionLevel, _excludedFileTypes)
Return _compactor.RunCompactAsync()
End Function
Public Async Function StartCompactingAsync(folders As ObservableCollection(Of WatchedFolder), monitors As List(Of FolderMonitor)) As Task(Of Boolean)
Debug.WriteLine("Background Compacting Started")
Dim cancellationToken As CancellationToken = cancellationTokenSource.Token
IsCompactorActive = True
Dim currentProcess As Process = Process.GetCurrentProcess()
currentProcess.PriorityClass = ProcessPriorityClass.Idle
Dim foldersCopy As List(Of WatchedFolder) = folders.Where(Function(f) f.DecayPercentage <> 0 AndAlso f.CompressionLevel <> Core.CompressionAlgorithm.NO_COMPRESSION).ToList()
Dim monitorsCopy As List(Of FolderMonitor) = monitors.ToList()
For Each folder In foldersCopy
folder.IsWorking = True
Dim recentThresholdDate As DateTime = DateTime.Now.AddSeconds(-LAST_SYSTEM_MODIFIED_TIME_THRESHOLD)
If folder.LastSystemModifiedDate > recentThresholdDate Then
Debug.WriteLine(" Skipping " & folder.DisplayName)
Continue For
End If
Debug.WriteLine(" Compacting " & folder.DisplayName)
Dim compactingTask = BeginCompacting(folder.Folder, folder.CompressionLevel)
isCompacting = True
While Not cancellationToken.IsCancellationRequested AndAlso Not compactingTask.IsCompleted
Await Task.WhenAny(compactingTask, Task.Delay(1000, cancellationToken))
' Check the idle state and adjust compacting status accordingly
If Not isSystemIdle AndAlso Not isCompactingPaused Then
PauseCompacting()
ElseIf isSystemIdle AndAlso isCompactingPaused Then
ResumeCompacting()
End If
End While
Dim result = Await compactingTask
If result AndAlso folders.Contains(folder) Then
' Ensure the folder is still in the original collection before updating
Dim analyser As New Core.Analyser(folder.Folder)
Await analyser.AnalyseFolder(Nothing)
folder.LastCheckedDate = DateTime.Now
folder.LastCheckedSize = analyser.CompressedBytes
folder.LastCompressedSize = analyser.CompressedBytes
folder.LastSystemModifiedDate = DateTime.Now
Dim mainCompressionLVL = analyser.FileCompressionDetailsList.Select(Function(f) f.CompressionMode).Max
folder.CompressionLevel = mainCompressionLVL
folder.LastCompressedDate = DateTime.Now
Dim monitor = monitorsCopy.Find(Function(m) m.Folder = folder.Folder)
If monitor IsNot Nothing AndAlso monitors.Contains(monitor) Then
monitor.HasTargetChanged = False
End If
End If
folder.IsWorking = False
Debug.WriteLine(" Finished Compacting " & folder.DisplayName)
Next
IsCompactorActive = False
isCompacting = False ' Ensure compacting status is reset after operation
Debug.WriteLine("Background Compacting Finished")
currentProcess.PriorityClass = ProcessPriorityClass.Normal
Return True
End Function
Public Sub PauseCompacting()
Debug.WriteLine(" - Pausing Background!")
isCompactingPaused = True ' Indicate compacting is paused
_compactor.PauseCompression()
End Sub
Public Sub ResumeCompacting()
Debug.WriteLine(" - Resuming Background!")
isCompactingPaused = False ' Indicate compacting is no longer paused
_compactor.ResumeCompression()
End Sub
End Class