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 public class SqliteNotificationsRepository : BaseSqliteRepository, INotificationsRepository
{ {
private IDbConnection _connection; public SqliteNotificationsRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector dbConnector) : base(logManager, dbConnector)
private readonly IServerApplicationPaths _appPaths; {
DbFilePath = Path.Combine(appPaths.DataPath, "notifications.db");
}
public event EventHandler<NotificationUpdateEventArgs> NotificationAdded; public event EventHandler<NotificationUpdateEventArgs> NotificationAdded;
public event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead; public event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead;
public event EventHandler<NotificationUpdateEventArgs> NotificationUpdated; public event EventHandler<NotificationUpdateEventArgs> NotificationUpdated;
private IDbCommand _replaceNotificationCommand; public async Task Initialize()
private IDbCommand _markReadCommand;
private IDbCommand _markAllReadCommand;
public SqliteNotificationsRepository(ILogManager logManager, IServerApplicationPaths appPaths)
: base(logManager)
{ {
_appPaths = appPaths; using (var connection = await CreateConnection().ConfigureAwait(false))
} {
string[] queries = {
public async Task Initialize(IDbConnector dbConnector)
{
var dbFile = Path.Combine(_appPaths.DataPath, "notifications.db");
_connection = await dbConnector.Connect(dbFile).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 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)", "create index if not exists idx_Notifications1 on Notifications(Id)",
@ -50,39 +40,8 @@ namespace MediaBrowser.Server.Implementations.Notifications
"pragma shrink_memory" "pragma shrink_memory"
}; };
_connection.RunQueries(queries, Logger); 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");
} }
/// <summary> /// <summary>
@ -94,49 +53,52 @@ namespace MediaBrowser.Server.Implementations.Notifications
{ {
var result = new NotificationResult(); var result = new NotificationResult();
using (var cmd = _connection.CreateCommand()) using (var connection = CreateConnection(true).Result)
{ {
var clauses = new List<string>(); using (var cmd = connection.CreateCommand())
if (query.IsRead.HasValue)
{ {
clauses.Add("IsRead=@IsRead"); var clauses = new List<string>();
cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = query.IsRead.Value;
}
clauses.Add("UserId=@UserId"); if (query.IsRead.HasValue)
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())
{ {
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 (reader.Read())
if (query.StartIndex.HasValue)
{ {
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(); 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"; using (var cmd = connection.CreateCommand())
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))
{ {
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; return result;
if (levels.Count > 0)
{
result.MaxUnreadNotificationLevel = levels.Max();
}
} }
return result;
} }
} }
@ -179,10 +144,14 @@ namespace MediaBrowser.Server.Implementations.Notifications
/// <returns>IEnumerable{Notification}.</returns> /// <returns>IEnumerable{Notification}.</returns>
private IEnumerable<Notification> GetNotifications(IDataReader reader) private IEnumerable<Notification> GetNotifications(IDataReader reader)
{ {
var list = new List<Notification>();
while (reader.Read()) while (reader.Read())
{ {
yield return GetNotification(reader); list.Add(GetNotification(reader));
} }
return list;
} }
private Notification GetNotification(IDataReader reader) private Notification GetNotification(IDataReader reader)
@ -273,59 +242,74 @@ namespace MediaBrowser.Server.Implementations.Notifications
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); using (var connection = await CreateConnection().ConfigureAwait(false))
IDbTransaction transaction = null;
try
{ {
transaction = _connection.BeginTransaction(); using (var replaceNotificationCommand = connection.CreateCommand())
_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(); 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(); cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); using (var connection = await CreateConnection().ConfigureAwait(false))
IDbTransaction transaction = null;
try
{ {
cancellationToken.ThrowIfCancellationRequested(); using (var markAllReadCommand = connection.CreateCommand())
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(); 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(); cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); using (var connection = await CreateConnection().ConfigureAwait(false))
IDbTransaction transaction = null;
try
{ {
cancellationToken.ThrowIfCancellationRequested(); using (var markReadCommand = connection.CreateCommand())
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.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 public abstract class BaseSqliteRepository : IDisposable
{ {
protected readonly SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1); protected readonly SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1);
protected readonly IDbConnector DbConnector;
protected ILogger Logger; 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); Logger = logManager.GetLogger(GetType().Name);
} }
protected Task<IDbConnection> CreateConnection(bool isReadOnly = false)
{
return DbConnector.Connect(DbFilePath, false, true);
}
private bool _disposed; private bool _disposed;
protected void CheckDisposed() 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 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> /// </summary>
public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository
{ {
private IDbConnection _connection; public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths, IDbConnector dbConnector)
: base(logManager, dbConnector)
public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths) : base(logManager)
{ {
_jsonSerializer = jsonSerializer; _jsonSerializer = jsonSerializer;
_appPaths = appPaths; DbFilePath = Path.Combine(appPaths.DataPath, "displaypreferences.db");
} }
/// <summary> /// <summary>
@ -43,22 +42,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary> /// </summary>
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
/// <summary>
/// The _app paths
/// </summary>
private readonly IApplicationPaths _appPaths;
/// <summary> /// <summary>
/// Opens the connection to the database /// Opens the connection to the database
/// </summary> /// </summary>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public async Task Initialize(IDbConnector dbConnector) public async Task Initialize()
{ {
var dbFile = Path.Combine(_appPaths.DataPath, "displaypreferences.db"); using (var connection = await CreateConnection().ConfigureAwait(false))
{
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = {
string[] queries = {
"create table if not exists userdisplaypreferences (id GUID, userId GUID, client text, data BLOB)", "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)", "create unique index if not exists userdisplaypreferencesindex on userdisplaypreferences (id, userId, client)",
@ -69,7 +61,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"pragma shrink_memory" "pragma shrink_memory"
}; };
_connection.RunQueries(queries, Logger); connection.RunQueries(queries, Logger);
}
} }
/// <summary> /// <summary>
@ -96,58 +89,57 @@ namespace MediaBrowser.Server.Implementations.Persistence
var serialized = _jsonSerializer.SerializeToBytes(displayPreferences); var serialized = _jsonSerializer.SerializeToBytes(displayPreferences);
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); using (var connection = await CreateConnection().ConfigureAwait(false))
IDbTransaction transaction = null;
try
{ {
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); using (var cmd = connection.CreateCommand())
cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId; {
cmd.Parameters.Add(cmd, "@3", DbType.String).Value = client; cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)";
cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized;
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();
} }
catch (OperationCanceledException)
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{ {
transaction.Rollback(); if (transaction != null)
{
transaction.Rollback();
}
throw;
} }
catch (Exception e)
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save display preferences:", e);
if (transaction != null)
{ {
transaction.Rollback(); Logger.ErrorException("Failed to save display preferences:", e);
}
throw; if (transaction != null)
} {
finally transaction.Rollback();
{ }
if (transaction != null)
throw;
}
finally
{ {
transaction.Dispose(); if (transaction != null)
{
transaction.Dispose();
}
} }
WriteLock.Release();
} }
} }
@ -168,64 +160,63 @@ namespace MediaBrowser.Server.Implementations.Persistence
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); using (var connection = await CreateConnection().ConfigureAwait(false))
IDbTransaction transaction = null;
try
{ {
transaction = _connection.BeginTransaction(); IDbTransaction transaction = null;
foreach (var displayPreference in displayPreferences) try
{ {
transaction = connection.BeginTransaction();
var serialized = _jsonSerializer.SerializeToBytes(displayPreference); foreach (var displayPreference in displayPreferences)
using (var cmd = _connection.CreateCommand())
{ {
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); var serialized = _jsonSerializer.SerializeToBytes(displayPreference);
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; 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 guidId = displayPreferencesId.GetMD5();
var cmd = _connection.CreateCommand(); using (var connection = CreateConnection(true).Result)
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))
{ {
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> /// <summary>
@ -278,36 +274,30 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <exception cref="System.ArgumentNullException">item</exception> /// <exception cref="System.ArgumentNullException">item</exception>
public IEnumerable<DisplayPreferences> GetAllDisplayPreferences(Guid userId) public IEnumerable<DisplayPreferences> GetAllDisplayPreferences(Guid userId)
{ {
var list = new List<DisplayPreferences>();
var cmd = _connection.CreateCommand(); using (var connection = CreateConnection(true).Result)
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))
{ {
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() return list;
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
} }
public Task SaveDisplayPreferences(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken) public Task SaveDisplayPreferences(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken)

View File

@ -19,11 +19,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <summary> /// <summary>
/// Connects to db. /// Connects to db.
/// </summary> /// </summary>
/// <param name="dbPath">The db path.</param> public static async Task<IDbConnection> ConnectToDb(string dbPath, bool isReadOnly, bool enablePooling, int? cacheSize, ILogger logger)
/// <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)
{ {
if (string.IsNullOrEmpty(dbPath)) if (string.IsNullOrEmpty(dbPath))
{ {
@ -38,7 +34,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
CacheSize = cacheSize ?? 2000, CacheSize = cacheSize ?? 2000,
SyncMode = SynchronizationModes.Normal, SyncMode = SynchronizationModes.Normal,
DataSource = dbPath, DataSource = dbPath,
JournalMode = SQLiteJournalModeEnum.Wal JournalMode = SQLiteJournalModeEnum.Wal,
Pooling = enablePooling,
ReadOnly = isReadOnly
}; };
var connection = new SQLiteConnection(connectionstr.ConnectionString); var connection = new SQLiteConnection(connectionstr.ConnectionString);
@ -47,15 +45,5 @@ namespace MediaBrowser.Server.Implementations.Persistence
return connection; 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 _deleteResultCommand;
private IDbCommand _deleteAllCommand; private IDbCommand _deleteAllCommand;
public SqliteFileOrganizationRepository(ILogManager logManager, IServerApplicationPaths appPaths) : base(logManager) public SqliteFileOrganizationRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector) : base(logManager, connector)
{ {
_appPaths = appPaths; _appPaths = appPaths;
} }
@ -39,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{ {
var dbFile = Path.Combine(_appPaths.DataPath, "fileorganization.db"); 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 = { string[] queries = {

View File

@ -99,8 +99,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class. /// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
/// </summary> /// </summary>
public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager) public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogManager logManager, IDbConnector connector)
: base(logManager) : base(logManager, connector)
{ {
if (config == null) if (config == null)
{ {
@ -127,7 +127,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{ {
var dbFile = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); 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 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))"; = "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 IDbConnection _connection;
private readonly IApplicationPaths _appPaths; 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; _appPaths = appPaths;
} }
@ -43,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{ {
var dbFile = Path.Combine(_appPaths.DataPath, "userdata_v2.db"); 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 = { string[] queries = {

View File

@ -17,14 +17,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary> /// </summary>
public class SqliteUserRepository : BaseSqliteRepository, IUserRepository public class SqliteUserRepository : BaseSqliteRepository, IUserRepository
{ {
private IDbConnection _connection;
private readonly IServerApplicationPaths _appPaths;
private readonly IJsonSerializer _jsonSerializer; 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; _jsonSerializer = jsonSerializer;
DbFilePath = Path.Combine(appPaths.DataPath, "users.db");
} }
/// <summary> /// <summary>
@ -43,13 +42,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// Opens the connection to the database /// Opens the connection to the database
/// </summary> /// </summary>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public async Task Initialize(IDbConnector dbConnector) public async Task Initialize()
{ {
var dbFile = Path.Combine(_appPaths.DataPath, "users.db"); using (var connection = await CreateConnection().ConfigureAwait(false))
{
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = {
string[] queries = {
"create table if not exists users (guid GUID primary key, data BLOB)", "create table if not exists users (guid GUID primary key, data BLOB)",
"create index if not exists idx_users on users(guid)", "create index if not exists idx_users on users(guid)",
@ -61,7 +58,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"pragma shrink_memory" "pragma shrink_memory"
}; };
_connection.RunQueries(queries, Logger); connection.RunQueries(queries, Logger);
}
} }
/// <summary> /// <summary>
@ -84,55 +82,54 @@ namespace MediaBrowser.Server.Implementations.Persistence
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); using (var connection = await CreateConnection().ConfigureAwait(false))
IDbTransaction transaction = null;
try
{ {
transaction = _connection.BeginTransaction(); IDbTransaction transaction = null;
using (var cmd = _connection.CreateCommand()) try
{ {
cmd.CommandText = "replace into users (guid, data) values (@1, @2)"; transaction = connection.BeginTransaction();
cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = user.Id;
cmd.Parameters.Add(cmd, "@2", DbType.Binary).Value = serialized;
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();
} }
catch (OperationCanceledException)
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{ {
transaction.Rollback(); if (transaction != null)
{
transaction.Rollback();
}
throw;
} }
catch (Exception e)
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to save user:", e);
if (transaction != null)
{ {
transaction.Rollback(); Logger.ErrorException("Failed to save user:", e);
}
throw; if (transaction != null)
} {
finally transaction.Rollback();
{ }
if (transaction != null)
throw;
}
finally
{ {
transaction.Dispose(); if (transaction != null)
{
transaction.Dispose();
}
} }
WriteLock.Release();
} }
} }
@ -142,25 +139,32 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <returns>IEnumerable{User}.</returns> /// <returns>IEnumerable{User}.</returns>
public IEnumerable<User> RetrieveAllUsers() 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 cmd = connection.CreateCommand())
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{ {
while (reader.Read()) cmd.CommandText = "select guid,data from users";
{
var id = reader.GetGuid(0);
using (var stream = reader.GetMemoryStream(1)) using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{ {
var user = _jsonSerializer.DeserializeFromStream<User>(stream); var id = reader.GetGuid(0);
user.Id = id;
yield return user; using (var stream = reader.GetMemoryStream(1))
{
var user = _jsonSerializer.DeserializeFromStream<User>(stream);
user.Id = id;
list.Add(user);
}
} }
} }
} }
} }
return list;
} }
/// <summary> /// <summary>
@ -179,69 +183,54 @@ namespace MediaBrowser.Server.Implementations.Persistence
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); using (var connection = await CreateConnection().ConfigureAwait(false))
IDbTransaction transaction = null;
try
{ {
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();
} }
catch (OperationCanceledException)
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{ {
transaction.Rollback(); if (transaction != null)
{
transaction.Rollback();
}
throw;
} }
catch (Exception e)
throw;
}
catch (Exception e)
{
Logger.ErrorException("Failed to delete user:", e);
if (transaction != null)
{ {
transaction.Rollback(); Logger.ErrorException("Failed to delete user:", e);
}
throw; if (transaction != null)
} {
finally transaction.Rollback();
{ }
if (transaction != null)
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 public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository
{ {
private IDbConnection _connection;
private readonly IServerApplicationPaths _appPaths; private readonly IServerApplicationPaths _appPaths;
private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private IDbCommand _saveInfoCommand; public AuthenticationRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector)
: base(logManager, connector)
public AuthenticationRepository(ILogManager logManager, IServerApplicationPaths appPaths)
: base(logManager)
{ {
_appPaths = appPaths; _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"); using (var connection = await CreateConnection().ConfigureAwait(false))
{
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = {
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 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)", "create index if not exists idx_AccessTokens on AccessTokens(Id)",
@ -44,28 +40,10 @@ namespace MediaBrowser.Server.Implementations.Security
"pragma shrink_memory" "pragma shrink_memory"
}; };
_connection.RunQueries(queries, Logger); connection.RunQueries(queries, Logger);
_connection.AddColumn(Logger, "AccessTokens", "AppVersion", "TEXT"); 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");
} }
public Task Create(AuthenticationInfo info, CancellationToken cancellationToken) public Task Create(AuthenticationInfo info, CancellationToken cancellationToken)
@ -84,61 +62,76 @@ namespace MediaBrowser.Server.Implementations.Security
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); using (var connection = await CreateConnection().ConfigureAwait(false))
IDbTransaction transaction = null;
try
{ {
transaction = _connection.BeginTransaction(); using (var saveInfoCommand = connection.CreateCommand())
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(); 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"); throw new ArgumentNullException("query");
} }
using (var cmd = _connection.CreateCommand()) using (var connection = CreateConnection(true).Result)
{ {
cmd.CommandText = BaseSelectText; using (var cmd = connection.CreateCommand())
var whereClauses = new List<string>();
var startIndex = query.StartIndex ?? 0;
if (!string.IsNullOrWhiteSpace(query.AccessToken))
{ {
whereClauses.Add("AccessToken=@AccessToken"); cmd.CommandText = BaseSelectText;
cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken;
}
if (!string.IsNullOrWhiteSpace(query.UserId)) var whereClauses = new List<string>();
{
whereClauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId;
}
if (!string.IsNullOrWhiteSpace(query.DeviceId)) var startIndex = query.StartIndex ?? 0;
{
whereClauses.Add("DeviceId=@DeviceId");
cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId;
}
if (query.IsActive.HasValue) if (!string.IsNullOrWhiteSpace(query.AccessToken))
{
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"); 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 ? if (!string.IsNullOrWhiteSpace(query.DeviceId))
string.Empty : {
" where " + string.Join(" AND ", whereClauses.ToArray()); whereClauses.Add("DeviceId=@DeviceId");
cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId;
}
if (startIndex > 0) if (query.IsActive.HasValue)
{ {
var pagingWhereText = whereClauses.Count == 0 ? 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 : string.Empty :
" where " + string.Join(" AND ", whereClauses.ToArray()); " where " + string.Join(" AND ", whereClauses.ToArray());
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens {0} ORDER BY DateCreated LIMIT {1})", if (startIndex > 0)
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())
{ {
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()) var whereText = whereClauses.Count == 0 ?
{ string.Empty :
count = reader.GetInt32(0); " where " + string.Join(" AND ", whereClauses.ToArray());
}
}
return new QueryResult<AuthenticationInfo>() cmd.CommandText += whereText;
{
Items = list.ToArray(), cmd.CommandText += " ORDER BY DateCreated";
TotalRecordCount = count
}; 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"); throw new ArgumentNullException("id");
} }
var guid = new Guid(id); using (var connection = CreateConnection(true).Result)
using (var cmd = _connection.CreateCommand())
{ {
cmd.CommandText = BaseSelectText + " where Id=@Id"; var guid = new Guid(id);
cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; using (var cmd = connection.CreateCommand())
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{ {
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) private AuthenticationInfo Get(IDataReader reader)
@ -319,19 +318,5 @@ namespace MediaBrowser.Server.Implementations.Security
return info; 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 public class SharingRepository : BaseSqliteRepository
{ {
private IDbConnection _connection; public SharingRepository(ILogManager logManager, IApplicationPaths appPaths, IDbConnector dbConnector)
private IDbCommand _saveShareCommand; : base(logManager, dbConnector)
private readonly IApplicationPaths _appPaths;
public SharingRepository(ILogManager logManager, IApplicationPaths appPaths)
: base(logManager)
{ {
_appPaths = appPaths; DbFilePath = Path.Combine(appPaths.DataPath, "shares.db");
} }
/// <summary> /// <summary>
/// Opens the connection to the database /// Opens the connection to the database
/// </summary> /// </summary>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public async Task Initialize(IDbConnector dbConnector) public async Task Initialize()
{ {
var dbFile = Path.Combine(_appPaths.DataPath, "shares.db"); using (var connection = await CreateConnection().ConfigureAwait(false))
{
_connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = {
string[] queries = {
"create table if not exists Shares (Id GUID, ItemId TEXT, UserId TEXT, ExpirationDate DateTime, PRIMARY KEY (Id))", "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)", "create index if not exists idx_Shares on Shares(Id)",
@ -43,23 +37,8 @@ namespace MediaBrowser.Server.Implementations.Social
"pragma shrink_memory" "pragma shrink_memory"
}; };
_connection.RunQueries(queries, Logger); 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");
} }
public async Task CreateShare(SocialShareInfo info) public async Task CreateShare(SocialShareInfo info)
@ -77,53 +56,62 @@ namespace MediaBrowser.Server.Implementations.Social
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); using (var connection = await CreateConnection().ConfigureAwait(false))
IDbTransaction transaction = null;
try
{ {
transaction = _connection.BeginTransaction(); using (var saveShareCommand = connection.CreateCommand())
_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(); 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"); throw new ArgumentNullException("id");
} }
var cmd = _connection.CreateCommand(); using (var connection = CreateConnection(true).Result)
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))
{ {
if (reader.Read()) var cmd = connection.CreateCommand();
{ cmd.CommandText = "select Id, ItemId, UserId, ExpirationDate from Shares where id = @id";
return GetSocialShareInfo(reader);
}
}
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) private SocialShareInfo GetSocialShareInfo(IDataReader reader)
@ -164,21 +155,7 @@ namespace MediaBrowser.Server.Implementations.Social
public async Task DeleteShare(string id) public async Task DeleteShare(string id)
{ {
}
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