Skip to content

Commit

Permalink
Prefer CoW over hard link
Browse files Browse the repository at this point in the history
  • Loading branch information
huoyaoyuan committed Oct 11, 2024
1 parent 7c6d60d commit e323d1a
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 10 deletions.
5 changes: 5 additions & 0 deletions osu.Game/Database/ImportParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public struct ImportParameters
/// </remarks>
public bool Batch { get; set; }

/// <summary>
/// Whether this import should use copy on write cloning if available.
/// </summary>
public bool PreferCopyOnWrite { get; set; }

/// <summary>
/// Whether this import should use hard links rather than file copy operations if available.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion osu.Game/Database/LegacyModelImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public Task ImportFromStableAsync(StableStorage stableStorage)
{
var tasks = GetStableImportPaths(storage).Select(p => new ImportTask(p)).ToArray();

await Importer.Import(tasks, new ImportParameters { Batch = true, PreferHardLinks = true }).ConfigureAwait(false);
await Importer.Import(tasks, new ImportParameters { Batch = true, PreferHardLinks = true, PreferCopyOnWrite = true }).ConfigureAwait(false);
});
}

Expand Down
2 changes: 1 addition & 1 deletion osu.Game/Database/RealmArchiveModelImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public async Task<ExternalEditOperation<TModel>> BeginExternalEditing(TModel mod
foreach (var filenames in getShortenedFilenames(archive))
{
using (Stream s = archive.GetStream(filenames.original))
files.Add(new RealmNamedFileUsage(Files.Add(s, realm, false, parameters.PreferHardLinks), filenames.shortened));
files.Add(new RealmNamedFileUsage(Files.Add(s, realm, false, parameters.PreferHardLinks, parameters.PreferCopyOnWrite), filenames.shortened));
}
}

Expand Down
14 changes: 9 additions & 5 deletions osu.Game/Database/RealmFileStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public RealmFileStore(RealmAccess realm, Storage storage)
/// <param name="realm">The realm instance to add to. Should already be in a transaction.</param>
/// <param name="addToRealm">Whether the <see cref="RealmFile"/> should immediately be added to the underlying realm. If <c>false</c> is provided here, the instance must be manually added.</param>
/// <param name="preferHardLinks">Whether this import should use hard links rather than file copy operations if available.</param>
public RealmFile Add(Stream data, Realm realm, bool addToRealm = true, bool preferHardLinks = false)
public RealmFile Add(Stream data, Realm realm, bool addToRealm = true, bool preferHardLinks = false, bool preferCopyOnWrite = false)

Check warning on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Build only (Android)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check warning on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Build only (Android)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check warning on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Build only (iOS)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check warning on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Build only (iOS)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Code Quality

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Code Quality

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, SingleThread)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, SingleThread)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, MultiThreaded)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Test (Windows, windows-latest, MultiThreaded)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, SingleThread)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, SingleThread)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, MultiThreaded)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)

Check failure on line 44 in osu.Game/Database/RealmFileStore.cs

View workflow job for this annotation

GitHub Actions / Test (Linux, ubuntu-latest, MultiThreaded)

Parameter 'preferCopyOnWrite' has no matching param tag in the XML comment for 'RealmFileStore.Add(Stream, Realm, bool, bool, bool)' (but other parameters do)
{
string hash = data.ComputeSHA2Hash();

Expand All @@ -50,20 +50,24 @@ public RealmFile Add(Stream data, Realm realm, bool addToRealm = true, bool pref
var file = existing ?? new RealmFile { Hash = hash };

if (!checkFileExistsAndMatchesHash(file))
copyToStore(file, data, preferHardLinks);
copyToStore(file, data, preferHardLinks, preferCopyOnWrite);

if (addToRealm && !file.IsManaged)
realm.Add(file);

return file;
}

private void copyToStore(RealmFile file, Stream data, bool preferHardLinks)
private void copyToStore(RealmFile file, Stream data, bool preferHardLinks, bool preferCopyOnWrite)
{
if (data is FileStream fs && preferHardLinks)
if (data is FileStream fs && preferCopyOnWrite)
{
// Prefer CoW over hard link because it provides better isolation.
if (preferCopyOnWrite && HardLinkHelper.TryCreateHardLink(Storage.GetFullPath(file.GetStoragePath(), true), fs.Name))
return;

// attempt to do a fast hard link rather than copy.
if (HardLinkHelper.TryCreateHardLink(Storage.GetFullPath(file.GetStoragePath(), true), fs.Name))
if (preferHardLinks && HardLinkHelper.TryCreateHardLink(Storage.GetFullPath(file.GetStoragePath(), true), fs.Name))
return;
}

Expand Down
15 changes: 12 additions & 3 deletions osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,19 @@ private void updateStablePath()
stableLocatorTextBox.Current.Value = storage.GetFullPath(string.Empty);
importButton.Enabled.Value = true;

bool available = legacyImportManager.CheckSongsFolderHardLinkAvailability();
Logger.Log($"Hard link support for beatmaps is {available}");
bool cowAvailable = legacyImportManager.CheckSongsFolderCoWAvailability();
Logger.Log($"CoW support for beatmaps is {cowAvailable}");

if (available)
bool hardLinkAvailable = legacyImportManager.CheckSongsFolderHardLinkAvailability();
Logger.Log($"Hard link support for beatmaps is {hardLinkAvailable}");

if (cowAvailable)
{
copyInformation.Text = FirstRunOverlayImportFromStableScreenStrings.DataMigrationNoExtraSpaceWithCoW;
copyInformation.AddText(@" "); // just to ensure correct spacing
copyInformation.AddLink(FirstRunOverlayImportFromStableScreenStrings.LearnMoreAboutCoW, LinkAction.OpenWiki, @"Client/Release_stream/Lazer/File_storage#via-copy-on-write");
}
else if (hardLinkAvailable)
{
copyInformation.Text = FirstRunOverlayImportFromStableScreenStrings.DataMigrationNoExtraSpace;
copyInformation.AddText(@" "); // just to ensure correct spacing
Expand Down

0 comments on commit e323d1a

Please sign in to comment.