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.cs137
1 files changed, 123 insertions, 14 deletions
diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
index 8febe83b2..6c1a96813 100644
--- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
+++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
@@ -4,13 +4,15 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Logging;
using SQLitePCL.pretty;
+using System.Linq;
+using SQLitePCL;
namespace Emby.Server.Implementations.Data
{
public abstract class BaseSqliteRepository : IDisposable
{
protected string DbFilePath { get; set; }
- protected SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1);
+ protected ReaderWriterLockSlim WriteLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
protected ILogger Logger { get; private set; }
protected BaseSqliteRepository(ILogger logger)
@@ -23,12 +25,20 @@ namespace Emby.Server.Implementations.Data
get { return true; }
}
- protected virtual SQLiteDatabaseConnection CreateConnection(bool isReadOnly = false)
+ static BaseSqliteRepository()
{
SQLite3.EnableSharedCache = false;
+ int rc = raw.sqlite3_config(raw.SQLITE_CONFIG_MEMSTATUS, 0);
+ //CheckOk(rc);
+ }
+
+ protected virtual SQLiteDatabaseConnection CreateConnection(bool isReadOnly = false)
+ {
ConnectionFlags connectionFlags;
+ //isReadOnly = false;
+
if (isReadOnly)
{
connectionFlags = ConnectionFlags.ReadOnly;
@@ -54,25 +64,67 @@ namespace Emby.Server.Implementations.Data
var db = SQLite3.Open(DbFilePath, connectionFlags, null);
- var queries = new[]
+ var queries = new List<string>
{
+ "pragma default_temp_store = memory",
"PRAGMA page_size=4096",
"PRAGMA journal_mode=WAL",
"PRAGMA temp_store=memory",
"PRAGMA synchronous=Normal",
//"PRAGMA cache size=-10000"
- };
+ };
+
+ var cacheSize = CacheSize;
+ if (cacheSize.HasValue)
+ {
+
+ }
+
+ if (EnableExclusiveMode)
+ {
+ queries.Add("PRAGMA locking_mode=EXCLUSIVE");
+ }
//foreach (var query in queries)
//{
// db.Execute(query);
//}
- db.ExecuteAll(string.Join(";", queries));
-
+ db.ExecuteAll(string.Join(";", queries.ToArray()));
+
return db;
}
+ protected virtual int? CacheSize
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ protected virtual bool EnableExclusiveMode
+ {
+ get { return false; }
+ }
+
+ internal static void CheckOk(int rc)
+ {
+ string msg = "";
+
+ if (raw.SQLITE_OK != rc)
+ {
+ throw CreateException((ErrorCode)rc, msg);
+ }
+ }
+
+ internal static Exception CreateException(ErrorCode rc, string msg)
+ {
+ var exp = new Exception(msg);
+
+ return exp;
+ }
+
private bool _disposed;
protected void CheckDisposed()
{
@@ -103,9 +155,10 @@ namespace Emby.Server.Implementations.Data
{
lock (_disposeLock)
{
- WriteLock.Wait();
-
- CloseConnection();
+ using (WriteLock.Write())
+ {
+ CloseConnection();
+ }
}
}
catch (Exception ex)
@@ -120,21 +173,30 @@ namespace Emby.Server.Implementations.Data
}
- protected void AddColumn(IDatabaseConnection connection, string table, string columnName, string type)
+ protected List<string> GetColumnNames(IDatabaseConnection connection, string table)
{
+ var list = new List<string>();
+
foreach (var row in connection.Query("PRAGMA table_info(" + table + ")"))
{
if (row[1].SQLiteType != SQLiteType.Null)
{
var name = row[1].ToString();
- if (string.Equals(name, columnName, StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
+ list.Add(name);
}
}
+ return list;
+ }
+
+ protected void AddColumn(IDatabaseConnection connection, string table, string columnName, string type, List<string> existingColumnNames)
+ {
+ if (existingColumnNames.Contains(columnName, StringComparer.OrdinalIgnoreCase))
+ {
+ return;
+ }
+
connection.ExecuteAll(string.Join(";", new string[]
{
"alter table " + table,
@@ -142,4 +204,51 @@ namespace Emby.Server.Implementations.Data
}));
}
}
+
+ public static class ReaderWriterLockSlimExtensions
+ {
+ private sealed class ReadLockToken : IDisposable
+ {
+ private ReaderWriterLockSlim _sync;
+ public ReadLockToken(ReaderWriterLockSlim sync)
+ {
+ _sync = sync;
+ sync.EnterReadLock();
+ }
+ public void Dispose()
+ {
+ if (_sync != null)
+ {
+ _sync.ExitReadLock();
+ _sync = null;
+ }
+ }
+ }
+ private sealed class WriteLockToken : IDisposable
+ {
+ private ReaderWriterLockSlim _sync;
+ public WriteLockToken(ReaderWriterLockSlim sync)
+ {
+ _sync = sync;
+ sync.EnterWriteLock();
+ }
+ public void Dispose()
+ {
+ if (_sync != null)
+ {
+ _sync.ExitWriteLock();
+ _sync = null;
+ }
+ }
+ }
+
+ public static IDisposable Read(this ReaderWriterLockSlim obj)
+ {
+ return new ReadLockToken(obj);
+ }
+ public static IDisposable Write(this ReaderWriterLockSlim obj)
+ {
+ return new WriteLockToken(obj);
+ }
+ }
}