using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using SQLitePCL.pretty; namespace Emby.Server.Implementations.Data { /// /// Class SQLiteUserRepository /// public class SqliteUserRepository : BaseSqliteRepository, IUserRepository { private readonly IJsonSerializer _jsonSerializer; private readonly IMemoryStreamFactory _memoryStreamProvider; public SqliteUserRepository(ILogger logger, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IMemoryStreamFactory memoryStreamProvider) : base(logger) { _jsonSerializer = jsonSerializer; _memoryStreamProvider = memoryStreamProvider; DbFilePath = Path.Combine(appPaths.DataPath, "users.db"); } /// /// Gets the name of the repository /// /// The name. public string Name { get { return "SQLite"; } } /// /// Opens the connection to the database /// /// Task. public void Initialize() { using (var connection = CreateConnection()) { RunDefaultInitialization(connection); 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)", "pragma shrink_memory" }; connection.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"); } cancellationToken.ThrowIfCancellationRequested(); var serialized = _jsonSerializer.SerializeToBytes(user, _memoryStreamProvider); cancellationToken.ThrowIfCancellationRequested(); using (WriteLock.Write()) { using (var connection = CreateConnection()) { connection.RunInTransaction(db => { using (var statement = db.PrepareStatement("replace into users (guid, data) values (@guid, @data)")) { statement.TryBind("@guid", user.Id.ToGuidParamValue()); statement.TryBind("@data", serialized); statement.MoveNext(); } }, TransactionMode); } } } /// /// Retrieve all users from the database /// /// IEnumerable{User}. public IEnumerable RetrieveAllUsers() { var list = new List(); using (WriteLock.Read()) { using (var connection = CreateConnection(true)) { foreach (var row in connection.Query("select guid,data from users")) { var id = row[0].ReadGuid(); using (var stream = _memoryStreamProvider.CreateNew(row[1].ToBlob())) { stream.Position = 0; var user = _jsonSerializer.DeserializeFromStream(stream); user.Id = id; list.Add(user); } } } } return list; } /// /// Deletes the user. /// /// The user. /// The cancellation token. /// Task. /// user public async Task DeleteUser(User user, CancellationToken cancellationToken) { if (user == null) { throw new ArgumentNullException("user"); } cancellationToken.ThrowIfCancellationRequested(); using (WriteLock.Write()) { using (var connection = CreateConnection()) { connection.RunInTransaction(db => { using (var statement = db.PrepareStatement("delete from users where guid=@id")) { statement.TryBind("@id", user.Id.ToGuidParamValue()); statement.MoveNext(); } }, TransactionMode); } } } } }