use individual connections

This commit is contained in:
Luke Pulverenti 2016-06-11 11:55:05 -04:00
parent 682edf5abd
commit 4c7f292ba8
12 changed files with 1196 additions and 1281 deletions

View File

@ -15,30 +15,20 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
public class SqliteNotificationsRepository : BaseSqliteRepository, INotificationsRepository
{
private IDbConnection _connection;
private readonly IServerApplicationPaths _appPaths;
public SqliteNotificationsRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector dbConnector) : base(logManager, dbConnector)
{
DbFilePath = Path.Combine(appPaths.DataPath, "notifications.db");
}
public event EventHandler<NotificationUpdateEventArgs> NotificationAdded;
public event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead;
public event EventHandler<NotificationUpdateEventArgs> NotificationUpdated;
private IDbCommand _replaceNotificationCommand;
private IDbCommand _markReadCommand;
private IDbCommand _markAllReadCommand;
public SqliteNotificationsRepository(ILogManager logManager, IServerApplicationPaths appPaths)
: base(logManager)
public async Task Initialize()
{
_appPaths = appPaths;
}
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "notifications.db");
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
using (var connection = await CreateConnection().ConfigureAwait(false))
{
string[] queries = {
"create table if not exists Notifications (Id GUID NOT NULL, UserId GUID NOT NULL, Date DATETIME NOT NULL, Name TEXT NOT NULL, Description TEXT, Url TEXT, Level TEXT NOT NULL, IsRead BOOLEAN NOT NULL, Category TEXT NOT NULL, RelatedId TEXT, PRIMARY KEY (Id, UserId))",
"create index if not exists idx_Notifications1 on Notifications(Id)",
@ -50,39 +40,8 @@ namespace MediaBrowser.Server.Implementations.Notifications
"pragma shrink_memory"
};
_connection.RunQueries(queries, Logger);
PrepareStatements();
}
private void PrepareStatements()
{
_replaceNotificationCommand = _connection.CreateCommand();
_replaceNotificationCommand.CommandText = "replace into Notifications (Id, UserId, Date, Name, Description, Url, Level, IsRead, Category, RelatedId) values (@Id, @UserId, @Date, @Name, @Description, @Url, @Level, @IsRead, @Category, @RelatedId)";
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@Id");
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@UserId");
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@Date");
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@Name");
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@Description");
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@Url");
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@Level");
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@IsRead");
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@Category");
_replaceNotificationCommand.Parameters.Add(_replaceNotificationCommand, "@RelatedId");
_markReadCommand = _connection.CreateCommand();
_markReadCommand.CommandText = "update Notifications set IsRead=@IsRead where Id=@Id and UserId=@UserId";
_markReadCommand.Parameters.Add(_replaceNotificationCommand, "@UserId");
_markReadCommand.Parameters.Add(_replaceNotificationCommand, "@IsRead");
_markReadCommand.Parameters.Add(_replaceNotificationCommand, "@Id");
_markAllReadCommand = _connection.CreateCommand();
_markAllReadCommand.CommandText = "update Notifications set IsRead=@IsRead where UserId=@UserId";
_markAllReadCommand.Parameters.Add(_replaceNotificationCommand, "@UserId");
_markAllReadCommand.Parameters.Add(_replaceNotificationCommand, "@IsRead");
connection.RunQueries(queries, Logger);
}
}
/// <summary>
@ -94,49 +53,52 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
var result = new NotificationResult();
using (var cmd = _connection.CreateCommand())
using (var connection = CreateConnection(true).Result)
{
var clauses = new List<string>();
if (query.IsRead.HasValue)
using (var cmd = connection.CreateCommand())
{
clauses.Add("IsRead=@IsRead");
cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = query.IsRead.Value;
}
var clauses = new List<string>();
clauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(query.UserId);
var whereClause = " where " + string.Join(" And ", clauses.ToArray());
cmd.CommandText = string.Format("select count(Id) from Notifications{0};select Id,UserId,Date,Name,Description,Url,Level,IsRead,Category,RelatedId from Notifications{0} order by IsRead asc, Date desc", whereClause);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
if (reader.Read())
if (query.IsRead.HasValue)
{
result.TotalRecordCount = reader.GetInt32(0);
clauses.Add("IsRead=@IsRead");
cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = query.IsRead.Value;
}
if (reader.NextResult())
clauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(query.UserId);
var whereClause = " where " + string.Join(" And ", clauses.ToArray());
cmd.CommandText = string.Format("select count(Id) from Notifications{0};select Id,UserId,Date,Name,Description,Url,Level,IsRead,Category,RelatedId from Notifications{0} order by IsRead asc, Date desc", whereClause);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
var notifications = GetNotifications(reader);
if (query.StartIndex.HasValue)
if (reader.Read())
{
notifications = notifications.Skip(query.StartIndex.Value);
result.TotalRecordCount = reader.GetInt32(0);
}
if (query.Limit.HasValue)
if (reader.NextResult())
{
notifications = notifications.Take(query.Limit.Value);
}
var notifications = GetNotifications(reader);
result.Notifications = notifications.ToArray();
if (query.StartIndex.HasValue)
{
notifications = notifications.Skip(query.StartIndex.Value);
}
if (query.Limit.HasValue)
{
notifications = notifications.Take(query.Limit.Value);
}
result.Notifications = notifications.ToArray();
}
}
}
return result;
return result;
}
}
}
@ -144,31 +106,34 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
var result = new NotificationsSummary();
using (var cmd = _connection.CreateCommand())
using (var connection = CreateConnection(true).Result)
{
cmd.CommandText = "select Level from Notifications where UserId=@UserId and IsRead=@IsRead";
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(userId);
cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = false;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
using (var cmd = connection.CreateCommand())
{
var levels = new List<NotificationLevel>();
cmd.CommandText = "select Level from Notifications where UserId=@UserId and IsRead=@IsRead";
while (reader.Read())
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(userId);
cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = false;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
levels.Add(GetLevel(reader, 0));
var levels = new List<NotificationLevel>();
while (reader.Read())
{
levels.Add(GetLevel(reader, 0));
}
result.UnreadCount = levels.Count;
if (levels.Count > 0)
{
result.MaxUnreadNotificationLevel = levels.Max();
}
}
result.UnreadCount = levels.Count;
if (levels.Count > 0)
{
result.MaxUnreadNotificationLevel = levels.Max();
}
return result;
}
return result;
}
}
@ -179,10 +144,14 @@ namespace MediaBrowser.Server.Implementations.Notifications
/// <returns>IEnumerable{Notification}.</returns>
private IEnumerable<Notification> GetNotifications(IDataReader reader)
{
var list = new List<Notification>();
while (reader.Read())
{
yield return GetNotification(reader);
list.Add(GetNotification(reader));
}
return list;
}
private Notification GetNotification(IDataReader reader)
@ -273,59 +242,74 @@ namespace MediaBrowser.Server.Implementations.Notifications
cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
using (var connection = await CreateConnection().ConfigureAwait(false))
{
transaction = _connection.BeginTransaction();
_replaceNotificationCommand.GetParameter(0).Value = new Guid(notification.Id);
_replaceNotificationCommand.GetParameter(1).Value = new Guid(notification.UserId);
_replaceNotificationCommand.GetParameter(2).Value = notification.Date.ToUniversalTime();
_replaceNotificationCommand.GetParameter(3).Value = notification.Name;
_replaceNotificationCommand.GetParameter(4).Value = notification.Description;
_replaceNotificationCommand.GetParameter(5).Value = notification.Url;
_replaceNotificationCommand.GetParameter(6).Value = notification.Level.ToString();
_replaceNotificationCommand.GetParameter(7).Value = notification.IsRead;
_replaceNotificationCommand.GetParameter(8).Value = string.Empty;
_replaceNotificationCommand.GetParameter(9).Value = string.Empty;
_replaceNotificationCommand.Transaction = transaction;
_replaceNotificationCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
using (var replaceNotificationCommand = connection.CreateCommand())
{
transaction.Rollback();
replaceNotificationCommand.CommandText = "replace into Notifications (Id, UserId, Date, Name, Description, Url, Level, IsRead, Category, RelatedId) values (@Id, @UserId, @Date, @Name, @Description, @Url, @Level, @IsRead, @Category, @RelatedId)";
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Id");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@UserId");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Date");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Name");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Description");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Url");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Level");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@IsRead");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@Category");
replaceNotificationCommand.Parameters.Add(replaceNotificationCommand, "@RelatedId");
IDbTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
replaceNotificationCommand.GetParameter(0).Value = new Guid(notification.Id);
replaceNotificationCommand.GetParameter(1).Value = new Guid(notification.UserId);
replaceNotificationCommand.GetParameter(2).Value = notification.Date.ToUniversalTime();
replaceNotificationCommand.GetParameter(3).Value = notification.Name;
replaceNotificationCommand.GetParameter(4).Value = notification.Description;
replaceNotificationCommand.GetParameter(5).Value = notification.Url;
replaceNotificationCommand.GetParameter(6).Value = notification.Level.ToString();
replaceNotificationCommand.GetParameter(7).Value = notification.IsRead;
replaceNotificationCommand.GetParameter(8).Value = string.Empty;
replaceNotificationCommand.GetParameter(9).Value = string.Empty;
replaceNotificationCommand.Transaction = transaction;
replaceNotificationCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save notification:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save notification:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
WriteLock.Release();
}
}
@ -366,51 +350,58 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
using (var connection = await CreateConnection().ConfigureAwait(false))
{
cancellationToken.ThrowIfCancellationRequested();
transaction = _connection.BeginTransaction();
_markAllReadCommand.GetParameter(0).Value = new Guid(userId);
_markAllReadCommand.GetParameter(1).Value = isRead;
_markAllReadCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
using (var markAllReadCommand = connection.CreateCommand())
{
transaction.Rollback();
markAllReadCommand.CommandText = "update Notifications set IsRead=@IsRead where UserId=@UserId";
markAllReadCommand.Parameters.Add(markAllReadCommand, "@UserId");
markAllReadCommand.Parameters.Add(markAllReadCommand, "@IsRead");
IDbTransaction transaction = null;
try
{
cancellationToken.ThrowIfCancellationRequested();
transaction = connection.BeginTransaction();
markAllReadCommand.GetParameter(0).Value = new Guid(userId);
markAllReadCommand.GetParameter(1).Value = isRead;
markAllReadCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save notification:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save notification:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
WriteLock.Release();
}
}
@ -418,72 +409,66 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
using (var connection = await CreateConnection().ConfigureAwait(false))
{
cancellationToken.ThrowIfCancellationRequested();
transaction = _connection.BeginTransaction();
_markReadCommand.GetParameter(0).Value = new Guid(userId);
_markReadCommand.GetParameter(1).Value = isRead;
foreach (var id in notificationIdList)
using (var markReadCommand = connection.CreateCommand())
{
_markReadCommand.GetParameter(2).Value = id;
markReadCommand.CommandText = "update Notifications set IsRead=@IsRead where Id=@Id and UserId=@UserId";
_markReadCommand.Transaction = transaction;
markReadCommand.Parameters.Add(markReadCommand, "@UserId");
markReadCommand.Parameters.Add(markReadCommand, "@IsRead");
markReadCommand.Parameters.Add(markReadCommand, "@Id");
_markReadCommand.ExecuteNonQuery();
IDbTransaction transaction = null;
try
{
cancellationToken.ThrowIfCancellationRequested();
transaction = connection.BeginTransaction();
markReadCommand.GetParameter(0).Value = new Guid(userId);
markReadCommand.GetParameter(1).Value = isRead;
foreach (var id in notificationIdList)
{
markReadCommand.GetParameter(2).Value = id;
markReadCommand.Transaction = transaction;
markReadCommand.ExecuteNonQuery();
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save notification:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save notification:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
WriteLock.Release();
}
}
protected override void CloseConnection()
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
}
}

View File

@ -9,13 +9,22 @@ namespace MediaBrowser.Server.Implementations.Persistence
public abstract class BaseSqliteRepository : IDisposable
{
protected readonly SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1);
protected readonly IDbConnector DbConnector;
protected ILogger Logger;
protected BaseSqliteRepository(ILogManager logManager)
protected string DbFilePath { get; set; }
protected BaseSqliteRepository(ILogManager logManager, IDbConnector dbConnector)
{
DbConnector = dbConnector;
Logger = logManager.GetLogger(GetType().Name);
}
protected Task<IDbConnection> CreateConnection(bool isReadOnly = false)
{
return DbConnector.Connect(DbFilePath, false, true);
}
private bool _disposed;
protected void CheckDisposed()
{
@ -84,6 +93,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
protected abstract void CloseConnection();
protected virtual void CloseConnection()
{
}
}
}

View File

@ -5,6 +5,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
public interface IDbConnector
{
Task<IDbConnection> Connect(string dbPath, int? cacheSize = null);
Task<IDbConnection> Connect(string dbPath, bool isReadOnly, bool enablePooling = false, int? cacheSize = null);
}
}

View File

@ -18,12 +18,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary>
public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository
{
private IDbConnection _connection;
public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths) : base(logManager)
public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector)
: base(logManager, dbConnector)
{
_jsonSerializer = jsonSerializer;
_appPaths = appPaths;
DbFilePath = Path.Combine(appPaths.DataPath, "displaypreferences.db");
}
/// <summary>
@ -43,22 +42,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary>
private readonly IJsonSerializer _jsonSerializer;
/// <summary>
/// The _app paths
/// </summary>
private readonly IApplicationPaths _appPaths;
/// <summary>
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize(IDbConnector dbConnector)
public async Task Initialize()
{
var dbFile = Path.Combine(_appPaths.DataPath, "displaypreferences.db");
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
using (var connection = await CreateConnection().ConfigureAwait(false))
{
string[] queries = {
"create table if not exists userdisplaypreferences (id GUID, userId GUID, client text, data BLOB)",
"create unique index if not exists userdisplaypreferencesindex on userdisplaypreferences (id, userId, client)",
@ -69,7 +61,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"pragma shrink_memory"
};
_connection.RunQueries(queries, Logger);
connection.RunQueries(queries, Logger);
}
}
/// <summary>
@ -96,58 +89,57 @@ namespace MediaBrowser.Server.Implementations.Persistence
var serialized = _jsonSerializer.SerializeToBytes(displayPreferences);
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
using (var connection = await CreateConnection().ConfigureAwait(false))
{
transaction = _connection.BeginTransaction();
IDbTransaction transaction = null;
using (var cmd = _connection.CreateCommand())
try
{
cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)";
transaction = connection.BeginTransaction();
cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = new Guid(displayPreferences.Id);
cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@3", DbType.String).Value = client;
cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized;
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)";
cmd.Transaction = transaction;
cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = new Guid(displayPreferences.Id);
cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@3", DbType.String).Value = client;
cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized;
cmd.ExecuteNonQuery();
cmd.Transaction = transaction;
cmd.ExecuteNonQuery();
}
transaction.Commit();
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
catch (OperationCanceledException)
{
transaction.Rollback();
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save display preferences:", e);
if (transaction != null)
catch (Exception e)
{
transaction.Rollback();
}
Logger.ErrorException("Failed to save display preferences:", e);
throw;
}
finally
{
if (transaction != null)
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
transaction.Dispose();
if (transaction != null)
{
transaction.Dispose();
}
}
WriteLock.Release();
}
}
@ -168,64 +160,63 @@ namespace MediaBrowser.Server.Implementations.Persistence
cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
using (var connection = await CreateConnection().ConfigureAwait(false))
{
transaction = _connection.BeginTransaction();
IDbTransaction transaction = null;
foreach (var displayPreference in displayPreferences)
try
{
transaction = connection.BeginTransaction();
var serialized = _jsonSerializer.SerializeToBytes(displayPreference);
using (var cmd = _connection.CreateCommand())
foreach (var displayPreference in displayPreferences)
{
cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)";
cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = new Guid(displayPreference.Id);
cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@3", DbType.String).Value = displayPreference.Client;
cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized;
var serialized = _jsonSerializer.SerializeToBytes(displayPreference);
cmd.Transaction = transaction;
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)";
cmd.ExecuteNonQuery();
cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = new Guid(displayPreference.Id);
cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@3", DbType.String).Value = displayPreference.Client;
cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized;
cmd.Transaction = transaction;
cmd.ExecuteNonQuery();
}
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save display preferences:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save display preferences:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
WriteLock.Release();
}
}
@ -246,28 +237,33 @@ namespace MediaBrowser.Server.Implementations.Persistence
var guidId = displayPreferencesId.GetMD5();
var cmd = _connection.CreateCommand();
cmd.CommandText = "select data from userdisplaypreferences where id = @id and userId=@userId and client=@client";
cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = guidId;
cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@client", DbType.String).Value = client;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
using (var connection = CreateConnection(true).Result)
{
if (reader.Read())
using (var cmd = connection.CreateCommand())
{
using (var stream = reader.GetMemoryStream(0))
cmd.CommandText = "select data from userdisplaypreferences where id = @id and userId=@userId and client=@client";
cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = guidId;
cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@client", DbType.String).Value = client;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
return _jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream);
if (reader.Read())
{
using (var stream = reader.GetMemoryStream(0))
{
return _jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream);
}
}
}
return new DisplayPreferences
{
Id = guidId.ToString("N")
};
}
}
return new DisplayPreferences
{
Id = guidId.ToString("N")
};
}
/// <summary>
@ -278,36 +274,30 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <exception cref="System.ArgumentNullException">item</exception>
public IEnumerable<DisplayPreferences> GetAllDisplayPreferences(Guid userId)
{
var list = new List<DisplayPreferences>();
var cmd = _connection.CreateCommand();
cmd.CommandText = "select data from userdisplaypreferences where userId=@userId";
cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
using (var connection = CreateConnection(true).Result)
{
while (reader.Read())
using (var cmd = connection.CreateCommand())
{
using (var stream = reader.GetMemoryStream(0))
cmd.CommandText = "select data from userdisplaypreferences where userId=@userId";
cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
yield return _jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream);
while (reader.Read())
{
using (var stream = reader.GetMemoryStream(0))
{
list.Add(_jsonSerializer.DeserializeFromStream<DisplayPreferences>(stream));
}
}
}
}
}
}
protected override void CloseConnection()
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
return list;
}
public Task SaveDisplayPreferences(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken)

View File

@ -19,11 +19,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <summary>
/// Connects to db.
/// </summary>
/// <param name="dbPath">The db path.</param>
/// <param name="logger">The logger.</param>
/// <returns>Task{IDbConnection}.</returns>
/// <exception cref="System.ArgumentNullException">dbPath</exception>
public static async Task<IDbConnection> ConnectToDb(string dbPath, int? cacheSize, ILogger logger)
public static async Task<IDbConnection> ConnectToDb(string dbPath, bool isReadOnly, bool enablePooling, int? cacheSize, ILogger logger)
{
if (string.IsNullOrEmpty(dbPath))
{
@ -38,7 +34,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
CacheSize = cacheSize ?? 2000,
SyncMode = SynchronizationModes.Normal,
DataSource = dbPath,
JournalMode = SQLiteJournalModeEnum.Wal
JournalMode = SQLiteJournalModeEnum.Wal,
Pooling = enablePooling,
ReadOnly = isReadOnly
};
var connection = new SQLiteConnection(connectionstr.ConnectionString);
@ -47,15 +45,5 @@ namespace MediaBrowser.Server.Implementations.Persistence
return connection;
}
public static void BindFunction(this SQLiteConnection connection, SQLiteFunction function)
{
var attributes = function.GetType().GetCustomAttributes(typeof(SQLiteFunctionAttribute), true).Cast<SQLiteFunctionAttribute>().ToArray();
if (attributes.Length == 0)
{
throw new InvalidOperationException("SQLiteFunction doesn't have SQLiteFunctionAttribute");
}
connection.BindFunction(attributes[0], function);
}
}
}

View File

@ -26,7 +26,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _deleteResultCommand;
private IDbCommand _deleteAllCommand;
public SqliteFileOrganizationRepository(ILogManager logManager, IServerApplicationPaths appPaths) : base(logManager)
public SqliteFileOrganizationRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector) : base(logManager, connector)
{
_appPaths = appPaths;
}
@ -39,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var dbFile = Path.Combine(_appPaths.DataPath, "fileorganization.db");
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile, false).ConfigureAwait(false);
string[] queries = {

View File

@ -99,8 +99,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
/// </summary>
public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager)
: base(logManager)
public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager, IDbConnector connector)
: base(logManager, connector)
{
if (config == null)
{
@ -127,7 +127,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var dbFile = Path.Combine(_config.ApplicationPaths.DataPath, "library.db");
_connection = await dbConnector.Connect(dbFile, 6000).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile, false, false, 6000).ConfigureAwait(false);
var createMediaStreamsTableCommand
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";

View File

@ -18,7 +18,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbConnection _connection;
private readonly IApplicationPaths _appPaths;
public SqliteUserDataRepository(ILogManager logManager, IApplicationPaths appPaths) : base(logManager)
public SqliteUserDataRepository(ILogManager logManager, IApplicationPaths appPaths, IDbConnector connector) : base(logManager, connector)
{
_appPaths = appPaths;
}
@ -43,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
var dbFile = Path.Combine(_appPaths.DataPath, "userdata_v2.db");
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
_connection = await dbConnector.Connect(dbFile, false).ConfigureAwait(false);
string[] queries = {

View File

@ -17,14 +17,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary>
public class SqliteUserRepository : BaseSqliteRepository, IUserRepository
{
private IDbConnection _connection;
private readonly IServerApplicationPaths _appPaths;
private readonly IJsonSerializer _jsonSerializer;
public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer) : base(logManager)
public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer, IDbConnector dbConnector) : base(logManager, dbConnector)
{
_appPaths = appPaths;
_jsonSerializer = jsonSerializer;
DbFilePath = Path.Combine(appPaths.DataPath, "users.db");
}
/// <summary>
@ -43,13 +42,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize(IDbConnector dbConnector)
public async Task Initialize()
{
var dbFile = Path.Combine(_appPaths.DataPath, "users.db");
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
using (var connection = await CreateConnection().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)",
@ -61,7 +58,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"pragma shrink_memory"
};
_connection.RunQueries(queries, Logger);
connection.RunQueries(queries, Logger);
}
}
/// <summary>
@ -84,55 +82,54 @@ namespace MediaBrowser.Server.Implementations.Persistence
cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
using (var connection = await CreateConnection().ConfigureAwait(false))
{
transaction = _connection.BeginTransaction();
IDbTransaction transaction = null;
using (var cmd = _connection.CreateCommand())
try
{
cmd.CommandText = "replace into users (guid, data) values (@1, @2)";
cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = user.Id;
cmd.Parameters.Add(cmd, "@2", DbType.Binary).Value = serialized;
transaction = connection.BeginTransaction();
cmd.Transaction = transaction;
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "replace into users (guid, data) values (@1, @2)";
cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = user.Id;
cmd.Parameters.Add(cmd, "@2", DbType.Binary).Value = serialized;
cmd.ExecuteNonQuery();
cmd.Transaction = transaction;
cmd.ExecuteNonQuery();
}
transaction.Commit();
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
catch (OperationCanceledException)
{
transaction.Rollback();
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save user:", e);
if (transaction != null)
catch (Exception e)
{
transaction.Rollback();
}
Logger.ErrorException("Failed to save user:", e);
throw;
}
finally
{
if (transaction != null)
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
transaction.Dispose();
if (transaction != null)
{
transaction.Dispose();
}
}
WriteLock.Release();
}
}
@ -142,25 +139,32 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <returns>IEnumerable{User}.</returns>
public IEnumerable<User> RetrieveAllUsers()
{
using (var cmd = _connection.CreateCommand())
var list = new List<User>();
using (var connection = CreateConnection(true).Result)
{
cmd.CommandText = "select guid,data from users";
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
using (var cmd = connection.CreateCommand())
{
while (reader.Read())
{
var id = reader.GetGuid(0);
cmd.CommandText = "select guid,data from users";
using (var stream = reader.GetMemoryStream(1))
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
var user = _jsonSerializer.DeserializeFromStream<User>(stream);
user.Id = id;
yield return user;
var id = reader.GetGuid(0);
using (var stream = reader.GetMemoryStream(1))
{
var user = _jsonSerializer.DeserializeFromStream<User>(stream);
user.Id = id;
list.Add(user);
}
}
}
}
}
return list;
}
/// <summary>
@ -179,69 +183,54 @@ namespace MediaBrowser.Server.Implementations.Persistence
cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
using (var connection = await CreateConnection().ConfigureAwait(false))
{
transaction = _connection.BeginTransaction();
IDbTransaction transaction = null;
using (var cmd = _connection.CreateCommand())
try
{
cmd.CommandText = "delete from users where guid=@guid";
transaction = connection.BeginTransaction();
cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = user.Id;
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "delete from users where guid=@guid";
cmd.Transaction = transaction;
cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = user.Id;
cmd.ExecuteNonQuery();
cmd.Transaction = transaction;
cmd.ExecuteNonQuery();
}
transaction.Commit();
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
catch (OperationCanceledException)
{
transaction.Rollback();
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to delete user:", e);
if (transaction != null)
catch (Exception e)
{
transaction.Rollback();
}
Logger.ErrorException("Failed to delete user:", e);
throw;
}
finally
{
if (transaction != null)
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
transaction.Dispose();
if (transaction != null)
{
transaction.Dispose();
}
}
WriteLock.Release();
}
}
protected override void CloseConnection()
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
}
}

View File

@ -15,25 +15,21 @@ namespace MediaBrowser.Server.Implementations.Security
{
public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository
{
private IDbConnection _connection;
private readonly IServerApplicationPaths _appPaths;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private IDbCommand _saveInfoCommand;
public AuthenticationRepository(ILogManager logManager, IServerApplicationPaths appPaths)
: base(logManager)
public AuthenticationRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector)
: base(logManager, connector)
{
_appPaths = appPaths;
DbFilePath = Path.Combine(appPaths.DataPath, "authentication.db");
}
public async Task Initialize(IDbConnector dbConnector)
public async Task Initialize()
{
var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db");
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
using (var connection = await CreateConnection().ConfigureAwait(false))
{
string[] queries = {
"create table if not exists AccessTokens (Id GUID PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT, AppName TEXT, AppVersion TEXT, DeviceName TEXT, UserId TEXT, IsActive BIT, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)",
"create index if not exists idx_AccessTokens on AccessTokens(Id)",
@ -44,28 +40,10 @@ namespace MediaBrowser.Server.Implementations.Security
"pragma shrink_memory"
};
_connection.RunQueries(queries, Logger);
connection.RunQueries(queries, Logger);
_connection.AddColumn(Logger, "AccessTokens", "AppVersion", "TEXT");
PrepareStatements();
}
private void PrepareStatements()
{
_saveInfoCommand = _connection.CreateCommand();
_saveInfoCommand.CommandText = "replace into AccessTokens (Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)";
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@Id");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AccessToken");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceId");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AppName");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AppVersion");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceName");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@UserId");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@IsActive");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateCreated");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateRevoked");
connection.AddColumn(Logger, "AccessTokens", "AppVersion", "TEXT");
}
}
public Task Create(AuthenticationInfo info, CancellationToken cancellationToken)
@ -84,61 +62,76 @@ namespace MediaBrowser.Server.Implementations.Security
cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
using (var connection = await CreateConnection().ConfigureAwait(false))
{
transaction = _connection.BeginTransaction();
var index = 0;
_saveInfoCommand.GetParameter(index++).Value = new Guid(info.Id);
_saveInfoCommand.GetParameter(index++).Value = info.AccessToken;
_saveInfoCommand.GetParameter(index++).Value = info.DeviceId;
_saveInfoCommand.GetParameter(index++).Value = info.AppName;
_saveInfoCommand.GetParameter(index++).Value = info.AppVersion;
_saveInfoCommand.GetParameter(index++).Value = info.DeviceName;
_saveInfoCommand.GetParameter(index++).Value = info.UserId;
_saveInfoCommand.GetParameter(index++).Value = info.IsActive;
_saveInfoCommand.GetParameter(index++).Value = info.DateCreated;
_saveInfoCommand.GetParameter(index++).Value = info.DateRevoked;
_saveInfoCommand.Transaction = transaction;
_saveInfoCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
using (var saveInfoCommand = connection.CreateCommand())
{
transaction.Rollback();
saveInfoCommand.CommandText = "replace into AccessTokens (Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)";
saveInfoCommand.Parameters.Add(saveInfoCommand, "@Id");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@AccessToken");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@DeviceId");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@AppName");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@AppVersion");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@DeviceName");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@UserId");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@IsActive");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@DateCreated");
saveInfoCommand.Parameters.Add(saveInfoCommand, "@DateRevoked");
IDbTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
var index = 0;
saveInfoCommand.GetParameter(index++).Value = new Guid(info.Id);
saveInfoCommand.GetParameter(index++).Value = info.AccessToken;
saveInfoCommand.GetParameter(index++).Value = info.DeviceId;
saveInfoCommand.GetParameter(index++).Value = info.AppName;
saveInfoCommand.GetParameter(index++).Value = info.AppVersion;
saveInfoCommand.GetParameter(index++).Value = info.DeviceName;
saveInfoCommand.GetParameter(index++).Value = info.UserId;
saveInfoCommand.GetParameter(index++).Value = info.IsActive;
saveInfoCommand.GetParameter(index++).Value = info.DateCreated;
saveInfoCommand.GetParameter(index++).Value = info.DateRevoked;
saveInfoCommand.Transaction = transaction;
saveInfoCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save record:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save record:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
WriteLock.Release();
}
}
@ -151,101 +144,104 @@ namespace MediaBrowser.Server.Implementations.Security
throw new ArgumentNullException("query");
}
using (var cmd = _connection.CreateCommand())
using (var connection = CreateConnection(true).Result)
{
cmd.CommandText = BaseSelectText;
var whereClauses = new List<string>();
var startIndex = query.StartIndex ?? 0;
if (!string.IsNullOrWhiteSpace(query.AccessToken))
using (var cmd = connection.CreateCommand())
{
whereClauses.Add("AccessToken=@AccessToken");
cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken;
}
cmd.CommandText = BaseSelectText;
if (!string.IsNullOrWhiteSpace(query.UserId))
{
whereClauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId;
}
var whereClauses = new List<string>();
if (!string.IsNullOrWhiteSpace(query.DeviceId))
{
whereClauses.Add("DeviceId=@DeviceId");
cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId;
}
var startIndex = query.StartIndex ?? 0;
if (query.IsActive.HasValue)
{
whereClauses.Add("IsActive=@IsActive");
cmd.Parameters.Add(cmd, "@IsActive", DbType.Boolean).Value = query.IsActive.Value;
}
if (query.HasUser.HasValue)
{
if (query.HasUser.Value)
if (!string.IsNullOrWhiteSpace(query.AccessToken))
{
whereClauses.Add("UserId not null");
whereClauses.Add("AccessToken=@AccessToken");
cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken;
}
else
if (!string.IsNullOrWhiteSpace(query.UserId))
{
whereClauses.Add("UserId is null");
whereClauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId;
}
}
var whereTextWithoutPaging = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
if (!string.IsNullOrWhiteSpace(query.DeviceId))
{
whereClauses.Add("DeviceId=@DeviceId");
cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId;
}
if (startIndex > 0)
{
var pagingWhereText = whereClauses.Count == 0 ?
if (query.IsActive.HasValue)
{
whereClauses.Add("IsActive=@IsActive");
cmd.Parameters.Add(cmd, "@IsActive", DbType.Boolean).Value = query.IsActive.Value;
}
if (query.HasUser.HasValue)
{
if (query.HasUser.Value)
{
whereClauses.Add("UserId not null");
}
else
{
whereClauses.Add("UserId is null");
}
}
var whereTextWithoutPaging = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens {0} ORDER BY DateCreated LIMIT {1})",
pagingWhereText,
startIndex.ToString(_usCulture)));
}
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
cmd.CommandText += whereText;
cmd.CommandText += " ORDER BY DateCreated";
if (query.Limit.HasValue)
{
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture);
}
cmd.CommandText += "; select count (Id) from AccessTokens" + whereTextWithoutPaging;
var list = new List<AuthenticationInfo>();
var count = 0;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
if (startIndex > 0)
{
list.Add(Get(reader));
var pagingWhereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens {0} ORDER BY DateCreated LIMIT {1})",
pagingWhereText,
startIndex.ToString(_usCulture)));
}
if (reader.NextResult() && reader.Read())
{
count = reader.GetInt32(0);
}
}
var whereText = whereClauses.Count == 0 ?
string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray());
return new QueryResult<AuthenticationInfo>()
{
Items = list.ToArray(),
TotalRecordCount = count
};
cmd.CommandText += whereText;
cmd.CommandText += " ORDER BY DateCreated";
if (query.Limit.HasValue)
{
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture);
}
cmd.CommandText += "; select count (Id) from AccessTokens" + whereTextWithoutPaging;
var list = new List<AuthenticationInfo>();
var count = 0;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
list.Add(Get(reader));
}
if (reader.NextResult() && reader.Read())
{
count = reader.GetInt32(0);
}
}
return new QueryResult<AuthenticationInfo>()
{
Items = list.ToArray(),
TotalRecordCount = count
};
}
}
}
@ -256,24 +252,27 @@ namespace MediaBrowser.Server.Implementations.Security
throw new ArgumentNullException("id");
}
var guid = new Guid(id);
using (var cmd = _connection.CreateCommand())
using (var connection = CreateConnection(true).Result)
{
cmd.CommandText = BaseSelectText + " where Id=@Id";
var guid = new Guid(id);
cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
using (var cmd = connection.CreateCommand())
{
if (reader.Read())
cmd.CommandText = BaseSelectText + " where Id=@Id";
cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
return Get(reader);
if (reader.Read())
{
return Get(reader);
}
}
}
}
return null;
return null;
}
}
private AuthenticationInfo Get(IDataReader reader)
@ -319,19 +318,5 @@ namespace MediaBrowser.Server.Implementations.Security
return info;
}
protected override void CloseConnection()
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
}
}
}

View File

@ -12,27 +12,21 @@ namespace MediaBrowser.Server.Implementations.Social
{
public class SharingRepository : BaseSqliteRepository
{
private IDbConnection _connection;
private IDbCommand _saveShareCommand;
private readonly IApplicationPaths _appPaths;
public SharingRepository(ILogManager logManager, IApplicationPaths appPaths)
: base(logManager)
public SharingRepository(ILogManager logManager, IApplicationPaths appPaths, IDbConnector dbConnector)
: base(logManager, dbConnector)
{
_appPaths = appPaths;
DbFilePath = Path.Combine(appPaths.DataPath, "shares.db");
}
/// <summary>
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public async Task Initialize(IDbConnector dbConnector)
public async Task Initialize()
{
var dbFile = Path.Combine(_appPaths.DataPath, "shares.db");
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false);
string[] queries = {
using (var connection = await CreateConnection().ConfigureAwait(false))
{
string[] queries = {
"create table if not exists Shares (Id GUID, ItemId TEXT, UserId TEXT, ExpirationDate DateTime, PRIMARY KEY (Id))",
"create index if not exists idx_Shares on Shares(Id)",
@ -43,23 +37,8 @@ namespace MediaBrowser.Server.Implementations.Social
"pragma shrink_memory"
};
_connection.RunQueries(queries, Logger);
PrepareStatements();
}
/// <summary>
/// Prepares the statements.
/// </summary>
private void PrepareStatements()
{
_saveShareCommand = _connection.CreateCommand();
_saveShareCommand.CommandText = "replace into Shares (Id, ItemId, UserId, ExpirationDate) values (@Id, @ItemId, @UserId, @ExpirationDate)";
_saveShareCommand.Parameters.Add(_saveShareCommand, "@Id");
_saveShareCommand.Parameters.Add(_saveShareCommand, "@ItemId");
_saveShareCommand.Parameters.Add(_saveShareCommand, "@UserId");
_saveShareCommand.Parameters.Add(_saveShareCommand, "@ExpirationDate");
connection.RunQueries(queries, Logger);
}
}
public async Task CreateShare(SocialShareInfo info)
@ -77,53 +56,62 @@ namespace MediaBrowser.Server.Implementations.Social
cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
using (var connection = await CreateConnection().ConfigureAwait(false))
{
transaction = _connection.BeginTransaction();
_saveShareCommand.GetParameter(0).Value = new Guid(info.Id);
_saveShareCommand.GetParameter(1).Value = info.ItemId;
_saveShareCommand.GetParameter(2).Value = info.UserId;
_saveShareCommand.GetParameter(3).Value = info.ExpirationDate;
_saveShareCommand.Transaction = transaction;
_saveShareCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
using (var saveShareCommand = connection.CreateCommand())
{
transaction.Rollback();
saveShareCommand.CommandText = "replace into Shares (Id, ItemId, UserId, ExpirationDate) values (@Id, @ItemId, @UserId, @ExpirationDate)";
saveShareCommand.Parameters.Add(saveShareCommand, "@Id");
saveShareCommand.Parameters.Add(saveShareCommand, "@ItemId");
saveShareCommand.Parameters.Add(saveShareCommand, "@UserId");
saveShareCommand.Parameters.Add(saveShareCommand, "@ExpirationDate");
IDbTransaction transaction = null;
try
{
transaction = connection.BeginTransaction();
saveShareCommand.GetParameter(0).Value = new Guid(info.Id);
saveShareCommand.GetParameter(1).Value = info.ItemId;
saveShareCommand.GetParameter(2).Value = info.UserId;
saveShareCommand.GetParameter(3).Value = info.ExpirationDate;
saveShareCommand.Transaction = transaction;
saveShareCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save share:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
}
}
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save share:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
WriteLock.Release();
}
}
@ -134,20 +122,23 @@ namespace MediaBrowser.Server.Implementations.Social
throw new ArgumentNullException("id");
}
var cmd = _connection.CreateCommand();
cmd.CommandText = "select Id, ItemId, UserId, ExpirationDate from Shares where id = @id";
cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = new Guid(id);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
using (var connection = CreateConnection(true).Result)
{
if (reader.Read())
{
return GetSocialShareInfo(reader);
}
}
var cmd = connection.CreateCommand();
cmd.CommandText = "select Id, ItemId, UserId, ExpirationDate from Shares where id = @id";
return null;
cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = new Guid(id);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
if (reader.Read())
{
return GetSocialShareInfo(reader);
}
}
return null;
}
}
private SocialShareInfo GetSocialShareInfo(IDataReader reader)
@ -166,19 +157,5 @@ namespace MediaBrowser.Server.Implementations.Social
{
}
protected override void CloseConnection()
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
}
}
}

File diff suppressed because it is too large Load Diff