From 15f0832a042ef77bee549958fcf130986af9f430 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 21 May 2016 02:12:00 -0400 Subject: deprecate refreshinfo db --- .../Persistence/SqliteItemRepository.cs | 44 ---- .../Persistence/SqliteProviderInfoRepository.cs | 248 --------------------- 2 files changed, 292 deletions(-) delete mode 100644 MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 7f45e61842..c5e4fcd07e 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -254,53 +254,9 @@ namespace MediaBrowser.Server.Implementations.Persistence new MediaStreamColumns(_connection, Logger).AddColumns(); - var mediaStreamsDbFile = Path.Combine(_config.ApplicationPaths.DataPath, "mediainfo.db"); - if (File.Exists(mediaStreamsDbFile)) - { - MigrateMediaStreams(mediaStreamsDbFile); - } - DataExtensions.Attach(_connection, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"), "UserDataDb"); } - private void MigrateMediaStreams(string file) - { - try - { - var backupFile = file + ".bak"; - File.Copy(file, backupFile, true); - DataExtensions.Attach(_connection, backupFile, "MediaInfoOld"); - - var columns = string.Join(",", _mediaStreamSaveColumns); - - string[] queries = { - "REPLACE INTO mediastreams("+columns+") SELECT "+columns+" FROM MediaInfoOld.mediastreams;" - }; - - _connection.RunQueries(queries, Logger); - } - catch (Exception ex) - { - Logger.ErrorException("Error migrating media info database", ex); - } - finally - { - TryDeleteFile(file); - } - } - - private void TryDeleteFile(string file) - { - try - { - File.Delete(file); - } - catch (Exception ex) - { - Logger.ErrorException("Error deleting file {0}", ex, file); - } - } - private readonly string[] _retriveItemColumns = { "type", diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs deleted file mode 100644 index 40d5c9586e..0000000000 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs +++ /dev/null @@ -1,248 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using System; -using System.Data; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - public class SqliteProviderInfoRepository : BaseSqliteRepository, IProviderRepository - { - private IDbConnection _connection; - - private IDbCommand _saveStatusCommand; - private readonly IApplicationPaths _appPaths; - - public SqliteProviderInfoRepository(ILogManager logManager, IApplicationPaths appPaths) : base(logManager) - { - _appPaths = appPaths; - } - - /// - /// Gets the name of the repository - /// - /// The name. - public string Name - { - get - { - return "SQLite"; - } - } - - /// - /// Opens the connection to the database - /// - /// Task. - public async Task Initialize(IDbConnector dbConnector) - { - var dbFile = Path.Combine(_appPaths.DataPath, "refreshinfo.db"); - - _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); - - string[] queries = { - - "create table if not exists MetadataStatus (ItemId GUID PRIMARY KEY, DateLastMetadataRefresh datetime, DateLastImagesRefresh datetime, ItemDateModified DateTimeNull)", - "create index if not exists idx_MetadataStatus on MetadataStatus(ItemId)", - - //pragmas - "pragma temp_store = memory", - - "pragma shrink_memory" - }; - - _connection.RunQueries(queries, Logger); - - AddItemDateModifiedCommand(); - - PrepareStatements(); - } - - private static readonly string[] StatusColumns = - { - "ItemId", - "DateLastMetadataRefresh", - "DateLastImagesRefresh", - "ItemDateModified" - }; - - private void AddItemDateModifiedCommand() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(MetadataStatus)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "ItemDateModified", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table MetadataStatus"); - builder.AppendLine("add column ItemDateModified DateTime NULL"); - - _connection.RunQueries(new[] { builder.ToString() }, Logger); - } - - /// - /// Prepares the statements. - /// - private void PrepareStatements() - { - _saveStatusCommand = _connection.CreateCommand(); - - _saveStatusCommand.CommandText = string.Format("replace into MetadataStatus ({0}) values ({1})", - string.Join(",", StatusColumns), - string.Join(",", StatusColumns.Select(i => "@" + i).ToArray())); - - foreach (var col in StatusColumns) - { - _saveStatusCommand.Parameters.Add(_saveStatusCommand, "@" + col); - } - } - - public MetadataStatus GetMetadataStatus(Guid itemId) - { - if (itemId == Guid.Empty) - { - throw new ArgumentNullException("itemId"); - } - - using (var cmd = _connection.CreateCommand()) - { - var cmdText = "select " + string.Join(",", StatusColumns) + " from MetadataStatus where"; - - cmdText += " ItemId=@ItemId"; - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = itemId; - - cmd.CommandText = cmdText; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - while (reader.Read()) - { - return GetStatus(reader); - } - - return null; - } - } - } - - private MetadataStatus GetStatus(IDataReader reader) - { - var result = new MetadataStatus - { - ItemId = reader.GetGuid(0) - }; - - if (!reader.IsDBNull(1)) - { - result.DateLastMetadataRefresh = reader.GetDateTime(1).ToUniversalTime(); - } - - if (!reader.IsDBNull(2)) - { - result.DateLastImagesRefresh = reader.GetDateTime(2).ToUniversalTime(); - } - - if (!reader.IsDBNull(3)) - { - result.ItemDateModified = reader.GetDateTime(3).ToUniversalTime(); - } - - return result; - } - - public async Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken) - { - if (status == null) - { - throw new ArgumentNullException("status"); - } - - cancellationToken.ThrowIfCancellationRequested(); - - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - _saveStatusCommand.GetParameter(0).Value = status.ItemId; - _saveStatusCommand.GetParameter(1).Value = status.DateLastMetadataRefresh; - _saveStatusCommand.GetParameter(2).Value = status.DateLastImagesRefresh; - _saveStatusCommand.GetParameter(3).Value = status.ItemDateModified; - - _saveStatusCommand.Transaction = transaction; - - _saveStatusCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save provider info:", 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; - } - } - } -} -- cgit v1.2.3 From e5049f92b4ea4f67ea1406888269c0093ff193ae Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 22 May 2016 14:53:37 -0400 Subject: remove schema version checks --- .../Entities/Audio/MusicArtist.cs | 7 -- MediaBrowser.Controller/Entities/Folder.cs | 87 ---------------------- .../Persistence/SqliteItemRepository.cs | 49 +++--------- 3 files changed, 11 insertions(+), 132 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 02dad93cbe..c1743c749c 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -62,13 +62,6 @@ namespace MediaBrowser.Controller.Entities.Audio query.ArtistNames = new[] { Name }; } - // Need this for now since the artist filter isn't yet supported by the db - if (ConfigurationManager.Configuration.SchemaVersion < 79) - { - var filter = GetItemFilter(); - return LibraryManager.GetItemList(query).Where(filter); - } - return LibraryManager.GetItemList(query); } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index e7b1df55ad..ac49dc3b2b 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -773,53 +773,8 @@ namespace MediaBrowser.Controller.Entities } } - var supportsUserDataQueries = ConfigurationManager.Configuration.SchemaVersion >= 76; - if (query.SortBy != null && query.SortBy.Length > 0) { - if (!supportsUserDataQueries) - { - if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed"); - return true; - } - } - - if (ConfigurationManager.Configuration.SchemaVersion < 79) - { - if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist"); - return true; - } - if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist"); - return true; - } - } - if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase)) { Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder"); @@ -884,39 +839,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (!supportsUserDataQueries) - { - if (query.IsLiked.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsLiked"); - return true; - } - - if (query.IsFavoriteOrLiked.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked"); - return true; - } - - if (query.IsFavorite.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsFavorite"); - return true; - } - - if (query.IsResumable.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsResumable"); - return true; - } - - if (query.IsPlayed.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsPlayed"); - return true; - } - } - if (query.IsInBoxSet.HasValue) { Logger.Debug("Query requires post-filtering due to IsInBoxSet"); @@ -1102,15 +1024,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (ConfigurationManager.Configuration.SchemaVersion < 79) - { - if (query.ArtistNames.Length > 0) - { - Logger.Debug("Query requires post-filtering due to ArtistNames"); - return true; - } - } - return false; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index c5e4fcd07e..19f9653a8c 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1504,11 +1504,6 @@ namespace MediaBrowser.Server.Implementations.Persistence private bool EnableJoinUserData(InternalItemsQuery query) { - if (_config.Configuration.SchemaVersion < 76) - { - return false; - } - if (query.User == null) { return false; @@ -1623,7 +1618,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66) + if (EnableGroupByPresentationUniqueKey(query)) { cmd.CommandText += " Group by PresentationUniqueKey"; } @@ -1711,7 +1706,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66) + if (EnableGroupByPresentationUniqueKey(query)) { cmd.CommandText += " Group by PresentationUniqueKey"; } @@ -1730,7 +1725,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } } - if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66) + if (EnableGroupByPresentationUniqueKey(query)) { cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; } @@ -1880,7 +1875,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66) + if (EnableGroupByPresentationUniqueKey(query)) { cmd.CommandText += " Group by PresentationUniqueKey"; } @@ -1940,7 +1935,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66) + if (EnableGroupByPresentationUniqueKey(query)) { cmd.CommandText += " Group by PresentationUniqueKey"; } @@ -2023,7 +2018,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66) + if (EnableGroupByPresentationUniqueKey(query)) { cmd.CommandText += " Group by PresentationUniqueKey"; } @@ -2042,7 +2037,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } } - if (EnableGroupByPresentationUniqueKey(query) && _config.Configuration.SchemaVersion >= 66) + if (EnableGroupByPresentationUniqueKey(query)) { cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; } @@ -2319,41 +2314,19 @@ namespace MediaBrowser.Server.Implementations.Persistence if (!string.IsNullOrWhiteSpace(query.SlugName)) { - if (_config.Configuration.SchemaVersion >= 70) - { - whereClauses.Add("SlugName=@SlugName"); - } - else - { - whereClauses.Add("Name=@SlugName"); - } + whereClauses.Add("SlugName=@SlugName"); cmd.Parameters.Add(cmd, "@SlugName", DbType.String).Value = query.SlugName; } if (!string.IsNullOrWhiteSpace(query.Name)) { - if (_config.Configuration.SchemaVersion >= 66) - { - whereClauses.Add("CleanName=@Name"); - cmd.Parameters.Add(cmd, "@Name", DbType.String).Value = query.Name.RemoveDiacritics(); - } - else - { - whereClauses.Add("Name=@Name"); - cmd.Parameters.Add(cmd, "@Name", DbType.String).Value = query.Name; - } + whereClauses.Add("CleanName=@Name"); + cmd.Parameters.Add(cmd, "@Name", DbType.String).Value = query.Name.RemoveDiacritics(); } if (!string.IsNullOrWhiteSpace(query.NameContains)) { - if (_config.Configuration.SchemaVersion >= 66) - { - whereClauses.Add("CleanName like @NameContains"); - } - else - { - whereClauses.Add("Name like @NameContains"); - } + whereClauses.Add("CleanName like @NameContains"); cmd.Parameters.Add(cmd, "@NameContains", DbType.String).Value = "%" + query.NameContains.RemoveDiacritics() + "%"; } if (!string.IsNullOrWhiteSpace(query.NameStartsWith)) -- cgit v1.2.3 From bc2f18bce37794b6968e19f13ca69eb109ec7c03 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 23 May 2016 00:11:37 -0400 Subject: save series name separately --- MediaBrowser.Model/Configuration/ServerConfiguration.cs | 1 - .../Persistence/SqliteItemRepository.cs | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index e9084d4d1e..66bea95bb3 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -223,7 +223,6 @@ namespace MediaBrowser.Model.Configuration DenyIFrameEmbedding = true; EnableUPnP = true; - SchemaVersion = 79; SharingExpirationDays = 30; MinResumePct = 5; MaxResumePct = 90; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 19f9653a8c..7e2cc2da3c 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -87,7 +87,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - public const int LatestSchemaVersion = 79; + public const int LatestSchemaVersion = 80; /// /// Initializes a new instance of the class. @@ -239,6 +239,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME"); _connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "IsVirtualItem", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "SeriesName", "Text"); _connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT"); @@ -433,7 +434,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "PrimaryVersionId", "DateLastMediaAdded", "Album", - "IsVirtualItem" + "IsVirtualItem", + "SeriesName" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -835,6 +837,16 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = null; } + var hasSeries = item as IHasSeries; + if (hasSeries != null) + { + _saveItemCommand.GetParameter(index++).Value = hasSeries.SeriesName; + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); -- cgit v1.2.3 From 446b50e5567311f96ce9ef91425fe82fed27bbc7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 23 May 2016 14:25:52 -0400 Subject: add index on TopParentId --- .../Persistence/SqliteItemRepository.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 7e2cc2da3c..9978e9781d 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -246,7 +246,8 @@ namespace MediaBrowser.Server.Implementations.Persistence string[] postQueries = { "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)", - "create index if not exists idx_Type on TypedBaseItems(Type)" + "create index if not exists idx_Type on TypedBaseItems(Type)", + "create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)" }; _connection.RunQueries(postQueries, Logger); -- cgit v1.2.3 From 178a5f6978c417b3209c27bb9bde184749a9ef58 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 24 May 2016 14:28:58 -0400 Subject: fix attach --- MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs index 103b75f840..61ce6e351b 100644 --- a/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs @@ -122,7 +122,10 @@ namespace MediaBrowser.Server.Implementations.Persistence { using (var cmd = db.CreateCommand()) { - cmd.CommandText = string.Format("attach '{0}' as {1};", path, alias); + cmd.CommandText = string.Format("attach @dbPath as {0};", alias); + cmd.Parameters.Add(cmd, "@dbPath", DbType.String); + cmd.GetParameter(0).Value = path; + cmd.ExecuteNonQuery(); } } -- cgit v1.2.3 From 6bb6e0ff849e09fa39281adf6001599c0a73f979 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 24 May 2016 20:22:41 -0400 Subject: update logging --- .../Persistence/SqliteItemRepository.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 9978e9781d..ec10fdaf69 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1670,7 +1670,13 @@ namespace MediaBrowser.Server.Implementations.Persistence { var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds; - if (elapsed >= 400) + var slowThreshold = 1000; + +#if DEBUG + slowThreshold = 200; +#endif + + if (elapsed >= slowThreshold) { Logger.Debug("{2} query time (slow): {0}ms. Query: {1}", Convert.ToInt32(elapsed), -- cgit v1.2.3 From a02e0473d8ae4b84f31e90ebce00d0f1e681904d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 26 May 2016 13:28:20 -0400 Subject: update logging --- .../Persistence/SqliteItemRepository.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index ec10fdaf69..2775389a22 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -247,7 +247,8 @@ namespace MediaBrowser.Server.Implementations.Persistence { "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)", "create index if not exists idx_Type on TypedBaseItems(Type)", - "create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)" + "create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)", + "create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)" }; _connection.RunQueries(postQueries, Logger); @@ -1673,7 +1674,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var slowThreshold = 1000; #if DEBUG - slowThreshold = 200; + slowThreshold = 100; #endif if (elapsed >= slowThreshold) -- cgit v1.2.3 From dd9cb28ee9e1fe95564618bdbc1b3eaaee1f7d96 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 26 May 2016 15:22:37 -0400 Subject: update index --- MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 2775389a22..b1f43d20f7 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -248,7 +248,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)", "create index if not exists idx_Type on TypedBaseItems(Type)", "create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)", - "create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)" + //"create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)" }; _connection.RunQueries(postQueries, Logger); -- cgit v1.2.3 From c5e5aba027ee889ac6347ce464e739280cac5da9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 May 2016 14:42:28 -0400 Subject: update index --- MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index b1f43d20f7..2775389a22 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -248,7 +248,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)", "create index if not exists idx_Type on TypedBaseItems(Type)", "create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)", - //"create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)" + "create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)" }; _connection.RunQueries(postQueries, Logger); -- cgit v1.2.3 From f091e6f55f741e2ebd9a818a837c1950c49c1967 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 30 May 2016 14:16:44 -0400 Subject: stub out tv movies in suggestions --- MediaBrowser.Api/Movies/MoviesService.cs | 27 +++++++++------- .../Persistence/SqliteItemRepository.cs | 36 +++++++++++++++++++++- 2 files changed, 51 insertions(+), 12 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 8a6e5b8dfb..b06007c787 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -14,6 +14,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using MediaBrowser.Controller.LiveTv; namespace MediaBrowser.Api.Movies { @@ -132,13 +133,15 @@ namespace MediaBrowser.Api.Movies var query = new InternalItemsQuery(user) { - IncludeItemTypes = new[] { typeof(Movie).Name } + IncludeItemTypes = new[] + { + typeof(Movie).Name, + typeof(Trailer).Name, + //typeof(LiveTvProgram).Name + }, + // IsMovie = true }; - var includeList = query.IncludeItemTypes.ToList(); - includeList.Add(typeof(Trailer).Name); - query.IncludeItemTypes = includeList.ToArray(); - var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId }; var movies = _libraryManager.GetItemList(query, parentIds) .OrderBy(i => (int)i.SourceType); @@ -179,16 +182,18 @@ namespace MediaBrowser.Api.Movies var item = string.IsNullOrEmpty(request.Id) ? (!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder : _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); - + var query = new InternalItemsQuery(user) { - IncludeItemTypes = new[] { typeof(Movie).Name } + IncludeItemTypes = new[] + { + typeof(Movie).Name, + typeof(Trailer).Name, + //typeof(LiveTvProgram).Name + }, + //IsMovie = true }; - var includeList = query.IncludeItemTypes.ToList(); - includeList.Add(typeof(Trailer).Name); - query.IncludeItemTypes = includeList.ToArray(); - var list = _libraryManager.GetItemList(query) .OrderBy(i => (int)i.SourceType) .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N")) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 2775389a22..1de0ea7108 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -2132,7 +2132,41 @@ namespace MediaBrowser.Server.Implementations.Persistence } if (query.IsMovie.HasValue) { - whereClauses.Add("IsMovie=@IsMovie"); + var alternateTypes = new List(); + if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name)) + { + alternateTypes.Add(typeof(Movie).FullName); + } + if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name)) + { + alternateTypes.Add(typeof(Trailer).FullName); + } + + if (alternateTypes.Count == 0) + { + whereClauses.Add("IsMovie=@IsMovie"); + } + else + { + if (query.IsMovie.Value) + { + var typeClauses = new List(); + var typeIndex = 0; + foreach (var type in alternateTypes) + { + var paramName = "@AlternateType" + typeIndex.ToString(CultureInfo.InvariantCulture); + typeClauses.Add("Type=" + paramName); + cmd.Parameters.Add(cmd, paramName, DbType.String).Value = type; + typeIndex++; + } + + whereClauses.Add("(IsMovie=@IsMovie OR " + string.Join(" OR ", typeClauses.ToArray()) + ")"); + } + else + { + whereClauses.Add("(IsMovie is null OR IsMovie=@IsMovie)"); + } + } cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = query.IsMovie; } if (query.IsKids.HasValue) -- cgit v1.2.3 From 977f62336be3c54fc33b3476d80d3cce4c0b244c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 31 May 2016 14:07:54 -0400 Subject: update storage of genres, studios, tags, & keywords --- MediaBrowser.Api/ItemUpdateService.cs | 6 +--- MediaBrowser.Api/SimilarItemsHelper.cs | 8 +----- MediaBrowser.Controller/Entities/BaseItem.cs | 3 ++ MediaBrowser.Controller/Entities/IHasKeywords.cs | 31 -------------------- .../Entities/InternalItemsQuery.cs | 2 ++ .../Entities/KeywordExtensions.cs | 21 ++++++++++++++ MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 9 +----- MediaBrowser.Controller/Entities/Movies/Movie.cs | 4 +-- MediaBrowser.Controller/Entities/Trailer.cs | 4 +-- .../MediaBrowser.Controller.csproj | 2 +- .../Providers/BaseItemXmlParser.cs | 8 ++---- .../Savers/XmlSaverHelpers.cs | 18 +++++------- MediaBrowser.Providers/Manager/ProviderUtils.cs | 10 ++----- .../Movies/GenericMovieDbInfo.cs | 6 +--- .../Dto/DtoService.cs | 11 +------- .../Intros/DefaultIntroProvider.cs | 8 +----- .../Persistence/SqliteItemRepository.cs | 33 +++++++++++++++++----- .../Native/SqliteExtensions.cs | 2 +- .../Native/SqliteExtensions.cs | 2 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 8 ++---- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 8 ++---- 21 files changed, 78 insertions(+), 126 deletions(-) delete mode 100644 MediaBrowser.Controller/Entities/IHasKeywords.cs create mode 100644 MediaBrowser.Controller/Entities/KeywordExtensions.cs (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index 5bb4ed5f00..36e8a504c8 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -298,11 +298,7 @@ namespace MediaBrowser.Api hasShortOverview.ShortOverview = request.ShortOverview; } - var hasKeywords = item as IHasKeywords; - if (hasKeywords != null) - { - hasKeywords.Keywords = request.Keywords; - } + item.Keywords = request.Keywords; if (request.Studios != null) { diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs index 277bba1dd1..76bc16a96f 100644 --- a/MediaBrowser.Api/SimilarItemsHelper.cs +++ b/MediaBrowser.Api/SimilarItemsHelper.cs @@ -127,13 +127,7 @@ namespace MediaBrowser.Api private static IEnumerable GetKeywords(BaseItem item) { - var hasTags = item as IHasKeywords; - if (hasTags != null) - { - return hasTags.Keywords; - } - - return new List(); + return item.Keywords; } /// diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 2a00ce992e..78f1828eaf 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -37,6 +37,7 @@ namespace MediaBrowser.Controller.Entities { protected BaseItem() { + Keywords = new List(); Tags = new List(); Genres = new List(); Studios = new List(); @@ -811,6 +812,8 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public List Tags { get; set; } + public List Keywords { get; set; } + /// /// Gets or sets the home page URL. /// diff --git a/MediaBrowser.Controller/Entities/IHasKeywords.cs b/MediaBrowser.Controller/Entities/IHasKeywords.cs deleted file mode 100644 index ab9eb4aeee..0000000000 --- a/MediaBrowser.Controller/Entities/IHasKeywords.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasKeywords - { - /// - /// Gets or sets the keywords. - /// - /// The keywords. - List Keywords { get; set; } - } - - public static class KeywordExtensions - { - public static void AddKeyword(this IHasKeywords item, string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - if (!item.Keywords.Contains(name, StringComparer.OrdinalIgnoreCase)) - { - item.Keywords.Add(name); - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 823f4066c4..7e38d7ed9f 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -33,6 +33,7 @@ namespace MediaBrowser.Controller.Entities public string[] ExcludeTags { get; set; } public string[] ExcludeInheritedTags { get; set; } public string[] Genres { get; set; } + public string[] Keywords { get; set; } public bool? IsMissing { get; set; } public bool? IsUnaired { get; set; } @@ -151,6 +152,7 @@ namespace MediaBrowser.Controller.Entities OfficialRatings = new string[] { }; SortBy = new string[] { }; MediaTypes = new string[] { }; + Keywords = new string[] { }; IncludeItemTypes = new string[] { }; ExcludeItemTypes = new string[] { }; Genres = new string[] { }; diff --git a/MediaBrowser.Controller/Entities/KeywordExtensions.cs b/MediaBrowser.Controller/Entities/KeywordExtensions.cs new file mode 100644 index 0000000000..5c9afdf3d5 --- /dev/null +++ b/MediaBrowser.Controller/Entities/KeywordExtensions.cs @@ -0,0 +1,21 @@ +using System; +using System.Linq; + +namespace MediaBrowser.Controller.Entities +{ + public static class KeywordExtensions + { + public static void AddKeyword(this BaseItem item, string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentNullException("name"); + } + + if (!item.Keywords.Contains(name, StringComparer.OrdinalIgnoreCase)) + { + item.Keywords.Add(name); + } + } + } +} diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 09a9d97bcf..4effc162e4 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities.Movies /// /// Class BoxSet /// - public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo, IHasShares + public class BoxSet : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo, IHasShares { public List Shares { get; set; } @@ -26,7 +26,6 @@ namespace MediaBrowser.Controller.Entities.Movies RemoteTrailerIds = new List(); DisplayOrder = ItemSortBy.PremiereDate; - Keywords = new List(); Shares = new List(); } @@ -47,12 +46,6 @@ namespace MediaBrowser.Controller.Entities.Movies /// The remote trailers. public List RemoteTrailers { get; set; } - /// - /// Gets or sets the tags. - /// - /// The tags. - public List Keywords { get; set; } - /// /// Gets or sets the display order. /// diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 605221dcde..c7a833c58f 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities.Movies /// /// Class Movie /// - public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo, ISupportsBoxSetGrouping, IHasOriginalTitle + public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo, ISupportsBoxSetGrouping, IHasOriginalTitle { public List SpecialFeatureIds { get; set; } @@ -32,7 +32,6 @@ namespace MediaBrowser.Controller.Entities.Movies ThemeSongIds = new List(); ThemeVideoIds = new List(); Taglines = new List(); - Keywords = new List(); ProductionLocations = new List(); } @@ -42,7 +41,6 @@ namespace MediaBrowser.Controller.Entities.Movies public List LocalTrailerIds { get; set; } public List RemoteTrailerIds { get; set; } - public List Keywords { get; set; } public List RemoteTrailers { get; set; } diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 74645bbe91..eab5ab6794 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities /// /// Class Trailer /// - public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo + public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo { public List ProductionLocations { get; set; } @@ -31,8 +31,6 @@ namespace MediaBrowser.Controller.Entities public List RemoteTrailers { get; set; } - public List Keywords { get; set; } - [IgnoreDataMember] public bool IsLocalTrailer { diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 4d9999b37d..b15bb94c78 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -142,7 +142,7 @@ - + diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index 1014fc2ee9..aaa440060c 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -816,11 +816,7 @@ namespace MediaBrowser.Controller.Providers { using (var subtree = reader.ReadSubtree()) { - var hasTags = item as IHasKeywords; - if (hasTags != null) - { - FetchFromKeywordsNode(subtree, hasTags); - } + FetchFromKeywordsNode(subtree, item); } break; } @@ -1099,7 +1095,7 @@ namespace MediaBrowser.Controller.Providers } } - private void FetchFromKeywordsNode(XmlReader reader, IHasKeywords item) + private void FetchFromKeywordsNode(XmlReader reader, BaseItem item) { reader.MoveToContent(); diff --git a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs index be81d21d20..ca19b403ab 100644 --- a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs @@ -609,20 +609,16 @@ namespace MediaBrowser.LocalMetadata.Savers } } - var hasKeywords = item as IHasKeywords; - if (hasKeywords != null) + if (item.Keywords.Count > 0) { - if (hasKeywords.Keywords.Count > 0) - { - builder.Append(""); - - foreach (var tag in hasKeywords.Keywords) - { - builder.Append("" + SecurityElement.Escape(tag) + ""); - } + builder.Append(""); - builder.Append(""); + foreach (var tag in item.Keywords) + { + builder.Append("" + SecurityElement.Escape(tag) + ""); } + + builder.Append(""); } var people = libraryManager.GetPeople(item); diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index 59a2da4603..a6f02f3f74 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -165,15 +165,9 @@ namespace MediaBrowser.Providers.Manager if (!lockedFields.Contains(MetadataFields.Keywords)) { - var sourceHasKeywords = source as IHasKeywords; - var targetHasKeywords = target as IHasKeywords; - - if (sourceHasKeywords != null && targetHasKeywords != null) + if (replaceData || target.Keywords.Count == 0) { - if (replaceData || targetHasKeywords.Keywords.Count == 0) - { - targetHasKeywords.Keywords = sourceHasKeywords.Keywords; - } + target.Keywords = source.Keywords; } } diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs index d13716cba1..3b3065893c 100644 --- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs +++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs @@ -314,11 +314,7 @@ namespace MediaBrowser.Providers.Movies if (movieData.keywords != null && movieData.keywords.keywords != null) { - var hasTags = movie as IHasKeywords; - if (hasTags != null) - { - hasTags.Keywords = movieData.keywords.keywords.Select(i => i.name).ToList(); - } + movie.Keywords = movieData.keywords.keywords.Select(i => i.name).ToList(); } if (movieData.trailers != null && movieData.trailers.youtube != null && diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index eb868d3630..bfcdb2a264 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -983,16 +983,7 @@ namespace MediaBrowser.Server.Implementations.Dto if (fields.Contains(ItemFields.Keywords)) { - var hasTags = item as IHasKeywords; - if (hasTags != null) - { - dto.Keywords = hasTags.Keywords; - } - - if (dto.Keywords == null) - { - dto.Keywords = new List(); - } + dto.Keywords = item.Keywords; } if (fields.Contains(ItemFields.ProductionLocations)) diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index 49012c65af..df128a90b0 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -433,13 +433,7 @@ namespace MediaBrowser.Server.Implementations.Intros private static IEnumerable GetKeywords(BaseItem item) { - var hasTags = item as IHasKeywords; - if (hasTags != null) - { - return hasTags.Keywords; - } - - return new List(); + return item.Keywords; } public IEnumerable GetAllIntroFiles() diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 1de0ea7108..a85bf1c81b 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -87,7 +87,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - public const int LatestSchemaVersion = 80; + public const int LatestSchemaVersion = 82; /// /// Initializes a new instance of the class. @@ -2489,8 +2489,8 @@ namespace MediaBrowser.Server.Implementations.Persistence var index = 0; foreach (var item in query.Genres) { - clauses.Add("Genres like @Genres" + index); - cmd.Parameters.Add(cmd, "@Genres" + index, DbType.String).Value = "%" + item + "%"; + clauses.Add("@Genre" + index + " in (select value from itemvalues where ItemId=Guid and Type=2)"); + cmd.Parameters.Add(cmd, "@Genre" + index, DbType.String).Value = item; index++; } var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; @@ -2503,8 +2503,8 @@ namespace MediaBrowser.Server.Implementations.Persistence var index = 0; foreach (var item in query.Tags) { - clauses.Add("Tags like @Tags" + index); - cmd.Parameters.Add(cmd, "@Tags" + index, DbType.String).Value = "%" + item + "%"; + clauses.Add("@Tag" + index + " in (select value from itemvalues where ItemId=Guid and Type=4)"); + cmd.Parameters.Add(cmd, "@Tag" + index, DbType.String).Value = item; index++; } var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; @@ -2517,8 +2517,22 @@ namespace MediaBrowser.Server.Implementations.Persistence var index = 0; foreach (var item in query.Studios) { - clauses.Add("Studios like @Studios" + index); - cmd.Parameters.Add(cmd, "@Studios" + index, DbType.String).Value = "%" + item + "%"; + clauses.Add("@Studio" + index + " in (select value from itemvalues where ItemId=Guid and Type=3)"); + cmd.Parameters.Add(cmd, "@Studio" + index, DbType.String).Value = item; + index++; + } + var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + whereClauses.Add(clause); + } + + if (query.Keywords.Length > 0) + { + var clauses = new List(); + var index = 0; + foreach (var item in query.Keywords) + { + clauses.Add("@Keyword" + index + " in (select value from itemvalues where ItemId=Guid and Type=5)"); + cmd.Parameters.Add(cmd, "@Keyword" + index, DbType.String).Value = item; index++; } var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; @@ -3233,6 +3247,11 @@ namespace MediaBrowser.Server.Implementations.Persistence list.AddRange(hasAlbumArtist.AlbumArtists.Select(i => new Tuple(1, i))); } + list.AddRange(item.Genres.Select(i => new Tuple(2, i))); + list.AddRange(item.Studios.Select(i => new Tuple(3, i))); + list.AddRange(item.Tags.Select(i => new Tuple(4, i))); + list.AddRange(item.Keywords.Select(i => new Tuple(5, i))); + return list; } diff --git a/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs b/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs index 385a7d0c58..ca2327282e 100644 --- a/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs +++ b/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.Server.Mono.Native { PageSize = 4096, CacheSize = 2000, - SyncMode = SynchronizationModes.Full, + SyncMode = SynchronizationModes.Normal, DataSource = dbPath, JournalMode = SQLiteJournalModeEnum.Wal }; diff --git a/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs b/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs index 4e6c824959..bdf5c33237 100644 --- a/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs +++ b/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.ServerApplication.Native { PageSize = 4096, CacheSize = 2000, - SyncMode = SynchronizationModes.Full, + SyncMode = SynchronizationModes.Normal, DataSource = dbPath, JournalMode = SQLiteJournalModeEnum.Wal }; diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index d020a73fe0..ad1c6802d2 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -932,13 +932,9 @@ namespace MediaBrowser.XbmcMetadata.Parsers { var val = reader.ReadElementContentAsString(); - var hasKeywords = item as IHasKeywords; - if (hasKeywords != null) + if (!string.IsNullOrWhiteSpace(val)) { - if (!string.IsNullOrWhiteSpace(val)) - { - hasKeywords.AddKeyword(val); - } + item.AddKeyword(val); } break; } diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index d2e09d4ebf..5bb9577ff3 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -752,13 +752,9 @@ namespace MediaBrowser.XbmcMetadata.Savers } } - var hasKeywords = item as IHasKeywords; - if (hasKeywords != null) + foreach (var tag in item.Keywords) { - foreach (var tag in hasKeywords.Keywords) - { - writer.WriteElementString("plotkeyword", tag); - } + writer.WriteElementString("plotkeyword", tag); } var hasAwards = item as IHasAwards; -- cgit v1.2.3 From ec23e084d04bcb3361fcc0799e65943ae9ea95b5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 31 May 2016 14:45:37 -0400 Subject: update movie suggestions --- .../Persistence/SqliteItemRepository.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index a85bf1c81b..3149352a90 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -2628,6 +2628,20 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add("MediaType in (" + val + ")"); } + if (query.ExcludeItemIds.Length > 0) + { + var excludeIds = new List(); + + var index = 0; + foreach (var id in query.ExcludeItemIds) + { + excludeIds.Add("Guid <> @ExcludeId" + index); + cmd.Parameters.Add(cmd, "@ExcludeId" + index, DbType.Guid).Value = new Guid(id); + index++; + } + + whereClauses.Add(string.Join(" AND ", excludeIds.ToArray())); + } if (query.AlbumNames.Length > 0) { -- cgit v1.2.3 From e1f562e16ff585b440a43029efe9db314b4de965 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 1 Jun 2016 01:50:00 -0400 Subject: calculate similarity at database level --- MediaBrowser.Api/GamesService.cs | 41 +++-- MediaBrowser.Api/Movies/MoviesService.cs | 114 +++++--------- MediaBrowser.Api/TvShowsService.cs | 41 +++-- .../Entities/InternalItemsQuery.cs | 2 + .../Persistence/IDbConnector.cs | 1 + .../Persistence/SqliteExtensions.cs | 175 +++++++++++++++++++++ .../Persistence/SqliteItemRepository.cs | 80 +++++++--- .../MediaBrowser.Server.Mono.csproj | 5 +- MediaBrowser.Server.Mono/Native/DbConnector.cs | 29 ++++ .../Native/SqliteExtensions.cs | 62 -------- .../MediaBrowser.ServerApplication.csproj | 5 +- .../Native/DbConnector.cs | 38 +++++ .../Native/SqliteExtensions.cs | 71 --------- 13 files changed, 409 insertions(+), 255 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs create mode 100644 MediaBrowser.Server.Mono/Native/DbConnector.cs delete mode 100644 MediaBrowser.Server.Mono/Native/SqliteExtensions.cs create mode 100644 MediaBrowser.ServerApplication/Native/DbConnector.cs delete mode 100644 MediaBrowser.ServerApplication/Native/SqliteExtensions.cs (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/GamesService.cs b/MediaBrowser.Api/GamesService.cs index 387771b6d5..cb77e62adf 100644 --- a/MediaBrowser.Api/GamesService.cs +++ b/MediaBrowser.Api/GamesService.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using MediaBrowser.Model.Querying; namespace MediaBrowser.Api { @@ -187,18 +188,40 @@ namespace MediaBrowser.Api /// System.Object. public object Get(GetSimilarGames request) { + var result = GetSimilarItemsResult(request); + + return ToOptimizedSerializedResultUsingCache(result); + } + + private QueryResult GetSimilarItemsResult(BaseGetSimilarItemsFromItem request) + { + var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; + + var item = string.IsNullOrEmpty(request.Id) ? + (!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder : + _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); + + var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) + { + Limit = request.Limit, + IncludeItemTypes = new[] + { + typeof(Game).Name + }, + SimilarTo = item + + }).ToList(); + var dtoOptions = GetDtoOptions(request); - var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager, - _itemRepo, - _libraryManager, - _userDataRepository, - _dtoService, - Logger, - request, new[] { typeof(Game) }, - SimilarItemsHelper.GetSimiliarityScore); + var result = new QueryResult + { + Items = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ToArray(), - return ToOptimizedSerializedResultUsingCache(result); + TotalRecordCount = itemsResult.Count + }; + + return result; } } } diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index ce36dd2ac9..ff18d440c1 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -111,18 +111,16 @@ namespace MediaBrowser.Api.Movies /// /// The request. /// System.Object. - public async Task Get(GetSimilarMovies request) + public object Get(GetSimilarMovies request) { - var result = await GetSimilarItemsResult( - request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false); + var result = GetSimilarItemsResult(request); return ToOptimizedSerializedResultUsingCache(result); } - public async Task Get(GetSimilarTrailers request) + public object Get(GetSimilarTrailers request) { - var result = await GetSimilarItemsResult( - request, SimilarItemsHelper.GetSimiliarityScore).ConfigureAwait(false); + var result = GetSimilarItemsResult(request); return ToOptimizedSerializedResultUsingCache(result); } @@ -131,42 +129,16 @@ namespace MediaBrowser.Api.Movies { var user = _userManager.GetUserById(request.UserId); - var query = new InternalItemsQuery(user) - { - IncludeItemTypes = new[] - { - typeof(Movie).Name, - typeof(Trailer).Name, - //typeof(LiveTvProgram).Name - }, - // IsMovie = true - }; - - var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId }; - var movies = _libraryManager.GetItemList(query, parentIds) - .OrderBy(i => (int)i.SourceType); - - var listEligibleForSuggestion = new List(); - - var list = movies.ToList(); - - listEligibleForSuggestion.AddRange(list); - - listEligibleForSuggestion = listEligibleForSuggestion - .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase) - .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase) - .ToList(); - var dtoOptions = GetDtoOptions(request); dtoOptions.Fields = request.GetItemFields().ToList(); - var result = GetRecommendationCategories(user, request.ParentId, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, dtoOptions); + var result = GetRecommendationCategories(user, request.ParentId, request.CategoryLimit, request.ItemLimit, dtoOptions); return ToOptimizedResult(result); } - private async Task GetSimilarItemsResult(BaseGetSimilarItemsFromItem request, Func, List, BaseItem, int> getSimilarityScore) + private QueryResult GetSimilarItemsResult(BaseGetSimilarItemsFromItem request) { var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; @@ -174,57 +146,32 @@ namespace MediaBrowser.Api.Movies (!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder : _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); - var query = new InternalItemsQuery(user) + var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) { + Limit = request.Limit, IncludeItemTypes = new[] { - typeof(Movie).Name, - typeof(Trailer).Name, - //typeof(LiveTvProgram).Name + typeof(Movie).Name, + typeof(Trailer).Name, + typeof(LiveTvProgram).Name }, - //IsMovie = true - }; - - var list = _libraryManager.GetItemList(query) - .OrderBy(i => (int)i.SourceType) - .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N")) - .ToList(); - - if (item is Video) - { - var imdbId = item.GetProviderId(MetadataProviders.Imdb); - - // Use imdb id to try to filter duplicates of the same item - if (!string.IsNullOrWhiteSpace(imdbId)) - { - list = list - .Where(i => !string.Equals(imdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase)) - .ToList(); - } - } - - var items = SimilarItemsHelper.GetSimilaritems(item, _libraryManager, list, getSimilarityScore).ToList(); - - IEnumerable returnItems = items; - - if (request.Limit.HasValue) - { - returnItems = returnItems.Take(request.Limit.Value); - } + IsMovie = true, + SimilarTo = item + }).ToList(); var dtoOptions = GetDtoOptions(request); - var result = new ItemsResult + var result = new QueryResult { - Items = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user).ToArray(), + Items = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ToArray(), - TotalRecordCount = items.Count + TotalRecordCount = itemsResult.Count }; return result; } - private IEnumerable GetRecommendationCategories(User user, string parentId, List allMovies, int categoryLimit, int itemLimit, DtoOptions dtoOptions) + private IEnumerable GetRecommendationCategories(User user, string parentId, int categoryLimit, int itemLimit, DtoOptions dtoOptions) { var categories = new List(); @@ -260,7 +207,7 @@ namespace MediaBrowser.Api.Movies IsFavoriteOrLiked = true, ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id.ToString("N")).ToArray() - }, parentIds); + }, parentIds).ToList(); var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList(); // Get recently played directors @@ -273,8 +220,8 @@ namespace MediaBrowser.Api.Movies .OrderBy(i => Guid.NewGuid()) .ToList(); - var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(7).OrderBy(i => Guid.NewGuid()), itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator(); - var similarToLiked = GetSimilarTo(user, allMovies, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator(); + var similarToRecentlyPlayed = GetSimilarTo(user, recentlyPlayedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator(); + var similarToLiked = GetSimilarTo(user, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator(); var hasDirectorFromRecentlyPlayed = GetWithDirector(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator(); var hasActorFromRecentlyPlayed = GetWithActor(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator(); @@ -389,14 +336,23 @@ namespace MediaBrowser.Api.Movies } } - private IEnumerable GetSimilarTo(User user, List allMovies, IEnumerable baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type) + private IEnumerable GetSimilarTo(User user, List baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type) { foreach (var item in baselineItems) { - var similar = SimilarItemsHelper - .GetSimilaritems(item, _libraryManager, allMovies, SimilarItemsHelper.GetSimiliarityScore) - .Take(itemLimit) - .ToList(); + var similar = _libraryManager.GetItemList(new InternalItemsQuery(user) + { + Limit = itemLimit, + IncludeItemTypes = new[] + { + typeof(Movie).Name, + typeof(Trailer).Name, + typeof(LiveTvProgram).Name + }, + IsMovie = true, + SimilarTo = item + + }).ToList(); if (similar.Count > 0) { diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index aa0485d57e..5ccfede1ef 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -12,6 +12,7 @@ using ServiceStack; using System; using System.Collections.Generic; using System.Linq; +using MediaBrowser.Model.Dto; namespace MediaBrowser.Api { @@ -273,18 +274,40 @@ namespace MediaBrowser.Api /// System.Object. public object Get(GetSimilarShows request) { + var result = GetSimilarItemsResult(request); + + return ToOptimizedSerializedResultUsingCache(result); + } + + private QueryResult GetSimilarItemsResult(BaseGetSimilarItemsFromItem request) + { + var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; + + var item = string.IsNullOrEmpty(request.Id) ? + (!string.IsNullOrWhiteSpace(request.UserId) ? user.RootFolder : + _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); + + var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) + { + Limit = request.Limit, + IncludeItemTypes = new[] + { + typeof(Series).Name + }, + SimilarTo = item + + }).ToList(); + var dtoOptions = GetDtoOptions(request); - var result = SimilarItemsHelper.GetSimilarItemsResult(dtoOptions, _userManager, - _itemRepo, - _libraryManager, - _userDataManager, - _dtoService, - Logger, - request, new[] { typeof(Series) }, - SimilarItemsHelper.GetSimiliarityScore); + var result = new QueryResult + { + Items = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user).ToArray(), - return ToOptimizedSerializedResultUsingCache(result); + TotalRecordCount = itemsResult.Count + }; + + return result; } public object Get(GetUpcomingEpisodes request) diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index f3f05a08fa..0047a13b28 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -19,6 +19,8 @@ namespace MediaBrowser.Controller.Entities public User User { get; set; } + public BaseItem SimilarTo { get; set; } + public bool? IsFolder { get; set; } public bool? IsFavorite { get; set; } public bool? IsFavoriteOrLiked { get; set; } diff --git a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs index cac9fe9835..985d79a0ac 100644 --- a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs +++ b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs @@ -6,5 +6,6 @@ namespace MediaBrowser.Server.Implementations.Persistence public interface IDbConnector { Task Connect(string dbPath); + void BindSimilarityScoreFunction(IDbConnection connection); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs new file mode 100644 index 0000000000..5e07bac310 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SQLite; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.Server.Implementations.Persistence +{ + /// + /// Class SQLiteExtensions + /// + public static class SqliteExtensions + { + /// + /// Connects to db. + /// + /// The db path. + /// The logger. + /// Task{IDbConnection}. + /// dbPath + public static async Task ConnectToDb(string dbPath, ILogger logger) + { + if (string.IsNullOrEmpty(dbPath)) + { + throw new ArgumentNullException("dbPath"); + } + + logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); + + var connectionstr = new SQLiteConnectionStringBuilder + { + PageSize = 4096, + CacheSize = 2000, + SyncMode = SynchronizationModes.Normal, + DataSource = dbPath, + JournalMode = SQLiteJournalModeEnum.Wal + }; + + var connection = new SQLiteConnection(connectionstr.ConnectionString); + + await connection.OpenAsync().ConfigureAwait(false); + + return connection; + } + + public static void BindGetSimilarityScore(IDbConnection connection, ILogger logger) + { + var sqlConnection = (SQLiteConnection) connection; + SimiliarToFunction.Logger = logger; + sqlConnection.BindFunction(new SimiliarToFunction()); + } + + public static void BindFunction(this SQLiteConnection connection, SQLiteFunction function) + { + var attributes = function.GetType().GetCustomAttributes(typeof(SQLiteFunctionAttribute), true).Cast().ToArray(); + if (attributes.Length == 0) + { + throw new InvalidOperationException("SQLiteFunction doesn't have SQLiteFunctionAttribute"); + } + connection.BindFunction(attributes[0], function); + } + } + + [SQLiteFunction(Name = "GetSimilarityScore", Arguments = 12, FuncType = FunctionType.Scalar)] + public class SimiliarToFunction : SQLiteFunction + { + internal static ILogger Logger; + + public override object Invoke(object[] args) + { + var score = 0; + + var inputOfficialRating = args[0] as string; + var rowOfficialRating = args[1] as string; + if (!string.IsNullOrWhiteSpace(inputOfficialRating) && string.Equals(inputOfficialRating, rowOfficialRating)) + { + score += 10; + } + + long? inputYear = args[2] == null ? (long?)null : (long)args[2]; + long? rowYear = args[3] == null ? (long?)null : (long)args[3]; + + if (inputYear.HasValue && rowYear.HasValue) + { + var diff = Math.Abs(inputYear.Value - rowYear.Value); + + // Add if they came out within the same decade + if (diff < 10) + { + score += 2; + } + + // And more if within five years + if (diff < 5) + { + score += 2; + } + } + + // genres + score += GetListScore(args, 4, 5); + + // tags + score += GetListScore(args, 6, 7); + + // keywords + score += GetListScore(args, 8, 9); + + // studios + score += GetListScore(args, 10, 11, 3); + + + // TODO: People + // var item2PeopleNames = allPeople.Where(i => i.ItemId == item2.Id) + //.Select(i => i.Name) + //.Where(i => !string.IsNullOrWhiteSpace(i)) + //.DistinctNames() + //.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); + + // points += item1People.Where(i => item2PeopleNames.ContainsKey(i.Name)).Sum(i => + // { + // if (string.Equals(i.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Director, StringComparison.OrdinalIgnoreCase)) + // { + // return 5; + // } + // if (string.Equals(i.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Actor, StringComparison.OrdinalIgnoreCase)) + // { + // return 3; + // } + // if (string.Equals(i.Type, PersonType.Composer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Composer, StringComparison.OrdinalIgnoreCase)) + // { + // return 3; + // } + // if (string.Equals(i.Type, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase)) + // { + // return 3; + // } + // if (string.Equals(i.Type, PersonType.Writer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase)) + // { + // return 2; + // } + + // return 1; + // }); + + // return points; + + //Logger.Debug("Returning score {0}", score); + return score; + } + + private int GetListScore(object[] args, int index1, int index2, int value = 10) + { + var score = 0; + + var inputGenres = args[index1] as string; + var rowGenres = args[index2] as string; + var inputGenreList = string.IsNullOrWhiteSpace(inputGenres) ? new string[] { } : inputGenres.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + var rowGenresList = string.IsNullOrWhiteSpace(rowGenres) ? new string[] { } : rowGenres.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var genre in inputGenreList) + { + if (rowGenresList.Contains(genre, StringComparer.OrdinalIgnoreCase)) + { + score += value; + } + } + + return score; + } + } +} diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 3149352a90..131158dd2d 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -15,6 +15,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Runtime.Serialization; +using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Extensions; @@ -258,6 +259,8 @@ namespace MediaBrowser.Server.Implementations.Persistence new MediaStreamColumns(_connection, Logger).AddColumns(); DataExtensions.Attach(_connection, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"), "UserDataDb"); + + dbConnector.BindSimilarityScoreFunction(_connection); } private readonly string[] _retriveItemColumns = @@ -1575,7 +1578,7 @@ namespace MediaBrowser.Server.Implementations.Persistence return false; } - private string[] GetFinalColumnsToSelect(InternalItemsQuery query, string[] startColumns) + private string[] GetFinalColumnsToSelect(InternalItemsQuery query, string[] startColumns, IDbCommand cmd) { var list = startColumns.ToList(); @@ -1590,6 +1593,45 @@ namespace MediaBrowser.Server.Implementations.Persistence list.Add("UserDataDb.UserData.rating"); } + if (query.SimilarTo != null) + { + var item = query.SimilarTo; + + var builder = new StringBuilder(); + builder.Append("GetSimilarityScore("); + + builder.Append("@ItemOfficialRating,"); + builder.Append("OfficialRating,"); + + builder.Append("@ItemProductionYear,"); + builder.Append("ProductionYear,"); + + builder.Append("@ItemGenres,"); + builder.Append("Genres,"); + + builder.Append("@ItemTags,"); + builder.Append("Tags,"); + + builder.Append("@ItemKeywords,"); + builder.Append("(select group_concat((Select Value from ItemValues where ItemId=Guid and Type=5), '|')),"); + + builder.Append("@ItemStudios,"); + builder.Append("Studios"); + builder.Append(") as SimilarityScore"); + + list.Add(builder.ToString()); + cmd.Parameters.Add(cmd, "@ItemOfficialRating", DbType.String).Value = item.OfficialRating; + cmd.Parameters.Add(cmd, "@ItemProductionYear", DbType.Int32).Value = item.ProductionYear ?? -1; + cmd.Parameters.Add(cmd, "@ItemGenres", DbType.String).Value = string.Join("|", item.Genres.ToArray()); + cmd.Parameters.Add(cmd, "@ItemTags", DbType.String).Value = string.Join("|", item.Tags.ToArray()); + cmd.Parameters.Add(cmd, "@ItemKeywords", DbType.String).Value = string.Join("|", item.Keywords.ToArray()); + cmd.Parameters.Add(cmd, "@ItemStudios", DbType.String).Value = string.Join("|", item.Studios.ToArray()); + + var excludeIds = query.ExcludeItemIds.ToList(); + excludeIds.Add(item.Id.ToString("N")); + query.ExcludeItemIds = excludeIds.ToArray(); + } + return list.ToArray(); } @@ -1616,7 +1658,7 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + " from TypedBaseItems"; + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; cmd.CommandText += GetJoinUserDataText(query); if (EnableJoinUserData(query)) @@ -1706,7 +1748,7 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns)) + " from TypedBaseItems"; + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; cmd.CommandText += GetJoinUserDataText(query); if (EnableJoinUserData(query)) @@ -1789,6 +1831,15 @@ namespace MediaBrowser.Server.Implementations.Persistence private string GetOrderByText(InternalItemsQuery query) { + if (query.SimilarTo != null) + { + if (query.SortBy == null || query.SortBy.Length == 0) + { + query.SortBy = new[] { "SimilarityScore", "Random" }; + query.SortOrder = SortOrder.Descending; + } + } + if (query.SortBy == null || query.SortBy.Length == 0) { return string.Empty; @@ -1879,7 +1930,7 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + " from TypedBaseItems"; + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; cmd.CommandText += GetJoinUserDataText(query); if (EnableJoinUserData(query)) @@ -2022,7 +2073,7 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" })) + " from TypedBaseItems"; + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; var whereClauses = GetWhereClauses(query, cmd); cmd.CommandText += GetJoinUserDataText(query); @@ -2148,24 +2199,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } else { - if (query.IsMovie.Value) - { - var typeClauses = new List(); - var typeIndex = 0; - foreach (var type in alternateTypes) - { - var paramName = "@AlternateType" + typeIndex.ToString(CultureInfo.InvariantCulture); - typeClauses.Add("Type=" + paramName); - cmd.Parameters.Add(cmd, paramName, DbType.String).Value = type; - typeIndex++; - } - - whereClauses.Add("(IsMovie=@IsMovie OR " + string.Join(" OR ", typeClauses.ToArray()) + ")"); - } - else - { - whereClauses.Add("(IsMovie is null OR IsMovie=@IsMovie)"); - } + whereClauses.Add("(IsMovie is null OR IsMovie=@IsMovie)"); } cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = query.IsMovie; } diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index b71877e17a..45071c9d9e 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -82,11 +82,14 @@ + + Native\SqliteExtensions.cs + Properties\SharedVersion.cs - + diff --git a/MediaBrowser.Server.Mono/Native/DbConnector.cs b/MediaBrowser.Server.Mono/Native/DbConnector.cs new file mode 100644 index 0000000000..536cd73223 --- /dev/null +++ b/MediaBrowser.Server.Mono/Native/DbConnector.cs @@ -0,0 +1,29 @@ +using System; +using System.Data; +using System.Data.SQLite; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.Persistence; + +namespace MediaBrowser.Server.Mono.Native +{ + public class DbConnector : IDbConnector + { + private readonly ILogger _logger; + + public DbConnector(ILogger logger) + { + _logger = logger; + } + + public void BindSimilarityScoreFunction(IDbConnection connection) + { + SqliteExtensions.BindGetSimilarityScore(connection, _logger); + } + + public Task Connect(string dbPath) + { + return SqliteExtensions.ConnectToDb(dbPath, _logger); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs b/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs deleted file mode 100644 index ca2327282e..0000000000 --- a/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Data; -using System.Data.SQLite; -using System.Threading.Tasks; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.Persistence; - -namespace MediaBrowser.Server.Mono.Native -{ - /// - /// Class SQLiteExtensions - /// - static class SqliteExtensions - { - /// - /// Connects to db. - /// - /// The db path. - /// The logger. - /// Task{IDbConnection}. - /// dbPath - public static async Task ConnectToDb(string dbPath, ILogger logger) - { - if (string.IsNullOrEmpty(dbPath)) - { - throw new ArgumentNullException("dbPath"); - } - - logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); - - var connectionstr = new SQLiteConnectionStringBuilder - { - PageSize = 4096, - CacheSize = 2000, - SyncMode = SynchronizationModes.Normal, - DataSource = dbPath, - JournalMode = SQLiteJournalModeEnum.Wal - }; - - var connection = new SQLiteConnection(connectionstr.ConnectionString); - - await connection.OpenAsync().ConfigureAwait(false); - - return connection; - } - } - - public class DbConnector : IDbConnector - { - private readonly ILogger _logger; - - public DbConnector(ILogger logger) - { - _logger = logger; - } - - public Task Connect(string dbPath) - { - return SqliteExtensions.ConnectToDb(dbPath, _logger); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 366d4b6083..35660b2b1f 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -97,6 +97,9 @@ + + Native\SqliteExtensions.cs + Properties\SharedVersion.cs @@ -114,7 +117,7 @@ - + diff --git a/MediaBrowser.ServerApplication/Native/DbConnector.cs b/MediaBrowser.ServerApplication/Native/DbConnector.cs new file mode 100644 index 0000000000..f93cad62cb --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/DbConnector.cs @@ -0,0 +1,38 @@ +using System; +using System.Data; +using System.Data.SQLite; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.Persistence; + +namespace MediaBrowser.ServerApplication.Native +{ + public class DbConnector : IDbConnector + { + private readonly ILogger _logger; + + public DbConnector(ILogger logger) + { + _logger = logger; + } + + public void BindSimilarityScoreFunction(IDbConnection connection) + { + SqliteExtensions.BindGetSimilarityScore(connection, _logger); + } + + public async Task Connect(string dbPath) + { + try + { + return await SqliteExtensions.ConnectToDb(dbPath, _logger).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error opening database {0}", ex, dbPath); + + throw; + } + } + } +} \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs b/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs deleted file mode 100644 index bdf5c33237..0000000000 --- a/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Data; -using System.Data.SQLite; -using System.Threading.Tasks; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.Persistence; - -namespace MediaBrowser.ServerApplication.Native -{ - /// - /// Class SQLiteExtensions - /// - static class SqliteExtensions - { - /// - /// Connects to db. - /// - /// The db path. - /// The logger. - /// Task{IDbConnection}. - /// dbPath - public static async Task ConnectToDb(string dbPath, ILogger logger) - { - if (string.IsNullOrEmpty(dbPath)) - { - throw new ArgumentNullException("dbPath"); - } - - logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); - - var connectionstr = new SQLiteConnectionStringBuilder - { - PageSize = 4096, - CacheSize = 2000, - SyncMode = SynchronizationModes.Normal, - DataSource = dbPath, - JournalMode = SQLiteJournalModeEnum.Wal - }; - - var connection = new SQLiteConnection(connectionstr.ConnectionString); - - await connection.OpenAsync().ConfigureAwait(false); - - return connection; - } - } - - public class DbConnector : IDbConnector - { - private readonly ILogger _logger; - - public DbConnector(ILogger logger) - { - _logger = logger; - } - - public async Task Connect(string dbPath) - { - try - { - return await SqliteExtensions.ConnectToDb(dbPath, _logger).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error opening database {0}", ex, dbPath); - - throw; - } - } - } -} \ No newline at end of file -- cgit v1.2.3 From 669af870148a92db4a851868781e2e3af4111a26 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 1 Jun 2016 02:01:43 -0400 Subject: support querying more fields --- MediaBrowser.Controller/Entities/Folder.cs | 16 ---------------- .../Persistence/SqliteItemRepository.cs | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 16 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index cbbd0ad686..0d307c35bc 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -793,11 +793,6 @@ namespace MediaBrowser.Controller.Entities Logger.Debug("Query requires post-filtering due to ItemSortBy.Metascore"); return true; } - if (query.SortBy.Contains(ItemSortBy.OfficialRating, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating"); - return true; - } if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase)) { Logger.Debug("Query requires post-filtering due to ItemSortBy.Players"); @@ -813,11 +808,6 @@ namespace MediaBrowser.Controller.Entities Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName"); return true; } - if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio"); - return true; - } if (query.SortBy.Contains(ItemSortBy.VideoBitRate, StringComparer.OrdinalIgnoreCase)) { Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate"); @@ -962,12 +952,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (query.OfficialRatings.Length > 0) - { - Logger.Debug("Query requires post-filtering due to OfficialRatings"); - return true; - } - if (query.IsMissing.HasValue) { Logger.Debug("Query requires post-filtering due to IsMissing"); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 131158dd2d..9b815bc0b2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1913,6 +1913,14 @@ namespace MediaBrowser.Server.Implementations.Persistence { return new Tuple("(select value from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false); } + if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) + { + return new Tuple("ParentalRatingValue", false); + } + if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) + { + return new Tuple("(select value from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", false); + } return new Tuple(name, false); } @@ -2573,6 +2581,20 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add(clause); } + if (query.OfficialRatings.Length > 0) + { + var clauses = new List(); + var index = 0; + foreach (var item in query.OfficialRatings) + { + clauses.Add("OfficialRating=@OfficialRating" + index); + cmd.Parameters.Add(cmd, "@OfficialRating" + index, DbType.String).Value = item; + index++; + } + var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + whereClauses.Add(clause); + } + if (query.MinParentalRating.HasValue) { whereClauses.Add("InheritedParentalRatingValue<=@MinParentalRating"); -- cgit v1.2.3 From 900cf09e0329af915b36b203b4a1e03477507e04 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 1 Jun 2016 02:20:21 -0400 Subject: use similar query for intros --- .../Intros/DefaultIntroProvider.cs | 182 +-------------------- .../Persistence/SqliteItemRepository.cs | 14 +- 2 files changed, 21 insertions(+), 175 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index df128a90b0..7c7a535cd7 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -63,16 +63,8 @@ namespace MediaBrowser.Server.Implementations.Intros ? null : _localization.GetRatingLevel(item.OfficialRating); - var random = new Random(Environment.TickCount + Guid.NewGuid().GetHashCode()); - var candidates = new List(); - var itemPeople = _libraryManager.GetPeople(item); - var allPeople = _libraryManager.GetPeople(new InternalPeopleQuery - { - AppearsInItemId = item.Id - }); - var trailerTypes = new List(); if (config.EnableIntrosFromMoviesInLibrary) @@ -105,26 +97,25 @@ namespace MediaBrowser.Server.Implementations.Intros var trailerResult = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - TrailerTypes = trailerTypes.ToArray() + TrailerTypes = trailerTypes.ToArray(), + SimilarTo = item, + IsPlayed = config.EnableIntrosForWatchedContent ? (bool?) null : false, + MaxParentalRating = config.EnableIntrosParentalControl ? ratingLevel : null, + Limit = config.TrailerLimit }); candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer { Item = i, Type = i.SourceType == SourceType.Channel ? ItemWithTrailerType.ChannelTrailer : ItemWithTrailerType.ItemWithTrailer, - User = user, - WatchingItem = item, - WatchingItemPeople = itemPeople, - AllPeople = allPeople, - Random = random, LibraryManager = _libraryManager })); } - return GetResult(item, candidates, config, ratingLevel); + return GetResult(item, candidates, config); } - private IEnumerable GetResult(BaseItem item, IEnumerable candidates, CinemaModeConfiguration config, int? ratingLevel) + private IEnumerable GetResult(BaseItem item, IEnumerable candidates, CinemaModeConfiguration config) { var customIntros = !string.IsNullOrWhiteSpace(config.CustomIntroPath) ? GetCustomIntros(config) : @@ -134,48 +125,12 @@ namespace MediaBrowser.Server.Implementations.Intros GetMediaInfoIntros(config, item) : new List(); - var trailerLimit = config.TrailerLimit; - // Avoid implicitly captured closure - return candidates.Where(i => - { - if (config.EnableIntrosParentalControl && !FilterByParentalRating(ratingLevel, i.Item)) - { - return false; - } - - if (!config.EnableIntrosForWatchedContent && i.IsPlayed) - { - return false; - } - return !IsDuplicate(item, i.Item); - }) - .OrderByDescending(i => i.Score) - .ThenBy(i => Guid.NewGuid()) - .ThenByDescending(i => i.IsPlayed ? 0 : 1) - .Select(i => i.IntroInfo) - .Take(trailerLimit) + return candidates.Select(i => i.IntroInfo) .Concat(customIntros.Take(1)) .Concat(mediaInfoIntros); } - private bool IsDuplicate(BaseItem playingContent, BaseItem test) - { - var id = playingContent.GetProviderId(MetadataProviders.Imdb); - if (!string.IsNullOrWhiteSpace(id) && string.Equals(id, test.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - id = playingContent.GetProviderId(MetadataProviders.Tmdb); - if (!string.IsNullOrWhiteSpace(id) && string.Equals(id, test.GetProviderId(MetadataProviders.Tmdb), StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - return false; - } - private CinemaModeConfiguration GetOptions() { return _serverConfig.GetConfiguration("cinemamode"); @@ -346,96 +301,6 @@ namespace MediaBrowser.Server.Implementations.Intros return list.Distinct(StringComparer.OrdinalIgnoreCase); } - private bool FilterByParentalRating(int? ratingLevel, BaseItem item) - { - // Only content rated same or lower - if (ratingLevel.HasValue) - { - var level = string.IsNullOrWhiteSpace(item.OfficialRating) - ? (int?)null - : _localization.GetRatingLevel(item.OfficialRating); - - return level.HasValue && level.Value <= ratingLevel.Value; - } - - return true; - } - - internal static int GetSimiliarityScore(BaseItem item1, List item1People, List allPeople, BaseItem item2, Random random, ILibraryManager libraryManager) - { - var points = 0; - - if (!string.IsNullOrEmpty(item1.OfficialRating) && string.Equals(item1.OfficialRating, item2.OfficialRating, StringComparison.OrdinalIgnoreCase)) - { - points += 10; - } - - // Find common genres - points += item1.Genres.Where(i => item2.Genres.Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10); - - // Find common tags - points += GetTags(item1).Where(i => GetTags(item2).Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10); - - // Find common keywords - points += GetKeywords(item1).Where(i => GetKeywords(item2).Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10); - - // Find common studios - points += item1.Studios.Where(i => item2.Studios.Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 5); - - var item2PeopleNames = allPeople.Where(i => i.ItemId == item2.Id) - .Select(i => i.Name) - .Where(i => !string.IsNullOrWhiteSpace(i)) - .DistinctNames() - .ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); - - points += item1People.Where(i => item2PeopleNames.ContainsKey(i.Name)).Sum(i => - { - if (string.Equals(i.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Director, StringComparison.OrdinalIgnoreCase)) - { - return 5; - } - if (string.Equals(i.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Actor, StringComparison.OrdinalIgnoreCase)) - { - return 3; - } - if (string.Equals(i.Type, PersonType.Composer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Composer, StringComparison.OrdinalIgnoreCase)) - { - return 3; - } - if (string.Equals(i.Type, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase)) - { - return 3; - } - if (string.Equals(i.Type, PersonType.Writer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase)) - { - return 2; - } - - return 1; - }); - - // Add some randomization so that you're not always seeing the same ones for a given movie - points += random.Next(0, 50); - - return points; - } - - private static IEnumerable GetTags(BaseItem item) - { - var hasTags = item as IHasTags; - if (hasTags != null) - { - return hasTags.Tags; - } - - return new List(); - } - - private static IEnumerable GetKeywords(BaseItem item) - { - return item.Keywords; - } - public IEnumerable GetAllIntroFiles() { return GetCustomIntroFiles(GetOptions(), true, true); @@ -455,39 +320,8 @@ namespace MediaBrowser.Server.Implementations.Intros { internal BaseItem Item; internal ItemWithTrailerType Type; - internal User User; - internal BaseItem WatchingItem; - internal List WatchingItemPeople; - internal List AllPeople; - internal Random Random; internal ILibraryManager LibraryManager; - private bool? _isPlayed; - public bool IsPlayed - { - get - { - if (!_isPlayed.HasValue) - { - _isPlayed = Item.IsPlayed(User); - } - return _isPlayed.Value; - } - } - - private int? _score; - public int Score - { - get - { - if (!_score.HasValue) - { - _score = GetSimiliarityScore(WatchingItem, WatchingItemPeople, AllPeople, Item, Random, LibraryManager); - } - return _score.Value; - } - } - public IntroInfo IntroInfo { get diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 9b815bc0b2..c00c4bf300 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1526,6 +1526,11 @@ namespace MediaBrowser.Server.Implementations.Persistence return false; } + if (query.SimilarTo != null) + { + return true; + } + if (query.SortBy != null && query.SortBy.Length > 0) { if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase)) @@ -1835,7 +1840,14 @@ namespace MediaBrowser.Server.Implementations.Persistence { if (query.SortBy == null || query.SortBy.Length == 0) { - query.SortBy = new[] { "SimilarityScore", "Random" }; + if (query.User != null) + { + query.SortBy = new[] { "SimilarityScore", "IsUnplayed", "Random" }; + } + else + { + query.SortBy = new[] { "SimilarityScore", "Random" }; + } query.SortOrder = SortOrder.Descending; } } -- cgit v1.2.3 From 2979185d8e658dfa083ac4c29cd982e00ba1933a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Jun 2016 00:41:12 -0400 Subject: add provider ids to database --- MediaBrowser.Api/Reports/ReportsService.cs | 1 - MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs | 3 - MediaBrowser.Api/UserLibrary/ItemsService.cs | 1 - MediaBrowser.Controller/Entities/BaseItem.cs | 1 + MediaBrowser.Controller/Entities/Folder.cs | 24 ------ .../Entities/InternalItemsQuery.cs | 5 +- .../Entities/UserViewBuilder.cs | 43 ----------- .../MediaBrowser.Server.Implementations.csproj | 4 +- .../Persistence/SqliteItemRepository.cs | 89 +++++++++++++++++++++- .../packages.config | 2 +- 10 files changed, 95 insertions(+), 78 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/Reports/ReportsService.cs b/MediaBrowser.Api/Reports/ReportsService.cs index cb16158268..36a2a4b619 100644 --- a/MediaBrowser.Api/Reports/ReportsService.cs +++ b/MediaBrowser.Api/Reports/ReportsService.cs @@ -213,7 +213,6 @@ namespace MediaBrowser.Api.Reports NameStartsWith = request.NameStartsWith, NameStartsWithOrGreater = request.NameStartsWithOrGreater, HasImdbId = request.HasImdbId, - IsYearMismatched = request.IsYearMismatched, IsPlaceHolder = request.IsPlaceHolder, IsLocked = request.IsLocked, IsInBoxSet = request.IsInBoxSet, diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs index aee1a8d545..d27a560ba5 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs @@ -100,9 +100,6 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "HasTvdbId", Description = "Optional filter by items that have a tvdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? HasTvdbId { get; set; } - [ApiMember(Name = "IsYearMismatched", Description = "Optional filter by items that are potentially misidentified.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] - public bool? IsYearMismatched { get; set; } - [ApiMember(Name = "IsInBoxSet", Description = "Optional filter by items that are in boxsets, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? IsInBoxSet { get; set; } diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index dac1a6b1a8..644b284370 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -187,7 +187,6 @@ namespace MediaBrowser.Api.UserLibrary NameStartsWith = request.NameStartsWith, NameStartsWithOrGreater = request.NameStartsWithOrGreater, HasImdbId = request.HasImdbId, - IsYearMismatched = request.IsYearMismatched, IsPlaceHolder = request.IsPlaceHolder, IsLocked = request.IsLocked, IsInBoxSet = request.IsInBoxSet, diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 78f1828eaf..5101a9f289 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -75,6 +75,7 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the album. /// /// The album. + [IgnoreDataMember] public string Album { get; set; } /// diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 0d307c35bc..a4cbd34b2c 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -840,30 +840,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (query.HasImdbId.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasImdbId"); - return true; - } - - if (query.HasTmdbId.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasTmdbId"); - return true; - } - - if (query.HasTvdbId.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasTvdbId"); - return true; - } - - if (query.IsYearMismatched.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsYearMismatched"); - return true; - } - if (query.HasOfficialRating.HasValue) { Logger.Debug("Query requires post-filtering due to HasOfficialRating"); diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 0047a13b28..04dfc94912 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -64,7 +64,6 @@ namespace MediaBrowser.Controller.Entities public bool? IsInBoxSet { get; set; } public bool? IsLocked { get; set; } public bool? IsPlaceHolder { get; set; } - public bool? IsYearMismatched { get; set; } public bool? HasImdbId { get; set; } public bool? HasOverview { get; set; } @@ -141,6 +140,7 @@ namespace MediaBrowser.Controller.Entities public bool GroupByPresentationUniqueKey { get; set; } public bool EnableTotalRecordCount { get; set; } public bool ForceDirect { get; set; } + public Dictionary ExcludeProviderIds { get; set; } public InternalItemsQuery() { @@ -149,7 +149,8 @@ namespace MediaBrowser.Controller.Entities AlbumNames = new string[] { }; ArtistNames = new string[] { }; - + ExcludeProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); + BlockUnratedItems = new UnratedItem[] { }; Tags = new string[] { }; OfficialRatings = new string[] { }; diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 2bde80641d..655dff06aa 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -995,11 +995,6 @@ namespace MediaBrowser.Controller.Entities return false; } - if (request.IsYearMismatched.HasValue) - { - return false; - } - if (!string.IsNullOrWhiteSpace(request.Person)) { return false; @@ -1418,16 +1413,6 @@ namespace MediaBrowser.Controller.Entities } } - if (query.IsYearMismatched.HasValue) - { - var filterValue = query.IsYearMismatched.Value; - - if (IsYearMismatched(item, libraryManager) != filterValue) - { - return false; - } - } - if (query.HasOfficialRating.HasValue) { var filterValue = query.HasOfficialRating.Value; @@ -1979,34 +1964,6 @@ namespace MediaBrowser.Controller.Entities return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None); } - public static bool IsYearMismatched(BaseItem item, ILibraryManager libraryManager) - { - if (item.ProductionYear.HasValue) - { - var path = item.Path; - - if (!string.IsNullOrEmpty(path)) - { - var info = libraryManager.ParseName(Path.GetFileName(path)); - var yearInName = info.Year; - - // Go up a level if we didn't get a year - if (!yearInName.HasValue) - { - info = libraryManager.ParseName(Path.GetFileName(Path.GetDirectoryName(path))); - yearInName = info.Year; - } - - if (yearInName.HasValue) - { - return yearInName.Value != item.ProductionYear.Value; - } - } - } - - return false; - } - public static IEnumerable FilterForAdjacency(IEnumerable items, string adjacentToId) { var list = items.ToList(); diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 0df6c338c5..5b3419639e 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -56,8 +56,8 @@ ..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll - - ..\packages\MediaBrowser.Naming.1.0.0.50\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll + + ..\packages\MediaBrowser.Naming.1.0.0.51\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll True diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index c00c4bf300..a67f7b675f 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -85,10 +85,13 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _deleteItemValuesCommand; private IDbCommand _saveItemValuesCommand; + private IDbCommand _deleteProviderIdsCommand; + private IDbCommand _saveProviderIdsCommand; + private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - public const int LatestSchemaVersion = 82; + public const int LatestSchemaVersion = 83; /// /// Initializes a new instance of the class. @@ -143,6 +146,9 @@ namespace MediaBrowser.Server.Implementations.Persistence "create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT)", "create index if not exists idx_ItemValues on ItemValues(ItemId)", + "create table if not exists ProviderIds (ItemId GUID, Name TEXT, Value TEXT)", + "create index if not exists Idx_ProviderIds on ProviderIds(ItemId)", + "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)", "create index if not exists idxPeopleItemId on People(ItemId)", "create index if not exists idxPeopleName on People(Name)", @@ -548,6 +554,17 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Type"); _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Value"); + // provider ids + _deleteProviderIdsCommand = _connection.CreateCommand(); + _deleteProviderIdsCommand.CommandText = "delete from ProviderIds where ItemId=@Id"; + _deleteProviderIdsCommand.Parameters.Add(_deleteProviderIdsCommand, "@Id"); + + _saveProviderIdsCommand = _connection.CreateCommand(); + _saveProviderIdsCommand.CommandText = "insert into ProviderIds (ItemId, Name, Value) values (@ItemId, @Name, @Value)"; + _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@ItemId"); + _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Name"); + _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Value"); + } /// @@ -862,6 +879,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), transaction); + UpdateProviderIds(item.Id, item.ProviderIds, transaction); UpdateItemValues(item.Id, GetItemValues(item), transaction); } @@ -1635,6 +1653,8 @@ namespace MediaBrowser.Server.Implementations.Persistence var excludeIds = query.ExcludeItemIds.ToList(); excludeIds.Add(item.Id.ToString("N")); query.ExcludeItemIds = excludeIds.ToArray(); + + query.ExcludeProviderIds = item.ProviderIds; } return list.ToArray(); @@ -2711,6 +2731,37 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add(string.Join(" AND ", excludeIds.ToArray())); } + if (query.ExcludeProviderIds.Count > 0) + { + var excludeIds = new List(); + + var index = 0; + foreach (var pair in query.ExcludeProviderIds) + { + var paramName = "@ExcludeProviderId" + index; + excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Imdb'), '') <> "+ paramName + ")"); + cmd.Parameters.Add(cmd, paramName, DbType.String).Value = pair.Value; + index++; + } + + whereClauses.Add(string.Join(" AND ", excludeIds.ToArray())); + } + + if (query.HasImdbId.HasValue) + { + whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Imdb'), '') <> '')"); + } + + if (query.HasTmdbId.HasValue) + { + whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Tmdb'), '') <> '')"); + } + + if (query.HasTvdbId.HasValue) + { + whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Tvdb'), '') <> '')"); + } + if (query.AlbumNames.Length > 0) { var clause = "("; @@ -3121,6 +3172,11 @@ namespace MediaBrowser.Server.Implementations.Persistence _deleteItemValuesCommand.Transaction = transaction; _deleteItemValuesCommand.ExecuteNonQuery(); + // Delete provider ids + _deleteProviderIdsCommand.GetParameter(0).Value = id; + _deleteProviderIdsCommand.Transaction = transaction; + _deleteProviderIdsCommand.ExecuteNonQuery(); + // Delete the item _deleteItemCommand.GetParameter(0).Value = id; _deleteItemCommand.Transaction = transaction; @@ -3337,6 +3393,37 @@ namespace MediaBrowser.Server.Implementations.Persistence return list; } + private void UpdateProviderIds(Guid itemId, Dictionary values, IDbTransaction transaction) + { + if (itemId == Guid.Empty) + { + throw new ArgumentNullException("itemId"); + } + + if (values == null) + { + throw new ArgumentNullException("keys"); + } + + CheckDisposed(); + + // First delete + _deleteProviderIdsCommand.GetParameter(0).Value = itemId; + _deleteProviderIdsCommand.Transaction = transaction; + + _deleteProviderIdsCommand.ExecuteNonQuery(); + + foreach (var pair in values) + { + _saveProviderIdsCommand.GetParameter(0).Value = itemId; + _saveProviderIdsCommand.GetParameter(1).Value = pair.Key; + _saveProviderIdsCommand.GetParameter(2).Value = pair.Value; + _saveProviderIdsCommand.Transaction = transaction; + + _saveProviderIdsCommand.ExecuteNonQuery(); + } + } + private void UpdateItemValues(Guid itemId, List> values, IDbTransaction transaction) { if (itemId == Guid.Empty) diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 9d1aa2c33e..516bf32716 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -4,7 +4,7 @@ - + -- cgit v1.2.3 From e50a74e35b5e3749f2a76e4a823441d64a34becd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Jun 2016 00:43:13 -0400 Subject: update provider id queries --- .../Persistence/SqliteItemRepository.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index a67f7b675f..13f7a0d379 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -2739,7 +2739,7 @@ namespace MediaBrowser.Server.Implementations.Persistence foreach (var pair in query.ExcludeProviderIds) { var paramName = "@ExcludeProviderId" + index; - excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Imdb'), '') <> "+ paramName + ")"); + excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Imdb'), '') <> " + paramName + ")"); cmd.Parameters.Add(cmd, paramName, DbType.String).Value = pair.Value; index++; } @@ -2749,17 +2749,20 @@ namespace MediaBrowser.Server.Implementations.Persistence if (query.HasImdbId.HasValue) { - whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Imdb'), '') <> '')"); + var fn = query.HasImdbId.Value ? "<>" : "="; + whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Imdb'), '') " + fn + " '')"); } if (query.HasTmdbId.HasValue) { - whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Tmdb'), '') <> '')"); + var fn = query.HasTmdbId.Value ? "<>" : "="; + whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Tmdb'), '') " + fn + " '')"); } if (query.HasTvdbId.HasValue) { - whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Tvdb'), '') <> '')"); + var fn = query.HasTvdbId.Value ? "<>" : "="; + whereClauses.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Tvdb'), '') " + fn + " '')"); } if (query.AlbumNames.Length > 0) @@ -3393,7 +3396,7 @@ namespace MediaBrowser.Server.Implementations.Persistence return list; } - private void UpdateProviderIds(Guid itemId, Dictionary values, IDbTransaction transaction) + private void UpdateProviderIds(Guid itemId, Dictionary values, IDbTransaction transaction) { if (itemId == Guid.Empty) { -- cgit v1.2.3 From 85c508bcd1e09355b9881bdc243c511e81bc621c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Jun 2016 12:17:35 -0400 Subject: update provider setting --- .../Persistence/SqliteItemRepository.cs | 5 ++--- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 13f7a0d379..494e1b12f3 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - public const int LatestSchemaVersion = 83; + public const int LatestSchemaVersion = 84; /// /// Initializes a new instance of the class. @@ -132,7 +132,6 @@ namespace MediaBrowser.Server.Implementations.Persistence string[] queries = { "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID, Path TEXT)", - "create index if not exists idx_TypedBaseItems on TypedBaseItems(guid)", "create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)", "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)", @@ -146,7 +145,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT)", "create index if not exists idx_ItemValues on ItemValues(ItemId)", - "create table if not exists ProviderIds (ItemId GUID, Name TEXT, Value TEXT)", + "create table if not exists ProviderIds (ItemId GUID, Name TEXT, Value TEXT, PRIMARY KEY (ItemId, Name))", "create index if not exists Idx_ProviderIds on ProviderIds(ItemId)", "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)", diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index d528686db8..1d860ed29f 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -137,9 +137,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest -- cgit v1.2.3 From 05acd63f8f0019e46ea57ab895bf54372c14161b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Jun 2016 15:32:15 -0400 Subject: add people to similar queries --- .../Persistence/SqliteExtensions.cs | 59 +++++++++------------- .../Persistence/SqliteItemRepository.cs | 6 ++- 2 files changed, 28 insertions(+), 37 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index 5e07bac310..b819fb9790 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -5,6 +5,8 @@ using System.Data.SQLite; using System.Linq; using System.Text; using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; namespace MediaBrowser.Server.Implementations.Persistence @@ -48,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.Persistence public static void BindGetSimilarityScore(IDbConnection connection, ILogger logger) { - var sqlConnection = (SQLiteConnection) connection; + var sqlConnection = (SQLiteConnection)connection; SimiliarToFunction.Logger = logger; sqlConnection.BindFunction(new SimiliarToFunction()); } @@ -64,11 +66,23 @@ namespace MediaBrowser.Server.Implementations.Persistence } } - [SQLiteFunction(Name = "GetSimilarityScore", Arguments = 12, FuncType = FunctionType.Scalar)] + [SQLiteFunction(Name = "GetSimilarityScore", Arguments = 13, FuncType = FunctionType.Scalar)] public class SimiliarToFunction : SQLiteFunction { internal static ILogger Logger; + private readonly Dictionary _personTypeScores = new Dictionary(StringComparer.OrdinalIgnoreCase) + { + { PersonType.Actor, 3}, + { PersonType.Director, 5}, + { PersonType.Composer, 2}, + { PersonType.GuestStar, 3}, + { PersonType.Writer, 2}, + { PersonType.Conductor, 2}, + { PersonType.Producer, 2}, + { PersonType.Lyricist, 2} + }; + public override object Invoke(object[] args) { var score = 0; @@ -112,41 +126,14 @@ namespace MediaBrowser.Server.Implementations.Persistence // studios score += GetListScore(args, 10, 11, 3); + var rowPeopleNamesText = (args[12] as string) ?? string.Empty; + var rowPeopleNames = rowPeopleNamesText.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); - // TODO: People - // var item2PeopleNames = allPeople.Where(i => i.ItemId == item2.Id) - //.Select(i => i.Name) - //.Where(i => !string.IsNullOrWhiteSpace(i)) - //.DistinctNames() - //.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); - - // points += item1People.Where(i => item2PeopleNames.ContainsKey(i.Name)).Sum(i => - // { - // if (string.Equals(i.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Director, StringComparison.OrdinalIgnoreCase)) - // { - // return 5; - // } - // if (string.Equals(i.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Actor, StringComparison.OrdinalIgnoreCase)) - // { - // return 3; - // } - // if (string.Equals(i.Type, PersonType.Composer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Composer, StringComparison.OrdinalIgnoreCase)) - // { - // return 3; - // } - // if (string.Equals(i.Type, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase)) - // { - // return 3; - // } - // if (string.Equals(i.Type, PersonType.Writer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase)) - // { - // return 2; - // } - - // return 1; - // }); - - // return points; + foreach (var name in rowPeopleNames) + { + // TODO: Send along person types + score += 3; + } //Logger.Debug("Returning score {0}", score); return score; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 494e1b12f3..bf50f9a0e4 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1638,7 +1638,10 @@ namespace MediaBrowser.Server.Implementations.Persistence builder.Append("(select group_concat((Select Value from ItemValues where ItemId=Guid and Type=5), '|')),"); builder.Append("@ItemStudios,"); - builder.Append("Studios"); + builder.Append("Studios,"); + + builder.Append("(select group_concat((Select Name from People where ItemId=Guid and Name in (Select Name from People where ItemId=@SimilarItemId)), '|'))"); + builder.Append(") as SimilarityScore"); list.Add(builder.ToString()); @@ -1648,6 +1651,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.Parameters.Add(cmd, "@ItemTags", DbType.String).Value = string.Join("|", item.Tags.ToArray()); cmd.Parameters.Add(cmd, "@ItemKeywords", DbType.String).Value = string.Join("|", item.Keywords.ToArray()); cmd.Parameters.Add(cmd, "@ItemStudios", DbType.String).Value = string.Join("|", item.Studios.ToArray()); + cmd.Parameters.Add(cmd, "@SimilarItemId", DbType.Guid).Value = item.Id; var excludeIds = query.ExcludeItemIds.ToList(); excludeIds.Add(item.Id.ToString("N")); -- cgit v1.2.3 From 53afb1e1e54a383f9fdda9b9c5fb21a6af50962e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 3 Jun 2016 12:24:04 -0400 Subject: add images table --- MediaBrowser.Api/StartupWizardService.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 6 - .../Configuration/UserConfiguration.cs | 3 +- MediaBrowser.Model/Entities/ImageType.cs | 24 ++-- .../FileOrganization/EpisodeFileOrganizer.cs | 7 +- .../Persistence/SqliteExtensions.cs | 43 +++---- .../Persistence/SqliteItemRepository.cs | 132 +++++++++++++++++---- 7 files changed, 150 insertions(+), 67 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 8bb840697e..0a8d39ee5c 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -113,7 +113,7 @@ namespace MediaBrowser.Api config.EnableCustomPathSubFolders = true; config.EnableStandaloneMusicKeys = true; config.EnableCaseSensitiveItemIds = true; - config.SchemaVersion = 79; + config.SchemaVersion = 87; } public void Post(UpdateStartupConfiguration request) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index ba94c99d2a..2cec15d511 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -889,12 +889,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (query.ImageTypes.Length > 0) - { - Logger.Debug("Query requires post-filtering due to ImageTypes"); - return true; - } - // Apply studio filter if (query.StudioIds.Length > 0) { diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 6195e3e70f..69dc23b21c 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -48,7 +48,8 @@ namespace MediaBrowser.Model.Configuration public bool RememberAudioSelections { get; set; } public bool RememberSubtitleSelections { get; set; } public bool EnableNextEpisodeAutoPlay { get; set; } - + public bool DisplayFoldersView { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.Model/Entities/ImageType.cs b/MediaBrowser.Model/Entities/ImageType.cs index 18097abb44..6e0ba717f0 100644 --- a/MediaBrowser.Model/Entities/ImageType.cs +++ b/MediaBrowser.Model/Entities/ImageType.cs @@ -9,50 +9,50 @@ namespace MediaBrowser.Model.Entities /// /// The primary /// - Primary, + Primary = 0, /// /// The art /// - Art, + Art = 1, /// /// The backdrop /// - Backdrop, + Backdrop = 2, /// /// The banner /// - Banner, + Banner = 3, /// /// The logo /// - Logo, + Logo = 4, /// /// The thumb /// - Thumb, + Thumb = 5, /// /// The disc /// - Disc, + Disc = 6, /// /// The box /// - Box, + Box = 7, /// /// The screenshot /// - Screenshot, + Screenshot = 8, /// /// The menu /// - Menu, + Menu = 9, /// /// The chapter image /// - Chapter, + Chapter = 10, /// /// The box rear /// - BoxRear + BoxRear = 11 } } diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 83801b3e76..2109f8d59e 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -562,9 +562,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization series = _libraryManager.GetItemList(new Controller.Entities.InternalItemsQuery { IncludeItemTypes = new[] { typeof(Series).Name }, - Recursive = true - }).Cast() - .FirstOrDefault(i => string.Equals(i.Name, info.ItemName, StringComparison.OrdinalIgnoreCase)); + Recursive = true, + Name = info.ItemName + + }).Cast().FirstOrDefault(); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index b819fb9790..519731a5cc 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -66,7 +66,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } } - [SQLiteFunction(Name = "GetSimilarityScore", Arguments = 13, FuncType = FunctionType.Scalar)] + [SQLiteFunction(Name = "GetSimilarityScore", Arguments = 6, FuncType = FunctionType.Scalar)] public class SimiliarToFunction : SQLiteFunction { internal static ILogger Logger; @@ -87,19 +87,17 @@ namespace MediaBrowser.Server.Implementations.Persistence { var score = 0; - var inputOfficialRating = args[0] as string; - var rowOfficialRating = args[1] as string; - if (!string.IsNullOrWhiteSpace(inputOfficialRating) && string.Equals(inputOfficialRating, rowOfficialRating)) + // Official rating equals + if ((long)args[0] == 1) { score += 10; } - long? inputYear = args[2] == null ? (long?)null : (long)args[2]; - long? rowYear = args[3] == null ? (long?)null : (long)args[3]; - - if (inputYear.HasValue && rowYear.HasValue) + // Year difference + long? yearDifference = args[1] == null ? (long?)null : (long)args[1]; + if (yearDifference.HasValue) { - var diff = Math.Abs(inputYear.Value - rowYear.Value); + var diff = Math.Abs(yearDifference.Value); // Add if they came out within the same decade if (diff < 10) @@ -115,25 +113,28 @@ namespace MediaBrowser.Server.Implementations.Persistence } // genres - score += GetListScore(args, 4, 5); + score += Convert.ToInt32((long)args[2]) * 10; // tags - score += GetListScore(args, 6, 7); + score += Convert.ToInt32((long)args[3]) * 10; + + // # of common keywords + score += Convert.ToInt32((long)args[4]) *10; - // keywords - score += GetListScore(args, 8, 9); + // # of common studios + score += Convert.ToInt32((long)args[5]) * 3; // studios - score += GetListScore(args, 10, 11, 3); + //score += GetListScore(args, 7, 8, 3); - var rowPeopleNamesText = (args[12] as string) ?? string.Empty; - var rowPeopleNames = rowPeopleNamesText.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + //var rowPeopleNamesText = (args[12] as string) ?? string.Empty; + //var rowPeopleNames = rowPeopleNamesText.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); - foreach (var name in rowPeopleNames) - { - // TODO: Send along person types - score += 3; - } + //foreach (var name in rowPeopleNames) + //{ + // // TODO: Send along person types + // score += 3; + //} //Logger.Debug("Returning score {0}", score); return score; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index bf50f9a0e4..9f827c553a 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -88,10 +88,13 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _deleteProviderIdsCommand; private IDbCommand _saveProviderIdsCommand; + private IDbCommand _deleteImagesCommand; + private IDbCommand _saveImagesCommand; + private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - public const int LatestSchemaVersion = 84; + public const int LatestSchemaVersion = 87; /// /// Initializes a new instance of the class. @@ -144,10 +147,14 @@ namespace MediaBrowser.Server.Implementations.Persistence "create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT)", "create index if not exists idx_ItemValues on ItemValues(ItemId)", + "create index if not exists idx_ItemValues2 on ItemValues(ItemId,Type)", "create table if not exists ProviderIds (ItemId GUID, Name TEXT, Value TEXT, PRIMARY KEY (ItemId, Name))", "create index if not exists Idx_ProviderIds on ProviderIds(ItemId)", + "create table if not exists Images (ItemId GUID NOT NULL, Path TEXT NOT NULL, ImageType INT NOT NULL, DateModified DATETIME, IsPlaceHolder BIT NOT NULL, SortOrder INT)", + "create index if not exists idx_Images on Images(ItemId)", + "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)", "create index if not exists idxPeopleItemId on People(ItemId)", "create index if not exists idxPeopleName on People(Name)", @@ -564,6 +571,19 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Name"); _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Value"); + // images + _deleteImagesCommand = _connection.CreateCommand(); + _deleteImagesCommand.CommandText = "delete from Images where ItemId=@Id"; + _deleteImagesCommand.Parameters.Add(_deleteImagesCommand, "@Id"); + + _saveImagesCommand = _connection.CreateCommand(); + _saveImagesCommand.CommandText = "insert into Images (ItemId, ImageType, Path, DateModified, IsPlaceHolder, SortOrder) values (@ItemId, @ImageType, @Path, @DateModified, @IsPlaceHolder, @SortOrder)"; + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ItemId"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ImageType"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@Path"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@DateModified"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@IsPlaceHolder"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@SortOrder"); } /// @@ -878,6 +898,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), transaction); + UpdateImages(item.Id, item.ImageInfos, transaction); UpdateProviderIds(item.Id, item.ProviderIds, transaction); UpdateItemValues(item.Id, GetItemValues(item), transaction); } @@ -1620,37 +1641,33 @@ namespace MediaBrowser.Server.Implementations.Persistence var item = query.SimilarTo; var builder = new StringBuilder(); - builder.Append("GetSimilarityScore("); + builder.Append("("); + + builder.Append("((OfficialRating=@ItemOfficialRating) * 10)"); + //builder.Append("+ ((ProductionYear=@ItemProductionYear) * 10)"); - builder.Append("@ItemOfficialRating,"); - builder.Append("OfficialRating,"); + builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 10 Then 2 Else 0 End )"); + builder.Append("+(Select Case When Abs(COALESCE(ProductionYear, 0) - @ItemProductionYear) < 5 Then 2 Else 0 End )"); - builder.Append("@ItemProductionYear,"); - builder.Append("ProductionYear,"); + //// genres + builder.Append("+ ((Select count(value) from ItemValues where ItemId=Guid and Type=2 and value in (select value from itemvalues where ItemId=@SimilarItemId and type=2)) * 10)"); - builder.Append("@ItemGenres,"); - builder.Append("Genres,"); + //// tags + builder.Append("+ ((Select count(value) from ItemValues where ItemId=Guid and Type=4 and value in (select value from itemvalues where ItemId=@SimilarItemId and type=4)) * 10)"); - builder.Append("@ItemTags,"); - builder.Append("Tags,"); + builder.Append("+ ((Select count(value) from ItemValues where ItemId=Guid and Type=5 and value in (select value from itemvalues where ItemId=@SimilarItemId and type=5)) * 10)"); - builder.Append("@ItemKeywords,"); - builder.Append("(select group_concat((Select Value from ItemValues where ItemId=Guid and Type=5), '|')),"); + builder.Append("+ ((Select count(value) from ItemValues where ItemId=Guid and Type=3 and value in (select value from itemvalues where ItemId=@SimilarItemId and type=3)) * 3)"); - builder.Append("@ItemStudios,"); - builder.Append("Studios,"); + //builder.Append("+ ((Select count(Name) from People where ItemId=Guid and Name in (select Name from People where ItemId=@SimilarItemId)) * 3)"); - builder.Append("(select group_concat((Select Name from People where ItemId=Guid and Name in (Select Name from People where ItemId=@SimilarItemId)), '|'))"); + ////builder.Append("(select group_concat((Select Name from People where ItemId=Guid and Name in (Select Name from People where ItemId=@SimilarItemId)), '|'))"); builder.Append(") as SimilarityScore"); list.Add(builder.ToString()); cmd.Parameters.Add(cmd, "@ItemOfficialRating", DbType.String).Value = item.OfficialRating; - cmd.Parameters.Add(cmd, "@ItemProductionYear", DbType.Int32).Value = item.ProductionYear ?? -1; - cmd.Parameters.Add(cmd, "@ItemGenres", DbType.String).Value = string.Join("|", item.Genres.ToArray()); - cmd.Parameters.Add(cmd, "@ItemTags", DbType.String).Value = string.Join("|", item.Tags.ToArray()); - cmd.Parameters.Add(cmd, "@ItemKeywords", DbType.String).Value = string.Join("|", item.Keywords.ToArray()); - cmd.Parameters.Add(cmd, "@ItemStudios", DbType.String).Value = string.Join("|", item.Studios.ToArray()); + cmd.Parameters.Add(cmd, "@ItemProductionYear", DbType.Int32).Value = item.ProductionYear ?? 0; cmd.Parameters.Add(cmd, "@SimilarItemId", DbType.Guid).Value = item.Id; var excludeIds = query.ExcludeItemIds.ToList(); @@ -1865,7 +1882,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { if (query.User != null) { - query.SortBy = new[] { "SimilarityScore", "IsUnplayed", "Random" }; + query.SortBy = new[] { "SimilarityScore", "IsPlayed", "Random" }; } else { @@ -2478,6 +2495,19 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.Parameters.Add(cmd, "@NameLessThan", DbType.String).Value = query.NameLessThan.ToLower(); } + if (query.ImageTypes.Length > 0 && _config.Configuration.SchemaVersion >= 87) + { + var requiredImageIndex = 0; + + foreach (var requiredImage in query.ImageTypes) + { + var paramName = "@RequiredImageType" + requiredImageIndex; + whereClauses.Add("(select path from images where ItemId=Guid and ImageType=" + paramName + " limit 1) not null"); + cmd.Parameters.Add(cmd, paramName, DbType.Int32).Value = (int)requiredImage; + requiredImageIndex++; + } + } + if (query.IsLiked.HasValue) { if (query.IsLiked.Value) @@ -2741,8 +2771,13 @@ namespace MediaBrowser.Server.Implementations.Persistence var index = 0; foreach (var pair in query.ExcludeProviderIds) { + if (string.Equals(pair.Key, MetadataProviders.TmdbCollection.ToString(), StringComparison.OrdinalIgnoreCase)) + { + continue; + } + var paramName = "@ExcludeProviderId" + index; - excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = 'Imdb'), '') <> " + paramName + ")"); + excludeIds.Add("(COALESCE((select value from ProviderIds where ItemId=Guid and Name = '" + pair.Key + "'), '') <> " + paramName + ")"); cmd.Parameters.Add(cmd, paramName, DbType.String).Value = pair.Value; index++; } @@ -3183,6 +3218,11 @@ namespace MediaBrowser.Server.Implementations.Persistence _deleteProviderIdsCommand.Transaction = transaction; _deleteProviderIdsCommand.ExecuteNonQuery(); + // Delete images + _deleteImagesCommand.GetParameter(0).Value = id; + _deleteImagesCommand.Transaction = transaction; + _deleteImagesCommand.ExecuteNonQuery(); + // Delete the item _deleteItemCommand.GetParameter(0).Value = id; _deleteItemCommand.Transaction = transaction; @@ -3399,6 +3439,52 @@ namespace MediaBrowser.Server.Implementations.Persistence return list; } + private void UpdateImages(Guid itemId, List images, IDbTransaction transaction) + { + if (itemId == Guid.Empty) + { + throw new ArgumentNullException("itemId"); + } + + if (images == null) + { + throw new ArgumentNullException("images"); + } + + CheckDisposed(); + + // First delete + _deleteImagesCommand.GetParameter(0).Value = itemId; + _deleteImagesCommand.Transaction = transaction; + + _deleteImagesCommand.ExecuteNonQuery(); + + var index = 0; + foreach (var image in images) + { + _saveImagesCommand.GetParameter(0).Value = itemId; + _saveImagesCommand.GetParameter(1).Value = image.Type; + _saveImagesCommand.GetParameter(2).Value = image.Path; + + if (image.DateModified == default(DateTime)) + { + _saveImagesCommand.GetParameter(3).Value = null; + } + else + { + _saveImagesCommand.GetParameter(3).Value = image.DateModified; + } + + _saveImagesCommand.GetParameter(4).Value = image.IsPlaceholder; + _saveImagesCommand.GetParameter(5).Value = index; + + _saveImagesCommand.Transaction = transaction; + + _saveImagesCommand.ExecuteNonQuery(); + index++; + } + } + private void UpdateProviderIds(Guid itemId, Dictionary values, IDbTransaction transaction) { if (itemId == Guid.Empty) @@ -3408,7 +3494,7 @@ namespace MediaBrowser.Server.Implementations.Persistence if (values == null) { - throw new ArgumentNullException("keys"); + throw new ArgumentNullException("values"); } CheckDisposed(); -- cgit v1.2.3 From ddb6ea6f0576a6ba9c6050cc0799ac6b0e3c2fa8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 3 Jun 2016 20:15:14 -0400 Subject: rework user data --- MediaBrowser.Controller/Entities/Folder.cs | 69 +-------------- MediaBrowser.Controller/Entities/TV/Episode.cs | 8 +- MediaBrowser.Controller/Entities/TV/Season.cs | 49 ++--------- MediaBrowser.Controller/Entities/TV/Series.cs | 45 ++++++---- .../Persistence/IUserDataRepository.cs | 2 + .../Library/UserDataManager.cs | 98 ++++++---------------- .../Persistence/SqliteUserDataRepository.cs | 48 +++++++++++ .../TV/TVSeriesManager.cs | 40 ++++----- 8 files changed, 138 insertions(+), 221 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 2cec15d511..2e4cf3745e 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -164,49 +164,15 @@ namespace MediaBrowser.Controller.Entities item.DateModified = DateTime.UtcNow; } - AddChildInternal(item.Id); - await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); } - protected void AddChildrenInternal(List children) - { - lock (_childrenSyncLock) - { - var newChildren = ChildIds.ToList(); - newChildren.AddRange(children); - _children = newChildren.ToList(); - } - } - protected void AddChildInternal(Guid child) - { - lock (_childrenSyncLock) - { - var childIds = ChildIds.ToList(); - if (!childIds.Contains(child)) - { - childIds.Add(child); - _children = childIds.ToList(); - } - } - } - - protected void RemoveChildrenInternal(List children) - { - lock (_childrenSyncLock) - { - _children = ChildIds.Except(children).ToList(); - } - } - /// /// Removes the child. /// /// The item. public void RemoveChild(BaseItem item) { - RemoveChildrenInternal(new[] { item.Id }.ToList()); - item.SetParent(null); } @@ -241,33 +207,6 @@ namespace MediaBrowser.Controller.Entities #endregion - /// - /// The children - /// - private IReadOnlyList _children; - /// - /// The _children sync lock - /// - private readonly object _childrenSyncLock = new object(); - /// - /// Gets or sets the actual children. - /// - /// The actual children. - protected virtual IEnumerable ChildIds - { - get - { - lock (_childrenSyncLock) - { - if (_children == null) - { - _children = LoadChildren().ToList(); - } - return _children.ToList(); - } - } - } - /// /// Gets the actual children. /// @@ -277,7 +216,7 @@ namespace MediaBrowser.Controller.Entities { get { - return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null); + return LoadChildren().Select(LibraryManager.GetItemById).Where(i => i != null); } } @@ -479,8 +418,6 @@ namespace MediaBrowser.Controller.Entities if (actualRemovals.Count > 0) { - RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList()); - foreach (var item in actualRemovals) { Logger.Debug("Removed item: " + item.Path); @@ -493,8 +430,6 @@ namespace MediaBrowser.Controller.Entities } await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false); - - AddChildrenInternal(newItems.Select(i => i.Id).ToList()); } } @@ -766,7 +701,7 @@ namespace MediaBrowser.Controller.Entities { if (!(this is ICollectionFolder)) { - Logger.Debug("Query requires post-filtering due to LinkedChildren"); + Logger.Debug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name); return true; } } diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 7ca09d9b28..2dc459239d 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -108,7 +108,13 @@ namespace MediaBrowser.Controller.Entities.TV var series = Series; if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue) { - list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"))); + var seriesUserDataKeys = series.GetUserDataKeys(); + var take = seriesUserDataKeys.Count; + if (seriesUserDataKeys.Count > 1) + { + take--; + } + list.InsertRange(0, seriesUserDataKeys.Take(take).Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"))); } return list; diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 7fa1b55dea..f07d4be13e 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -196,52 +196,17 @@ namespace MediaBrowser.Controller.Entities.TV { var config = user.Configuration; - return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); + return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } - public IEnumerable GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) + public IEnumerable GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) { - var series = Series; - - if (IndexNumber.HasValue && series != null) - { - return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes); - } - - var episodes = GetRecursiveChildren(user) - .OfType(); - - if (series != null && series.ContainsEpisodesWithoutSeasonFolders) - { - var seasonNumber = IndexNumber; - var list = episodes.ToList(); - - if (seasonNumber.HasValue) - { - list.AddRange(series.GetRecursiveChildren(user).OfType() - .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value)); - } - else - { - list.AddRange(series.GetRecursiveChildren(user).OfType() - .Where(i => !i.ParentIndexNumber.HasValue)); - } - - episodes = list.DistinctBy(i => i.Id); - } - - if (!includeMissingEpisodes) - { - episodes = episodes.Where(i => !i.IsMissingEpisode); - } - if (!includeVirtualUnairedEpisodes) - { - episodes = episodes.Where(i => !i.IsVirtualUnaired); - } + return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null); + } - return LibraryManager - .Sort(episodes, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending) - .Cast(); + public IEnumerable GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable allSeriesEpisodes) + { + return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes); } public IEnumerable GetEpisodes() diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 600ea173a2..bbb9b30196 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -183,24 +183,20 @@ namespace MediaBrowser.Controller.Entities.TV protected override Task> GetItemsInternal(InternalItemsQuery query) { + if (query.User == null) + { + return base.GetItemsInternal(query); + } + var user = query.User; Func filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); IEnumerable items; - if (query.User == null) - { - items = query.Recursive - ? GetRecursiveChildren(filter) - : Children.Where(filter); - } - else - { - items = query.Recursive - ? GetSeasons(user).Cast().Concat(GetEpisodes(user)).Where(filter) - : GetSeasons(user).Where(filter); - } + items = query.Recursive + ? GetSeasons(user).Cast().Concat(GetEpisodes(user)).Where(filter) + : GetSeasons(user).Where(filter); var result = PostFilterAndSort(items, query); @@ -260,8 +256,10 @@ namespace MediaBrowser.Controller.Entities.TV public IEnumerable GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired) { + var allSeriesEpisodes = GetAllEpisodes(user).ToList(); + var allEpisodes = GetSeasons(user, true, true) - .SelectMany(i => i.GetEpisodes(user, includeMissing, includeVirtualUnaired)) + .SelectMany(i => i.GetEpisodes(this, user, includeMissing, includeVirtualUnaired, allSeriesEpisodes)) .Reverse() .ToList(); @@ -350,7 +348,7 @@ namespace MediaBrowser.Controller.Entities.TV return false; } - public IEnumerable GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) + private IEnumerable GetAllEpisodes(User user) { IEnumerable episodes; @@ -388,7 +386,24 @@ namespace MediaBrowser.Controller.Entities.TV }).Cast(); } - episodes = FilterEpisodesBySeason(episodes, parentSeason, DisplaySpecialsWithSeasons); + return episodes; + } + + public IEnumerable GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) + { + IEnumerable episodes = GetAllEpisodes(user); + + return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes); + } + + public IEnumerable GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable allSeriesEpisodes) + { + if (allSeriesEpisodes == null) + { + return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes); + } + + var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, DisplaySpecialsWithSeasons); if (!includeMissingEpisodes) { diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs index 2e165f4163..ca4dc97513 100644 --- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs +++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs @@ -29,6 +29,8 @@ namespace MediaBrowser.Controller.Persistence /// Task{UserItemData}. UserItemData GetUserData(Guid userId, string key); + UserItemData GetUserData(Guid userId, List keys); + /// /// Return all user data associated with the given user /// diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs index afbce87a9f..c2606dc4b2 100644 --- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs @@ -23,7 +23,8 @@ namespace MediaBrowser.Server.Implementations.Library { public event EventHandler UserDataSaved; - private readonly Dictionary _userData = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary _userData = + new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private readonly ILogger _logger; private readonly IServerConfigurationManager _config; @@ -64,13 +65,6 @@ namespace MediaBrowser.Server.Implementations.Library try { await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); - - var newValue = userData; - - lock (_userData) - { - _userData[GetCacheKey(userId, key)] = newValue; - } } catch (Exception ex) { @@ -80,6 +74,9 @@ namespace MediaBrowser.Server.Implementations.Library } } + var cacheKey = GetCacheKey(userId, item.Id); + _userData.AddOrUpdate(cacheKey, userData, (k, v) => userData); + EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs { Keys = keys, @@ -122,7 +119,7 @@ namespace MediaBrowser.Server.Implementations.Library throw; } - + } /// @@ -140,7 +137,7 @@ namespace MediaBrowser.Server.Implementations.Library return Repository.GetAllUserData(userId); } - public UserItemData GetUserData(Guid userId, List keys) + public UserItemData GetUserData(Guid userId, Guid itemId, List keys) { if (userId == Guid.Empty) { @@ -150,26 +147,23 @@ namespace MediaBrowser.Server.Implementations.Library { throw new ArgumentNullException("keys"); } - - lock (_userData) + if (keys.Count == 0) { - foreach (var key in keys) - { - var cacheKey = GetCacheKey(userId, key); - UserItemData value; - if (_userData.TryGetValue(cacheKey, out value)) - { - return value; - } + throw new ArgumentException("UserData keys cannot be empty."); + } - value = Repository.GetUserData(userId, key); + var cacheKey = GetCacheKey(userId, itemId); - if (value != null) - { - _userData[cacheKey] = value; - return value; - } - } + return _userData.GetOrAdd(cacheKey, k => GetUserDataInternal(userId, keys)); + } + + private UserItemData GetUserDataInternal(Guid userId, List keys) + { + var userData = Repository.GetUserData(userId, keys); + + if (userData != null) + { + return userData; } if (keys.Count > 0) @@ -184,57 +178,13 @@ namespace MediaBrowser.Server.Implementations.Library return null; } - /// - /// Gets the user data. - /// - /// The user id. - /// The key. - /// Task{UserItemData}. - public UserItemData GetUserData(Guid userId, string key) - { - if (userId == Guid.Empty) - { - throw new ArgumentNullException("userId"); - } - if (string.IsNullOrEmpty(key)) - { - throw new ArgumentNullException("key"); - } - - lock (_userData) - { - var cacheKey = GetCacheKey(userId, key); - UserItemData value; - if (_userData.TryGetValue(cacheKey, out value)) - { - return value; - } - - value = Repository.GetUserData(userId, key); - - if (value == null) - { - value = new UserItemData - { - UserId = userId, - Key = key - }; - } - - _userData[cacheKey] = value; - return value; - } - } - /// /// Gets the internal key. /// - /// The user id. - /// The key. /// System.String. - private string GetCacheKey(Guid userId, string key) + private string GetCacheKey(Guid userId, Guid itemId) { - return userId + key; + return userId.ToString("N") + itemId.ToString("N"); } public UserItemData GetUserData(IHasUserData user, IHasUserData item) @@ -249,7 +199,7 @@ namespace MediaBrowser.Server.Implementations.Library public UserItemData GetUserData(Guid userId, IHasUserData item) { - return GetUserData(userId, item.GetUserDataKeys()); + return GetUserData(userId, item.Id, item.GetUserDataKeys()); } public UserItemDataDto GetUserDataDto(IHasUserData item, User user) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index 7f3b32e062..bfdb9e0c7a 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -5,7 +5,9 @@ using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; using System.Data; +using System.Globalization; using System.IO; +using System.Text; using System.Threading; using System.Threading.Tasks; @@ -300,6 +302,52 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + public UserItemData GetUserData(Guid userId, List keys) + { + if (userId == Guid.Empty) + { + throw new ArgumentNullException("userId"); + } + if (keys == null) + { + throw new ArgumentNullException("keys"); + } + + using (var cmd = _connection.CreateCommand()) + { + var index = 0; + var excludeIds = new List(); + var builder = new StringBuilder(); + foreach (var key in keys) + { + var paramName = "@Key" + index; + excludeIds.Add("Key =" + paramName); + cmd.Parameters.Add(cmd, paramName, DbType.String).Value = key; + builder.Append(" WHEN Key=" + paramName + " THEN " + index); + index++; + } + + var keyText = string.Join(" OR ", excludeIds.ToArray()); + + cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId AND (" + keyText + ") "; + + cmd.CommandText += " ORDER BY (Case " + builder + " Else " + keys.Count.ToString(CultureInfo.InvariantCulture) + " End )"; + cmd.CommandText += " LIMIT 1"; + + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + { + if (reader.Read()) + { + return ReadRow(reader); + } + } + + return null; + } + } + /// /// Return all user-data associated with the given user /// diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs index ec91dc1b71..6019d64b4b 100644 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs @@ -111,24 +111,6 @@ namespace MediaBrowser.Server.Implementations.TV .Select(i => GetNextUp(i, currentUser)) // Include if an episode was found, and either the series is not unwatched or the specific series was requested .Where(i => i.Item1 != null && (!i.Item3 || !string.IsNullOrWhiteSpace(request.SeriesId))) - //.OrderByDescending(i => - //{ - // var episode = i.Item1; - - // var seriesUserData = _userDataManager.GetUserData(user, episode.Series); - - // if (seriesUserData.IsFavorite) - // { - // return 2; - // } - - // if (seriesUserData.Likes.HasValue) - // { - // return seriesUserData.Likes.Value ? 1 : -1; - // } - - // return 0; - //}) .OrderByDescending(i => i.Item2) .ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue) .Select(i => i.Item1); @@ -143,9 +125,8 @@ namespace MediaBrowser.Server.Implementations.TV private Tuple GetNextUp(Series series, User user) { // Get them in display order, then reverse - var allEpisodes = series.GetSeasons(user, true, true) - .Where(i => !i.IndexNumber.HasValue || i.IndexNumber.Value != 0) - .SelectMany(i => i.GetEpisodes(user)) + var allEpisodes = series.GetEpisodes(user, true, true) + .Where(i => !i.ParentIndexNumber.HasValue || i.ParentIndexNumber.Value != 0) .Reverse() .ToList(); @@ -155,6 +136,8 @@ namespace MediaBrowser.Server.Implementations.TV var includeMissing = user.Configuration.DisplayMissingEpisodes; + var unplayedEpisodes = new List(); + // Go back starting with the most recent episodes foreach (var episode in allEpisodes) { @@ -172,6 +155,8 @@ namespace MediaBrowser.Server.Implementations.TV } else { + unplayedEpisodes.Add(episode); + if (!episode.IsVirtualUnaired && (includeMissing || !episode.IsMissingEpisode)) { nextUp = episode; @@ -184,7 +169,18 @@ namespace MediaBrowser.Server.Implementations.TV return new Tuple(nextUp, lastWatchedDate, false); } - var firstEpisode = allEpisodes.LastOrDefault(i => !i.IsVirtualUnaired && (includeMissing || !i.IsMissingEpisode) && !i.IsPlayed(user)); + Episode firstEpisode = null; + // Find the first unplayed episode. Start from the back of the list since they're in reverse order + for (var i = unplayedEpisodes.Count - 1; i >= 0; i--) + { + var unplayedEpisode = unplayedEpisodes[i]; + + if (!unplayedEpisode.IsVirtualUnaired && (includeMissing || !unplayedEpisode.IsMissingEpisode)) + { + firstEpisode = unplayedEpisode; + break; + } + } // Return the first episode return new Tuple(firstEpisode, DateTime.MinValue, true); -- cgit v1.2.3 From b320d5740938bdf0f64b6942a5d25327931ec418 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 4 Jun 2016 00:57:46 -0400 Subject: restore episode pooling --- MediaBrowser.Api/StartupWizardService.cs | 2 +- MediaBrowser.Controller/Entities/TV/Series.cs | 81 ++++------------------ .../Persistence/SqliteItemRepository.cs | 3 +- 3 files changed, 17 insertions(+), 69 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 0a8d39ee5c..989dea6c60 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -113,7 +113,7 @@ namespace MediaBrowser.Api config.EnableCustomPathSubFolders = true; config.EnableStandaloneMusicKeys = true; config.EnableCaseSensitiveItemIds = true; - config.SchemaVersion = 87; + config.SchemaVersion = 89; } public void Post(UpdateStartupConfiguration request) diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index bbb9b30196..e361fa87d5 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -107,9 +107,11 @@ namespace MediaBrowser.Controller.Entities.TV { get { - if (EnablePooling()) + var userdatakeys = GetUserDataKeys(); + + if (userdatakeys.Count > 1) { - return GetUserDataKeys().First(); + return userdatakeys[0]; } return base.PresentationUniqueKey; } @@ -207,33 +209,13 @@ namespace MediaBrowser.Controller.Entities.TV { IEnumerable seasons; - if (EnablePooling()) + seasons = LibraryManager.GetItemList(new InternalItemsQuery(user) { - var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user) - { - PresentationUniqueKey = PresentationUniqueKey, - IncludeItemTypes = new[] { typeof(Series).Name } - }); - - if (seriesIds.Count > 1) - { - seasons = LibraryManager.GetItemList(new InternalItemsQuery(user) - { - AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(), - IncludeItemTypes = new[] { typeof(Season).Name }, - SortBy = new[] { ItemSortBy.SortName } + AncestorWithPresentationUniqueKey = PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Season).Name }, + SortBy = new[] { ItemSortBy.SortName } - }).Cast(); - } - else - { - seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType(); - } - } - else - { - seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType(); - } + }).Cast(); if (!includeMissingSeasons) { @@ -343,50 +325,15 @@ namespace MediaBrowser.Controller.Entities.TV return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } - private bool EnablePooling() - { - return false; - } - private IEnumerable GetAllEpisodes(User user) { - IEnumerable episodes; - - if (EnablePooling()) - { - var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user) - { - PresentationUniqueKey = PresentationUniqueKey, - IncludeItemTypes = new[] { typeof(Series).Name } - }); - - if (seriesIds.Count > 1) - { - episodes = LibraryManager.GetItemList(new InternalItemsQuery(user) - { - AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(), - IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.SortName } - - }).Cast(); - } - else - { - episodes = GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Episode).Name } - }).Cast(); - } - } - else + return LibraryManager.GetItemList(new InternalItemsQuery(user) { - episodes = GetRecursiveChildren(user, new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Episode).Name } - }).Cast(); - } + AncestorWithPresentationUniqueKey = PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Episode).Name }, + SortBy = new[] { ItemSortBy.SortName } - return episodes; + }).Cast(); } public IEnumerable GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 9f827c553a..c790e829a8 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - public const int LatestSchemaVersion = 87; + public const int LatestSchemaVersion = 89; /// /// Initializes a new instance of the class. @@ -137,6 +137,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID, Path TEXT)", "create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)", "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)", + "create index if not exists idx_TypedBaseItems2 on TypedBaseItems(Type,Guid)", "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))", "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)", -- cgit v1.2.3 From 1edd61bf38f26665f0d0381788d12e180230c4f3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 4 Jun 2016 13:14:03 -0400 Subject: update tabs --- .../Music/MusicBrainzAlbumProvider.cs | 2 +- .../Persistence/SqliteExtensions.cs | 102 --------------------- .../Migrations/FolderViewSettingMigration.cs | 5 +- 3 files changed, 5 insertions(+), 104 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index d76c89dfb8..6e57b4022a 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Music private readonly IApplicationHost _appHost; private readonly ILogger _logger; - public static string MusicBrainzBaseUrl = "http://musicbrainz.fercasas.com:5000"; + public static string MusicBrainzBaseUrl = "https://www.musicbrainz.org"; public MusicBrainzAlbumProvider(IHttpClient httpClient, IApplicationHost appHost, ILogger logger) { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index 519731a5cc..dd2f15cfd7 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -48,13 +48,6 @@ namespace MediaBrowser.Server.Implementations.Persistence return connection; } - public static void BindGetSimilarityScore(IDbConnection connection, ILogger logger) - { - var sqlConnection = (SQLiteConnection)connection; - SimiliarToFunction.Logger = logger; - sqlConnection.BindFunction(new SimiliarToFunction()); - } - public static void BindFunction(this SQLiteConnection connection, SQLiteFunction function) { var attributes = function.GetType().GetCustomAttributes(typeof(SQLiteFunctionAttribute), true).Cast().ToArray(); @@ -65,99 +58,4 @@ namespace MediaBrowser.Server.Implementations.Persistence connection.BindFunction(attributes[0], function); } } - - [SQLiteFunction(Name = "GetSimilarityScore", Arguments = 6, FuncType = FunctionType.Scalar)] - public class SimiliarToFunction : SQLiteFunction - { - internal static ILogger Logger; - - private readonly Dictionary _personTypeScores = new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { PersonType.Actor, 3}, - { PersonType.Director, 5}, - { PersonType.Composer, 2}, - { PersonType.GuestStar, 3}, - { PersonType.Writer, 2}, - { PersonType.Conductor, 2}, - { PersonType.Producer, 2}, - { PersonType.Lyricist, 2} - }; - - public override object Invoke(object[] args) - { - var score = 0; - - // Official rating equals - if ((long)args[0] == 1) - { - score += 10; - } - - // Year difference - long? yearDifference = args[1] == null ? (long?)null : (long)args[1]; - if (yearDifference.HasValue) - { - var diff = Math.Abs(yearDifference.Value); - - // Add if they came out within the same decade - if (diff < 10) - { - score += 2; - } - - // And more if within five years - if (diff < 5) - { - score += 2; - } - } - - // genres - score += Convert.ToInt32((long)args[2]) * 10; - - // tags - score += Convert.ToInt32((long)args[3]) * 10; - - // # of common keywords - score += Convert.ToInt32((long)args[4]) *10; - - // # of common studios - score += Convert.ToInt32((long)args[5]) * 3; - - // studios - //score += GetListScore(args, 7, 8, 3); - - //var rowPeopleNamesText = (args[12] as string) ?? string.Empty; - //var rowPeopleNames = rowPeopleNamesText.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); - - //foreach (var name in rowPeopleNames) - //{ - // // TODO: Send along person types - // score += 3; - //} - - //Logger.Debug("Returning score {0}", score); - return score; - } - - private int GetListScore(object[] args, int index1, int index2, int value = 10) - { - var score = 0; - - var inputGenres = args[index1] as string; - var rowGenres = args[index2] as string; - var inputGenreList = string.IsNullOrWhiteSpace(inputGenres) ? new string[] { } : inputGenres.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); - var rowGenresList = string.IsNullOrWhiteSpace(rowGenres) ? new string[] { } : rowGenres.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (var genre in inputGenreList) - { - if (rowGenresList.Contains(genre, StringComparer.OrdinalIgnoreCase)) - { - score += value; - } - } - - return score; - } - } } diff --git a/MediaBrowser.Server.Startup.Common/Migrations/FolderViewSettingMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/FolderViewSettingMigration.cs index 4049d17548..12054864b3 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/FolderViewSettingMigration.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/FolderViewSettingMigration.cs @@ -24,7 +24,10 @@ namespace MediaBrowser.Server.Startup.Common.Migrations { if (_config.Configuration.IsStartupWizardCompleted) { - _config.Configuration.EnableFolderView = _userManager.Users.Any(i => i.Configuration.DisplayFoldersView); + if (_userManager.Users.Any(i => i.Configuration.DisplayFoldersView)) + { + _config.Configuration.EnableFolderView = true; + } } migrationKeyList.Add(migrationKey); -- cgit v1.2.3 From 68613fcb5b50438928a0c7756022d79b6ec4753d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 4 Jun 2016 13:14:43 -0400 Subject: remove dead code --- MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs | 1 - MediaBrowser.Server.Mono/Native/DbConnector.cs | 5 ----- MediaBrowser.ServerApplication/Native/DbConnector.cs | 5 ----- 3 files changed, 11 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs index 985d79a0ac..cac9fe9835 100644 --- a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs +++ b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs @@ -6,6 +6,5 @@ namespace MediaBrowser.Server.Implementations.Persistence public interface IDbConnector { Task Connect(string dbPath); - void BindSimilarityScoreFunction(IDbConnection connection); } } diff --git a/MediaBrowser.Server.Mono/Native/DbConnector.cs b/MediaBrowser.Server.Mono/Native/DbConnector.cs index 536cd73223..3230f92f9c 100644 --- a/MediaBrowser.Server.Mono/Native/DbConnector.cs +++ b/MediaBrowser.Server.Mono/Native/DbConnector.cs @@ -16,11 +16,6 @@ namespace MediaBrowser.Server.Mono.Native _logger = logger; } - public void BindSimilarityScoreFunction(IDbConnection connection) - { - SqliteExtensions.BindGetSimilarityScore(connection, _logger); - } - public Task Connect(string dbPath) { return SqliteExtensions.ConnectToDb(dbPath, _logger); diff --git a/MediaBrowser.ServerApplication/Native/DbConnector.cs b/MediaBrowser.ServerApplication/Native/DbConnector.cs index f93cad62cb..48ba7d0e7c 100644 --- a/MediaBrowser.ServerApplication/Native/DbConnector.cs +++ b/MediaBrowser.ServerApplication/Native/DbConnector.cs @@ -16,11 +16,6 @@ namespace MediaBrowser.ServerApplication.Native _logger = logger; } - public void BindSimilarityScoreFunction(IDbConnection connection) - { - SqliteExtensions.BindGetSimilarityScore(connection, _logger); - } - public async Task Connect(string dbPath) { try -- cgit v1.2.3 From 59d174ef9e19a4a8a1ba5d3fda325a99ac3f8313 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 4 Jun 2016 13:15:01 -0400 Subject: remove method call --- MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs | 2 -- 1 file changed, 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index c790e829a8..fcec820292 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -272,8 +272,6 @@ namespace MediaBrowser.Server.Implementations.Persistence new MediaStreamColumns(_connection, Logger).AddColumns(); DataExtensions.Attach(_connection, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"), "UserDataDb"); - - dbConnector.BindSimilarityScoreFunction(_connection); } private readonly string[] _retriveItemColumns = -- cgit v1.2.3 From 70b1d39445d7972be58299420f5085c3d7ebeab6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 4 Jun 2016 20:17:35 -0400 Subject: update buttons --- MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fcec820292..460a67ca72 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -975,7 +975,7 @@ namespace MediaBrowser.Server.Implementations.Persistence if (type == null) { - Logger.Debug("Unknown type {0}", typeString); + //Logger.Debug("Unknown type {0}", typeString); return null; } -- cgit v1.2.3 From 19ee883ca26739a64d65ab54dfaf3b603ae36bfe Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 6 Jun 2016 17:13:00 -0400 Subject: record time base --- MediaBrowser.Api/ItemUpdateService.cs | 5 -- MediaBrowser.Api/Subtitles/SubtitleService.cs | 2 +- MediaBrowser.Controller/Entities/TV/Series.cs | 5 +- .../Probing/ProbeResultNormalizer.cs | 4 +- .../Configuration/ServerConfiguration.cs | 2 + MediaBrowser.Model/Entities/MediaStream.cs | 3 + MediaBrowser.Providers/TV/SeriesMetadataService.cs | 5 -- .../Dto/DtoService.cs | 5 -- .../Persistence/MediaStreamColumns.cs | 64 ++++++++++++++++++++++ .../Persistence/SqliteItemRepository.cs | 19 ++++++- 10 files changed, 91 insertions(+), 23 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index 6cb23a140d..79aaccfe80 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -419,11 +419,6 @@ namespace MediaBrowser.Api series.Status = request.SeriesStatus; series.AirDays = request.AirDays; series.AirTime = request.AirTime; - - if (request.DisplaySpecialsWithSeasons.HasValue) - { - series.DisplaySpecialsWithSeasons = request.DisplaySpecialsWithSeasons.Value; - } } } diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs index 0500f33055..160fda065f 100644 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -221,7 +221,7 @@ namespace MediaBrowser.Api.Subtitles if (string.Equals(request.Format, "vtt", StringComparison.OrdinalIgnoreCase) && request.AddVttTimeMap) { - //text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000"); + text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000"); } return ResultFactory.GetResult(text, MimeTypes.GetMimeType("file." + request.Format)); diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index a241483607..459b6dfb63 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -31,7 +31,6 @@ namespace MediaBrowser.Controller.Entities.TV RemoteTrailers = new List(); LocalTrailerIds = new List(); RemoteTrailerIds = new List(); - DisplaySpecialsWithSeasons = true; } [IgnoreDataMember] @@ -58,8 +57,6 @@ namespace MediaBrowser.Controller.Entities.TV } } - public bool DisplaySpecialsWithSeasons { get; set; } - public List LocalTrailerIds { get; set; } public List RemoteTrailerIds { get; set; } @@ -357,7 +354,7 @@ namespace MediaBrowser.Controller.Entities.TV return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes); } - var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, DisplaySpecialsWithSeasons); + var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons); if (!includeMissingEpisodes) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 44c69d4c1b..44a0f264da 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -408,7 +408,9 @@ namespace MediaBrowser.MediaEncoding.Probing Level = streamInfo.level, Index = streamInfo.index, PixelFormat = streamInfo.pix_fmt, - NalLengthSize = streamInfo.nal_length_size + NalLengthSize = streamInfo.nal_length_size, + TimeBase = streamInfo.time_base, + CodecTimeBase = streamInfo.codec_time_base }; if (string.Equals(streamInfo.is_avc, "true", StringComparison.OrdinalIgnoreCase) || diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 993799f658..0ce69970f2 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -200,6 +200,7 @@ namespace MediaBrowser.Model.Configuration public bool EnableLocalizedGuids { get; set; } public bool EnableFolderView { get; set; } public bool EnableGroupingIntoCollections { get; set; } + public bool DisplaySpecialsWithinSeasons { get; set; } /// /// Initializes a new instance of the class. @@ -210,6 +211,7 @@ namespace MediaBrowser.Model.Configuration EnableCustomPathSubFolders = true; EnableLocalizedGuids = true; + DisplaySpecialsWithinSeasons = true; ImageSavingConvention = ImageSavingConvention.Compatible; PublicPort = 8096; diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 6a3c08425f..868f6b64f5 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -36,6 +36,9 @@ namespace MediaBrowser.Model.Entities /// The comment. public string Comment { get; set; } + public string TimeBase { get; set; } + public string CodecTimeBase { get; set; } + public string Title { get; set; } public string DisplayTitle diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs index 041969a59a..f440baf5b4 100644 --- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs @@ -76,11 +76,6 @@ namespace MediaBrowser.Providers.TV { targetItem.AirDays = sourceItem.AirDays; } - - if (mergeMetadataSettings) - { - targetItem.DisplaySpecialsWithSeasons = sourceItem.DisplaySpecialsWithSeasons; - } } } } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 5588405e36..2c31a8aae9 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1466,11 +1466,6 @@ namespace MediaBrowser.Server.Implementations.Dto dto.AirTime = series.AirTime; dto.SeriesStatus = series.Status; - if (fields.Contains(ItemFields.Settings)) - { - dto.DisplaySpecialsWithSeasons = series.DisplaySpecialsWithSeasons; - } - dto.AnimeSeriesIndex = series.AnimeSeriesIndex; } diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index 948e99cb82..1d9be2e0d6 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -28,6 +28,8 @@ namespace MediaBrowser.Server.Implementations.Persistence AddNalColumn(); AddIsAvcColumn(); AddTitleColumn(); + AddTimeBaseColumn(); + AddCodecTimeBaseColumn(); } private void AddIsAvcColumn() @@ -61,6 +63,68 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.RunQueries(new[] { builder.ToString() }, _logger); } + private void AddTimeBaseColumn() + { + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "PRAGMA table_info(mediastreams)"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + if (!reader.IsDBNull(1)) + { + var name = reader.GetString(1); + + if (string.Equals(name, "TimeBase", StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + } + + var builder = new StringBuilder(); + + builder.AppendLine("alter table mediastreams"); + builder.AppendLine("add column TimeBase TEXT"); + + _connection.RunQueries(new[] { builder.ToString() }, _logger); + } + + private void AddCodecTimeBaseColumn() + { + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "PRAGMA table_info(mediastreams)"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + if (!reader.IsDBNull(1)) + { + var name = reader.GetString(1); + + if (string.Equals(name, "CodecTimeBase", StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + } + + var builder = new StringBuilder(); + + builder.AppendLine("alter table mediastreams"); + builder.AppendLine("add column CodecTimeBase TEXT"); + + _connection.RunQueries(new[] { builder.ToString() }, _logger); + } + private void AddTitleColumn() { using (var cmd = _connection.CreateCommand()) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 460a67ca72..a4cb0c48b0 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -130,7 +130,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await dbConnector.Connect(dbFile).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, 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))"; string[] queries = { @@ -368,7 +368,9 @@ namespace MediaBrowser.Server.Implementations.Persistence "Comment", "NalLengthSize", "IsAvc", - "Title" + "Title", + "TimeBase", + "CodecTimeBase" }; /// @@ -3805,6 +3807,9 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.IsAVC; _saveStreamCommand.GetParameter(index++).Value = stream.Title; + _saveStreamCommand.GetParameter(index++).Value = stream.TimeBase; + _saveStreamCommand.GetParameter(index++).Value = stream.CodecTimeBase; + _saveStreamCommand.Transaction = transaction; _saveStreamCommand.ExecuteNonQuery(); } @@ -3977,6 +3982,16 @@ namespace MediaBrowser.Server.Implementations.Persistence item.Title = reader.GetString(29); } + if (!reader.IsDBNull(30)) + { + item.TimeBase = reader.GetString(30); + } + + if (!reader.IsDBNull(31)) + { + item.CodecTimeBase = reader.GetString(31); + } + return item; } -- cgit v1.2.3 From 3ba9d3c12f71208cb45d58b93b7c472780a5d541 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 10 Jun 2016 12:45:04 -0400 Subject: update channel mapping --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 8 +++++--- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 2 ++ .../Library/MediaSourceManager.cs | 4 ++++ .../LiveTv/Listings/SchedulesDirect.cs | 14 +++++++++++--- .../Persistence/IDbConnector.cs | 2 +- .../Persistence/SqliteExtensions.cs | 4 ++-- .../Persistence/SqliteItemRepository.cs | 2 +- MediaBrowser.Server.Mono/Native/DbConnector.cs | 4 ++-- MediaBrowser.ServerApplication/Native/DbConnector.cs | 4 ++-- 9 files changed, 30 insertions(+), 14 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index ddc389f03a..b2f0704ea4 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -578,7 +578,9 @@ namespace MediaBrowser.Api.LiveTv { var config = GetConfiguration(); - var listingProvider = config.ListingProviders.First(i => string.Equals(request.ProviderId, i.Id, StringComparison.OrdinalIgnoreCase)); + var listingsProviderInfo = config.ListingProviders.First(i => string.Equals(request.ProviderId, i.Id, StringComparison.OrdinalIgnoreCase)); + + var listingsProviderName = _liveTvManager.ListingProviders.First(i => string.Equals(i.Type, listingsProviderInfo.Type, StringComparison.OrdinalIgnoreCase)).Name; var tunerChannels = await _liveTvManager.GetChannelsForListingsProvider(request.ProviderId, CancellationToken.None) .ConfigureAwait(false); @@ -586,7 +588,7 @@ namespace MediaBrowser.Api.LiveTv var providerChannels = await _liveTvManager.GetChannelsFromListingsProviderData(request.ProviderId, CancellationToken.None) .ConfigureAwait(false); - var mappings = listingProvider.ChannelMappings.ToList(); + var mappings = listingsProviderInfo.ChannelMappings.ToList(); var result = new ChannelMappingOptions { @@ -601,7 +603,7 @@ namespace MediaBrowser.Api.LiveTv Mappings = mappings, - ProviderName = "Schedules Direct" + ProviderName = listingsProviderName }; return ToOptimizedResult(result); diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 9cb0476bac..ffba3097ce 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -390,6 +390,8 @@ namespace MediaBrowser.Controller.LiveTv Task> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken); Task> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken); + List ListingProviders { get;} + event EventHandler> SeriesTimerCancelled; event EventHandler> TimerCancelled; event EventHandler> TimerCreated; diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 0ef7efe1b8..1bcb02ac39 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -73,6 +73,10 @@ namespace MediaBrowser.Server.Implementations.Library { return false; } + if (string.Equals(stream.Codec, "ssa", StringComparison.OrdinalIgnoreCase)) + { + return false; + } return true; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 6443440c81..e37109c148 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -879,6 +879,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings throw new Exception("ListingsId required"); } + await AddMetadata(info, new List(), cancellationToken).ConfigureAwait(false); + var token = await GetToken(info, cancellationToken); if (string.IsNullOrWhiteSpace(token)) @@ -886,8 +888,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings throw new Exception("token required"); } - ClearPairCache(listingsId); - var httpOptions = new HttpRequestOptions() { Url = ApiUrl + "/lineups/" + listingsId, @@ -921,10 +921,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings } channelNumber = channelNumber.TrimStart('0'); + var name = channelNumber; + var station = GetStation(listingsId, channelNumber, null); + + if (station != null) + { + name = station.name; + } + list.Add(new ChannelInfo { Number = channelNumber, - Name = map.channel + Name = name }); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs index cac9fe9835..2092f830a7 100644 --- a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs +++ b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs @@ -5,6 +5,6 @@ namespace MediaBrowser.Server.Implementations.Persistence { public interface IDbConnector { - Task Connect(string dbPath); + Task Connect(string dbPath, int? cacheSize = null); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index dd2f15cfd7..2f3f34aa4c 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Server.Implementations.Persistence /// The logger. /// Task{IDbConnection}. /// dbPath - public static async Task ConnectToDb(string dbPath, ILogger logger) + public static async Task ConnectToDb(string dbPath, int? cacheSize, ILogger logger) { if (string.IsNullOrEmpty(dbPath)) { @@ -35,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var connectionstr = new SQLiteConnectionStringBuilder { PageSize = 4096, - CacheSize = 2000, + CacheSize = cacheSize ?? 2000, SyncMode = SynchronizationModes.Normal, DataSource = dbPath, JournalMode = SQLiteJournalModeEnum.Wal diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index a4cb0c48b0..071951018d 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -127,7 +127,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { var dbFile = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); - _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile, 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))"; diff --git a/MediaBrowser.Server.Mono/Native/DbConnector.cs b/MediaBrowser.Server.Mono/Native/DbConnector.cs index 3230f92f9c..7553dbe1ac 100644 --- a/MediaBrowser.Server.Mono/Native/DbConnector.cs +++ b/MediaBrowser.Server.Mono/Native/DbConnector.cs @@ -16,9 +16,9 @@ namespace MediaBrowser.Server.Mono.Native _logger = logger; } - public Task Connect(string dbPath) + public Task Connect(string dbPath, int? cacheSize = null) { - return SqliteExtensions.ConnectToDb(dbPath, _logger); + return SqliteExtensions.ConnectToDb(dbPath, cacheSize, _logger); } } } \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Native/DbConnector.cs b/MediaBrowser.ServerApplication/Native/DbConnector.cs index 48ba7d0e7c..6001ac3c07 100644 --- a/MediaBrowser.ServerApplication/Native/DbConnector.cs +++ b/MediaBrowser.ServerApplication/Native/DbConnector.cs @@ -16,11 +16,11 @@ namespace MediaBrowser.ServerApplication.Native _logger = logger; } - public async Task Connect(string dbPath) + public async Task Connect(string dbPath, int? cacheSize = null) { try { - return await SqliteExtensions.ConnectToDb(dbPath, _logger).ConfigureAwait(false); + return await SqliteExtensions.ConnectToDb(dbPath, cacheSize, _logger).ConfigureAwait(false); } catch (Exception ex) { -- cgit v1.2.3 From 4c7f292ba884c16b9e95eb319f3664469189d22c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 11 Jun 2016 11:55:05 -0400 Subject: use individual connections --- .../Notifications/SqliteNotificationsRepository.cs | 443 +++++------ .../Persistence/BaseSqliteRepository.cs | 16 +- .../Persistence/IDbConnector.cs | 2 +- .../SqliteDisplayPreferencesRepository.cs | 256 +++--- .../Persistence/SqliteExtensions.cs | 20 +- .../SqliteFileOrganizationRepository.cs | 4 +- .../Persistence/SqliteItemRepository.cs | 6 +- .../Persistence/SqliteUserDataRepository.cs | 4 +- .../Persistence/SqliteUserRepository.cs | 201 +++-- .../Security/AuthenticationRepository.cs | 325 ++++---- .../Social/SharingRepository.cs | 171 ++-- .../Sync/SyncRepository.cs | 865 ++++++++++----------- 12 files changed, 1114 insertions(+), 1199 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs index 10e8c5699e..6c3bc3050e 100644 --- a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs +++ b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs @@ -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 NotificationAdded; public event EventHandler NotificationsMarkedRead; public event EventHandler 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); + } } /// @@ -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(); - - 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(); - clauses.Add("UserId=@UserId"); - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(query.UserId); + if (query.IsRead.HasValue) + { + clauses.Add("IsRead=@IsRead"); + cmd.Parameters.Add(cmd, "@IsRead", DbType.Boolean).Value = query.IsRead.Value; + } - var whereClause = " where " + string.Join(" And ", clauses.ToArray()); + clauses.Add("UserId=@UserId"); + cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(query.UserId); - 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); + var whereClause = " where " + string.Join(" And ", clauses.ToArray()); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - if (reader.Read()) - { - result.TotalRecordCount = reader.GetInt32(0); - } + 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); - if (reader.NextResult()) + 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(); + 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(); - result.UnreadCount = levels.Count; + while (reader.Read()) + { + levels.Add(GetLevel(reader, 0)); + } - 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 /// IEnumerable{Notification}. private IEnumerable GetNotifications(IDataReader reader) { + var list = new List(); + 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(); + using (var 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"); + + 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.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.Transaction = transaction; - _replaceNotificationCommand.ExecuteNonQuery(); + replaceNotificationCommand.ExecuteNonQuery(); - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save notification:", e); + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save notification:", e); - if (transaction != null) - { - transaction.Rollback(); - } + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); + 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); + using (var connection = await CreateConnection().ConfigureAwait(false)) + { + using (var markAllReadCommand = connection.CreateCommand()) + { + markAllReadCommand.CommandText = "update Notifications set IsRead=@IsRead where UserId=@UserId"; - IDbTransaction transaction = null; + markAllReadCommand.Parameters.Add(markAllReadCommand, "@UserId"); + markAllReadCommand.Parameters.Add(markAllReadCommand, "@IsRead"); - try - { - cancellationToken.ThrowIfCancellationRequested(); + IDbTransaction transaction = null; - transaction = _connection.BeginTransaction(); + try + { + cancellationToken.ThrowIfCancellationRequested(); - _markAllReadCommand.GetParameter(0).Value = new Guid(userId); - _markAllReadCommand.GetParameter(1).Value = isRead; + transaction = connection.BeginTransaction(); - _markAllReadCommand.ExecuteNonQuery(); + markAllReadCommand.GetParameter(0).Value = new Guid(userId); + markAllReadCommand.GetParameter(1).Value = isRead; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + markAllReadCommand.ExecuteNonQuery(); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save notification:", e); + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save notification:", e); - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } + if (transaction != null) + { + transaction.Rollback(); + } - WriteLock.Release(); + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + } + } } } @@ -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(); + using (var markReadCommand = connection.CreateCommand()) + { + markReadCommand.CommandText = "update Notifications set IsRead=@IsRead where Id=@Id and UserId=@UserId"; - transaction = _connection.BeginTransaction(); + markReadCommand.Parameters.Add(markReadCommand, "@UserId"); + markReadCommand.Parameters.Add(markReadCommand, "@IsRead"); + markReadCommand.Parameters.Add(markReadCommand, "@Id"); - _markReadCommand.GetParameter(0).Value = new Guid(userId); - _markReadCommand.GetParameter(1).Value = isRead; + IDbTransaction transaction = null; - foreach (var id in notificationIdList) - { - _markReadCommand.GetParameter(2).Value = id; + try + { + cancellationToken.ThrowIfCancellationRequested(); - _markReadCommand.Transaction = transaction; + transaction = connection.BeginTransaction(); - _markReadCommand.ExecuteNonQuery(); - } + markReadCommand.GetParameter(0).Value = new Guid(userId); + markReadCommand.GetParameter(1).Value = isRead; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + foreach (var id in notificationIdList) + { + markReadCommand.GetParameter(2).Value = id; - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save notification:", e); + markReadCommand.Transaction = transaction; - if (transaction != null) - { - transaction.Rollback(); - } + markReadCommand.ExecuteNonQuery(); + } - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - WriteLock.Release(); - } - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save notification:", e); - protected override void CloseConnection() - { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } + if (transaction != null) + { + transaction.Rollback(); + } - _connection.Dispose(); - _connection = null; + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + } + } } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs index 3959078449..f9c892b76a 100644 --- a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs @@ -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 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() + { + + } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs index 2092f830a7..596cf8407a 100644 --- a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs +++ b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs @@ -5,6 +5,6 @@ namespace MediaBrowser.Server.Implementations.Persistence { public interface IDbConnector { - Task Connect(string dbPath, int? cacheSize = null); + Task Connect(string dbPath, bool isReadOnly, bool enablePooling = false, int? cacheSize = null); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs index 6077cfdba4..1a6a88ebe2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs @@ -18,12 +18,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// 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"); } /// @@ -43,22 +42,15 @@ namespace MediaBrowser.Server.Implementations.Persistence /// private readonly IJsonSerializer _jsonSerializer; - /// - /// The _app paths - /// - private readonly IApplicationPaths _appPaths; - /// /// Opens the connection to the database /// /// Task. - 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); + } } /// @@ -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(); + + 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(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.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.Transaction = transaction; + cmd.Transaction = transaction; - cmd.ExecuteNonQuery(); - } + cmd.ExecuteNonQuery(); + } - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + transaction.Commit(); + } + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to save display preferences:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save display preferences:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + 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.Commit(); + } + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to save display preferences:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save display preferences:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + finally { - transaction.Dispose(); + 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(stream); + if (reader.Read()) + { + using (var stream = reader.GetMemoryStream(0)) + { + return _jsonSerializer.DeserializeFromStream(stream); + } + } } + + return new DisplayPreferences + { + Id = guidId.ToString("N") + }; } } - - return new DisplayPreferences - { - Id = guidId.ToString("N") - }; } /// @@ -278,36 +274,30 @@ namespace MediaBrowser.Server.Implementations.Persistence /// item public IEnumerable GetAllDisplayPreferences(Guid userId) { + var list = new List(); - 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(stream); + while (reader.Read()) + { + using (var stream = reader.GetMemoryStream(0)) + { + list.Add(_jsonSerializer.DeserializeFromStream(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) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index 2f3f34aa4c..cc9e3ebccf 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -19,11 +19,7 @@ namespace MediaBrowser.Server.Implementations.Persistence /// /// Connects to db. /// - /// The db path. - /// The logger. - /// Task{IDbConnection}. - /// dbPath - public static async Task ConnectToDb(string dbPath, int? cacheSize, ILogger logger) + public static async Task 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().ToArray(); - if (attributes.Length == 0) - { - throw new InvalidOperationException("SQLiteFunction doesn't have SQLiteFunctionAttribute"); - } - connection.BindFunction(attributes[0], function); - } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs index 037776997e..8a4ba6460d 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs @@ -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 = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 071951018d..9bfdd879da 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -99,8 +99,8 @@ namespace MediaBrowser.Server.Implementations.Persistence /// /// Initializes a new instance of the class. /// - 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))"; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index bfdb9e0c7a..d81f4ad37b 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -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 = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs index f7ca39a548..4c07a60181 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs @@ -17,14 +17,13 @@ namespace MediaBrowser.Server.Implementations.Persistence /// 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"); } /// @@ -43,13 +42,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - 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); + } } /// @@ -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; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + cmd.ExecuteNonQuery(); + } + + transaction.Commit(); + } + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to save user:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save user:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + finally { - transaction.Dispose(); + if (transaction != null) + { + transaction.Dispose(); + } } - - WriteLock.Release(); } } @@ -142,25 +139,32 @@ namespace MediaBrowser.Server.Implementations.Persistence /// IEnumerable{User}. public IEnumerable RetrieveAllUsers() { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "select guid,data from users"; + var list = new List(); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + using (var connection = CreateConnection(true).Result) + { + 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(stream); - user.Id = id; - yield return user; + var id = reader.GetGuid(0); + + using (var stream = reader.GetMemoryStream(1)) + { + var user = _jsonSerializer.DeserializeFromStream(stream); + user.Id = id; + list.Add(user); + } } } } } + + return list; } /// @@ -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"; - - cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = user.Id; + transaction = connection.BeginTransaction(); - cmd.Transaction = transaction; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "delete from users where guid=@guid"; - cmd.ExecuteNonQuery(); - } + cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = user.Id; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + cmd.Transaction = transaction; - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to delete user:", e); + cmd.ExecuteNonQuery(); + } - if (transaction != null) - { - transaction.Rollback(); + transaction.Commit(); } - - throw; - } - finally - { - if (transaction != null) + catch (OperationCanceledException) { - transaction.Dispose(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to delete user:", e); - WriteLock.Release(); - } - } + if (transaction != null) + { + transaction.Rollback(); + } - protected override void CloseConnection() - { - if (_connection != null) - { - if (_connection.IsOpen()) + throw; + } + finally { - _connection.Close(); + if (transaction != null) + { + transaction.Dispose(); + } } - - _connection.Dispose(); - _connection = null; } } } diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs index e8d9814ecb..3013510de1 100644 --- a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs +++ b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs @@ -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.AddColumn(Logger, "AccessTokens", "AppVersion", "TEXT"); + connection.RunQueries(queries, Logger); - 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(); + using (var 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"); + + IDbTransaction transaction = null; + + try + { + transaction = connection.BeginTransaction(); - var index = 0; + 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.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.Transaction = transaction; - _saveInfoCommand.ExecuteNonQuery(); + saveInfoCommand.ExecuteNonQuery(); - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save record:", e); + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save record:", e); - if (transaction != null) - { - transaction.Rollback(); - } + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); + 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(); - - 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(); - 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 (!string.IsNullOrWhiteSpace(query.AccessToken)) + { + whereClauses.Add("AccessToken=@AccessToken"); + cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken; + } - if (query.HasUser.HasValue) - { - if (query.HasUser.Value) + if (!string.IsNullOrWhiteSpace(query.UserId)) { - whereClauses.Add("UserId not null"); + whereClauses.Add("UserId=@UserId"); + cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId; } - else + + if (!string.IsNullOrWhiteSpace(query.DeviceId)) { - whereClauses.Add("UserId is null"); + whereClauses.Add("DeviceId=@DeviceId"); + cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId; } - } - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + if (query.IsActive.HasValue) + { + whereClauses.Add("IsActive=@IsActive"); + cmd.Parameters.Add(cmd, "@IsActive", DbType.Boolean).Value = query.IsActive.Value; + } - if (startIndex > 0) - { - var pagingWhereText = whereClauses.Count == 0 ? + 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))); - } + if (startIndex > 0) + { + 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))); + } - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - cmd.CommandText += whereText; + cmd.CommandText += whereText; - cmd.CommandText += " ORDER BY DateCreated"; + cmd.CommandText += " ORDER BY DateCreated"; - if (query.Limit.HasValue) - { - cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); - } + if (query.Limit.HasValue) + { + cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); + } - cmd.CommandText += "; select count (Id) from AccessTokens" + whereTextWithoutPaging; + cmd.CommandText += "; select count (Id) from AccessTokens" + whereTextWithoutPaging; - var list = new List(); - var count = 0; + var list = new List(); + var count = 0; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { - list.Add(Get(reader)); + while (reader.Read()) + { + list.Add(Get(reader)); + } + + if (reader.NextResult() && reader.Read()) + { + count = reader.GetInt32(0); + } } - if (reader.NextResult() && reader.Read()) + return new QueryResult() { - count = reader.GetInt32(0); - } + Items = list.ToArray(), + TotalRecordCount = count + }; } - - return new QueryResult() - { - 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"; - - cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; + var guid = new Guid(id); - 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; - } - } } } diff --git a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs index 317743eb1b..8a895037e7 100644 --- a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs +++ b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs @@ -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"); } /// /// Opens the connection to the database /// /// Task. - 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(); - } - - /// - /// Prepares the statements. - /// - 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"; + using (var connection = CreateConnection(true).Result) + { + 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); + 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()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { - return GetSocialShareInfo(reader); + if (reader.Read()) + { + return GetSocialShareInfo(reader); + } } - } - return null; + return null; + } } private SocialShareInfo GetSocialShareInfo(IDataReader reader) @@ -164,21 +155,7 @@ namespace MediaBrowser.Server.Implementations.Social public async Task DeleteShare(string id) { - - } - - protected override void CloseConnection() - { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - _connection.Dispose(); - _connection = null; - } } } } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 739d1ab6e6..5b623cf2ad 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -18,34 +18,22 @@ namespace MediaBrowser.Server.Implementations.Sync { public class SyncRepository : BaseSqliteRepository, ISyncRepository { - private IDbConnection _connection; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private IDbCommand _insertJobCommand; - private IDbCommand _updateJobCommand; - private IDbCommand _deleteJobCommand; - - private IDbCommand _deleteJobItemsCommand; - private IDbCommand _insertJobItemCommand; - private IDbCommand _updateJobItemCommand; - private readonly IJsonSerializer _json; - private readonly IServerApplicationPaths _appPaths; - public SyncRepository(ILogManager logManager, IJsonSerializer json, IServerApplicationPaths appPaths) - : base(logManager) + public SyncRepository(ILogManager logManager, IJsonSerializer json, IServerApplicationPaths appPaths, IDbConnector connector) + : base(logManager, connector) { _json = json; - _appPaths = appPaths; + DbFilePath = Path.Combine(appPaths.DataPath, "sync14.db"); } - public async Task Initialize(IDbConnector dbConnector) + public async Task Initialize() { - var dbFile = Path.Combine(_appPaths.DataPath, "sync14.db"); - - _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); - - string[] queries = { + using (var connection = await CreateConnection().ConfigureAwait(false)) + { + string[] queries = { "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Profile TEXT, Quality TEXT, Bitrate INT, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)", "create index if not exists idx_SyncJobs on SyncJobs(Id)", @@ -61,114 +49,12 @@ namespace MediaBrowser.Server.Implementations.Sync "pragma shrink_memory" }; - _connection.RunQueries(queries, Logger); - - _connection.AddColumn(Logger, "SyncJobs", "Profile", "TEXT"); - _connection.AddColumn(Logger, "SyncJobs", "Bitrate", "INT"); - _connection.AddColumn(Logger, "SyncJobItems", "ItemDateModifiedTicks", "BIGINT"); + connection.RunQueries(queries, Logger); - PrepareStatements(); - } - - private void PrepareStatements() - { - // _deleteJobCommand - _deleteJobCommand = _connection.CreateCommand(); - _deleteJobCommand.CommandText = "delete from SyncJobs where Id=@Id"; - _deleteJobCommand.Parameters.Add(_deleteJobCommand, "@Id"); - - // _deleteJobItemsCommand - _deleteJobItemsCommand = _connection.CreateCommand(); - _deleteJobItemsCommand.CommandText = "delete from SyncJobItems where JobId=@JobId"; - _deleteJobItemsCommand.Parameters.Add(_deleteJobItemsCommand, "@JobId"); - - // _insertJobCommand - _insertJobCommand = _connection.CreateCommand(); - _insertJobCommand.CommandText = "insert into SyncJobs (Id, TargetId, Name, Profile, Quality, Bitrate, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount) values (@Id, @TargetId, @Name, @Profile, @Quality, @Bitrate, @Status, @Progress, @UserId, @ItemIds, @Category, @ParentId, @UnwatchedOnly, @ItemLimit, @SyncNewContent, @DateCreated, @DateLastModified, @ItemCount)"; - - _insertJobCommand.Parameters.Add(_insertJobCommand, "@Id"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@TargetId"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@Name"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@Profile"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@Quality"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@Bitrate"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@Status"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@Progress"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@UserId"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@ItemIds"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@Category"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@ParentId"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@UnwatchedOnly"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@ItemLimit"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@SyncNewContent"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@DateCreated"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@DateLastModified"); - _insertJobCommand.Parameters.Add(_insertJobCommand, "@ItemCount"); - - // _updateJobCommand - _updateJobCommand = _connection.CreateCommand(); - _updateJobCommand.CommandText = "update SyncJobs set TargetId=@TargetId,Name=@Name,Profile=@Profile,Quality=@Quality,Bitrate=@Bitrate,Status=@Status,Progress=@Progress,UserId=@UserId,ItemIds=@ItemIds,Category=@Category,ParentId=@ParentId,UnwatchedOnly=@UnwatchedOnly,ItemLimit=@ItemLimit,SyncNewContent=@SyncNewContent,DateCreated=@DateCreated,DateLastModified=@DateLastModified,ItemCount=@ItemCount where Id=@Id"; - - _updateJobCommand.Parameters.Add(_updateJobCommand, "@Id"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@TargetId"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@Name"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@Profile"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@Quality"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@Bitrate"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@Status"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@Progress"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@UserId"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@ItemIds"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@Category"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@ParentId"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@UnwatchedOnly"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@ItemLimit"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@SyncNewContent"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@DateCreated"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@DateLastModified"); - _updateJobCommand.Parameters.Add(_updateJobCommand, "@ItemCount"); - - // _insertJobItemCommand - _insertJobItemCommand = _connection.CreateCommand(); - _insertJobItemCommand.CommandText = "insert into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex, ItemDateModifiedTicks) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval, @JobItemIndex, @ItemDateModifiedTicks)"; - - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@Id"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@ItemId"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@ItemName"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@MediaSourceId"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@JobId"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@TemporaryPath"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@OutputPath"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@Status"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@TargetId"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@DateCreated"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@Progress"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@AdditionalFiles"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@MediaSource"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@IsMarkedForRemoval"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@JobItemIndex"); - _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@ItemDateModifiedTicks"); - - // _updateJobItemCommand - _updateJobItemCommand = _connection.CreateCommand(); - _updateJobItemCommand.CommandText = "update SyncJobItems set ItemId=@ItemId,ItemName=@ItemName,MediaSourceId=@MediaSourceId,JobId=@JobId,TemporaryPath=@TemporaryPath,OutputPath=@OutputPath,Status=@Status,TargetId=@TargetId,DateCreated=@DateCreated,Progress=@Progress,AdditionalFiles=@AdditionalFiles,MediaSource=@MediaSource,IsMarkedForRemoval=@IsMarkedForRemoval,JobItemIndex=@JobItemIndex,ItemDateModifiedTicks=@ItemDateModifiedTicks where Id=@Id"; - - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@Id"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@ItemId"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@ItemName"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@MediaSourceId"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@JobId"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@TemporaryPath"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@OutputPath"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@Status"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@TargetId"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@DateCreated"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@Progress"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@AdditionalFiles"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@MediaSource"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@IsMarkedForRemoval"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@JobItemIndex"); - _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@ItemDateModifiedTicks"); + connection.AddColumn(Logger, "SyncJobs", "Profile", "TEXT"); + connection.AddColumn(Logger, "SyncJobs", "Bitrate", "INT"); + connection.AddColumn(Logger, "SyncJobItems", "ItemDateModifiedTicks", "BIGINT"); + } } private const string BaseJobSelectText = "select Id, TargetId, Name, Profile, Quality, Bitrate, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs"; @@ -182,7 +68,7 @@ namespace MediaBrowser.Server.Implementations.Sync } CheckDisposed(); - + var guid = new Guid(id); if (guid == Guid.Empty) @@ -190,22 +76,25 @@ namespace MediaBrowser.Server.Implementations.Sync throw new ArgumentNullException("id"); } - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = BaseJobSelectText + " where Id=@Id"; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = BaseJobSelectText + " where Id=@Id"; - cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; + cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { - return GetJob(reader); + if (reader.Read()) + { + return GetJob(reader); + } } } - } - return null; + return null; + } } private SyncJob GetJob(IDataReader reader) @@ -283,15 +172,15 @@ namespace MediaBrowser.Server.Implementations.Sync public Task Create(SyncJob job) { - return InsertOrUpdate(job, _insertJobCommand); + return InsertOrUpdate(job, true); } public Task Update(SyncJob job) { - return InsertOrUpdate(job, _updateJobCommand); + return InsertOrUpdate(job, false); } - private async Task InsertOrUpdate(SyncJob job, IDbCommand cmd) + private async Task InsertOrUpdate(SyncJob job, bool insert) { if (job == null) { @@ -299,70 +188,119 @@ namespace MediaBrowser.Server.Implementations.Sync } CheckDisposed(); - - await WriteLock.WaitAsync().ConfigureAwait(false); - - IDbTransaction transaction = null; - try + using (var connection = await CreateConnection().ConfigureAwait(false)) { - transaction = _connection.BeginTransaction(); - - var index = 0; - - cmd.GetParameter(index++).Value = new Guid(job.Id); - cmd.GetParameter(index++).Value = job.TargetId; - cmd.GetParameter(index++).Value = job.Name; - cmd.GetParameter(index++).Value = job.Profile; - cmd.GetParameter(index++).Value = job.Quality; - cmd.GetParameter(index++).Value = job.Bitrate; - cmd.GetParameter(index++).Value = job.Status.ToString(); - cmd.GetParameter(index++).Value = job.Progress; - cmd.GetParameter(index++).Value = job.UserId; - cmd.GetParameter(index++).Value = string.Join(",", job.RequestedItemIds.ToArray()); - cmd.GetParameter(index++).Value = job.Category; - cmd.GetParameter(index++).Value = job.ParentId; - cmd.GetParameter(index++).Value = job.UnwatchedOnly; - cmd.GetParameter(index++).Value = job.ItemLimit; - cmd.GetParameter(index++).Value = job.SyncNewContent; - cmd.GetParameter(index++).Value = job.DateCreated; - cmd.GetParameter(index++).Value = job.DateLastModified; - cmd.GetParameter(index++).Value = job.ItemCount; - - cmd.Transaction = transaction; + using (var cmd = connection.CreateCommand()) + { + if (insert) + { + cmd.CommandText = "insert into SyncJobs (Id, TargetId, Name, Profile, Quality, Bitrate, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount) values (@Id, @TargetId, @Name, @Profile, @Quality, @Bitrate, @Status, @Progress, @UserId, @ItemIds, @Category, @ParentId, @UnwatchedOnly, @ItemLimit, @SyncNewContent, @DateCreated, @DateLastModified, @ItemCount)"; + + cmd.Parameters.Add(cmd, "@Id"); + cmd.Parameters.Add(cmd, "@TargetId"); + cmd.Parameters.Add(cmd, "@Name"); + cmd.Parameters.Add(cmd, "@Profile"); + cmd.Parameters.Add(cmd, "@Quality"); + cmd.Parameters.Add(cmd, "@Bitrate"); + cmd.Parameters.Add(cmd, "@Status"); + cmd.Parameters.Add(cmd, "@Progress"); + cmd.Parameters.Add(cmd, "@UserId"); + cmd.Parameters.Add(cmd, "@ItemIds"); + cmd.Parameters.Add(cmd, "@Category"); + cmd.Parameters.Add(cmd, "@ParentId"); + cmd.Parameters.Add(cmd, "@UnwatchedOnly"); + cmd.Parameters.Add(cmd, "@ItemLimit"); + cmd.Parameters.Add(cmd, "@SyncNewContent"); + cmd.Parameters.Add(cmd, "@DateCreated"); + cmd.Parameters.Add(cmd, "@DateLastModified"); + cmd.Parameters.Add(cmd, "@ItemCount"); + } + else + { + cmd.CommandText = "update SyncJobs set TargetId=@TargetId,Name=@Name,Profile=@Profile,Quality=@Quality,Bitrate=@Bitrate,Status=@Status,Progress=@Progress,UserId=@UserId,ItemIds=@ItemIds,Category=@Category,ParentId=@ParentId,UnwatchedOnly=@UnwatchedOnly,ItemLimit=@ItemLimit,SyncNewContent=@SyncNewContent,DateCreated=@DateCreated,DateLastModified=@DateLastModified,ItemCount=@ItemCount where Id=@Id"; + + cmd.Parameters.Add(cmd, "@Id"); + cmd.Parameters.Add(cmd, "@TargetId"); + cmd.Parameters.Add(cmd, "@Name"); + cmd.Parameters.Add(cmd, "@Profile"); + cmd.Parameters.Add(cmd, "@Quality"); + cmd.Parameters.Add(cmd, "@Bitrate"); + cmd.Parameters.Add(cmd, "@Status"); + cmd.Parameters.Add(cmd, "@Progress"); + cmd.Parameters.Add(cmd, "@UserId"); + cmd.Parameters.Add(cmd, "@ItemIds"); + cmd.Parameters.Add(cmd, "@Category"); + cmd.Parameters.Add(cmd, "@ParentId"); + cmd.Parameters.Add(cmd, "@UnwatchedOnly"); + cmd.Parameters.Add(cmd, "@ItemLimit"); + cmd.Parameters.Add(cmd, "@SyncNewContent"); + cmd.Parameters.Add(cmd, "@DateCreated"); + cmd.Parameters.Add(cmd, "@DateLastModified"); + cmd.Parameters.Add(cmd, "@ItemCount"); + } - cmd.ExecuteNonQuery(); + IDbTransaction transaction = null; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + try + { + transaction = connection.BeginTransaction(); + + var index = 0; + + cmd.GetParameter(index++).Value = new Guid(job.Id); + cmd.GetParameter(index++).Value = job.TargetId; + cmd.GetParameter(index++).Value = job.Name; + cmd.GetParameter(index++).Value = job.Profile; + cmd.GetParameter(index++).Value = job.Quality; + cmd.GetParameter(index++).Value = job.Bitrate; + cmd.GetParameter(index++).Value = job.Status.ToString(); + cmd.GetParameter(index++).Value = job.Progress; + cmd.GetParameter(index++).Value = job.UserId; + cmd.GetParameter(index++).Value = string.Join(",", job.RequestedItemIds.ToArray()); + cmd.GetParameter(index++).Value = job.Category; + cmd.GetParameter(index++).Value = job.ParentId; + cmd.GetParameter(index++).Value = job.UnwatchedOnly; + cmd.GetParameter(index++).Value = job.ItemLimit; + cmd.GetParameter(index++).Value = job.SyncNewContent; + cmd.GetParameter(index++).Value = job.DateCreated; + cmd.GetParameter(index++).Value = job.DateLastModified; + cmd.GetParameter(index++).Value = job.ItemCount; + + cmd.Transaction = transaction; + + cmd.ExecuteNonQuery(); + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save record:", e); + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save record:", e); - if (transaction != null) - { - transaction.Rollback(); - } + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + } } - - WriteLock.Release(); } } @@ -374,56 +312,66 @@ namespace MediaBrowser.Server.Implementations.Sync } CheckDisposed(); - - await WriteLock.WaitAsync().ConfigureAwait(false); - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - var index = 0; - - _deleteJobCommand.GetParameter(index++).Value = new Guid(id); - _deleteJobCommand.Transaction = transaction; - _deleteJobCommand.ExecuteNonQuery(); - - index = 0; - _deleteJobItemsCommand.GetParameter(index++).Value = id; - _deleteJobItemsCommand.Transaction = transaction; - _deleteJobItemsCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) + using (var connection = await CreateConnection().ConfigureAwait(false)) { - Logger.ErrorException("Failed to save record:", e); - - if (transaction != null) + using (var deleteJobCommand = connection.CreateCommand()) { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); + using (var deleteJobItemsCommand = connection.CreateCommand()) + { + IDbTransaction transaction = null; + + try + { + // _deleteJobCommand + deleteJobCommand.CommandText = "delete from SyncJobs where Id=@Id"; + deleteJobCommand.Parameters.Add(deleteJobCommand, "@Id"); + + transaction = connection.BeginTransaction(); + + deleteJobCommand.GetParameter(0).Value = new Guid(id); + deleteJobCommand.Transaction = transaction; + deleteJobCommand.ExecuteNonQuery(); + + // _deleteJobItemsCommand + deleteJobItemsCommand.CommandText = "delete from SyncJobItems where JobId=@JobId"; + deleteJobItemsCommand.Parameters.Add(deleteJobItemsCommand, "@JobId"); + + deleteJobItemsCommand.GetParameter(0).Value = id; + deleteJobItemsCommand.Transaction = transaction; + deleteJobItemsCommand.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(); + } + } + } } - - WriteLock.Release(); } } @@ -435,83 +383,86 @@ namespace MediaBrowser.Server.Implementations.Sync } CheckDisposed(); - - using (var cmd = _connection.CreateCommand()) + + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = BaseJobSelectText; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = BaseJobSelectText; - var whereClauses = new List(); + var whereClauses = new List(); - if (query.Statuses.Length > 0) - { - var statuses = string.Join(",", query.Statuses.Select(i => "'" + i.ToString() + "'").ToArray()); + if (query.Statuses.Length > 0) + { + var statuses = string.Join(",", query.Statuses.Select(i => "'" + i.ToString() + "'").ToArray()); - whereClauses.Add(string.Format("Status in ({0})", statuses)); - } - if (!string.IsNullOrWhiteSpace(query.TargetId)) - { - whereClauses.Add("TargetId=@TargetId"); - cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId; - } - if (!string.IsNullOrWhiteSpace(query.UserId)) - { - whereClauses.Add("UserId=@UserId"); - cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId; - } - if (query.SyncNewContent.HasValue) - { - whereClauses.Add("SyncNewContent=@SyncNewContent"); - cmd.Parameters.Add(cmd, "@SyncNewContent", DbType.Boolean).Value = query.SyncNewContent.Value; - } + whereClauses.Add(string.Format("Status in ({0})", statuses)); + } + if (!string.IsNullOrWhiteSpace(query.TargetId)) + { + whereClauses.Add("TargetId=@TargetId"); + cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId; + } + if (!string.IsNullOrWhiteSpace(query.UserId)) + { + whereClauses.Add("UserId=@UserId"); + cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId; + } + if (query.SyncNewContent.HasValue) + { + whereClauses.Add("SyncNewContent=@SyncNewContent"); + cmd.Parameters.Add(cmd, "@SyncNewContent", DbType.Boolean).Value = query.SyncNewContent.Value; + } - cmd.CommandText += " mainTable"; + cmd.CommandText += " mainTable"; - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereTextWithoutPaging = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - var startIndex = query.StartIndex ?? 0; - if (startIndex > 0) - { - whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobs ORDER BY (Select Max(DateLastModified) from SyncJobs where TargetId=mainTable.TargetId) DESC, DateLastModified DESC LIMIT {0})", - startIndex.ToString(_usCulture))); - } + var startIndex = query.StartIndex ?? 0; + if (startIndex > 0) + { + whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobs ORDER BY (Select Max(DateLastModified) from SyncJobs where TargetId=mainTable.TargetId) DESC, DateLastModified DESC LIMIT {0})", + startIndex.ToString(_usCulture))); + } - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } + if (whereClauses.Count > 0) + { + cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + } - cmd.CommandText += " ORDER BY (Select Max(DateLastModified) from SyncJobs where TargetId=mainTable.TargetId) DESC, DateLastModified DESC"; + cmd.CommandText += " ORDER BY (Select Max(DateLastModified) from SyncJobs where TargetId=mainTable.TargetId) DESC, DateLastModified DESC"; - if (query.Limit.HasValue) - { - cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); - } + if (query.Limit.HasValue) + { + cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); + } - cmd.CommandText += "; select count (Id) from SyncJobs" + whereTextWithoutPaging; + cmd.CommandText += "; select count (Id) from SyncJobs" + whereTextWithoutPaging; - var list = new List(); - var count = 0; + var list = new List(); + var count = 0; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { - list.Add(GetJob(reader)); + while (reader.Read()) + { + list.Add(GetJob(reader)); + } + + if (reader.NextResult() && reader.Read()) + { + count = reader.GetInt32(0); + } } - if (reader.NextResult() && reader.Read()) + return new QueryResult() { - count = reader.GetInt32(0); - } + Items = list.ToArray(), + TotalRecordCount = count + }; } - - return new QueryResult() - { - Items = list.ToArray(), - TotalRecordCount = count - }; } } @@ -523,25 +474,28 @@ namespace MediaBrowser.Server.Implementations.Sync } CheckDisposed(); - + var guid = new Guid(id); - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = BaseJobItemSelectText + " where Id=@Id"; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = BaseJobItemSelectText + " where Id=@Id"; - cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; + cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { - return GetJobItem(reader); + if (reader.Read()) + { + return GetJobItem(reader); + } } } - } - return null; + return null; + } } private QueryResult GetJobItemReader(SyncJobItemQuery query, string baseSelectText, Func itemFactory) @@ -551,81 +505,84 @@ namespace MediaBrowser.Server.Implementations.Sync throw new ArgumentNullException("query"); } - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = baseSelectText; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = baseSelectText; - var whereClauses = new List(); + var whereClauses = new List(); - if (!string.IsNullOrWhiteSpace(query.JobId)) - { - whereClauses.Add("JobId=@JobId"); - cmd.Parameters.Add(cmd, "@JobId", DbType.String).Value = query.JobId; - } - if (!string.IsNullOrWhiteSpace(query.ItemId)) - { - whereClauses.Add("ItemId=@ItemId"); - cmd.Parameters.Add(cmd, "@ItemId", DbType.String).Value = query.ItemId; - } - if (!string.IsNullOrWhiteSpace(query.TargetId)) - { - whereClauses.Add("TargetId=@TargetId"); - cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId; - } + if (!string.IsNullOrWhiteSpace(query.JobId)) + { + whereClauses.Add("JobId=@JobId"); + cmd.Parameters.Add(cmd, "@JobId", DbType.String).Value = query.JobId; + } + if (!string.IsNullOrWhiteSpace(query.ItemId)) + { + whereClauses.Add("ItemId=@ItemId"); + cmd.Parameters.Add(cmd, "@ItemId", DbType.String).Value = query.ItemId; + } + if (!string.IsNullOrWhiteSpace(query.TargetId)) + { + whereClauses.Add("TargetId=@TargetId"); + cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId; + } - if (query.Statuses.Length > 0) - { - var statuses = string.Join(",", query.Statuses.Select(i => "'" + i.ToString() + "'").ToArray()); + if (query.Statuses.Length > 0) + { + var statuses = string.Join(",", query.Statuses.Select(i => "'" + i.ToString() + "'").ToArray()); - whereClauses.Add(string.Format("Status in ({0})", statuses)); - } + whereClauses.Add(string.Format("Status in ({0})", statuses)); + } - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereTextWithoutPaging = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - var startIndex = query.StartIndex ?? 0; - if (startIndex > 0) - { - whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobItems ORDER BY JobItemIndex, DateCreated LIMIT {0})", - startIndex.ToString(_usCulture))); - } + var startIndex = query.StartIndex ?? 0; + if (startIndex > 0) + { + whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobItems ORDER BY JobItemIndex, DateCreated LIMIT {0})", + startIndex.ToString(_usCulture))); + } - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } + if (whereClauses.Count > 0) + { + cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + } - cmd.CommandText += " ORDER BY JobItemIndex, DateCreated"; + cmd.CommandText += " ORDER BY JobItemIndex, DateCreated"; - if (query.Limit.HasValue) - { - cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); - } + if (query.Limit.HasValue) + { + cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); + } - cmd.CommandText += "; select count (Id) from SyncJobItems" + whereTextWithoutPaging; + cmd.CommandText += "; select count (Id) from SyncJobItems" + whereTextWithoutPaging; - var list = new List(); - var count = 0; + var list = new List(); + var count = 0; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { - list.Add(itemFactory(reader)); + while (reader.Read()) + { + list.Add(itemFactory(reader)); + } + + if (reader.NextResult() && reader.Read()) + { + count = reader.GetInt32(0); + } } - if (reader.NextResult() && reader.Read()) + return new QueryResult() { - count = reader.GetInt32(0); - } + Items = list.ToArray(), + TotalRecordCount = count + }; } - - return new QueryResult() - { - Items = list.ToArray(), - TotalRecordCount = count - }; } } @@ -641,15 +598,15 @@ namespace MediaBrowser.Server.Implementations.Sync public Task Create(SyncJobItem jobItem) { - return InsertOrUpdate(jobItem, _insertJobItemCommand); + return InsertOrUpdate(jobItem, true); } public Task Update(SyncJobItem jobItem) { - return InsertOrUpdate(jobItem, _updateJobItemCommand); + return InsertOrUpdate(jobItem, false); } - private async Task InsertOrUpdate(SyncJobItem jobItem, IDbCommand cmd) + private async Task InsertOrUpdate(SyncJobItem jobItem, bool insert) { if (jobItem == null) { @@ -657,68 +614,114 @@ namespace MediaBrowser.Server.Implementations.Sync } CheckDisposed(); - - await WriteLock.WaitAsync().ConfigureAwait(false); - IDbTransaction transaction = null; - - try + using (var connection = await CreateConnection().ConfigureAwait(false)) { - transaction = _connection.BeginTransaction(); - - var index = 0; - - cmd.GetParameter(index++).Value = new Guid(jobItem.Id); - cmd.GetParameter(index++).Value = jobItem.ItemId; - cmd.GetParameter(index++).Value = jobItem.ItemName; - cmd.GetParameter(index++).Value = jobItem.MediaSourceId; - cmd.GetParameter(index++).Value = jobItem.JobId; - cmd.GetParameter(index++).Value = jobItem.TemporaryPath; - cmd.GetParameter(index++).Value = jobItem.OutputPath; - cmd.GetParameter(index++).Value = jobItem.Status.ToString(); - cmd.GetParameter(index++).Value = jobItem.TargetId; - cmd.GetParameter(index++).Value = jobItem.DateCreated; - cmd.GetParameter(index++).Value = jobItem.Progress; - cmd.GetParameter(index++).Value = _json.SerializeToString(jobItem.AdditionalFiles); - cmd.GetParameter(index++).Value = jobItem.MediaSource == null ? null : _json.SerializeToString(jobItem.MediaSource); - cmd.GetParameter(index++).Value = jobItem.IsMarkedForRemoval; - cmd.GetParameter(index++).Value = jobItem.JobItemIndex; - cmd.GetParameter(index++).Value = jobItem.ItemDateModifiedTicks; - - cmd.Transaction = transaction; + using (var cmd = connection.CreateCommand()) + { + if (insert) + { + cmd.CommandText = "insert into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex, ItemDateModifiedTicks) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval, @JobItemIndex, @ItemDateModifiedTicks)"; + + cmd.Parameters.Add(cmd, "@Id"); + cmd.Parameters.Add(cmd, "@ItemId"); + cmd.Parameters.Add(cmd, "@ItemName"); + cmd.Parameters.Add(cmd, "@MediaSourceId"); + cmd.Parameters.Add(cmd, "@JobId"); + cmd.Parameters.Add(cmd, "@TemporaryPath"); + cmd.Parameters.Add(cmd, "@OutputPath"); + cmd.Parameters.Add(cmd, "@Status"); + cmd.Parameters.Add(cmd, "@TargetId"); + cmd.Parameters.Add(cmd, "@DateCreated"); + cmd.Parameters.Add(cmd, "@Progress"); + cmd.Parameters.Add(cmd, "@AdditionalFiles"); + cmd.Parameters.Add(cmd, "@MediaSource"); + cmd.Parameters.Add(cmd, "@IsMarkedForRemoval"); + cmd.Parameters.Add(cmd, "@JobItemIndex"); + cmd.Parameters.Add(cmd, "@ItemDateModifiedTicks"); + } + else + { + // cmd + cmd.CommandText = "update SyncJobItems set ItemId=@ItemId,ItemName=@ItemName,MediaSourceId=@MediaSourceId,JobId=@JobId,TemporaryPath=@TemporaryPath,OutputPath=@OutputPath,Status=@Status,TargetId=@TargetId,DateCreated=@DateCreated,Progress=@Progress,AdditionalFiles=@AdditionalFiles,MediaSource=@MediaSource,IsMarkedForRemoval=@IsMarkedForRemoval,JobItemIndex=@JobItemIndex,ItemDateModifiedTicks=@ItemDateModifiedTicks where Id=@Id"; + + cmd.Parameters.Add(cmd, "@Id"); + cmd.Parameters.Add(cmd, "@ItemId"); + cmd.Parameters.Add(cmd, "@ItemName"); + cmd.Parameters.Add(cmd, "@MediaSourceId"); + cmd.Parameters.Add(cmd, "@JobId"); + cmd.Parameters.Add(cmd, "@TemporaryPath"); + cmd.Parameters.Add(cmd, "@OutputPath"); + cmd.Parameters.Add(cmd, "@Status"); + cmd.Parameters.Add(cmd, "@TargetId"); + cmd.Parameters.Add(cmd, "@DateCreated"); + cmd.Parameters.Add(cmd, "@Progress"); + cmd.Parameters.Add(cmd, "@AdditionalFiles"); + cmd.Parameters.Add(cmd, "@MediaSource"); + cmd.Parameters.Add(cmd, "@IsMarkedForRemoval"); + cmd.Parameters.Add(cmd, "@JobItemIndex"); + cmd.Parameters.Add(cmd, "@ItemDateModifiedTicks"); + } - cmd.ExecuteNonQuery(); + IDbTransaction transaction = null; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + try + { + transaction = connection.BeginTransaction(); + + var index = 0; + + cmd.GetParameter(index++).Value = new Guid(jobItem.Id); + cmd.GetParameter(index++).Value = jobItem.ItemId; + cmd.GetParameter(index++).Value = jobItem.ItemName; + cmd.GetParameter(index++).Value = jobItem.MediaSourceId; + cmd.GetParameter(index++).Value = jobItem.JobId; + cmd.GetParameter(index++).Value = jobItem.TemporaryPath; + cmd.GetParameter(index++).Value = jobItem.OutputPath; + cmd.GetParameter(index++).Value = jobItem.Status.ToString(); + cmd.GetParameter(index++).Value = jobItem.TargetId; + cmd.GetParameter(index++).Value = jobItem.DateCreated; + cmd.GetParameter(index++).Value = jobItem.Progress; + cmd.GetParameter(index++).Value = _json.SerializeToString(jobItem.AdditionalFiles); + cmd.GetParameter(index++).Value = jobItem.MediaSource == null ? null : _json.SerializeToString(jobItem.MediaSource); + cmd.GetParameter(index++).Value = jobItem.IsMarkedForRemoval; + cmd.GetParameter(index++).Value = jobItem.JobItemIndex; + cmd.GetParameter(index++).Value = jobItem.ItemDateModifiedTicks; + + cmd.Transaction = transaction; + + cmd.ExecuteNonQuery(); + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save record:", e); + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save record:", e); - if (transaction != null) - { - transaction.Rollback(); - } + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + } } - - WriteLock.Release(); } } @@ -809,19 +812,5 @@ namespace MediaBrowser.Server.Implementations.Sync return item; } - - protected override void CloseConnection() - { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } } } -- cgit v1.2.3 From 96b1ddfddf43cdc4d18d1de0f49027ae6f0ea1ac Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 11 Jun 2016 13:26:35 -0400 Subject: update user data db --- .../Persistence/BaseSqliteRepository.cs | 6 - .../Persistence/SqliteUserDataRepository.cs | 313 ++++++++++----------- 2 files changed, 153 insertions(+), 166 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs index f9c892b76a..de0c245bdb 100644 --- a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs @@ -45,8 +45,6 @@ namespace MediaBrowser.Server.Implementations.Persistence { CheckDisposed(); - await WriteLock.WaitAsync().ConfigureAwait(false); - try { using (var cmd = connection.CreateCommand()) @@ -61,10 +59,6 @@ namespace MediaBrowser.Server.Implementations.Persistence throw; } - finally - { - WriteLock.Release(); - } } private readonly object _disposeLock = new object(); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index d81f4ad37b..0ce27fa5a2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -15,12 +15,9 @@ namespace MediaBrowser.Server.Implementations.Persistence { public class SqliteUserDataRepository : BaseSqliteRepository, IUserDataRepository { - private IDbConnection _connection; - private readonly IApplicationPaths _appPaths; - public SqliteUserDataRepository(ILogManager logManager, IApplicationPaths appPaths, IDbConnector connector) : base(logManager, connector) { - _appPaths = appPaths; + DbFilePath = Path.Combine(appPaths.DataPath, "userdata_v2.db"); } /// @@ -41,11 +38,9 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Task. public async Task Initialize(IDbConnector dbConnector) { - var dbFile = Path.Combine(_appPaths.DataPath, "userdata_v2.db"); - - _connection = await dbConnector.Connect(dbFile, false).ConfigureAwait(false); - - string[] queries = { + using (var connection = await CreateConnection().ConfigureAwait(false)) + { + string[] queries = { "create table if not exists userdata (key nvarchar, userId GUID, rating float null, played bit, playCount int, isFavorite bit, playbackPositionTicks bigint, lastPlayedDate datetime null)", @@ -58,10 +53,11 @@ namespace MediaBrowser.Server.Implementations.Persistence "pragma shrink_memory" }; - _connection.RunQueries(queries, Logger); + connection.RunQueries(queries, Logger); - _connection.AddColumn(Logger, "userdata", "AudioStreamIndex", "int"); - _connection.AddColumn(Logger, "userdata", "SubtitleStreamIndex", "int"); + connection.AddColumn(Logger, "userdata", "AudioStreamIndex", "int"); + connection.AddColumn(Logger, "userdata", "SubtitleStreamIndex", "int"); + } } /// @@ -123,64 +119,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; - using (var cmd = _connection.CreateCommand()) + try { - cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; + transaction = connection.BeginTransaction(); - cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userData.Rating; - cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userData.Played; - cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userData.PlayCount; - cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userData.IsFavorite; - cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userData.PlaybackPositionTicks; - cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userData.LastPlayedDate; - cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userData.AudioStreamIndex; - cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userData.SubtitleStreamIndex; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - } + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userData.Rating; + cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userData.Played; + cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userData.PlayCount; + cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userData.IsFavorite; + cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userData.PlaybackPositionTicks; + cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userData.LastPlayedDate; + cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userData.AudioStreamIndex; + cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userData.SubtitleStreamIndex; - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save user data:", e); + cmd.Transaction = transaction; + + cmd.ExecuteNonQuery(); + } - if (transaction != null) + transaction.Commit(); + } + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to save user data:", e); - throw; - } - finally - { - if (transaction != null) + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + finally { - transaction.Dispose(); + if (transaction != null) + { + transaction.Dispose(); + } } - - WriteLock.Release(); } } @@ -195,69 +190,68 @@ 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 userItemData in userData) + try { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; + transaction = connection.BeginTransaction(); - cmd.Parameters.Add(cmd, "@key", DbType.String).Value = userItemData.Key; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userItemData.Rating; - cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userItemData.Played; - cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userItemData.PlayCount; - cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userItemData.IsFavorite; - cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userItemData.PlaybackPositionTicks; - cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userItemData.LastPlayedDate; - cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userItemData.AudioStreamIndex; - cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userItemData.SubtitleStreamIndex; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); + foreach (var userItemData in userData) + { + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; + + cmd.Parameters.Add(cmd, "@key", DbType.String).Value = userItemData.Key; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userItemData.Rating; + cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userItemData.Played; + cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userItemData.PlayCount; + cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userItemData.IsFavorite; + cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userItemData.PlaybackPositionTicks; + cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userItemData.LastPlayedDate; + cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userItemData.AudioStreamIndex; + cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userItemData.SubtitleStreamIndex; + + cmd.Transaction = transaction; + + cmd.ExecuteNonQuery(); + } + + cancellationToken.ThrowIfCancellationRequested(); } - cancellationToken.ThrowIfCancellationRequested(); + transaction.Commit(); } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to save user data:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save user data:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + finally { - transaction.Dispose(); + if (transaction != null) + { + transaction.Dispose(); + } } - - WriteLock.Release(); } } @@ -283,22 +277,25 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("key"); } - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where key = @key and userId=@userId"; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where key = @key and userId=@userId"; - cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { - return ReadRow(reader); + if (reader.Read()) + { + return ReadRow(reader); + } } - } - return null; + return null; + } } } @@ -313,38 +310,41 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("keys"); } - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - var index = 0; - var excludeIds = new List(); - var builder = new StringBuilder(); - foreach (var key in keys) + using (var cmd = connection.CreateCommand()) { - var paramName = "@Key" + index; - excludeIds.Add("Key =" + paramName); - cmd.Parameters.Add(cmd, paramName, DbType.String).Value = key; - builder.Append(" WHEN Key=" + paramName + " THEN " + index); - index++; - } + var index = 0; + var excludeIds = new List(); + var builder = new StringBuilder(); + foreach (var key in keys) + { + var paramName = "@Key" + index; + excludeIds.Add("Key =" + paramName); + cmd.Parameters.Add(cmd, paramName, DbType.String).Value = key; + builder.Append(" WHEN Key=" + paramName + " THEN " + index); + index++; + } - var keyText = string.Join(" OR ", excludeIds.ToArray()); + var keyText = string.Join(" OR ", excludeIds.ToArray()); - cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId AND (" + keyText + ") "; + cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId AND (" + keyText + ") "; - cmd.CommandText += " ORDER BY (Case " + builder + " Else " + keys.Count.ToString(CultureInfo.InvariantCulture) + " End )"; - cmd.CommandText += " LIMIT 1"; + cmd.CommandText += " ORDER BY (Case " + builder + " Else " + keys.Count.ToString(CultureInfo.InvariantCulture) + " End )"; + cmd.CommandText += " LIMIT 1"; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { - return ReadRow(reader); + if (reader.Read()) + { + return ReadRow(reader); + } } - } - return null; + return null; + } } } @@ -360,20 +360,27 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("userId"); } - using (var cmd = _connection.CreateCommand()) + var list = new List(); + + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId"; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId"; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - yield return ReadRow(reader); + while (reader.Read()) + { + list.Add(ReadRow(reader)); + } } } } + + return list; } /// @@ -414,19 +421,5 @@ namespace MediaBrowser.Server.Implementations.Persistence return userData; } - - protected override void CloseConnection() - { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } } } \ No newline at end of file -- cgit v1.2.3 From da6e94396fb417077010d3a2e5f3282bf06234c3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 11 Jun 2016 16:12:01 -0400 Subject: update connection pooling --- .../Chapters/IChapterManager.cs | 2 +- .../Persistence/IItemRepository.cs | 4 +- MediaBrowser.Providers/Chapters/ChapterManager.cs | 2 +- .../Activity/ActivityRepository.cs | 7 +- .../Library/LibraryManager.cs | 10 +- .../LiveTv/LiveTvManager.cs | 2 +- .../Notifications/SqliteNotificationsRepository.cs | 7 +- .../Persistence/BaseSqliteRepository.cs | 12 +- .../SqliteDisplayPreferencesRepository.cs | 7 +- .../Persistence/SqliteExtensions.cs | 13 +- .../SqliteFileOrganizationRepository.cs | 7 +- .../Persistence/SqliteItemRepository.cs | 2855 ++++++++++---------- .../Persistence/SqliteUserDataRepository.cs | 7 +- .../Persistence/SqliteUserRepository.cs | 3 - .../Security/AuthenticationRepository.cs | 7 +- .../Social/SharingRepository.cs | 3 - .../Sync/SyncRepository.cs | 3 - 17 files changed, 1533 insertions(+), 1418 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs index 676ef9c561..27e06fb8dd 100644 --- a/MediaBrowser.Controller/Chapters/IChapterManager.cs +++ b/MediaBrowser.Controller/Chapters/IChapterManager.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Chapters /// The chapters. /// The cancellation token. /// Task. - Task SaveChapters(string itemId, IEnumerable chapters, CancellationToken cancellationToken); + Task SaveChapters(string itemId, List chapters, CancellationToken cancellationToken); /// /// Searches the specified video. diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 7bcc36958a..80a6e4042f 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Persistence /// The chapters. /// The cancellation token. /// Task. - Task SaveChapters(Guid id, IEnumerable chapters, CancellationToken cancellationToken); + Task SaveChapters(Guid id, List chapters, CancellationToken cancellationToken); /// /// Gets the media streams. @@ -97,7 +97,7 @@ namespace MediaBrowser.Controller.Persistence /// The streams. /// The cancellation token. /// Task. - Task SaveMediaStreams(Guid id, IEnumerable streams, CancellationToken cancellationToken); + Task SaveMediaStreams(Guid id, List streams, CancellationToken cancellationToken); /// /// Gets the item ids. diff --git a/MediaBrowser.Providers/Chapters/ChapterManager.cs b/MediaBrowser.Providers/Chapters/ChapterManager.cs index 6e2cd77eb3..88811c850d 100644 --- a/MediaBrowser.Providers/Chapters/ChapterManager.cs +++ b/MediaBrowser.Providers/Chapters/ChapterManager.cs @@ -259,7 +259,7 @@ namespace MediaBrowser.Providers.Chapters return _itemRepo.GetChapters(new Guid(itemId)); } - public Task SaveChapters(string itemId, IEnumerable chapters, CancellationToken cancellationToken) + public Task SaveChapters(string itemId, List chapters, CancellationToken cancellationToken) { return _itemRepo.SaveChapters(new Guid(itemId), chapters, cancellationToken); } diff --git a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs index d6ae381e9d..c992def39d 100644 --- a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs +++ b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs @@ -30,12 +30,7 @@ namespace MediaBrowser.Server.Implementations.Activity string[] queries = { "create table if not exists ActivityLogEntries (Id GUID PRIMARY KEY, Name TEXT, Overview TEXT, ShortOverview TEXT, Type TEXT, ItemId TEXT, UserId TEXT, DateCreated DATETIME, LogSeverity TEXT)", - "create index if not exists idx_ActivityLogEntries on ActivityLogEntries(Id)", - - //pragmas - "pragma temp_store = memory", - - "pragma shrink_memory" + "create index if not exists idx_ActivityLogEntries on ActivityLogEntries(Id)" }; connection.RunQueries(queries, Logger); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 503fb1aa74..2483ec93e8 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1309,7 +1309,15 @@ namespace MediaBrowser.Server.Implementations.Library AddUserToQuery(query, query.User); } - return ItemRepository.GetItems(query); + if (query.EnableTotalRecordCount) + { + return ItemRepository.GetItems(query); + } + + return new QueryResult + { + Items = ItemRepository.GetItemList(query).ToArray() + }; } public List GetItemIds(InternalItemsQuery query) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index d7491d2de1..171ed824e8 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -952,7 +952,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (query.Limit.HasValue) { - internalQuery.Limit = Math.Max(query.Limit.Value * 5, 300); + internalQuery.Limit = Math.Max(query.Limit.Value * 5, 200); } if (query.HasAired.HasValue) diff --git a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs index 6c3bc3050e..be8c6d48d6 100644 --- a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs +++ b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs @@ -32,12 +32,7 @@ namespace MediaBrowser.Server.Implementations.Notifications "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_Notifications2 on Notifications(UserId)", - - //pragmas - "pragma temp_store = memory", - - "pragma shrink_memory" + "create index if not exists idx_Notifications2 on Notifications(UserId)" }; connection.RunQueries(queries, Logger); diff --git a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs index de0c245bdb..c6e7952294 100644 --- a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs @@ -20,9 +20,17 @@ namespace MediaBrowser.Server.Implementations.Persistence Logger = logManager.GetLogger(GetType().Name); } - protected Task CreateConnection(bool isReadOnly = false) + protected virtual async Task CreateConnection(bool isReadOnly = false) { - return DbConnector.Connect(DbFilePath, false, true); + var connection = await DbConnector.Connect(DbFilePath, false, true).ConfigureAwait(false); + + connection.RunQueries(new [] + { + "pragma temp_store = memory" + + }, Logger); + + return connection; } private bool _disposed; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs index 1a6a88ebe2..40970dbe4d 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs @@ -53,12 +53,7 @@ namespace MediaBrowser.Server.Implementations.Persistence 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)", - - //pragmas - "pragma temp_store = memory", - - "pragma shrink_memory" + "create unique index if not exists userdisplaypreferencesindex on userdisplaypreferences (id, userId, client)" }; connection.RunQueries(queries, Logger); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index cc9e3ebccf..0a76381e12 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -26,8 +26,6 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("dbPath"); } - logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); - var connectionstr = new SQLiteConnectionStringBuilder { PageSize = 4096, @@ -39,7 +37,16 @@ namespace MediaBrowser.Server.Implementations.Persistence ReadOnly = isReadOnly }; - var connection = new SQLiteConnection(connectionstr.ConnectionString); + var connectionString = connectionstr.ConnectionString; + + if (enablePooling) + { + connectionString += ";Max Pool Size=100"; + } + + //logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, connectionString); + + var connection = new SQLiteConnection(connectionString); await connection.OpenAsync().ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs index 8a4ba6460d..d7e8afdd4c 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs @@ -44,12 +44,7 @@ namespace MediaBrowser.Server.Implementations.Persistence string[] queries = { "create table if not exists FileOrganizerResults (ResultId GUID PRIMARY KEY, OriginalPath TEXT, TargetPath TEXT, FileLength INT, OrganizationDate datetime, Status TEXT, OrganizationType TEXT, StatusMessage TEXT, ExtractedName TEXT, ExtractedYear int null, ExtractedSeasonNumber int null, ExtractedEpisodeNumber int null, ExtractedEndingEpisodeNumber, DuplicatePaths TEXT int null)", - "create index if not exists idx_FileOrganizerResults on FileOrganizerResults(ResultId)", - - //pragmas - "pragma temp_store = memory", - - "pragma shrink_memory" + "create index if not exists idx_FileOrganizerResults on FileOrganizerResults(ResultId)" }; _connection.RunQueries(queries, Logger); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 9bfdd879da..0eb56a1fc4 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -31,8 +31,6 @@ namespace MediaBrowser.Server.Implementations.Persistence /// public class SqliteItemRepository : BaseSqliteRepository, IItemRepository { - private IDbConnection _connection; - private readonly TypeMapper _typeMapper = new TypeMapper(); /// @@ -58,42 +56,8 @@ namespace MediaBrowser.Server.Implementations.Persistence /// private readonly IServerConfigurationManager _config; - /// - /// The _save item command - /// - private IDbCommand _saveItemCommand; - private readonly string _criticReviewsPath; - private IDbCommand _deleteItemCommand; - - private IDbCommand _deletePeopleCommand; - private IDbCommand _savePersonCommand; - - private IDbCommand _deleteChaptersCommand; - private IDbCommand _saveChapterCommand; - - private IDbCommand _deleteStreamsCommand; - private IDbCommand _saveStreamCommand; - - private IDbCommand _deleteAncestorsCommand; - private IDbCommand _saveAncestorCommand; - - private IDbCommand _deleteUserDataKeysCommand; - private IDbCommand _saveUserDataKeysCommand; - - private IDbCommand _deleteItemValuesCommand; - private IDbCommand _saveItemValuesCommand; - - private IDbCommand _deleteProviderIdsCommand; - private IDbCommand _saveProviderIdsCommand; - - private IDbCommand _deleteImagesCommand; - private IDbCommand _saveImagesCommand; - - private IDbCommand _updateInheritedRatingCommand; - private IDbCommand _updateInheritedTagsCommand; - public const int LatestSchemaVersion = 89; /// @@ -115,6 +79,22 @@ namespace MediaBrowser.Server.Implementations.Persistence _jsonSerializer = jsonSerializer; _criticReviewsPath = Path.Combine(_config.ApplicationPaths.DataPath, "critic-reviews"); + DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); + } + + protected override async Task CreateConnection(bool isReadOnly = false) + { + var connection = await DbConnector.Connect(DbFilePath, false, true, 20000).ConfigureAwait(false); + + //AttachUserDataDb(connection); + + //connection.RunQueries(new [] + //{ + // "pragma locking_mode=EXCLUSIVE" + + //}, Logger); + + return connection; } private const string ChaptersTableName = "Chapters2"; @@ -125,14 +105,12 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Task. public async Task Initialize(IDbConnector dbConnector) { - var dbFile = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); - - _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))"; + using (var connection = await CreateConnection().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))"; - string[] queries = { + string[] queries = { "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID, Path TEXT)", "create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)", @@ -165,113 +143,113 @@ namespace MediaBrowser.Server.Implementations.Persistence createMediaStreamsTableCommand, "create index if not exists idx_mediastreams1 on mediastreams(ItemId)", - - //pragmas - "pragma temp_store = memory", - - "pragma shrink_memory" + }; - _connection.RunQueries(queries, Logger); - - _connection.AddColumn(Logger, "AncestorIds", "AncestorIdText", "Text"); - - _connection.AddColumn(Logger, "TypedBaseItems", "Path", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "StartDate", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "EndDate", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "ChannelId", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsMovie", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsSports", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsKids", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "CommunityRating", "Float"); - _connection.AddColumn(Logger, "TypedBaseItems", "CustomRating", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IndexNumber", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsLocked", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "Name", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "OfficialRating", "Text"); - - _connection.AddColumn(Logger, "TypedBaseItems", "MediaType", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Overview", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ParentIndexNumber", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "PremiereDate", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "ProductionYear", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "ParentId", "GUID"); - _connection.AddColumn(Logger, "TypedBaseItems", "Genres", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ParentalRatingValue", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "SchemaVersion", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "SortName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "RunTimeTicks", "BIGINT"); - - _connection.AddColumn(Logger, "TypedBaseItems", "OfficialRatingDescription", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "HomePageUrl", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "VoteCount", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "DisplayMediaType", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "DateCreated", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "DateModified", "DATETIME"); - - _connection.AddColumn(Logger, "TypedBaseItems", "ForcedSortName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsOffline", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "LocationType", "Text"); - - _connection.AddColumn(Logger, "TypedBaseItems", "IsSeries", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsLive", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsNews", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsPremiere", "BIT"); - - _connection.AddColumn(Logger, "TypedBaseItems", "EpisodeTitle", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsRepeat", "BIT"); - - _connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataLanguage", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataCountryCode", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsHD", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "ExternalEtag", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "DateLastRefreshed", "DATETIME"); - - _connection.AddColumn(Logger, "TypedBaseItems", "DateLastSaved", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsInMixedFolder", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "LockedFields", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Studios", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Audio", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "ExternalServiceId", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "Tags", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsFolder", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "InheritedParentalRatingValue", "INT"); - _connection.AddColumn(Logger, "TypedBaseItems", "UnratedType", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "TopParentId", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsItemByName", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "SourceType", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "TrailerTypes", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "CriticRating", "Float"); - _connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "PresentationUniqueKey", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "SlugName", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "OriginalTitle", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "PrimaryVersionId", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME"); - _connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text"); - _connection.AddColumn(Logger, "TypedBaseItems", "IsVirtualItem", "BIT"); - _connection.AddColumn(Logger, "TypedBaseItems", "SeriesName", "Text"); - - _connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT"); - - string[] postQueries = - { + connection.RunQueries(queries, Logger); + + connection.AddColumn(Logger, "AncestorIds", "AncestorIdText", "Text"); + + connection.AddColumn(Logger, "TypedBaseItems", "Path", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "StartDate", "DATETIME"); + connection.AddColumn(Logger, "TypedBaseItems", "EndDate", "DATETIME"); + connection.AddColumn(Logger, "TypedBaseItems", "ChannelId", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "IsMovie", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "IsSports", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "IsKids", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "CommunityRating", "Float"); + connection.AddColumn(Logger, "TypedBaseItems", "CustomRating", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "IndexNumber", "INT"); + connection.AddColumn(Logger, "TypedBaseItems", "IsLocked", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "Name", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "OfficialRating", "Text"); + + connection.AddColumn(Logger, "TypedBaseItems", "MediaType", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "Overview", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "ParentIndexNumber", "INT"); + connection.AddColumn(Logger, "TypedBaseItems", "PremiereDate", "DATETIME"); + connection.AddColumn(Logger, "TypedBaseItems", "ProductionYear", "INT"); + connection.AddColumn(Logger, "TypedBaseItems", "ParentId", "GUID"); + connection.AddColumn(Logger, "TypedBaseItems", "Genres", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "ParentalRatingValue", "INT"); + connection.AddColumn(Logger, "TypedBaseItems", "SchemaVersion", "INT"); + connection.AddColumn(Logger, "TypedBaseItems", "SortName", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "RunTimeTicks", "BIGINT"); + + connection.AddColumn(Logger, "TypedBaseItems", "OfficialRatingDescription", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "HomePageUrl", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "VoteCount", "INT"); + connection.AddColumn(Logger, "TypedBaseItems", "DisplayMediaType", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "DateCreated", "DATETIME"); + connection.AddColumn(Logger, "TypedBaseItems", "DateModified", "DATETIME"); + + connection.AddColumn(Logger, "TypedBaseItems", "ForcedSortName", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "IsOffline", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "LocationType", "Text"); + + connection.AddColumn(Logger, "TypedBaseItems", "IsSeries", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "IsLive", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "IsNews", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "IsPremiere", "BIT"); + + connection.AddColumn(Logger, "TypedBaseItems", "EpisodeTitle", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "IsRepeat", "BIT"); + + connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataLanguage", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataCountryCode", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "IsHD", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "ExternalEtag", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "DateLastRefreshed", "DATETIME"); + + connection.AddColumn(Logger, "TypedBaseItems", "DateLastSaved", "DATETIME"); + connection.AddColumn(Logger, "TypedBaseItems", "IsInMixedFolder", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "LockedFields", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "Studios", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "Audio", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "ExternalServiceId", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "Tags", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "IsFolder", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "InheritedParentalRatingValue", "INT"); + connection.AddColumn(Logger, "TypedBaseItems", "UnratedType", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "TopParentId", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "IsItemByName", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "SourceType", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "TrailerTypes", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "CriticRating", "Float"); + connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); + connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "PresentationUniqueKey", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "SlugName", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "OriginalTitle", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "PrimaryVersionId", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME"); + connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text"); + connection.AddColumn(Logger, "TypedBaseItems", "IsVirtualItem", "BIT"); + connection.AddColumn(Logger, "TypedBaseItems", "SeriesName", "Text"); + + connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT"); + + string[] postQueries = + { "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)", "create index if not exists idx_Type on TypedBaseItems(Type)", "create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)", "create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)" - }; + }; - _connection.RunQueries(postQueries, Logger); + connection.RunQueries(postQueries, Logger); - PrepareStatements(); + new MediaStreamColumns(connection, Logger).AddColumns(); - new MediaStreamColumns(_connection, Logger).AddColumns(); + //AttachUserDataDb(connection); + } + } - DataExtensions.Attach(_connection, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"), "UserDataDb"); + private void AttachUserDataDb(IDbConnection connection) + { + DataExtensions.Attach(connection, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"), "UserDataDb" + Guid.NewGuid().ToString("N")); } private readonly string[] _retriveItemColumns = @@ -373,220 +351,6 @@ namespace MediaBrowser.Server.Implementations.Persistence "CodecTimeBase" }; - /// - /// Prepares the statements. - /// - private void PrepareStatements() - { - var saveColumns = new List - { - "guid", - "type", - "data", - "Path", - "StartDate", - "EndDate", - "ChannelId", - "IsKids", - "IsMovie", - "IsSports", - "IsSeries", - "IsLive", - "IsNews", - "IsPremiere", - "EpisodeTitle", - "IsRepeat", - "CommunityRating", - "CustomRating", - "IndexNumber", - "IsLocked", - "Name", - "OfficialRating", - "MediaType", - "Overview", - "ParentIndexNumber", - "PremiereDate", - "ProductionYear", - "ParentId", - "Genres", - "ParentalRatingValue", - "InheritedParentalRatingValue", - "SchemaVersion", - "SortName", - "RunTimeTicks", - "OfficialRatingDescription", - "HomePageUrl", - "VoteCount", - "DisplayMediaType", - "DateCreated", - "DateModified", - "ForcedSortName", - "IsOffline", - "LocationType", - "PreferredMetadataLanguage", - "PreferredMetadataCountryCode", - "IsHD", - "ExternalEtag", - "DateLastRefreshed", - "DateLastSaved", - "IsInMixedFolder", - "LockedFields", - "Studios", - "Audio", - "ExternalServiceId", - "Tags", - "IsFolder", - "UnratedType", - "TopParentId", - "IsItemByName", - "SourceType", - "TrailerTypes", - "CriticRating", - "CriticRatingSummary", - "DateModifiedDuringLastRefresh", - "InheritedTags", - "CleanName", - "PresentationUniqueKey", - "SlugName", - "OriginalTitle", - "PrimaryVersionId", - "DateLastMediaAdded", - "Album", - "IsVirtualItem", - "SeriesName" - }; - _saveItemCommand = _connection.CreateCommand(); - _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; - - for (var i = 1; i <= saveColumns.Count; i++) - { - if (i > 1) - { - _saveItemCommand.CommandText += ","; - } - _saveItemCommand.CommandText += "@" + i.ToString(CultureInfo.InvariantCulture); - - _saveItemCommand.Parameters.Add(_saveItemCommand, "@" + i.ToString(CultureInfo.InvariantCulture)); - } - _saveItemCommand.CommandText += ")"; - - _deleteItemCommand = _connection.CreateCommand(); - _deleteItemCommand.CommandText = "delete from TypedBaseItems where guid=@Id"; - _deleteItemCommand.Parameters.Add(_deleteItemCommand, "@Id"); - - // People - _deletePeopleCommand = _connection.CreateCommand(); - _deletePeopleCommand.CommandText = "delete from People where ItemId=@Id"; - _deletePeopleCommand.Parameters.Add(_deletePeopleCommand, "@Id"); - - _savePersonCommand = _connection.CreateCommand(); - _savePersonCommand.CommandText = "insert into People (ItemId, Name, Role, PersonType, SortOrder, ListOrder) values (@ItemId, @Name, @Role, @PersonType, @SortOrder, @ListOrder)"; - _savePersonCommand.Parameters.Add(_savePersonCommand, "@ItemId"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@Name"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@Role"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@PersonType"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@SortOrder"); - _savePersonCommand.Parameters.Add(_savePersonCommand, "@ListOrder"); - - // Ancestors - _deleteAncestorsCommand = _connection.CreateCommand(); - _deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id"; - _deleteAncestorsCommand.Parameters.Add(_deleteAncestorsCommand, "@Id"); - - _saveAncestorCommand = _connection.CreateCommand(); - _saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId, AncestorIdText) values (@ItemId, @AncestorId, @AncestorIdText)"; - _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@ItemId"); - _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorId"); - _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorIdText"); - - // Chapters - _deleteChaptersCommand = _connection.CreateCommand(); - _deleteChaptersCommand.CommandText = "delete from " + ChaptersTableName + " where ItemId=@ItemId"; - _deleteChaptersCommand.Parameters.Add(_deleteChaptersCommand, "@ItemId"); - - _saveChapterCommand = _connection.CreateCommand(); - _saveChapterCommand.CommandText = "replace into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath) values (@ItemId, @ChapterIndex, @StartPositionTicks, @Name, @ImagePath)"; - - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ItemId"); - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ChapterIndex"); - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@StartPositionTicks"); - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@Name"); - _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ImagePath"); - - // MediaStreams - _deleteStreamsCommand = _connection.CreateCommand(); - _deleteStreamsCommand.CommandText = "delete from mediastreams where ItemId=@ItemId"; - _deleteStreamsCommand.Parameters.Add(_deleteStreamsCommand, "@ItemId"); - - _saveStreamCommand = _connection.CreateCommand(); - - _saveStreamCommand.CommandText = string.Format("replace into mediastreams ({0}) values ({1})", - string.Join(",", _mediaStreamSaveColumns), - string.Join(",", _mediaStreamSaveColumns.Select(i => "@" + i).ToArray())); - - foreach (var col in _mediaStreamSaveColumns) - { - _saveStreamCommand.Parameters.Add(_saveStreamCommand, "@" + col); - } - - _updateInheritedRatingCommand = _connection.CreateCommand(); - _updateInheritedRatingCommand.CommandText = "Update TypedBaseItems set InheritedParentalRatingValue=@InheritedParentalRatingValue where Guid=@Guid"; - _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@Guid"); - _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@InheritedParentalRatingValue"); - - _updateInheritedTagsCommand = _connection.CreateCommand(); - _updateInheritedTagsCommand.CommandText = "Update TypedBaseItems set InheritedTags=@InheritedTags where Guid=@Guid"; - _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@Guid"); - _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@InheritedTags"); - - // user data - _deleteUserDataKeysCommand = _connection.CreateCommand(); - _deleteUserDataKeysCommand.CommandText = "delete from UserDataKeys where ItemId=@Id"; - _deleteUserDataKeysCommand.Parameters.Add(_deleteUserDataKeysCommand, "@Id"); - - _saveUserDataKeysCommand = _connection.CreateCommand(); - _saveUserDataKeysCommand.CommandText = "insert into UserDataKeys (ItemId, UserDataKey, Priority) values (@ItemId, @UserDataKey, @Priority)"; - _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@ItemId"); - _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@UserDataKey"); - _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@Priority"); - - // item values - _deleteItemValuesCommand = _connection.CreateCommand(); - _deleteItemValuesCommand.CommandText = "delete from ItemValues where ItemId=@Id"; - _deleteItemValuesCommand.Parameters.Add(_deleteItemValuesCommand, "@Id"); - - _saveItemValuesCommand = _connection.CreateCommand(); - _saveItemValuesCommand.CommandText = "insert into ItemValues (ItemId, Type, Value) values (@ItemId, @Type, @Value)"; - _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@ItemId"); - _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Type"); - _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Value"); - - // provider ids - _deleteProviderIdsCommand = _connection.CreateCommand(); - _deleteProviderIdsCommand.CommandText = "delete from ProviderIds where ItemId=@Id"; - _deleteProviderIdsCommand.Parameters.Add(_deleteProviderIdsCommand, "@Id"); - - _saveProviderIdsCommand = _connection.CreateCommand(); - _saveProviderIdsCommand.CommandText = "insert into ProviderIds (ItemId, Name, Value) values (@ItemId, @Name, @Value)"; - _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@ItemId"); - _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Name"); - _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Value"); - - // images - _deleteImagesCommand = _connection.CreateCommand(); - _deleteImagesCommand.CommandText = "delete from Images where ItemId=@Id"; - _deleteImagesCommand.Parameters.Add(_deleteImagesCommand, "@Id"); - - _saveImagesCommand = _connection.CreateCommand(); - _saveImagesCommand.CommandText = "insert into Images (ItemId, ImageType, Path, DateModified, IsPlaceHolder, SortOrder) values (@ItemId, @ImageType, @Path, @DateModified, @IsPlaceHolder, @SortOrder)"; - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ItemId"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ImageType"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@Path"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@DateModified"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@IsPlaceHolder"); - _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@SortOrder"); - } - /// /// Save a standard item in the repo /// @@ -626,314 +390,408 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - 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 item in items) + try { - cancellationToken.ThrowIfCancellationRequested(); - - var index = 0; - - _saveItemCommand.GetParameter(index++).Value = item.Id; - _saveItemCommand.GetParameter(index++).Value = item.GetType().FullName; - _saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item); - - _saveItemCommand.GetParameter(index++).Value = item.Path; - - var hasStartDate = item as IHasStartDate; - if (hasStartDate != null) - { - _saveItemCommand.GetParameter(index++).Value = hasStartDate.StartDate; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.EndDate; - _saveItemCommand.GetParameter(index++).Value = item.ChannelId; - - var hasProgramAttributes = item as IHasProgramAttributes; - if (hasProgramAttributes != null) - { - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsKids; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsMovie; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSports; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSeries; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsLive; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsNews; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsPremiere; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.EpisodeTitle; - _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsRepeat; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.CommunityRating; - _saveItemCommand.GetParameter(index++).Value = item.CustomRating; - - _saveItemCommand.GetParameter(index++).Value = item.IndexNumber; - _saveItemCommand.GetParameter(index++).Value = item.IsLocked; - - _saveItemCommand.GetParameter(index++).Value = item.Name; - _saveItemCommand.GetParameter(index++).Value = item.OfficialRating; - - _saveItemCommand.GetParameter(index++).Value = item.MediaType; - _saveItemCommand.GetParameter(index++).Value = item.Overview; - _saveItemCommand.GetParameter(index++).Value = item.ParentIndexNumber; - _saveItemCommand.GetParameter(index++).Value = item.PremiereDate; - _saveItemCommand.GetParameter(index++).Value = item.ProductionYear; - - if (item.ParentId == Guid.Empty) - { - _saveItemCommand.GetParameter(index++).Value = null; - } - else - { - _saveItemCommand.GetParameter(index++).Value = item.ParentId; - } - - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Genres.ToArray()); - _saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue() ?? 0; - _saveItemCommand.GetParameter(index++).Value = item.GetInheritedParentalRatingValue() ?? 0; - - _saveItemCommand.GetParameter(index++).Value = LatestSchemaVersion; - _saveItemCommand.GetParameter(index++).Value = item.SortName; - _saveItemCommand.GetParameter(index++).Value = item.RunTimeTicks; - - _saveItemCommand.GetParameter(index++).Value = item.OfficialRatingDescription; - _saveItemCommand.GetParameter(index++).Value = item.HomePageUrl; - _saveItemCommand.GetParameter(index++).Value = item.VoteCount; - _saveItemCommand.GetParameter(index++).Value = item.DisplayMediaType; - _saveItemCommand.GetParameter(index++).Value = item.DateCreated; - _saveItemCommand.GetParameter(index++).Value = item.DateModified; - - _saveItemCommand.GetParameter(index++).Value = item.ForcedSortName; - _saveItemCommand.GetParameter(index++).Value = item.IsOffline; - _saveItemCommand.GetParameter(index++).Value = item.LocationType.ToString(); - - _saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataLanguage; - _saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataCountryCode; - _saveItemCommand.GetParameter(index++).Value = item.IsHD; - _saveItemCommand.GetParameter(index++).Value = item.ExternalEtag; - - if (item.DateLastRefreshed == default(DateTime)) - { - _saveItemCommand.GetParameter(index++).Value = null; - } - else - { - _saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed; - } - - if (item.DateLastSaved == default(DateTime)) - { - _saveItemCommand.GetParameter(index++).Value = null; - } - else - { - _saveItemCommand.GetParameter(index++).Value = item.DateLastSaved; - } - - _saveItemCommand.GetParameter(index++).Value = item.IsInMixedFolder; - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()); - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.ToArray()); - - if (item.Audio.HasValue) - { - _saveItemCommand.GetParameter(index++).Value = item.Audio.Value.ToString(); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.ServiceName; - - if (item.Tags.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.IsFolder; - - _saveItemCommand.GetParameter(index++).Value = item.GetBlockUnratedType().ToString(); - - var topParent = item.GetTopParent(); - if (topParent != null) - { - //Logger.Debug("Item {0} has top parent {1}", item.Id, topParent.Id); - _saveItemCommand.GetParameter(index++).Value = topParent.Id.ToString("N"); - } - else - { - //Logger.Debug("Item {0} has null top parent", item.Id); - _saveItemCommand.GetParameter(index++).Value = null; - } - - var isByName = false; - var byName = item as IItemByName; - if (byName != null) - { - var dualAccess = item as IHasDualAccess; - isByName = dualAccess == null || dualAccess.IsAccessedByName; - } - _saveItemCommand.GetParameter(index++).Value = isByName; - - _saveItemCommand.GetParameter(index++).Value = item.SourceType.ToString(); - - var trailer = item as Trailer; - if (trailer != null && trailer.TrailerTypes.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } + transaction = connection.BeginTransaction(); - _saveItemCommand.GetParameter(index++).Value = item.CriticRating; - _saveItemCommand.GetParameter(index++).Value = item.CriticRatingSummary; - - if (!item.DateModifiedDuringLastRefresh.HasValue || item.DateModifiedDuringLastRefresh.Value == default(DateTime)) - { - _saveItemCommand.GetParameter(index++).Value = null; - } - else - { - _saveItemCommand.GetParameter(index++).Value = item.DateModifiedDuringLastRefresh.Value; - } - - var inheritedTags = item.GetInheritedTags(); - if (inheritedTags.Count > 0) - { - _saveItemCommand.GetParameter(index++).Value = string.Join("|", inheritedTags.ToArray()); - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - if (string.IsNullOrWhiteSpace(item.Name)) - { - _saveItemCommand.GetParameter(index++).Value = null; - } - else + using (var saveItemCommand = connection.CreateCommand()) { - _saveItemCommand.GetParameter(index++).Value = item.Name.RemoveDiacritics(); - } - - _saveItemCommand.GetParameter(index++).Value = item.PresentationUniqueKey; - _saveItemCommand.GetParameter(index++).Value = item.SlugName; - _saveItemCommand.GetParameter(index++).Value = item.OriginalTitle; - - var video = item as Video; - if (video != null) - { - _saveItemCommand.GetParameter(index++).Value = video.PrimaryVersionId; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - var folder = item as Folder; - if (folder != null && folder.DateLastMediaAdded.HasValue) - { - _saveItemCommand.GetParameter(index++).Value = folder.DateLastMediaAdded.Value; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } - - _saveItemCommand.GetParameter(index++).Value = item.Album; + var saveColumns = new List + { + "guid", + "type", + "data", + "Path", + "StartDate", + "EndDate", + "ChannelId", + "IsKids", + "IsMovie", + "IsSports", + "IsSeries", + "IsLive", + "IsNews", + "IsPremiere", + "EpisodeTitle", + "IsRepeat", + "CommunityRating", + "CustomRating", + "IndexNumber", + "IsLocked", + "Name", + "OfficialRating", + "MediaType", + "Overview", + "ParentIndexNumber", + "PremiereDate", + "ProductionYear", + "ParentId", + "Genres", + "ParentalRatingValue", + "InheritedParentalRatingValue", + "SchemaVersion", + "SortName", + "RunTimeTicks", + "OfficialRatingDescription", + "HomePageUrl", + "VoteCount", + "DisplayMediaType", + "DateCreated", + "DateModified", + "ForcedSortName", + "IsOffline", + "LocationType", + "PreferredMetadataLanguage", + "PreferredMetadataCountryCode", + "IsHD", + "ExternalEtag", + "DateLastRefreshed", + "DateLastSaved", + "IsInMixedFolder", + "LockedFields", + "Studios", + "Audio", + "ExternalServiceId", + "Tags", + "IsFolder", + "UnratedType", + "TopParentId", + "IsItemByName", + "SourceType", + "TrailerTypes", + "CriticRating", + "CriticRatingSummary", + "DateModifiedDuringLastRefresh", + "InheritedTags", + "CleanName", + "PresentationUniqueKey", + "SlugName", + "OriginalTitle", + "PrimaryVersionId", + "DateLastMediaAdded", + "Album", + "IsVirtualItem", + "SeriesName" + }; + + saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; + + for (var i = 1; i <= saveColumns.Count; i++) + { + if (i > 1) + { + saveItemCommand.CommandText += ","; + } + saveItemCommand.CommandText += "@" + i.ToString(CultureInfo.InvariantCulture); - var season = item as Season; - if (season != null && season.IsVirtualItem.HasValue) - { - _saveItemCommand.GetParameter(index++).Value = season.IsVirtualItem.Value; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; - } + saveItemCommand.Parameters.Add(saveItemCommand, "@" + i.ToString(CultureInfo.InvariantCulture)); + } + saveItemCommand.CommandText += ")"; - var hasSeries = item as IHasSeries; - if (hasSeries != null) - { - _saveItemCommand.GetParameter(index++).Value = hasSeries.SeriesName; - } - else - { - _saveItemCommand.GetParameter(index++).Value = null; + foreach (var item in items) + { + cancellationToken.ThrowIfCancellationRequested(); + + var index = 0; + + saveItemCommand.GetParameter(index++).Value = item.Id; + saveItemCommand.GetParameter(index++).Value = item.GetType().FullName; + saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item); + + saveItemCommand.GetParameter(index++).Value = item.Path; + + var hasStartDate = item as IHasStartDate; + if (hasStartDate != null) + { + saveItemCommand.GetParameter(index++).Value = hasStartDate.StartDate; + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + } + + saveItemCommand.GetParameter(index++).Value = item.EndDate; + saveItemCommand.GetParameter(index++).Value = item.ChannelId; + + var hasProgramAttributes = item as IHasProgramAttributes; + if (hasProgramAttributes != null) + { + saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsKids; + saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsMovie; + saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSports; + saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSeries; + saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsLive; + saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsNews; + saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsPremiere; + saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.EpisodeTitle; + saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsRepeat; + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + saveItemCommand.GetParameter(index++).Value = null; + saveItemCommand.GetParameter(index++).Value = null; + saveItemCommand.GetParameter(index++).Value = null; + saveItemCommand.GetParameter(index++).Value = null; + saveItemCommand.GetParameter(index++).Value = null; + saveItemCommand.GetParameter(index++).Value = null; + saveItemCommand.GetParameter(index++).Value = null; + saveItemCommand.GetParameter(index++).Value = null; + } + + saveItemCommand.GetParameter(index++).Value = item.CommunityRating; + saveItemCommand.GetParameter(index++).Value = item.CustomRating; + + saveItemCommand.GetParameter(index++).Value = item.IndexNumber; + saveItemCommand.GetParameter(index++).Value = item.IsLocked; + + saveItemCommand.GetParameter(index++).Value = item.Name; + saveItemCommand.GetParameter(index++).Value = item.OfficialRating; + + saveItemCommand.GetParameter(index++).Value = item.MediaType; + saveItemCommand.GetParameter(index++).Value = item.Overview; + saveItemCommand.GetParameter(index++).Value = item.ParentIndexNumber; + saveItemCommand.GetParameter(index++).Value = item.PremiereDate; + saveItemCommand.GetParameter(index++).Value = item.ProductionYear; + + if (item.ParentId == Guid.Empty) + { + saveItemCommand.GetParameter(index++).Value = null; + } + else + { + saveItemCommand.GetParameter(index++).Value = item.ParentId; + } + + saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Genres.ToArray()); + saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue() ?? 0; + saveItemCommand.GetParameter(index++).Value = item.GetInheritedParentalRatingValue() ?? 0; + + saveItemCommand.GetParameter(index++).Value = LatestSchemaVersion; + saveItemCommand.GetParameter(index++).Value = item.SortName; + saveItemCommand.GetParameter(index++).Value = item.RunTimeTicks; + + saveItemCommand.GetParameter(index++).Value = item.OfficialRatingDescription; + saveItemCommand.GetParameter(index++).Value = item.HomePageUrl; + saveItemCommand.GetParameter(index++).Value = item.VoteCount; + saveItemCommand.GetParameter(index++).Value = item.DisplayMediaType; + saveItemCommand.GetParameter(index++).Value = item.DateCreated; + saveItemCommand.GetParameter(index++).Value = item.DateModified; + + saveItemCommand.GetParameter(index++).Value = item.ForcedSortName; + saveItemCommand.GetParameter(index++).Value = item.IsOffline; + saveItemCommand.GetParameter(index++).Value = item.LocationType.ToString(); + + saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataLanguage; + saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataCountryCode; + saveItemCommand.GetParameter(index++).Value = item.IsHD; + saveItemCommand.GetParameter(index++).Value = item.ExternalEtag; + + if (item.DateLastRefreshed == default(DateTime)) + { + saveItemCommand.GetParameter(index++).Value = null; + } + else + { + saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed; + } + + if (item.DateLastSaved == default(DateTime)) + { + saveItemCommand.GetParameter(index++).Value = null; + } + else + { + saveItemCommand.GetParameter(index++).Value = item.DateLastSaved; + } + + saveItemCommand.GetParameter(index++).Value = item.IsInMixedFolder; + saveItemCommand.GetParameter(index++).Value = string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()); + saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.ToArray()); + + if (item.Audio.HasValue) + { + saveItemCommand.GetParameter(index++).Value = item.Audio.Value.ToString(); + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + } + + saveItemCommand.GetParameter(index++).Value = item.ServiceName; + + if (item.Tags.Count > 0) + { + saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + } + + saveItemCommand.GetParameter(index++).Value = item.IsFolder; + + saveItemCommand.GetParameter(index++).Value = item.GetBlockUnratedType().ToString(); + + var topParent = item.GetTopParent(); + if (topParent != null) + { + //Logger.Debug("Item {0} has top parent {1}", item.Id, topParent.Id); + saveItemCommand.GetParameter(index++).Value = topParent.Id.ToString("N"); + } + else + { + //Logger.Debug("Item {0} has null top parent", item.Id); + saveItemCommand.GetParameter(index++).Value = null; + } + + var isByName = false; + var byName = item as IItemByName; + if (byName != null) + { + var dualAccess = item as IHasDualAccess; + isByName = dualAccess == null || dualAccess.IsAccessedByName; + } + saveItemCommand.GetParameter(index++).Value = isByName; + + saveItemCommand.GetParameter(index++).Value = item.SourceType.ToString(); + + var trailer = item as Trailer; + if (trailer != null && trailer.TrailerTypes.Count > 0) + { + saveItemCommand.GetParameter(index++).Value = string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray()); + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + } + + saveItemCommand.GetParameter(index++).Value = item.CriticRating; + saveItemCommand.GetParameter(index++).Value = item.CriticRatingSummary; + + if (!item.DateModifiedDuringLastRefresh.HasValue || item.DateModifiedDuringLastRefresh.Value == default(DateTime)) + { + saveItemCommand.GetParameter(index++).Value = null; + } + else + { + saveItemCommand.GetParameter(index++).Value = item.DateModifiedDuringLastRefresh.Value; + } + + var inheritedTags = item.GetInheritedTags(); + if (inheritedTags.Count > 0) + { + saveItemCommand.GetParameter(index++).Value = string.Join("|", inheritedTags.ToArray()); + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + } + + if (string.IsNullOrWhiteSpace(item.Name)) + { + saveItemCommand.GetParameter(index++).Value = null; + } + else + { + saveItemCommand.GetParameter(index++).Value = item.Name.RemoveDiacritics(); + } + + saveItemCommand.GetParameter(index++).Value = item.PresentationUniqueKey; + saveItemCommand.GetParameter(index++).Value = item.SlugName; + saveItemCommand.GetParameter(index++).Value = item.OriginalTitle; + + var video = item as Video; + if (video != null) + { + saveItemCommand.GetParameter(index++).Value = video.PrimaryVersionId; + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + } + + var folder = item as Folder; + if (folder != null && folder.DateLastMediaAdded.HasValue) + { + saveItemCommand.GetParameter(index++).Value = folder.DateLastMediaAdded.Value; + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + } + + saveItemCommand.GetParameter(index++).Value = item.Album; + + var season = item as Season; + if (season != null && season.IsVirtualItem.HasValue) + { + saveItemCommand.GetParameter(index++).Value = season.IsVirtualItem.Value; + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + } + + var hasSeries = item as IHasSeries; + if (hasSeries != null) + { + saveItemCommand.GetParameter(index++).Value = hasSeries.SeriesName; + } + else + { + saveItemCommand.GetParameter(index++).Value = null; + } + + saveItemCommand.Transaction = transaction; + + saveItemCommand.ExecuteNonQuery(); + + if (item.SupportsAncestors) + { + UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), connection, transaction); + } + + UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), connection, transaction); + UpdateImages(item.Id, item.ImageInfos, connection, transaction); + UpdateProviderIds(item.Id, item.ProviderIds, connection, transaction); + UpdateItemValues(item.Id, GetItemValues(item), connection, transaction); + } } - _saveItemCommand.Transaction = transaction; - - _saveItemCommand.ExecuteNonQuery(); - - if (item.SupportsAncestors) + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) { - UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), transaction); + transaction.Rollback(); } - UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), transaction); - UpdateImages(item.Id, item.ImageInfos, transaction); - UpdateProviderIds(item.Id, item.ProviderIds, transaction); - UpdateItemValues(item.Id, GetItemValues(item), transaction); + throw; } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + catch (Exception e) { - transaction.Rollback(); - } + Logger.ErrorException("Failed to save items:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save items:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + finally { - transaction.Dispose(); + if (transaction != null) + { + transaction.Dispose(); + } } - - WriteLock.Release(); } } @@ -953,19 +811,22 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where guid = @guid"; - cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = id; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + using (var cmd = connection.CreateCommand()) { - if (reader.Read()) + cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where guid = @guid"; + cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = id; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { - return GetItem(reader); + if (reader.Read()) + { + return GetItem(reader); + } } + return null; } - return null; } } @@ -1371,22 +1232,25 @@ namespace MediaBrowser.Server.Implementations.Persistence } var list = new List(); - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select StartPositionTicks,Name,ImagePath from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc"; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select StartPositionTicks,Name,ImagePath from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc"; - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; + cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - list.Add(GetChapter(reader)); + while (reader.Read()) + { + list.Add(GetChapter(reader)); + } } } - } - return list; + return list; + } } /// @@ -1404,21 +1268,24 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("id"); } - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select StartPositionTicks,Name,ImagePath from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex"; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select StartPositionTicks,Name,ImagePath from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex"; - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; - cmd.Parameters.Add(cmd, "@ChapterIndex", DbType.Int32).Value = index; + cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; + cmd.Parameters.Add(cmd, "@ChapterIndex", DbType.Int32).Value = index; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) - { - if (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { - return GetChapter(reader); + if (reader.Read()) + { + return GetChapter(reader); + } } + return null; } - return null; } } @@ -1447,6 +1314,21 @@ namespace MediaBrowser.Server.Implementations.Persistence return chapter; } + private void DeleteChapters(IDbConnection connection, IDbTransaction transaction, Guid id) + { + using (var deleteChaptersCommand = connection.CreateCommand()) + { + deleteChaptersCommand.CommandText = "delete from " + ChaptersTableName + " where ItemId=@ItemId"; + deleteChaptersCommand.Parameters.Add(deleteChaptersCommand, "@ItemId"); + + deleteChaptersCommand.GetParameter(0).Value = id; + + deleteChaptersCommand.Transaction = transaction; + + deleteChaptersCommand.ExecuteNonQuery(); + } + } + /// /// Saves the chapters. /// @@ -1461,7 +1343,7 @@ namespace MediaBrowser.Server.Implementations.Persistence /// or /// cancellationToken /// - public async Task SaveChapters(Guid id, IEnumerable chapters, CancellationToken cancellationToken) + public async Task SaveChapters(Guid id, List chapters, CancellationToken cancellationToken) { CheckDisposed(); @@ -1477,90 +1359,89 @@ 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(); - - // First delete chapters - _deleteChaptersCommand.GetParameter(0).Value = id; + IDbTransaction transaction = null; - _deleteChaptersCommand.Transaction = transaction; - - _deleteChaptersCommand.ExecuteNonQuery(); - - var index = 0; - - foreach (var chapter in chapters) + try { - cancellationToken.ThrowIfCancellationRequested(); + transaction = connection.BeginTransaction(); - _saveChapterCommand.GetParameter(0).Value = id; - _saveChapterCommand.GetParameter(1).Value = index; - _saveChapterCommand.GetParameter(2).Value = chapter.StartPositionTicks; - _saveChapterCommand.GetParameter(3).Value = chapter.Name; - _saveChapterCommand.GetParameter(4).Value = chapter.ImagePath; + // First delete chapters + DeleteChapters(connection, transaction, id); - _saveChapterCommand.Transaction = transaction; + var index = 0; - _saveChapterCommand.ExecuteNonQuery(); + if (chapters.Count > 0) + { + using (var saveChapterCommand = connection.CreateCommand()) + { + saveChapterCommand.CommandText = "replace into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath) values (@ItemId, @ChapterIndex, @StartPositionTicks, @Name, @ImagePath)"; + saveChapterCommand.Parameters.Add(saveChapterCommand, "@ItemId"); + saveChapterCommand.Parameters.Add(saveChapterCommand, "@ChapterIndex"); + saveChapterCommand.Parameters.Add(saveChapterCommand, "@StartPositionTicks"); + saveChapterCommand.Parameters.Add(saveChapterCommand, "@Name"); + saveChapterCommand.Parameters.Add(saveChapterCommand, "@ImagePath"); + + if (chapters.Count > 1) + { + saveChapterCommand.Prepare(); + } + + foreach (var chapter in chapters) + { + cancellationToken.ThrowIfCancellationRequested(); + + saveChapterCommand.GetParameter(0).Value = id; + saveChapterCommand.GetParameter(1).Value = index; + saveChapterCommand.GetParameter(2).Value = chapter.StartPositionTicks; + saveChapterCommand.GetParameter(3).Value = chapter.Name; + saveChapterCommand.GetParameter(4).Value = chapter.ImagePath; + + saveChapterCommand.Transaction = transaction; + + saveChapterCommand.ExecuteNonQuery(); + + index++; + } + } + } - index++; + transaction.Commit(); } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to save chapters:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save chapters:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + finally { - transaction.Dispose(); + if (transaction != null) + { + transaction.Dispose(); + } } - - WriteLock.Release(); } } - protected override void CloseConnection() + private bool EnableJoinUserData(InternalItemsQuery query) { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } - - private bool EnableJoinUserData(InternalItemsQuery query) - { - if (query.User == null) + if (query.User == null) { return false; } @@ -1628,13 +1509,13 @@ namespace MediaBrowser.Server.Implementations.Persistence if (EnableJoinUserData(query)) { - list.Add("UserDataDb.UserData.UserId"); - list.Add("UserDataDb.UserData.lastPlayedDate"); - list.Add("UserDataDb.UserData.playbackPositionTicks"); - list.Add("UserDataDb.UserData.playcount"); - list.Add("UserDataDb.UserData.isFavorite"); - list.Add("UserDataDb.UserData.played"); - list.Add("UserDataDb.UserData.rating"); + list.Add("UserData.UserId"); + list.Add("UserData.lastPlayedDate"); + list.Add("UserData.playbackPositionTicks"); + list.Add("UserData.playcount"); + list.Add("UserData.isFavorite"); + list.Add("UserData.played"); + list.Add("UserData.rating"); } if (query.SimilarTo != null) @@ -1688,7 +1569,7 @@ namespace MediaBrowser.Server.Implementations.Persistence return string.Empty; } - return " left join UserDataDb.UserData on (select UserDataKey from UserDataKeys where ItemId=Guid order by Priority LIMIT 1)=UserDataDb.UserData.Key"; + return " left join UserData on (select UserDataKey from UserDataKeys where ItemId=Guid order by Priority LIMIT 1)=UserData.Key"; } public IEnumerable GetItemList(InternalItemsQuery query) @@ -1702,53 +1583,61 @@ namespace MediaBrowser.Server.Implementations.Persistence var now = DateTime.UtcNow; - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; - cmd.CommandText += GetJoinUserDataText(query); - if (EnableJoinUserData(query)) { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; + AttachUserDataDb(connection); } - var whereClauses = GetWhereClauses(query, cmd); + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; + cmd.CommandText += GetJoinUserDataText(query); - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + if (EnableJoinUserData(query)) + { + cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; + } - cmd.CommandText += whereText; + var whereClauses = GetWhereClauses(query, cmd); - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - cmd.CommandText += GetOrderByText(query); + cmd.CommandText += whereText; - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var limit = query.Limit ?? int.MaxValue; + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += " Group by PresentationUniqueKey"; + } - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); + cmd.CommandText += GetOrderByText(query); - if (query.StartIndex.HasValue) + if (query.Limit.HasValue || query.StartIndex.HasValue) { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); - } - } + var limit = query.Limit ?? int.MaxValue; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - LogQueryTime("GetItemList", cmd, now); + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - while (reader.Read()) + if (query.StartIndex.HasValue) + { + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); + } + } + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - var item = GetItem(reader); - if (item != null) + LogQueryTime("GetItemList", cmd, now); + + while (reader.Read()) { - yield return item; + var item = GetItem(reader); + if (item != null) + { + yield return item; + } } } } @@ -1792,86 +1681,94 @@ namespace MediaBrowser.Server.Implementations.Persistence var now = DateTime.UtcNow; - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; - cmd.CommandText += GetJoinUserDataText(query); - if (EnableJoinUserData(query)) { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; + AttachUserDataDb(connection); } - var whereClauses = GetWhereClauses(query, cmd); + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; + cmd.CommandText += GetJoinUserDataText(query); + + if (EnableJoinUserData(query)) + { + cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; + } - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereClauses = GetWhereClauses(query, cmd); - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereTextWithoutPaging = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - cmd.CommandText += whereText; + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + cmd.CommandText += whereText; + + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += " Group by PresentationUniqueKey"; + } - cmd.CommandText += GetOrderByText(query); + cmd.CommandText += GetOrderByText(query); - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var limit = query.Limit ?? int.MaxValue; + if (query.Limit.HasValue || query.StartIndex.HasValue) + { + var limit = query.Limit ?? int.MaxValue; + + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); + if (query.StartIndex.HasValue) + { + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); + } + } - if (query.StartIndex.HasValue) + if (EnableGroupByPresentationUniqueKey(query)) { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); + cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; + } + else + { + cmd.CommandText += "; select count (guid) from TypedBaseItems"; } - } - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; - } - else - { - cmd.CommandText += "; select count (guid) from TypedBaseItems"; - } + cmd.CommandText += GetJoinUserDataText(query); + cmd.CommandText += whereTextWithoutPaging; - cmd.CommandText += GetJoinUserDataText(query); - cmd.CommandText += whereTextWithoutPaging; + var list = new List(); + var count = 0; - var list = new List(); - var count = 0; + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + { + LogQueryTime("GetItems", cmd, now); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - LogQueryTime("GetItems", cmd, now); + while (reader.Read()) + { + var item = GetItem(reader); + if (item != null) + { + list.Add(item); + } + } - while (reader.Read()) - { - var item = GetItem(reader); - if (item != null) + if (reader.NextResult() && reader.Read()) { - list.Add(item); + count = reader.GetInt32(0); } } - if (reader.NextResult() && reader.Read()) + return new QueryResult() { - count = reader.GetInt32(0); - } + Items = list.ToArray(), + TotalRecordCount = count + }; } - - return new QueryResult() - { - Items = list.ToArray(), - TotalRecordCount = count - }; } } @@ -1989,56 +1886,64 @@ namespace MediaBrowser.Server.Implementations.Persistence var now = DateTime.UtcNow; - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; - cmd.CommandText += GetJoinUserDataText(query); - if (EnableJoinUserData(query)) { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; + AttachUserDataDb(connection); } - var whereClauses = GetWhereClauses(query, cmd); + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; + cmd.CommandText += GetJoinUserDataText(query); - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + if (EnableJoinUserData(query)) + { + cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; + } - cmd.CommandText += whereText; + var whereClauses = GetWhereClauses(query, cmd); - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - cmd.CommandText += GetOrderByText(query); + cmd.CommandText += whereText; - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var limit = query.Limit ?? int.MaxValue; + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += " Group by PresentationUniqueKey"; + } - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); + cmd.CommandText += GetOrderByText(query); - if (query.StartIndex.HasValue) + if (query.Limit.HasValue || query.StartIndex.HasValue) { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); - } - } + var limit = query.Limit ?? int.MaxValue; - var list = new List(); + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - LogQueryTime("GetItemIdsList", cmd, now); + if (query.StartIndex.HasValue) + { + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); + } + } + + var list = new List(); - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - list.Add(reader.GetGuid(0)); + LogQueryTime("GetItemIdsList", cmd, now); + + while (reader.Read()) + { + list.Add(reader.GetGuid(0)); + } } - } - return list; + return list; + } } } @@ -2051,73 +1956,76 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select guid,path from TypedBaseItems"; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select guid,path from TypedBaseItems"; - var whereClauses = GetWhereClauses(query, cmd); + var whereClauses = GetWhereClauses(query, cmd); - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereTextWithoutPaging = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - cmd.CommandText += whereText; + cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += " Group by PresentationUniqueKey"; + } - cmd.CommandText += GetOrderByText(query); + cmd.CommandText += GetOrderByText(query); - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var limit = query.Limit ?? int.MaxValue; + if (query.Limit.HasValue || query.StartIndex.HasValue) + { + var limit = query.Limit ?? int.MaxValue; - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - if (query.StartIndex.HasValue) - { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); + if (query.StartIndex.HasValue) + { + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); + } } - } - cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging; + cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging; - var list = new List>(); - var count = 0; + var list = new List>(); + var count = 0; - Logger.Debug(cmd.CommandText); + Logger.Debug(cmd.CommandText); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { - var id = reader.GetGuid(0); - string path = null; + while (reader.Read()) + { + var id = reader.GetGuid(0); + string path = null; + + if (!reader.IsDBNull(1)) + { + path = reader.GetString(1); + } + list.Add(new Tuple(id, path)); + } - if (!reader.IsDBNull(1)) + if (reader.NextResult() && reader.Read()) { - path = reader.GetString(1); + count = reader.GetInt32(0); } - list.Add(new Tuple(id, path)); } - if (reader.NextResult() && reader.Read()) + return new QueryResult>() { - count = reader.GetInt32(0); - } + Items = list.ToArray(), + TotalRecordCount = count + }; } - - return new QueryResult>() - { - Items = list.ToArray(), - TotalRecordCount = count - }; } } @@ -2132,78 +2040,86 @@ namespace MediaBrowser.Server.Implementations.Persistence var now = DateTime.UtcNow; - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; - - var whereClauses = GetWhereClauses(query, cmd); - cmd.CommandText += GetJoinUserDataText(query); - if (EnableJoinUserData(query)) { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; + AttachUserDataDb(connection); } - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); - - cmd.CommandText += whereText; - - if (EnableGroupByPresentationUniqueKey(query)) + using (var cmd = connection.CreateCommand()) { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; - cmd.CommandText += GetOrderByText(query); + var whereClauses = GetWhereClauses(query, cmd); + cmd.CommandText += GetJoinUserDataText(query); - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var limit = query.Limit ?? int.MaxValue; + if (EnableJoinUserData(query)) + { + cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; + } + + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); + cmd.CommandText += whereText; - if (query.StartIndex.HasValue) + if (EnableGroupByPresentationUniqueKey(query)) { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); + cmd.CommandText += " Group by PresentationUniqueKey"; } - } - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; - } - else - { - cmd.CommandText += "; select count (guid) from TypedBaseItems"; - } + cmd.CommandText += GetOrderByText(query); - cmd.CommandText += GetJoinUserDataText(query); - cmd.CommandText += whereText; + if (query.Limit.HasValue || query.StartIndex.HasValue) + { + var limit = query.Limit ?? int.MaxValue; - var list = new List(); - var count = 0; + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - LogQueryTime("GetItemIds", cmd, now); + if (query.StartIndex.HasValue) + { + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); + } + } - while (reader.Read()) + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; + } + else { - list.Add(reader.GetGuid(0)); + cmd.CommandText += "; select count (guid) from TypedBaseItems"; } - if (reader.NextResult() && reader.Read()) + cmd.CommandText += GetJoinUserDataText(query); + cmd.CommandText += whereText; + + var list = new List(); + var count = 0; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { - count = reader.GetInt32(0); + LogQueryTime("GetItemIds", cmd, now); + + while (reader.Read()) + { + list.Add(reader.GetGuid(0)); + } + + if (reader.NextResult() && reader.Read()) + { + count = reader.GetInt32(0); + } } - } - return new QueryResult() - { - Items = list.ToArray(), - TotalRecordCount = count - }; + return new QueryResult() + { + Items = list.ToArray(), + TotalRecordCount = count + }; + } } } @@ -2987,77 +2903,88 @@ namespace MediaBrowser.Server.Implementations.Persistence private async Task UpdateInheritedTags(CancellationToken cancellationToken) { - var newValues = new List>(); - - using (var cmd = _connection.CreateCommand()) + using (var connection = await CreateConnection().ConfigureAwait(false)) { - cmd.CommandText = "select Guid,InheritedTags,(select group_concat(Tags, '|') from TypedBaseItems where (guid=outer.guid) OR (guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid))) as NewInheritedTags from typedbaseitems as Outer where NewInheritedTags <> InheritedTags"; + var newValues = new List>(); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + using (var cmd = connection.CreateCommand()) { - while (reader.Read()) + cmd.CommandText = "select Guid,InheritedTags,(select group_concat(Tags, '|') from TypedBaseItems where (guid=outer.guid) OR (guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid))) as NewInheritedTags from typedbaseitems as Outer where NewInheritedTags <> InheritedTags"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - var id = reader.GetGuid(0); - string value = reader.IsDBNull(2) ? null : reader.GetString(2); + while (reader.Read()) + { + var id = reader.GetGuid(0); + string value = reader.IsDBNull(2) ? null : reader.GetString(2); - newValues.Add(new Tuple(id, value)); + newValues.Add(new Tuple(id, value)); + } } } - } - Logger.Debug("UpdateInheritedTags - {0} rows", newValues.Count); - if (newValues.Count == 0) - { - return; - } + Logger.Debug("UpdateInheritedTags - {0} rows", newValues.Count); + if (newValues.Count == 0) + { + return; + } - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); + IDbTransaction transaction = null; - IDbTransaction transaction = null; + try + { + transaction = connection.BeginTransaction(); - try - { - transaction = _connection.BeginTransaction(); + using (var updateInheritedTagsCommand = connection.CreateCommand()) + { + updateInheritedTagsCommand.CommandText = "Update TypedBaseItems set InheritedTags=@InheritedTags where Guid=@Guid"; + updateInheritedTagsCommand.Parameters.Add(updateInheritedTagsCommand, "@Guid"); + updateInheritedTagsCommand.Parameters.Add(updateInheritedTagsCommand, "@InheritedTags"); - foreach (var item in newValues) - { - _updateInheritedTagsCommand.GetParameter(0).Value = item.Item1; - _updateInheritedTagsCommand.GetParameter(1).Value = item.Item2; + if (newValues.Count > 1) + { + updateInheritedTagsCommand.Prepare(); + } - _updateInheritedTagsCommand.Transaction = transaction; - _updateInheritedTagsCommand.ExecuteNonQuery(); - } + foreach (var item in newValues) + { + updateInheritedTagsCommand.GetParameter(0).Value = item.Item1; + updateInheritedTagsCommand.GetParameter(1).Value = item.Item2; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + updateInheritedTagsCommand.Transaction = transaction; + updateInheritedTagsCommand.ExecuteNonQuery(); + } + } + + transaction.Commit(); + } + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Error running query:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Error running query:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + finally { - transaction.Dispose(); + if (transaction != null) + { + transaction.Dispose(); + } } - - WriteLock.Release(); } } @@ -3065,75 +2992,82 @@ namespace MediaBrowser.Server.Implementations.Persistence { var newValues = new List>(); - using (var cmd = _connection.CreateCommand()) + using (var connection = await CreateConnection().ConfigureAwait(false)) { - cmd.CommandText = "select Guid,InheritedParentalRatingValue,(select Max(ParentalRatingValue, (select COALESCE(MAX(ParentalRatingValue),0) from TypedBaseItems where guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid)))) as NewInheritedParentalRatingValue from typedbaseitems as Outer where InheritedParentalRatingValue <> NewInheritedParentalRatingValue"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + using (var cmd = connection.CreateCommand()) { - while (reader.Read()) + cmd.CommandText = "select Guid,InheritedParentalRatingValue,(select Max(ParentalRatingValue, (select COALESCE(MAX(ParentalRatingValue),0) from TypedBaseItems where guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid)))) as NewInheritedParentalRatingValue from typedbaseitems as Outer where InheritedParentalRatingValue <> NewInheritedParentalRatingValue"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - var id = reader.GetGuid(0); - var newValue = reader.GetInt32(2); + while (reader.Read()) + { + var id = reader.GetGuid(0); + var newValue = reader.GetInt32(2); - newValues.Add(new Tuple(id, newValue)); + newValues.Add(new Tuple(id, newValue)); + } } } - } - Logger.Debug("UpdateInheritedParentalRatings - {0} rows", newValues.Count); - if (newValues.Count == 0) - { - return; - } + Logger.Debug("UpdateInheritedParentalRatings - {0} rows", newValues.Count); + if (newValues.Count == 0) + { + return; + } - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); + using (var updateInheritedRatingCommand = connection.CreateCommand()) + { + updateInheritedRatingCommand.CommandText = "Update TypedBaseItems set InheritedParentalRatingValue=@InheritedParentalRatingValue where Guid=@Guid"; + updateInheritedRatingCommand.Parameters.Add(updateInheritedRatingCommand, "@Guid"); + updateInheritedRatingCommand.Parameters.Add(updateInheritedRatingCommand, "@InheritedParentalRatingValue"); + updateInheritedRatingCommand.Prepare(); - IDbTransaction transaction = null; + IDbTransaction transaction = null; - try - { - transaction = _connection.BeginTransaction(); + try + { + transaction = connection.BeginTransaction(); - foreach (var item in newValues) - { - _updateInheritedRatingCommand.GetParameter(0).Value = item.Item1; - _updateInheritedRatingCommand.GetParameter(1).Value = item.Item2; + foreach (var item in newValues) + { + updateInheritedRatingCommand.GetParameter(0).Value = item.Item1; + updateInheritedRatingCommand.GetParameter(1).Value = item.Item2; - _updateInheritedRatingCommand.Transaction = transaction; - _updateInheritedRatingCommand.ExecuteNonQuery(); - } + updateInheritedRatingCommand.Transaction = transaction; + updateInheritedRatingCommand.ExecuteNonQuery(); + } - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - catch (Exception e) - { - Logger.ErrorException("Error running query:", e); + throw; + } + catch (Exception e) + { + Logger.ErrorException("Error running query:", e); - if (transaction != null) - { - transaction.Rollback(); - } + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + } } - - WriteLock.Release(); } } @@ -3176,89 +3110,73 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try + using (var connection = await CreateConnection().ConfigureAwait(false)) { - transaction = _connection.BeginTransaction(); + IDbTransaction transaction = null; - // Delete people - _deletePeopleCommand.GetParameter(0).Value = id; - _deletePeopleCommand.Transaction = transaction; - _deletePeopleCommand.ExecuteNonQuery(); + try + { + transaction = connection.BeginTransaction(); - // Delete chapters - _deleteChaptersCommand.GetParameter(0).Value = id; - _deleteChaptersCommand.Transaction = transaction; - _deleteChaptersCommand.ExecuteNonQuery(); + // Delete people + DeletePeople(connection, transaction, id); + DeleteChapters(connection, transaction, id); + DeleteMediaStreams(connection, transaction, id); - // Delete media streams - _deleteStreamsCommand.GetParameter(0).Value = id; - _deleteStreamsCommand.Transaction = transaction; - _deleteStreamsCommand.ExecuteNonQuery(); + // Delete ancestors + DeleteAncestors(connection, transaction, id); - // Delete ancestors - _deleteAncestorsCommand.GetParameter(0).Value = id; - _deleteAncestorsCommand.Transaction = transaction; - _deleteAncestorsCommand.ExecuteNonQuery(); + // Delete user data keys + DeleteUserDataKeys(connection, transaction, id); - // Delete user data keys - _deleteUserDataKeysCommand.GetParameter(0).Value = id; - _deleteUserDataKeysCommand.Transaction = transaction; - _deleteUserDataKeysCommand.ExecuteNonQuery(); + // Delete item values + DeleteItemValues(connection, transaction, id); - // Delete item values - _deleteItemValuesCommand.GetParameter(0).Value = id; - _deleteItemValuesCommand.Transaction = transaction; - _deleteItemValuesCommand.ExecuteNonQuery(); + // Delete provider ids + DeleteProviderIds(connection, transaction, id); - // Delete provider ids - _deleteProviderIdsCommand.GetParameter(0).Value = id; - _deleteProviderIdsCommand.Transaction = transaction; - _deleteProviderIdsCommand.ExecuteNonQuery(); + DeleteImages(connection, transaction, id); - // Delete images - _deleteImagesCommand.GetParameter(0).Value = id; - _deleteImagesCommand.Transaction = transaction; - _deleteImagesCommand.ExecuteNonQuery(); + // Delete the item + using (var deleteItemCommand = connection.CreateCommand()) + { + deleteItemCommand.CommandText = "delete from TypedBaseItems where guid=@Id"; + deleteItemCommand.Parameters.Add(deleteItemCommand, "@Id"); - // Delete the item - _deleteItemCommand.GetParameter(0).Value = id; - _deleteItemCommand.Transaction = transaction; - _deleteItemCommand.ExecuteNonQuery(); + deleteItemCommand.GetParameter(0).Value = id; + deleteItemCommand.Transaction = transaction; + deleteItemCommand.ExecuteNonQuery(); + } - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + transaction.Commit(); + } + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to save children:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save children:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + finally { - transaction.Dispose(); + if (transaction != null) + { + transaction.Dispose(); + } } - - WriteLock.Release(); } } @@ -3271,30 +3189,33 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select Distinct Name from People"; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select Distinct Name from People"; - var whereClauses = GetPeopleWhereClauses(query, cmd); + var whereClauses = GetPeopleWhereClauses(query, cmd); - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } + if (whereClauses.Count > 0) + { + cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + } - cmd.CommandText += " order by ListOrder"; + cmd.CommandText += " order by ListOrder"; - var list = new List(); + var list = new List(); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - list.Add(reader.GetString(0)); + while (reader.Read()) + { + list.Add(reader.GetString(0)); + } } - } - return list; + return list; + } } } @@ -3307,30 +3228,33 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select ItemId, Name, Role, PersonType, SortOrder from People"; + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "select ItemId, Name, Role, PersonType, SortOrder from People"; - var whereClauses = GetPeopleWhereClauses(query, cmd); + var whereClauses = GetPeopleWhereClauses(query, cmd); - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } + if (whereClauses.Count > 0) + { + cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + } - cmd.CommandText += " order by ListOrder"; + cmd.CommandText += " order by ListOrder"; - var list = new List(); + var list = new List(); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - list.Add(GetPerson(reader)); + while (reader.Read()) + { + list.Add(GetPerson(reader)); + } } - } - return list; + return list; + } } } @@ -3384,7 +3308,21 @@ namespace MediaBrowser.Server.Implementations.Persistence return whereClauses; } - private void UpdateAncestors(Guid itemId, List ancestorIds, IDbTransaction transaction) + private void DeleteAncestors(IDbConnection connection, IDbTransaction transaction, Guid id) + { + using (var deleteAncestorsCommand = connection.CreateCommand()) + { + deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id"; + deleteAncestorsCommand.Parameters.Add(deleteAncestorsCommand, "@Id"); + + deleteAncestorsCommand.GetParameter(0).Value = id; + deleteAncestorsCommand.Transaction = transaction; + + deleteAncestorsCommand.ExecuteNonQuery(); + } + } + + private void UpdateAncestors(Guid itemId, List ancestorIds, IDbConnection connection, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3399,20 +3337,33 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - _deleteAncestorsCommand.GetParameter(0).Value = itemId; - _deleteAncestorsCommand.Transaction = transaction; + DeleteAncestors(connection, transaction, itemId); - _deleteAncestorsCommand.ExecuteNonQuery(); - - foreach (var ancestorId in ancestorIds) + if (ancestorIds.Count > 0) { - _saveAncestorCommand.GetParameter(0).Value = itemId; - _saveAncestorCommand.GetParameter(1).Value = ancestorId; - _saveAncestorCommand.GetParameter(2).Value = ancestorId.ToString("N"); + using (var saveAncestorCommand = connection.CreateCommand()) + { + saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId, AncestorIdText) values (@ItemId, @AncestorId, @AncestorIdText)"; + saveAncestorCommand.Parameters.Add(saveAncestorCommand, "@ItemId"); + saveAncestorCommand.Parameters.Add(saveAncestorCommand, "@AncestorId"); + saveAncestorCommand.Parameters.Add(saveAncestorCommand, "@AncestorIdText"); + + if (ancestorIds.Count > 1) + { + saveAncestorCommand.Prepare(); + } + + foreach (var ancestorId in ancestorIds) + { + saveAncestorCommand.GetParameter(0).Value = itemId; + saveAncestorCommand.GetParameter(1).Value = ancestorId; + saveAncestorCommand.GetParameter(2).Value = ancestorId.ToString("N"); - _saveAncestorCommand.Transaction = transaction; + saveAncestorCommand.Transaction = transaction; - _saveAncestorCommand.ExecuteNonQuery(); + saveAncestorCommand.ExecuteNonQuery(); + } + } } } @@ -3440,7 +3391,20 @@ namespace MediaBrowser.Server.Implementations.Persistence return list; } - private void UpdateImages(Guid itemId, List images, IDbTransaction transaction) + private void DeleteImages(IDbConnection connection, IDbTransaction transaction, Guid id) + { + using (var deleteImagesCommand = connection.CreateCommand()) + { + deleteImagesCommand.CommandText = "delete from Images where ItemId=@Id"; + deleteImagesCommand.Parameters.Add(deleteImagesCommand, "@Id"); + + deleteImagesCommand.GetParameter(0).Value = id; + deleteImagesCommand.Transaction = transaction; + deleteImagesCommand.ExecuteNonQuery(); + } + } + + private void UpdateImages(Guid itemId, List images, IDbConnection connection, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3455,38 +3419,70 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - _deleteImagesCommand.GetParameter(0).Value = itemId; - _deleteImagesCommand.Transaction = transaction; - - _deleteImagesCommand.ExecuteNonQuery(); + DeleteImages(connection, transaction, itemId); - var index = 0; - foreach (var image in images) + if (images.Count > 0) { - _saveImagesCommand.GetParameter(0).Value = itemId; - _saveImagesCommand.GetParameter(1).Value = image.Type; - _saveImagesCommand.GetParameter(2).Value = image.Path; - - if (image.DateModified == default(DateTime)) - { - _saveImagesCommand.GetParameter(3).Value = null; - } - else + using (var saveImagesCommand = connection.CreateCommand()) { - _saveImagesCommand.GetParameter(3).Value = image.DateModified; + var index = 0; + + saveImagesCommand.CommandText = "insert into Images (ItemId, ImageType, Path, DateModified, IsPlaceHolder, SortOrder) values (@ItemId, @ImageType, @Path, @DateModified, @IsPlaceHolder, @SortOrder)"; + saveImagesCommand.Parameters.Add(saveImagesCommand, "@ItemId"); + saveImagesCommand.Parameters.Add(saveImagesCommand, "@ImageType"); + saveImagesCommand.Parameters.Add(saveImagesCommand, "@Path"); + saveImagesCommand.Parameters.Add(saveImagesCommand, "@DateModified"); + saveImagesCommand.Parameters.Add(saveImagesCommand, "@IsPlaceHolder"); + saveImagesCommand.Parameters.Add(saveImagesCommand, "@SortOrder"); + + if (images.Count > 1) + { + saveImagesCommand.Prepare(); + } + + foreach (var image in images) + { + saveImagesCommand.GetParameter(0).Value = itemId; + saveImagesCommand.GetParameter(1).Value = image.Type; + saveImagesCommand.GetParameter(2).Value = image.Path; + + if (image.DateModified == default(DateTime)) + { + saveImagesCommand.GetParameter(3).Value = null; + } + else + { + saveImagesCommand.GetParameter(3).Value = image.DateModified; + } + + saveImagesCommand.GetParameter(4).Value = image.IsPlaceholder; + saveImagesCommand.GetParameter(5).Value = index; + + saveImagesCommand.Transaction = transaction; + + saveImagesCommand.ExecuteNonQuery(); + index++; + } } + } + } - _saveImagesCommand.GetParameter(4).Value = image.IsPlaceholder; - _saveImagesCommand.GetParameter(5).Value = index; + private void DeleteProviderIds(IDbConnection connection, IDbTransaction transaction, Guid itemId) + { + using (var deleteProviderIdsCommand = connection.CreateCommand()) + { + // provider ids + deleteProviderIdsCommand.CommandText = "delete from ProviderIds where ItemId=@Id"; + deleteProviderIdsCommand.Parameters.Add(deleteProviderIdsCommand, "@Id"); - _saveImagesCommand.Transaction = transaction; + deleteProviderIdsCommand.GetParameter(0).Value = itemId; + deleteProviderIdsCommand.Transaction = transaction; - _saveImagesCommand.ExecuteNonQuery(); - index++; + deleteProviderIdsCommand.ExecuteNonQuery(); } } - private void UpdateProviderIds(Guid itemId, Dictionary values, IDbTransaction transaction) + private void UpdateProviderIds(Guid itemId, Dictionary values, IDbConnection connection, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3501,23 +3497,51 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - _deleteProviderIdsCommand.GetParameter(0).Value = itemId; - _deleteProviderIdsCommand.Transaction = transaction; + DeleteProviderIds(connection, transaction, itemId); + + if (values.Count > 0) + { + using (var saveProviderIdsCommand = connection.CreateCommand()) + { + saveProviderIdsCommand.CommandText = "insert into ProviderIds (ItemId, Name, Value) values (@ItemId, @Name, @Value)"; + saveProviderIdsCommand.Parameters.Add(saveProviderIdsCommand, "@ItemId"); + saveProviderIdsCommand.Parameters.Add(saveProviderIdsCommand, "@Name"); + saveProviderIdsCommand.Parameters.Add(saveProviderIdsCommand, "@Value"); + + if (values.Count > 1) + { + saveProviderIdsCommand.Prepare(); + } + + foreach (var pair in values) + { + saveProviderIdsCommand.GetParameter(0).Value = itemId; + saveProviderIdsCommand.GetParameter(1).Value = pair.Key; + saveProviderIdsCommand.GetParameter(2).Value = pair.Value; + saveProviderIdsCommand.Transaction = transaction; - _deleteProviderIdsCommand.ExecuteNonQuery(); + saveProviderIdsCommand.ExecuteNonQuery(); + } + } + } + } - foreach (var pair in values) + private void DeleteItemValues(IDbConnection connection, IDbTransaction transaction, Guid itemId) + { + using (var deleteItemValuesCommand = connection.CreateCommand()) { - _saveProviderIdsCommand.GetParameter(0).Value = itemId; - _saveProviderIdsCommand.GetParameter(1).Value = pair.Key; - _saveProviderIdsCommand.GetParameter(2).Value = pair.Value; - _saveProviderIdsCommand.Transaction = transaction; + deleteItemValuesCommand.CommandText = "delete from ItemValues where ItemId=@Id"; + deleteItemValuesCommand.Parameters.Add(deleteItemValuesCommand, "@Id"); + + // First delete + deleteItemValuesCommand.GetParameter(0).Value = itemId; + deleteItemValuesCommand.Transaction = transaction; - _saveProviderIdsCommand.ExecuteNonQuery(); + deleteItemValuesCommand.ExecuteNonQuery(); } } - private void UpdateItemValues(Guid itemId, List> values, IDbTransaction transaction) + private void UpdateItemValues(Guid itemId, List> values, IDbConnection connection, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3532,23 +3556,51 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - _deleteItemValuesCommand.GetParameter(0).Value = itemId; - _deleteItemValuesCommand.Transaction = transaction; + DeleteItemValues(connection, transaction, itemId); + + if (values.Count > 0) + { + using (var saveItemValuesCommand = connection.CreateCommand()) + { + saveItemValuesCommand.CommandText = "insert into ItemValues (ItemId, Type, Value) values (@ItemId, @Type, @Value)"; + saveItemValuesCommand.Parameters.Add(saveItemValuesCommand, "@ItemId"); + saveItemValuesCommand.Parameters.Add(saveItemValuesCommand, "@Type"); + saveItemValuesCommand.Parameters.Add(saveItemValuesCommand, "@Value"); + + if (values.Count > 1) + { + saveItemValuesCommand.Prepare(); + } + + foreach (var pair in values) + { + saveItemValuesCommand.GetParameter(0).Value = itemId; + saveItemValuesCommand.GetParameter(1).Value = pair.Item1; + saveItemValuesCommand.GetParameter(2).Value = pair.Item2; + saveItemValuesCommand.Transaction = transaction; - _deleteItemValuesCommand.ExecuteNonQuery(); + saveItemValuesCommand.ExecuteNonQuery(); + } + } + } + } - foreach (var pair in values) + private void DeleteUserDataKeys(IDbConnection connection, IDbTransaction transaction, Guid itemId) + { + using (var deleteUserDataKeysCommand = connection.CreateCommand()) { - _saveItemValuesCommand.GetParameter(0).Value = itemId; - _saveItemValuesCommand.GetParameter(1).Value = pair.Item1; - _saveItemValuesCommand.GetParameter(2).Value = pair.Item2; - _saveItemValuesCommand.Transaction = transaction; + // user data + deleteUserDataKeysCommand.CommandText = "delete from UserDataKeys where ItemId=@Id"; + deleteUserDataKeysCommand.Parameters.Add(deleteUserDataKeysCommand, "@Id"); + + deleteUserDataKeysCommand.GetParameter(0).Value = itemId; + deleteUserDataKeysCommand.Transaction = transaction; - _saveItemValuesCommand.ExecuteNonQuery(); + deleteUserDataKeysCommand.ExecuteNonQuery(); } } - private void UpdateUserDataKeys(Guid itemId, List keys, IDbTransaction transaction) + private void UpdateUserDataKeys(Guid itemId, List keys, IDbConnection connection, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3563,21 +3615,50 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - _deleteUserDataKeysCommand.GetParameter(0).Value = itemId; - _deleteUserDataKeysCommand.Transaction = transaction; + DeleteUserDataKeys(connection, transaction, itemId); - _deleteUserDataKeysCommand.ExecuteNonQuery(); var index = 0; - foreach (var key in keys) + if (keys.Count > 0) + { + using (var saveUserDataKeysCommand = connection.CreateCommand()) + { + saveUserDataKeysCommand.CommandText = "insert into UserDataKeys (ItemId, UserDataKey, Priority) values (@ItemId, @UserDataKey, @Priority)"; + saveUserDataKeysCommand.Parameters.Add(saveUserDataKeysCommand, "@ItemId"); + saveUserDataKeysCommand.Parameters.Add(saveUserDataKeysCommand, "@UserDataKey"); + saveUserDataKeysCommand.Parameters.Add(saveUserDataKeysCommand, "@Priority"); + + if (keys.Count > 1) + { + saveUserDataKeysCommand.Prepare(); + } + + foreach (var key in keys) + { + saveUserDataKeysCommand.GetParameter(0).Value = itemId; + saveUserDataKeysCommand.GetParameter(1).Value = key; + saveUserDataKeysCommand.GetParameter(2).Value = index; + index++; + saveUserDataKeysCommand.Transaction = transaction; + + saveUserDataKeysCommand.ExecuteNonQuery(); + } + } + } + } + + private void DeletePeople(IDbConnection connection, IDbTransaction transaction, Guid id) + { + using (var deletePeopleCommand = connection.CreateCommand()) { - _saveUserDataKeysCommand.GetParameter(0).Value = itemId; - _saveUserDataKeysCommand.GetParameter(1).Value = key; - _saveUserDataKeysCommand.GetParameter(2).Value = index; - index++; - _saveUserDataKeysCommand.Transaction = transaction; + deletePeopleCommand.CommandText = "delete from People where ItemId=@Id"; + deletePeopleCommand.Parameters.Add(deletePeopleCommand, "@Id"); - _saveUserDataKeysCommand.ExecuteNonQuery(); + + deletePeopleCommand.GetParameter(0).Value = id; + deletePeopleCommand.Transaction = transaction; + + deletePeopleCommand.ExecuteNonQuery(); } } @@ -3597,69 +3678,85 @@ namespace MediaBrowser.Server.Implementations.Persistence var cancellationToken = CancellationToken.None; - await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try + using (var connection = await CreateConnection().ConfigureAwait(false)) { - transaction = _connection.BeginTransaction(); - - // First delete - _deletePeopleCommand.GetParameter(0).Value = itemId; - _deletePeopleCommand.Transaction = transaction; + IDbTransaction transaction = null; - _deletePeopleCommand.ExecuteNonQuery(); + try + { + transaction = connection.BeginTransaction(); - var listIndex = 0; + // First delete + DeletePeople(connection, transaction, itemId); - foreach (var person in people) - { - cancellationToken.ThrowIfCancellationRequested(); + var listIndex = 0; - _savePersonCommand.GetParameter(0).Value = itemId; - _savePersonCommand.GetParameter(1).Value = person.Name; - _savePersonCommand.GetParameter(2).Value = person.Role; - _savePersonCommand.GetParameter(3).Value = person.Type; - _savePersonCommand.GetParameter(4).Value = person.SortOrder; - _savePersonCommand.GetParameter(5).Value = listIndex; + if (people.Count > 0) + { + using (var savePersonCommand = connection.CreateCommand()) + { + savePersonCommand.CommandText = "insert into People (ItemId, Name, Role, PersonType, SortOrder, ListOrder) values (@ItemId, @Name, @Role, @PersonType, @SortOrder, @ListOrder)"; + savePersonCommand.Parameters.Add(savePersonCommand, "@ItemId"); + savePersonCommand.Parameters.Add(savePersonCommand, "@Name"); + savePersonCommand.Parameters.Add(savePersonCommand, "@Role"); + savePersonCommand.Parameters.Add(savePersonCommand, "@PersonType"); + savePersonCommand.Parameters.Add(savePersonCommand, "@SortOrder"); + savePersonCommand.Parameters.Add(savePersonCommand, "@ListOrder"); + + if (people.Count > 1) + { + savePersonCommand.Prepare(); + } + + foreach (var person in people) + { + cancellationToken.ThrowIfCancellationRequested(); + + savePersonCommand.GetParameter(0).Value = itemId; + savePersonCommand.GetParameter(1).Value = person.Name; + savePersonCommand.GetParameter(2).Value = person.Role; + savePersonCommand.GetParameter(3).Value = person.Type; + savePersonCommand.GetParameter(4).Value = person.SortOrder; + savePersonCommand.GetParameter(5).Value = listIndex; + + savePersonCommand.Transaction = transaction; + + savePersonCommand.ExecuteNonQuery(); + listIndex++; + } + } + } - _savePersonCommand.Transaction = transaction; + transaction.Commit(); - _savePersonCommand.ExecuteNonQuery(); - listIndex++; } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to save people:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save people:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + finally { - transaction.Dispose(); + if (transaction != null) + { + transaction.Dispose(); + } } - - WriteLock.Release(); } } @@ -3699,42 +3796,61 @@ namespace MediaBrowser.Server.Implementations.Persistence var list = new List(); - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - var cmdText = "select " + string.Join(",", _mediaStreamSaveColumns) + " from mediastreams where"; + using (var cmd = connection.CreateCommand()) + { + var cmdText = "select " + string.Join(",", _mediaStreamSaveColumns) + " from mediastreams where"; - cmdText += " ItemId=@ItemId"; - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = query.ItemId; + cmdText += " ItemId=@ItemId"; + cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = query.ItemId; - if (query.Type.HasValue) - { - cmdText += " AND StreamType=@StreamType"; - cmd.Parameters.Add(cmd, "@StreamType", DbType.String).Value = query.Type.Value.ToString(); - } + if (query.Type.HasValue) + { + cmdText += " AND StreamType=@StreamType"; + cmd.Parameters.Add(cmd, "@StreamType", DbType.String).Value = query.Type.Value.ToString(); + } - if (query.Index.HasValue) - { - cmdText += " AND StreamIndex=@StreamIndex"; - cmd.Parameters.Add(cmd, "@StreamIndex", DbType.Int32).Value = query.Index.Value; - } + if (query.Index.HasValue) + { + cmdText += " AND StreamIndex=@StreamIndex"; + cmd.Parameters.Add(cmd, "@StreamIndex", DbType.Int32).Value = query.Index.Value; + } - cmdText += " order by StreamIndex ASC"; + cmdText += " order by StreamIndex ASC"; - cmd.CommandText = cmdText; + cmd.CommandText = cmdText; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - list.Add(GetMediaStream(reader)); + while (reader.Read()) + { + list.Add(GetMediaStream(reader)); + } } } + + return list; } + } - return list; + private void DeleteMediaStreams(IDbConnection connection, IDbTransaction transaction, Guid id) + { + using (var deleteStreamsCommand = connection.CreateCommand()) + { + // MediaStreams + deleteStreamsCommand.CommandText = "delete from mediastreams where ItemId=@ItemId"; + deleteStreamsCommand.Parameters.Add(deleteStreamsCommand, "@ItemId"); + + deleteStreamsCommand.GetParameter(0).Value = id; + + deleteStreamsCommand.Transaction = transaction; + + deleteStreamsCommand.ExecuteNonQuery(); + } } - public async Task SaveMediaStreams(Guid id, IEnumerable streams, CancellationToken cancellationToken) + public async Task SaveMediaStreams(Guid id, List streams, CancellationToken cancellationToken) { CheckDisposed(); @@ -3750,100 +3866,115 @@ 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(); - - // First delete chapters - _deleteStreamsCommand.GetParameter(0).Value = id; - - _deleteStreamsCommand.Transaction = transaction; + IDbTransaction transaction = null; - _deleteStreamsCommand.ExecuteNonQuery(); - - foreach (var stream in streams) + try { - cancellationToken.ThrowIfCancellationRequested(); - - var index = 0; - - _saveStreamCommand.GetParameter(index++).Value = id; - _saveStreamCommand.GetParameter(index++).Value = stream.Index; - _saveStreamCommand.GetParameter(index++).Value = stream.Type.ToString(); - _saveStreamCommand.GetParameter(index++).Value = stream.Codec; - _saveStreamCommand.GetParameter(index++).Value = stream.Language; - _saveStreamCommand.GetParameter(index++).Value = stream.ChannelLayout; - _saveStreamCommand.GetParameter(index++).Value = stream.Profile; - _saveStreamCommand.GetParameter(index++).Value = stream.AspectRatio; - _saveStreamCommand.GetParameter(index++).Value = stream.Path; - - _saveStreamCommand.GetParameter(index++).Value = stream.IsInterlaced; - - _saveStreamCommand.GetParameter(index++).Value = stream.BitRate; - _saveStreamCommand.GetParameter(index++).Value = stream.Channels; - _saveStreamCommand.GetParameter(index++).Value = stream.SampleRate; + transaction = connection.BeginTransaction(); - _saveStreamCommand.GetParameter(index++).Value = stream.IsDefault; - _saveStreamCommand.GetParameter(index++).Value = stream.IsForced; - _saveStreamCommand.GetParameter(index++).Value = stream.IsExternal; + // First delete + DeleteMediaStreams(connection, transaction, id); - _saveStreamCommand.GetParameter(index++).Value = stream.Width; - _saveStreamCommand.GetParameter(index++).Value = stream.Height; - _saveStreamCommand.GetParameter(index++).Value = stream.AverageFrameRate; - _saveStreamCommand.GetParameter(index++).Value = stream.RealFrameRate; - _saveStreamCommand.GetParameter(index++).Value = stream.Level; - _saveStreamCommand.GetParameter(index++).Value = stream.PixelFormat; - _saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; - _saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; - _saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; - - _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; - _saveStreamCommand.GetParameter(index++).Value = stream.Comment; - _saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; - _saveStreamCommand.GetParameter(index++).Value = stream.IsAVC; - _saveStreamCommand.GetParameter(index++).Value = stream.Title; - - _saveStreamCommand.GetParameter(index++).Value = stream.TimeBase; - _saveStreamCommand.GetParameter(index++).Value = stream.CodecTimeBase; + if (streams.Count > 0) + { + using (var saveStreamCommand = connection.CreateCommand()) + { + saveStreamCommand.CommandText = string.Format("replace into mediastreams ({0}) values ({1})", + string.Join(",", _mediaStreamSaveColumns), + string.Join(",", _mediaStreamSaveColumns.Select(i => "@" + i).ToArray())); + + foreach (var col in _mediaStreamSaveColumns) + { + saveStreamCommand.Parameters.Add(saveStreamCommand, "@" + col); + } + + if (streams.Count > 1) + { + saveStreamCommand.Prepare(); + } + + foreach (var stream in streams) + { + cancellationToken.ThrowIfCancellationRequested(); + + var index = 0; + + saveStreamCommand.GetParameter(index++).Value = id; + saveStreamCommand.GetParameter(index++).Value = stream.Index; + saveStreamCommand.GetParameter(index++).Value = stream.Type.ToString(); + saveStreamCommand.GetParameter(index++).Value = stream.Codec; + saveStreamCommand.GetParameter(index++).Value = stream.Language; + saveStreamCommand.GetParameter(index++).Value = stream.ChannelLayout; + saveStreamCommand.GetParameter(index++).Value = stream.Profile; + saveStreamCommand.GetParameter(index++).Value = stream.AspectRatio; + saveStreamCommand.GetParameter(index++).Value = stream.Path; + + saveStreamCommand.GetParameter(index++).Value = stream.IsInterlaced; + + saveStreamCommand.GetParameter(index++).Value = stream.BitRate; + saveStreamCommand.GetParameter(index++).Value = stream.Channels; + saveStreamCommand.GetParameter(index++).Value = stream.SampleRate; + + saveStreamCommand.GetParameter(index++).Value = stream.IsDefault; + saveStreamCommand.GetParameter(index++).Value = stream.IsForced; + saveStreamCommand.GetParameter(index++).Value = stream.IsExternal; + + saveStreamCommand.GetParameter(index++).Value = stream.Width; + saveStreamCommand.GetParameter(index++).Value = stream.Height; + saveStreamCommand.GetParameter(index++).Value = stream.AverageFrameRate; + saveStreamCommand.GetParameter(index++).Value = stream.RealFrameRate; + saveStreamCommand.GetParameter(index++).Value = stream.Level; + saveStreamCommand.GetParameter(index++).Value = stream.PixelFormat; + saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; + saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; + saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; + + saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; + saveStreamCommand.GetParameter(index++).Value = stream.Comment; + saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; + saveStreamCommand.GetParameter(index++).Value = stream.IsAVC; + saveStreamCommand.GetParameter(index++).Value = stream.Title; + + saveStreamCommand.GetParameter(index++).Value = stream.TimeBase; + saveStreamCommand.GetParameter(index++).Value = stream.CodecTimeBase; + + saveStreamCommand.Transaction = transaction; + saveStreamCommand.ExecuteNonQuery(); + } + } + } - _saveStreamCommand.Transaction = transaction; - _saveStreamCommand.ExecuteNonQuery(); + transaction.Commit(); } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + catch (OperationCanceledException) { - transaction.Rollback(); + if (transaction != null) + { + transaction.Rollback(); + } + + throw; } + catch (Exception e) + { + Logger.ErrorException("Failed to save media streams:", e); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save media streams:", e); + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); + throw; } - - throw; - } - finally - { - if (transaction != null) + finally { - transaction.Dispose(); + if (transaction != null) + { + transaction.Dispose(); + } } - - WriteLock.Release(); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index 0ce27fa5a2..da0f584d53 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -45,12 +45,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "create table if not exists userdata (key nvarchar, userId GUID, rating float null, played bit, playCount int, isFavorite bit, playbackPositionTicks bigint, lastPlayedDate datetime null)", "create index if not exists idx_userdata on userdata(key)", - "create unique index if not exists userdataindex on userdata (key, userId)", - - //pragmas - "pragma temp_store = memory", - - "pragma shrink_memory" + "create unique index if not exists userdataindex on userdata (key, userId)" }; connection.RunQueries(queries, Logger); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs index 4c07a60181..25ab60ca50 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs @@ -52,9 +52,6 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_users on users(guid)", "create table if not exists schema_version (table_name primary key, version)", - //pragmas - "pragma temp_store = memory", - "pragma shrink_memory" }; diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs index 3013510de1..74a552dccc 100644 --- a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs +++ b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs @@ -32,12 +32,7 @@ namespace MediaBrowser.Server.Implementations.Security 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)", - - //pragmas - "pragma temp_store = memory", - - "pragma shrink_memory" + "create index if not exists idx_AccessTokens on AccessTokens(Id)" }; connection.RunQueries(queries, Logger); diff --git a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs index 8a895037e7..c4243c1a76 100644 --- a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs +++ b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs @@ -31,9 +31,6 @@ namespace MediaBrowser.Server.Implementations.Social "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)", - //pragmas - "pragma temp_store = memory", - "pragma shrink_memory" }; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 5b623cf2ad..a1ed66a995 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -43,9 +43,6 @@ namespace MediaBrowser.Server.Implementations.Sync "create index if not exists idx_SyncJobItems1 on SyncJobItems(Id)", "create index if not exists idx_SyncJobItems2 on SyncJobItems(TargetId)", - //pragmas - "pragma temp_store = memory", - "pragma shrink_memory" }; -- cgit v1.2.3 From d7edd499d23c12252cf78e33e5ee2c96a952a6f6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 11 Jun 2016 21:25:20 -0400 Subject: update organizer db --- .../Persistence/BaseSqliteRepository.cs | 25 -- .../SqliteFileOrganizationRepository.cs | 425 ++++++++++----------- .../ApplicationHost.cs | 2 +- 3 files changed, 204 insertions(+), 248 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs index c6e7952294..709971797f 100644 --- a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs @@ -8,7 +8,6 @@ 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; @@ -46,7 +45,6 @@ namespace MediaBrowser.Server.Implementations.Persistence { _disposed = true; Dispose(true); - GC.SuppressFinalize(this); } protected async Task Vacuum(IDbConnection connection) @@ -69,35 +67,12 @@ namespace MediaBrowser.Server.Implementations.Persistence } } - private readonly object _disposeLock = new object(); - /// /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool dispose) { - if (dispose) - { - try - { - lock (_disposeLock) - { - WriteLock.Wait(); - - CloseConnection(); - } - } - catch (Exception ex) - { - Logger.ErrorException("Error disposing database", ex); - } - } - } - - protected virtual void CloseConnection() - { - } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs index d7e8afdd4c..7a5e000905 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs @@ -16,69 +16,29 @@ namespace MediaBrowser.Server.Implementations.Persistence { public class SqliteFileOrganizationRepository : BaseSqliteRepository, IFileOrganizationRepository, IDisposable { - private IDbConnection _connection; - - private readonly IServerApplicationPaths _appPaths; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private IDbCommand _saveResultCommand; - private IDbCommand _deleteResultCommand; - private IDbCommand _deleteAllCommand; - public SqliteFileOrganizationRepository(ILogManager logManager, IServerApplicationPaths appPaths, IDbConnector connector) : base(logManager, connector) { - _appPaths = appPaths; + DbFilePath = Path.Combine(appPaths.DataPath, "fileorganization.db"); } /// /// Opens the connection to the database /// /// Task. - public async Task Initialize(IDbConnector dbConnector) + public async Task Initialize() { - var dbFile = Path.Combine(_appPaths.DataPath, "fileorganization.db"); - - _connection = await dbConnector.Connect(dbFile, false).ConfigureAwait(false); - - string[] queries = { + using (var connection = await CreateConnection().ConfigureAwait(false)) + { + string[] queries = { "create table if not exists FileOrganizerResults (ResultId GUID PRIMARY KEY, OriginalPath TEXT, TargetPath TEXT, FileLength INT, OrganizationDate datetime, Status TEXT, OrganizationType TEXT, StatusMessage TEXT, ExtractedName TEXT, ExtractedYear int null, ExtractedSeasonNumber int null, ExtractedEpisodeNumber int null, ExtractedEndingEpisodeNumber, DuplicatePaths TEXT int null)", "create index if not exists idx_FileOrganizerResults on FileOrganizerResults(ResultId)" }; - _connection.RunQueries(queries, Logger); - - PrepareStatements(); - } - - private void PrepareStatements() - { - _saveResultCommand = _connection.CreateCommand(); - _saveResultCommand.CommandText = "replace into FileOrganizerResults (ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths) values (@ResultId, @OriginalPath, @TargetPath, @FileLength, @OrganizationDate, @Status, @OrganizationType, @StatusMessage, @ExtractedName, @ExtractedYear, @ExtractedSeasonNumber, @ExtractedEpisodeNumber, @ExtractedEndingEpisodeNumber, @DuplicatePaths)"; - - _saveResultCommand.Parameters.Add(_saveResultCommand, "@ResultId"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@OriginalPath"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@TargetPath"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@FileLength"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@OrganizationDate"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@Status"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@OrganizationType"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@StatusMessage"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedName"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedYear"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedSeasonNumber"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedEpisodeNumber"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@ExtractedEndingEpisodeNumber"); - _saveResultCommand.Parameters.Add(_saveResultCommand, "@DuplicatePaths"); - - _deleteResultCommand = _connection.CreateCommand(); - _deleteResultCommand.CommandText = "delete from FileOrganizerResults where ResultId = @ResultId"; - - _deleteResultCommand.Parameters.Add(_saveResultCommand, "@ResultId"); - - _deleteAllCommand = _connection.CreateCommand(); - _deleteAllCommand.CommandText = "delete from FileOrganizerResults"; + connection.RunQueries(queries, Logger); + } } public async Task SaveResult(FileOrganizationResult result, CancellationToken cancellationToken) @@ -90,65 +50,84 @@ 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(); - - var index = 0; - - _saveResultCommand.GetParameter(index++).Value = new Guid(result.Id); - _saveResultCommand.GetParameter(index++).Value = result.OriginalPath; - _saveResultCommand.GetParameter(index++).Value = result.TargetPath; - _saveResultCommand.GetParameter(index++).Value = result.FileSize; - _saveResultCommand.GetParameter(index++).Value = result.Date; - _saveResultCommand.GetParameter(index++).Value = result.Status.ToString(); - _saveResultCommand.GetParameter(index++).Value = result.Type.ToString(); - _saveResultCommand.GetParameter(index++).Value = result.StatusMessage; - _saveResultCommand.GetParameter(index++).Value = result.ExtractedName; - _saveResultCommand.GetParameter(index++).Value = result.ExtractedYear; - _saveResultCommand.GetParameter(index++).Value = result.ExtractedSeasonNumber; - _saveResultCommand.GetParameter(index++).Value = result.ExtractedEpisodeNumber; - _saveResultCommand.GetParameter(index++).Value = result.ExtractedEndingEpisodeNumber; - _saveResultCommand.GetParameter(index).Value = string.Join("|", result.DuplicatePaths.ToArray()); - - _saveResultCommand.Transaction = transaction; - - _saveResultCommand.ExecuteNonQuery(); - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + using (var saveResultCommand = connection.CreateCommand()) { - transaction.Rollback(); - } + saveResultCommand.CommandText = "replace into FileOrganizerResults (ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths) values (@ResultId, @OriginalPath, @TargetPath, @FileLength, @OrganizationDate, @Status, @OrganizationType, @StatusMessage, @ExtractedName, @ExtractedYear, @ExtractedSeasonNumber, @ExtractedEpisodeNumber, @ExtractedEndingEpisodeNumber, @DuplicatePaths)"; + + saveResultCommand.Parameters.Add(saveResultCommand, "@ResultId"); + saveResultCommand.Parameters.Add(saveResultCommand, "@OriginalPath"); + saveResultCommand.Parameters.Add(saveResultCommand, "@TargetPath"); + saveResultCommand.Parameters.Add(saveResultCommand, "@FileLength"); + saveResultCommand.Parameters.Add(saveResultCommand, "@OrganizationDate"); + saveResultCommand.Parameters.Add(saveResultCommand, "@Status"); + saveResultCommand.Parameters.Add(saveResultCommand, "@OrganizationType"); + saveResultCommand.Parameters.Add(saveResultCommand, "@StatusMessage"); + saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedName"); + saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedYear"); + saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedSeasonNumber"); + saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedEpisodeNumber"); + saveResultCommand.Parameters.Add(saveResultCommand, "@ExtractedEndingEpisodeNumber"); + saveResultCommand.Parameters.Add(saveResultCommand, "@DuplicatePaths"); + + IDbTransaction transaction = null; + + try + { + transaction = connection.BeginTransaction(); + + var index = 0; + + saveResultCommand.GetParameter(index++).Value = new Guid(result.Id); + saveResultCommand.GetParameter(index++).Value = result.OriginalPath; + saveResultCommand.GetParameter(index++).Value = result.TargetPath; + saveResultCommand.GetParameter(index++).Value = result.FileSize; + saveResultCommand.GetParameter(index++).Value = result.Date; + saveResultCommand.GetParameter(index++).Value = result.Status.ToString(); + saveResultCommand.GetParameter(index++).Value = result.Type.ToString(); + saveResultCommand.GetParameter(index++).Value = result.StatusMessage; + saveResultCommand.GetParameter(index++).Value = result.ExtractedName; + saveResultCommand.GetParameter(index++).Value = result.ExtractedYear; + saveResultCommand.GetParameter(index++).Value = result.ExtractedSeasonNumber; + saveResultCommand.GetParameter(index++).Value = result.ExtractedEpisodeNumber; + saveResultCommand.GetParameter(index++).Value = result.ExtractedEndingEpisodeNumber; + saveResultCommand.GetParameter(index).Value = string.Join("|", result.DuplicatePaths.ToArray()); + + saveResultCommand.Transaction = transaction; + + saveResultCommand.ExecuteNonQuery(); + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save FileOrganizationResult:", e); + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save FileOrganizationResult:", e); - if (transaction != null) - { - transaction.Rollback(); - } + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + } } - - WriteLock.Release(); } } @@ -159,100 +138,110 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("id"); } - await WriteLock.WaitAsync().ConfigureAwait(false); + using (var connection = await CreateConnection().ConfigureAwait(false)) + { + using (var deleteResultCommand = connection.CreateCommand()) + { + deleteResultCommand.CommandText = "delete from FileOrganizerResults where ResultId = @ResultId"; - IDbTransaction transaction = null; + deleteResultCommand.Parameters.Add(deleteResultCommand, "@ResultId"); - try - { - transaction = _connection.BeginTransaction(); + IDbTransaction transaction = null; - _deleteResultCommand.GetParameter(0).Value = new Guid(id); + try + { + transaction = connection.BeginTransaction(); - _deleteResultCommand.Transaction = transaction; + deleteResultCommand.GetParameter(0).Value = new Guid(id); - _deleteResultCommand.ExecuteNonQuery(); + deleteResultCommand.Transaction = transaction; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + deleteResultCommand.ExecuteNonQuery(); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to delete FileOrganizationResult:", e); + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to delete FileOrganizationResult:", e); - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } + if (transaction != null) + { + transaction.Rollback(); + } - WriteLock.Release(); + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + } + } } } public async Task DeleteAll() { - await WriteLock.WaitAsync().ConfigureAwait(false); + using (var connection = await CreateConnection().ConfigureAwait(false)) + { + using (var cmd = connection.CreateCommand()) + { + cmd.CommandText = "delete from FileOrganizerResults"; - IDbTransaction transaction = null; + IDbTransaction transaction = null; - try - { - transaction = _connection.BeginTransaction(); - - _deleteAllCommand.Transaction = transaction; + try + { + transaction = connection.BeginTransaction(); - _deleteAllCommand.ExecuteNonQuery(); + cmd.Transaction = transaction; - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + cmd.ExecuteNonQuery(); - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to delete results", e); + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to delete results", e); - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } + if (transaction != null) + { + transaction.Rollback(); + } - WriteLock.Release(); + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + } + } } } - + public QueryResult GetResults(FileOrganizationResultQuery query) { if (query == null) @@ -260,46 +249,49 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("query"); } - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "SELECT ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths from FileOrganizerResults"; - - if (query.StartIndex.HasValue && query.StartIndex.Value > 0) + using (var cmd = connection.CreateCommand()) { - cmd.CommandText += string.Format(" WHERE ResultId NOT IN (SELECT ResultId FROM FileOrganizerResults ORDER BY OrganizationDate desc LIMIT {0})", - query.StartIndex.Value.ToString(_usCulture)); - } + cmd.CommandText = "SELECT ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths from FileOrganizerResults"; - cmd.CommandText += " ORDER BY OrganizationDate desc"; + if (query.StartIndex.HasValue && query.StartIndex.Value > 0) + { + cmd.CommandText += string.Format(" WHERE ResultId NOT IN (SELECT ResultId FROM FileOrganizerResults ORDER BY OrganizationDate desc LIMIT {0})", + query.StartIndex.Value.ToString(_usCulture)); + } - if (query.Limit.HasValue) - { - cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); - } + cmd.CommandText += " ORDER BY OrganizationDate desc"; + + if (query.Limit.HasValue) + { + cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture); + } - cmd.CommandText += "; select count (ResultId) from FileOrganizerResults"; + cmd.CommandText += "; select count (ResultId) from FileOrganizerResults"; - var list = new List(); - var count = 0; + var list = new List(); + var count = 0; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - while (reader.Read()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { - list.Add(GetResult(reader)); + while (reader.Read()) + { + list.Add(GetResult(reader)); + } + + if (reader.NextResult() && reader.Read()) + { + count = reader.GetInt32(0); + } } - if (reader.NextResult() && reader.Read()) + return new QueryResult() { - count = reader.GetInt32(0); - } + Items = list.ToArray(), + TotalRecordCount = count + }; } - - return new QueryResult() - { - Items = list.ToArray(), - TotalRecordCount = count - }; } } @@ -310,24 +302,27 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("id"); } - var guid = new Guid(id); - - using (var cmd = _connection.CreateCommand()) + using (var connection = CreateConnection(true).Result) { - cmd.CommandText = "select ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths from FileOrganizerResults where ResultId=@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 = "select ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths from FileOrganizerResults where ResultId=@Id"; + + cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { - return GetResult(reader); + if (reader.Read()) + { + return GetResult(reader); + } } } - } - return null; + return null; + } } public FileOrganizationResult GetResult(IDataReader reader) @@ -409,19 +404,5 @@ namespace MediaBrowser.Server.Implementations.Persistence return result; } - - protected override void CloseConnection() - { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } } } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 9e869478ce..b0cf93673c 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -691,7 +691,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteFileOrganizationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, NativeApp.GetDbConnector()); - await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); + await repo.Initialize().ConfigureAwait(false); return repo; } -- cgit v1.2.3 From f378a2c789a7a12c3f848e262885b5bdd137754e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 12 Jun 2016 01:03:52 -0400 Subject: update item queries --- MediaBrowser.Api/StartupWizardService.cs | 2 +- .../Channels/ChannelItemInfo.cs | 2 + MediaBrowser.Controller/Entities/BaseItem.cs | 3 + .../Entities/InternalItemsQuery.cs | 1 + MediaBrowser.Controller/Entities/TV/Season.cs | 27 +------ MediaBrowser.Controller/Entities/TV/Series.cs | 6 +- .../TV/MissingEpisodeProvider.cs | 3 +- .../Channels/ChannelManager.cs | 1 + .../Library/UserViewManager.cs | 37 ++++------ .../LiveTv/LiveTvManager.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 86 +++++++++++++--------- 11 files changed, 83 insertions(+), 87 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index dbb6478a18..21f87a6117 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -114,7 +114,7 @@ namespace MediaBrowser.Api config.EnableStandaloneMusicKeys = true; config.EnableCaseSensitiveItemIds = true; config.EnableFolderView = true; - config.SchemaVersion = 89; + config.SchemaVersion = 91; } public void Post(UpdateStartupConfiguration request) diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs index 587023ab48..6135240e91 100644 --- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs @@ -53,6 +53,8 @@ namespace MediaBrowser.Controller.Channels public bool IsInfiniteStream { get; set; } + public string HomePageUrl { get; set; } + public ChannelItemInfo() { MediaSources = new List(); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index a45a462df4..33fd03e15d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -71,6 +71,9 @@ namespace MediaBrowser.Controller.Entities public List ImageInfos { get; set; } + [IgnoreDataMember] + public bool IsVirtualItem { get; set; } + /// /// Gets or sets the album. /// diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 04dfc94912..5b9d94fc26 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -117,6 +117,7 @@ namespace MediaBrowser.Controller.Entities public bool? IsCurrentSchema { get; set; } public bool? HasDeadParentId { get; set; } public bool? IsOffline { get; set; } + public bool? IsVirtualItem { get; set; } public Guid? ParentId { get; set; } public string[] AncestorIds { get; set; } diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index f07d4be13e..c984a2832a 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -128,39 +128,16 @@ namespace MediaBrowser.Controller.Entities.TV return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name; } - public override bool RequiresRefresh() - { - var result = base.RequiresRefresh(); - - if (!result) - { - if (!IsVirtualItem.HasValue) - { - return true; - } - } - - return result; - } - - [IgnoreDataMember] - public bool? IsVirtualItem { get; set; } - [IgnoreDataMember] public bool IsMissingSeason { - get { return (IsVirtualItem ?? DetectIsVirtualItem()) && !IsUnaired; } + get { return (IsVirtualItem) && !IsUnaired; } } [IgnoreDataMember] public bool IsVirtualUnaired { - get { return (IsVirtualItem ?? DetectIsVirtualItem()) && IsUnaired; } - } - - private bool DetectIsVirtualItem() - { - return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.LocationType == LocationType.Virtual); + get { return (IsVirtualItem) && IsUnaired; } } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 2f2968db8f..cc1378ae1a 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -92,10 +92,7 @@ namespace MediaBrowser.Controller.Entities.TV { get { - return GetRecursiveChildren(i => i is Episode) - .Select(i => i.DateCreated) - .OrderByDescending(i => i) - .FirstOrDefault(); + return DateLastMediaAdded ?? DateTime.MinValue; } } @@ -240,6 +237,7 @@ namespace MediaBrowser.Controller.Entities.TV AncestorWithPresentationUniqueKey = PresentationUniqueKey, IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }, SortBy = new[] { ItemSortBy.SortName } + }).ToList(); var allSeriesEpisodes = allItems.OfType().ToList(); diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 2a3150c78b..4e2d9a8d2d 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -428,7 +428,8 @@ namespace MediaBrowser.Providers.TV Name = name, IndexNumber = episodeNumber, ParentIndexNumber = seasonNumber, - Id = _libraryManager.GetNewItemId((series.Id + seasonNumber.ToString(_usCulture) + name), typeof(Episode)) + Id = _libraryManager.GetNewItemId((series.Id + seasonNumber.ToString(_usCulture) + name), typeof(Episode)), + IsVirtualItem = true }; episode.SetParent(season); diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index 6a9842cb2e..8dc2091980 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -1307,6 +1307,7 @@ namespace MediaBrowser.Server.Implementations.Channels item.OfficialRating = info.OfficialRating; item.DateCreated = info.DateCreated ?? DateTime.UtcNow; item.Tags = info.Tags; + item.HomePageUrl = info.HomePageUrl; } var trailer = item as Trailer; diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index e6a571f07d..319e715c33 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -202,23 +202,7 @@ namespace MediaBrowser.Server.Implementations.Library { var user = _userManager.GetUserById(request.UserId); - var includeTypes = request.IncludeItemTypes; - - var currentUser = user; - - var libraryItems = GetItemsForLatestItems(user, request.ParentId, includeTypes, request.Limit ?? 10).Where(i => - { - if (request.IsPlayed.HasValue) - { - var val = request.IsPlayed.Value; - if (i is Video && i.IsPlayed(currentUser) != val) - { - return false; - } - } - - return true; - }); + var libraryItems = GetItemsForLatestItems(user, request); var list = new List>>(); @@ -254,8 +238,13 @@ namespace MediaBrowser.Server.Implementations.Library return list; } - private IEnumerable GetItemsForLatestItems(User user, string parentId, string[] includeItemTypes, int limit) + private IEnumerable GetItemsForLatestItems(User user, LatestItemsQuery request) { + var parentId = request.ParentId; + + var includeItemTypes = request.IncludeItemTypes; + var limit = request.Limit ?? 10; + var parentIds = string.IsNullOrEmpty(parentId) ? new string[] { } : new[] { parentId }; @@ -276,7 +265,12 @@ namespace MediaBrowser.Server.Implementations.Library var excludeItemTypes = includeItemTypes.Length == 0 ? new[] { - typeof(Person).Name, typeof(Studio).Name, typeof(Year).Name, typeof(GameGenre).Name, typeof(MusicGenre).Name, typeof(Genre).Name + typeof(Person).Name, + typeof(Studio).Name, + typeof(Year).Name, + typeof(GameGenre).Name, + typeof(MusicGenre).Name, + typeof(Genre).Name } : new string[] { }; @@ -288,8 +282,9 @@ namespace MediaBrowser.Server.Implementations.Library IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null, ExcludeItemTypes = excludeItemTypes, ExcludeLocationTypes = new[] { LocationType.Virtual }, - Limit = limit * 20, - ExcludeSourceTypes = parentIds.Length == 0 ? new[] { SourceType.Channel, SourceType.LiveTV } : new SourceType[] { } + Limit = limit * 5, + ExcludeSourceTypes = parentIds.Length == 0 ? new[] { SourceType.Channel, SourceType.LiveTV } : new SourceType[] { }, + IsPlayed = request.IsPlayed }, parentIds); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 171ed824e8..b3bd24d96d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -952,7 +952,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (query.Limit.HasValue) { - internalQuery.Limit = Math.Max(query.Limit.Value * 5, 200); + internalQuery.Limit = Math.Max(query.Limit.Value * 4, 200); } if (query.HasAired.HasValue) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 0eb56a1fc4..ba3ada7049 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -58,7 +58,9 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly string _criticReviewsPath; - public const int LatestSchemaVersion = 89; + public const int LatestSchemaVersion = 91; + + private IDbConnection _connection; /// /// Initializes a new instance of the class. @@ -88,9 +90,9 @@ namespace MediaBrowser.Server.Implementations.Persistence //AttachUserDataDb(connection); - //connection.RunQueries(new [] + //connection.RunQueries(new[] //{ - // "pragma locking_mode=EXCLUSIVE" + // "pragma locking_mode=NORMAL" //}, Logger); @@ -105,6 +107,8 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Task. public async Task Initialize(IDbConnector dbConnector) { + //_connection = await CreateConnection().ConfigureAwait(false); + using (var connection = await CreateConnection().ConfigureAwait(false)) { var createMediaStreamsTableCommand @@ -115,7 +119,6 @@ namespace MediaBrowser.Server.Implementations.Persistence "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID, Path TEXT)", "create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)", "create index if not exists idx_ParentIdTypedBaseItems on TypedBaseItems(ParentId)", - "create index if not exists idx_TypedBaseItems2 on TypedBaseItems(Type,Guid)", "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))", "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)", @@ -234,9 +237,14 @@ namespace MediaBrowser.Server.Implementations.Persistence string[] postQueries = { "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)", + "create index if not exists idx_GuidType on TypedBaseItems(Guid,Type)", "create index if not exists idx_Type on TypedBaseItems(Type)", "create index if not exists idx_TopParentId on TypedBaseItems(TopParentId)", - "create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)" + "create index if not exists idx_TypeTopParentId on TypedBaseItems(Type,TopParentId)", + "create index if not exists idx_TypeTopParentId2 on TypedBaseItems(TopParentId,MediaType,IsVirtualItem)", + "create index if not exists idx_TypeTopParentId3 on TypedBaseItems(TopParentId,IsFolder,IsVirtualItem)", + "create index if not exists idx_TypeTopParentId4 on TypedBaseItems(TopParentId,Type,IsVirtualItem)", + "create index if not exists idx_TypeTopParentId5 on TypedBaseItems(TopParentId,IsVirtualItem)" }; connection.RunQueries(postQueries, Logger); @@ -727,15 +735,7 @@ namespace MediaBrowser.Server.Implementations.Persistence saveItemCommand.GetParameter(index++).Value = item.Album; - var season = item as Season; - if (season != null && season.IsVirtualItem.HasValue) - { - saveItemCommand.GetParameter(index++).Value = season.IsVirtualItem.Value; - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - } + saveItemCommand.GetParameter(index++).Value = item.IsVirtualItem || (!item.IsFolder && item.LocationType == LocationType.Virtual); var hasSeries = item as IHasSeries; if (hasSeries != null) @@ -1167,10 +1167,9 @@ namespace MediaBrowser.Server.Implementations.Persistence item.CriticRatingSummary = reader.GetString(57); } - var season = item as Season; - if (season != null && !reader.IsDBNull(58)) + if (!reader.IsDBNull(58)) { - season.IsVirtualItem = reader.GetBoolean(58); + item.IsVirtualItem = reader.GetBoolean(58); } return item; @@ -1651,7 +1650,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var slowThreshold = 1000; #if DEBUG - slowThreshold = 100; + slowThreshold = 30; #endif if (elapsed >= slowThreshold) @@ -2196,18 +2195,6 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.Parameters.Add(cmd, "@IsFolder", DbType.Boolean).Value = query.IsFolder; } - var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); - if (includeTypes.Length == 1) - { - whereClauses.Add("type=@type"); - cmd.Parameters.Add(cmd, "@type", DbType.String).Value = includeTypes[0]; - } - else if (includeTypes.Length > 1) - { - var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("type in ({0})", inClause)); - } - var excludeTypes = query.ExcludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); if (excludeTypes.Length == 1) { @@ -2220,6 +2207,18 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add(string.Format("type not in ({0})", inClause)); } + var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); + if (includeTypes.Length == 1) + { + whereClauses.Add("type=@type"); + cmd.Parameters.Add(cmd, "@type", DbType.String).Value = includeTypes[0]; + } + else if (includeTypes.Length > 1) + { + var inClause = string.Join(",", includeTypes.Select(i => "'" + i + "'").ToArray()); + whereClauses.Add(string.Format("type in ({0})", inClause)); + } + if (query.ChannelIds.Length == 1) { whereClauses.Add("ChannelId=@ChannelId"); @@ -2635,8 +2634,15 @@ namespace MediaBrowser.Server.Implementations.Persistence if (query.LocationTypes.Length == 1) { - whereClauses.Add("LocationType=@LocationType"); - cmd.Parameters.Add(cmd, "@LocationType", DbType.String).Value = query.LocationTypes[0].ToString(); + if (query.LocationTypes[0] == LocationType.Virtual && _config.Configuration.SchemaVersion >= 90) + { + query.IsVirtualItem = true; + } + else + { + whereClauses.Add("LocationType=@LocationType"); + cmd.Parameters.Add(cmd, "@LocationType", DbType.String).Value = query.LocationTypes[0].ToString(); + } } else if (query.LocationTypes.Length > 1) { @@ -2646,8 +2652,15 @@ namespace MediaBrowser.Server.Implementations.Persistence } if (query.ExcludeLocationTypes.Length == 1) { - whereClauses.Add("LocationType<>@ExcludeLocationTypes"); - cmd.Parameters.Add(cmd, "@ExcludeLocationTypes", DbType.String).Value = query.ExcludeLocationTypes[0].ToString(); + if (query.ExcludeLocationTypes[0] == LocationType.Virtual && _config.Configuration.SchemaVersion >= 90) + { + query.IsVirtualItem = false; + } + else + { + whereClauses.Add("LocationType<>@ExcludeLocationTypes"); + cmd.Parameters.Add(cmd, "@ExcludeLocationTypes", DbType.String).Value = query.ExcludeLocationTypes[0].ToString(); + } } else if (query.ExcludeLocationTypes.Length > 1) { @@ -2655,6 +2668,11 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add("LocationType not in (" + val + ")"); } + if (query.IsVirtualItem.HasValue) + { + whereClauses.Add("IsVirtualItem=@IsVirtualItem"); + cmd.Parameters.Add(cmd, "@IsVirtualItem", DbType.Boolean).Value = query.IsVirtualItem.Value; + } if (query.MediaTypes.Length == 1) { whereClauses.Add("MediaType=@MediaTypes"); -- cgit v1.2.3 From 383110f9af6b5ad79ddabb3c8db0bdb7d4b4db03 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 12 Jun 2016 19:33:11 -0400 Subject: switch recordings to ts when preserving original audio --- MediaBrowser.Providers/TV/SeriesPostScanTask.cs | 39 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- .../Persistence/BaseSqliteRepository.cs | 40 +- .../Persistence/SqliteExtensions.cs | 6 +- .../Persistence/SqliteItemRepository.cs | 2851 ++++++++++---------- .../Persistence/SqliteUserDataRepository.cs | 322 +-- .../ApplicationHost.cs | 4 +- 7 files changed, 1595 insertions(+), 1669 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index 3c0a5fc73b..d044c828ff 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -195,28 +195,35 @@ namespace MediaBrowser.Providers.TV private async void LibraryUpdateTimerCallback(object state) { - if (MissingEpisodeProvider.IsRunning) + try { - return; - } + if (MissingEpisodeProvider.IsRunning) + { + return; + } - if (_libraryManager.IsScanRunning) - { - return ; - } + if (_libraryManager.IsScanRunning) + { + return; + } - var seriesList = _libraryManager.GetItemList(new InternalItemsQuery() - { - IncludeItemTypes = new[] { typeof(Series).Name }, - Recursive = true, - GroupByPresentationUniqueKey = false + var seriesList = _libraryManager.GetItemList(new InternalItemsQuery() + { + IncludeItemTypes = new[] { typeof(Series).Name }, + Recursive = true, + GroupByPresentationUniqueKey = false - }).Cast().ToList(); + }).Cast().ToList(); - var seriesGroups = SeriesPostScanTask.FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList(); + var seriesGroups = SeriesPostScanTask.FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList(); - await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem) - .Run(seriesGroups, false, CancellationToken.None).ConfigureAwait(false); + await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem) + .Run(seriesGroups, false, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error in SeriesPostScanTask", ex); + } } private bool FilterItem(BaseItem item) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index e9ea49fa32..4022252ac8 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var streams = mediaSource.MediaStreams ?? new List(); if (streams.Any(i => i.Type == MediaStreamType.Audio && (i.Codec ?? string.Empty).IndexOf("aac", StringComparison.OrdinalIgnoreCase) != -1)) { - return Path.ChangeExtension(targetFile, ".mkv"); + return Path.ChangeExtension(targetFile, ".ts"); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs index 709971797f..eec5b4b76c 100644 --- a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs @@ -8,6 +8,7 @@ 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; @@ -19,11 +20,16 @@ namespace MediaBrowser.Server.Implementations.Persistence Logger = logManager.GetLogger(GetType().Name); } + protected virtual bool EnableConnectionPooling + { + get { return true; } + } + protected virtual async Task CreateConnection(bool isReadOnly = false) { var connection = await DbConnector.Connect(DbFilePath, false, true).ConfigureAwait(false); - connection.RunQueries(new [] + connection.RunQueries(new[] { "pragma temp_store = memory" @@ -45,12 +51,15 @@ namespace MediaBrowser.Server.Implementations.Persistence { _disposed = true; Dispose(true); + GC.SuppressFinalize(this); } protected async Task Vacuum(IDbConnection connection) { CheckDisposed(); + await WriteLock.WaitAsync().ConfigureAwait(false); + try { using (var cmd = connection.CreateCommand()) @@ -65,14 +74,41 @@ namespace MediaBrowser.Server.Implementations.Persistence throw; } + finally + { + WriteLock.Release(); + } } + private readonly object _disposeLock = new object(); + /// /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool dispose) { + if (dispose) + { + try + { + lock (_disposeLock) + { + WriteLock.Wait(); + + CloseConnection(); + } + } + catch (Exception ex) + { + Logger.ErrorException("Error disposing database", ex); + } + } + } + + protected virtual void CloseConnection() + { + } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index 0a76381e12..b1206c297a 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -39,12 +39,8 @@ namespace MediaBrowser.Server.Implementations.Persistence var connectionString = connectionstr.ConnectionString; - if (enablePooling) - { - connectionString += ";Max Pool Size=100"; - } - //logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, connectionString); + SQLiteConnection.SetMemoryStatus(false); var connection = new SQLiteConnection(connectionString); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index ba3ada7049..4e851053b1 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -31,6 +31,8 @@ namespace MediaBrowser.Server.Implementations.Persistence /// public class SqliteItemRepository : BaseSqliteRepository, IItemRepository { + private IDbConnection _connection; + private readonly TypeMapper _typeMapper = new TypeMapper(); /// @@ -56,11 +58,43 @@ namespace MediaBrowser.Server.Implementations.Persistence /// private readonly IServerConfigurationManager _config; + /// + /// The _save item command + /// + private IDbCommand _saveItemCommand; + private readonly string _criticReviewsPath; - public const int LatestSchemaVersion = 91; + private IDbCommand _deleteItemCommand; - private IDbConnection _connection; + private IDbCommand _deletePeopleCommand; + private IDbCommand _savePersonCommand; + + private IDbCommand _deleteChaptersCommand; + private IDbCommand _saveChapterCommand; + + private IDbCommand _deleteStreamsCommand; + private IDbCommand _saveStreamCommand; + + private IDbCommand _deleteAncestorsCommand; + private IDbCommand _saveAncestorCommand; + + private IDbCommand _deleteUserDataKeysCommand; + private IDbCommand _saveUserDataKeysCommand; + + private IDbCommand _deleteItemValuesCommand; + private IDbCommand _saveItemValuesCommand; + + private IDbCommand _deleteProviderIdsCommand; + private IDbCommand _saveProviderIdsCommand; + + private IDbCommand _deleteImagesCommand; + private IDbCommand _saveImagesCommand; + + private IDbCommand _updateInheritedRatingCommand; + private IDbCommand _updateInheritedTagsCommand; + + public const int LatestSchemaVersion = 89; /// /// Initializes a new instance of the class. @@ -84,37 +118,33 @@ namespace MediaBrowser.Server.Implementations.Persistence DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); } + private const string ChaptersTableName = "Chapters2"; + protected override async Task CreateConnection(bool isReadOnly = false) { - var connection = await DbConnector.Connect(DbFilePath, false, true, 20000).ConfigureAwait(false); - - //AttachUserDataDb(connection); + var connection = await DbConnector.Connect(DbFilePath, false, false, 6000).ConfigureAwait(false); - //connection.RunQueries(new[] - //{ - // "pragma locking_mode=NORMAL" + connection.RunQueries(new[] + { + "pragma temp_store = memory" - //}, Logger); + }, Logger); return connection; } - private const string ChaptersTableName = "Chapters2"; - /// /// Opens the connection to the database /// /// Task. - public async Task Initialize(IDbConnector dbConnector) + public async Task Initialize() { - //_connection = await CreateConnection().ConfigureAwait(false); + _connection = await CreateConnection(false).ConfigureAwait(false); - using (var connection = await CreateConnection().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))"; + 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))"; - string[] queries = { + string[] queries = { "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID, Path TEXT)", "create index if not exists idx_PathTypedBaseItems on TypedBaseItems(Path)", @@ -146,96 +176,96 @@ namespace MediaBrowser.Server.Implementations.Persistence createMediaStreamsTableCommand, "create index if not exists idx_mediastreams1 on mediastreams(ItemId)", - + }; - connection.RunQueries(queries, Logger); - - connection.AddColumn(Logger, "AncestorIds", "AncestorIdText", "Text"); - - connection.AddColumn(Logger, "TypedBaseItems", "Path", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "StartDate", "DATETIME"); - connection.AddColumn(Logger, "TypedBaseItems", "EndDate", "DATETIME"); - connection.AddColumn(Logger, "TypedBaseItems", "ChannelId", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "IsMovie", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "IsSports", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "IsKids", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "CommunityRating", "Float"); - connection.AddColumn(Logger, "TypedBaseItems", "CustomRating", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "IndexNumber", "INT"); - connection.AddColumn(Logger, "TypedBaseItems", "IsLocked", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "Name", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "OfficialRating", "Text"); - - connection.AddColumn(Logger, "TypedBaseItems", "MediaType", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "Overview", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "ParentIndexNumber", "INT"); - connection.AddColumn(Logger, "TypedBaseItems", "PremiereDate", "DATETIME"); - connection.AddColumn(Logger, "TypedBaseItems", "ProductionYear", "INT"); - connection.AddColumn(Logger, "TypedBaseItems", "ParentId", "GUID"); - connection.AddColumn(Logger, "TypedBaseItems", "Genres", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "ParentalRatingValue", "INT"); - connection.AddColumn(Logger, "TypedBaseItems", "SchemaVersion", "INT"); - connection.AddColumn(Logger, "TypedBaseItems", "SortName", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "RunTimeTicks", "BIGINT"); - - connection.AddColumn(Logger, "TypedBaseItems", "OfficialRatingDescription", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "HomePageUrl", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "VoteCount", "INT"); - connection.AddColumn(Logger, "TypedBaseItems", "DisplayMediaType", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "DateCreated", "DATETIME"); - connection.AddColumn(Logger, "TypedBaseItems", "DateModified", "DATETIME"); - - connection.AddColumn(Logger, "TypedBaseItems", "ForcedSortName", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "IsOffline", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "LocationType", "Text"); - - connection.AddColumn(Logger, "TypedBaseItems", "IsSeries", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "IsLive", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "IsNews", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "IsPremiere", "BIT"); - - connection.AddColumn(Logger, "TypedBaseItems", "EpisodeTitle", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "IsRepeat", "BIT"); - - connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataLanguage", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataCountryCode", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "IsHD", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "ExternalEtag", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "DateLastRefreshed", "DATETIME"); - - connection.AddColumn(Logger, "TypedBaseItems", "DateLastSaved", "DATETIME"); - connection.AddColumn(Logger, "TypedBaseItems", "IsInMixedFolder", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "LockedFields", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "Studios", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "Audio", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "ExternalServiceId", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "Tags", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "IsFolder", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "InheritedParentalRatingValue", "INT"); - connection.AddColumn(Logger, "TypedBaseItems", "UnratedType", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "TopParentId", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "IsItemByName", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "SourceType", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "TrailerTypes", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "CriticRating", "Float"); - connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); - connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "PresentationUniqueKey", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "SlugName", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "OriginalTitle", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "PrimaryVersionId", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME"); - connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text"); - connection.AddColumn(Logger, "TypedBaseItems", "IsVirtualItem", "BIT"); - connection.AddColumn(Logger, "TypedBaseItems", "SeriesName", "Text"); - - connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT"); - - string[] postQueries = - { + _connection.RunQueries(queries, Logger); + + _connection.AddColumn(Logger, "AncestorIds", "AncestorIdText", "Text"); + + _connection.AddColumn(Logger, "TypedBaseItems", "Path", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "StartDate", "DATETIME"); + _connection.AddColumn(Logger, "TypedBaseItems", "EndDate", "DATETIME"); + _connection.AddColumn(Logger, "TypedBaseItems", "ChannelId", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsMovie", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsSports", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsKids", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "CommunityRating", "Float"); + _connection.AddColumn(Logger, "TypedBaseItems", "CustomRating", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "IndexNumber", "INT"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsLocked", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "Name", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "OfficialRating", "Text"); + + _connection.AddColumn(Logger, "TypedBaseItems", "MediaType", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "Overview", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "ParentIndexNumber", "INT"); + _connection.AddColumn(Logger, "TypedBaseItems", "PremiereDate", "DATETIME"); + _connection.AddColumn(Logger, "TypedBaseItems", "ProductionYear", "INT"); + _connection.AddColumn(Logger, "TypedBaseItems", "ParentId", "GUID"); + _connection.AddColumn(Logger, "TypedBaseItems", "Genres", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "ParentalRatingValue", "INT"); + _connection.AddColumn(Logger, "TypedBaseItems", "SchemaVersion", "INT"); + _connection.AddColumn(Logger, "TypedBaseItems", "SortName", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "RunTimeTicks", "BIGINT"); + + _connection.AddColumn(Logger, "TypedBaseItems", "OfficialRatingDescription", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "HomePageUrl", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "VoteCount", "INT"); + _connection.AddColumn(Logger, "TypedBaseItems", "DisplayMediaType", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "DateCreated", "DATETIME"); + _connection.AddColumn(Logger, "TypedBaseItems", "DateModified", "DATETIME"); + + _connection.AddColumn(Logger, "TypedBaseItems", "ForcedSortName", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsOffline", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "LocationType", "Text"); + + _connection.AddColumn(Logger, "TypedBaseItems", "IsSeries", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsLive", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsNews", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsPremiere", "BIT"); + + _connection.AddColumn(Logger, "TypedBaseItems", "EpisodeTitle", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsRepeat", "BIT"); + + _connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataLanguage", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "PreferredMetadataCountryCode", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsHD", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "ExternalEtag", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "DateLastRefreshed", "DATETIME"); + + _connection.AddColumn(Logger, "TypedBaseItems", "DateLastSaved", "DATETIME"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsInMixedFolder", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "LockedFields", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "Studios", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "Audio", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "ExternalServiceId", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "Tags", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsFolder", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "InheritedParentalRatingValue", "INT"); + _connection.AddColumn(Logger, "TypedBaseItems", "UnratedType", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "TopParentId", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsItemByName", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "SourceType", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "TrailerTypes", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "CriticRating", "Float"); + _connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); + _connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "PresentationUniqueKey", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "SlugName", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "OriginalTitle", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "PrimaryVersionId", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME"); + _connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "IsVirtualItem", "BIT"); + _connection.AddColumn(Logger, "TypedBaseItems", "SeriesName", "Text"); + + _connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT"); + + string[] postQueries = + { "create index if not exists idx_PresentationUniqueKey on TypedBaseItems(PresentationUniqueKey)", "create index if not exists idx_GuidType on TypedBaseItems(Guid,Type)", "create index if not exists idx_Type on TypedBaseItems(Type)", @@ -247,17 +277,13 @@ namespace MediaBrowser.Server.Implementations.Persistence "create index if not exists idx_TypeTopParentId5 on TypedBaseItems(TopParentId,IsVirtualItem)" }; - connection.RunQueries(postQueries, Logger); + _connection.RunQueries(postQueries, Logger); - new MediaStreamColumns(connection, Logger).AddColumns(); + PrepareStatements(); - //AttachUserDataDb(connection); - } - } + new MediaStreamColumns(_connection, Logger).AddColumns(); - private void AttachUserDataDb(IDbConnection connection) - { - DataExtensions.Attach(connection, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"), "UserDataDb" + Guid.NewGuid().ToString("N")); + DataExtensions.Attach(_connection, Path.Combine(_config.ApplicationPaths.DataPath, "userdata_v2.db"), "UserDataDb"); } private readonly string[] _retriveItemColumns = @@ -359,6 +385,220 @@ namespace MediaBrowser.Server.Implementations.Persistence "CodecTimeBase" }; + /// + /// Prepares the statements. + /// + private void PrepareStatements() + { + var saveColumns = new List + { + "guid", + "type", + "data", + "Path", + "StartDate", + "EndDate", + "ChannelId", + "IsKids", + "IsMovie", + "IsSports", + "IsSeries", + "IsLive", + "IsNews", + "IsPremiere", + "EpisodeTitle", + "IsRepeat", + "CommunityRating", + "CustomRating", + "IndexNumber", + "IsLocked", + "Name", + "OfficialRating", + "MediaType", + "Overview", + "ParentIndexNumber", + "PremiereDate", + "ProductionYear", + "ParentId", + "Genres", + "ParentalRatingValue", + "InheritedParentalRatingValue", + "SchemaVersion", + "SortName", + "RunTimeTicks", + "OfficialRatingDescription", + "HomePageUrl", + "VoteCount", + "DisplayMediaType", + "DateCreated", + "DateModified", + "ForcedSortName", + "IsOffline", + "LocationType", + "PreferredMetadataLanguage", + "PreferredMetadataCountryCode", + "IsHD", + "ExternalEtag", + "DateLastRefreshed", + "DateLastSaved", + "IsInMixedFolder", + "LockedFields", + "Studios", + "Audio", + "ExternalServiceId", + "Tags", + "IsFolder", + "UnratedType", + "TopParentId", + "IsItemByName", + "SourceType", + "TrailerTypes", + "CriticRating", + "CriticRatingSummary", + "DateModifiedDuringLastRefresh", + "InheritedTags", + "CleanName", + "PresentationUniqueKey", + "SlugName", + "OriginalTitle", + "PrimaryVersionId", + "DateLastMediaAdded", + "Album", + "IsVirtualItem", + "SeriesName" + }; + _saveItemCommand = _connection.CreateCommand(); + _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; + + for (var i = 1; i <= saveColumns.Count; i++) + { + if (i > 1) + { + _saveItemCommand.CommandText += ","; + } + _saveItemCommand.CommandText += "@" + i.ToString(CultureInfo.InvariantCulture); + + _saveItemCommand.Parameters.Add(_saveItemCommand, "@" + i.ToString(CultureInfo.InvariantCulture)); + } + _saveItemCommand.CommandText += ")"; + + _deleteItemCommand = _connection.CreateCommand(); + _deleteItemCommand.CommandText = "delete from TypedBaseItems where guid=@Id"; + _deleteItemCommand.Parameters.Add(_deleteItemCommand, "@Id"); + + // People + _deletePeopleCommand = _connection.CreateCommand(); + _deletePeopleCommand.CommandText = "delete from People where ItemId=@Id"; + _deletePeopleCommand.Parameters.Add(_deletePeopleCommand, "@Id"); + + _savePersonCommand = _connection.CreateCommand(); + _savePersonCommand.CommandText = "insert into People (ItemId, Name, Role, PersonType, SortOrder, ListOrder) values (@ItemId, @Name, @Role, @PersonType, @SortOrder, @ListOrder)"; + _savePersonCommand.Parameters.Add(_savePersonCommand, "@ItemId"); + _savePersonCommand.Parameters.Add(_savePersonCommand, "@Name"); + _savePersonCommand.Parameters.Add(_savePersonCommand, "@Role"); + _savePersonCommand.Parameters.Add(_savePersonCommand, "@PersonType"); + _savePersonCommand.Parameters.Add(_savePersonCommand, "@SortOrder"); + _savePersonCommand.Parameters.Add(_savePersonCommand, "@ListOrder"); + + // Ancestors + _deleteAncestorsCommand = _connection.CreateCommand(); + _deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id"; + _deleteAncestorsCommand.Parameters.Add(_deleteAncestorsCommand, "@Id"); + + _saveAncestorCommand = _connection.CreateCommand(); + _saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId, AncestorIdText) values (@ItemId, @AncestorId, @AncestorIdText)"; + _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@ItemId"); + _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorId"); + _saveAncestorCommand.Parameters.Add(_saveAncestorCommand, "@AncestorIdText"); + + // Chapters + _deleteChaptersCommand = _connection.CreateCommand(); + _deleteChaptersCommand.CommandText = "delete from " + ChaptersTableName + " where ItemId=@ItemId"; + _deleteChaptersCommand.Parameters.Add(_deleteChaptersCommand, "@ItemId"); + + _saveChapterCommand = _connection.CreateCommand(); + _saveChapterCommand.CommandText = "replace into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath) values (@ItemId, @ChapterIndex, @StartPositionTicks, @Name, @ImagePath)"; + + _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ItemId"); + _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ChapterIndex"); + _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@StartPositionTicks"); + _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@Name"); + _saveChapterCommand.Parameters.Add(_saveChapterCommand, "@ImagePath"); + + // MediaStreams + _deleteStreamsCommand = _connection.CreateCommand(); + _deleteStreamsCommand.CommandText = "delete from mediastreams where ItemId=@ItemId"; + _deleteStreamsCommand.Parameters.Add(_deleteStreamsCommand, "@ItemId"); + + _saveStreamCommand = _connection.CreateCommand(); + + _saveStreamCommand.CommandText = string.Format("replace into mediastreams ({0}) values ({1})", + string.Join(",", _mediaStreamSaveColumns), + string.Join(",", _mediaStreamSaveColumns.Select(i => "@" + i).ToArray())); + + foreach (var col in _mediaStreamSaveColumns) + { + _saveStreamCommand.Parameters.Add(_saveStreamCommand, "@" + col); + } + + _updateInheritedRatingCommand = _connection.CreateCommand(); + _updateInheritedRatingCommand.CommandText = "Update TypedBaseItems set InheritedParentalRatingValue=@InheritedParentalRatingValue where Guid=@Guid"; + _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@Guid"); + _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@InheritedParentalRatingValue"); + + _updateInheritedTagsCommand = _connection.CreateCommand(); + _updateInheritedTagsCommand.CommandText = "Update TypedBaseItems set InheritedTags=@InheritedTags where Guid=@Guid"; + _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@Guid"); + _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@InheritedTags"); + + // user data + _deleteUserDataKeysCommand = _connection.CreateCommand(); + _deleteUserDataKeysCommand.CommandText = "delete from UserDataKeys where ItemId=@Id"; + _deleteUserDataKeysCommand.Parameters.Add(_deleteUserDataKeysCommand, "@Id"); + + _saveUserDataKeysCommand = _connection.CreateCommand(); + _saveUserDataKeysCommand.CommandText = "insert into UserDataKeys (ItemId, UserDataKey, Priority) values (@ItemId, @UserDataKey, @Priority)"; + _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@ItemId"); + _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@UserDataKey"); + _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@Priority"); + + // item values + _deleteItemValuesCommand = _connection.CreateCommand(); + _deleteItemValuesCommand.CommandText = "delete from ItemValues where ItemId=@Id"; + _deleteItemValuesCommand.Parameters.Add(_deleteItemValuesCommand, "@Id"); + + _saveItemValuesCommand = _connection.CreateCommand(); + _saveItemValuesCommand.CommandText = "insert into ItemValues (ItemId, Type, Value) values (@ItemId, @Type, @Value)"; + _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@ItemId"); + _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Type"); + _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Value"); + + // provider ids + _deleteProviderIdsCommand = _connection.CreateCommand(); + _deleteProviderIdsCommand.CommandText = "delete from ProviderIds where ItemId=@Id"; + _deleteProviderIdsCommand.Parameters.Add(_deleteProviderIdsCommand, "@Id"); + + _saveProviderIdsCommand = _connection.CreateCommand(); + _saveProviderIdsCommand.CommandText = "insert into ProviderIds (ItemId, Name, Value) values (@ItemId, @Name, @Value)"; + _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@ItemId"); + _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Name"); + _saveProviderIdsCommand.Parameters.Add(_saveProviderIdsCommand, "@Value"); + + // images + _deleteImagesCommand = _connection.CreateCommand(); + _deleteImagesCommand.CommandText = "delete from Images where ItemId=@Id"; + _deleteImagesCommand.Parameters.Add(_deleteImagesCommand, "@Id"); + + _saveImagesCommand = _connection.CreateCommand(); + _saveImagesCommand.CommandText = "insert into Images (ItemId, ImageType, Path, DateModified, IsPlaceHolder, SortOrder) values (@ItemId, @ImageType, @Path, @DateModified, @IsPlaceHolder, @SortOrder)"; + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ItemId"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@ImageType"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@Path"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@DateModified"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@IsPlaceHolder"); + _saveImagesCommand.Parameters.Add(_saveImagesCommand, "@SortOrder"); + } + /// /// Save a standard item in the repo /// @@ -398,400 +638,306 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var connection = await CreateConnection().ConfigureAwait(false)) + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try { - IDbTransaction transaction = null; + transaction = _connection.BeginTransaction(); - try + foreach (var item in items) { - transaction = connection.BeginTransaction(); + cancellationToken.ThrowIfCancellationRequested(); + + var index = 0; - using (var saveItemCommand = connection.CreateCommand()) + _saveItemCommand.GetParameter(index++).Value = item.Id; + _saveItemCommand.GetParameter(index++).Value = item.GetType().FullName; + _saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item); + + _saveItemCommand.GetParameter(index++).Value = item.Path; + + var hasStartDate = item as IHasStartDate; + if (hasStartDate != null) { - var saveColumns = new List - { - "guid", - "type", - "data", - "Path", - "StartDate", - "EndDate", - "ChannelId", - "IsKids", - "IsMovie", - "IsSports", - "IsSeries", - "IsLive", - "IsNews", - "IsPremiere", - "EpisodeTitle", - "IsRepeat", - "CommunityRating", - "CustomRating", - "IndexNumber", - "IsLocked", - "Name", - "OfficialRating", - "MediaType", - "Overview", - "ParentIndexNumber", - "PremiereDate", - "ProductionYear", - "ParentId", - "Genres", - "ParentalRatingValue", - "InheritedParentalRatingValue", - "SchemaVersion", - "SortName", - "RunTimeTicks", - "OfficialRatingDescription", - "HomePageUrl", - "VoteCount", - "DisplayMediaType", - "DateCreated", - "DateModified", - "ForcedSortName", - "IsOffline", - "LocationType", - "PreferredMetadataLanguage", - "PreferredMetadataCountryCode", - "IsHD", - "ExternalEtag", - "DateLastRefreshed", - "DateLastSaved", - "IsInMixedFolder", - "LockedFields", - "Studios", - "Audio", - "ExternalServiceId", - "Tags", - "IsFolder", - "UnratedType", - "TopParentId", - "IsItemByName", - "SourceType", - "TrailerTypes", - "CriticRating", - "CriticRatingSummary", - "DateModifiedDuringLastRefresh", - "InheritedTags", - "CleanName", - "PresentationUniqueKey", - "SlugName", - "OriginalTitle", - "PrimaryVersionId", - "DateLastMediaAdded", - "Album", - "IsVirtualItem", - "SeriesName" - }; - - saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; - - for (var i = 1; i <= saveColumns.Count; i++) - { - if (i > 1) - { - saveItemCommand.CommandText += ","; - } - saveItemCommand.CommandText += "@" + i.ToString(CultureInfo.InvariantCulture); + _saveItemCommand.GetParameter(index++).Value = hasStartDate.StartDate; + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } - saveItemCommand.Parameters.Add(saveItemCommand, "@" + i.ToString(CultureInfo.InvariantCulture)); - } - saveItemCommand.CommandText += ")"; + _saveItemCommand.GetParameter(index++).Value = item.EndDate; + _saveItemCommand.GetParameter(index++).Value = item.ChannelId; - foreach (var item in items) - { - cancellationToken.ThrowIfCancellationRequested(); - - var index = 0; - - saveItemCommand.GetParameter(index++).Value = item.Id; - saveItemCommand.GetParameter(index++).Value = item.GetType().FullName; - saveItemCommand.GetParameter(index++).Value = _jsonSerializer.SerializeToBytes(item); - - saveItemCommand.GetParameter(index++).Value = item.Path; - - var hasStartDate = item as IHasStartDate; - if (hasStartDate != null) - { - saveItemCommand.GetParameter(index++).Value = hasStartDate.StartDate; - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - } - - saveItemCommand.GetParameter(index++).Value = item.EndDate; - saveItemCommand.GetParameter(index++).Value = item.ChannelId; - - var hasProgramAttributes = item as IHasProgramAttributes; - if (hasProgramAttributes != null) - { - saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsKids; - saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsMovie; - saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSports; - saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSeries; - saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsLive; - saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsNews; - saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsPremiere; - saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.EpisodeTitle; - saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsRepeat; - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - saveItemCommand.GetParameter(index++).Value = null; - saveItemCommand.GetParameter(index++).Value = null; - saveItemCommand.GetParameter(index++).Value = null; - saveItemCommand.GetParameter(index++).Value = null; - saveItemCommand.GetParameter(index++).Value = null; - saveItemCommand.GetParameter(index++).Value = null; - saveItemCommand.GetParameter(index++).Value = null; - saveItemCommand.GetParameter(index++).Value = null; - } - - saveItemCommand.GetParameter(index++).Value = item.CommunityRating; - saveItemCommand.GetParameter(index++).Value = item.CustomRating; - - saveItemCommand.GetParameter(index++).Value = item.IndexNumber; - saveItemCommand.GetParameter(index++).Value = item.IsLocked; - - saveItemCommand.GetParameter(index++).Value = item.Name; - saveItemCommand.GetParameter(index++).Value = item.OfficialRating; - - saveItemCommand.GetParameter(index++).Value = item.MediaType; - saveItemCommand.GetParameter(index++).Value = item.Overview; - saveItemCommand.GetParameter(index++).Value = item.ParentIndexNumber; - saveItemCommand.GetParameter(index++).Value = item.PremiereDate; - saveItemCommand.GetParameter(index++).Value = item.ProductionYear; - - if (item.ParentId == Guid.Empty) - { - saveItemCommand.GetParameter(index++).Value = null; - } - else - { - saveItemCommand.GetParameter(index++).Value = item.ParentId; - } - - saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Genres.ToArray()); - saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue() ?? 0; - saveItemCommand.GetParameter(index++).Value = item.GetInheritedParentalRatingValue() ?? 0; - - saveItemCommand.GetParameter(index++).Value = LatestSchemaVersion; - saveItemCommand.GetParameter(index++).Value = item.SortName; - saveItemCommand.GetParameter(index++).Value = item.RunTimeTicks; - - saveItemCommand.GetParameter(index++).Value = item.OfficialRatingDescription; - saveItemCommand.GetParameter(index++).Value = item.HomePageUrl; - saveItemCommand.GetParameter(index++).Value = item.VoteCount; - saveItemCommand.GetParameter(index++).Value = item.DisplayMediaType; - saveItemCommand.GetParameter(index++).Value = item.DateCreated; - saveItemCommand.GetParameter(index++).Value = item.DateModified; - - saveItemCommand.GetParameter(index++).Value = item.ForcedSortName; - saveItemCommand.GetParameter(index++).Value = item.IsOffline; - saveItemCommand.GetParameter(index++).Value = item.LocationType.ToString(); - - saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataLanguage; - saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataCountryCode; - saveItemCommand.GetParameter(index++).Value = item.IsHD; - saveItemCommand.GetParameter(index++).Value = item.ExternalEtag; - - if (item.DateLastRefreshed == default(DateTime)) - { - saveItemCommand.GetParameter(index++).Value = null; - } - else - { - saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed; - } - - if (item.DateLastSaved == default(DateTime)) - { - saveItemCommand.GetParameter(index++).Value = null; - } - else - { - saveItemCommand.GetParameter(index++).Value = item.DateLastSaved; - } - - saveItemCommand.GetParameter(index++).Value = item.IsInMixedFolder; - saveItemCommand.GetParameter(index++).Value = string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()); - saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.ToArray()); - - if (item.Audio.HasValue) - { - saveItemCommand.GetParameter(index++).Value = item.Audio.Value.ToString(); - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - } - - saveItemCommand.GetParameter(index++).Value = item.ServiceName; - - if (item.Tags.Count > 0) - { - saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - } - - saveItemCommand.GetParameter(index++).Value = item.IsFolder; - - saveItemCommand.GetParameter(index++).Value = item.GetBlockUnratedType().ToString(); - - var topParent = item.GetTopParent(); - if (topParent != null) - { - //Logger.Debug("Item {0} has top parent {1}", item.Id, topParent.Id); - saveItemCommand.GetParameter(index++).Value = topParent.Id.ToString("N"); - } - else - { - //Logger.Debug("Item {0} has null top parent", item.Id); - saveItemCommand.GetParameter(index++).Value = null; - } - - var isByName = false; - var byName = item as IItemByName; - if (byName != null) - { - var dualAccess = item as IHasDualAccess; - isByName = dualAccess == null || dualAccess.IsAccessedByName; - } - saveItemCommand.GetParameter(index++).Value = isByName; - - saveItemCommand.GetParameter(index++).Value = item.SourceType.ToString(); - - var trailer = item as Trailer; - if (trailer != null && trailer.TrailerTypes.Count > 0) - { - saveItemCommand.GetParameter(index++).Value = string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray()); - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - } - - saveItemCommand.GetParameter(index++).Value = item.CriticRating; - saveItemCommand.GetParameter(index++).Value = item.CriticRatingSummary; - - if (!item.DateModifiedDuringLastRefresh.HasValue || item.DateModifiedDuringLastRefresh.Value == default(DateTime)) - { - saveItemCommand.GetParameter(index++).Value = null; - } - else - { - saveItemCommand.GetParameter(index++).Value = item.DateModifiedDuringLastRefresh.Value; - } - - var inheritedTags = item.GetInheritedTags(); - if (inheritedTags.Count > 0) - { - saveItemCommand.GetParameter(index++).Value = string.Join("|", inheritedTags.ToArray()); - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - } - - if (string.IsNullOrWhiteSpace(item.Name)) - { - saveItemCommand.GetParameter(index++).Value = null; - } - else - { - saveItemCommand.GetParameter(index++).Value = item.Name.RemoveDiacritics(); - } - - saveItemCommand.GetParameter(index++).Value = item.PresentationUniqueKey; - saveItemCommand.GetParameter(index++).Value = item.SlugName; - saveItemCommand.GetParameter(index++).Value = item.OriginalTitle; - - var video = item as Video; - if (video != null) - { - saveItemCommand.GetParameter(index++).Value = video.PrimaryVersionId; - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - } - - var folder = item as Folder; - if (folder != null && folder.DateLastMediaAdded.HasValue) - { - saveItemCommand.GetParameter(index++).Value = folder.DateLastMediaAdded.Value; - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - } - - saveItemCommand.GetParameter(index++).Value = item.Album; - - saveItemCommand.GetParameter(index++).Value = item.IsVirtualItem || (!item.IsFolder && item.LocationType == LocationType.Virtual); - - var hasSeries = item as IHasSeries; - if (hasSeries != null) - { - saveItemCommand.GetParameter(index++).Value = hasSeries.SeriesName; - } - else - { - saveItemCommand.GetParameter(index++).Value = null; - } - - saveItemCommand.Transaction = transaction; - - saveItemCommand.ExecuteNonQuery(); - - if (item.SupportsAncestors) - { - UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), connection, transaction); - } - - UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), connection, transaction); - UpdateImages(item.Id, item.ImageInfos, connection, transaction); - UpdateProviderIds(item.Id, item.ProviderIds, connection, transaction); - UpdateItemValues(item.Id, GetItemValues(item), connection, transaction); - } + var hasProgramAttributes = item as IHasProgramAttributes; + if (hasProgramAttributes != null) + { + _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsKids; + _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsMovie; + _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSports; + _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsSeries; + _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsLive; + _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsNews; + _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsPremiere; + _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.EpisodeTitle; + _saveItemCommand.GetParameter(index++).Value = hasProgramAttributes.IsRepeat; + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + _saveItemCommand.GetParameter(index++).Value = null; + _saveItemCommand.GetParameter(index++).Value = null; + _saveItemCommand.GetParameter(index++).Value = null; + _saveItemCommand.GetParameter(index++).Value = null; + _saveItemCommand.GetParameter(index++).Value = null; + _saveItemCommand.GetParameter(index++).Value = null; + _saveItemCommand.GetParameter(index++).Value = null; + _saveItemCommand.GetParameter(index++).Value = null; } - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) + _saveItemCommand.GetParameter(index++).Value = item.CommunityRating; + _saveItemCommand.GetParameter(index++).Value = item.CustomRating; + + _saveItemCommand.GetParameter(index++).Value = item.IndexNumber; + _saveItemCommand.GetParameter(index++).Value = item.IsLocked; + + _saveItemCommand.GetParameter(index++).Value = item.Name; + _saveItemCommand.GetParameter(index++).Value = item.OfficialRating; + + _saveItemCommand.GetParameter(index++).Value = item.MediaType; + _saveItemCommand.GetParameter(index++).Value = item.Overview; + _saveItemCommand.GetParameter(index++).Value = item.ParentIndexNumber; + _saveItemCommand.GetParameter(index++).Value = item.PremiereDate; + _saveItemCommand.GetParameter(index++).Value = item.ProductionYear; + + if (item.ParentId == Guid.Empty) + { + _saveItemCommand.GetParameter(index++).Value = null; + } + else { - transaction.Rollback(); + _saveItemCommand.GetParameter(index++).Value = item.ParentId; } - throw; - } - catch (Exception e) - { - Logger.ErrorException("Failed to save items:", e); + _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Genres.ToArray()); + _saveItemCommand.GetParameter(index++).Value = item.GetParentalRatingValue() ?? 0; + _saveItemCommand.GetParameter(index++).Value = item.GetInheritedParentalRatingValue() ?? 0; + + _saveItemCommand.GetParameter(index++).Value = LatestSchemaVersion; + _saveItemCommand.GetParameter(index++).Value = item.SortName; + _saveItemCommand.GetParameter(index++).Value = item.RunTimeTicks; + + _saveItemCommand.GetParameter(index++).Value = item.OfficialRatingDescription; + _saveItemCommand.GetParameter(index++).Value = item.HomePageUrl; + _saveItemCommand.GetParameter(index++).Value = item.VoteCount; + _saveItemCommand.GetParameter(index++).Value = item.DisplayMediaType; + _saveItemCommand.GetParameter(index++).Value = item.DateCreated; + _saveItemCommand.GetParameter(index++).Value = item.DateModified; + + _saveItemCommand.GetParameter(index++).Value = item.ForcedSortName; + _saveItemCommand.GetParameter(index++).Value = item.IsOffline; + _saveItemCommand.GetParameter(index++).Value = item.LocationType.ToString(); + + _saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataLanguage; + _saveItemCommand.GetParameter(index++).Value = item.PreferredMetadataCountryCode; + _saveItemCommand.GetParameter(index++).Value = item.IsHD; + _saveItemCommand.GetParameter(index++).Value = item.ExternalEtag; + + if (item.DateLastRefreshed == default(DateTime)) + { + _saveItemCommand.GetParameter(index++).Value = null; + } + else + { + _saveItemCommand.GetParameter(index++).Value = item.DateLastRefreshed; + } - if (transaction != null) + if (item.DateLastSaved == default(DateTime)) { - transaction.Rollback(); + _saveItemCommand.GetParameter(index++).Value = null; + } + else + { + _saveItemCommand.GetParameter(index++).Value = item.DateLastSaved; } - throw; - } - finally - { - if (transaction != null) + _saveItemCommand.GetParameter(index++).Value = item.IsInMixedFolder; + _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()); + _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Studios.ToArray()); + + if (item.Audio.HasValue) + { + _saveItemCommand.GetParameter(index++).Value = item.Audio.Value.ToString(); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + + _saveItemCommand.GetParameter(index++).Value = item.ServiceName; + + if (item.Tags.Count > 0) + { + _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + + _saveItemCommand.GetParameter(index++).Value = item.IsFolder; + + _saveItemCommand.GetParameter(index++).Value = item.GetBlockUnratedType().ToString(); + + var topParent = item.GetTopParent(); + if (topParent != null) + { + //Logger.Debug("Item {0} has top parent {1}", item.Id, topParent.Id); + _saveItemCommand.GetParameter(index++).Value = topParent.Id.ToString("N"); + } + else + { + //Logger.Debug("Item {0} has null top parent", item.Id); + _saveItemCommand.GetParameter(index++).Value = null; + } + + var isByName = false; + var byName = item as IItemByName; + if (byName != null) + { + var dualAccess = item as IHasDualAccess; + isByName = dualAccess == null || dualAccess.IsAccessedByName; + } + _saveItemCommand.GetParameter(index++).Value = isByName; + + _saveItemCommand.GetParameter(index++).Value = item.SourceType.ToString(); + + var trailer = item as Trailer; + if (trailer != null && trailer.TrailerTypes.Count > 0) + { + _saveItemCommand.GetParameter(index++).Value = string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray()); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + + _saveItemCommand.GetParameter(index++).Value = item.CriticRating; + _saveItemCommand.GetParameter(index++).Value = item.CriticRatingSummary; + + if (!item.DateModifiedDuringLastRefresh.HasValue || item.DateModifiedDuringLastRefresh.Value == default(DateTime)) + { + _saveItemCommand.GetParameter(index++).Value = null; + } + else + { + _saveItemCommand.GetParameter(index++).Value = item.DateModifiedDuringLastRefresh.Value; + } + + var inheritedTags = item.GetInheritedTags(); + if (inheritedTags.Count > 0) { - transaction.Dispose(); + _saveItemCommand.GetParameter(index++).Value = string.Join("|", inheritedTags.ToArray()); } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + + if (string.IsNullOrWhiteSpace(item.Name)) + { + _saveItemCommand.GetParameter(index++).Value = null; + } + else + { + _saveItemCommand.GetParameter(index++).Value = item.Name.RemoveDiacritics(); + } + + _saveItemCommand.GetParameter(index++).Value = item.PresentationUniqueKey; + _saveItemCommand.GetParameter(index++).Value = item.SlugName; + _saveItemCommand.GetParameter(index++).Value = item.OriginalTitle; + + var video = item as Video; + if (video != null) + { + _saveItemCommand.GetParameter(index++).Value = video.PrimaryVersionId; + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + + var folder = item as Folder; + if (folder != null && folder.DateLastMediaAdded.HasValue) + { + _saveItemCommand.GetParameter(index++).Value = folder.DateLastMediaAdded.Value; + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + + _saveItemCommand.GetParameter(index++).Value = item.Album; + + _saveItemCommand.GetParameter(index++).Value = item.IsVirtualItem || (!item.IsFolder && item.LocationType == LocationType.Virtual); + + var hasSeries = item as IHasSeries; + if (hasSeries != null) + { + _saveItemCommand.GetParameter(index++).Value = hasSeries.SeriesName; + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + + _saveItemCommand.Transaction = transaction; + + _saveItemCommand.ExecuteNonQuery(); + + if (item.SupportsAncestors) + { + UpdateAncestors(item.Id, item.GetAncestorIds().Distinct().ToList(), transaction); + } + + UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), transaction); + UpdateImages(item.Id, item.ImageInfos, transaction); + UpdateProviderIds(item.Id, item.ProviderIds, transaction); + UpdateItemValues(item.Id, GetItemValues(item), transaction); + } + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save items:", e); + + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); } + + WriteLock.Release(); } } @@ -811,22 +957,19 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where guid = @guid"; - cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = id; + cmd.CommandText = "select " + string.Join(",", _retriveItemColumns) + " from TypedBaseItems where guid = @guid"; + cmd.Parameters.Add(cmd, "@guid", DbType.Guid).Value = id; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + { + if (reader.Read()) { - if (reader.Read()) - { - return GetItem(reader); - } + return GetItem(reader); } - return null; } + return null; } } @@ -1231,25 +1374,22 @@ namespace MediaBrowser.Server.Implementations.Persistence } var list = new List(); - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select StartPositionTicks,Name,ImagePath from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc"; + cmd.CommandText = "select StartPositionTicks,Name,ImagePath from " + ChaptersTableName + " where ItemId = @ItemId order by ChapterIndex asc"; - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; + cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) { - while (reader.Read()) - { - list.Add(GetChapter(reader)); - } + list.Add(GetChapter(reader)); } } - - return list; } + + return list; } /// @@ -1267,24 +1407,21 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("id"); } - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select StartPositionTicks,Name,ImagePath from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex"; + cmd.CommandText = "select StartPositionTicks,Name,ImagePath from " + ChaptersTableName + " where ItemId = @ItemId and ChapterIndex=@ChapterIndex"; - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; - cmd.Parameters.Add(cmd, "@ChapterIndex", DbType.Int32).Value = index; + cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = id; + cmd.Parameters.Add(cmd, "@ChapterIndex", DbType.Int32).Value = index; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + { + if (reader.Read()) { - if (reader.Read()) - { - return GetChapter(reader); - } + return GetChapter(reader); } - return null; } + return null; } } @@ -1313,21 +1450,6 @@ namespace MediaBrowser.Server.Implementations.Persistence return chapter; } - private void DeleteChapters(IDbConnection connection, IDbTransaction transaction, Guid id) - { - using (var deleteChaptersCommand = connection.CreateCommand()) - { - deleteChaptersCommand.CommandText = "delete from " + ChaptersTableName + " where ItemId=@ItemId"; - deleteChaptersCommand.Parameters.Add(deleteChaptersCommand, "@ItemId"); - - deleteChaptersCommand.GetParameter(0).Value = id; - - deleteChaptersCommand.Transaction = transaction; - - deleteChaptersCommand.ExecuteNonQuery(); - } - } - /// /// Saves the chapters. /// @@ -1358,83 +1480,84 @@ namespace MediaBrowser.Server.Implementations.Persistence cancellationToken.ThrowIfCancellationRequested(); - using (var connection = await CreateConnection().ConfigureAwait(false)) + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try { - IDbTransaction transaction = null; + transaction = _connection.BeginTransaction(); - try + // First delete chapters + _deleteChaptersCommand.GetParameter(0).Value = id; + + _deleteChaptersCommand.Transaction = transaction; + + _deleteChaptersCommand.ExecuteNonQuery(); + + var index = 0; + + foreach (var chapter in chapters) { - transaction = connection.BeginTransaction(); + cancellationToken.ThrowIfCancellationRequested(); - // First delete chapters - DeleteChapters(connection, transaction, id); + _saveChapterCommand.GetParameter(0).Value = id; + _saveChapterCommand.GetParameter(1).Value = index; + _saveChapterCommand.GetParameter(2).Value = chapter.StartPositionTicks; + _saveChapterCommand.GetParameter(3).Value = chapter.Name; + _saveChapterCommand.GetParameter(4).Value = chapter.ImagePath; - var index = 0; + _saveChapterCommand.Transaction = transaction; - if (chapters.Count > 0) - { - using (var saveChapterCommand = connection.CreateCommand()) - { - saveChapterCommand.CommandText = "replace into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath) values (@ItemId, @ChapterIndex, @StartPositionTicks, @Name, @ImagePath)"; - saveChapterCommand.Parameters.Add(saveChapterCommand, "@ItemId"); - saveChapterCommand.Parameters.Add(saveChapterCommand, "@ChapterIndex"); - saveChapterCommand.Parameters.Add(saveChapterCommand, "@StartPositionTicks"); - saveChapterCommand.Parameters.Add(saveChapterCommand, "@Name"); - saveChapterCommand.Parameters.Add(saveChapterCommand, "@ImagePath"); - - if (chapters.Count > 1) - { - saveChapterCommand.Prepare(); - } - - foreach (var chapter in chapters) - { - cancellationToken.ThrowIfCancellationRequested(); - - saveChapterCommand.GetParameter(0).Value = id; - saveChapterCommand.GetParameter(1).Value = index; - saveChapterCommand.GetParameter(2).Value = chapter.StartPositionTicks; - saveChapterCommand.GetParameter(3).Value = chapter.Name; - saveChapterCommand.GetParameter(4).Value = chapter.ImagePath; - - saveChapterCommand.Transaction = transaction; - - saveChapterCommand.ExecuteNonQuery(); - - index++; - } - } - } + _saveChapterCommand.ExecuteNonQuery(); - transaction.Commit(); + index++; } - catch (OperationCanceledException) + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) { - if (transaction != null) - { - transaction.Rollback(); - } + transaction.Rollback(); + } + + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save chapters:", e); - throw; + if (transaction != null) + { + transaction.Rollback(); } - catch (Exception e) + + throw; + } + finally + { + if (transaction != null) { - Logger.ErrorException("Failed to save chapters:", e); + transaction.Dispose(); + } - if (transaction != null) - { - transaction.Rollback(); - } + WriteLock.Release(); + } + } - throw; - } - finally + protected override void CloseConnection() + { + if (_connection != null) + { + if (_connection.IsOpen()) { - if (transaction != null) - { - transaction.Dispose(); - } + _connection.Close(); } + + _connection.Dispose(); + _connection = null; } } @@ -1508,13 +1631,13 @@ namespace MediaBrowser.Server.Implementations.Persistence if (EnableJoinUserData(query)) { - list.Add("UserData.UserId"); - list.Add("UserData.lastPlayedDate"); - list.Add("UserData.playbackPositionTicks"); - list.Add("UserData.playcount"); - list.Add("UserData.isFavorite"); - list.Add("UserData.played"); - list.Add("UserData.rating"); + list.Add("UserDataDb.UserData.UserId"); + list.Add("UserDataDb.UserData.lastPlayedDate"); + list.Add("UserDataDb.UserData.playbackPositionTicks"); + list.Add("UserDataDb.UserData.playcount"); + list.Add("UserDataDb.UserData.isFavorite"); + list.Add("UserDataDb.UserData.played"); + list.Add("UserDataDb.UserData.rating"); } if (query.SimilarTo != null) @@ -1568,7 +1691,7 @@ namespace MediaBrowser.Server.Implementations.Persistence return string.Empty; } - return " left join UserData on (select UserDataKey from UserDataKeys where ItemId=Guid order by Priority LIMIT 1)=UserData.Key"; + return " left join UserDataDb.UserData on (select UserDataKey from UserDataKeys where ItemId=Guid order by Priority LIMIT 1)=UserDataDb.UserData.Key"; } public IEnumerable GetItemList(InternalItemsQuery query) @@ -1582,61 +1705,53 @@ namespace MediaBrowser.Server.Implementations.Persistence var now = DateTime.UtcNow; - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; + cmd.CommandText += GetJoinUserDataText(query); + if (EnableJoinUserData(query)) { - AttachUserDataDb(connection); + cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; } - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; - cmd.CommandText += GetJoinUserDataText(query); + var whereClauses = GetWhereClauses(query, cmd); - if (EnableJoinUserData(query)) - { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; - } + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereClauses = GetWhereClauses(query, cmd); + cmd.CommandText += whereText; - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += " Group by PresentationUniqueKey"; + } - cmd.CommandText += whereText; + cmd.CommandText += GetOrderByText(query); - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + if (query.Limit.HasValue || query.StartIndex.HasValue) + { + var limit = query.Limit ?? int.MaxValue; - cmd.CommandText += GetOrderByText(query); + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - if (query.Limit.HasValue || query.StartIndex.HasValue) + if (query.StartIndex.HasValue) { - var limit = query.Limit ?? int.MaxValue; - - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - - if (query.StartIndex.HasValue) - { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); - } + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); } + } - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - LogQueryTime("GetItemList", cmd, now); + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + LogQueryTime("GetItemList", cmd, now); - while (reader.Read()) + while (reader.Read()) + { + var item = GetItem(reader); + if (item != null) { - var item = GetItem(reader); - if (item != null) - { - yield return item; - } + yield return item; } } } @@ -1650,7 +1765,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var slowThreshold = 1000; #if DEBUG - slowThreshold = 30; + slowThreshold = 100; #endif if (elapsed >= slowThreshold) @@ -1680,94 +1795,86 @@ namespace MediaBrowser.Server.Implementations.Persistence var now = DateTime.UtcNow; - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; + cmd.CommandText += GetJoinUserDataText(query); + if (EnableJoinUserData(query)) { - AttachUserDataDb(connection); + cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; } - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; - cmd.CommandText += GetJoinUserDataText(query); - - if (EnableJoinUserData(query)) - { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; - } - - var whereClauses = GetWhereClauses(query, cmd); + var whereClauses = GetWhereClauses(query, cmd); - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereTextWithoutPaging = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - cmd.CommandText += whereText; + cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } - - cmd.CommandText += GetOrderByText(query); + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += " Group by PresentationUniqueKey"; + } - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var limit = query.Limit ?? int.MaxValue; + cmd.CommandText += GetOrderByText(query); - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); + if (query.Limit.HasValue || query.StartIndex.HasValue) + { + var limit = query.Limit ?? int.MaxValue; - if (query.StartIndex.HasValue) - { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); - } - } + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - if (EnableGroupByPresentationUniqueKey(query)) + if (query.StartIndex.HasValue) { - cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; - } - else - { - cmd.CommandText += "; select count (guid) from TypedBaseItems"; + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); } + } - cmd.CommandText += GetJoinUserDataText(query); - cmd.CommandText += whereTextWithoutPaging; + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; + } + else + { + cmd.CommandText += "; select count (guid) from TypedBaseItems"; + } - var list = new List(); - var count = 0; + cmd.CommandText += GetJoinUserDataText(query); + cmd.CommandText += whereTextWithoutPaging; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) - { - LogQueryTime("GetItems", cmd, now); + var list = new List(); + var count = 0; - while (reader.Read()) - { - var item = GetItem(reader); - if (item != null) - { - list.Add(item); - } - } + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + { + LogQueryTime("GetItems", cmd, now); - if (reader.NextResult() && reader.Read()) + while (reader.Read()) + { + var item = GetItem(reader); + if (item != null) { - count = reader.GetInt32(0); + list.Add(item); } } - return new QueryResult() + if (reader.NextResult() && reader.Read()) { - Items = list.ToArray(), - TotalRecordCount = count - }; + count = reader.GetInt32(0); + } } + + return new QueryResult() + { + Items = list.ToArray(), + TotalRecordCount = count + }; } } @@ -1885,64 +1992,56 @@ namespace MediaBrowser.Server.Implementations.Persistence var now = DateTime.UtcNow; - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; + cmd.CommandText += GetJoinUserDataText(query); + if (EnableJoinUserData(query)) { - AttachUserDataDb(connection); + cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; } - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; - cmd.CommandText += GetJoinUserDataText(query); + var whereClauses = GetWhereClauses(query, cmd); - if (EnableJoinUserData(query)) - { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; - } + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereClauses = GetWhereClauses(query, cmd); + cmd.CommandText += whereText; - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += " Group by PresentationUniqueKey"; + } - cmd.CommandText += whereText; + cmd.CommandText += GetOrderByText(query); - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + if (query.Limit.HasValue || query.StartIndex.HasValue) + { + var limit = query.Limit ?? int.MaxValue; - cmd.CommandText += GetOrderByText(query); + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - if (query.Limit.HasValue || query.StartIndex.HasValue) + if (query.StartIndex.HasValue) { - var limit = query.Limit ?? int.MaxValue; - - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - - if (query.StartIndex.HasValue) - { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); - } + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); } + } - var list = new List(); + var list = new List(); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - LogQueryTime("GetItemIdsList", cmd, now); + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + LogQueryTime("GetItemIdsList", cmd, now); - while (reader.Read()) - { - list.Add(reader.GetGuid(0)); - } + while (reader.Read()) + { + list.Add(reader.GetGuid(0)); } - - return list; } + + return list; } } @@ -1955,76 +2054,73 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select guid,path from TypedBaseItems"; + cmd.CommandText = "select guid,path from TypedBaseItems"; - var whereClauses = GetWhereClauses(query, cmd); + var whereClauses = GetWhereClauses(query, cmd); - var whereTextWithoutPaging = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereTextWithoutPaging = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - cmd.CommandText += whereText; + cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += " Group by PresentationUniqueKey"; + } - cmd.CommandText += GetOrderByText(query); + cmd.CommandText += GetOrderByText(query); - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var limit = query.Limit ?? int.MaxValue; + if (query.Limit.HasValue || query.StartIndex.HasValue) + { + var limit = query.Limit ?? int.MaxValue; - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - if (query.StartIndex.HasValue) - { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); - } + if (query.StartIndex.HasValue) + { + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); } + } - cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging; + cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging; - var list = new List>(); - var count = 0; + var list = new List>(); + var count = 0; - Logger.Debug(cmd.CommandText); + Logger.Debug(cmd.CommandText); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + { + while (reader.Read()) { - while (reader.Read()) - { - var id = reader.GetGuid(0); - string path = null; - - if (!reader.IsDBNull(1)) - { - path = reader.GetString(1); - } - list.Add(new Tuple(id, path)); - } + var id = reader.GetGuid(0); + string path = null; - if (reader.NextResult() && reader.Read()) + if (!reader.IsDBNull(1)) { - count = reader.GetInt32(0); + path = reader.GetString(1); } + list.Add(new Tuple(id, path)); } - return new QueryResult>() + if (reader.NextResult() && reader.Read()) { - Items = list.ToArray(), - TotalRecordCount = count - }; + count = reader.GetInt32(0); + } } + + return new QueryResult>() + { + Items = list.ToArray(), + TotalRecordCount = count + }; } } @@ -2039,86 +2135,78 @@ namespace MediaBrowser.Server.Implementations.Persistence var now = DateTime.UtcNow; - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; + + var whereClauses = GetWhereClauses(query, cmd); + cmd.CommandText += GetJoinUserDataText(query); + if (EnableJoinUserData(query)) { - AttachUserDataDb(connection); + cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; } - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; + var whereText = whereClauses.Count == 0 ? + string.Empty : + " where " + string.Join(" AND ", whereClauses.ToArray()); - var whereClauses = GetWhereClauses(query, cmd); - cmd.CommandText += GetJoinUserDataText(query); + cmd.CommandText += whereText; - if (EnableJoinUserData(query)) - { - cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = query.User.Id; - } + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += " Group by PresentationUniqueKey"; + } - var whereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + cmd.CommandText += GetOrderByText(query); - cmd.CommandText += whereText; + if (query.Limit.HasValue || query.StartIndex.HasValue) + { + var limit = query.Limit ?? int.MaxValue; + + cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); - if (EnableGroupByPresentationUniqueKey(query)) + if (query.StartIndex.HasValue) { - cmd.CommandText += " Group by PresentationUniqueKey"; + cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); } + } - cmd.CommandText += GetOrderByText(query); + if (EnableGroupByPresentationUniqueKey(query)) + { + cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; + } + else + { + cmd.CommandText += "; select count (guid) from TypedBaseItems"; + } - if (query.Limit.HasValue || query.StartIndex.HasValue) - { - var limit = query.Limit ?? int.MaxValue; + cmd.CommandText += GetJoinUserDataText(query); + cmd.CommandText += whereText; - cmd.CommandText += " LIMIT " + limit.ToString(CultureInfo.InvariantCulture); + var list = new List(); + var count = 0; - if (query.StartIndex.HasValue) - { - cmd.CommandText += " OFFSET " + query.StartIndex.Value.ToString(CultureInfo.InvariantCulture); - } - } + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + { + LogQueryTime("GetItemIds", cmd, now); - if (EnableGroupByPresentationUniqueKey(query)) + while (reader.Read()) { - cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; + list.Add(reader.GetGuid(0)); } - else - { - cmd.CommandText += "; select count (guid) from TypedBaseItems"; - } - - cmd.CommandText += GetJoinUserDataText(query); - cmd.CommandText += whereText; - var list = new List(); - var count = 0; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + if (reader.NextResult() && reader.Read()) { - LogQueryTime("GetItemIds", cmd, now); - - while (reader.Read()) - { - list.Add(reader.GetGuid(0)); - } - - if (reader.NextResult() && reader.Read()) - { - count = reader.GetInt32(0); - } + count = reader.GetInt32(0); } - - return new QueryResult() - { - Items = list.ToArray(), - TotalRecordCount = count - }; } + + return new QueryResult() + { + Items = list.ToArray(), + TotalRecordCount = count + }; } } @@ -2195,18 +2283,6 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.Parameters.Add(cmd, "@IsFolder", DbType.Boolean).Value = query.IsFolder; } - var excludeTypes = query.ExcludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); - if (excludeTypes.Length == 1) - { - whereClauses.Add("type<>@type"); - cmd.Parameters.Add(cmd, "@type", DbType.String).Value = excludeTypes[0]; - } - else if (excludeTypes.Length > 1) - { - var inClause = string.Join(",", excludeTypes.Select(i => "'" + i + "'").ToArray()); - whereClauses.Add(string.Format("type not in ({0})", inClause)); - } - var includeTypes = query.IncludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); if (includeTypes.Length == 1) { @@ -2219,6 +2295,18 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add(string.Format("type in ({0})", inClause)); } + var excludeTypes = query.ExcludeItemTypes.SelectMany(MapIncludeItemTypes).ToArray(); + if (excludeTypes.Length == 1) + { + whereClauses.Add("type<>@type"); + cmd.Parameters.Add(cmd, "@type", DbType.String).Value = excludeTypes[0]; + } + else if (excludeTypes.Length > 1) + { + var inClause = string.Join(",", excludeTypes.Select(i => "'" + i + "'").ToArray()); + whereClauses.Add(string.Format("type not in ({0})", inClause)); + } + if (query.ChannelIds.Length == 1) { whereClauses.Add("ChannelId=@ChannelId"); @@ -2921,88 +3009,77 @@ namespace MediaBrowser.Server.Implementations.Persistence private async Task UpdateInheritedTags(CancellationToken cancellationToken) { - using (var connection = await CreateConnection().ConfigureAwait(false)) + var newValues = new List>(); + + using (var cmd = _connection.CreateCommand()) { - var newValues = new List>(); + cmd.CommandText = "select Guid,InheritedTags,(select group_concat(Tags, '|') from TypedBaseItems where (guid=outer.guid) OR (guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid))) as NewInheritedTags from typedbaseitems as Outer where NewInheritedTags <> InheritedTags"; - using (var cmd = connection.CreateCommand()) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - cmd.CommandText = "select Guid,InheritedTags,(select group_concat(Tags, '|') from TypedBaseItems where (guid=outer.guid) OR (guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid))) as NewInheritedTags from typedbaseitems as Outer where NewInheritedTags <> InheritedTags"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + while (reader.Read()) { - while (reader.Read()) - { - var id = reader.GetGuid(0); - string value = reader.IsDBNull(2) ? null : reader.GetString(2); + var id = reader.GetGuid(0); + string value = reader.IsDBNull(2) ? null : reader.GetString(2); - newValues.Add(new Tuple(id, value)); - } + newValues.Add(new Tuple(id, value)); } } + } - Logger.Debug("UpdateInheritedTags - {0} rows", newValues.Count); - if (newValues.Count == 0) - { - return; - } - - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - using (var updateInheritedTagsCommand = connection.CreateCommand()) - { - updateInheritedTagsCommand.CommandText = "Update TypedBaseItems set InheritedTags=@InheritedTags where Guid=@Guid"; - updateInheritedTagsCommand.Parameters.Add(updateInheritedTagsCommand, "@Guid"); - updateInheritedTagsCommand.Parameters.Add(updateInheritedTagsCommand, "@InheritedTags"); + Logger.Debug("UpdateInheritedTags - {0} rows", newValues.Count); + if (newValues.Count == 0) + { + return; + } - if (newValues.Count > 1) - { - updateInheritedTagsCommand.Prepare(); - } + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - foreach (var item in newValues) - { - updateInheritedTagsCommand.GetParameter(0).Value = item.Item1; - updateInheritedTagsCommand.GetParameter(1).Value = item.Item2; + IDbTransaction transaction = null; - updateInheritedTagsCommand.Transaction = transaction; - updateInheritedTagsCommand.ExecuteNonQuery(); - } - } + try + { + transaction = _connection.BeginTransaction(); - transaction.Commit(); - } - catch (OperationCanceledException) + foreach (var item in newValues) { - if (transaction != null) - { - transaction.Rollback(); - } + _updateInheritedTagsCommand.GetParameter(0).Value = item.Item1; + _updateInheritedTagsCommand.GetParameter(1).Value = item.Item2; - throw; + _updateInheritedTagsCommand.Transaction = transaction; + _updateInheritedTagsCommand.ExecuteNonQuery(); } - catch (Exception e) + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) { - Logger.ErrorException("Error running query:", e); + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Error running query:", e); - throw; + if (transaction != null) + { + transaction.Rollback(); } - finally + + throw; + } + finally + { + if (transaction != null) { - if (transaction != null) - { - transaction.Dispose(); - } + transaction.Dispose(); } + + WriteLock.Release(); } } @@ -3010,82 +3087,75 @@ namespace MediaBrowser.Server.Implementations.Persistence { var newValues = new List>(); - using (var connection = await CreateConnection().ConfigureAwait(false)) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select Guid,InheritedParentalRatingValue,(select Max(ParentalRatingValue, (select COALESCE(MAX(ParentalRatingValue),0) from TypedBaseItems where guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid)))) as NewInheritedParentalRatingValue from typedbaseitems as Outer where InheritedParentalRatingValue <> NewInheritedParentalRatingValue"; + cmd.CommandText = "select Guid,InheritedParentalRatingValue,(select Max(ParentalRatingValue, (select COALESCE(MAX(ParentalRatingValue),0) from TypedBaseItems where guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid)))) as NewInheritedParentalRatingValue from typedbaseitems as Outer where InheritedParentalRatingValue <> NewInheritedParentalRatingValue"; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) { - while (reader.Read()) - { - var id = reader.GetGuid(0); - var newValue = reader.GetInt32(2); + var id = reader.GetGuid(0); + var newValue = reader.GetInt32(2); - newValues.Add(new Tuple(id, newValue)); - } + newValues.Add(new Tuple(id, newValue)); } } + } - Logger.Debug("UpdateInheritedParentalRatings - {0} rows", newValues.Count); - if (newValues.Count == 0) - { - return; - } + Logger.Debug("UpdateInheritedParentalRatings - {0} rows", newValues.Count); + if (newValues.Count == 0) + { + return; + } - using (var updateInheritedRatingCommand = connection.CreateCommand()) - { - updateInheritedRatingCommand.CommandText = "Update TypedBaseItems set InheritedParentalRatingValue=@InheritedParentalRatingValue where Guid=@Guid"; - updateInheritedRatingCommand.Parameters.Add(updateInheritedRatingCommand, "@Guid"); - updateInheritedRatingCommand.Parameters.Add(updateInheritedRatingCommand, "@InheritedParentalRatingValue"); - updateInheritedRatingCommand.Prepare(); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - IDbTransaction transaction = null; + IDbTransaction transaction = null; - try - { - transaction = connection.BeginTransaction(); + try + { + transaction = _connection.BeginTransaction(); - foreach (var item in newValues) - { - updateInheritedRatingCommand.GetParameter(0).Value = item.Item1; - updateInheritedRatingCommand.GetParameter(1).Value = item.Item2; + foreach (var item in newValues) + { + _updateInheritedRatingCommand.GetParameter(0).Value = item.Item1; + _updateInheritedRatingCommand.GetParameter(1).Value = item.Item2; - updateInheritedRatingCommand.Transaction = transaction; - updateInheritedRatingCommand.ExecuteNonQuery(); - } + _updateInheritedRatingCommand.Transaction = transaction; + _updateInheritedRatingCommand.ExecuteNonQuery(); + } - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - catch (Exception e) - { - Logger.ErrorException("Error running query:", e); + throw; + } + catch (Exception e) + { + Logger.ErrorException("Error running query:", e); - if (transaction != null) - { - transaction.Rollback(); - } + if (transaction != null) + { + transaction.Rollback(); + } - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - } + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); } + + WriteLock.Release(); } } @@ -3128,73 +3198,89 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var connection = await CreateConnection().ConfigureAwait(false)) + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try { - IDbTransaction transaction = null; + transaction = _connection.BeginTransaction(); - try - { - transaction = connection.BeginTransaction(); + // Delete people + _deletePeopleCommand.GetParameter(0).Value = id; + _deletePeopleCommand.Transaction = transaction; + _deletePeopleCommand.ExecuteNonQuery(); - // Delete people - DeletePeople(connection, transaction, id); - DeleteChapters(connection, transaction, id); - DeleteMediaStreams(connection, transaction, id); + // Delete chapters + _deleteChaptersCommand.GetParameter(0).Value = id; + _deleteChaptersCommand.Transaction = transaction; + _deleteChaptersCommand.ExecuteNonQuery(); - // Delete ancestors - DeleteAncestors(connection, transaction, id); + // Delete media streams + _deleteStreamsCommand.GetParameter(0).Value = id; + _deleteStreamsCommand.Transaction = transaction; + _deleteStreamsCommand.ExecuteNonQuery(); - // Delete user data keys - DeleteUserDataKeys(connection, transaction, id); + // Delete ancestors + _deleteAncestorsCommand.GetParameter(0).Value = id; + _deleteAncestorsCommand.Transaction = transaction; + _deleteAncestorsCommand.ExecuteNonQuery(); - // Delete item values - DeleteItemValues(connection, transaction, id); + // Delete user data keys + _deleteUserDataKeysCommand.GetParameter(0).Value = id; + _deleteUserDataKeysCommand.Transaction = transaction; + _deleteUserDataKeysCommand.ExecuteNonQuery(); - // Delete provider ids - DeleteProviderIds(connection, transaction, id); + // Delete item values + _deleteItemValuesCommand.GetParameter(0).Value = id; + _deleteItemValuesCommand.Transaction = transaction; + _deleteItemValuesCommand.ExecuteNonQuery(); - DeleteImages(connection, transaction, id); + // Delete provider ids + _deleteProviderIdsCommand.GetParameter(0).Value = id; + _deleteProviderIdsCommand.Transaction = transaction; + _deleteProviderIdsCommand.ExecuteNonQuery(); - // Delete the item - using (var deleteItemCommand = connection.CreateCommand()) - { - deleteItemCommand.CommandText = "delete from TypedBaseItems where guid=@Id"; - deleteItemCommand.Parameters.Add(deleteItemCommand, "@Id"); + // Delete images + _deleteImagesCommand.GetParameter(0).Value = id; + _deleteImagesCommand.Transaction = transaction; + _deleteImagesCommand.ExecuteNonQuery(); - deleteItemCommand.GetParameter(0).Value = id; - deleteItemCommand.Transaction = transaction; - deleteItemCommand.ExecuteNonQuery(); - } + // Delete the item + _deleteItemCommand.GetParameter(0).Value = id; + _deleteItemCommand.Transaction = transaction; + _deleteItemCommand.ExecuteNonQuery(); - transaction.Commit(); - } - catch (OperationCanceledException) + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; + transaction.Rollback(); } - catch (Exception e) - { - Logger.ErrorException("Failed to save children:", e); - if (transaction != null) - { - transaction.Rollback(); - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save children:", e); - throw; + if (transaction != null) + { + transaction.Rollback(); } - finally + + throw; + } + finally + { + if (transaction != null) { - if (transaction != null) - { - transaction.Dispose(); - } + transaction.Dispose(); } + + WriteLock.Release(); } } @@ -3207,33 +3293,30 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select Distinct Name from People"; + cmd.CommandText = "select Distinct Name from People"; - var whereClauses = GetPeopleWhereClauses(query, cmd); + var whereClauses = GetPeopleWhereClauses(query, cmd); - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } + if (whereClauses.Count > 0) + { + cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + } - cmd.CommandText += " order by ListOrder"; + cmd.CommandText += " order by ListOrder"; - var list = new List(); + var list = new List(); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) { - while (reader.Read()) - { - list.Add(reader.GetString(0)); - } + list.Add(reader.GetString(0)); } - - return list; } + + return list; } } @@ -3246,33 +3329,30 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select ItemId, Name, Role, PersonType, SortOrder from People"; + cmd.CommandText = "select ItemId, Name, Role, PersonType, SortOrder from People"; - var whereClauses = GetPeopleWhereClauses(query, cmd); + var whereClauses = GetPeopleWhereClauses(query, cmd); - if (whereClauses.Count > 0) - { - cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); - } + if (whereClauses.Count > 0) + { + cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray()); + } - cmd.CommandText += " order by ListOrder"; + cmd.CommandText += " order by ListOrder"; - var list = new List(); + var list = new List(); - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) { - while (reader.Read()) - { - list.Add(GetPerson(reader)); - } + list.Add(GetPerson(reader)); } - - return list; } + + return list; } } @@ -3326,21 +3406,7 @@ namespace MediaBrowser.Server.Implementations.Persistence return whereClauses; } - private void DeleteAncestors(IDbConnection connection, IDbTransaction transaction, Guid id) - { - using (var deleteAncestorsCommand = connection.CreateCommand()) - { - deleteAncestorsCommand.CommandText = "delete from AncestorIds where ItemId=@Id"; - deleteAncestorsCommand.Parameters.Add(deleteAncestorsCommand, "@Id"); - - deleteAncestorsCommand.GetParameter(0).Value = id; - deleteAncestorsCommand.Transaction = transaction; - - deleteAncestorsCommand.ExecuteNonQuery(); - } - } - - private void UpdateAncestors(Guid itemId, List ancestorIds, IDbConnection connection, IDbTransaction transaction) + private void UpdateAncestors(Guid itemId, List ancestorIds, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3355,33 +3421,20 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - DeleteAncestors(connection, transaction, itemId); + _deleteAncestorsCommand.GetParameter(0).Value = itemId; + _deleteAncestorsCommand.Transaction = transaction; - if (ancestorIds.Count > 0) - { - using (var saveAncestorCommand = connection.CreateCommand()) - { - saveAncestorCommand.CommandText = "insert into AncestorIds (ItemId, AncestorId, AncestorIdText) values (@ItemId, @AncestorId, @AncestorIdText)"; - saveAncestorCommand.Parameters.Add(saveAncestorCommand, "@ItemId"); - saveAncestorCommand.Parameters.Add(saveAncestorCommand, "@AncestorId"); - saveAncestorCommand.Parameters.Add(saveAncestorCommand, "@AncestorIdText"); - - if (ancestorIds.Count > 1) - { - saveAncestorCommand.Prepare(); - } + _deleteAncestorsCommand.ExecuteNonQuery(); - foreach (var ancestorId in ancestorIds) - { - saveAncestorCommand.GetParameter(0).Value = itemId; - saveAncestorCommand.GetParameter(1).Value = ancestorId; - saveAncestorCommand.GetParameter(2).Value = ancestorId.ToString("N"); + foreach (var ancestorId in ancestorIds) + { + _saveAncestorCommand.GetParameter(0).Value = itemId; + _saveAncestorCommand.GetParameter(1).Value = ancestorId; + _saveAncestorCommand.GetParameter(2).Value = ancestorId.ToString("N"); - saveAncestorCommand.Transaction = transaction; + _saveAncestorCommand.Transaction = transaction; - saveAncestorCommand.ExecuteNonQuery(); - } - } + _saveAncestorCommand.ExecuteNonQuery(); } } @@ -3409,20 +3462,7 @@ namespace MediaBrowser.Server.Implementations.Persistence return list; } - private void DeleteImages(IDbConnection connection, IDbTransaction transaction, Guid id) - { - using (var deleteImagesCommand = connection.CreateCommand()) - { - deleteImagesCommand.CommandText = "delete from Images where ItemId=@Id"; - deleteImagesCommand.Parameters.Add(deleteImagesCommand, "@Id"); - - deleteImagesCommand.GetParameter(0).Value = id; - deleteImagesCommand.Transaction = transaction; - deleteImagesCommand.ExecuteNonQuery(); - } - } - - private void UpdateImages(Guid itemId, List images, IDbConnection connection, IDbTransaction transaction) + private void UpdateImages(Guid itemId, List images, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3437,70 +3477,38 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - DeleteImages(connection, transaction, itemId); + _deleteImagesCommand.GetParameter(0).Value = itemId; + _deleteImagesCommand.Transaction = transaction; - if (images.Count > 0) - { - using (var saveImagesCommand = connection.CreateCommand()) - { - var index = 0; - - saveImagesCommand.CommandText = "insert into Images (ItemId, ImageType, Path, DateModified, IsPlaceHolder, SortOrder) values (@ItemId, @ImageType, @Path, @DateModified, @IsPlaceHolder, @SortOrder)"; - saveImagesCommand.Parameters.Add(saveImagesCommand, "@ItemId"); - saveImagesCommand.Parameters.Add(saveImagesCommand, "@ImageType"); - saveImagesCommand.Parameters.Add(saveImagesCommand, "@Path"); - saveImagesCommand.Parameters.Add(saveImagesCommand, "@DateModified"); - saveImagesCommand.Parameters.Add(saveImagesCommand, "@IsPlaceHolder"); - saveImagesCommand.Parameters.Add(saveImagesCommand, "@SortOrder"); + _deleteImagesCommand.ExecuteNonQuery(); - if (images.Count > 1) - { - saveImagesCommand.Prepare(); - } - - foreach (var image in images) - { - saveImagesCommand.GetParameter(0).Value = itemId; - saveImagesCommand.GetParameter(1).Value = image.Type; - saveImagesCommand.GetParameter(2).Value = image.Path; - - if (image.DateModified == default(DateTime)) - { - saveImagesCommand.GetParameter(3).Value = null; - } - else - { - saveImagesCommand.GetParameter(3).Value = image.DateModified; - } - - saveImagesCommand.GetParameter(4).Value = image.IsPlaceholder; - saveImagesCommand.GetParameter(5).Value = index; - - saveImagesCommand.Transaction = transaction; + var index = 0; + foreach (var image in images) + { + _saveImagesCommand.GetParameter(0).Value = itemId; + _saveImagesCommand.GetParameter(1).Value = image.Type; + _saveImagesCommand.GetParameter(2).Value = image.Path; - saveImagesCommand.ExecuteNonQuery(); - index++; - } + if (image.DateModified == default(DateTime)) + { + _saveImagesCommand.GetParameter(3).Value = null; + } + else + { + _saveImagesCommand.GetParameter(3).Value = image.DateModified; } - } - } - private void DeleteProviderIds(IDbConnection connection, IDbTransaction transaction, Guid itemId) - { - using (var deleteProviderIdsCommand = connection.CreateCommand()) - { - // provider ids - deleteProviderIdsCommand.CommandText = "delete from ProviderIds where ItemId=@Id"; - deleteProviderIdsCommand.Parameters.Add(deleteProviderIdsCommand, "@Id"); + _saveImagesCommand.GetParameter(4).Value = image.IsPlaceholder; + _saveImagesCommand.GetParameter(5).Value = index; - deleteProviderIdsCommand.GetParameter(0).Value = itemId; - deleteProviderIdsCommand.Transaction = transaction; + _saveImagesCommand.Transaction = transaction; - deleteProviderIdsCommand.ExecuteNonQuery(); + _saveImagesCommand.ExecuteNonQuery(); + index++; } } - private void UpdateProviderIds(Guid itemId, Dictionary values, IDbConnection connection, IDbTransaction transaction) + private void UpdateProviderIds(Guid itemId, Dictionary values, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3515,51 +3523,23 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - DeleteProviderIds(connection, transaction, itemId); - - if (values.Count > 0) - { - using (var saveProviderIdsCommand = connection.CreateCommand()) - { - saveProviderIdsCommand.CommandText = "insert into ProviderIds (ItemId, Name, Value) values (@ItemId, @Name, @Value)"; - saveProviderIdsCommand.Parameters.Add(saveProviderIdsCommand, "@ItemId"); - saveProviderIdsCommand.Parameters.Add(saveProviderIdsCommand, "@Name"); - saveProviderIdsCommand.Parameters.Add(saveProviderIdsCommand, "@Value"); - - if (values.Count > 1) - { - saveProviderIdsCommand.Prepare(); - } - - foreach (var pair in values) - { - saveProviderIdsCommand.GetParameter(0).Value = itemId; - saveProviderIdsCommand.GetParameter(1).Value = pair.Key; - saveProviderIdsCommand.GetParameter(2).Value = pair.Value; - saveProviderIdsCommand.Transaction = transaction; + _deleteProviderIdsCommand.GetParameter(0).Value = itemId; + _deleteProviderIdsCommand.Transaction = transaction; - saveProviderIdsCommand.ExecuteNonQuery(); - } - } - } - } + _deleteProviderIdsCommand.ExecuteNonQuery(); - private void DeleteItemValues(IDbConnection connection, IDbTransaction transaction, Guid itemId) - { - using (var deleteItemValuesCommand = connection.CreateCommand()) + foreach (var pair in values) { - deleteItemValuesCommand.CommandText = "delete from ItemValues where ItemId=@Id"; - deleteItemValuesCommand.Parameters.Add(deleteItemValuesCommand, "@Id"); - - // First delete - deleteItemValuesCommand.GetParameter(0).Value = itemId; - deleteItemValuesCommand.Transaction = transaction; + _saveProviderIdsCommand.GetParameter(0).Value = itemId; + _saveProviderIdsCommand.GetParameter(1).Value = pair.Key; + _saveProviderIdsCommand.GetParameter(2).Value = pair.Value; + _saveProviderIdsCommand.Transaction = transaction; - deleteItemValuesCommand.ExecuteNonQuery(); + _saveProviderIdsCommand.ExecuteNonQuery(); } } - private void UpdateItemValues(Guid itemId, List> values, IDbConnection connection, IDbTransaction transaction) + private void UpdateItemValues(Guid itemId, List> values, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3574,51 +3554,23 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - DeleteItemValues(connection, transaction, itemId); + _deleteItemValuesCommand.GetParameter(0).Value = itemId; + _deleteItemValuesCommand.Transaction = transaction; - if (values.Count > 0) - { - using (var saveItemValuesCommand = connection.CreateCommand()) - { - saveItemValuesCommand.CommandText = "insert into ItemValues (ItemId, Type, Value) values (@ItemId, @Type, @Value)"; - saveItemValuesCommand.Parameters.Add(saveItemValuesCommand, "@ItemId"); - saveItemValuesCommand.Parameters.Add(saveItemValuesCommand, "@Type"); - saveItemValuesCommand.Parameters.Add(saveItemValuesCommand, "@Value"); + _deleteItemValuesCommand.ExecuteNonQuery(); - if (values.Count > 1) - { - saveItemValuesCommand.Prepare(); - } - - foreach (var pair in values) - { - saveItemValuesCommand.GetParameter(0).Value = itemId; - saveItemValuesCommand.GetParameter(1).Value = pair.Item1; - saveItemValuesCommand.GetParameter(2).Value = pair.Item2; - saveItemValuesCommand.Transaction = transaction; - - saveItemValuesCommand.ExecuteNonQuery(); - } - } - } - } - - private void DeleteUserDataKeys(IDbConnection connection, IDbTransaction transaction, Guid itemId) - { - using (var deleteUserDataKeysCommand = connection.CreateCommand()) + foreach (var pair in values) { - // user data - deleteUserDataKeysCommand.CommandText = "delete from UserDataKeys where ItemId=@Id"; - deleteUserDataKeysCommand.Parameters.Add(deleteUserDataKeysCommand, "@Id"); - - deleteUserDataKeysCommand.GetParameter(0).Value = itemId; - deleteUserDataKeysCommand.Transaction = transaction; + _saveItemValuesCommand.GetParameter(0).Value = itemId; + _saveItemValuesCommand.GetParameter(1).Value = pair.Item1; + _saveItemValuesCommand.GetParameter(2).Value = pair.Item2; + _saveItemValuesCommand.Transaction = transaction; - deleteUserDataKeysCommand.ExecuteNonQuery(); + _saveItemValuesCommand.ExecuteNonQuery(); } } - private void UpdateUserDataKeys(Guid itemId, List keys, IDbConnection connection, IDbTransaction transaction) + private void UpdateUserDataKeys(Guid itemId, List keys, IDbTransaction transaction) { if (itemId == Guid.Empty) { @@ -3633,50 +3585,21 @@ namespace MediaBrowser.Server.Implementations.Persistence CheckDisposed(); // First delete - DeleteUserDataKeys(connection, transaction, itemId); + _deleteUserDataKeysCommand.GetParameter(0).Value = itemId; + _deleteUserDataKeysCommand.Transaction = transaction; + _deleteUserDataKeysCommand.ExecuteNonQuery(); var index = 0; - if (keys.Count > 0) + foreach (var key in keys) { - using (var saveUserDataKeysCommand = connection.CreateCommand()) - { - saveUserDataKeysCommand.CommandText = "insert into UserDataKeys (ItemId, UserDataKey, Priority) values (@ItemId, @UserDataKey, @Priority)"; - saveUserDataKeysCommand.Parameters.Add(saveUserDataKeysCommand, "@ItemId"); - saveUserDataKeysCommand.Parameters.Add(saveUserDataKeysCommand, "@UserDataKey"); - saveUserDataKeysCommand.Parameters.Add(saveUserDataKeysCommand, "@Priority"); - - if (keys.Count > 1) - { - saveUserDataKeysCommand.Prepare(); - } + _saveUserDataKeysCommand.GetParameter(0).Value = itemId; + _saveUserDataKeysCommand.GetParameter(1).Value = key; + _saveUserDataKeysCommand.GetParameter(2).Value = index; + index++; + _saveUserDataKeysCommand.Transaction = transaction; - foreach (var key in keys) - { - saveUserDataKeysCommand.GetParameter(0).Value = itemId; - saveUserDataKeysCommand.GetParameter(1).Value = key; - saveUserDataKeysCommand.GetParameter(2).Value = index; - index++; - saveUserDataKeysCommand.Transaction = transaction; - - saveUserDataKeysCommand.ExecuteNonQuery(); - } - } - } - } - - private void DeletePeople(IDbConnection connection, IDbTransaction transaction, Guid id) - { - using (var deletePeopleCommand = connection.CreateCommand()) - { - deletePeopleCommand.CommandText = "delete from People where ItemId=@Id"; - deletePeopleCommand.Parameters.Add(deletePeopleCommand, "@Id"); - - - deletePeopleCommand.GetParameter(0).Value = id; - deletePeopleCommand.Transaction = transaction; - - deletePeopleCommand.ExecuteNonQuery(); + _saveUserDataKeysCommand.ExecuteNonQuery(); } } @@ -3696,85 +3619,69 @@ namespace MediaBrowser.Server.Implementations.Persistence var cancellationToken = CancellationToken.None; - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - IDbTransaction transaction = null; + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - try - { - transaction = connection.BeginTransaction(); + IDbTransaction transaction = null; - // First delete - DeletePeople(connection, transaction, itemId); + try + { + transaction = _connection.BeginTransaction(); - var listIndex = 0; + // First delete + _deletePeopleCommand.GetParameter(0).Value = itemId; + _deletePeopleCommand.Transaction = transaction; - if (people.Count > 0) - { - using (var savePersonCommand = connection.CreateCommand()) - { - savePersonCommand.CommandText = "insert into People (ItemId, Name, Role, PersonType, SortOrder, ListOrder) values (@ItemId, @Name, @Role, @PersonType, @SortOrder, @ListOrder)"; - savePersonCommand.Parameters.Add(savePersonCommand, "@ItemId"); - savePersonCommand.Parameters.Add(savePersonCommand, "@Name"); - savePersonCommand.Parameters.Add(savePersonCommand, "@Role"); - savePersonCommand.Parameters.Add(savePersonCommand, "@PersonType"); - savePersonCommand.Parameters.Add(savePersonCommand, "@SortOrder"); - savePersonCommand.Parameters.Add(savePersonCommand, "@ListOrder"); - - if (people.Count > 1) - { - savePersonCommand.Prepare(); - } - - foreach (var person in people) - { - cancellationToken.ThrowIfCancellationRequested(); - - savePersonCommand.GetParameter(0).Value = itemId; - savePersonCommand.GetParameter(1).Value = person.Name; - savePersonCommand.GetParameter(2).Value = person.Role; - savePersonCommand.GetParameter(3).Value = person.Type; - savePersonCommand.GetParameter(4).Value = person.SortOrder; - savePersonCommand.GetParameter(5).Value = listIndex; - - savePersonCommand.Transaction = transaction; - - savePersonCommand.ExecuteNonQuery(); - listIndex++; - } - } - } + _deletePeopleCommand.ExecuteNonQuery(); - transaction.Commit(); + var listIndex = 0; - } - catch (OperationCanceledException) + foreach (var person in people) { - if (transaction != null) - { - transaction.Rollback(); - } + cancellationToken.ThrowIfCancellationRequested(); + + _savePersonCommand.GetParameter(0).Value = itemId; + _savePersonCommand.GetParameter(1).Value = person.Name; + _savePersonCommand.GetParameter(2).Value = person.Role; + _savePersonCommand.GetParameter(3).Value = person.Type; + _savePersonCommand.GetParameter(4).Value = person.SortOrder; + _savePersonCommand.GetParameter(5).Value = listIndex; - throw; + _savePersonCommand.Transaction = transaction; + + _savePersonCommand.ExecuteNonQuery(); + listIndex++; } - catch (Exception e) + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) { - Logger.ErrorException("Failed to save people:", e); + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save people:", e); - throw; + if (transaction != null) + { + transaction.Rollback(); } - finally + + throw; + } + finally + { + if (transaction != null) { - if (transaction != null) - { - transaction.Dispose(); - } + transaction.Dispose(); } + + WriteLock.Release(); } } @@ -3814,58 +3721,39 @@ namespace MediaBrowser.Server.Implementations.Persistence var list = new List(); - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - var cmdText = "select " + string.Join(",", _mediaStreamSaveColumns) + " from mediastreams where"; + var cmdText = "select " + string.Join(",", _mediaStreamSaveColumns) + " from mediastreams where"; - cmdText += " ItemId=@ItemId"; - cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = query.ItemId; + cmdText += " ItemId=@ItemId"; + cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = query.ItemId; - if (query.Type.HasValue) - { - cmdText += " AND StreamType=@StreamType"; - cmd.Parameters.Add(cmd, "@StreamType", DbType.String).Value = query.Type.Value.ToString(); - } + if (query.Type.HasValue) + { + cmdText += " AND StreamType=@StreamType"; + cmd.Parameters.Add(cmd, "@StreamType", DbType.String).Value = query.Type.Value.ToString(); + } - if (query.Index.HasValue) - { - cmdText += " AND StreamIndex=@StreamIndex"; - cmd.Parameters.Add(cmd, "@StreamIndex", DbType.Int32).Value = query.Index.Value; - } + if (query.Index.HasValue) + { + cmdText += " AND StreamIndex=@StreamIndex"; + cmd.Parameters.Add(cmd, "@StreamIndex", DbType.Int32).Value = query.Index.Value; + } - cmdText += " order by StreamIndex ASC"; + cmdText += " order by StreamIndex ASC"; - cmd.CommandText = cmdText; + cmd.CommandText = cmdText; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) { - while (reader.Read()) - { - list.Add(GetMediaStream(reader)); - } + list.Add(GetMediaStream(reader)); } } - - return list; } - } - - private void DeleteMediaStreams(IDbConnection connection, IDbTransaction transaction, Guid id) - { - using (var deleteStreamsCommand = connection.CreateCommand()) - { - // MediaStreams - deleteStreamsCommand.CommandText = "delete from mediastreams where ItemId=@ItemId"; - deleteStreamsCommand.Parameters.Add(deleteStreamsCommand, "@ItemId"); - - deleteStreamsCommand.GetParameter(0).Value = id; - - deleteStreamsCommand.Transaction = transaction; - deleteStreamsCommand.ExecuteNonQuery(); - } + return list; } public async Task SaveMediaStreams(Guid id, List streams, CancellationToken cancellationToken) @@ -3884,115 +3772,100 @@ namespace MediaBrowser.Server.Implementations.Persistence cancellationToken.ThrowIfCancellationRequested(); - using (var connection = await CreateConnection().ConfigureAwait(false)) + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try { - IDbTransaction transaction = null; + transaction = _connection.BeginTransaction(); - try - { - transaction = connection.BeginTransaction(); + // First delete chapters + _deleteStreamsCommand.GetParameter(0).Value = id; - // First delete - DeleteMediaStreams(connection, transaction, id); + _deleteStreamsCommand.Transaction = transaction; - if (streams.Count > 0) - { - using (var saveStreamCommand = connection.CreateCommand()) - { - saveStreamCommand.CommandText = string.Format("replace into mediastreams ({0}) values ({1})", - string.Join(",", _mediaStreamSaveColumns), - string.Join(",", _mediaStreamSaveColumns.Select(i => "@" + i).ToArray())); - - foreach (var col in _mediaStreamSaveColumns) - { - saveStreamCommand.Parameters.Add(saveStreamCommand, "@" + col); - } - - if (streams.Count > 1) - { - saveStreamCommand.Prepare(); - } - - foreach (var stream in streams) - { - cancellationToken.ThrowIfCancellationRequested(); - - var index = 0; - - saveStreamCommand.GetParameter(index++).Value = id; - saveStreamCommand.GetParameter(index++).Value = stream.Index; - saveStreamCommand.GetParameter(index++).Value = stream.Type.ToString(); - saveStreamCommand.GetParameter(index++).Value = stream.Codec; - saveStreamCommand.GetParameter(index++).Value = stream.Language; - saveStreamCommand.GetParameter(index++).Value = stream.ChannelLayout; - saveStreamCommand.GetParameter(index++).Value = stream.Profile; - saveStreamCommand.GetParameter(index++).Value = stream.AspectRatio; - saveStreamCommand.GetParameter(index++).Value = stream.Path; - - saveStreamCommand.GetParameter(index++).Value = stream.IsInterlaced; - - saveStreamCommand.GetParameter(index++).Value = stream.BitRate; - saveStreamCommand.GetParameter(index++).Value = stream.Channels; - saveStreamCommand.GetParameter(index++).Value = stream.SampleRate; - - saveStreamCommand.GetParameter(index++).Value = stream.IsDefault; - saveStreamCommand.GetParameter(index++).Value = stream.IsForced; - saveStreamCommand.GetParameter(index++).Value = stream.IsExternal; - - saveStreamCommand.GetParameter(index++).Value = stream.Width; - saveStreamCommand.GetParameter(index++).Value = stream.Height; - saveStreamCommand.GetParameter(index++).Value = stream.AverageFrameRate; - saveStreamCommand.GetParameter(index++).Value = stream.RealFrameRate; - saveStreamCommand.GetParameter(index++).Value = stream.Level; - saveStreamCommand.GetParameter(index++).Value = stream.PixelFormat; - saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; - saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; - saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; - - saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; - saveStreamCommand.GetParameter(index++).Value = stream.Comment; - saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; - saveStreamCommand.GetParameter(index++).Value = stream.IsAVC; - saveStreamCommand.GetParameter(index++).Value = stream.Title; - - saveStreamCommand.GetParameter(index++).Value = stream.TimeBase; - saveStreamCommand.GetParameter(index++).Value = stream.CodecTimeBase; - - saveStreamCommand.Transaction = transaction; - saveStreamCommand.ExecuteNonQuery(); - } - } - } + _deleteStreamsCommand.ExecuteNonQuery(); - transaction.Commit(); - } - catch (OperationCanceledException) + foreach (var stream in streams) { - if (transaction != null) - { - transaction.Rollback(); - } + cancellationToken.ThrowIfCancellationRequested(); + + var index = 0; + + _saveStreamCommand.GetParameter(index++).Value = id; + _saveStreamCommand.GetParameter(index++).Value = stream.Index; + _saveStreamCommand.GetParameter(index++).Value = stream.Type.ToString(); + _saveStreamCommand.GetParameter(index++).Value = stream.Codec; + _saveStreamCommand.GetParameter(index++).Value = stream.Language; + _saveStreamCommand.GetParameter(index++).Value = stream.ChannelLayout; + _saveStreamCommand.GetParameter(index++).Value = stream.Profile; + _saveStreamCommand.GetParameter(index++).Value = stream.AspectRatio; + _saveStreamCommand.GetParameter(index++).Value = stream.Path; - throw; + _saveStreamCommand.GetParameter(index++).Value = stream.IsInterlaced; + + _saveStreamCommand.GetParameter(index++).Value = stream.BitRate; + _saveStreamCommand.GetParameter(index++).Value = stream.Channels; + _saveStreamCommand.GetParameter(index++).Value = stream.SampleRate; + + _saveStreamCommand.GetParameter(index++).Value = stream.IsDefault; + _saveStreamCommand.GetParameter(index++).Value = stream.IsForced; + _saveStreamCommand.GetParameter(index++).Value = stream.IsExternal; + + _saveStreamCommand.GetParameter(index++).Value = stream.Width; + _saveStreamCommand.GetParameter(index++).Value = stream.Height; + _saveStreamCommand.GetParameter(index++).Value = stream.AverageFrameRate; + _saveStreamCommand.GetParameter(index++).Value = stream.RealFrameRate; + _saveStreamCommand.GetParameter(index++).Value = stream.Level; + _saveStreamCommand.GetParameter(index++).Value = stream.PixelFormat; + _saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; + _saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; + _saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; + + _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; + _saveStreamCommand.GetParameter(index++).Value = stream.Comment; + _saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; + _saveStreamCommand.GetParameter(index++).Value = stream.IsAVC; + _saveStreamCommand.GetParameter(index++).Value = stream.Title; + + _saveStreamCommand.GetParameter(index++).Value = stream.TimeBase; + _saveStreamCommand.GetParameter(index++).Value = stream.CodecTimeBase; + + _saveStreamCommand.Transaction = transaction; + _saveStreamCommand.ExecuteNonQuery(); } - catch (Exception e) + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) { - Logger.ErrorException("Failed to save media streams:", e); + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save media streams:", e); - throw; + if (transaction != null) + { + transaction.Rollback(); } - finally + + throw; + } + finally + { + if (transaction != null) { - if (transaction != null) - { - transaction.Dispose(); - } + transaction.Dispose(); } + + WriteLock.Release(); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index da0f584d53..6edacba535 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -15,11 +15,18 @@ namespace MediaBrowser.Server.Implementations.Persistence { public class SqliteUserDataRepository : BaseSqliteRepository, IUserDataRepository { + private IDbConnection _connection; + public SqliteUserDataRepository(ILogManager logManager, IApplicationPaths appPaths, IDbConnector connector) : base(logManager, connector) { DbFilePath = Path.Combine(appPaths.DataPath, "userdata_v2.db"); } + protected override bool EnableConnectionPooling + { + get { return false; } + } + /// /// Gets the name of the repository /// @@ -36,23 +43,27 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize(IDbConnector dbConnector) + public async Task Initialize() { - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - string[] queries = { + _connection = await CreateConnection(false).ConfigureAwait(false); + + string[] queries = { "create table if not exists userdata (key nvarchar, userId GUID, rating float null, played bit, playCount int, isFavorite bit, playbackPositionTicks bigint, lastPlayedDate datetime null)", "create index if not exists idx_userdata on userdata(key)", - "create unique index if not exists userdataindex on userdata (key, userId)" + "create unique index if not exists userdataindex on userdata (key, userId)", + + //pragmas + "pragma temp_store = memory", + + "pragma shrink_memory" }; - connection.RunQueries(queries, Logger); + _connection.RunQueries(queries, Logger); - connection.AddColumn(Logger, "userdata", "AudioStreamIndex", "int"); - connection.AddColumn(Logger, "userdata", "SubtitleStreamIndex", "int"); - } + _connection.AddColumn(Logger, "userdata", "AudioStreamIndex", "int"); + _connection.AddColumn(Logger, "userdata", "SubtitleStreamIndex", "int"); } /// @@ -114,63 +125,64 @@ namespace MediaBrowser.Server.Implementations.Persistence { cancellationToken.ThrowIfCancellationRequested(); - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - IDbTransaction transaction = null; - - try - { - transaction = connection.BeginTransaction(); - - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; - - cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userData.Rating; - cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userData.Played; - cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userData.PlayCount; - cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userData.IsFavorite; - cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userData.PlaybackPositionTicks; - cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userData.LastPlayedDate; - cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userData.AudioStreamIndex; - cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userData.SubtitleStreamIndex; + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - cmd.Transaction = transaction; + IDbTransaction transaction = null; - cmd.ExecuteNonQuery(); - } + try + { + transaction = _connection.BeginTransaction(); - transaction.Commit(); - } - catch (OperationCanceledException) + using (var cmd = _connection.CreateCommand()) { - if (transaction != null) - { - transaction.Rollback(); - } + cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; - throw; + cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userData.Rating; + cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userData.Played; + cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userData.PlayCount; + cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userData.IsFavorite; + cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userData.PlaybackPositionTicks; + cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userData.LastPlayedDate; + cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userData.AudioStreamIndex; + cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userData.SubtitleStreamIndex; + + cmd.Transaction = transaction; + + cmd.ExecuteNonQuery(); } - catch (Exception e) + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) { - Logger.ErrorException("Failed to save user data:", e); + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save user data:", e); - throw; + if (transaction != null) + { + transaction.Rollback(); } - finally + + throw; + } + finally + { + if (transaction != null) { - if (transaction != null) - { - transaction.Dispose(); - } + transaction.Dispose(); } + + WriteLock.Release(); } } @@ -185,68 +197,69 @@ namespace MediaBrowser.Server.Implementations.Persistence { cancellationToken.ThrowIfCancellationRequested(); - using (var connection = await CreateConnection().ConfigureAwait(false)) - { - IDbTransaction transaction = null; + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); - try - { - transaction = connection.BeginTransaction(); + IDbTransaction transaction = null; - foreach (var userItemData in userData) - { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; - - cmd.Parameters.Add(cmd, "@key", DbType.String).Value = userItemData.Key; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userItemData.Rating; - cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userItemData.Played; - cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userItemData.PlayCount; - cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userItemData.IsFavorite; - cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userItemData.PlaybackPositionTicks; - cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userItemData.LastPlayedDate; - cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userItemData.AudioStreamIndex; - cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userItemData.SubtitleStreamIndex; - - cmd.Transaction = transaction; - - cmd.ExecuteNonQuery(); - } - - cancellationToken.ThrowIfCancellationRequested(); - } + try + { + transaction = _connection.BeginTransaction(); - transaction.Commit(); - } - catch (OperationCanceledException) + foreach (var userItemData in userData) { - if (transaction != null) + using (var cmd = _connection.CreateCommand()) { - transaction.Rollback(); + cmd.CommandText = "replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"; + + cmd.Parameters.Add(cmd, "@key", DbType.String).Value = userItemData.Key; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@rating", DbType.Double).Value = userItemData.Rating; + cmd.Parameters.Add(cmd, "@played", DbType.Boolean).Value = userItemData.Played; + cmd.Parameters.Add(cmd, "@playCount", DbType.Int32).Value = userItemData.PlayCount; + cmd.Parameters.Add(cmd, "@isFavorite", DbType.Boolean).Value = userItemData.IsFavorite; + cmd.Parameters.Add(cmd, "@playbackPositionTicks", DbType.Int64).Value = userItemData.PlaybackPositionTicks; + cmd.Parameters.Add(cmd, "@lastPlayedDate", DbType.DateTime).Value = userItemData.LastPlayedDate; + cmd.Parameters.Add(cmd, "@AudioStreamIndex", DbType.Int32).Value = userItemData.AudioStreamIndex; + cmd.Parameters.Add(cmd, "@SubtitleStreamIndex", DbType.Int32).Value = userItemData.SubtitleStreamIndex; + + cmd.Transaction = transaction; + + cmd.ExecuteNonQuery(); } - throw; + cancellationToken.ThrowIfCancellationRequested(); } - catch (Exception e) + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) { - Logger.ErrorException("Failed to save user data:", e); + transaction.Rollback(); + } - if (transaction != null) - { - transaction.Rollback(); - } + throw; + } + catch (Exception e) + { + Logger.ErrorException("Failed to save user data:", e); - throw; + if (transaction != null) + { + transaction.Rollback(); } - finally + + throw; + } + finally + { + if (transaction != null) { - if (transaction != null) - { - transaction.Dispose(); - } + transaction.Dispose(); } + + WriteLock.Release(); } } @@ -272,25 +285,22 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("key"); } - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where key = @key and userId=@userId"; + cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where key = @key and userId=@userId"; - cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@key", DbType.String).Value = key; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + { + if (reader.Read()) { - if (reader.Read()) - { - return ReadRow(reader); - } + return ReadRow(reader); } - - return null; } + + return null; } } @@ -305,41 +315,38 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("keys"); } - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) + var index = 0; + var excludeIds = new List(); + var builder = new StringBuilder(); + foreach (var key in keys) { - var index = 0; - var excludeIds = new List(); - var builder = new StringBuilder(); - foreach (var key in keys) - { - var paramName = "@Key" + index; - excludeIds.Add("Key =" + paramName); - cmd.Parameters.Add(cmd, paramName, DbType.String).Value = key; - builder.Append(" WHEN Key=" + paramName + " THEN " + index); - index++; - } + var paramName = "@Key" + index; + excludeIds.Add("Key =" + paramName); + cmd.Parameters.Add(cmd, paramName, DbType.String).Value = key; + builder.Append(" WHEN Key=" + paramName + " THEN " + index); + index++; + } - var keyText = string.Join(" OR ", excludeIds.ToArray()); + var keyText = string.Join(" OR ", excludeIds.ToArray()); - cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId AND (" + keyText + ") "; + cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId AND (" + keyText + ") "; - cmd.CommandText += " ORDER BY (Case " + builder + " Else " + keys.Count.ToString(CultureInfo.InvariantCulture) + " End )"; - cmd.CommandText += " LIMIT 1"; + cmd.CommandText += " ORDER BY (Case " + builder + " Else " + keys.Count.ToString(CultureInfo.InvariantCulture) + " End )"; + cmd.CommandText += " LIMIT 1"; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow)) + { + if (reader.Read()) { - if (reader.Read()) - { - return ReadRow(reader); - } + return ReadRow(reader); } - - return null; } + + return null; } } @@ -355,27 +362,20 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("userId"); } - var list = new List(); - - using (var connection = CreateConnection(true).Result) + using (var cmd = _connection.CreateCommand()) { - using (var cmd = connection.CreateCommand()) - { - cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId"; + cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId"; - cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; + cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId; - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) { - while (reader.Read()) - { - list.Add(ReadRow(reader)); - } + yield return ReadRow(reader); } } } - - return list; } /// @@ -416,5 +416,19 @@ namespace MediaBrowser.Server.Implementations.Persistence return userData; } + + protected override void CloseConnection() + { + if (_connection != null) + { + if (_connection.IsOpen()) + { + _connection.Close(); + } + + _connection.Dispose(); + _connection = null; + } + } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index b0cf93673c..e7f5c071c7 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -573,7 +573,7 @@ namespace MediaBrowser.Server.Startup.Common await displayPreferencesRepo.Initialize().ConfigureAwait(false); await ConfigureUserDataRepositories().ConfigureAwait(false); - await itemRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); + await itemRepo.Initialize().ConfigureAwait(false); ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; await ConfigureNotificationsRepository().ConfigureAwait(false); progress.Report(100); @@ -746,7 +746,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteUserDataRepository(LogManager, ApplicationPaths, NativeApp.GetDbConnector()); - await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); + await repo.Initialize().ConfigureAwait(false); ((UserDataManager)UserDataManager).Repository = repo; } -- cgit v1.2.3 From 5f1bf17030853886feebfab97e7155571ea07a97 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 14 Jun 2016 00:15:13 -0400 Subject: update forms --- MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index b1206c297a..40cac82c32 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -33,7 +33,9 @@ namespace MediaBrowser.Server.Implementations.Persistence SyncMode = SynchronizationModes.Normal, DataSource = dbPath, JournalMode = SQLiteJournalModeEnum.Wal, - Pooling = enablePooling, + + // This is causing crashing under linux + Pooling = Environment.OSVersion.Platform == PlatformID.Win32NT, ReadOnly = isReadOnly }; -- cgit v1.2.3 From 66c86ccc58d1022bdb65d63b47df82845ad921c7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 14 Jun 2016 15:21:26 -0400 Subject: update pooling --- .../HttpServer/LoggerUtils.cs | 2 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 6 +- .../Persistence/SqliteExtensions.cs | 2 +- .../TV/TVSeriesManager.cs | 101 ++++++++++++--------- 4 files changed, 67 insertions(+), 44 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs index ce81000254..bfbb228edf 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration) { var durationMs = duration.TotalMilliseconds; - var logSuffix = durationMs >= 1000 ? "ms (slow)" : "ms"; + var logSuffix = durationMs >= 1000 && durationMs < 60000 ? "ms (slow)" : "ms"; logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 1628ddc019..07affb865c 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -45,6 +45,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings private async Task GetXml(string path, CancellationToken cancellationToken) { + _logger.Info("xmltv path: {0}", path); + if (!path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { return path; @@ -161,7 +163,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings { Id = c.Id, Name = c.DisplayName, - ImageUrl = c.Icon != null && !String.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null + ImageUrl = c.Icon != null && !String.IsNullOrEmpty(c.Icon.Source) ? c.Icon.Source : null, + Number = c.Id + }).ToList(); } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index 40cac82c32..73b3a22531 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.Persistence JournalMode = SQLiteJournalModeEnum.Wal, // This is causing crashing under linux - Pooling = Environment.OSVersion.Platform == PlatformID.Win32NT, + Pooling = enablePooling && Environment.OSVersion.Platform == PlatformID.Win32NT, ReadOnly = isReadOnly }; diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs index d57aea08e2..4aff3b6ef3 100644 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs @@ -124,58 +124,77 @@ namespace MediaBrowser.Server.Implementations.TV /// Task{Episode}. private Tuple GetNextUp(Series series, User user) { - // Get them in display order, then reverse - var allEpisodes = series.GetEpisodes(user, false, false) - .Where(i => !i.ParentIndexNumber.HasValue || i.ParentIndexNumber.Value != 0) - .Reverse() - .ToList(); - - Episode lastWatched = null; - var lastWatchedDate = DateTime.MinValue; - Episode nextUp = null; - - var unplayedEpisodes = new List(); - - // Go back starting with the most recent episodes - foreach (var episode in allEpisodes) + var firstUnwatchedEpisode = _libraryManager.GetItemList(new InternalItemsQuery(user) { - var userData = _userDataManager.GetUserData(user, episode); - - if (userData.Played) - { - if (lastWatched != null || nextUp == null) - { - break; - } - - lastWatched = episode; - lastWatchedDate = userData.LastPlayedDate ?? DateTime.MinValue; - } - else - { - unplayedEpisodes.Add(episode); + AncestorWithPresentationUniqueKey = series.PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Episode).Name }, + SortBy = new[] { ItemSortBy.SortName }, + SortOrder = SortOrder.Ascending, + Limit = 1, + IsPlayed = false, + IsVirtualItem = false - nextUp = episode; - } - } + }).Cast().FirstOrDefault(); - if (lastWatched != null) + if (firstUnwatchedEpisode == null) { - return new Tuple(nextUp, lastWatchedDate, false); + return new Tuple(null, DateTime.MinValue, true); } - Episode firstEpisode = null; - // Find the first unplayed episode. Start from the back of the list since they're in reverse order - for (var i = unplayedEpisodes.Count - 1; i >= 0; i--) + var lastWatchedEpisode = _libraryManager.GetItemList(new InternalItemsQuery(user) { - var unplayedEpisode = unplayedEpisodes[i]; + AncestorWithPresentationUniqueKey = series.PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Episode).Name }, + SortBy = new[] { ItemSortBy.DatePlayed }, + SortOrder = SortOrder.Descending, + Limit = 1, + IsVirtualItem = false + + }).FirstOrDefault(); + + //// Get them in display order, then reverse + //var allEpisodes = series.GetEpisodes(user, false, false) + // .Where(i => !i.ParentIndexNumber.HasValue || i.ParentIndexNumber.Value != 0) + // .Reverse() + // .ToList(); + + //Episode lastWatched = null; + //var lastWatchedDate = DateTime.MinValue; + //Episode nextUp = null; + + //// Go back starting with the most recent episodes + //foreach (var episode in allEpisodes) + //{ + // var userData = _userDataManager.GetUserData(user, episode); + + // if (userData.Played) + // { + // if (lastWatched != null || nextUp == null) + // { + // break; + // } + + // lastWatched = episode; + // lastWatchedDate = userData.LastPlayedDate ?? DateTime.MinValue; + // } + // else + // { + // nextUp = episode; + // } + //} + + if (lastWatchedEpisode != null) + { + var userData = _userDataManager.GetUserData(user, lastWatchedEpisode); - firstEpisode = unplayedEpisode; - break; + if (userData.LastPlayedDate.HasValue) + { + return new Tuple(firstUnwatchedEpisode, userData.LastPlayedDate.Value, false); + } } // Return the first episode - return new Tuple(firstEpisode, DateTime.MinValue, true); + return new Tuple(firstUnwatchedEpisode, DateTime.MinValue, true); } private QueryResult GetResult(IEnumerable items, int? totalRecordLimit, NextUpQuery query) -- cgit v1.2.3 From 2f39ad1673671c7f81b0e4948f37ae35b029ca0f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 14 Jun 2016 22:15:51 -0400 Subject: encapsulate order by --- .../Persistence/SqliteItemRepository.cs | 73 +++++++++++++--------- 1 file changed, 45 insertions(+), 28 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 4e851053b1..ed429286f2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1694,6 +1694,33 @@ namespace MediaBrowser.Server.Implementations.Persistence return " left join UserDataDb.UserData on (select UserDataKey from UserDataKeys where ItemId=Guid order by Priority LIMIT 1)=UserDataDb.UserData.Key"; } + private string GetGroupBy(InternalItemsQuery query) + { + var groups = new List(); + + if (!string.IsNullOrWhiteSpace(query.GroupByAncestorOfType)) + { + groups.Add("(Select PresentationUniqueKey from TypedBaseItems B where B.Type = 'MediaBrowser.Controller.Entities.TV.Series' And B.Guid in (Select AncestorId from AncestorIds where ItemId=A.Guid))"); + } + + if (EnableGroupByPresentationUniqueKey(query)) + { + groups.Add("PresentationUniqueKey"); + } + + if (groups.Count > 0) + { + return " Group by " + string.Join(",", groups.ToArray()); + } + + return string.Empty; + } + + private string GetFromText() + { + return " from TypedBaseItems A"; + } + public IEnumerable GetItemList(InternalItemsQuery query) { if (query == null) @@ -1707,7 +1734,7 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + GetFromText(); cmd.CommandText += GetJoinUserDataText(query); if (EnableJoinUserData(query)) @@ -1723,10 +1750,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + cmd.CommandText += GetGroupBy(query); cmd.CommandText += GetOrderByText(query); @@ -1797,7 +1821,7 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + " from TypedBaseItems"; + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, _retriveItemColumns, cmd)) + GetFromText(); cmd.CommandText += GetJoinUserDataText(query); if (EnableJoinUserData(query)) @@ -1817,10 +1841,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + cmd.CommandText += GetGroupBy(query); cmd.CommandText += GetOrderByText(query); @@ -1838,11 +1859,11 @@ namespace MediaBrowser.Server.Implementations.Persistence if (EnableGroupByPresentationUniqueKey(query)) { - cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; + cmd.CommandText += "; select count (distinct PresentationUniqueKey)" + GetFromText(); } else { - cmd.CommandText += "; select count (guid) from TypedBaseItems"; + cmd.CommandText += "; select count (guid)" + GetFromText(); } cmd.CommandText += GetJoinUserDataText(query); @@ -1994,7 +2015,7 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + GetFromText(); cmd.CommandText += GetJoinUserDataText(query); if (EnableJoinUserData(query)) @@ -2010,10 +2031,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + cmd.CommandText += GetGroupBy(query); cmd.CommandText += GetOrderByText(query); @@ -2070,10 +2088,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + cmd.CommandText += GetGroupBy(query); cmd.CommandText += GetOrderByText(query); @@ -2137,7 +2152,7 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var cmd = _connection.CreateCommand()) { - cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + " from TypedBaseItems"; + cmd.CommandText = "select " + string.Join(",", GetFinalColumnsToSelect(query, new[] { "guid" }, cmd)) + GetFromText(); var whereClauses = GetWhereClauses(query, cmd); cmd.CommandText += GetJoinUserDataText(query); @@ -2153,10 +2168,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cmd.CommandText += whereText; - if (EnableGroupByPresentationUniqueKey(query)) - { - cmd.CommandText += " Group by PresentationUniqueKey"; - } + cmd.CommandText += GetGroupBy(query); cmd.CommandText += GetOrderByText(query); @@ -2174,11 +2186,11 @@ namespace MediaBrowser.Server.Implementations.Persistence if (EnableGroupByPresentationUniqueKey(query)) { - cmd.CommandText += "; select count (distinct PresentationUniqueKey) from TypedBaseItems"; + cmd.CommandText += "; select count (distinct PresentationUniqueKey)" + GetFromText(); } else { - cmd.CommandText += "; select count (guid) from TypedBaseItems"; + cmd.CommandText += "; select count (guid)" + GetFromText(); } cmd.CommandText += GetJoinUserDataText(query); @@ -2370,6 +2382,11 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add("ParentIndexNumber=@ParentIndexNumber"); cmd.Parameters.Add(cmd, "@ParentIndexNumber", DbType.Int32).Value = query.ParentIndexNumber.Value; } + if (query.ParentIndexNumberNotEquals.HasValue) + { + whereClauses.Add("(ParentIndexNumber<>@ParentIndexNumber or ParentIndexNumber is null)"); + cmd.Parameters.Add(cmd, "@ParentIndexNumber", DbType.Int32).Value = query.ParentIndexNumberNotEquals.Value; + } if (query.MinEndDate.HasValue) { whereClauses.Add("EndDate>=@MinEndDate"); -- cgit v1.2.3 From 7dd2b1592cd9bef7379f3cc14e24de610daf2eeb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 14 Jun 2016 22:18:19 -0400 Subject: add index number filter --- MediaBrowser.Controller/Entities/InternalItemsQuery.cs | 3 ++- .../Persistence/SqliteItemRepository.cs | 8 ++++---- MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs | 6 ++++-- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 5b9d94fc26..d50f5b5255 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -110,6 +110,7 @@ namespace MediaBrowser.Controller.Entities internal List ItemIdsFromPersonFilters { get; set; } public int? ParentIndexNumber { get; set; } + public int? ParentIndexNumberNotEquals { get; set; } public int? IndexNumber { get; set; } public int? MinParentalRating { get; set; } public int? MaxParentalRating { get; set; } @@ -141,7 +142,7 @@ namespace MediaBrowser.Controller.Entities public bool GroupByPresentationUniqueKey { get; set; } public bool EnableTotalRecordCount { get; set; } public bool ForceDirect { get; set; } - public Dictionary ExcludeProviderIds { get; set; } + public Dictionary ExcludeProviderIds { get; set; } public InternalItemsQuery() { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index ed429286f2..d04dc57283 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1698,10 +1698,10 @@ namespace MediaBrowser.Server.Implementations.Persistence { var groups = new List(); - if (!string.IsNullOrWhiteSpace(query.GroupByAncestorOfType)) - { - groups.Add("(Select PresentationUniqueKey from TypedBaseItems B where B.Type = 'MediaBrowser.Controller.Entities.TV.Series' And B.Guid in (Select AncestorId from AncestorIds where ItemId=A.Guid))"); - } + //if (!string.IsNullOrWhiteSpace(query.GroupByAncestorOfType)) + //{ + // groups.Add("(Select PresentationUniqueKey from TypedBaseItems B where B.Type = 'MediaBrowser.Controller.Entities.TV.Series' And B.Guid in (Select AncestorId from AncestorIds where ItemId=A.Guid))"); + //} if (EnableGroupByPresentationUniqueKey(query)) { diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs index abef5db598..82232ffae0 100644 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs @@ -132,7 +132,8 @@ namespace MediaBrowser.Server.Implementations.TV SortOrder = SortOrder.Ascending, Limit = 1, IsPlayed = false, - IsVirtualItem = false + IsVirtualItem = false, + ParentIndexNumberNotEquals = 0 }).Cast().FirstOrDefault(); @@ -149,7 +150,8 @@ namespace MediaBrowser.Server.Implementations.TV SortBy = new[] { ItemSortBy.DatePlayed }, SortOrder = SortOrder.Descending, Limit = 1, - IsVirtualItem = false + IsVirtualItem = false, + ParentIndexNumberNotEquals = 0 }).FirstOrDefault(); -- cgit v1.2.3 From 80863e13264e871599d44668824a40159b0b080e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 14 Jun 2016 23:12:32 -0400 Subject: fix button alignments --- MediaBrowser.Controller/Entities/InternalItemsQuery.cs | 1 + MediaBrowser.Model/Querying/ItemSortBy.cs | 1 + .../LiveTv/Listings/XmlTvListingsProvider.cs | 6 +++++- .../Persistence/SqliteItemRepository.cs | 16 ++++++++++------ 4 files changed, 17 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index d50f5b5255..e193a9dadd 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -143,6 +143,7 @@ namespace MediaBrowser.Controller.Entities public bool EnableTotalRecordCount { get; set; } public bool ForceDirect { get; set; } public Dictionary ExcludeProviderIds { get; set; } + public string GroupByAncestorOfType { get; set; } public InternalItemsQuery() { diff --git a/MediaBrowser.Model/Querying/ItemSortBy.cs b/MediaBrowser.Model/Querying/ItemSortBy.cs index 9c2926b542..6f4ebd0c50 100644 --- a/MediaBrowser.Model/Querying/ItemSortBy.cs +++ b/MediaBrowser.Model/Querying/ItemSortBy.cs @@ -85,5 +85,6 @@ namespace MediaBrowser.Model.Querying public const string GameSystem = "GameSystem"; public const string IsFavoriteOrLiked = "IsFavoriteOrLiked"; public const string DateLastContentAdded = "DateLastContentAdded"; + public const string SeriesDatePlayed = "SeriesDatePlayed"; } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 07affb865c..010ee80ff6 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Emby.XmlTv.Classes; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Logging; @@ -68,6 +69,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings Progress = new Progress() }).ConfigureAwait(false); + + Directory.CreateDirectory(Path.GetDirectoryName(cacheFile)); File.Copy(tempFile, cacheFile, true); return cacheFile; @@ -103,7 +106,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings ImageUrl = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source) ? p.Icon.Source : null, HasImage = p.Icon != null && !String.IsNullOrEmpty(p.Icon.Source), OfficialRating = p.Rating != null && !String.IsNullOrEmpty(p.Rating.Value) ? p.Rating.Value : null, - CommunityRating = p.StarRating.HasValue ? p.StarRating.Value : (float?)null + CommunityRating = p.StarRating.HasValue ? p.StarRating.Value : (float?)null, + SeriesId = p.IsSeries ? p.Title.GetMD5().ToString("N") : null }); } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index d04dc57283..02f5483c5a 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1698,10 +1698,10 @@ namespace MediaBrowser.Server.Implementations.Persistence { var groups = new List(); - //if (!string.IsNullOrWhiteSpace(query.GroupByAncestorOfType)) - //{ - // groups.Add("(Select PresentationUniqueKey from TypedBaseItems B where B.Type = 'MediaBrowser.Controller.Entities.TV.Series' And B.Guid in (Select AncestorId from AncestorIds where ItemId=A.Guid))"); - //} + if (!string.IsNullOrWhiteSpace(query.GroupByAncestorOfType)) + { + groups.Add("(Select PresentationUniqueKey from TypedBaseItems B where B.Type = 'MediaBrowser.Controller.Entities.TV.Series' And B.Guid in (Select AncestorId from AncestorIds where ItemId=A.Guid))"); + } if (EnableGroupByPresentationUniqueKey(query)) { @@ -1926,7 +1926,7 @@ namespace MediaBrowser.Server.Implementations.Persistence return " ORDER BY " + string.Join(",", query.SortBy.Select(i => { - var columnMap = MapOrderByField(i); + var columnMap = MapOrderByField(i, query); var columnAscending = isAscending; if (columnMap.Item2) { @@ -1939,7 +1939,7 @@ namespace MediaBrowser.Server.Implementations.Persistence }).ToArray()); } - private Tuple MapOrderByField(string name) + private Tuple MapOrderByField(string name, InternalItemsQuery query) { if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase)) { @@ -1998,6 +1998,10 @@ namespace MediaBrowser.Server.Implementations.Persistence { return new Tuple("(select value from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", false); } + if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) + { + return new Tuple("(Select MAX(LastPlayedDate) from TypedBaseItems B"+ GetJoinUserDataText(query) + " where B.Guid in (Select ItemId from AncestorIds where AncestorId in (select guid from typedbaseitems c where C.Type = 'MediaBrowser.Controller.Entities.TV.Series' And C.Guid in (Select AncestorId from AncestorIds where ItemId=A.Guid))))", false); + } return new Tuple(name, false); } -- cgit v1.2.3 From 023b12a798d6bf475a3b20488c1921e7fdb68dc5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 15 Jun 2016 14:56:37 -0400 Subject: update recording format --- MediaBrowser.Api/StartupWizardService.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 10 +++-- MediaBrowser.Controller/Entities/TV/Series.cs | 23 +++++++---- .../Dto/DtoService.cs | 37 +++++++++++------ .../LiveTv/EmbyTV/EncodedRecorder.cs | 21 +++++----- .../Persistence/SqliteExtensions.cs | 8 +++- .../Persistence/SqliteItemRepository.cs | 47 +++++++++++++++------- .../Persistence/SqliteUserDataRepository.cs | 13 ++++++ .../Migrations/DbMigration.cs | 20 +++++++++ 9 files changed, 129 insertions(+), 52 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 21f87a6117..f4aee080a7 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -114,7 +114,7 @@ namespace MediaBrowser.Api config.EnableStandaloneMusicKeys = true; config.EnableCaseSensitiveItemIds = true; config.EnableFolderView = true; - config.SchemaVersion = 91; + config.SchemaVersion = 92; } public void Post(UpdateStartupConfiguration request) diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index b2788abe06..3c8d8baece 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1413,14 +1413,14 @@ namespace MediaBrowser.Controller.Entities return; } - var playedQueryResult = GetItems(new InternalItemsQuery(user) + var unplayedQueryResult = GetItems(new InternalItemsQuery(user) { Recursive = true, IsFolder = false, IsVirtualItem = false, EnableTotalRecordCount = true, Limit = 0, - IsPlayed = true + IsPlayed = false }).Result; @@ -1435,12 +1435,14 @@ namespace MediaBrowser.Controller.Entities }).Result; double recursiveItemCount = allItemsQueryResult.TotalRecordCount; - double playedCount = playedQueryResult.TotalRecordCount; + double unplayedCount = unplayedQueryResult.TotalRecordCount; if (recursiveItemCount > 0) { - dto.PlayedPercentage = (playedCount / recursiveItemCount) * 100; + var unplayedPercentage = (unplayedCount / recursiveItemCount) * 100; + dto.PlayedPercentage = 100 - unplayedPercentage; dto.Played = dto.PlayedPercentage.Value >= 100; + dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount; } } } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index cc1378ae1a..1f341ba138 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -186,16 +186,25 @@ namespace MediaBrowser.Controller.Entities.TV var user = query.User; - Func filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); - - IEnumerable items; + if (query.Recursive) + { + query.AncestorWithPresentationUniqueKey = PresentationUniqueKey; + if (query.SortBy.Length == 0) + { + query.SortBy = new[] { ItemSortBy.SortName }; + } + if (query.IncludeItemTypes.Length == 0) + { + query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }; + } + query.IsVirtualItem = false; + return Task.FromResult(LibraryManager.GetItemsResult(query)); + } - items = query.Recursive - ? GetSeasons(user).Cast().Concat(GetEpisodes(user)).Where(filter) - : GetSeasons(user).Where(filter); + Func filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); + var items = GetSeasons(user).Where(filter); var result = PostFilterAndSort(items, query); - return Task.FromResult(result); } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 2c31a8aae9..a2d895e2c1 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -469,22 +469,31 @@ namespace MediaBrowser.Server.Implementations.Dto { if (item.IsFolder) { - var userData = _userDataRepository.GetUserData(user, item); - - // Skip the user data manager because we've already looped through the recursive tree and don't want to do it twice - // TODO: Improve in future - dto.UserData = GetUserItemDataDto(userData); - var folder = (Folder)item; - if (item.SourceType == SourceType.Library) + if (fields.Contains(ItemFields.SyncInfo)) { - dto.ChildCount = GetChildCount(folder, user); + var userData = _userDataRepository.GetUserData(user, item); + + // Skip the user data manager because we've already looped through the recursive tree and don't want to do it twice + // TODO: Improve in future + dto.UserData = GetUserItemDataDto(userData); - if (folder.SupportsUserDataFromChildren) + if (item.SourceType == SourceType.Library && folder.SupportsUserDataFromChildren) { SetSpecialCounts(folder, user, dto, fields, syncProgress); } + + dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100; + } + else + { + dto.UserData = _userDataRepository.GetUserDataDto(item, user); + } + + if (item.SourceType == SourceType.Library) + { + dto.ChildCount = GetChildCount(folder, user); } if (fields.Contains(ItemFields.CumulativeRunTimeTicks)) @@ -496,8 +505,6 @@ namespace MediaBrowser.Server.Implementations.Dto { dto.DateLastMediaAdded = folder.DateLastMediaAdded; } - - dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100; } else @@ -1586,12 +1593,18 @@ namespace MediaBrowser.Server.Implementations.Dto /// Task. private void SetSpecialCounts(Folder folder, User user, BaseItemDto dto, List fields, Dictionary syncProgress) { + var addSyncInfo = fields.Contains(ItemFields.SyncInfo); + + if (!addSyncInfo) + { + return; + } + var recursiveItemCount = 0; var unplayed = 0; double totalPercentPlayed = 0; double totalSyncPercent = 0; - var addSyncInfo = fields.Contains(ItemFields.SyncInfo); var children = folder.GetItems(new InternalItemsQuery { diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index ffd5b65e41..13158d3461 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -44,16 +44,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile) { - if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings) - { - // if the audio is aac_latm, stream copying to mp4 will fail - var streams = mediaSource.MediaStreams ?? new List(); - if (streams.Any(i => i.Type == MediaStreamType.Audio && (i.Codec ?? string.Empty).IndexOf("aac", StringComparison.OrdinalIgnoreCase) != -1)) - { - return Path.ChangeExtension(targetFile, ".ts"); - } - } - return Path.ChangeExtension(targetFile, ".mp4"); } @@ -159,9 +149,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private string GetAudioArgs(MediaSourceInfo mediaSource) { - var copyAudio = new[] { "aac", "mp3" }; + // do not copy aac because many players have difficulty with aac_latm + var copyAudio = new[] { "mp3" }; var mediaStreams = mediaSource.MediaStreams ?? new List(); - if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings || mediaStreams.Any(i => i.Type == MediaStreamType.Audio && copyAudio.Contains(i.Codec, StringComparer.OrdinalIgnoreCase))) + var inputAudioCodec = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Select(i => i.Codec).FirstOrDefault() ?? string.Empty; + + if (copyAudio.Contains(inputAudioCodec, StringComparer.OrdinalIgnoreCase)) + { + return "-codec:a:0 copy"; + } + if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings && !string.Equals(inputAudioCodec, "aac", StringComparison.OrdinalIgnoreCase)) { return "-codec:a:0 copy"; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs index 73b3a22531..d5b582da56 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs @@ -26,6 +26,8 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("dbPath"); } + SQLiteConnection.SetMemoryStatus(false); + var connectionstr = new SQLiteConnectionStringBuilder { PageSize = 4096, @@ -41,8 +43,10 @@ namespace MediaBrowser.Server.Implementations.Persistence var connectionString = connectionstr.ConnectionString; - //logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, connectionString); - SQLiteConnection.SetMemoryStatus(false); + if (!enablePooling) + { + logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, connectionString); + } var connection = new SQLiteConnection(connectionString); diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 02f5483c5a..04118cb855 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - public const int LatestSchemaVersion = 89; + public const int LatestSchemaVersion = 92; /// /// Initializes a new instance of the class. @@ -122,7 +122,7 @@ namespace MediaBrowser.Server.Implementations.Persistence protected override async Task CreateConnection(bool isReadOnly = false) { - var connection = await DbConnector.Connect(DbFilePath, false, false, 6000).ConfigureAwait(false); + var connection = await DbConnector.Connect(DbFilePath, false, false, 20000).ConfigureAwait(false); connection.RunQueries(new[] { @@ -1789,7 +1789,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var slowThreshold = 1000; #if DEBUG - slowThreshold = 100; + slowThreshold = 80; #endif if (elapsed >= slowThreshold) @@ -1857,13 +1857,22 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + cmd.CommandText += ";"; + + var isReturningZeroItems = query.Limit.HasValue && query.Limit <= 0; + + if (isReturningZeroItems) + { + cmd.CommandText = ""; + } + if (EnableGroupByPresentationUniqueKey(query)) { - cmd.CommandText += "; select count (distinct PresentationUniqueKey)" + GetFromText(); + cmd.CommandText += " select count (distinct PresentationUniqueKey)" + GetFromText(); } else { - cmd.CommandText += "; select count (guid)" + GetFromText(); + cmd.CommandText += " select count (guid)" + GetFromText(); } cmd.CommandText += GetJoinUserDataText(query); @@ -1876,18 +1885,28 @@ namespace MediaBrowser.Server.Implementations.Persistence { LogQueryTime("GetItems", cmd, now); - while (reader.Read()) + if (isReturningZeroItems) { - var item = GetItem(reader); - if (item != null) + if (reader.Read()) { - list.Add(item); + count = reader.GetInt32(0); } } - - if (reader.NextResult() && reader.Read()) + else { - count = reader.GetInt32(0); + while (reader.Read()) + { + var item = GetItem(reader); + if (item != null) + { + list.Add(item); + } + } + + if (reader.NextResult() && reader.Read()) + { + count = reader.GetInt32(0); + } } } @@ -2388,8 +2407,8 @@ namespace MediaBrowser.Server.Implementations.Persistence } if (query.ParentIndexNumberNotEquals.HasValue) { - whereClauses.Add("(ParentIndexNumber<>@ParentIndexNumber or ParentIndexNumber is null)"); - cmd.Parameters.Add(cmd, "@ParentIndexNumber", DbType.Int32).Value = query.ParentIndexNumberNotEquals.Value; + whereClauses.Add("(ParentIndexNumber<>@ParentIndexNumberNotEquals or ParentIndexNumber is null)"); + cmd.Parameters.Add(cmd, "@ParentIndexNumberNotEquals", DbType.Int32).Value = query.ParentIndexNumberNotEquals.Value; } if (query.MinEndDate.HasValue) { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index 6edacba535..f40006b443 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -39,6 +39,19 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + protected override async Task CreateConnection(bool isReadOnly = false) + { + var connection = await DbConnector.Connect(DbFilePath, false, false, 10000).ConfigureAwait(false); + + connection.RunQueries(new[] + { + "pragma temp_store = memory" + + }, Logger); + + return connection; + } + /// /// Opens the connection to the database /// diff --git a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs index 65517c09c2..f0cb9e84ee 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/DbMigration.cs @@ -18,6 +18,7 @@ namespace MediaBrowser.Server.Startup.Common.Migrations public void Run() { + // If a forced migration is required, do that now if (_config.Configuration.MigrationVersion < CleanDatabaseScheduledTask.MigrationVersion) { if (!_config.Configuration.IsStartupWizardCompleted) @@ -36,6 +37,25 @@ namespace MediaBrowser.Server.Startup.Common.Migrations _taskManager.Execute(); }); + + return; + } + + if (_config.Configuration.SchemaVersion < SqliteItemRepository.LatestSchemaVersion) + { + if (!_config.Configuration.IsStartupWizardCompleted) + { + _config.Configuration.SchemaVersion = SqliteItemRepository.LatestSchemaVersion; + _config.SaveConfiguration(); + return; + } + + Task.Run(async () => + { + await Task.Delay(1000).ConfigureAwait(false); + + _taskManager.Execute(); + }); } } } -- cgit v1.2.3 From ed6a0b52966c1212a93f678c93acbecb3d7f4606 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 16 Jun 2016 09:18:52 -0400 Subject: update favorites --- MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/Persistence') diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 04118cb855..437d169744 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -122,7 +122,7 @@ namespace MediaBrowser.Server.Implementations.Persistence protected override async Task CreateConnection(bool isReadOnly = false) { - var connection = await DbConnector.Connect(DbFilePath, false, false, 20000).ConfigureAwait(false); + var connection = await DbConnector.Connect(DbFilePath, false, false, 5000).ConfigureAwait(false); connection.RunQueries(new[] { -- cgit v1.2.3