using MediaBrowser.Model.Logging; using System; using System.Data; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Persistence { public abstract class BaseSqliteRepository : IDisposable { protected readonly SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1); protected ILogger Logger; protected BaseSqliteRepository(ILogManager logManager) { Logger = logManager.GetLogger(GetType().Name); } private bool _disposed; protected void CheckDisposed() { if (_disposed) { throw new ObjectDisposedException(GetType().Name + " has been disposed and cannot be accessed."); } } public void Dispose() { _disposed = true; Dispose(true); GC.SuppressFinalize(this); } protected async Task Vacuum(IDbConnection connection) { CheckDisposed(); await WriteLock.WaitAsync().ConfigureAwait(false); try { using (var cmd = connection.CreateCommand()) { cmd.CommandText = "vacuum"; cmd.ExecuteNonQuery(); } } catch (Exception e) { Logger.ErrorException("Failed to vacuum:", e); throw; } finally { WriteLock.Release(); } } private readonly object _disposeLock = new object(); /// /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool dispose) { if (dispose) { try { lock (_disposeLock) { WriteLock.Wait(); CloseConnection(); } } catch (Exception ex) { Logger.ErrorException("Error disposing database", ex); } } } protected abstract void CloseConnection(); } }