aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations')
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs10
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs10
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj4
-rw-r--r--MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs353
-rw-r--r--MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs292
-rw-r--r--MediaBrowser.Server.Implementations/TV/SeriesPostScanTask.cs238
-rw-r--r--MediaBrowser.Server.Implementations/Threading/PeriodicTimer.cs72
7 files changed, 12 insertions, 967 deletions
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
index 769b7821a..565eeb259 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
@@ -14,13 +14,13 @@ using System.Threading.Tasks;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO;
-using MediaBrowser.Server.Implementations.Threading;
+using MediaBrowser.Model.Threading;
namespace MediaBrowser.Server.Implementations.Connect
{
public class ConnectEntryPoint : IServerEntryPoint
{
- private PeriodicTimer _timer;
+ private ITimer _timer;
private readonly IHttpClient _httpClient;
private readonly IApplicationPaths _appPaths;
private readonly ILogger _logger;
@@ -29,8 +29,9 @@ namespace MediaBrowser.Server.Implementations.Connect
private readonly INetworkManager _networkManager;
private readonly IApplicationHost _appHost;
private readonly IFileSystem _fileSystem;
+ private readonly ITimerFactory _timerFactory;
- public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem)
+ public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem, ITimerFactory timerFactory)
{
_httpClient = httpClient;
_appPaths = appPaths;
@@ -39,13 +40,14 @@ namespace MediaBrowser.Server.Implementations.Connect
_connectManager = connectManager;
_appHost = appHost;
_fileSystem = fileSystem;
+ _timerFactory = timerFactory;
}
public void Run()
{
LoadCachedAddress();
- _timer = new PeriodicTimer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(1));
+ _timer = _timerFactory.Create(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(1));
((ConnectManager)_connectManager).Start();
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
index d86990a40..dcfa27cc0 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
@@ -11,7 +11,7 @@ using System.Net;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Events;
-using MediaBrowser.Server.Implementations.Threading;
+using MediaBrowser.Model.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
{
@@ -23,16 +23,18 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly IServerConfigurationManager _config;
private readonly IDeviceDiscovery _deviceDiscovery;
- private PeriodicTimer _timer;
+ private ITimer _timer;
private bool _isStarted;
+ private readonly ITimerFactory _timerFactory;
- public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient)
+ public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, ITimerFactory timerFactory)
{
_logger = logmanager.GetLogger("PortMapper");
_appHost = appHost;
_config = config;
_deviceDiscovery = deviceDiscovery;
_httpClient = httpClient;
+ _timerFactory = timerFactory;
}
private string _lastConfigIdentifier;
@@ -94,7 +96,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
NatUtility.StartDiscovery();
- _timer = new PeriodicTimer(ClearCreatedRules, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
+ _timer = _timerFactory.Create(ClearCreatedRules, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
_deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered;
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 5d1d2fc38..adc5d6879 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -207,8 +207,6 @@
<Compile Include="Serialization\JsonSerializer.cs" />
<Compile Include="Social\SharingManager.cs" />
<Compile Include="Social\SharingRepository.cs" />
- <Compile Include="Threading\PeriodicTimer.cs" />
- <Compile Include="TV\SeriesPostScanTask.cs" />
<Compile Include="Persistence\SqliteFileOrganizationRepository.cs" />
<Compile Include="Notifications\SqliteNotificationsRepository.cs" />
<Compile Include="Persistence\TypeMapper.cs" />
@@ -217,8 +215,6 @@
<Compile Include="Security\AuthenticationRepository.cs" />
<Compile Include="Security\EncryptionManager.cs" />
<Compile Include="ServerApplicationPaths.cs" />
- <Compile Include="ServerManager\ServerManager.cs" />
- <Compile Include="ServerManager\WebSocketConnection.cs" />
<Compile Include="Session\HttpSessionController.cs" />
<Compile Include="Session\SessionManager.cs">
<SubType>Code</SubType>
diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
deleted file mode 100644
index 4e706324f..000000000
--- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
+++ /dev/null
@@ -1,353 +0,0 @@
-using MediaBrowser.Common.Events;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Net;
-using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Linq;
-using System.Net.Sockets;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Services;
-
-namespace MediaBrowser.Server.Implementations.ServerManager
-{
- /// <summary>
- /// Manages the Http Server, Udp Server and WebSocket connections
- /// </summary>
- public class ServerManager : IServerManager
- {
- /// <summary>
- /// Both the Ui and server will have a built-in HttpServer.
- /// People will inevitably want remote control apps so it's needed in the Ui too.
- /// </summary>
- /// <value>The HTTP server.</value>
- private IHttpServer HttpServer { get; set; }
-
- /// <summary>
- /// Gets or sets the json serializer.
- /// </summary>
- /// <value>The json serializer.</value>
- private readonly IJsonSerializer _jsonSerializer;
-
- /// <summary>
- /// The web socket connections
- /// </summary>
- private readonly List<IWebSocketConnection> _webSocketConnections = new List<IWebSocketConnection>();
- /// <summary>
- /// Gets the web socket connections.
- /// </summary>
- /// <value>The web socket connections.</value>
- public IEnumerable<IWebSocketConnection> WebSocketConnections
- {
- get { return _webSocketConnections; }
- }
-
- public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
-
- /// <summary>
- /// The _logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// The _application host
- /// </summary>
- private readonly IServerApplicationHost _applicationHost;
-
- /// <summary>
- /// Gets or sets the configuration manager.
- /// </summary>
- /// <value>The configuration manager.</value>
- private IServerConfigurationManager ConfigurationManager { get; set; }
-
- /// <summary>
- /// Gets the web socket listeners.
- /// </summary>
- /// <value>The web socket listeners.</value>
- private readonly List<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>();
-
- private bool _disposed;
- private readonly IMemoryStreamProvider _memoryStreamProvider;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ServerManager" /> class.
- /// </summary>
- /// <param name="applicationHost">The application host.</param>
- /// <param name="jsonSerializer">The json serializer.</param>
- /// <param name="logger">The logger.</param>
- /// <param name="configurationManager">The configuration manager.</param>
- /// <exception cref="System.ArgumentNullException">applicationHost</exception>
- public ServerManager(IServerApplicationHost applicationHost, IJsonSerializer jsonSerializer, ILogger logger, IServerConfigurationManager configurationManager, IMemoryStreamProvider memoryStreamProvider)
- {
- if (applicationHost == null)
- {
- throw new ArgumentNullException("applicationHost");
- }
- if (jsonSerializer == null)
- {
- throw new ArgumentNullException("jsonSerializer");
- }
- if (logger == null)
- {
- throw new ArgumentNullException("logger");
- }
-
- _logger = logger;
- _jsonSerializer = jsonSerializer;
- _applicationHost = applicationHost;
- ConfigurationManager = configurationManager;
- _memoryStreamProvider = memoryStreamProvider;
- }
-
- /// <summary>
- /// Starts this instance.
- /// </summary>
- public void Start(IEnumerable<string> urlPrefixes, string certificatePath)
- {
- ReloadHttpServer(urlPrefixes, certificatePath);
- }
-
- /// <summary>
- /// Restarts the Http Server, or starts it if not currently running
- /// </summary>
- private void ReloadHttpServer(IEnumerable<string> urlPrefixes, string certificatePath)
- {
- _logger.Info("Loading Http Server");
-
- try
- {
- HttpServer = _applicationHost.Resolve<IHttpServer>();
- HttpServer.StartServer(urlPrefixes, certificatePath);
- }
- catch (SocketException ex)
- {
- _logger.ErrorException("The http server is unable to start due to a Socket error. This can occasionally happen when the operating system takes longer than usual to release the IP bindings from the previous session. This can take up to five minutes. Please try waiting or rebooting the system.", ex);
-
- throw;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error starting Http Server", ex);
-
- throw;
- }
-
- HttpServer.WebSocketConnected += HttpServer_WebSocketConnected;
- }
-
- /// <summary>
- /// Handles the WebSocketConnected event of the HttpServer control.
- /// </summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="WebSocketConnectEventArgs" /> instance containing the event data.</param>
- void HttpServer_WebSocketConnected(object sender, WebSocketConnectEventArgs e)
- {
- if (_disposed)
- {
- return;
- }
-
- var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger, _memoryStreamProvider)
- {
- OnReceive = ProcessWebSocketMessageReceived,
- Url = e.Url,
- QueryString = e.QueryString ?? new QueryParamCollection()
- };
-
- _webSocketConnections.Add(connection);
-
- if (WebSocketConnected != null)
- {
- EventHelper.FireEventIfNotNull(WebSocketConnected, this, new GenericEventArgs<IWebSocketConnection> (connection), _logger);
- }
- }
-
- /// <summary>
- /// Processes the web socket message received.
- /// </summary>
- /// <param name="result">The result.</param>
- private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
- {
- if (_disposed)
- {
- return;
- }
-
- //_logger.Debug("Websocket message received: {0}", result.MessageType);
-
- var tasks = _webSocketListeners.Select(i => Task.Run(async () =>
- {
- try
- {
- await i.ProcessMessage(result).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("{0} failed processing WebSocket message {1}", ex, i.GetType().Name, result.MessageType ?? string.Empty);
- }
- }));
-
- await Task.WhenAll(tasks).ConfigureAwait(false);
- }
-
- /// <summary>
- /// Sends a message to all clients currently connected via a web socket
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="messageType">Type of the message.</param>
- /// <param name="data">The data.</param>
- /// <returns>Task.</returns>
- public void SendWebSocketMessage<T>(string messageType, T data)
- {
- SendWebSocketMessage(messageType, () => data);
- }
-
- /// <summary>
- /// Sends a message to all clients currently connected via a web socket
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="messageType">Type of the message.</param>
- /// <param name="dataFunction">The function that generates the data to send, if there are any connected clients</param>
- public void SendWebSocketMessage<T>(string messageType, Func<T> dataFunction)
- {
- SendWebSocketMessageAsync(messageType, dataFunction, CancellationToken.None);
- }
-
- /// <summary>
- /// Sends a message to all clients currently connected via a web socket
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="messageType">Type of the message.</param>
- /// <param name="dataFunction">The function that generates the data to send, if there are any connected clients</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">messageType</exception>
- public Task SendWebSocketMessageAsync<T>(string messageType, Func<T> dataFunction, CancellationToken cancellationToken)
- {
- return SendWebSocketMessageAsync(messageType, dataFunction, _webSocketConnections, cancellationToken);
- }
-
- /// <summary>
- /// Sends the web socket message async.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="messageType">Type of the message.</param>
- /// <param name="dataFunction">The data function.</param>
- /// <param name="connections">The connections.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">messageType
- /// or
- /// dataFunction
- /// or
- /// cancellationToken</exception>
- private async Task SendWebSocketMessageAsync<T>(string messageType, Func<T> dataFunction, IEnumerable<IWebSocketConnection> connections, CancellationToken cancellationToken)
- {
- if (string.IsNullOrEmpty(messageType))
- {
- throw new ArgumentNullException("messageType");
- }
-
- if (dataFunction == null)
- {
- throw new ArgumentNullException("dataFunction");
- }
-
- if (_disposed)
- {
- throw new ObjectDisposedException(GetType().Name);
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- var connectionsList = connections.Where(s => s.State == WebSocketState.Open).ToList();
-
- if (connectionsList.Count > 0)
- {
- _logger.Info("Sending web socket message {0}", messageType);
-
- var message = new WebSocketMessage<T> { MessageType = messageType, Data = dataFunction() };
- var json = _jsonSerializer.SerializeToString(message);
-
- var tasks = connectionsList.Select(s => Task.Run(() =>
- {
- try
- {
- s.SendAsync(json, cancellationToken);
- }
- catch (OperationCanceledException)
- {
- throw;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error sending web socket message {0} to {1}", ex, messageType, s.RemoteEndPoint);
- }
-
- }, cancellationToken));
-
- await Task.WhenAll(tasks).ConfigureAwait(false);
- }
- }
-
- /// <summary>
- /// Disposes the current HttpServer
- /// </summary>
- private void DisposeHttpServer()
- {
- foreach (var socket in _webSocketConnections)
- {
- // Dispose the connection
- socket.Dispose();
- }
-
- _webSocketConnections.Clear();
-
- if (HttpServer != null)
- {
- HttpServer.WebSocketConnected -= HttpServer_WebSocketConnected;
- HttpServer.Dispose();
- }
- }
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- _disposed = true;
-
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources.
- /// </summary>
- /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool dispose)
- {
- if (dispose)
- {
- DisposeHttpServer();
- }
- }
-
- /// <summary>
- /// Adds the web socket listeners.
- /// </summary>
- /// <param name="listeners">The listeners.</param>
- public void AddWebSocketListeners(IEnumerable<IWebSocketListener> listeners)
- {
- _webSocketListeners.AddRange(listeners);
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
deleted file mode 100644
index c1bd8ed6b..000000000
--- a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
+++ /dev/null
@@ -1,292 +0,0 @@
-using System.Text;
-using MediaBrowser.Common.Events;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Net;
-using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Specialized;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Services;
-using UniversalDetector;
-
-namespace MediaBrowser.Server.Implementations.ServerManager
-{
- /// <summary>
- /// Class WebSocketConnection
- /// </summary>
- public class WebSocketConnection : IWebSocketConnection
- {
- public event EventHandler<EventArgs> Closed;
-
- /// <summary>
- /// The _socket
- /// </summary>
- private readonly IWebSocket _socket;
-
- /// <summary>
- /// The _remote end point
- /// </summary>
- public string RemoteEndPoint { get; private set; }
-
- /// <summary>
- /// The _cancellation token source
- /// </summary>
- private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
-
- /// <summary>
- /// The logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// The _json serializer
- /// </summary>
- private readonly IJsonSerializer _jsonSerializer;
-
- /// <summary>
- /// Gets or sets the receive action.
- /// </summary>
- /// <value>The receive action.</value>
- public Action<WebSocketMessageInfo> OnReceive { get; set; }
-
- /// <summary>
- /// Gets the last activity date.
- /// </summary>
- /// <value>The last activity date.</value>
- public DateTime LastActivityDate { get; private set; }
-
- /// <summary>
- /// Gets the id.
- /// </summary>
- /// <value>The id.</value>
- public Guid Id { get; private set; }
-
- /// <summary>
- /// Gets or sets the URL.
- /// </summary>
- /// <value>The URL.</value>
- public string Url { get; set; }
- /// <summary>
- /// Gets or sets the query string.
- /// </summary>
- /// <value>The query string.</value>
- public QueryParamCollection QueryString { get; set; }
- private readonly IMemoryStreamProvider _memoryStreamProvider;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
- /// </summary>
- /// <param name="socket">The socket.</param>
- /// <param name="remoteEndPoint">The remote end point.</param>
- /// <param name="jsonSerializer">The json serializer.</param>
- /// <param name="logger">The logger.</param>
- /// <exception cref="System.ArgumentNullException">socket</exception>
- public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger, IMemoryStreamProvider memoryStreamProvider)
- {
- if (socket == null)
- {
- throw new ArgumentNullException("socket");
- }
- if (string.IsNullOrEmpty(remoteEndPoint))
- {
- throw new ArgumentNullException("remoteEndPoint");
- }
- if (jsonSerializer == null)
- {
- throw new ArgumentNullException("jsonSerializer");
- }
- if (logger == null)
- {
- throw new ArgumentNullException("logger");
- }
-
- Id = Guid.NewGuid();
- _jsonSerializer = jsonSerializer;
- _socket = socket;
- _socket.OnReceiveBytes = OnReceiveInternal;
- _socket.OnReceive = OnReceiveInternal;
- RemoteEndPoint = remoteEndPoint;
- _logger = logger;
- _memoryStreamProvider = memoryStreamProvider;
-
- socket.Closed += socket_Closed;
- }
-
- void socket_Closed(object sender, EventArgs e)
- {
- EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
- }
-
- /// <summary>
- /// Called when [receive].
- /// </summary>
- /// <param name="bytes">The bytes.</param>
- private void OnReceiveInternal(byte[] bytes)
- {
- LastActivityDate = DateTime.UtcNow;
-
- if (OnReceive == null)
- {
- return;
- }
- var charset = DetectCharset(bytes);
-
- if (string.Equals(charset, "utf-8", StringComparison.OrdinalIgnoreCase))
- {
- OnReceiveInternal(Encoding.UTF8.GetString(bytes));
- }
- else
- {
- OnReceiveInternal(Encoding.ASCII.GetString(bytes));
- }
- }
- private string DetectCharset(byte[] bytes)
- {
- try
- {
- using (var ms = _memoryStreamProvider.CreateNew(bytes))
- {
- var detector = new CharsetDetector();
- detector.Feed(ms);
- detector.DataEnd();
-
- var charset = detector.Charset;
-
- if (!string.IsNullOrWhiteSpace(charset))
- {
- //_logger.Debug("UniversalDetector detected charset {0}", charset);
- }
-
- return charset;
- }
- }
- catch (IOException ex)
- {
- _logger.ErrorException("Error attempting to determine web socket message charset", ex);
- }
-
- return null;
- }
-
- private void OnReceiveInternal(string message)
- {
- LastActivityDate = DateTime.UtcNow;
-
- if (!message.StartsWith("{", StringComparison.OrdinalIgnoreCase))
- {
- // This info is useful sometimes but also clogs up the log
- //_logger.Error("Received web socket message that is not a json structure: " + message);
- return;
- }
-
- if (OnReceive == null)
- {
- return;
- }
-
- try
- {
- var stub = (WebSocketMessage<object>)_jsonSerializer.DeserializeFromString(message, typeof(WebSocketMessage<object>));
-
- var info = new WebSocketMessageInfo
- {
- MessageType = stub.MessageType,
- Data = stub.Data == null ? null : stub.Data.ToString(),
- Connection = this
- };
-
- OnReceive(info);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error processing web socket message", ex);
- }
- }
-
- /// <summary>
- /// Sends a message asynchronously.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="message">The message.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">message</exception>
- public Task SendAsync<T>(WebSocketMessage<T> message, CancellationToken cancellationToken)
- {
- if (message == null)
- {
- throw new ArgumentNullException("message");
- }
-
- var json = _jsonSerializer.SerializeToString(message);
-
- return SendAsync(json, cancellationToken);
- }
-
- /// <summary>
- /// Sends a message asynchronously.
- /// </summary>
- /// <param name="buffer">The buffer.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- public Task SendAsync(byte[] buffer, CancellationToken cancellationToken)
- {
- if (buffer == null)
- {
- throw new ArgumentNullException("buffer");
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- return _socket.SendAsync(buffer, true, cancellationToken);
- }
-
- public Task SendAsync(string text, CancellationToken cancellationToken)
- {
- if (string.IsNullOrWhiteSpace(text))
- {
- throw new ArgumentNullException("text");
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- return _socket.SendAsync(text, true, cancellationToken);
- }
-
- /// <summary>
- /// Gets the state.
- /// </summary>
- /// <value>The state.</value>
- public WebSocketState State
- {
- get { return _socket.State; }
- }
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources.
- /// </summary>
- /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool dispose)
- {
- if (dispose)
- {
- _cancellationTokenSource.Dispose();
- _socket.Dispose();
- }
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/TV/SeriesPostScanTask.cs b/MediaBrowser.Server.Implementations/TV/SeriesPostScanTask.cs
deleted file mode 100644
index a498dfec3..000000000
--- a/MediaBrowser.Server.Implementations/TV/SeriesPostScanTask.cs
+++ /dev/null
@@ -1,238 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Plugins;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Tasks;
-using MediaBrowser.Model.Xml;
-using MediaBrowser.Providers.TV;
-
-namespace MediaBrowser.Server.Implementations.TV
-{
- class SeriesGroup : List<Series>, IGrouping<string, Series>
- {
- public string Key { get; set; }
- }
-
- class SeriesPostScanTask : ILibraryPostScanTask, IHasOrder
- {
- /// <summary>
- /// The _library manager
- /// </summary>
- private readonly ILibraryManager _libraryManager;
- private readonly IServerConfigurationManager _config;
- private readonly ILogger _logger;
- private readonly ILocalizationManager _localization;
- private readonly IFileSystem _fileSystem;
- private readonly IXmlReaderSettingsFactory _xmlSettings;
-
- public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, ILocalizationManager localization, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlSettings)
- {
- _libraryManager = libraryManager;
- _logger = logger;
- _config = config;
- _localization = localization;
- _fileSystem = fileSystem;
- _xmlSettings = xmlSettings;
- }
-
- public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
- {
- return RunInternal(progress, cancellationToken);
- }
-
- private Task RunInternal(IProgress<double> progress, CancellationToken cancellationToken)
- {
- var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
- {
- IncludeItemTypes = new[] { typeof(Series).Name },
- Recursive = true,
- GroupByPresentationUniqueKey = false
-
- }).Cast<Series>().ToList();
-
- var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
-
- return new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem, _xmlSettings).Run(seriesGroups, true, cancellationToken);
- }
-
- internal static IEnumerable<IGrouping<string, Series>> FindSeriesGroups(List<Series> seriesList)
- {
- var links = seriesList.ToDictionary(s => s, s => seriesList.Where(c => c != s && ShareProviderId(s, c)).ToList());
-
- var visited = new HashSet<Series>();
-
- foreach (var series in seriesList)
- {
- if (!visited.Contains(series))
- {
- var group = new SeriesGroup();
- FindAllLinked(series, visited, links, group);
-
- group.Key = group.Select(s => s.GetProviderId(MetadataProviders.Tvdb)).FirstOrDefault(id => !string.IsNullOrEmpty(id));
-
- yield return group;
- }
- }
- }
-
- private static void FindAllLinked(Series series, HashSet<Series> visited, IDictionary<Series, List<Series>> linksMap, List<Series> results)
- {
- results.Add(series);
- visited.Add(series);
-
- var links = linksMap[series];
-
- foreach (var s in links)
- {
- if (!visited.Contains(s))
- {
- FindAllLinked(s, visited, linksMap, results);
- }
- }
- }
-
- private static bool ShareProviderId(Series a, Series b)
- {
- return a.ProviderIds.Any(id =>
- {
- string value;
- return b.ProviderIds.TryGetValue(id.Key, out value) && id.Value == value;
- });
- }
-
- public int Order
- {
- get
- {
- // Run after tvdb update task
- return 1;
- }
- }
- }
-
- public class CleanMissingEpisodesEntryPoint : IServerEntryPoint
- {
- private readonly ILibraryManager _libraryManager;
- private readonly IServerConfigurationManager _config;
- private readonly ILogger _logger;
- private readonly ILocalizationManager _localization;
- private readonly IFileSystem _fileSystem;
- private readonly object _libraryChangedSyncLock = new object();
- private const int LibraryUpdateDuration = 180000;
- private readonly ITaskManager _taskManager;
- private readonly IXmlReaderSettingsFactory _xmlSettings;
-
- public CleanMissingEpisodesEntryPoint(ILibraryManager libraryManager, IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, IFileSystem fileSystem, ITaskManager taskManager, IXmlReaderSettingsFactory xmlSettings)
- {
- _libraryManager = libraryManager;
- _config = config;
- _logger = logger;
- _localization = localization;
- _fileSystem = fileSystem;
- _taskManager = taskManager;
- _xmlSettings = xmlSettings;
- }
-
- private Timer LibraryUpdateTimer { get; set; }
-
- public void Run()
- {
- _libraryManager.ItemAdded += _libraryManager_ItemAdded;
- }
-
- private void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
- {
- if (!FilterItem(e.Item))
- {
- return;
- }
-
- lock (_libraryChangedSyncLock)
- {
- if (LibraryUpdateTimer == null)
- {
- LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite);
- }
- else
- {
- LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
- }
- }
- }
-
- private async void LibraryUpdateTimerCallback(object state)
- {
- try
- {
- if (MissingEpisodeProvider.IsRunning)
- {
- return;
- }
-
- if (_libraryManager.IsScanRunning)
- {
- return;
- }
-
- var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
- {
- IncludeItemTypes = new[] { typeof(Series).Name },
- Recursive = true,
- GroupByPresentationUniqueKey = false
-
- }).Cast<Series>().ToList();
-
- var seriesGroups = SeriesPostScanTask.FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
-
- await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem, _xmlSettings)
- .Run(seriesGroups, false, CancellationToken.None).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in SeriesPostScanTask", ex);
- }
- }
-
- private bool FilterItem(BaseItem item)
- {
- return item is Episode && item.LocationType != LocationType.Virtual;
- }
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- }
-
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources.
- /// </summary>
- /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool dispose)
- {
- if (dispose)
- {
- if (LibraryUpdateTimer != null)
- {
- LibraryUpdateTimer.Dispose();
- LibraryUpdateTimer = null;
- }
-
- _libraryManager.ItemAdded -= _libraryManager_ItemAdded;
- }
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/Threading/PeriodicTimer.cs b/MediaBrowser.Server.Implementations/Threading/PeriodicTimer.cs
deleted file mode 100644
index 057a84483..000000000
--- a/MediaBrowser.Server.Implementations/Threading/PeriodicTimer.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using System;
-using System.Threading;
-using Microsoft.Win32;
-
-namespace MediaBrowser.Server.Implementations.Threading
-{
- public class PeriodicTimer : IDisposable
- {
- public Action<object> Callback { get; set; }
- private Timer _timer;
- private readonly object _state;
- private readonly object _timerLock = new object();
- private readonly TimeSpan _period;
-
- public PeriodicTimer(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period)
- {
- if (callback == null)
- {
- throw new ArgumentNullException("callback");
- }
-
- Callback = callback;
- _period = period;
- _state = state;
-
- StartTimer(dueTime);
- }
-
- void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
- {
- if (e.Mode == PowerModes.Resume)
- {
- DisposeTimer();
- StartTimer(Timeout.InfiniteTimeSpan);
- }
- }
-
- private void TimerCallback(object state)
- {
- Callback(state);
- }
-
- private void StartTimer(TimeSpan dueTime)
- {
- lock (_timerLock)
- {
- _timer = new Timer(TimerCallback, _state, dueTime, _period);
-
- SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
- }
- }
-
- private void DisposeTimer()
- {
- SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
-
- lock (_timerLock)
- {
- if (_timer != null)
- {
- _timer.Dispose();
- _timer = null;
- }
- }
- }
-
- public void Dispose()
- {
- DisposeTimer();
- }
- }
-}