1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-28 02:43:19 +08:00

Fix transactions not actually being committed

This commit is contained in:
Dean Herbert 2021-01-14 16:13:10 +09:00
parent af1509d892
commit 8a08d3f4ef
4 changed files with 49 additions and 21 deletions

View File

@ -1,8 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Threading; using System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Platform; using osu.Framework.Platform;
@ -92,19 +92,42 @@ namespace osu.Game.Database
{ {
} }
public class RealmWriteUsage : InvokeOnDisposal<RealmContextFactory> /// <summary>
/// A transaction used for making changes to realm data.
/// </summary>
public class RealmWriteUsage : IDisposable
{ {
public readonly Realm Context; public readonly Realm Realm;
public RealmWriteUsage(RealmContextFactory factory) private readonly RealmContextFactory factory;
: base(factory, usageCompleted) private readonly Transaction transaction;
internal RealmWriteUsage(RealmContextFactory factory)
{ {
Context = factory.createContext(); this.factory = factory;
Context.BeginWrite();
Realm = factory.createContext();
transaction = Realm.BeginWrite();
} }
private static void usageCompleted(RealmContextFactory factory) /// <summary>
/// Commit all changes made in this transaction.
/// </summary>
public void Commit() => transaction.Commit();
/// <summary>
/// Revert all changes made in this transaction.
/// </summary>
public void Rollback() => transaction.Rollback();
/// <summary>
/// Disposes this instance, calling the initially captured action.
/// </summary>
public virtual void Dispose()
{ {
// rollback if not explicitly committed.
transaction?.Dispose();
Monitor.Exit(factory.writeLock); Monitor.Exit(factory.writeLock);
pending_writes.Value--; pending_writes.Value--;
} }

View File

@ -53,12 +53,9 @@ namespace osu.Game.Input
{ {
var instance = ruleset.CreateInstance(); var instance = ruleset.CreateInstance();
using (realmFactory.GetForWrite())
{
foreach (var variant in instance.AvailableVariants) foreach (var variant in instance.AvailableVariants)
insertDefaults(instance.GetDefaultKeyBindings(variant), ruleset.ID, variant); insertDefaults(instance.GetDefaultKeyBindings(variant), ruleset.ID, variant);
} }
}
private void insertDefaults(IEnumerable<IKeyBinding> defaults, int? rulesetId = null, int? variant = null) private void insertDefaults(IEnumerable<IKeyBinding> defaults, int? rulesetId = null, int? variant = null)
{ {
@ -67,7 +64,7 @@ namespace osu.Game.Input
// compare counts in database vs defaults // compare counts in database vs defaults
foreach (var group in defaults.GroupBy(k => k.Action)) foreach (var group in defaults.GroupBy(k => k.Action))
{ {
int count = usage.Context.All<RealmKeyBinding>().Count(k => k.RulesetID == rulesetId && k.Variant == variant && k.ActionInt == (int)group.Key); int count = usage.Realm.All<RealmKeyBinding>().Count(k => k.RulesetID == rulesetId && k.Variant == variant && k.ActionInt == (int)group.Key);
int aimCount = group.Count(); int aimCount = group.Count();
if (aimCount <= count) if (aimCount <= count)
@ -76,7 +73,7 @@ namespace osu.Game.Input
foreach (var insertable in group.Skip(count).Take(aimCount - count)) foreach (var insertable in group.Skip(count).Take(aimCount - count))
{ {
// insert any defaults which are missing. // insert any defaults which are missing.
usage.Context.Add(new RealmKeyBinding usage.Realm.Add(new RealmKeyBinding
{ {
ID = Guid.NewGuid().ToString(), ID = Guid.NewGuid().ToString(),
KeyCombinationString = insertable.KeyCombination.ToString(), KeyCombinationString = insertable.KeyCombination.ToString(),
@ -86,6 +83,8 @@ namespace osu.Game.Input
}); });
} }
} }
usage.Commit();
} }
} }
} }

View File

@ -330,16 +330,16 @@ namespace osu.Game
private void migrateDataToRealm() private void migrateDataToRealm()
{ {
using (var db = contextFactory.GetForWrite()) using (var db = contextFactory.GetForWrite())
using (var realm = realmFactory.GetForWrite()) using (var usage = realmFactory.GetForWrite())
{ {
var existingBindings = db.Context.DatabasedKeyBinding; var existingBindings = db.Context.DatabasedKeyBinding;
// only migrate data if the realm database is empty. // only migrate data if the realm database is empty.
if (!realm.Context.All<RealmKeyBinding>().Any()) if (!usage.Realm.All<RealmKeyBinding>().Any())
{ {
foreach (var dkb in existingBindings) foreach (var dkb in existingBindings)
{ {
realm.Context.Add(new RealmKeyBinding usage.Realm.Add(new RealmKeyBinding
{ {
ID = Guid.NewGuid().ToString(), ID = Guid.NewGuid().ToString(),
KeyCombinationString = dkb.KeyCombination.ToString(), KeyCombinationString = dkb.KeyCombination.ToString(),
@ -351,6 +351,8 @@ namespace osu.Game
} }
db.Context.RemoveRange(existingBindings); db.Context.RemoveRange(existingBindings);
usage.Commit();
} }
} }

View File

@ -129,10 +129,12 @@ namespace osu.Game.Overlays.KeyBinding
var button = buttons[i++]; var button = buttons[i++];
button.UpdateKeyCombination(d); button.UpdateKeyCombination(d);
using (var write = realmFactory.GetForWrite()) using (var usage = realmFactory.GetForWrite())
{ {
var binding = write.Context.Find<RealmKeyBinding>(((IHasGuidPrimaryKey)button.KeyBinding).ID); var binding = usage.Realm.Find<RealmKeyBinding>(((IHasGuidPrimaryKey)button.KeyBinding).ID);
binding.KeyCombinationString = button.KeyBinding.KeyCombinationString; binding.KeyCombinationString = button.KeyBinding.KeyCombinationString;
usage.Commit();
} }
} }
} }
@ -294,8 +296,10 @@ namespace osu.Game.Overlays.KeyBinding
{ {
using (var write = realmFactory.GetForWrite()) using (var write = realmFactory.GetForWrite())
{ {
var binding = write.Context.Find<RealmKeyBinding>(((IHasGuidPrimaryKey)bindTarget.KeyBinding).ID); var binding = write.Realm.Find<RealmKeyBinding>(((IHasGuidPrimaryKey)bindTarget.KeyBinding).ID);
binding.KeyCombinationString = bindTarget.KeyBinding.KeyCombinationString; binding.KeyCombinationString = bindTarget.KeyBinding.KeyCombinationString;
write.Commit();
} }
bindTarget.IsBinding = false; bindTarget.IsBinding = false;