diff options
Diffstat (limited to 'Emby.Server.Implementations/Data/BaseSqliteRepository.cs')
| -rw-r--r-- | Emby.Server.Implementations/Data/BaseSqliteRepository.cs | 137 |
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); + } + } } |
