aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/Data/BaseSqliteRepository.cs')
-rw-r--r--Emby.Server.Implementations/Data/BaseSqliteRepository.cs114
1 files changed, 54 insertions, 60 deletions
diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
index 29edddb3a..6a19ea373 100644
--- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
+++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@@ -27,98 +28,93 @@ namespace Emby.Server.Implementations.Data
internal static int ThreadSafeMode { get; set; }
+ protected virtual ConnectionFlags DefaultConnectionFlags => ConnectionFlags.SharedCached | ConnectionFlags.FullMutex;
+
+ private readonly SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1);
+
+ private SQLiteDatabaseConnection WriteConnection;
+
+ private readonly BlockingCollection<SQLiteDatabaseConnection> ReadConnectionPool = new BlockingCollection<SQLiteDatabaseConnection>();
+
static BaseSqliteRepository()
{
ThreadSafeMode = raw.sqlite3_threadsafe();
}
- private static bool _versionLogged;
-
private string _defaultWal;
- protected SQLiteDatabaseConnection CreateConnection(bool isReadOnly = false)
+ protected async Task CreateConnections()
{
- if (!_versionLogged)
- {
- _versionLogged = true;
- Logger.LogInformation("Sqlite version: " + SQLite3.Version);
- Logger.LogInformation("Sqlite compiler options: " + string.Join(",", SQLite3.CompilerOptions));
- }
-
- ConnectionFlags connectionFlags;
-
- if (isReadOnly)
- {
- //Logger.LogInformation("Opening read connection");
- //connectionFlags = ConnectionFlags.Create;
- connectionFlags = ConnectionFlags.ReadOnly;
- }
- else
- {
- //Logger.LogInformation("Opening write connection");
- connectionFlags = ConnectionFlags.Create;
- connectionFlags |= ConnectionFlags.ReadWrite;
- }
-
- connectionFlags |= ConnectionFlags.SharedCached;
- connectionFlags |= ConnectionFlags.FullMutex;
-
- var db = SQLite3.Open(DbFilePath, connectionFlags, null);
+ await WriteLock.WaitAsync().ConfigureAwait(false);
try
{
- if (string.IsNullOrWhiteSpace(_defaultWal))
+ if (WriteConnection == null)
{
- _defaultWal = db.Query("PRAGMA journal_mode").SelectScalarString().First();
-
- Logger.LogInformation("Default journal_mode for {0} is {1}", DbFilePath, _defaultWal);
+ WriteConnection = SQLite3.Open(
+ DbFilePath,
+ DefaultConnectionFlags | ConnectionFlags.Create | ConnectionFlags.ReadWrite,
+ null);
}
- var queries = new List<string>
+ if (string.IsNullOrWhiteSpace(_defaultWal))
{
- //"PRAGMA cache size=-10000"
- //"PRAGMA read_uncommitted = true",
- //"PRAGMA synchronous=Normal"
- };
+ _defaultWal = WriteConnection.Query("PRAGMA journal_mode").SelectScalarString().First();
- if (CacheSize.HasValue)
- {
- queries.Add("PRAGMA cache_size=" + CacheSize.Value.ToString(CultureInfo.InvariantCulture));
+ Logger.LogInformation("Default journal_mode for {0} is {1}", DbFilePath, _defaultWal);
}
if (EnableTempStoreMemory)
{
- queries.Add("PRAGMA temp_store = memory");
+ WriteConnection.Execute("PRAGMA temp_store = memory");
}
else
{
- queries.Add("PRAGMA temp_store = file");
- }
-
- foreach (var query in queries)
- {
- db.Execute(query);
+ WriteConnection.Execute("PRAGMA temp_store = file");
}
}
catch
{
- using (db)
- {
-
- }
throw;
}
+ finally
+ {
+ WriteLock.Release();
+ }
- return db;
+ // Add one reading connection for each thread
+ int threads = System.Environment.ProcessorCount;
+ for (int i = 0; i <= threads; i++)
+ {
+ ReadConnectionPool.Add(SQLite3.Open(DbFilePath, DefaultConnectionFlags | ConnectionFlags.ReadOnly, null));
+ }
}
- public IStatement PrepareStatement(SQLiteDatabaseConnection connection, string sql)
+ protected ManagedConnection GetConnection(bool isReadOnly = false)
+ {
+ if (isReadOnly)
+ {
+ return new ManagedConnection(ReadConnectionPool.Take(), ReadConnectionPool);
+ }
+ else
+ {
+ if (WriteConnection == null)
+ {
+ throw new InvalidOperationException("Can't access the write connection at this time.");
+ }
+
+ WriteLock.Wait();
+ return new ManagedConnection(WriteConnection, WriteLock);
+ }
+ }
+
+ public IStatement PrepareStatement(ManagedConnection connection, string sql)
{
return connection.PrepareStatement(sql);
}
- public IStatement PrepareStatementSafe(SQLiteDatabaseConnection connection, string sql)
+ public IStatement PrepareStatementSafe(ManagedConnection connection, string sql)
{
return connection.PrepareStatement(sql);
}
@@ -143,7 +139,7 @@ namespace Emby.Server.Implementations.Data
return sql.Select(connection.PrepareStatement).ToList();
}
- protected bool TableExists(SQLiteDatabaseConnection connection, string name)
+ protected bool TableExists(ManagedConnection connection, string name)
{
return connection.RunInTransaction(db =>
{
@@ -163,7 +159,7 @@ namespace Emby.Server.Implementations.Data
}, ReadTransactionMode);
}
- protected void RunDefaultInitialization(SQLiteDatabaseConnection db)
+ protected void RunDefaultInitialization(ManagedConnection db)
{
var queries = new List<string>
{
@@ -192,9 +188,7 @@ namespace Emby.Server.Implementations.Data
Logger.LogInformation("PRAGMA synchronous=" + db.Query("PRAGMA synchronous").SelectScalarString().First());
}
- protected virtual bool EnableTempStoreMemory => false;
-
- protected virtual int? CacheSize => null;
+ protected virtual bool EnableTempStoreMemory => true;
private bool _disposed;
protected void CheckDisposed()