Browse Source

reduce use of timers throughout the system

Conflicts:
	MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
Luke Pulverenti 9 years ago
parent
commit
cfa8f6c6ec

+ 10 - 3
MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs

@@ -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 >= cacheMinutes;
+            var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= 1;
 
 
             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)
                     {
                     {

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

@@ -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 - 0
MediaBrowser.Common/Threading/PeriodicTimer.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();
+        }
+    }
+}

+ 7 - 11
MediaBrowser.Providers/People/MovieDbPersonProvider.cs

@@ -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)

+ 3 - 58
MediaBrowser.Server.Implementations/Channels/ChannelManager.cs

@@ -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;
-            }
-        }
     }
     }
 }
 }

+ 3 - 2
MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs

@@ -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" };

+ 3 - 2
MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs

@@ -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;
 
 

+ 5 - 11
MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs

@@ -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(object state)
+        private async void OnTimerFired()
         {
         {
             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;
-            }
         }
         }
     }
     }
 }
 }