1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-20 16:12:54 +08:00

Move SQLite connections out of database classes; make abstract Database.

This commit is contained in:
Dean Herbert 2017-04-17 14:37:52 +09:00
parent ce12cc20bd
commit 83b083ce64
No known key found for this signature in database
GPG Key ID: 46D71BF4958ABB49
8 changed files with 105 additions and 77 deletions

View File

@ -26,7 +26,7 @@ namespace osu.Desktop.VisualTests.Tests
if (db == null)
{
storage = new TestStorage(@"TestCasePlaySongSelect");
db = new BeatmapDatabase(storage);
db = new BeatmapDatabase(storage, storage.GetDatabase(@"client"));
var sets = new List<BeatmapSetInfo>();

View File

@ -4,7 +4,6 @@
using OpenTK.Graphics;
using osu.Game.Beatmaps.Timing;
using osu.Game.Database;
using osu.Game.Modes;
using osu.Game.Modes.Objects;
using System.Collections.Generic;

View File

@ -6,7 +6,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Modes;
using OpenTK;
using OpenTK.Graphics;

View File

@ -18,37 +18,19 @@ using SQLiteNetExtensions.Extensions;
namespace osu.Game.Database
{
public class BeatmapDatabase
public class BeatmapDatabase : Database
{
private SQLiteConnection connection { get; }
private readonly Storage storage;
public event Action<BeatmapSetInfo> BeatmapSetAdded;
public event Action<BeatmapSetInfo> BeatmapSetRemoved;
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
private BeatmapIPCChannel ipc;
public BeatmapDatabase(Storage storage, IIpcHost importHost = null)
public BeatmapDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null) : base(storage, connection)
{
this.storage = storage;
if (importHost != null)
ipc = new BeatmapIPCChannel(importHost, this);
if (connection == null)
{
try
{
connection = prepareConnection();
deletePending();
}
catch (Exception e)
{
Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database...");
storage.DeleteDatabase(@"beatmaps");
connection = prepareConnection();
}
}
}
private void deletePending()
@ -57,20 +39,20 @@ namespace osu.Game.Database
{
try
{
storage.Delete(b.Path);
Storage.Delete(b.Path);
GetChildren(b, true);
foreach (var i in b.Beatmaps)
{
if (i.Metadata != null) connection.Delete(i.Metadata);
if (i.Difficulty != null) connection.Delete(i.Difficulty);
if (i.Metadata != null) Connection.Delete(i.Metadata);
if (i.Difficulty != null) Connection.Delete(i.Difficulty);
connection.Delete(i);
Connection.Delete(i);
}
if (b.Metadata != null) connection.Delete(b.Metadata);
connection.Delete(b);
if (b.Metadata != null) Connection.Delete(b.Metadata);
Connection.Delete(b);
}
catch (Exception e)
{
@ -80,41 +62,31 @@ namespace osu.Game.Database
//this is required because sqlite migrations don't work, initially inserting nulls into this field.
//see https://github.com/praeclarum/sqlite-net/issues/326
connection.Query<BeatmapSetInfo>("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL");
Connection.Query<BeatmapSetInfo>("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL");
}
private SQLiteConnection prepareConnection()
protected override void Prepare()
{
var conn = storage.GetDatabase(@"beatmaps");
Connection.CreateTable<BeatmapMetadata>();
Connection.CreateTable<BeatmapDifficulty>();
Connection.CreateTable<BeatmapSetInfo>();
Connection.CreateTable<BeatmapInfo>();
try
{
conn.CreateTable<BeatmapMetadata>();
conn.CreateTable<BeatmapDifficulty>();
conn.CreateTable<BeatmapSetInfo>();
conn.CreateTable<BeatmapInfo>();
}
catch
{
conn.Close();
throw;
}
return conn;
deletePending();
}
public void Reset()
public override void Reset()
{
foreach (var setInfo in Query<BeatmapSetInfo>())
{
if (storage.Exists(setInfo.Path))
storage.Delete(setInfo.Path);
if (Storage.Exists(setInfo.Path))
Storage.Delete(setInfo.Path);
}
connection.DeleteAll<BeatmapMetadata>();
connection.DeleteAll<BeatmapDifficulty>();
connection.DeleteAll<BeatmapSetInfo>();
connection.DeleteAll<BeatmapInfo>();
Connection.DeleteAll<BeatmapMetadata>();
Connection.DeleteAll<BeatmapDifficulty>();
Connection.DeleteAll<BeatmapSetInfo>();
Connection.DeleteAll<BeatmapInfo>();
}
/// <summary>
@ -174,7 +146,7 @@ namespace osu.Game.Database
BeatmapMetadata metadata;
using (var reader = ArchiveReader.GetReader(storage, path))
using (var reader = ArchiveReader.GetReader(Storage, path))
{
using (var stream = new StreamReader(reader.GetStream(reader.BeatmapFilenames[0])))
metadata = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata;
@ -182,18 +154,18 @@ namespace osu.Game.Database
if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader
{
using (var input = storage.GetStream(path))
using (var input = Storage.GetStream(path))
{
hash = input.GetMd5Hash();
input.Seek(0, SeekOrigin.Begin);
path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash);
if (!storage.Exists(path))
using (var output = storage.GetStream(path, FileAccess.Write))
if (!Storage.Exists(path))
using (var output = Storage.GetStream(path, FileAccess.Write))
input.CopyTo(output);
}
}
var existing = connection.Table<BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash);
var existing = Connection.Table<BeatmapSetInfo>().FirstOrDefault(b => b.Hash == hash);
if (existing != null)
{
@ -216,7 +188,7 @@ namespace osu.Game.Database
Metadata = metadata
};
using (var archive = ArchiveReader.GetReader(storage, path))
using (var archive = ArchiveReader.GetReader(Storage, path))
{
string[] mapNames = archive.BeatmapFilenames;
foreach (var name in mapNames)
@ -248,17 +220,17 @@ namespace osu.Game.Database
public void Import(IEnumerable<BeatmapSetInfo> beatmapSets)
{
lock (connection)
lock (Connection)
{
connection.BeginTransaction();
Connection.BeginTransaction();
foreach (var s in beatmapSets)
{
connection.InsertWithChildren(s, true);
Connection.InsertWithChildren(s, true);
BeatmapSetAdded?.Invoke(s);
}
connection.Commit();
Connection.Commit();
}
}
@ -275,7 +247,7 @@ namespace osu.Game.Database
if (string.IsNullOrEmpty(beatmapSet.Path))
return null;
return ArchiveReader.GetReader(storage, beatmapSet.Path);
return ArchiveReader.GetReader(Storage, beatmapSet.Path);
}
public BeatmapSetInfo GetBeatmapSet(int id)
@ -305,25 +277,25 @@ namespace osu.Game.Database
public TableQuery<T> Query<T>() where T : class
{
return connection.Table<T>();
return Connection.Table<T>();
}
public T GetWithChildren<T>(object id) where T : class
{
return connection.GetWithChildren<T>(id);
return Connection.GetWithChildren<T>(id);
}
public List<T> GetAllWithChildren<T>(Expression<Func<T, bool>> filter = null, bool recursive = true)
where T : class
{
return connection.GetAllWithChildren(filter, recursive);
return Connection.GetAllWithChildren(filter, recursive);
}
public T GetChildren<T>(T item, bool recursive = false)
{
if (item == null) return default(T);
connection.GetChildren(item, recursive);
Connection.GetChildren(item, recursive);
return item;
}
@ -339,11 +311,11 @@ namespace osu.Game.Database
if (validTypes.All(t => t != typeof(T)))
throw new ArgumentException("Must be a type managed by BeatmapDatabase", nameof(T));
if (cascade)
connection.UpdateWithChildren(record);
Connection.UpdateWithChildren(record);
else
connection.Update(record);
Connection.Update(record);
}
public bool Exists(BeatmapSetInfo beatmapSet) => storage.Exists(beatmapSet.Path);
public bool Exists(BeatmapSetInfo beatmapSet) => Storage.Exists(beatmapSet.Path);
}
}

View File

@ -0,0 +1,44 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Logging;
using osu.Framework.Platform;
using SQLite.Net;
namespace osu.Game.Database
{
public abstract class Database
{
protected SQLiteConnection Connection { get; }
protected Storage Storage { get; }
protected Database(Storage storage, SQLiteConnection connection)
{
Storage = storage;
Connection = connection;
try
{
Prepare();
}
catch (Exception e)
{
Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database...");
storage.DeleteDatabase(@"beatmaps");
Reset();
Prepare();
}
}
/// <summary>
/// Prepare this database for use.
/// </summary>
protected abstract void Prepare();
/// <summary>
/// Reset this database to a default state. Undo all changes to database and storage backings.
/// </summary>
public abstract void Reset();
}
}

View File

@ -10,10 +10,11 @@ using osu.Game.IPC;
using osu.Game.Modes;
using osu.Game.Modes.Scoring;
using SharpCompress.Compressors.LZMA;
using SQLite.Net;
namespace osu.Game.Database
{
public class ScoreDatabase
public class ScoreDatabase : Database
{
private readonly Storage storage;
private readonly BeatmapDatabase beatmaps;
@ -23,7 +24,7 @@ namespace osu.Game.Database
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
private ScoreIPCChannel ipc;
public ScoreDatabase(Storage storage, IIpcHost importHost = null, BeatmapDatabase beatmaps = null)
public ScoreDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null, BeatmapDatabase beatmaps = null) : base(storage, connection)
{
this.storage = storage;
this.beatmaps = beatmaps;
@ -39,7 +40,7 @@ namespace osu.Game.Database
using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename)))
using (SerializationReader sr = new SerializationReader(s))
{
var ruleset = RulesetCollection.GetRuleset((int)sr.ReadByte());
var ruleset = RulesetCollection.GetRuleset(sr.ReadByte());
score = ruleset.CreateScoreProcessor().CreateScore();
/* score.Pass = true;*/
@ -107,5 +108,13 @@ namespace osu.Game.Database
return score;
}
protected override void Prepare()
{
}
public override void Reset()
{
}
}
}

View File

@ -18,6 +18,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.Processing;
using osu.Game.Online.API;
using SQLite.Net;
namespace osu.Game
{
@ -80,8 +81,11 @@ namespace osu.Game
{
Dependencies.Cache(this);
Dependencies.Cache(LocalConfig);
Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, Host));
Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, Host, BeatmapDatabase));
SQLiteConnection connection = Host.Storage.GetDatabase(@"client");
Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, connection, Host));
Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, connection, Host, BeatmapDatabase));
Dependencies.Cache(new OsuColour());
//this completely overrides the framework default. will need to change once we make a proper FontStore.

View File

@ -78,6 +78,7 @@
<Compile Include="Beatmaps\Timing\TimeSignatures.cs" />
<Compile Include="Beatmaps\Timing\TimingInfo.cs" />
<Compile Include="Database\BeatmapMetrics.cs" />
<Compile Include="Database\Database.cs" />
<Compile Include="Database\ScoreDatabase.cs" />
<Compile Include="Graphics\Backgrounds\Triangles.cs" />
<Compile Include="Graphics\Cursor\CursorTrail.cs" />