-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Add Disk Space Checker #35964
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
smallketchup82
wants to merge
7
commits into
ppy:master
Choose a base branch
from
smallketchup82:disk-usage
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+120
−0
Open
Add Disk Space Checker #35964
Changes from 3 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
6232a8b
Add disk usage checker
smallketchup82 8ee8c7f
Fix ambiguous `FileInfo`
smallketchup82 c641f0a
Return async task directy
smallketchup82 fb73dec
Fix external disks not working
smallketchup82 863a169
Rename `validPathRoot` to `validPath` and make it non-nullable
smallketchup82 d81fb0a
Fix capitalization
smallketchup82 2b47165
Improve exception message
smallketchup82 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| // Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
| // See the LICENCE file in the repository root for full licence text. | ||
|
|
||
| using System.IO; | ||
| using System.Threading.Tasks; | ||
| using NUnit.Framework; | ||
| using osu.Game.IO; | ||
|
|
||
| namespace osu.Game.Tests.Database | ||
| { | ||
| [TestFixture] | ||
| public class DiskUsageTests | ||
| { | ||
| private string tempDir = null!; | ||
|
|
||
| [SetUp] | ||
| public void SetUp() | ||
| { | ||
| // Create a temporary directory to ensure we are testing against a valid location | ||
| tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); | ||
| Directory.CreateDirectory(tempDir); | ||
| } | ||
|
|
||
| [TearDown] | ||
| public void TearDown() | ||
| { | ||
| if (Directory.Exists(tempDir)) | ||
| Directory.Delete(tempDir, true); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestSufficientSpace() | ||
| { | ||
| // Asking for 0 bytes should always succeed (unless the drive is 100% full) | ||
| Assert.DoesNotThrow(() => DiskUsage.EnsureSufficientSpace(tempDir, 0)); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestInsufficientSpace() | ||
| { | ||
| // Asking for the maximum possible long value should always exceed available space | ||
| Assert.Throws<IOException>(() => DiskUsage.EnsureSufficientSpace(tempDir, long.MaxValue)); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestNonExistentDirectory() | ||
| { | ||
| string nonExistentPath = Path.Combine(tempDir, "does_not_exist"); | ||
| Assert.Throws<DirectoryNotFoundException>(() => DiskUsage.EnsureSufficientSpace(nonExistentPath)); | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task TestAsyncWrapper() | ||
| { | ||
| await DiskUsage.EnsureSufficientSpaceAsync(tempDir, 0); | ||
| } | ||
| } | ||
| } |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| // Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
| // See the LICENCE file in the repository root for full licence text. | ||
|
|
||
| using System.IO; | ||
| using System.Threading.Tasks; | ||
| using osu.Framework.Logging; | ||
|
|
||
| namespace osu.Game.IO | ||
| { | ||
| public static class DiskUsage | ||
| { | ||
| /// <summary> | ||
| /// 500 MiB | ||
| /// </summary> | ||
| private const long required_space_default = 512L * 1024L * 1024L; | ||
|
|
||
| /// <summary> | ||
| /// Checks if the available free space on the drive containing the path is sufficient for normal operation. | ||
| /// This method is blocking, and <see cref="EnsureSufficientSpaceAsync"/> should be preferred in IO-bound scenarios. | ||
| /// </summary> | ||
| /// <param name="checkPath">A path to a file or directory in which the drive's disk space should be checked.</param> | ||
| /// <param name="requiredSpace">The amount of space to ensure is available in bytes. Defaults to <see cref="required_space_default"/>.</param> | ||
| public static void EnsureSufficientSpace(string checkPath, long requiredSpace = required_space_default) | ||
| { | ||
| if (!Directory.Exists(checkPath)) | ||
| throw new DirectoryNotFoundException($"The directory '{checkPath}' does not exist or could not be found."); | ||
|
|
||
| string? validPathRoot = Path.GetPathRoot(checkPath); | ||
|
|
||
| if (string.IsNullOrEmpty(validPathRoot)) | ||
| throw new IOException($"The directory '{checkPath}' is not a valid path."); | ||
|
|
||
| var activeDriveInfo = new DriveInfo(validPathRoot); | ||
|
|
||
| long availableFreeSpace = activeDriveInfo.AvailableFreeSpace; | ||
|
|
||
| #if DEBUG | ||
| Logger.Log($"Available disk space: {availableFreeSpace / 1048576L} MiB"); | ||
| #endif | ||
|
|
||
| if (availableFreeSpace < requiredSpace) | ||
| throw new IOException($"Insufficient disk space available! Required: {requiredSpace} | Available: {availableFreeSpace}"); | ||
| } | ||
|
|
||
| public static Task EnsureSufficientSpaceAsync(string checkDirectory, long requiredSpace = required_space_default) | ||
| { | ||
| return Task.Run(() => EnsureSufficientSpace(checkDirectory, requiredSpace)); | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm reading the documentation correctly, this will basically always return
"/"on non-Windows, making this code invalid if osu! is on an external disk. Have you checked that this correctly reports the free size when querying directories on external disks on macOS?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have not, thanks for catching that. Should be fixed in fb73dec
Using
GetPathRoot()does always return"/". Fortunately, my main use for that method was simply to check if the provided path is valid, so changing it toGetFullPath()properly provides the correct disk space while still checking path validity.Here's a test on my Linux PC, having switched to

GetFullPath(), testing for"/"and my HDD:Which is roughly consistent with what my OS reports for my hard drive:

Note: The reason for the large difference here is that the logger reports the available space in MiB, while
dufreports in GB. Convert the 385,103 MiB to GB and you get 403GB, which is exactly what my OS reports.The reason for that second discrepancy (376GB vs 403GB), is due to the fact that
dufreports btrfs's actual free space including metadata usage, whileDiskInfojust checks whatever my OS returns. The available space for my HDD is reported as 403GB in nautilus, so everything here is accurate and working as intended, just confusing due to linux shenanigans.