mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-06 11:34:57 +02:00
reduce use of timers throughout the system
Conflicts: MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
This commit is contained in:
parent
51899f1880
commit
cfa8f6c6ec
8 changed files with 99 additions and 87 deletions
|
@ -20,6 +20,14 @@ namespace MediaBrowser.Common.Implementations.Networking
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ClearCacheTimerCallback(object state)
|
||||||
|
{
|
||||||
|
lock (_localIpAddressSyncLock)
|
||||||
|
{
|
||||||
|
_localIpAddresses = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private volatile List<IPAddress> _localIpAddresses;
|
private volatile List<IPAddress> _localIpAddresses;
|
||||||
private readonly object _localIpAddressSyncLock = new object();
|
private readonly object _localIpAddressSyncLock = new object();
|
||||||
|
|
||||||
|
@ -29,14 +37,13 @@ namespace MediaBrowser.Common.Implementations.Networking
|
||||||
/// <returns>IPAddress.</returns>
|
/// <returns>IPAddress.</returns>
|
||||||
public IEnumerable<IPAddress> GetLocalIpAddresses()
|
public IEnumerable<IPAddress> GetLocalIpAddresses()
|
||||||
{
|
{
|
||||||
const int cacheMinutes = 3;
|
var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= 1;
|
||||||
var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes;
|
|
||||||
|
|
||||||
if (_localIpAddresses == null || forceRefresh)
|
if (_localIpAddresses == null || forceRefresh)
|
||||||
{
|
{
|
||||||
lock (_localIpAddressSyncLock)
|
lock (_localIpAddressSyncLock)
|
||||||
{
|
{
|
||||||
forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes;
|
forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= 1;
|
||||||
|
|
||||||
if (_localIpAddresses == null || forceRefresh)
|
if (_localIpAddresses == null || forceRefresh)
|
||||||
{
|
{
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
<Compile Include="Security\IRequiresRegistration.cs" />
|
<Compile Include="Security\IRequiresRegistration.cs" />
|
||||||
<Compile Include="Security\ISecurityManager.cs" />
|
<Compile Include="Security\ISecurityManager.cs" />
|
||||||
<Compile Include="Security\PaymentRequiredException.cs" />
|
<Compile Include="Security\PaymentRequiredException.cs" />
|
||||||
|
<Compile Include="Threading\PeriodicTimer.cs" />
|
||||||
<Compile Include="Updates\IInstallationManager.cs" />
|
<Compile Include="Updates\IInstallationManager.cs" />
|
||||||
<Compile Include="Updates\InstallationEventArgs.cs" />
|
<Compile Include="Updates\InstallationEventArgs.cs" />
|
||||||
<Compile Include="Updates\InstallationFailedEventArgs.cs" />
|
<Compile Include="Updates\InstallationFailedEventArgs.cs" />
|
||||||
|
|
67
MediaBrowser.Common/Threading/PeriodicTimer.cs
Normal file
67
MediaBrowser.Common/Threading/PeriodicTimer.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Common.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)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,7 @@ namespace MediaBrowser.Providers.People
|
||||||
|
|
||||||
private int _requestCount;
|
private int _requestCount;
|
||||||
private readonly object _requestCountLock = new object();
|
private readonly object _requestCountLock = new object();
|
||||||
private Timer _requestCountReset;
|
private DateTime _lastRequestCountReset;
|
||||||
|
|
||||||
public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger)
|
public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger)
|
||||||
{
|
{
|
||||||
|
@ -48,16 +48,6 @@ namespace MediaBrowser.Providers.People
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
Current = this;
|
Current = this;
|
||||||
|
|
||||||
_requestCountReset = new Timer(OnRequestThrottleTimerFired, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRequestThrottleTimerFired(object state)
|
|
||||||
{
|
|
||||||
lock (_requestCountLock)
|
|
||||||
{
|
|
||||||
_requestCount = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
|
@ -101,6 +91,12 @@ namespace MediaBrowser.Providers.People
|
||||||
{
|
{
|
||||||
lock (_requestCountLock)
|
lock (_requestCountLock)
|
||||||
{
|
{
|
||||||
|
if ((DateTime.UtcNow - _lastRequestCountReset).TotalHours >= 1)
|
||||||
|
{
|
||||||
|
_requestCount = 0;
|
||||||
|
_lastRequestCountReset = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
var requestCount = _requestCount;
|
var requestCount = _requestCount;
|
||||||
|
|
||||||
if (requestCount >= 5)
|
if (requestCount >= 5)
|
||||||
|
|
|
@ -29,7 +29,7 @@ using CommonIO;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.Channels
|
namespace MediaBrowser.Server.Implementations.Channels
|
||||||
{
|
{
|
||||||
public class ChannelManager : IChannelManager, IDisposable
|
public class ChannelManager : IChannelManager
|
||||||
{
|
{
|
||||||
private IChannel[] _channels;
|
private IChannel[] _channels;
|
||||||
|
|
||||||
|
@ -47,11 +47,6 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly ConcurrentDictionary<Guid, bool> _refreshedItems = new ConcurrentDictionary<Guid, bool>();
|
private readonly ConcurrentDictionary<Guid, bool> _refreshedItems = new ConcurrentDictionary<Guid, bool>();
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, int> _downloadCounts = new ConcurrentDictionary<string, int>();
|
|
||||||
|
|
||||||
private Timer _refreshTimer;
|
|
||||||
private Timer _clearDownloadCountsTimer;
|
|
||||||
|
|
||||||
public ChannelManager(IUserManager userManager, IDtoService dtoService, ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IUserDataManager userDataManager, IJsonSerializer jsonSerializer, ILocalizationManager localization, IHttpClient httpClient, IProviderManager providerManager)
|
public ChannelManager(IUserManager userManager, IDtoService dtoService, ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IUserDataManager userDataManager, IJsonSerializer jsonSerializer, ILocalizationManager localization, IHttpClient httpClient, IProviderManager providerManager)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
@ -65,9 +60,6 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
|
|
||||||
_refreshTimer = new Timer(s => _refreshedItems.Clear(), null, TimeSpan.FromHours(3), TimeSpan.FromHours(3));
|
|
||||||
_clearDownloadCountsTimer = new Timer(s => _downloadCounts.Clear(), null, TimeSpan.FromHours(24), TimeSpan.FromHours(24));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimeSpan CacheLength
|
private TimeSpan CacheLength
|
||||||
|
@ -206,6 +198,8 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
|
|
||||||
public async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
|
public async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
_refreshedItems.Clear();
|
||||||
|
|
||||||
var allChannelsList = GetAllChannels().ToList();
|
var allChannelsList = GetAllChannels().ToList();
|
||||||
|
|
||||||
var numComplete = 0;
|
var numComplete = 0;
|
||||||
|
@ -1471,12 +1465,6 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
|
|
||||||
var limit = features.DailyDownloadLimit;
|
var limit = features.DailyDownloadLimit;
|
||||||
|
|
||||||
if (!ValidateDownloadLimit(host, limit))
|
|
||||||
{
|
|
||||||
_logger.Error(string.Format("Download limit has been reached for {0}", channel.Name));
|
|
||||||
throw new ChannelDownloadException(string.Format("Download limit has been reached for {0}", channel.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var header in source.RequiredHttpHeaders)
|
foreach (var header in source.RequiredHttpHeaders)
|
||||||
{
|
{
|
||||||
options.RequestHeaders[header.Key] = header.Value;
|
options.RequestHeaders[header.Key] = header.Value;
|
||||||
|
@ -1495,8 +1483,6 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
IncrementDownloadCount(host, limit);
|
|
||||||
|
|
||||||
if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase) && response.ContentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase) && response.ContentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var extension = response.ContentType.Split('/')
|
var extension = response.ContentType.Split('/')
|
||||||
|
@ -1531,46 +1517,5 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void IncrementDownloadCount(string key, int? limit)
|
|
||||||
{
|
|
||||||
if (!limit.HasValue)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int current;
|
|
||||||
_downloadCounts.TryGetValue(key, out current);
|
|
||||||
|
|
||||||
current++;
|
|
||||||
_downloadCounts.AddOrUpdate(key, current, (k, v) => current);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ValidateDownloadLimit(string key, int? limit)
|
|
||||||
{
|
|
||||||
if (!limit.HasValue)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int current;
|
|
||||||
_downloadCounts.TryGetValue(key, out current);
|
|
||||||
|
|
||||||
return current < limit.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_clearDownloadCountsTimer != null)
|
|
||||||
{
|
|
||||||
_clearDownloadCountsTimer.Dispose();
|
|
||||||
_clearDownloadCountsTimer = null;
|
|
||||||
}
|
|
||||||
if (_refreshTimer != null)
|
|
||||||
{
|
|
||||||
_refreshTimer.Dispose();
|
|
||||||
_refreshTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,13 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
using MediaBrowser.Common.IO;
|
using MediaBrowser.Common.IO;
|
||||||
|
using MediaBrowser.Common.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.Connect
|
namespace MediaBrowser.Server.Implementations.Connect
|
||||||
{
|
{
|
||||||
public class ConnectEntryPoint : IServerEntryPoint
|
public class ConnectEntryPoint : IServerEntryPoint
|
||||||
{
|
{
|
||||||
private Timer _timer;
|
private PeriodicTimer _timer;
|
||||||
private readonly IHttpClient _httpClient;
|
private readonly IHttpClient _httpClient;
|
||||||
private readonly IApplicationPaths _appPaths;
|
private readonly IApplicationPaths _appPaths;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
@ -43,7 +44,7 @@ namespace MediaBrowser.Server.Implementations.Connect
|
||||||
{
|
{
|
||||||
Task.Run(() => LoadCachedAddress());
|
Task.Run(() => LoadCachedAddress());
|
||||||
|
|
||||||
_timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3));
|
_timer = new PeriodicTimer(null, new TimerCallback(TimerCallback), TimeSpan.FromSeconds(5), TimeSpan.FromHours(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly string[] _ipLookups = { "http://bot.whatismyipaddress.com", "https://connect.emby.media/service/ip" };
|
private readonly string[] _ipLookups = { "http://bot.whatismyipaddress.com", "https://connect.emby.media/service/ip" };
|
||||||
|
|
|
@ -11,6 +11,7 @@ using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using MediaBrowser.Common.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.EntryPoints
|
namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
{
|
{
|
||||||
|
@ -21,7 +22,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly ISsdpHandler _ssdp;
|
private readonly ISsdpHandler _ssdp;
|
||||||
|
|
||||||
private Timer _timer;
|
private PeriodicTimer _timer;
|
||||||
private bool _isStarted;
|
private bool _isStarted;
|
||||||
|
|
||||||
public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp)
|
public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp)
|
||||||
|
@ -95,7 +96,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
NatUtility.UnhandledException += NatUtility_UnhandledException;
|
NatUtility.UnhandledException += NatUtility_UnhandledException;
|
||||||
NatUtility.StartDiscovery();
|
NatUtility.StartDiscovery();
|
||||||
|
|
||||||
_timer = new Timer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
|
_timer = new PeriodicTimer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
|
||||||
|
|
||||||
_ssdp.MessageReceived += _ssdp_MessageReceived;
|
_ssdp.MessageReceived += _ssdp_MessageReceived;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Implementations.EntryPoints
|
namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
{
|
{
|
||||||
|
@ -23,7 +24,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
|
|
||||||
private Timer _timer;
|
|
||||||
private readonly TimeSpan _frequency = TimeSpan.FromHours(24);
|
private readonly TimeSpan _frequency = TimeSpan.FromHours(24);
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<Guid, ClientInfo> _apps = new ConcurrentDictionary<Guid, ClientInfo>();
|
private readonly ConcurrentDictionary<Guid, ClientInfo> _apps = new ConcurrentDictionary<Guid, ClientInfo>();
|
||||||
|
@ -95,16 +95,16 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public async void Run()
|
||||||
{
|
{
|
||||||
_timer = new Timer(OnTimerFired, null, TimeSpan.FromMilliseconds(5000), _frequency);
|
await Task.Delay(5000).ConfigureAwait(false);
|
||||||
|
OnTimerFired();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when [timer fired].
|
/// Called when [timer fired].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
private async void OnTimerFired()
|
||||||
private async void OnTimerFired(object state)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -121,12 +121,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_sessionManager.SessionStarted -= _sessionManager_SessionStarted;
|
_sessionManager.SessionStarted -= _sessionManager_SessionStarted;
|
||||||
|
|
||||||
if (_timer != null)
|
|
||||||
{
|
|
||||||
_timer.Dispose();
|
|
||||||
_timer = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue