Skip to content

Commit f13ab30

Browse files
committed
Refactor Core.Analyser to make code clearer
1 parent 5e9b9f8 commit f13ab30

File tree

5 files changed

+64
-68
lines changed

5 files changed

+64
-68
lines changed

CompactGUI.Core/Analyser.vb

Lines changed: 44 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,60 +5,76 @@ Imports System.Threading
55

66
Public Class Analyser
77

8-
Public Sub New(folder As String)
9-
FolderName = folder
10-
End Sub
11-
128
Public Property FolderName As String
139
Public Property UncompressedBytes As Long
1410
Public Property CompressedBytes As Long
1511
Public Property ContainsCompressedFiles As Boolean
1612
Public Property FileCompressionDetailsList As List(Of AnalysedFileDetails)
17-
Private _testField As Integer = 0
1813

19-
Public Async Function AnalyseFolder(cancellationToken As CancellationToken) As Task(Of Boolean)
14+
Public Sub New(folder As String)
15+
FolderName = folder
16+
End Sub
2017

18+
19+
Public Async Function AnalyseFolder(cancellationToken As CancellationToken) As Task(Of Boolean)
2120
Dim allFiles = Await Task.Run(Function() Directory.EnumerateFiles(FolderName, "*", New EnumerationOptions() With {.RecurseSubdirectories = True, .IgnoreInaccessible = True}).AsShortPathNames, cancellationToken).ConfigureAwait(False)
22-
Dim compressedFilesCount As Integer
2321
Dim fileDetails As New Concurrent.ConcurrentBag(Of AnalysedFileDetails)
22+
Dim compressedFilesCount As Integer = 0
23+
24+
' Use local variables to reduce contention
25+
Dim localCompressedBytes As Long = 0
26+
Dim localUncompressedBytes As Long = 0
2427

2528
Try
26-
Dim res = Await Task.Run(Function() Parallel.ForEach(allFiles, New ParallelOptions With {.CancellationToken = cancellationToken}, Sub(file) AnalyseFile(file, compressedFilesCount, fileDetails)))
29+
Parallel.ForEach(allFiles, New ParallelOptions With {.CancellationToken = cancellationToken},
30+
Sub(file)
31+
Dim details = AnalyseFile(file)
32+
If details IsNot Nothing Then
33+
fileDetails.Add(details)
34+
If details.CompressionMode <> CompressionAlgorithm.NO_COMPRESSION Then
35+
Interlocked.Increment(compressedFilesCount)
36+
End If
37+
Interlocked.Add(localCompressedBytes, details.CompressedSize)
38+
Interlocked.Add(localUncompressedBytes, details.UncompressedSize)
39+
End If
40+
End Sub)
41+
42+
' Update the shared state after the parallel loop to minimize contention
43+
CompressedBytes = localCompressedBytes
44+
UncompressedBytes = localUncompressedBytes
2745
Catch ex As OperationCanceledException
2846
Debug.WriteLine(ex.Message)
2947
Return Nothing
3048
End Try
3149

32-
ContainsCompressedFiles = compressedFilesCount <> 0
50+
Debug.WriteLine(CompressedBytes)
51+
Debug.WriteLine(UncompressedBytes)
52+
53+
54+
ContainsCompressedFiles = compressedFilesCount > 0
3355
FileCompressionDetailsList = fileDetails.ToList
3456
Return ContainsCompressedFiles
35-
3657
End Function
3758

3859

39-
Private Sub AnalyseFile(file As String, ByRef compressedFilesCount As Integer, ByRef fileDetails As Concurrent.ConcurrentBag(Of AnalysedFileDetails))
40-
60+
Private Function AnalyseFile(file As String) As AnalysedFileDetails
4161
Try
4262
Dim fInfo As New FileInfo(file)
4363
Dim unCompSize = fInfo.Length
4464
Dim compSize = GetFileSizeOnDisk(file)
4565
If compSize < 0 Then
46-
'GetFileSizeOnDisk failed, fall back to unCompSize
47-
compSize = unCompSize
66+
compSize = unCompSize ' GetFileSizeOnDisk failed, fall back to unCompSize
4867
End If
4968
Dim cLevel As CompressionAlgorithm = If(compSize = unCompSize, CompressionAlgorithm.NO_COMPRESSION, DetectCompression(fInfo))
5069

51-
'Sets the backing private fields directly because Interlocked doesn't play nice with properties!
52-
Interlocked.Add(_CompressedBytes, compSize)
53-
Interlocked.Add(_UncompressedBytes, unCompSize)
54-
Interlocked.Add(_testField, 1)
55-
fileDetails.Add(New AnalysedFileDetails With {.FileName = file, .CompressedSize = compSize, .UncompressedSize = unCompSize, .CompressionMode = cLevel})
56-
If cLevel <> CompressionAlgorithm.NO_COMPRESSION Then Interlocked.Increment(compressedFilesCount)
70+
Return New AnalysedFileDetails With {.FileName = file, .CompressedSize = compSize, .UncompressedSize = unCompSize, .CompressionMode = cLevel}
5771
Catch ex As IOException
5872
Debug.WriteLine($"Error analysing file {file}: {ex.Message}")
73+
Return Nothing
5974
End Try
75+
End Function
76+
6077

61-
End Sub
6278
Public Async Function GetPoorlyCompressedExtensions() As Task(Of List(Of ExtensionResult))
6379
Dim extClassResults As New List(Of ExtensionResult)
6480
Await Task.Run(
@@ -70,22 +86,22 @@ Public Class Analyser
7086
If fl.UncompressedSize = 0 Then Return
7187

7288
extRes.AddOrUpdate(xt,
73-
Function(addKey) ' Add value factory
74-
Return New ExtensionResult With {
89+
Function(addKey) ' Add value factory
90+
Return New ExtensionResult With {
7591
.extension = xt,
7692
.totalFiles = 1,
7793
.uncompressedBytes = fl.UncompressedSize,
7894
.compressedBytes = fl.CompressedSize
7995
}
80-
End Function,
81-
Function(updateKey, oldValue) ' Update value factory
82-
Return New ExtensionResult With {
96+
End Function,
97+
Function(updateKey, oldValue) ' Update value factory
98+
Return New ExtensionResult With {
8399
.extension = xt,
84100
.totalFiles = oldValue.totalFiles + 1,
85101
.uncompressedBytes = oldValue.uncompressedBytes + fl.UncompressedSize,
86102
.compressedBytes = oldValue.compressedBytes + fl.CompressedSize
87103
}
88-
End Function)
104+
End Function)
89105
End Sub)
90106

91107
' Filter and convert to list after aggregation
@@ -95,6 +111,7 @@ Public Class Analyser
95111
Return extClassResults
96112
End Function
97113

114+
98115
Private Function DetectCompression(fInfo As FileInfo) As CompressionAlgorithm
99116

100117
Dim isextFile As Integer
@@ -110,45 +127,6 @@ Public Class Analyser
110127
End Function
111128

112129

113-
114-
'Public Function HasDirectoryWritePermission() As Boolean
115-
116-
' Try
117-
' Dim ACRules = New DirectoryInfo(FolderName).GetAccessControl().GetAccessRules(True, True, GetType(Security.Principal.SecurityIdentifier))
118-
119-
' Dim identity = Security.Principal.WindowsIdentity.GetCurrent
120-
' Dim principal = New Security.Principal.WindowsPrincipal(identity)
121-
' Dim writeDenied = False
122-
123-
' For Each FSRule As FileSystemAccessRule In ACRules
124-
' If (FSRule.FileSystemRights And FileSystemRights.Write) = 0 Then Continue For
125-
126-
127-
' ' Use Translate to safely convert to NTAccount
128-
' Dim ntAccount As Security.Principal.NTAccount = Nothing
129-
' Try
130-
' ntAccount = DirectCast(FSRule.IdentityReference.Translate(GetType(Security.Principal.NTAccount)), System.Security.Principal.NTAccount)
131-
' Catch ex As Exception
132-
' Continue For
133-
' End Try
134-
135-
' If ntAccount Is Nothing OrElse Not principal.IsInRole(ntAccount.Value) Then Continue For
136-
137-
' If FSRule.AccessControlType = AccessControlType.Deny Then
138-
' writeDenied = True
139-
' Exit For
140-
' End If
141-
142-
' Next
143-
144-
' Return Not writeDenied
145-
' Catch ex As UnauthorizedAccessException
146-
'
147-
' Return False
148-
' End Try
149-
150-
'End Function
151-
152130
Public Function HasDirectoryWritePermission() As Boolean
153131
Try
154132
Dim directoryInfo = New DirectoryInfo(FolderName)

CompactGUI.Core/CompactGUI.Core.vbproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,13 @@
55
<TargetFramework>net6.0-windows</TargetFramework>
66
</PropertyGroup>
77

8+
<ItemGroup>
9+
<PackageReference Include="Fody" Version="6.8.0">
10+
<PrivateAssets>all</PrivateAssets>
11+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
12+
</PackageReference>
13+
<PackageReference Include="MeasurePerformance.Fody" Version="1.3.1" />
14+
<PackageReference Include="MethodTimer.Fody" Version="3.2.2" />
15+
</ItemGroup>
16+
817
</Project>

CompactGUI.Core/FodyWeavers.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
3+
<MeasurePerformance />
4+
</Weavers>

CompactGUI.Watcher/CompactGUI.Watcher.vbproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
</PropertyGroup>
77

88
<ItemGroup>
9-
<PackageReference Include="Fody" Version="6.6.2">
9+
<PackageReference Include="Fody" Version="6.8.1">
1010
<PrivateAssets>all</PrivateAssets>
1111
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1212
</PackageReference>
1313
<PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.1.2" />
14-
<PackageReference Include="PropertyChanged.Fody" Version="3.4.1" PrivateAssets="All"/>
14+
<PackageReference Include="PropertyChanged.Fody" Version="3.4.1" PrivateAssets="All" />
1515
</ItemGroup>
1616

1717
<ItemGroup>

CompactGUI/ViewModels/MainViewModel.vb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ Public Class MainViewModel : Inherits ObservableObject
106106
End Sub
107107

108108
Private Async Function UpdateWatcherAndState(containsCompressedFiles As Boolean, Analyser As Core.Analyser) As Task
109+
ActiveFolder.PoorlyCompressedFiles = Await Analyser.GetPoorlyCompressedExtensions()
110+
111+
For Each ix In ActiveFolder.PoorlyCompressedFiles
112+
Debug.WriteLine(" " & ix.extension & ": " & ix.totalFiles)
113+
Next
109114

110115
If containsCompressedFiles OrElse ActiveFolder.IsFreshlyCompressed Then
111116
State = "FolderCompressedResults"

0 commit comments

Comments
 (0)