Skip to content

Commit bf23c67

Browse files
authored
Merge pull request #31509 from bdach/local-metadata-cache-corruption
Refetch local metadata cache if corruption is detected
2 parents 11e84f3 + 6ceb348 commit bf23c67

File tree

2 files changed

+41
-20
lines changed

2 files changed

+41
-20
lines changed

osu.Game/Beatmaps/LocalCachedBeatmapMetadataSource.cs

+40-2
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,54 @@ public bool TryLookup(BeatmapInfo beatmapInfo, [NotNullWhen(true)] out OnlineBea
113113
return queryCacheVersion2(db, beatmapInfo, out onlineMetadata);
114114
}
115115
}
116+
117+
onlineMetadata = null;
118+
return false;
119+
}
120+
catch (SqliteException sqliteException)
121+
{
122+
onlineMetadata = null;
123+
124+
// There have been cases where the user's local database is corrupt.
125+
// Let's attempt to identify these cases and re-initialise the local cache.
126+
switch (sqliteException.SqliteErrorCode)
127+
{
128+
case 26: // SQLITE_NOTADB
129+
case 11: // SQLITE_CORRUPT
130+
// only attempt purge & re-download if there is no other refetch in progress
131+
if (cacheDownloadRequest != null)
132+
return false;
133+
134+
tryPurgeCache();
135+
prepareLocalCache();
136+
return false;
137+
}
138+
139+
logForModel(beatmapInfo.BeatmapSet, $@"Cached local retrieval for {beatmapInfo} failed with unhandled sqlite error {sqliteException}.");
140+
return false;
116141
}
117142
catch (Exception ex)
118143
{
119144
logForModel(beatmapInfo.BeatmapSet, $@"Cached local retrieval for {beatmapInfo} failed with {ex}.");
120145
onlineMetadata = null;
121146
return false;
122147
}
148+
}
123149

124-
onlineMetadata = null;
125-
return false;
150+
private void tryPurgeCache()
151+
{
152+
log(@"Local metadata cache is corrupted; attempting purge.");
153+
154+
try
155+
{
156+
File.Delete(storage.GetFullPath(cache_database_name));
157+
}
158+
catch (Exception ex)
159+
{
160+
log($@"Failed to purge local metadata cache: {ex}");
161+
}
162+
163+
log(@"Local metadata cache purged due to corruption.");
126164
}
127165

128166
private SqliteConnection getConnection() =>

osu.Game/Database/RealmAccess.cs

+1-18
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using System.Reflection;
1212
using System.Threading;
1313
using System.Threading.Tasks;
14-
using osu.Framework;
1514
using osu.Framework.Allocation;
1615
using osu.Framework.Development;
1716
using osu.Framework.Extensions;
@@ -414,18 +413,7 @@ private void cleanupPendingDeletions(Realm realm)
414413
/// Compact this realm.
415414
/// </summary>
416415
/// <returns></returns>
417-
public bool Compact()
418-
{
419-
try
420-
{
421-
return Realm.Compact(getConfiguration());
422-
}
423-
// Catch can be removed along with entity framework. Is specifically to allow a failure message to arrive to the user (see similar catches in EFToRealmMigrator).
424-
catch (AggregateException ae) when (RuntimeInfo.OS == RuntimeInfo.Platform.macOS && ae.Flatten().InnerException is TypeInitializationException)
425-
{
426-
return true;
427-
}
428-
}
416+
public bool Compact() => Realm.Compact(getConfiguration());
429417

430418
/// <summary>
431419
/// Run work on realm with a return value.
@@ -721,11 +709,6 @@ private Realm getRealmInstance()
721709

722710
return Realm.GetInstance(getConfiguration());
723711
}
724-
// Catch can be removed along with entity framework. Is specifically to allow a failure message to arrive to the user (see similar catches in EFToRealmMigrator).
725-
catch (AggregateException ae) when (RuntimeInfo.OS == RuntimeInfo.Platform.macOS && ae.Flatten().InnerException is TypeInitializationException)
726-
{
727-
return Realm.GetInstance();
728-
}
729712
finally
730713
{
731714
if (tookSemaphoreLock)

0 commit comments

Comments
 (0)