private void usageCompleted(DatabaseWriteUsage usage) { int usages = Interlocked.Decrement(ref currentWriteUsages); try { currentWriteDidWrite |= usage.PerformedWrite; if (usages > 0) { return; } if (currentWriteDidWrite) { // explicitly dispose to ensure any outstanding flushes happen as soon as possible (and underlying resources are purged). usage.Context.Dispose(); currentWriteDidWrite = false; // once all writes are complete, we want to refresh thread-specific contexts to make sure they don't have stale local caches. recycleThreadContexts(); } } finally { Monitor.Exit(writeLock); } }
private void migrateSettings(DatabaseWriteUsage db) { // migrate ruleset settings. can be removed 20220315. var existingSettings = db.Context.DatabasedSetting; // previous entries in EF are removed post migration. if (!existingSettings.Any()) { return; } using (var realm = realmContextFactory.CreateContext()) using (var transaction = realm.BeginWrite()) { // only migrate data if the realm database is empty. if (!realm.All <RealmRulesetSetting>().Any()) { foreach (var dkb in existingSettings) { if (dkb.RulesetID == null) { continue; } string?shortName = getRulesetShortNameFromLegacyID(dkb.RulesetID.Value); if (string.IsNullOrEmpty(shortName)) { continue; } realm.Add(new RealmRulesetSetting { Key = dkb.Key, Value = dkb.StringValue, RulesetName = shortName, Variant = dkb.Variant ?? 0, }); } } db.Context.RemoveRange(existingSettings); transaction.Commit(); } }
private void usageCompleted(DatabaseWriteUsage usage) { int usages = Interlocked.Decrement(ref currentWriteUsages); try { currentWriteDidWrite |= usage.PerformedWrite; currentWriteDidError |= usage.Errors.Any(); if (usages == 0) { if (currentWriteDidError) { rollbacks.Value++; currentWriteTransaction?.Rollback(); } else { commits.Value++; currentWriteTransaction?.Commit(); } if (currentWriteDidWrite || currentWriteDidError) { // explicitly dispose to ensure any outstanding flushes happen as soon as possible (and underlying resources are purged). usage.Context.Dispose(); // once all writes are complete, we want to refresh thread-specific contexts to make sure they don't have stale local caches. recycleThreadContexts(); } currentWriteTransaction = null; currentWriteDidWrite = false; currentWriteDidError = false; } } finally { Monitor.Exit(writeLock); } }
private void migrateSkins(DatabaseWriteUsage db) { // can be removed 20220530. var existingSkins = db.Context.SkinInfo .Include(s => s.Files) .ThenInclude(f => f.FileInfo) .ToList(); // previous entries in EF are removed post migration. if (!existingSkins.Any()) { return; } var userSkinChoice = config.GetBindable <string>(OsuSetting.Skin); int.TryParse(userSkinChoice.Value, out int userSkinInt); switch (userSkinInt) { case EFSkinInfo.DEFAULT_SKIN: userSkinChoice.Value = SkinInfo.DEFAULT_SKIN.ToString(); break; case EFSkinInfo.CLASSIC_SKIN: userSkinChoice.Value = SkinInfo.CLASSIC_SKIN.ToString(); break; } using (var realm = realmContextFactory.CreateContext()) using (var transaction = realm.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)) { foreach (var skin in existingSkins) { var realmSkin = new SkinInfo { Name = skin.Name, Creator = skin.Creator, Hash = skin.Hash, Protected = false, InstantiationInfo = skin.InstantiationInfo, }; foreach (var file in skin.Files) { var realmFile = realm.Find <RealmFile>(file.FileInfo.Hash); if (realmFile == null) { realm.Add(realmFile = new RealmFile { Hash = file.FileInfo.Hash }); } realmSkin.Files.Add(new RealmNamedFileUsage(realmFile, file.Filename)); } realm.Add(realmSkin); if (skin.ID == userSkinInt) { userSkinChoice.Value = realmSkin.ID.ToString(); } } } db.Context.RemoveRange(existingSkins); // Intentionally don't clean up the files, so they don't get purged by EF. transaction.Commit(); } }