mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 15:16:38 +09:00
Merge branch 'realm-clean-up' into realm-block-timeout-assert-failure
This commit is contained in:
@ -101,15 +101,15 @@ namespace osu.Game.Database
|
||||
{
|
||||
using (var ef = efContextFactory.Get())
|
||||
{
|
||||
realm.Write(realm =>
|
||||
realm.Write(r =>
|
||||
{
|
||||
// Before beginning, ensure realm is in an empty state.
|
||||
// Migrations which are half-completed could lead to issues if the user tries a second time.
|
||||
// Note that we only do this for beatmaps and scores since the other migrations are yonks old.
|
||||
realm.RemoveAll<BeatmapSetInfo>();
|
||||
realm.RemoveAll<BeatmapInfo>();
|
||||
realm.RemoveAll<BeatmapMetadata>();
|
||||
realm.RemoveAll<ScoreInfo>();
|
||||
r.RemoveAll<BeatmapSetInfo>();
|
||||
r.RemoveAll<BeatmapInfo>();
|
||||
r.RemoveAll<BeatmapMetadata>();
|
||||
r.RemoveAll<ScoreInfo>();
|
||||
});
|
||||
|
||||
migrateSettings(ef);
|
||||
@ -158,11 +158,11 @@ namespace osu.Game.Database
|
||||
|
||||
int count = existingBeatmapSets.Count();
|
||||
|
||||
realm.Run(realm =>
|
||||
realm.Run(r =>
|
||||
{
|
||||
log($"Found {count} beatmaps in EF");
|
||||
|
||||
var transaction = realm.BeginWrite();
|
||||
var transaction = r.BeginWrite();
|
||||
int written = 0;
|
||||
|
||||
try
|
||||
@ -172,7 +172,7 @@ namespace osu.Game.Database
|
||||
if (++written % 1000 == 0)
|
||||
{
|
||||
transaction.Commit();
|
||||
transaction = realm.BeginWrite();
|
||||
transaction = r.BeginWrite();
|
||||
log($"Migrated {written}/{count} beatmaps...");
|
||||
}
|
||||
|
||||
@ -186,11 +186,11 @@ namespace osu.Game.Database
|
||||
Protected = beatmapSet.Protected,
|
||||
};
|
||||
|
||||
migrateFiles(beatmapSet, realm, realmBeatmapSet);
|
||||
migrateFiles(beatmapSet, r, realmBeatmapSet);
|
||||
|
||||
foreach (var beatmap in beatmapSet.Beatmaps)
|
||||
{
|
||||
var ruleset = realm.Find<RulesetInfo>(beatmap.RulesetInfo.ShortName);
|
||||
var ruleset = r.Find<RulesetInfo>(beatmap.RulesetInfo.ShortName);
|
||||
var metadata = getBestMetadata(beatmap.Metadata, beatmapSet.Metadata);
|
||||
|
||||
var realmBeatmap = new BeatmapInfo(ruleset, new BeatmapDifficulty(beatmap.BaseDifficulty), metadata)
|
||||
@ -225,7 +225,7 @@ namespace osu.Game.Database
|
||||
realmBeatmapSet.Beatmaps.Add(realmBeatmap);
|
||||
}
|
||||
|
||||
realm.Add(realmBeatmapSet);
|
||||
r.Add(realmBeatmapSet);
|
||||
}
|
||||
}
|
||||
finally
|
||||
@ -280,11 +280,11 @@ namespace osu.Game.Database
|
||||
|
||||
int count = existingScores.Count();
|
||||
|
||||
realm.Run(realm =>
|
||||
realm.Run(r =>
|
||||
{
|
||||
log($"Found {count} scores in EF");
|
||||
|
||||
var transaction = realm.BeginWrite();
|
||||
var transaction = r.BeginWrite();
|
||||
int written = 0;
|
||||
|
||||
try
|
||||
@ -294,12 +294,12 @@ namespace osu.Game.Database
|
||||
if (++written % 1000 == 0)
|
||||
{
|
||||
transaction.Commit();
|
||||
transaction = realm.BeginWrite();
|
||||
transaction = r.BeginWrite();
|
||||
log($"Migrated {written}/{count} scores...");
|
||||
}
|
||||
|
||||
var beatmap = realm.All<BeatmapInfo>().First(b => b.Hash == score.BeatmapInfo.Hash);
|
||||
var ruleset = realm.Find<RulesetInfo>(score.Ruleset.ShortName);
|
||||
var beatmap = r.All<BeatmapInfo>().First(b => b.Hash == score.BeatmapInfo.Hash);
|
||||
var ruleset = r.Find<RulesetInfo>(score.Ruleset.ShortName);
|
||||
var user = new RealmUser
|
||||
{
|
||||
OnlineID = score.User.OnlineID,
|
||||
@ -329,9 +329,9 @@ namespace osu.Game.Database
|
||||
APIMods = score.APIMods,
|
||||
};
|
||||
|
||||
migrateFiles(score, realm, realmScore);
|
||||
migrateFiles(score, r, realmScore);
|
||||
|
||||
realm.Add(realmScore);
|
||||
r.Add(realmScore);
|
||||
}
|
||||
}
|
||||
finally
|
||||
@ -369,13 +369,13 @@ namespace osu.Game.Database
|
||||
break;
|
||||
}
|
||||
|
||||
realm.Run(realm =>
|
||||
realm.Run(r =>
|
||||
{
|
||||
using (var transaction = realm.BeginWrite())
|
||||
using (var transaction = r.BeginWrite())
|
||||
{
|
||||
// only migrate data if the realm database is empty.
|
||||
// note that this cannot be written as: `realm.All<SkinInfo>().All(s => s.Protected)`, because realm does not support `.All()`.
|
||||
if (!realm.All<SkinInfo>().Any(s => !s.Protected))
|
||||
// note that this cannot be written as: `r.All<SkinInfo>().All(s => s.Protected)`, because realm does not support `.All()`.
|
||||
if (!r.All<SkinInfo>().Any(s => !s.Protected))
|
||||
{
|
||||
log($"Migrating {existingSkins.Count} skins");
|
||||
|
||||
@ -390,9 +390,9 @@ namespace osu.Game.Database
|
||||
InstantiationInfo = skin.InstantiationInfo,
|
||||
};
|
||||
|
||||
migrateFiles(skin, realm, realmSkin);
|
||||
migrateFiles(skin, r, realmSkin);
|
||||
|
||||
realm.Add(realmSkin);
|
||||
r.Add(realmSkin);
|
||||
|
||||
if (skin.ID == userSkinInt)
|
||||
userSkinChoice.Value = realmSkin.ID.ToString();
|
||||
@ -428,12 +428,12 @@ namespace osu.Game.Database
|
||||
|
||||
log("Beginning settings migration to realm");
|
||||
|
||||
realm.Run(realm =>
|
||||
realm.Run(r =>
|
||||
{
|
||||
using (var transaction = realm.BeginWrite())
|
||||
using (var transaction = r.BeginWrite())
|
||||
{
|
||||
// only migrate data if the realm database is empty.
|
||||
if (!realm.All<RealmRulesetSetting>().Any())
|
||||
if (!r.All<RealmRulesetSetting>().Any())
|
||||
{
|
||||
log($"Migrating {existingSettings.Count} settings");
|
||||
|
||||
@ -447,7 +447,7 @@ namespace osu.Game.Database
|
||||
if (string.IsNullOrEmpty(shortName))
|
||||
continue;
|
||||
|
||||
realm.Add(new RealmRulesetSetting
|
||||
r.Add(new RealmRulesetSetting
|
||||
{
|
||||
Key = dkb.Key,
|
||||
Value = dkb.StringValue,
|
||||
|
@ -30,7 +30,7 @@ using Realms.Exceptions;
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
/// <summary>
|
||||
/// A factory which provides both the main (update thread bound) realm context and creates contexts for async usage.
|
||||
/// A factory which provides safe access to the realm storage backend.
|
||||
/// </summary>
|
||||
public class RealmAccess : IDisposable
|
||||
{
|
||||
@ -57,9 +57,9 @@ namespace osu.Game.Database
|
||||
private const int schema_version = 13;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object which is held during <see cref="BlockAllOperations"/> sections, blocking context creation during blocking periods.
|
||||
/// Lock object which is held during <see cref="BlockAllOperations"/> sections, blocking realm retrieval during blocking periods.
|
||||
/// </summary>
|
||||
private readonly SemaphoreSlim realmCreationLock = new SemaphoreSlim(1);
|
||||
private readonly SemaphoreSlim realmRetrievalLock = new SemaphoreSlim(1);
|
||||
|
||||
private readonly ThreadLocal<bool> currentThreadCanCreateRealmInstances = new ThreadLocal<bool>();
|
||||
|
||||
@ -76,7 +76,7 @@ namespace osu.Game.Database
|
||||
|
||||
/// <summary>
|
||||
/// Holds a map of functions registered via <see cref="RegisterForNotifications{T}"/> and a coinciding action which when triggered,
|
||||
/// fires a change set event with an empty collection. This is used to inform subscribers when a realm context goes away, and ensure they don't use invalidated
|
||||
/// fires a change set event with an empty collection. This is used to inform subscribers when the main realm instance gets recycled, and ensure they don't use invalidated
|
||||
/// managed realm objects from a previous firing.
|
||||
/// </summary>
|
||||
private readonly Dictionary<Func<Realm, IDisposable?>, Action> notificationsResetMap = new Dictionary<Func<Realm, IDisposable?>, Action>();
|
||||
@ -364,7 +364,7 @@ namespace osu.Game.Database
|
||||
{
|
||||
if (!currentThreadCanCreateRealmInstances.Value)
|
||||
{
|
||||
realmCreationLock.Wait();
|
||||
realmRetrievalLock.Wait();
|
||||
currentThreadCanCreateRealmInstances.Value = true;
|
||||
tookSemaphoreLock = true;
|
||||
}
|
||||
@ -383,7 +383,7 @@ namespace osu.Game.Database
|
||||
{
|
||||
if (tookSemaphoreLock)
|
||||
{
|
||||
realmCreationLock.Release();
|
||||
realmRetrievalLock.Release();
|
||||
currentThreadCanCreateRealmInstances.Value = false;
|
||||
}
|
||||
}
|
||||
@ -589,14 +589,14 @@ namespace osu.Game.Database
|
||||
|
||||
try
|
||||
{
|
||||
realmCreationLock.Wait();
|
||||
realmRetrievalLock.Wait();
|
||||
|
||||
lock (realmLock)
|
||||
{
|
||||
if (updateRealm == null)
|
||||
{
|
||||
// null context means the update thread has not yet retrieved its context.
|
||||
// we don't need to worry about reviving the update context in this case, so don't bother with the SynchronizationContext.
|
||||
// null realm means the update thread has not yet retrieved its instance.
|
||||
// we don't need to worry about reviving the update instance in this case, so don't bother with the SynchronizationContext.
|
||||
Debug.Assert(!ThreadSafety.IsUpdateThread);
|
||||
}
|
||||
else
|
||||
@ -648,7 +648,7 @@ namespace osu.Game.Database
|
||||
void restoreOperation()
|
||||
{
|
||||
Logger.Log(@"Restoring realm operations.", LoggingTarget.Database);
|
||||
realmCreationLock.Release();
|
||||
realmRetrievalLock.Release();
|
||||
// Post back to the update thread to revive any subscriptions.
|
||||
syncContext?.Post(_ => ensureUpdateRealm(), null);
|
||||
}
|
||||
@ -668,9 +668,9 @@ namespace osu.Game.Database
|
||||
|
||||
if (!isDisposed)
|
||||
{
|
||||
// intentionally block context creation indefinitely. this ensures that nothing can start consuming a new context after disposal.
|
||||
realmCreationLock.Wait();
|
||||
realmCreationLock.Dispose();
|
||||
// intentionally block realm retrieval indefinitely. this ensures that nothing can start consuming a new instance after disposal.
|
||||
realmRetrievalLock.Wait();
|
||||
realmRetrievalLock.Dispose();
|
||||
|
||||
isDisposed = true;
|
||||
}
|
||||
|
@ -51,10 +51,7 @@ namespace osu.Game.Database
|
||||
return;
|
||||
}
|
||||
|
||||
realm.Run(realm =>
|
||||
{
|
||||
perform(retrieveFromID(realm, ID));
|
||||
});
|
||||
realm.Run(r => perform(retrieveFromID(r, ID)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -66,9 +63,9 @@ namespace osu.Game.Database
|
||||
if (!IsManaged)
|
||||
return perform(data);
|
||||
|
||||
return realm.Run(realm =>
|
||||
return realm.Run(r =>
|
||||
{
|
||||
var returnData = perform(retrieveFromID(realm, ID));
|
||||
var returnData = perform(retrieveFromID(r, ID));
|
||||
|
||||
if (returnData is RealmObjectBase realmObject && realmObject.IsManaged)
|
||||
throw new InvalidOperationException(@$"Managed realm objects should not exit the scope of {nameof(PerformRead)}.");
|
||||
|
Reference in New Issue
Block a user