diff --git a/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs b/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs
deleted file mode 100644
index 10ff2515cb..0000000000
--- a/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs
+++ /dev/null
@@ -1,402 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-
-//TODO Fix namespace or replace
-namespace Priority_Queue
-{
- ///
- /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
- /// A copy of StablePriorityQueue which also has generic priority-type
- ///
- /// The values in the queue. Must extend the GenericPriorityQueue class
- /// The priority-type. Must extend IComparable<TPriority>
- public sealed class GenericPriorityQueue : IFixedSizePriorityQueue
- where TItem : GenericPriorityQueueNode
- where TPriority : IComparable
- {
- private int _numNodes;
- private TItem[] _nodes;
- private long _numNodesEverEnqueued;
-
- ///
- /// Instantiate a new Priority Queue
- ///
- /// The max nodes ever allowed to be enqueued (going over this will cause undefined behavior)
- public GenericPriorityQueue(int maxNodes)
- {
-#if DEBUG
- if (maxNodes <= 0)
- {
- throw new InvalidOperationException("New queue size cannot be smaller than 1");
- }
-#endif
-
- _numNodes = 0;
- _nodes = new TItem[maxNodes + 1];
- _numNodesEverEnqueued = 0;
- }
-
- ///
- /// Returns the number of nodes in the queue.
- /// O(1)
- ///
- public int Count => _numNodes;
-
- ///
- /// Returns the maximum number of items that can be enqueued at once in this queue. Once you hit this number (ie. once Count == MaxSize),
- /// attempting to enqueue another item will cause undefined behavior. O(1)
- ///
- public int MaxSize => _nodes.Length - 1;
-
- ///
- /// Removes every node from the queue.
- /// O(n) (So, don't do this often!)
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Clear()
- {
- Array.Clear(_nodes, 1, _numNodes);
- _numNodes = 0;
- }
-
- ///
- /// Returns (in O(1)!) whether the given node is in the queue. O(1)
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Contains(TItem node)
- {
-#if DEBUG
- if (node == null)
- {
- throw new ArgumentNullException(nameof(node));
- }
- if (node.QueueIndex < 0 || node.QueueIndex >= _nodes.Length)
- {
- throw new InvalidOperationException("node.QueueIndex has been corrupted. Did you change it manually? Or add this node to another queue?");
- }
-#endif
-
- return (_nodes[node.QueueIndex] == node);
- }
-
- ///
- /// Enqueue a node to the priority queue. Lower values are placed in front. Ties are broken by first-in-first-out.
- /// If the queue is full, the result is undefined.
- /// If the node is already enqueued, the result is undefined.
- /// O(log n)
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Enqueue(TItem node, TPriority priority)
- {
-#if DEBUG
- if (node == null)
- {
- throw new ArgumentNullException(nameof(node));
- }
- if (_numNodes >= _nodes.Length - 1)
- {
- throw new InvalidOperationException("Queue is full - node cannot be added: " + node);
- }
- if (Contains(node))
- {
- throw new InvalidOperationException("Node is already enqueued: " + node);
- }
-#endif
-
- node.Priority = priority;
- _numNodes++;
- _nodes[_numNodes] = node;
- node.QueueIndex = _numNodes;
- node.InsertionIndex = _numNodesEverEnqueued++;
- CascadeUp(_nodes[_numNodes]);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void Swap(TItem node1, TItem node2)
- {
- //Swap the nodes
- _nodes[node1.QueueIndex] = node2;
- _nodes[node2.QueueIndex] = node1;
-
- //Swap their indicies
- int temp = node1.QueueIndex;
- node1.QueueIndex = node2.QueueIndex;
- node2.QueueIndex = temp;
- }
-
- //Performance appears to be slightly better when this is NOT inlined o_O
- private void CascadeUp(TItem node)
- {
- //aka Heapify-up
- int parent = node.QueueIndex / 2;
- while (parent >= 1)
- {
- var parentNode = _nodes[parent];
- if (HasHigherPriority(parentNode, node))
- break;
-
- //Node has lower priority value, so move it up the heap
- Swap(node, parentNode); //For some reason, this is faster with Swap() rather than (less..?) individual operations, like in CascadeDown()
-
- parent = node.QueueIndex / 2;
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void CascadeDown(TItem node)
- {
- //aka Heapify-down
- TItem newParent;
- int finalQueueIndex = node.QueueIndex;
- while (true)
- {
- newParent = node;
- int childLeftIndex = 2 * finalQueueIndex;
-
- //Check if the left-child is higher-priority than the current node
- if (childLeftIndex > _numNodes)
- {
- //This could be placed outside the loop, but then we'd have to check newParent != node twice
- node.QueueIndex = finalQueueIndex;
- _nodes[finalQueueIndex] = node;
- break;
- }
-
- var childLeft = _nodes[childLeftIndex];
- if (HasHigherPriority(childLeft, newParent))
- {
- newParent = childLeft;
- }
-
- //Check if the right-child is higher-priority than either the current node or the left child
- int childRightIndex = childLeftIndex + 1;
- if (childRightIndex <= _numNodes)
- {
- var childRight = _nodes[childRightIndex];
- if (HasHigherPriority(childRight, newParent))
- {
- newParent = childRight;
- }
- }
-
- //If either of the children has higher (smaller) priority, swap and continue cascading
- if (newParent != node)
- {
- //Move new parent to its new index. node will be moved once, at the end
- //Doing it this way is one less assignment operation than calling Swap()
- _nodes[finalQueueIndex] = newParent;
-
- int temp = newParent.QueueIndex;
- newParent.QueueIndex = finalQueueIndex;
- finalQueueIndex = temp;
- }
- else
- {
- //See note above
- node.QueueIndex = finalQueueIndex;
- _nodes[finalQueueIndex] = node;
- break;
- }
- }
- }
-
- ///
- /// Returns true if 'higher' has higher priority than 'lower', false otherwise.
- /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private bool HasHigherPriority(TItem higher, TItem lower)
- {
- var cmp = higher.Priority.CompareTo(lower.Priority);
- return (cmp < 0 || (cmp == 0 && higher.InsertionIndex < lower.InsertionIndex));
- }
-
- ///
- /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
- /// If queue is empty, result is undefined
- /// O(log n)
- ///
- public bool TryDequeue(out TItem item)
- {
- if (_numNodes <= 0)
- {
- item = default(TItem);
- return false;
- }
-
-#if DEBUG
-
- if (!IsValidQueue())
- {
- throw new InvalidOperationException("Queue has been corrupted (Did you update a node priority manually instead of calling UpdatePriority()?" +
- "Or add the same node to two different queues?)");
- }
-#endif
-
- var returnMe = _nodes[1];
- Remove(returnMe);
- item = returnMe;
- return true;
- }
-
- ///
- /// Resize the queue so it can accept more nodes. All currently enqueued nodes are remain.
- /// Attempting to decrease the queue size to a size too small to hold the existing nodes results in undefined behavior
- /// O(n)
- ///
- public void Resize(int maxNodes)
- {
-#if DEBUG
- if (maxNodes <= 0)
- {
- throw new InvalidOperationException("Queue size cannot be smaller than 1");
- }
-
- if (maxNodes < _numNodes)
- {
- throw new InvalidOperationException("Called Resize(" + maxNodes + "), but current queue contains " + _numNodes + " nodes");
- }
-#endif
-
- TItem[] newArray = new TItem[maxNodes + 1];
- int highestIndexToCopy = Math.Min(maxNodes, _numNodes);
- for (int i = 1; i <= highestIndexToCopy; i++)
- {
- newArray[i] = _nodes[i];
- }
- _nodes = newArray;
- }
-
- ///
- /// Returns the head of the queue, without removing it (use Dequeue() for that).
- /// If the queue is empty, behavior is undefined.
- /// O(1)
- ///
- public TItem First
- {
- get
- {
-#if DEBUG
- if (_numNodes <= 0)
- {
- throw new InvalidOperationException("Cannot call .First on an empty queue");
- }
-#endif
-
- return _nodes[1];
- }
- }
-
- ///
- /// This method must be called on a node every time its priority changes while it is in the queue.
- /// Forgetting to call this method will result in a corrupted queue!
- /// Calling this method on a node not in the queue results in undefined behavior
- /// O(log n)
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void UpdatePriority(TItem node, TPriority priority)
- {
-#if DEBUG
- if (node == null)
- {
- throw new ArgumentNullException(nameof(node));
- }
- if (!Contains(node))
- {
- throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + node);
- }
-#endif
-
- node.Priority = priority;
- OnNodeUpdated(node);
- }
-
- private void OnNodeUpdated(TItem node)
- {
- //Bubble the updated node up or down as appropriate
- int parentIndex = node.QueueIndex / 2;
- var parentNode = _nodes[parentIndex];
-
- if (parentIndex > 0 && HasHigherPriority(node, parentNode))
- {
- CascadeUp(node);
- }
- else
- {
- //Note that CascadeDown will be called if parentNode == node (that is, node is the root)
- CascadeDown(node);
- }
- }
-
- ///
- /// Removes a node from the queue. The node does not need to be the head of the queue.
- /// If the node is not in the queue, the result is undefined. If unsure, check Contains() first
- /// O(log n)
- ///
- public void Remove(TItem node)
- {
-#if DEBUG
- if (node == null)
- {
- throw new ArgumentNullException(nameof(node));
- }
- if (!Contains(node))
- {
- throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + node);
- }
-#endif
-
- //If the node is already the last node, we can remove it immediately
- if (node.QueueIndex == _numNodes)
- {
- _nodes[_numNodes] = null;
- _numNodes--;
- return;
- }
-
- //Swap the node with the last node
- var formerLastNode = _nodes[_numNodes];
- Swap(node, formerLastNode);
- _nodes[_numNodes] = null;
- _numNodes--;
-
- //Now bubble formerLastNode (which is no longer the last node) up or down as appropriate
- OnNodeUpdated(formerLastNode);
- }
-
- public IEnumerator GetEnumerator()
- {
- for (int i = 1; i <= _numNodes; i++)
- yield return _nodes[i];
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- ///
- /// Should not be called in production code.
- /// Checks to make sure the queue is still in a valid state. Used for testing/debugging the queue.
- ///
- public bool IsValidQueue()
- {
- for (int i = 1; i < _nodes.Length; i++)
- {
- if (_nodes[i] != null)
- {
- int childLeftIndex = 2 * i;
- if (childLeftIndex < _nodes.Length && _nodes[childLeftIndex] != null && HasHigherPriority(_nodes[childLeftIndex], _nodes[i]))
- return false;
-
- int childRightIndex = childLeftIndex + 1;
- if (childRightIndex < _nodes.Length && _nodes[childRightIndex] != null && HasHigherPriority(_nodes[childRightIndex], _nodes[i]))
- return false;
- }
- }
- return true;
- }
- }
-}
diff --git a/MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs b/MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs
deleted file mode 100644
index b45ae0fd82..0000000000
--- a/MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace Priority_Queue
-{
- /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
- public class GenericPriorityQueueNode
- {
- ///
- /// The Priority to insert this node at. Must be set BEFORE adding a node to the queue (ideally just once, in the node's constructor).
- /// Should not be manually edited once the node has been enqueued - use queue.UpdatePriority() instead
- ///
- public TPriority Priority { get; protected internal set; }
-
- ///
- /// Represents the current position in the queue
- ///
- public int QueueIndex { get; internal set; }
-
- ///
- /// Represents the order the node was inserted in
- ///
- public long InsertionIndex { get; internal set; }
- }
-}
diff --git a/MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs b/MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs
deleted file mode 100644
index 509d98e426..0000000000
--- a/MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-
-namespace Priority_Queue
-{
- ///
- /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
- /// A helper-interface only needed to make writing unit tests a bit easier (hence the 'internal' access modifier)
- ///
- internal interface IFixedSizePriorityQueue : IPriorityQueue
- where TPriority : IComparable
- {
- ///
- /// Resize the queue so it can accept more nodes. All currently enqueued nodes are remain.
- /// Attempting to decrease the queue size to a size too small to hold the existing nodes results in undefined behavior
- ///
- void Resize(int maxNodes);
-
- ///
- /// Returns the maximum number of items that can be enqueued at once in this queue. Once you hit this number (ie. once Count == MaxSize),
- /// attempting to enqueue another item will cause undefined behavior.
- ///
- int MaxSize { get; }
- }
-}
diff --git a/MediaBrowser.Providers/Manager/IPriorityQueue.cs b/MediaBrowser.Providers/Manager/IPriorityQueue.cs
deleted file mode 100644
index dc319a7f8d..0000000000
--- a/MediaBrowser.Providers/Manager/IPriorityQueue.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Priority_Queue
-{
- ///
- /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
- /// The IPriorityQueue interface. This is mainly here for purists, and in case I decide to add more implementations later.
- /// For speed purposes, it is actually recommended that you *don't* access the priority queue through this interface, since the JIT can
- /// (theoretically?) optimize method calls from concrete-types slightly better.
- ///
- public interface IPriorityQueue : IEnumerable
- where TPriority : IComparable
- {
- ///
- /// Enqueue a node to the priority queue. Lower values are placed in front. Ties are broken by first-in-first-out.
- /// See implementation for how duplicates are handled.
- ///
- void Enqueue(TItem node, TPriority priority);
-
- ///
- /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
- ///
- bool TryDequeue(out TItem item);
-
- ///
- /// Removes every node from the queue.
- ///
- void Clear();
-
- ///
- /// Returns whether the given node is in the queue.
- ///
- bool Contains(TItem node);
-
- ///
- /// Removes a node from the queue. The node does not need to be the head of the queue.
- ///
- void Remove(TItem node);
-
- ///
- /// Call this method to change the priority of a node.
- ///
- void UpdatePriority(TItem node, TPriority priority);
-
- ///
- /// Returns the head of the queue, without removing it (use Dequeue() for that).
- ///
- TItem First { get; }
-
- ///
- /// Returns the number of nodes in the queue.
- ///
- int Count { get; }
- }
-}
diff --git a/MediaBrowser.Providers/Manager/SimplePriorityQueue.cs b/MediaBrowser.Providers/Manager/SimplePriorityQueue.cs
deleted file mode 100644
index d064312cfa..0000000000
--- a/MediaBrowser.Providers/Manager/SimplePriorityQueue.cs
+++ /dev/null
@@ -1,247 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace Priority_Queue
-{
- ///
- /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
- /// A simplified priority queue implementation. Is stable, auto-resizes, and thread-safe, at the cost of being slightly slower than
- /// FastPriorityQueue
- ///
- /// The type to enqueue
- /// The priority-type to use for nodes. Must extend IComparable<TPriority>
- public class SimplePriorityQueue : IPriorityQueue
- where TPriority : IComparable
- {
- private class SimpleNode : GenericPriorityQueueNode
- {
- public TItem Data { get; private set; }
-
- public SimpleNode(TItem data)
- {
- Data = data;
- }
- }
-
- private const int INITIAL_QUEUE_SIZE = 10;
- private readonly GenericPriorityQueue _queue;
-
- public SimplePriorityQueue()
- {
- _queue = new GenericPriorityQueue(INITIAL_QUEUE_SIZE);
- }
-
- ///
- /// Given an item of type T, returns the exist SimpleNode in the queue
- ///
- private SimpleNode GetExistingNode(TItem item)
- {
- var comparer = EqualityComparer.Default;
- foreach (var node in _queue)
- {
- if (comparer.Equals(node.Data, item))
- {
- return node;
- }
- }
- throw new InvalidOperationException("Item cannot be found in queue: " + item);
- }
-
- ///
- /// Returns the number of nodes in the queue.
- /// O(1)
- ///
- public int Count
- {
- get
- {
- lock (_queue)
- {
- return _queue.Count;
- }
- }
- }
-
-
- ///
- /// Returns the head of the queue, without removing it (use Dequeue() for that).
- /// Throws an exception when the queue is empty.
- /// O(1)
- ///
- public TItem First
- {
- get
- {
- lock (_queue)
- {
- if (_queue.Count <= 0)
- {
- throw new InvalidOperationException("Cannot call .First on an empty queue");
- }
-
- SimpleNode first = _queue.First;
- return (first != null ? first.Data : default(TItem));
- }
- }
- }
-
- ///
- /// Removes every node from the queue.
- /// O(n)
- ///
- public void Clear()
- {
- lock (_queue)
- {
- _queue.Clear();
- }
- }
-
- ///
- /// Returns whether the given item is in the queue.
- /// O(n)
- ///
- public bool Contains(TItem item)
- {
- lock (_queue)
- {
- var comparer = EqualityComparer.Default;
- foreach (var node in _queue)
- {
- if (comparer.Equals(node.Data, item))
- {
- return true;
- }
- }
- return false;
- }
- }
-
- ///
- /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
- /// If queue is empty, throws an exception
- /// O(log n)
- ///
- public bool TryDequeue(out TItem item)
- {
- lock (_queue)
- {
- if (_queue.Count <= 0)
- {
- item = default(TItem);
- return false;
- }
-
- if (_queue.TryDequeue(out SimpleNode node))
- {
- item = node.Data;
- return true;
- }
-
- item = default(TItem);
- return false;
- }
- }
-
- ///
- /// Enqueue a node to the priority queue. Lower values are placed in front. Ties are broken by first-in-first-out.
- /// This queue automatically resizes itself, so there's no concern of the queue becoming 'full'.
- /// Duplicates are allowed.
- /// O(log n)
- ///
- public void Enqueue(TItem item, TPriority priority)
- {
- lock (_queue)
- {
- var node = new SimpleNode(item);
- if (_queue.Count == _queue.MaxSize)
- {
- _queue.Resize(_queue.MaxSize * 2 + 1);
- }
- _queue.Enqueue(node, priority);
- }
- }
-
- ///
- /// Removes an item from the queue. The item does not need to be the head of the queue.
- /// If the item is not in the queue, an exception is thrown. If unsure, check Contains() first.
- /// If multiple copies of the item are enqueued, only the first one is removed.
- /// O(n)
- ///
- public void Remove(TItem item)
- {
- lock (_queue)
- {
- try
- {
- _queue.Remove(GetExistingNode(item));
- }
- catch (InvalidOperationException ex)
- {
- throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item, ex);
- }
- }
- }
-
- ///
- /// Call this method to change the priority of an item.
- /// Calling this method on a item not in the queue will throw an exception.
- /// If the item is enqueued multiple times, only the first one will be updated.
- /// (If your requirements are complex enough that you need to enqueue the same item multiple times and be able
- /// to update all of them, please wrap your items in a wrapper class so they can be distinguished).
- /// O(n)
- ///
- public void UpdatePriority(TItem item, TPriority priority)
- {
- lock (_queue)
- {
- try
- {
- SimpleNode updateMe = GetExistingNode(item);
- _queue.UpdatePriority(updateMe, priority);
- }
- catch (InvalidOperationException ex)
- {
- throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + item, ex);
- }
- }
- }
-
- public IEnumerator GetEnumerator()
- {
- var queueData = new List();
- lock (_queue)
- {
- //Copy to a separate list because we don't want to 'yield return' inside a lock
- foreach (var node in _queue)
- {
- queueData.Add(node.Data);
- }
- }
-
- return queueData.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- public bool IsValidQueue()
- {
- lock (_queue)
- {
- return _queue.IsValidQueue();
- }
- }
- }
-
- ///
- /// A simplified priority queue implementation. Is stable, auto-resizes, and thread-safe, at the cost of being slightly slower than
- /// FastPriorityQueue
- /// This class is kept here for backwards compatibility. It's recommended you use Simple
- ///
- /// The type to enqueue
- public class SimplePriorityQueue : SimplePriorityQueue { }
-}
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index e6ef889c3e..7b8d629ee6 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -1,4 +1,4 @@
-
+
@@ -11,6 +11,7 @@
+