Sfoglia il codice sorgente

reduce library queries

Luke Pulverenti 8 anni fa
parent
commit
f275d7f3d2
32 ha cambiato i file con 230 aggiunte e 176 eliminazioni
  1. 5 0
      Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs
  2. 1 1
      Emby.Server.Core/ApplicationHost.cs
  3. 2 3
      Emby.Server.Implementations/Activity/ActivityRepository.cs
  4. 29 8
      Emby.Server.Implementations/Data/BaseSqliteRepository.cs
  5. 2 3
      Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
  6. 2 3
      Emby.Server.Implementations/Data/SqliteFileOrganizationRepository.cs
  7. 48 48
      Emby.Server.Implementations/Data/SqliteItemRepository.cs
  8. 2 3
      Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
  9. 2 3
      Emby.Server.Implementations/Data/SqliteUserRepository.cs
  10. 15 1
      Emby.Server.Implementations/Dto/DtoService.cs
  11. 12 19
      Emby.Server.Implementations/Library/LibraryManager.cs
  12. 18 12
      Emby.Server.Implementations/Library/UserViewManager.cs
  13. 1 1
      Emby.Server.Implementations/LiveTv/LiveTvManager.cs
  14. 5 6
      Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
  15. 2 3
      Emby.Server.Implementations/Security/AuthenticationRepository.cs
  16. 2 3
      Emby.Server.Implementations/Social/SharingRepository.cs
  17. 2 3
      Emby.Server.Implementations/Sync/SyncRepository.cs
  18. 2 2
      Emby.Server.Implementations/TV/TVSeriesManager.cs
  19. 1 1
      MediaBrowser.Api/Library/LibraryService.cs
  20. 1 16
      MediaBrowser.Api/Movies/MoviesService.cs
  21. 6 0
      MediaBrowser.Controller/Entities/Audio/Audio.cs
  22. 18 4
      MediaBrowser.Controller/Entities/BaseItem.cs
  23. 24 15
      MediaBrowser.Controller/Entities/Folder.cs
  24. 0 1
      MediaBrowser.Controller/Entities/InternalItemsQuery.cs
  25. 6 0
      MediaBrowser.Controller/Entities/TV/Episode.cs
  26. 6 0
      MediaBrowser.Controller/Entities/TV/Season.cs
  27. 0 1
      MediaBrowser.Controller/Entities/TV/Series.cs
  28. 5 5
      MediaBrowser.Controller/Entities/UserViewBuilder.cs
  29. 1 4
      MediaBrowser.Controller/Library/ILibraryManager.cs
  30. 1 1
      MediaBrowser.Controller/TV/ITVSeriesManager.cs
  31. 1 0
      MediaBrowser.Model/System/IEnvironmentInfo.cs
  32. 8 6
      MediaBrowser.Providers/Manager/MetadataService.cs

+ 5 - 0
Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs

@@ -105,5 +105,10 @@ namespace Emby.Common.Implementations.EnvironmentInfo
         {
         {
             return null;
             return null;
         }
         }
+
+        public string StackTrace
+        {
+            get { return Environment.StackTrace; }
+        }
     }
     }
 }
 }

+ 1 - 1
Emby.Server.Core/ApplicationHost.cs

@@ -551,7 +551,7 @@ namespace Emby.Server.Core
             DisplayPreferencesRepository = displayPreferencesRepo;
             DisplayPreferencesRepository = displayPreferencesRepo;
             RegisterSingleInstance(DisplayPreferencesRepository);
             RegisterSingleInstance(DisplayPreferencesRepository);
 
 
-            var itemRepo = new SqliteItemRepository(ServerConfigurationManager, JsonSerializer, LogManager.GetLogger("SqliteItemRepository"), MemoryStreamFactory, assemblyInfo, FileSystemManager);
+            var itemRepo = new SqliteItemRepository(ServerConfigurationManager, JsonSerializer, LogManager.GetLogger("SqliteItemRepository"), MemoryStreamFactory, assemblyInfo, FileSystemManager, EnvironmentInfo);
             ItemRepository = itemRepo;
             ItemRepository = itemRepo;
             RegisterSingleInstance(ItemRepository);
             RegisterSingleInstance(ItemRepository);
 
 

+ 2 - 3
Emby.Server.Implementations/Activity/ActivityRepository.cs

@@ -29,10 +29,9 @@ namespace Emby.Server.Implementations.Activity
             {
             {
                 connection.ExecuteAll(string.Join(";", new[]
                 connection.ExecuteAll(string.Join(";", new[]
                 {
                 {
+                                "PRAGMA page_size=4096",
                                 "pragma default_temp_store = memory",
                                 "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "pragma temp_store = memory"
                 }));
                 }));
 
 
                 string[] queries = {
                 string[] queries = {

+ 29 - 8
Emby.Server.Implementations/Data/BaseSqliteRepository.cs

@@ -40,6 +40,8 @@ namespace Emby.Server.Implementations.Data
 
 
         private static bool _versionLogged;
         private static bool _versionLogged;
 
 
+        private string _defaultWal;
+
         protected SQLiteDatabaseConnection CreateConnection(bool isReadOnly = false, Action<SQLiteDatabaseConnection> onConnect = null)
         protected SQLiteDatabaseConnection CreateConnection(bool isReadOnly = false, Action<SQLiteDatabaseConnection> onConnect = null)
         {
         {
             if (!_versionLogged)
             if (!_versionLogged)
@@ -51,6 +53,15 @@ namespace Emby.Server.Implementations.Data
 
 
             ConnectionFlags connectionFlags;
             ConnectionFlags connectionFlags;
 
 
+            if (isReadOnly)
+            {
+                //Logger.Info("Opening read connection");
+            }
+            else
+            {
+                //Logger.Info("Opening write connection");
+            }
+
             isReadOnly = false;
             isReadOnly = false;
 
 
             if (isReadOnly)
             if (isReadOnly)
@@ -70,12 +81,16 @@ namespace Emby.Server.Implementations.Data
 
 
             var db = SQLite3.Open(DbFilePath, connectionFlags, null);
             var db = SQLite3.Open(DbFilePath, connectionFlags, null);
 
 
+            if (string.IsNullOrWhiteSpace(_defaultWal))
+            {
+                _defaultWal = db.Query("PRAGMA journal_mode").SelectScalarString().First();
+            }
+
             var queries = new List<string>
             var queries = new List<string>
             {
             {
+                "PRAGMA default_temp_store=memory",
                 "pragma temp_store = memory",
                 "pragma temp_store = memory",
-                "PRAGMA page_size=4096",
-                "PRAGMA journal_mode=WAL",
-                "pragma synchronous=Normal",
+                "PRAGMA journal_mode=WAL"
                 //"PRAGMA cache size=-10000"
                 //"PRAGMA cache size=-10000"
             };
             };
 
 
@@ -90,13 +105,19 @@ namespace Emby.Server.Implementations.Data
             ////    db.Execute(query);
             ////    db.Execute(query);
             ////}
             ////}
 
 
-            using (WriteLock.Write())
-            {
-                db.ExecuteAll(string.Join(";", queries.ToArray()));
+            //Logger.Info("synchronous: " + db.Query("PRAGMA synchronous").SelectScalarString().First());
+            //Logger.Info("temp_store: " + db.Query("PRAGMA temp_store").SelectScalarString().First());
 
 
-                if (onConnect != null)
+            //if (!string.Equals(_defaultWal, "wal", StringComparison.OrdinalIgnoreCase) || onConnect != null)
+            {
+                using (WriteLock.Write())
                 {
                 {
-                    onConnect(db);
+                    db.ExecuteAll(string.Join(";", queries.ToArray()));
+
+                    if (onConnect != null)
+                    {
+                        onConnect(db);
+                    }
                 }
                 }
             }
             }
 
 

+ 2 - 3
Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs

@@ -56,10 +56,9 @@ namespace Emby.Server.Implementations.Data
             {
             {
                 connection.ExecuteAll(string.Join(";", new[]
                 connection.ExecuteAll(string.Join(";", new[]
                {
                {
+                                "PRAGMA page_size=4096",
                                 "pragma default_temp_store = memory",
                                 "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "pragma temp_store = memory"
                 }));
                 }));
 
 
                 string[] queries = {
                 string[] queries = {

+ 2 - 3
Emby.Server.Implementations/Data/SqliteFileOrganizationRepository.cs

@@ -33,10 +33,9 @@ namespace Emby.Server.Implementations.Data
             {
             {
                 connection.ExecuteAll(string.Join(";", new[]
                 connection.ExecuteAll(string.Join(";", new[]
                 {
                 {
+                                "PRAGMA page_size=4096",
                                 "pragma default_temp_store = memory",
                                 "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "pragma temp_store = memory"
                 }));
                 }));
 
 
                 string[] queries = {
                 string[] queries = {

+ 48 - 48
Emby.Server.Implementations/Data/SqliteItemRepository.cs

@@ -29,6 +29,7 @@ using MediaBrowser.Server.Implementations.Devices;
 using MediaBrowser.Server.Implementations.Playlists;
 using MediaBrowser.Server.Implementations.Playlists;
 using MediaBrowser.Model.Reflection;
 using MediaBrowser.Model.Reflection;
 using SQLitePCL.pretty;
 using SQLitePCL.pretty;
+using MediaBrowser.Model.System;
 
 
 namespace Emby.Server.Implementations.Data
 namespace Emby.Server.Implementations.Data
 {
 {
@@ -66,14 +67,14 @@ namespace Emby.Server.Implementations.Data
 
 
         private readonly string _criticReviewsPath;
         private readonly string _criticReviewsPath;
 
 
-        public const int LatestSchemaVersion = 109;
         private readonly IMemoryStreamFactory _memoryStreamProvider;
         private readonly IMemoryStreamFactory _memoryStreamProvider;
         private readonly IFileSystem _fileSystem;
         private readonly IFileSystem _fileSystem;
+        private readonly IEnvironmentInfo _environmentInfo;
 
 
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
         /// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
         /// </summary>
         /// </summary>
-        public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogger logger, IMemoryStreamFactory memoryStreamProvider, IAssemblyInfo assemblyInfo, IFileSystem fileSystem)
+        public SqliteItemRepository(IServerConfigurationManager config, IJsonSerializer jsonSerializer, ILogger logger, IMemoryStreamFactory memoryStreamProvider, IAssemblyInfo assemblyInfo, IFileSystem fileSystem, IEnvironmentInfo environmentInfo)
             : base(logger)
             : base(logger)
         {
         {
             if (config == null)
             if (config == null)
@@ -89,6 +90,7 @@ namespace Emby.Server.Implementations.Data
             _jsonSerializer = jsonSerializer;
             _jsonSerializer = jsonSerializer;
             _memoryStreamProvider = memoryStreamProvider;
             _memoryStreamProvider = memoryStreamProvider;
             _fileSystem = fileSystem;
             _fileSystem = fileSystem;
+            _environmentInfo = environmentInfo;
             _typeMapper = new TypeMapper(assemblyInfo);
             _typeMapper = new TypeMapper(assemblyInfo);
 
 
             _criticReviewsPath = Path.Combine(_config.ApplicationPaths.DataPath, "critic-reviews");
             _criticReviewsPath = Path.Combine(_config.ApplicationPaths.DataPath, "critic-reviews");
@@ -129,10 +131,9 @@ namespace Emby.Server.Implementations.Data
 
 
             _connection.ExecuteAll(string.Join(";", new[]
             _connection.ExecuteAll(string.Join(";", new[]
             {
             {
-                                "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "PRAGMA page_size=4096",
+                                "PRAGMA default_temp_store=memory",
+                                "PRAGMA temp_store=memory"
              }));
              }));
 
 
             var createMediaStreamsTableCommand
             var createMediaStreamsTableCommand
@@ -193,7 +194,6 @@ namespace Emby.Server.Implementations.Data
                 AddColumn(db, "TypedBaseItems", "ProductionYear", "INT", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "ProductionYear", "INT", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "ParentId", "GUID", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "ParentId", "GUID", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "Genres", "Text", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "Genres", "Text", existingColumnNames);
-                AddColumn(db, "TypedBaseItems", "SchemaVersion", "INT", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
 
 
@@ -205,7 +205,6 @@ namespace Emby.Server.Implementations.Data
                 AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames);
 
 
                 AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames);
-                AddColumn(db, "TypedBaseItems", "IsOffline", "BIT", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "LocationType", "Text", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "LocationType", "Text", existingColumnNames);
 
 
                 AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames);
                 AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames);
@@ -381,7 +380,6 @@ namespace Emby.Server.Implementations.Data
             "data",
             "data",
             "StartDate",
             "StartDate",
             "EndDate",
             "EndDate",
-            "IsOffline",
             "ChannelId",
             "ChannelId",
             "IsMovie",
             "IsMovie",
             "IsSports",
             "IsSports",
@@ -529,7 +527,6 @@ namespace Emby.Server.Implementations.Data
                 "ParentId",
                 "ParentId",
                 "Genres",
                 "Genres",
                 "InheritedParentalRatingValue",
                 "InheritedParentalRatingValue",
-                "SchemaVersion",
                 "SortName",
                 "SortName",
                 "RunTimeTicks",
                 "RunTimeTicks",
                 "OfficialRatingDescription",
                 "OfficialRatingDescription",
@@ -539,7 +536,6 @@ namespace Emby.Server.Implementations.Data
                 "DateCreated",
                 "DateCreated",
                 "DateModified",
                 "DateModified",
                 "ForcedSortName",
                 "ForcedSortName",
-                "IsOffline",
                 "LocationType",
                 "LocationType",
                 "PreferredMetadataLanguage",
                 "PreferredMetadataLanguage",
                 "PreferredMetadataCountryCode",
                 "PreferredMetadataCountryCode",
@@ -790,7 +786,6 @@ namespace Emby.Server.Implementations.Data
             }
             }
 
 
             saveItemStatement.TryBind("@InheritedParentalRatingValue", item.GetInheritedParentalRatingValue() ?? 0);
             saveItemStatement.TryBind("@InheritedParentalRatingValue", item.GetInheritedParentalRatingValue() ?? 0);
-            saveItemStatement.TryBind("@SchemaVersion", LatestSchemaVersion);
 
 
             saveItemStatement.TryBind("@SortName", item.SortName);
             saveItemStatement.TryBind("@SortName", item.SortName);
             saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
             saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
@@ -803,7 +798,6 @@ namespace Emby.Server.Implementations.Data
             saveItemStatement.TryBind("@DateModified", item.DateModified);
             saveItemStatement.TryBind("@DateModified", item.DateModified);
 
 
             saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName);
             saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName);
-            saveItemStatement.TryBind("@IsOffline", item.IsOffline);
             saveItemStatement.TryBind("@LocationType", item.LocationType.ToString());
             saveItemStatement.TryBind("@LocationType", item.LocationType.ToString());
 
 
             saveItemStatement.TryBind("@PreferredMetadataLanguage", item.PreferredMetadataLanguage);
             saveItemStatement.TryBind("@PreferredMetadataLanguage", item.PreferredMetadataLanguage);
@@ -1182,7 +1176,7 @@ namespace Emby.Server.Implementations.Data
             }
             }
 
 
             CheckDisposed();
             CheckDisposed();
-
+            //Logger.Info("Retrieving item {0}", id.ToString("N"));
             using (var connection = CreateConnection(true))
             using (var connection = CreateConnection(true))
             {
             {
                 using (WriteLock.Read())
                 using (WriteLock.Read())
@@ -1369,64 +1363,72 @@ namespace Emby.Server.Implementations.Data
 
 
             if (!reader.IsDBNull(4))
             if (!reader.IsDBNull(4))
             {
             {
-                item.IsOffline = reader.GetBoolean(4);
+                item.ChannelId = reader.GetString(4);
             }
             }
 
 
-            if (!reader.IsDBNull(5))
-            {
-                item.ChannelId = reader.GetString(5);
-            }
+            var index = 5;
 
 
             var hasProgramAttributes = item as IHasProgramAttributes;
             var hasProgramAttributes = item as IHasProgramAttributes;
             if (hasProgramAttributes != null)
             if (hasProgramAttributes != null)
             {
             {
-                if (!reader.IsDBNull(6))
+                if (!reader.IsDBNull(index))
                 {
                 {
-                    hasProgramAttributes.IsMovie = reader.GetBoolean(6);
+                    hasProgramAttributes.IsMovie = reader.GetBoolean(index);
                 }
                 }
+                index++;
 
 
-                if (!reader.IsDBNull(7))
+                if (!reader.IsDBNull(index))
                 {
                 {
-                    hasProgramAttributes.IsSports = reader.GetBoolean(7);
+                    hasProgramAttributes.IsSports = reader.GetBoolean(index);
                 }
                 }
+                index++;
 
 
-                if (!reader.IsDBNull(8))
+                if (!reader.IsDBNull(index))
                 {
                 {
-                    hasProgramAttributes.IsKids = reader.GetBoolean(8);
+                    hasProgramAttributes.IsKids = reader.GetBoolean(index);
                 }
                 }
+                index++;
 
 
-                if (!reader.IsDBNull(9))
+                if (!reader.IsDBNull(index))
                 {
                 {
-                    hasProgramAttributes.IsSeries = reader.GetBoolean(9);
+                    hasProgramAttributes.IsSeries = reader.GetBoolean(index);
                 }
                 }
+                index++;
 
 
-                if (!reader.IsDBNull(10))
+                if (!reader.IsDBNull(index))
                 {
                 {
-                    hasProgramAttributes.IsLive = reader.GetBoolean(10);
+                    hasProgramAttributes.IsLive = reader.GetBoolean(index);
                 }
                 }
+                index++;
 
 
-                if (!reader.IsDBNull(11))
+                if (!reader.IsDBNull(index))
                 {
                 {
-                    hasProgramAttributes.IsNews = reader.GetBoolean(11);
+                    hasProgramAttributes.IsNews = reader.GetBoolean(index);
                 }
                 }
+                index++;
 
 
-                if (!reader.IsDBNull(12))
+                if (!reader.IsDBNull(index))
                 {
                 {
-                    hasProgramAttributes.IsPremiere = reader.GetBoolean(12);
+                    hasProgramAttributes.IsPremiere = reader.GetBoolean(index);
                 }
                 }
+                index++;
 
 
-                if (!reader.IsDBNull(13))
+                if (!reader.IsDBNull(index))
                 {
                 {
-                    hasProgramAttributes.EpisodeTitle = reader.GetString(13);
+                    hasProgramAttributes.EpisodeTitle = reader.GetString(index);
                 }
                 }
+                index++;
 
 
-                if (!reader.IsDBNull(14))
+                if (!reader.IsDBNull(index))
                 {
                 {
-                    hasProgramAttributes.IsRepeat = reader.GetBoolean(14);
+                    hasProgramAttributes.IsRepeat = reader.GetBoolean(index);
                 }
                 }
+                index++;
+            }
+            else
+            {
+                index += 9;
             }
             }
-
-            var index = 15;
 
 
             if (!reader.IsDBNull(index))
             if (!reader.IsDBNull(index))
             {
             {
@@ -2368,6 +2370,8 @@ namespace Emby.Server.Implementations.Data
 
 
             CheckDisposed();
             CheckDisposed();
 
 
+            //Logger.Info("GetItemList: " + _environmentInfo.StackTrace);
+
             var now = DateTime.UtcNow;
             var now = DateTime.UtcNow;
 
 
             var list = new List<BaseItem>();
             var list = new List<BaseItem>();
@@ -2533,6 +2537,7 @@ namespace Emby.Server.Implementations.Data
                     TotalRecordCount = returnList.Count
                     TotalRecordCount = returnList.Count
                 };
                 };
             }
             }
+            //Logger.Info("GetItems: " + _environmentInfo.StackTrace);
 
 
             var now = DateTime.UtcNow;
             var now = DateTime.UtcNow;
 
 
@@ -2770,6 +2775,7 @@ namespace Emby.Server.Implementations.Data
             }
             }
 
 
             CheckDisposed();
             CheckDisposed();
+            //Logger.Info("GetItemIdsList: " + _environmentInfo.StackTrace);
 
 
             var now = DateTime.UtcNow;
             var now = DateTime.UtcNow;
 
 
@@ -2928,6 +2934,7 @@ namespace Emby.Server.Implementations.Data
                     TotalRecordCount = returnList.Count
                     TotalRecordCount = returnList.Count
                 };
                 };
             }
             }
+            //Logger.Info("GetItemIds: " + _environmentInfo.StackTrace);
 
 
             var now = DateTime.UtcNow;
             var now = DateTime.UtcNow;
 
 
@@ -3053,14 +3060,6 @@ namespace Emby.Server.Implementations.Data
                     statement.TryBind("@IsLocked", query.IsLocked);
                     statement.TryBind("@IsLocked", query.IsLocked);
                 }
                 }
             }
             }
-            if (query.IsOffline.HasValue)
-            {
-                whereClauses.Add("IsOffline=@IsOffline");
-                if (statement != null)
-                {
-                    statement.TryBind("@IsOffline", query.IsOffline);
-                }
-            }
 
 
             var exclusiveProgramAttribtues = !(query.IsMovie ?? true) ||
             var exclusiveProgramAttribtues = !(query.IsMovie ?? true) ||
                                              !(query.IsSports ?? true) ||
                                              !(query.IsSports ?? true) ||
@@ -4721,7 +4720,7 @@ namespace Emby.Server.Implementations.Data
 
 
             using (var connection = CreateConnection(true))
             using (var connection = CreateConnection(true))
             {
             {
-                using (WriteLock.Write())
+                using (WriteLock.Read())
                 {
                 {
                     foreach (var row in connection.Query(commandText))
                     foreach (var row in connection.Query(commandText))
                     {
                     {
@@ -4750,6 +4749,7 @@ namespace Emby.Server.Implementations.Data
             }
             }
 
 
             CheckDisposed();
             CheckDisposed();
+            //Logger.Info("GetItemValues: " + _environmentInfo.StackTrace);
 
 
             var now = DateTime.UtcNow;
             var now = DateTime.UtcNow;
 
 

+ 2 - 3
Emby.Server.Implementations/Data/SqliteUserDataRepository.cs

@@ -45,10 +45,9 @@ namespace Emby.Server.Implementations.Data
             {
             {
                 connection.ExecuteAll(string.Join(";", new[]
                 connection.ExecuteAll(string.Join(";", new[]
                 {
                 {
+                                "PRAGMA page_size=4096",
                                 "pragma default_temp_store = memory",
                                 "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "pragma temp_store = memory"
                 }));
                 }));
 
 
                 string[] queries = {
                 string[] queries = {

+ 2 - 3
Emby.Server.Implementations/Data/SqliteUserRepository.cs

@@ -52,10 +52,9 @@ namespace Emby.Server.Implementations.Data
             {
             {
                 connection.ExecuteAll(string.Join(";", new[]
                 connection.ExecuteAll(string.Join(";", new[]
                 {
                 {
+                                "PRAGMA page_size=4096",
                                 "pragma default_temp_store = memory",
                                 "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "pragma temp_store = memory"
                 }));
                 }));
 
 
                 string[] queries = {
                 string[] queries = {

+ 15 - 1
Emby.Server.Implementations/Dto/DtoService.cs

@@ -482,7 +482,7 @@ namespace Emby.Server.Implementations.Dto
             {
             {
                 if (dtoOptions.EnableUserData)
                 if (dtoOptions.EnableUserData)
                 {
                 {
-                    dto.UserData = _userDataRepository.GetUserDataDto(item, user).Result;
+                    dto.UserData = await _userDataRepository.GetUserDataDto(item, user).ConfigureAwait(false);
                 }
                 }
             }
             }
 
 
@@ -1450,11 +1450,19 @@ namespace Emby.Server.Implementations.Dto
 
 
         private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem owner)
         private void AddInheritedImages(BaseItemDto dto, BaseItem item, DtoOptions options, BaseItem owner)
         {
         {
+            if (!item.SupportsInheritedParentImages)
+            {
+                return;
+            }
+
             var logoLimit = options.GetImageLimit(ImageType.Logo);
             var logoLimit = options.GetImageLimit(ImageType.Logo);
             var artLimit = options.GetImageLimit(ImageType.Art);
             var artLimit = options.GetImageLimit(ImageType.Art);
             var thumbLimit = options.GetImageLimit(ImageType.Thumb);
             var thumbLimit = options.GetImageLimit(ImageType.Thumb);
             var backdropLimit = options.GetImageLimit(ImageType.Backdrop);
             var backdropLimit = options.GetImageLimit(ImageType.Backdrop);
 
 
+            // For now. Emby apps are not using this
+            artLimit = 0;
+
             if (logoLimit == 0 && artLimit == 0 && thumbLimit == 0 && backdropLimit == 0)
             if (logoLimit == 0 && artLimit == 0 && thumbLimit == 0 && backdropLimit == 0)
             {
             {
                 return;
                 return;
@@ -1515,6 +1523,12 @@ namespace Emby.Server.Implementations.Dto
                 }
                 }
 
 
                 isFirst = false;
                 isFirst = false;
+
+                if (!parent.SupportsInheritedParentImages)
+                {
+                    break;
+                }
+
                 parent = parent.GetParent();
                 parent = parent.GetParent();
             }
             }
         }
         }

+ 12 - 19
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -339,11 +339,6 @@ namespace Emby.Server.Implementations.Library
             {
             {
                 throw new ArgumentNullException("item");
                 throw new ArgumentNullException("item");
             }
             }
-            RegisterItem(item.Id, item);
-        }
-
-        private void RegisterItem(Guid id, BaseItem item)
-        {
             if (item is IItemByName)
             if (item is IItemByName)
             {
             {
                 if (!(item is MusicArtist))
                 if (!(item is MusicArtist))
@@ -354,13 +349,13 @@ namespace Emby.Server.Implementations.Library
 
 
             if (item.IsFolder)
             if (item.IsFolder)
             {
             {
-                if (!(item is ICollectionFolder) && !(item is UserView) && !(item is Channel) && !(item is AggregateFolder))
-                {
-                    if (item.SourceType != SourceType.Library)
-                    {
-                        return;
-                    }
-                }
+                //if (!(item is ICollectionFolder) && !(item is UserView) && !(item is Channel) && !(item is AggregateFolder))
+                //{
+                //    if (item.SourceType != SourceType.Library)
+                //    {
+                //        return;
+                //    }
+                //}
             }
             }
             else
             else
             {
             {
@@ -370,7 +365,7 @@ namespace Emby.Server.Implementations.Library
                 }
                 }
             }
             }
 
 
-            LibraryItemsCache.AddOrUpdate(id, item, delegate { return item; });
+            LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; });
         }
         }
 
 
         public async Task DeleteItem(BaseItem item, DeleteOptions options)
         public async Task DeleteItem(BaseItem item, DeleteOptions options)
@@ -822,7 +817,7 @@ namespace Emby.Server.Implementations.Library
 
 
             return _userRootFolder;
             return _userRootFolder;
         }
         }
-
+        
         public BaseItem FindByPath(string path, bool? isFolder)
         public BaseItem FindByPath(string path, bool? isFolder)
         {
         {
             // If this returns multiple items it could be tricky figuring out which one is correct. 
             // If this returns multiple items it could be tricky figuring out which one is correct. 
@@ -836,7 +831,7 @@ namespace Emby.Server.Implementations.Library
                 SortOrder = SortOrder.Descending,
                 SortOrder = SortOrder.Descending,
                 Limit = 1
                 Limit = 1
             };
             };
-
+            
             return GetItemList(query)
             return GetItemList(query)
                 .FirstOrDefault();
                 .FirstOrDefault();
         }
         }
@@ -1273,10 +1268,8 @@ namespace Emby.Server.Implementations.Library
             return ItemRepository.GetItemList(query);
             return ItemRepository.GetItemList(query);
         }
         }
 
 
-        public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, IEnumerable<string> parentIds)
+        public IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents)
         {
         {
-            var parents = parentIds.Select(i => GetItemById(new Guid(i))).Where(i => i != null).ToList();
-
             SetTopParentIdsOrAncestors(query, parents);
             SetTopParentIdsOrAncestors(query, parents);
 
 
             if (query.AncestorIds.Length == 0 && query.TopParentIds.Length == 0)
             if (query.AncestorIds.Length == 0 && query.TopParentIds.Length == 0)
@@ -1536,7 +1529,7 @@ namespace Emby.Server.Implementations.Library
                 }
                 }
 
 
                 // Handle grouping
                 // Handle grouping
-                if (user != null && !string.IsNullOrWhiteSpace(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType))
+                if (user != null && !string.IsNullOrWhiteSpace(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType) && user.Configuration.GroupedFolders.Length > 0)
                 {
                 {
                     return user.RootFolder
                     return user.RootFolder
                         .GetChildren(user, true)
                         .GetChildren(user, true)

+ 18 - 12
Emby.Server.Implementations/Library/UserViewManager.cs

@@ -245,20 +245,26 @@ namespace Emby.Server.Implementations.Library
             var includeItemTypes = request.IncludeItemTypes;
             var includeItemTypes = request.IncludeItemTypes;
             var limit = request.Limit ?? 10;
             var limit = request.Limit ?? 10;
 
 
-            var parentIds = string.IsNullOrEmpty(parentId)
-              ? new string[] { }
-              : new[] { parentId };
+            var parents = new List<BaseItem>();
 
 
-            if (parentIds.Length == 0)
+            if (!string.IsNullOrWhiteSpace(parentId))
             {
             {
-                parentIds = user.RootFolder.GetChildren(user, true)
-                    .OfType<Folder>()
-                    .Select(i => i.Id.ToString("N"))
-                    .Where(i => !user.Configuration.LatestItemsExcludes.Contains(i))
-                    .ToArray();
+                var parent = _libraryManager.GetItemById(parentId) as Folder;
+                if (parent != null)
+                {
+                    parents.Add(parent);
+                }
+            }
+
+            if (parents.Count == 0)
+            {
+                parents = user.RootFolder.GetChildren(user, true)
+                    .Where(i => i is Folder)
+                    .Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N")))
+                    .ToList();
             }
             }
 
 
-            if (parentIds.Length == 0)
+            if (parents.Count == 0)
             {
             {
                 return new List<BaseItem>();
                 return new List<BaseItem>();
             }
             }
@@ -283,10 +289,10 @@ namespace Emby.Server.Implementations.Library
                 ExcludeItemTypes = excludeItemTypes,
                 ExcludeItemTypes = excludeItemTypes,
                 ExcludeLocationTypes = new[] { LocationType.Virtual },
                 ExcludeLocationTypes = new[] { LocationType.Virtual },
                 Limit = limit * 5,
                 Limit = limit * 5,
-                SourceTypes = parentIds.Length == 0 ? new[] { SourceType.Library } : new SourceType[] { },
+                SourceTypes = parents.Count == 0 ? new[] { SourceType.Library } : new SourceType[] { },
                 IsPlayed = request.IsPlayed
                 IsPlayed = request.IsPlayed
 
 
-            }, parentIds);
+            }, parents);
         }
         }
     }
     }
 }
 }

+ 1 - 1
Emby.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -491,7 +491,7 @@ namespace Emby.Server.Implementations.LiveTv
 
 
             var id = _tvDtoService.GetInternalChannelId(serviceName, channelInfo.Id);
             var id = _tvDtoService.GetInternalChannelId(serviceName, channelInfo.Id);
 
 
-            var item = _itemRepo.RetrieveItem(id) as LiveTvChannel;
+            var item = _libraryManager.GetItemById(id) as LiveTvChannel;
 
 
             if (item == null)
             if (item == null)
             {
             {

+ 5 - 6
Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs

@@ -31,10 +31,9 @@ namespace Emby.Server.Implementations.Notifications
             {
             {
                 connection.ExecuteAll(string.Join(";", new[]
                 connection.ExecuteAll(string.Join(";", new[]
                 {
                 {
+                                "PRAGMA page_size=4096",
                                 "pragma default_temp_store = memory",
                                 "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "pragma temp_store = memory"
                 }));
                 }));
 
 
                 string[] queries = {
                 string[] queries = {
@@ -57,9 +56,9 @@ namespace Emby.Server.Implementations.Notifications
         {
         {
             var result = new NotificationResult();
             var result = new NotificationResult();
 
 
-            using (WriteLock.Read())
+            using (var connection = CreateConnection(true))
             {
             {
-                using (var connection = CreateConnection(true))
+                //using (WriteLock.Read())
                 {
                 {
                     var clauses = new List<string>();
                     var clauses = new List<string>();
                     var paramList = new List<object>();
                     var paramList = new List<object>();
@@ -114,7 +113,7 @@ namespace Emby.Server.Implementations.Notifications
 
 
             using (var connection = CreateConnection(true))
             using (var connection = CreateConnection(true))
             {
             {
-                using (WriteLock.Read())
+                //using (WriteLock.Read())
                 {
                 {
                     using (var statement = connection.PrepareStatement("select Level from Notifications where UserId=@UserId and IsRead=@IsRead"))
                     using (var statement = connection.PrepareStatement("select Level from Notifications where UserId=@UserId and IsRead=@IsRead"))
                     {
                     {

+ 2 - 3
Emby.Server.Implementations/Security/AuthenticationRepository.cs

@@ -32,10 +32,9 @@ namespace Emby.Server.Implementations.Security
             {
             {
                 connection.ExecuteAll(string.Join(";", new[]
                 connection.ExecuteAll(string.Join(";", new[]
                 {
                 {
+                                "PRAGMA page_size=4096",
                                 "pragma default_temp_store = memory",
                                 "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "pragma temp_store = memory"
                 }));
                 }));
 
 
                 string[] queries = {
                 string[] queries = {

+ 2 - 3
Emby.Server.Implementations/Social/SharingRepository.cs

@@ -29,10 +29,9 @@ namespace Emby.Server.Implementations.Social
             {
             {
                 connection.ExecuteAll(string.Join(";", new[]
                 connection.ExecuteAll(string.Join(";", new[]
                 {
                 {
+                                "PRAGMA page_size=4096",
                                 "pragma default_temp_store = memory",
                                 "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "pragma temp_store = memory"
                 }));
                 }));
 
 
                 string[] queries = {
                 string[] queries = {

+ 2 - 3
Emby.Server.Implementations/Sync/SyncRepository.cs

@@ -45,10 +45,9 @@ namespace Emby.Server.Implementations.Sync
             {
             {
                 connection.ExecuteAll(string.Join(";", new[]
                 connection.ExecuteAll(string.Join(";", new[]
                 {
                 {
+                                "PRAGMA page_size=4096",
                                 "pragma default_temp_store = memory",
                                 "pragma default_temp_store = memory",
-                                "pragma default_synchronous=Normal",
-                                "pragma temp_store = memory",
-                                "pragma synchronous=Normal",
+                                "pragma temp_store = memory"
                 }));
                 }));
 
 
                 string[] queries = {
                 string[] queries = {

+ 2 - 2
Emby.Server.Implementations/TV/TVSeriesManager.cs

@@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.TV
             return GetResult(episodes, null, request);
             return GetResult(episodes, null, request);
         }
         }
 
 
-        public QueryResult<BaseItem> GetNextUp(NextUpQuery request, IEnumerable<Folder> parentsFolders)
+        public QueryResult<BaseItem> GetNextUp(NextUpQuery request, List<Folder> parentsFolders)
         {
         {
             var user = _userManager.GetUserById(request.UserId);
             var user = _userManager.GetUserById(request.UserId);
 
 
@@ -106,7 +106,7 @@ namespace Emby.Server.Implementations.TV
                 PresentationUniqueKey = presentationUniqueKey,
                 PresentationUniqueKey = presentationUniqueKey,
                 Limit = limit
                 Limit = limit
 
 
-            }, parentsFolders.Select(i => i.Id.ToString("N"))).Cast<Series>();
+            }, parentsFolders.Cast<BaseItem>().ToList()).Cast<Series>();
 
 
             // Avoid implicitly captured closure
             // Avoid implicitly captured closure
             var episodes = GetNextUpEpisodes(request, user, items);
             var episodes = GetNextUpEpisodes(request, user, items);

+ 1 - 1
MediaBrowser.Api/Library/LibraryService.cs

@@ -369,7 +369,7 @@ namespace MediaBrowser.Api.Library
 
 
             if (item is Movie || (program != null && program.IsMovie) || item is Trailer)
             if (item is Movie || (program != null && program.IsMovie) || item is Trailer)
             {
             {
-                return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _config, _authContext)
+                return new MoviesService(_userManager, _libraryManager, _dtoService, _config, _authContext)
                 {
                 {
                     Request = Request,
                     Request = Request,
 
 

+ 1 - 16
MediaBrowser.Api/Movies/MoviesService.cs

@@ -78,16 +78,8 @@ namespace MediaBrowser.Api.Movies
         /// </summary>
         /// </summary>
         private readonly IUserManager _userManager;
         private readonly IUserManager _userManager;
 
 
-        /// <summary>
-        /// The _user data repository
-        /// </summary>
-        private readonly IUserDataManager _userDataRepository;
-        /// <summary>
-        /// The _library manager
-        /// </summary>
         private readonly ILibraryManager _libraryManager;
         private readonly ILibraryManager _libraryManager;
 
 
-        private readonly IItemRepository _itemRepo;
         private readonly IDtoService _dtoService;
         private readonly IDtoService _dtoService;
         private readonly IServerConfigurationManager _config;
         private readonly IServerConfigurationManager _config;
         private readonly IAuthorizationContext _authContext;
         private readonly IAuthorizationContext _authContext;
@@ -95,17 +87,10 @@ namespace MediaBrowser.Api.Movies
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="MoviesService" /> class.
         /// Initializes a new instance of the <see cref="MoviesService" /> class.
         /// </summary>
         /// </summary>
-        /// <param name="userManager">The user manager.</param>
-        /// <param name="userDataRepository">The user data repository.</param>
-        /// <param name="libraryManager">The library manager.</param>
-        /// <param name="itemRepo">The item repo.</param>
-        /// <param name="dtoService">The dto service.</param>
-        public MoviesService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IServerConfigurationManager config, IAuthorizationContext authContext)
+        public MoviesService(IUserManager userManager, ILibraryManager libraryManager, IDtoService dtoService, IServerConfigurationManager config, IAuthorizationContext authContext)
         {
         {
             _userManager = userManager;
             _userManager = userManager;
-            _userDataRepository = userDataRepository;
             _libraryManager = libraryManager;
             _libraryManager = libraryManager;
-            _itemRepo = itemRepo;
             _dtoService = dtoService;
             _dtoService = dtoService;
             _config = config;
             _config = config;
             _authContext = authContext;
             _authContext = authContext;

+ 6 - 0
MediaBrowser.Controller/Entities/Audio/Audio.cs

@@ -61,6 +61,12 @@ namespace MediaBrowser.Controller.Entities.Audio
             get { return true; }
             get { return true; }
         }
         }
 
 
+        [IgnoreDataMember]
+        public override bool SupportsInheritedParentImages
+        {
+            get { return true; }
+        }
+
         [IgnoreDataMember]
         [IgnoreDataMember]
         protected override bool SupportsOwnedItems
         protected override bool SupportsOwnedItems
         {
         {

+ 18 - 4
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -1569,6 +1569,12 @@ namespace MediaBrowser.Controller.Entities
             return IsVisibleStandaloneInternal(user, true);
             return IsVisibleStandaloneInternal(user, true);
         }
         }
 
 
+        [IgnoreDataMember]
+        public virtual bool SupportsInheritedParentImages
+        {
+            get { return false; }
+        }
+
         protected bool IsVisibleStandaloneInternal(User user, bool checkFolders)
         protected bool IsVisibleStandaloneInternal(User user, bool checkFolders)
         {
         {
             if (!IsVisible(user))
             if (!IsVisible(user))
@@ -2329,17 +2335,25 @@ namespace MediaBrowser.Controller.Entities
         {
         {
             get
             get
             {
             {
-                if (GetParent() is AggregateFolder || this is BasePluginFolder || this is Channel)
+                if (this is BasePluginFolder || this is Channel)
                 {
                 {
                     return true;
                     return true;
                 }
                 }
 
 
                 var view = this as UserView;
                 var view = this as UserView;
-                if (view != null && string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
+                if (view != null)
                 {
                 {
-                    return true;
+                    if (string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
+                    {
+                        return true;
+                    }
+                    if (string.Equals(view.ViewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase))
+                    {
+                        return true;
+                    }
                 }
                 }
-                if (view != null && string.Equals(view.ViewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase))
+
+                if (GetParent() is AggregateFolder)
                 {
                 {
                     return true;
                     return true;
                 }
                 }

+ 24 - 15
MediaBrowser.Controller/Entities/Folder.cs

@@ -1383,6 +1383,15 @@ namespace MediaBrowser.Controller.Entities
                 {
                 {
                     return false;
                     return false;
                 }
                 }
+                var iItemByName = this as IItemByName;
+                if (iItemByName != null)
+                {
+                    var hasDualAccess = this as IHasDualAccess;
+                    if (hasDualAccess == null || hasDualAccess.IsAccessedByName)
+                    {
+                        return false;
+                    }
+                }
 
 
                 return true;
                 return true;
             }
             }
@@ -1395,17 +1404,6 @@ namespace MediaBrowser.Controller.Entities
                 return;
                 return;
             }
             }
 
 
-            var unplayedQueryResult = await GetItems(new InternalItemsQuery(user)
-            {
-                Recursive = true,
-                IsFolder = false,
-                IsVirtualItem = false,
-                EnableTotalRecordCount = true,
-                Limit = 0,
-                IsPlayed = false
-
-            }).ConfigureAwait(false);
-
             var allItemsQueryResult = await GetItems(new InternalItemsQuery(user)
             var allItemsQueryResult = await GetItems(new InternalItemsQuery(user)
             {
             {
                 Recursive = true,
                 Recursive = true,
@@ -1415,17 +1413,28 @@ namespace MediaBrowser.Controller.Entities
                 Limit = 0
                 Limit = 0
 
 
             }).ConfigureAwait(false);
             }).ConfigureAwait(false);
+            var recursiveItemCount = allItemsQueryResult.TotalRecordCount;
 
 
             if (itemDto != null)
             if (itemDto != null)
             {
             {
                 itemDto.RecursiveItemCount = allItemsQueryResult.TotalRecordCount;
                 itemDto.RecursiveItemCount = allItemsQueryResult.TotalRecordCount;
             }
             }
 
 
-            var recursiveItemCount = allItemsQueryResult.TotalRecordCount;
-            double unplayedCount = unplayedQueryResult.TotalRecordCount;
-
-            if (recursiveItemCount > 0)
+            if (recursiveItemCount > 0 && SupportsPlayedStatus)
             {
             {
+                var unplayedQueryResult = recursiveItemCount > 0 ? await GetItems(new InternalItemsQuery(user)
+                {
+                    Recursive = true,
+                    IsFolder = false,
+                    IsVirtualItem = false,
+                    EnableTotalRecordCount = true,
+                    Limit = 0,
+                    IsPlayed = false
+
+                }).ConfigureAwait(false) : new QueryResult<BaseItem>();
+
+                double unplayedCount = unplayedQueryResult.TotalRecordCount;
+
                 var unplayedPercentage = (unplayedCount / recursiveItemCount) * 100;
                 var unplayedPercentage = (unplayedCount / recursiveItemCount) * 100;
                 dto.PlayedPercentage = 100 - unplayedPercentage;
                 dto.PlayedPercentage = 100 - unplayedPercentage;
                 dto.Played = dto.PlayedPercentage.Value >= 100;
                 dto.Played = dto.PlayedPercentage.Value >= 100;

+ 0 - 1
MediaBrowser.Controller/Entities/InternalItemsQuery.cs

@@ -124,7 +124,6 @@ namespace MediaBrowser.Controller.Entities
         public int? MaxParentalRating { get; set; }
         public int? MaxParentalRating { get; set; }
 
 
         public bool? HasDeadParentId { get; set; }
         public bool? HasDeadParentId { get; set; }
-        public bool? IsOffline { get; set; }
         public bool? IsVirtualItem { get; set; }
         public bool? IsVirtualItem { get; set; }
 
 
         public Guid? ParentId { get; set; }
         public Guid? ParentId { get; set; }

+ 6 - 0
MediaBrowser.Controller/Entities/TV/Episode.cs

@@ -71,6 +71,12 @@ namespace MediaBrowser.Controller.Entities.TV
             {
             {
                 return IsStacked || MediaSourceCount > 1;
                 return IsStacked || MediaSourceCount > 1;
             }
             }
+        }
+
+        [IgnoreDataMember]
+        public override bool SupportsInheritedParentImages
+        {
+            get { return true; }
         }
         }
 
 
         [IgnoreDataMember]
         [IgnoreDataMember]

+ 6 - 0
MediaBrowser.Controller/Entities/TV/Season.cs

@@ -39,6 +39,12 @@ namespace MediaBrowser.Controller.Entities.TV
             }
             }
         }
         }
 
 
+        [IgnoreDataMember]
+        public override bool SupportsInheritedParentImages
+        {
+            get { return true; }
+        }
+
         [IgnoreDataMember]
         [IgnoreDataMember]
         public override Guid? DisplayParentId
         public override Guid? DisplayParentId
         {
         {

+ 0 - 1
MediaBrowser.Controller/Entities/TV/Series.cs

@@ -135,7 +135,6 @@ namespace MediaBrowser.Controller.Entities.TV
             {
             {
                 AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this),
                 AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this),
                 IncludeItemTypes = new[] { typeof(Season).Name },
                 IncludeItemTypes = new[] { typeof(Season).Name },
-                SortBy = new[] { ItemSortBy.SortName },
                 IsVirtualItem = false,
                 IsVirtualItem = false,
                 Limit = 0
                 Limit = 0
             });
             });

+ 5 - 5
MediaBrowser.Controller/Entities/UserViewBuilder.cs

@@ -1812,7 +1812,7 @@ namespace MediaBrowser.Controller.Entities
                 .Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i));
                 .Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i));
         }
         }
 
 
-        private IEnumerable<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes)
+        private List<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes)
         {
         {
             if (user == null)
             if (user == null)
             {
             {
@@ -1822,7 +1822,7 @@ namespace MediaBrowser.Controller.Entities
                         var folder = i as ICollectionFolder;
                         var folder = i as ICollectionFolder;
 
 
                         return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
                         return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
-                    });
+                    }).ToList();
             }
             }
             return GetMediaFolders(user)
             return GetMediaFolders(user)
                 .Where(i =>
                 .Where(i =>
@@ -1830,17 +1830,17 @@ namespace MediaBrowser.Controller.Entities
                     var folder = i as ICollectionFolder;
                     var folder = i as ICollectionFolder;
 
 
                     return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
                     return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
-                });
+                }).ToList();
         }
         }
 
 
-        private IEnumerable<Folder> GetMediaFolders(Folder parent, User user, IEnumerable<string> viewTypes)
+        private List<Folder> GetMediaFolders(Folder parent, User user, IEnumerable<string> viewTypes)
         {
         {
             if (parent == null || parent is UserView)
             if (parent == null || parent is UserView)
             {
             {
                 return GetMediaFolders(user, viewTypes);
                 return GetMediaFolders(user, viewTypes);
             }
             }
 
 
-            return new[] { parent };
+            return new List<Folder> { parent };
         }
         }
 
 
         private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, IEnumerable<string> viewTypes)
         private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, IEnumerable<string> viewTypes)

+ 1 - 4
MediaBrowser.Controller/Library/ILibraryManager.cs

@@ -538,10 +538,7 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// <summary>
         /// Gets the items.
         /// Gets the items.
         /// </summary>
         /// </summary>
-        /// <param name="query">The query.</param>
-        /// <param name="parentIds">The parent ids.</param>
-        /// <returns>List&lt;BaseItem&gt;.</returns>
-        IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, IEnumerable<string> parentIds);
+        IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents);
 
 
         /// <summary>
         /// <summary>
         /// Gets the items result.
         /// Gets the items result.

+ 1 - 1
MediaBrowser.Controller/TV/ITVSeriesManager.cs

@@ -19,6 +19,6 @@ namespace MediaBrowser.Controller.TV
         /// <param name="request">The request.</param>
         /// <param name="request">The request.</param>
         /// <param name="parentsFolders">The parents folders.</param>
         /// <param name="parentsFolders">The parents folders.</param>
         /// <returns>QueryResult&lt;BaseItem&gt;.</returns>
         /// <returns>QueryResult&lt;BaseItem&gt;.</returns>
-        QueryResult<BaseItem> GetNextUp(NextUpQuery request, IEnumerable<Folder> parentsFolders);
+        QueryResult<BaseItem> GetNextUp(NextUpQuery request, List<Folder> parentsFolders);
     }
     }
 }
 }

+ 1 - 0
MediaBrowser.Model/System/IEnvironmentInfo.cs

@@ -14,6 +14,7 @@ namespace MediaBrowser.Model.System
         Architecture SystemArchitecture { get; }
         Architecture SystemArchitecture { get; }
         string GetEnvironmentVariable(string name);
         string GetEnvironmentVariable(string name);
         string GetUserId();
         string GetUserId();
+        string StackTrace { get; }
     }
     }
 
 
     public enum OperatingSystem
     public enum OperatingSystem

+ 8 - 6
MediaBrowser.Providers/Manager/MetadataService.cs

@@ -536,7 +536,7 @@ namespace MediaBrowser.Providers.Manager
                         refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport;
                         refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport;
 
 
                         // Only one local provider allowed per item
                         // Only one local provider allowed per item
-                        if (item.IsLocked || IsFullLocalMetadata(localItem.Item))
+                        if (item.IsLocked || localItem.Item.IsLocked || IsFullLocalMetadata(localItem.Item))
                         {
                         {
                             hasLocalMetadata = true;
                             hasLocalMetadata = true;
                         }
                         }
@@ -573,14 +573,16 @@ namespace MediaBrowser.Providers.Manager
             {
             {
                 if (refreshResult.UpdateType > ItemUpdateType.None)
                 if (refreshResult.UpdateType > ItemUpdateType.None)
                 {
                 {
-                    // If no local metadata, take data from item itself
-                    if (!hasLocalMetadata)
+                    if (hasLocalMetadata)
+                    {
+                        MergeData(temp, metadata, item.LockedFields, true, true);
+                    }
+                    else
                     {
                     {
                         // TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields
                         // TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields
-                        MergeData(metadata, temp, new List<MetadataFields>(), false, true);
+                        MergeData(metadata, temp, new List<MetadataFields>(), false, false);
+                        MergeData(temp, metadata, item.LockedFields, true, false);
                     }
                     }
-
-                    MergeData(temp, metadata, item.LockedFields, true, true);
                 }
                 }
             }
             }