diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index 7a6eea44c1..3d13c56728 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Linq.Expressions; using System.Security.Cryptography; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; @@ -39,16 +40,37 @@ public BeatmapDatabase(Storage storage, GameHost importHost = null) try { connection = prepareConnection(); + deletePending(); } - catch + catch (Exception e) { - Console.WriteLine(@"Failed to initialise the beatmap database! Trying again with a clean database..."); + Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database..."); storage.DeleteDatabase(@"beatmaps"); connection = prepareConnection(); } } } + private void deletePending() + { + foreach (var b in Query().Where(b => b.DeletePending)) + { + try + { + storage.Delete(b.Path); + connection.Delete(b); + } + catch (Exception e) + { + Logger.Error(e, $@"Could not delete beatmap {b.ToString()}"); + } + } + + //this is required because sqlite migrations don't work, initially inserting nulls into this field. + //see https://github.com/praeclarum/sqlite-net/issues/326 + connection.Query("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL"); + } + private SQLiteConnection prepareConnection() { var conn = storage.GetDatabase(@"beatmaps"); @@ -161,8 +183,9 @@ public void Import(IEnumerable beatmapSets) public void Delete(BeatmapSetInfo beatmapSet) { - storage.Delete(beatmapSet.Path); - connection.Delete(beatmapSet); + beatmapSet.DeletePending = true; + Update(beatmapSet, false); + BeatmapSetRemoved?.Invoke(beatmapSet); } diff --git a/osu.Game/Database/BeatmapSetInfo.cs b/osu.Game/Database/BeatmapSetInfo.cs index 88d35d20a8..e4e9c35963 100644 --- a/osu.Game/Database/BeatmapSetInfo.cs +++ b/osu.Game/Database/BeatmapSetInfo.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.ComponentModel; using SQLite.Net.Attributes; using SQLiteNetExtensions.Attributes; @@ -23,6 +24,8 @@ public class BeatmapSetInfo [OneToMany(CascadeOperations = CascadeOperation.All)] public List Beatmaps { get; set; } + public bool DeletePending { get; set; } + public string Hash { get; set; } public string Path { get; set; } diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index ccc02adf84..256231e041 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -377,7 +377,7 @@ private void removeBeatmapSet(BeatmapSetInfo beatmapSet) private void addBeatmapSets(Framework.Game game, CancellationToken token) { - foreach (var beatmapSet in database.Query()) + foreach (var beatmapSet in database.Query().Where(b => !b.DeletePending)) { if (token.IsCancellationRequested) return; addBeatmapSet(beatmapSet, game);