فهرست منبع

Manage some items as single instance throughout #54

Eric Reed 12 سال پیش
والد
کامیت
c02ac2a8ca

+ 5 - 1
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -24,7 +24,11 @@ namespace MediaBrowser.Controller.Entities
     /// </summary>
     public abstract class BaseItem : IHasProviderIds
     {
-        /// <summary>
+        private Guid _testId = Guid.NewGuid();
+        public Guid TestId
+        {
+            get { return _testId; }
+        }        /// <summary>
         /// The trailer folder name
         /// </summary>
         public const string TrailerFolderName = "trailers";

+ 2 - 1
MediaBrowser.Controller/Entities/BasePluginFolder.cs

@@ -1,5 +1,6 @@
 using MediaBrowser.Common.Extensions;
 using System;
+using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Controller.Entities
 {
@@ -7,7 +8,7 @@ namespace MediaBrowser.Controller.Entities
     /// Plugins derive from and export this class to create a folder that will appear in the root along
     /// with all the other actual physical folders in the system.
     /// </summary>
-    public abstract class BasePluginFolder : Folder, ICollectionFolder
+    public abstract class BasePluginFolder : Folder, ICollectionFolder, IByReferenceItem
     {
         /// <summary>
         /// Gets or sets the id.

+ 2 - 1
MediaBrowser.Controller/Entities/CollectionFolder.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Extensions;
+using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Tasks;
 using System;
 using System.Collections.Concurrent;
@@ -15,7 +16,7 @@ namespace MediaBrowser.Controller.Entities
     /// Specialized Folder class that points to a subset of the physical folders in the system.
     /// It is created from the user-specific folders within the system root
     /// </summary>
-    public class CollectionFolder : Folder, ICollectionFolder
+    public class CollectionFolder : Folder, ICollectionFolder, IByReferenceItem
     {
         /// <summary>
         /// Gets a value indicating whether this instance is virtual folder.

+ 1 - 1
MediaBrowser.Controller/Entities/Folder.cs

@@ -811,7 +811,7 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>IEnumerable{BaseItem}.</returns>
         protected virtual IEnumerable<BaseItem> GetCachedChildren()
         {
-            return Kernel.Instance.ItemRepository.RetrieveChildren(this);
+            return Kernel.Instance.ItemRepository.RetrieveChildren(this).Select(i => i is IByReferenceItem ? LibraryManager.GetOrAddByReferenceItem(i) : i);
         }
 
         /// <summary>

+ 7 - 0
MediaBrowser.Controller/Library/ILibraryManager.cs

@@ -181,5 +181,12 @@ namespace MediaBrowser.Controller.Library
         /// <param name="searchTerm">The search term.</param>
         /// <returns>IEnumerable{BaseItem}.</returns>
         IEnumerable<BaseItem> Search(IEnumerable<BaseItem> items, string searchTerm);
+
+        /// <summary>
+        /// Ensure supplied item has only one instance throughout
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns>The proper instance to the item</returns>
+        BaseItem GetOrAddByReferenceItem(BaseItem item);
     }
 }

+ 16 - 0
MediaBrowser.Model/Entities/IByReferenceItem.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MediaBrowser.Model.Entities
+{
+    /// <summary>
+    /// This is a marker class that tells us that a particular item type may be physically resolved
+    /// more than once within the library and we need to be sure to resolve them all to the same
+    /// instance of that item.
+    /// </summary>
+    public interface IByReferenceItem
+    {
+    }
+}

+ 1 - 0
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -45,6 +45,7 @@
     <Compile Include="Dto\BaseItemPerson.cs" />
     <Compile Include="Dto\ChapterInfoDto.cs" />
     <Compile Include="Dto\IItemDto.cs" />
+    <Compile Include="Entities\IByReferenceItem.cs" />
     <Compile Include="Querying\ItemsByNameQuery.cs" />
     <Compile Include="Entities\BaseItemInfo.cs" />
     <Compile Include="Connectivity\ClientConnectionInfo.cs" />

+ 36 - 4
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -105,6 +105,13 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <value>The configuration manager.</value>
         private IServerConfigurationManager ConfigurationManager { get; set; }
 
+        /// <summary>
+        /// A collection of items that may be referenced from multiple physical places in the library
+        /// (typically, multiple user roots).  We store them here and be sure they all reference a
+        /// single instance.
+        /// </summary>
+        private ConcurrentDictionary<Guid, BaseItem> ByReferenceItems { get; set; } 
+
         /// <summary>
         /// Initializes a new instance of the <see cref="LibraryManager" /> class.
         /// </summary>
@@ -120,6 +127,7 @@ namespace MediaBrowser.Server.Implementations.Library
             _taskManager = taskManager;
             _userManager = userManager;
             ConfigurationManager = configurationManager;
+            ByReferenceItems = new ConcurrentDictionary<Guid, BaseItem>();
 
             ConfigurationManager.ConfigurationUpdated += kernel_ConfigurationUpdated;
 
@@ -232,11 +240,35 @@ namespace MediaBrowser.Server.Implementations.Library
             if (item != null)
             {
                 ResolverHelper.SetInitialItemValues(item, args);
+
+                // Now handle the issue with posibly having the same item referenced from multiple physical
+                // places within the library.  Be sure we always end up with just one instance.
+                if (item is IByReferenceItem)
+                {
+                    item = GetOrAddByReferenceItem(item);
+                }
             }
 
             return item;
         }
 
+
+        /// <summary>
+        /// Ensure supplied item has only one instance throughout
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns>The proper instance to the item</returns>
+        public BaseItem GetOrAddByReferenceItem(BaseItem item)
+        {
+            // Add this item to our list if not there already
+            if (!ByReferenceItems.TryAdd(item.Id, item))
+            {
+                // Already there - return the existing reference
+                item = ByReferenceItems[item.Id];
+            }
+            return item;
+        }
+
         /// <summary>
         /// Resolves a path into a BaseItem
         /// </summary>
@@ -617,10 +649,10 @@ namespace MediaBrowser.Server.Implementations.Library
             // Now validate the entire media library
             await RootFolder.ValidateChildren(progress, cancellationToken, recursive: true).ConfigureAwait(false);
 
-            foreach (var user in _userManager.Users)
-            {
-                await user.ValidateMediaLibrary(new Progress<double> { }, cancellationToken).ConfigureAwait(false);
-            }
+            //foreach (var user in _userManager.Users)
+            //{
+            //    await user.ValidateMediaLibrary(new Progress<double> { }, cancellationToken).ConfigureAwait(false);
+            //}
         }
 
         /// <summary>