using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Sqlite { /// /// Class SQLiteUserRepository /// public class SQLiteUserRepository : SqliteRepository, IUserRepository { /// /// The repository name /// public const string RepositoryName = "SQLite"; /// /// Gets the name of the repository /// /// The name. public string Name { get { return RepositoryName; } } /// /// Gets the json serializer. /// /// The json serializer. private readonly IJsonSerializer _jsonSerializer; /// /// The _app paths /// private readonly IApplicationPaths _appPaths; /// /// Gets a value indicating whether [enable delayed commands]. /// /// true if [enable delayed commands]; otherwise, false. protected override bool EnableDelayedCommands { get { return false; } } /// /// Initializes a new instance of the class. /// /// The app paths. /// The json serializer. /// The log manager. /// appPaths public SQLiteUserRepository(IApplicationPaths appPaths, IJsonSerializer jsonSerializer, ILogManager logManager) : base(logManager) { if (appPaths == null) { throw new ArgumentNullException("appPaths"); } if (jsonSerializer == null) { throw new ArgumentNullException("jsonSerializer"); } _appPaths = appPaths; _jsonSerializer = jsonSerializer; } /// /// Opens the connection to the database /// /// Task. public async Task Initialize() { var dbFile = Path.Combine(_appPaths.DataPath, "users.db"); await ConnectToDB(dbFile).ConfigureAwait(false); string[] queries = { "create table if not exists users (guid GUID primary key, data BLOB)", "create index if not exists idx_users on users(guid)", "create table if not exists schema_version (table_name primary key, version)", //pragmas "pragma temp_store = memory" }; RunQueries(queries); } /// /// Save a user in the repo /// /// The user. /// The cancellation token. /// Task. /// user public async Task SaveUser(User user, CancellationToken cancellationToken) { if (user == null) { throw new ArgumentNullException("user"); } if (cancellationToken == null) { throw new ArgumentNullException("cancellationToken"); } cancellationToken.ThrowIfCancellationRequested(); var serialized = _jsonSerializer.SerializeToBytes(user); cancellationToken.ThrowIfCancellationRequested(); var cmd = connection.CreateCommand(); cmd.CommandText = "replace into users (guid, data) values (@1, @2)"; cmd.AddParam("@1", user.Id); cmd.AddParam("@2", serialized); using (var tran = connection.BeginTransaction()) { try { cmd.Transaction = tran; await cmd.ExecuteNonQueryAsync(cancellationToken); tran.Commit(); } catch (OperationCanceledException) { tran.Rollback(); } catch (Exception e) { Logger.ErrorException("Failed to commit transaction.", e); tran.Rollback(); } } } /// /// Retrieve all users from the database /// /// IEnumerable{User}. public IEnumerable RetrieveAllUsers() { var cmd = connection.CreateCommand(); cmd.CommandText = "select data from users"; using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { while (reader.Read()) { using (var stream = GetStream(reader, 0)) { var user = _jsonSerializer.DeserializeFromStream(stream); yield return user; } } } } /// /// Deletes the user. /// /// The user. /// The cancellation token. /// Task. /// user public Task DeleteUser(User user, CancellationToken cancellationToken) { if (user == null) { throw new ArgumentNullException("user"); } if (cancellationToken == null) { throw new ArgumentNullException("cancellationToken"); } return Task.Run(() => { cancellationToken.ThrowIfCancellationRequested(); var cmd = connection.CreateCommand(); cmd.CommandText = "delete from users where guid=@guid"; var guidParam = cmd.Parameters.Add("@guid", DbType.Guid); guidParam.Value = user.Id; return ExecuteCommand(cmd); }); } } }