Created
January 18, 2024 10:49
-
-
Save anonhostpi/131ff50d0ab648daaf64d2aaa98e160f to your computer and use it in GitHub Desktop.
Temporary path generation and garbage collection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Scope table for the module | |
$scope = @{} | |
$scope.mname = "TempPathModule" | |
$scope.parent_path = @( | |
[System.IO.Path]::GetTempPath() | |
$scope.mname | |
) | Join-Path | |
$scope.mutexes = @{} | |
# Enforce the Parent Path for the module's temporary paths | |
New-Item -ItemType Directory -Path $scope.parent_path -Force | |
function New-TempPath{ | |
param( | |
[string] $Name | |
) | |
$tempname = $Name | |
While( Test-Path $tempname ){ | |
[string] $uuid = [System.Guid]::NewGuid() | |
$bigint = [uint128]::Parse( $uuid.ToString().Replace("-",""), 'AllowHexSpecifier') | |
$compressed = "" | |
# Make hex-string more compressed by encoding it in base36 (alphanumeric) | |
$chars = "0123456789abcdefghijklmnopqrstuvwxyz" | |
While( $bigint -gt 0 ){ | |
$remainder = $bigint % 36 | |
$compressed = $chars[$remainder] + $compressed | |
$bigint = $bigint/36 | |
} | |
$tempname = $compressed | |
} | |
$ammend_name_condition = ` | |
(-not [string]::IsNullOrWhiteSpace( $Name ) ) -and ` | |
$Name -ne $tempname | |
If( $ammend_name_condition ){ | |
$Name = "$Name-$tempname" | |
} | |
$scope.mutexes."$Name" = New-Object System.Threading.Mutex($true, "Global\$( $scope.mname )-$Name") # Lock the directory from automatic removal | |
$path = @( | |
$scope.parent_path, | |
$Name | |
) | Join-Path | |
New-Item -ItemType Directory -Path $path -Force | |
} | |
# Garbage Collector - can only clear: | |
# - garbage from this session or | |
# - (-AllUnused) all unused garbage from all sessions | |
function Clear-TempPaths { | |
param( | |
[Alias("Name")] | |
[string] $Id, | |
[switch] $AllUnused | |
) | |
# Clear the TempPath from any unused directories | |
If( $AllUnused ){ | |
Resolve-Path (Join-Path $scope.parent_path "*") | ForEach-Object -Parallel { | |
$Id = $_ | Split-Path -Leaf | |
[bool] $freed = $false | |
# Check if the directory is still in use, by checking its Mutex | |
$m = New-Object System.Threading.Mutex( $false, "Global\$( $scope.mname )-$id", [ref] $freed ) | |
If( $freed ){ | |
Remove-Item $_ -Recurse -ErrorAction Stop | |
} | |
$m.Dispose() | |
} -ThrottleLimit 12 -AsJob | Out-Null | |
} Elseif( @( $scope.mutexes.Keys ) -contains $Id ){ | |
$path = (Join-Path $scope.parent_path $Id) | |
If( Test-Path $path ){ | |
Remove-Item $path -Recurse -ErrorAction Stop | |
} | |
$scope.mutexes."$Id".Dispose() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment