| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 | 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 SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1);        protected readonly IDbConnector DbConnector;        protected ILogger Logger;        protected string DbFilePath { get; set; }        protected BaseSqliteRepository(ILogManager logManager, IDbConnector dbConnector)        {            DbConnector = dbConnector;            Logger = logManager.GetLogger(GetType().Name);        }        protected virtual bool EnableConnectionPooling        {            get { return true; }        }        protected virtual async Task<IDbConnection> CreateConnection(bool isReadOnly = false)        {            var connection = await DbConnector.Connect(DbFilePath, false, true).ConfigureAwait(false);            connection.RunQueries(new[]            {                "pragma temp_store = memory"            }, Logger);            return connection;        }        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();        /// <summary>        /// Releases unmanaged and - optionally - managed resources.        /// </summary>        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>        protected virtual void Dispose(bool dispose)        {            if (dispose)            {                try                {                    lock (_disposeLock)                    {                        WriteLock.Wait();                        CloseConnection();                    }                }                catch (Exception ex)                {                    Logger.ErrorException("Error disposing database", ex);                }            }        }        protected virtual void CloseConnection()        {        }    }}
 |