diff --git a/osu.Game/Database/IRealmFactory.cs b/osu.Game/Database/IRealmFactory.cs index 0fffc3d7be..4a92a5683b 100644 --- a/osu.Game/Database/IRealmFactory.cs +++ b/osu.Game/Database/IRealmFactory.cs @@ -22,6 +22,6 @@ namespace osu.Game.Database /// This method may block if a write is already active on a different thread. /// /// A usage containing a usable context. - RealmWriteUsage GetForWrite(); + RealmContextFactory.RealmWriteUsage GetForWrite(); } } diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs index ea3549a9cd..dc8761fb3c 100644 --- a/osu.Game/Database/RealmContextFactory.cs +++ b/osu.Game/Database/RealmContextFactory.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Threading; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Framework.Platform; @@ -13,6 +14,7 @@ namespace osu.Game.Database public class RealmContextFactory : Component, IRealmFactory { private readonly Storage storage; + private const string database_name = @"client"; private const int schema_version = 5; @@ -22,20 +24,11 @@ namespace osu.Game.Database /// private readonly object writeLock = new object(); - private ThreadLocal refreshCompleted = new ThreadLocal(); - - private bool rollbackRequired; - private int currentWriteUsages; - private Transaction currentWriteTransaction; - private static readonly GlobalStatistic reads = GlobalStatistics.Get("Realm", "Get (Read)"); private static readonly GlobalStatistic writes = GlobalStatistics.Get("Realm", "Get (Write)"); - private static readonly GlobalStatistic refreshes = GlobalStatistics.Get("Realm", "Refreshes"); - private static readonly GlobalStatistic commits = GlobalStatistics.Get("Realm", "Commits"); - private static readonly GlobalStatistic rollbacks = GlobalStatistics.Get("Realm", "Rollbacks"); - private static readonly GlobalStatistic contexts_open = GlobalStatistics.Get("Realm", "Contexts (Open)"); + private static readonly GlobalStatistic refreshes = GlobalStatistics.Get("Realm", "Dirty Refreshes"); private static readonly GlobalStatistic contexts_created = GlobalStatistics.Get("Realm", "Contexts (Created)"); private Realm context; @@ -72,24 +65,8 @@ namespace osu.Game.Database writes.Value++; Monitor.Enter(writeLock); - Realm realm; - - try - { - realm = createContext(); - - currentWriteTransaction ??= realm.BeginWrite(); - } - catch - { - // retrieval of a context could trigger a fatal error. - Monitor.Exit(writeLock); - throw; - } - Interlocked.Increment(ref currentWriteUsages); - - return new RealmWriteUsage(realm, usageCompleted) { IsTransactionLeader = currentWriteTransaction != null && currentWriteUsages == 1 }; + return new RealmWriteUsage(this); } protected override void Update() @@ -111,41 +88,25 @@ namespace osu.Game.Database }); } - private void usageCompleted(RealmWriteUsage usage) - { - int usages = Interlocked.Decrement(ref currentWriteUsages); - - try - { - rollbackRequired |= usage.RollbackRequired; - - if (usages == 0) - { - if (rollbackRequired) - { - rollbacks.Value++; - currentWriteTransaction?.Rollback(); - } - else - { - commits.Value++; - currentWriteTransaction?.Commit(); - } - - currentWriteTransaction = null; - rollbackRequired = false; - - refreshCompleted = new ThreadLocal(); - } - } - finally - { - Monitor.Exit(writeLock); - } - } - private void onMigration(Migration migration, ulong lastSchemaVersion) { } + + public class RealmWriteUsage : InvokeOnDisposal + { + public readonly Realm Context; + + public RealmWriteUsage(RealmContextFactory factory) + : base(factory, usageCompleted) + { + Context = factory.createContext(); + Context.BeginWrite(); + } + + private static void usageCompleted(RealmContextFactory factory) + { + Monitor.Exit(factory.writeLock); + } + } } } diff --git a/osu.Game/Database/RealmWriteUsage.cs b/osu.Game/Database/RealmWriteUsage.cs deleted file mode 100644 index 35e30e8123..0000000000 --- a/osu.Game/Database/RealmWriteUsage.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using Realms; - -namespace osu.Game.Database -{ - public class RealmWriteUsage : IDisposable - { - public readonly Realm Context; - private readonly Action usageCompleted; - - public bool RollbackRequired { get; private set; } - - public RealmWriteUsage(Realm context, Action onCompleted) - { - Context = context; - usageCompleted = onCompleted; - } - - /// - /// Whether this write usage will commit a transaction on completion. - /// If false, there is a parent usage responsible for transaction commit. - /// - public bool IsTransactionLeader; - - private bool isDisposed; - - protected void Dispose(bool disposing) - { - if (isDisposed) return; - - isDisposed = true; - - usageCompleted?.Invoke(this); - } - - public void Rollback(Exception error = null) - { - RollbackRequired = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~RealmWriteUsage() - { - Dispose(false); - } - } -}