reduce use of timers throughout the system

pull/702/head
Luke Pulverenti 9 years ago
parent 8ff5d4af47
commit 3510ef3d2b

@ -6,7 +6,6 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading;
using MoreLinq; using MoreLinq;
namespace MediaBrowser.Common.Implementations.Networking namespace MediaBrowser.Common.Implementations.Networking
@ -14,14 +13,11 @@ namespace MediaBrowser.Common.Implementations.Networking
public abstract class BaseNetworkManager public abstract class BaseNetworkManager
{ {
protected ILogger Logger { get; private set; } protected ILogger Logger { get; private set; }
private Timer _clearCacheTimer; private DateTime _lastRefresh;
protected BaseNetworkManager(ILogger logger) protected BaseNetworkManager(ILogger logger)
{ {
Logger = logger; Logger = logger;
// Can't use network change events due to a crash in Linux
_clearCacheTimer = new Timer(ClearCacheTimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
} }
private void ClearCacheTimerCallback(object state) private void ClearCacheTimerCallback(object state)
@ -41,15 +37,20 @@ namespace MediaBrowser.Common.Implementations.Networking
/// <returns>IPAddress.</returns> /// <returns>IPAddress.</returns>
public IEnumerable<IPAddress> GetLocalIpAddresses() public IEnumerable<IPAddress> GetLocalIpAddresses()
{ {
if (_localIpAddresses == null) var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= 1;
if (_localIpAddresses == null || forceRefresh)
{ {
lock (_localIpAddressSyncLock) lock (_localIpAddressSyncLock)
{ {
if (_localIpAddresses == null) forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= 1;
if (_localIpAddresses == null || forceRefresh)
{ {
var addresses = GetLocalIpAddressesInternal().ToList(); var addresses = GetLocalIpAddressesInternal().ToList();
_localIpAddresses = addresses; _localIpAddresses = addresses;
_lastRefresh = DateTime.UtcNow;
return addresses; return addresses;
} }

@ -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" />

@ -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
@ -211,6 +203,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;
@ -1487,12 +1481,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;
@ -1511,8 +1499,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('/')
@ -1547,46 +1533,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…
Cancel
Save