Added TimerProvider

pull/3113/head
kay.one 13 years ago
parent 848553da73
commit 59899286ee

@ -93,6 +93,7 @@
<Compile Include="AutoMoq\Unity\AutoMockingContainerExtension.cs"> <Compile Include="AutoMoq\Unity\AutoMockingContainerExtension.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="TimerProviderTest.cs" />
<Compile Include="SyncProviderTest.cs" /> <Compile Include="SyncProviderTest.cs" />
<Compile Include="RootDirProviderTest.cs" /> <Compile Include="RootDirProviderTest.cs" />
<Compile Include="IndexerProviderTest.cs" /> <Compile Include="IndexerProviderTest.cs" />

@ -1,4 +1,5 @@
using MbUnit.Framework; using System.Threading;
using MbUnit.Framework;
using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Repository.Quality;
namespace NzbDrone.Core.Test namespace NzbDrone.Core.Test
@ -13,8 +14,8 @@ namespace NzbDrone.Core.Test
* *
*/ */
[Test] [Test]
[Timeout(1)]
[Row("Sonny.With.a.Chance.S02E15", 2, 15)] [Row("Sonny.With.a.Chance.S02E15", 2, 15)]
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1)] [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, 1)]
[Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)] [Row("Two.and.a.Half.Me.103.720p.HDTV.X264-DIMENSION", 1, 3)]
@ -40,6 +41,7 @@ namespace NzbDrone.Core.Test
} }
[Test] [Test]
[Timeout(1)]
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.BDRip)] [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", QualityTypes.BDRip)]
[Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.BDRip)] [Row("WEEDS.S03E01-06.DUAL.BDRip.AC3.-HELLYWOOD", QualityTypes.BDRip)]
[Row("Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", QualityTypes.HDTV)] [Row("Two.and.a.Half.Men.S08E05.720p.HDTV.X264-DIMENSION", QualityTypes.HDTV)]
@ -66,9 +68,10 @@ namespace NzbDrone.Core.Test
} }
[Test] [Test]
[Timeout(1)]
[Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, new[] { 1, 2, 3, 4, 5, 6 })] [Row("WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD", 3, new[] { 1, 2, 3, 4, 5, 6 })]
[Row("Two.and.a.Half.Men.103.104.720p.HDTV.X264-DIMENSION", 1, new[] {3, 4})] [Row("Two.and.a.Half.Men.103.104.720p.HDTV.X264-DIMENSION", 1, new[] { 3, 4 })]
[Row("Weeds.S03E01.S03E02.720p.HDTV.X264-DIMENSION", 3, new[] {1, 2})] [Row("Weeds.S03E01.S03E02.720p.HDTV.X264-DIMENSION", 3, new[] { 1, 2 })]
[Row("The Borgias S01e01 e02 ShoHD On Demand 1080i DD5 1 ALANiS", 1, new[] { 1, 2 })] [Row("The Borgias S01e01 e02 ShoHD On Demand 1080i DD5 1 ALANiS", 1, new[] { 1, 2 })]
[Row("Big Time Rush 1x01 to 10 480i DD2 0 Sianto", 1, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 })] [Row("Big Time Rush 1x01 to 10 480i DD2 0 Sianto", 1, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 })]
[Row("White.Collar.2x04.2x05.720p.BluRay-FUTV", 2, new[] { 4, 5 })] [Row("White.Collar.2x04.2x05.720p.BluRay-FUTV", 2, new[] { 4, 5 })]

@ -0,0 +1,110 @@
using System;
using System.Linq;
using System.Collections.Generic;
using AutoMoq;
using MbUnit.Framework;
using Moq;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Timers;
namespace NzbDrone.Core.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class TimerProviderTest
{
[Test]
public void Run_Timers()
{
IEnumerable<ITimer> fakeTimers = new List<ITimer> { new FakeTimer() };
var mocker = new AutoMoqer();
mocker.SetConstant(MockLib.GetEmptyRepository());
mocker.SetConstant(fakeTimers);
var timerProvider = mocker.Resolve<TimerProvider>();
timerProvider.Initialize();
timerProvider.Run();
}
[Test]
public void Init_Timers()
{
var fakeTimer = new FakeTimer();
IEnumerable<ITimer> fakeTimers = new List<ITimer> { fakeTimer };
var mocker = new AutoMoqer();
mocker.SetConstant(MockLib.GetEmptyRepository());
mocker.SetConstant(fakeTimers);
var timerProvider = mocker.Resolve<TimerProvider>();
timerProvider.Initialize();
var timers = timerProvider.All();
//Assert
Assert.Count(1, timers);
Assert.AreEqual(fakeTimer.DefaultInterval, timers[0].Interval);
Assert.AreEqual(fakeTimer.Name, timers[0].Name);
Assert.AreEqual(fakeTimer.GetType().ToString(), timers[0].TypeName);
Assert.AreEqual(DateTime.MinValue, timers[0].LastExecution);
Assert.IsTrue(timers[0].Enable);
}
[Test]
public void Init_Timers_only_registers_once()
{
var repo = MockLib.GetEmptyRepository();
for (int i = 0; i < 2; i++)
{
var fakeTimer = new FakeTimer();
IEnumerable<ITimer> fakeTimers = new List<ITimer> { fakeTimer };
var mocker = new AutoMoqer();
mocker.SetConstant(repo);
mocker.SetConstant(fakeTimers);
var timerProvider = mocker.Resolve<TimerProvider>();
timerProvider.Initialize();
}
var mocker2 = new AutoMoqer();
mocker2.SetConstant(repo);
var assertTimerProvider = mocker2.Resolve<TimerProvider>();
var timers = assertTimerProvider.All();
//Assert
Assert.Count(1, timers);
}
}
public class FakeTimer : ITimer
{
public string Name
{
get { return "FakeTimer"; }
}
public int DefaultInterval
{
get { return 15; }
}
public void Start()
{
}
}
}

@ -10,6 +10,7 @@ using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Indexer; using NzbDrone.Core.Providers.Indexer;
using NzbDrone.Core.Providers.Timers;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Repository.Quality;
using SubSonic.DataProviders; using SubSonic.DataProviders;
@ -22,7 +23,6 @@ namespace NzbDrone.Core
private static StandardKernel _kernel; private static StandardKernel _kernel;
private static readonly Object KernelLock = new object(); private static readonly Object KernelLock = new object();
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static string _startupPath;
public static String AppPath public static String AppPath
{ {
@ -36,21 +36,6 @@ namespace NzbDrone.Core
} }
} }
public static string ExecutablePath
{
get
{
//var uri = new Uri(Assembly.EscapedCodeBase);
//return Path.GetDirectoryName(uri.LocalPath);
return Directory.GetCurrentDirectory();
}
}
public static string StartupPath
{
get { return _startupPath; }
}
public static StandardKernel NinjectKernel public static StandardKernel NinjectKernel
{ {
get get
@ -70,19 +55,16 @@ namespace NzbDrone.Core
Logger.Debug("Binding Ninject's Kernel"); Logger.Debug("Binding Ninject's Kernel");
_kernel = new StandardKernel(); _kernel = new StandardKernel();
//Store the startup path
_startupPath = AppPath;
//Sqlite //Sqlite
var AppDataPath = new DirectoryInfo(Path.Combine(AppPath, "App_Data")); var appDataPath = new DirectoryInfo(Path.Combine(AppPath, "App_Data"));
if (!AppDataPath.Exists) AppDataPath.Create(); if (!appDataPath.Exists) appDataPath.Create();
string connectionString = String.Format("Data Source={0};Version=3;", string connectionString = String.Format("Data Source={0};Version=3;",
Path.Combine(AppDataPath.FullName, "nzbdrone.db")); Path.Combine(appDataPath.FullName, "nzbdrone.db"));
var dbProvider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite"); var dbProvider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite");
string logConnectionString = String.Format("Data Source={0};Version=3;", string logConnectionString = String.Format("Data Source={0};Version=3;",
Path.Combine(AppDataPath.FullName, "log.db")); Path.Combine(appDataPath.FullName, "log.db"));
var logDbProvider = ProviderFactory.GetProvider(logConnectionString, "System.Data.SQLite"); var logDbProvider = ProviderFactory.GetProvider(logConnectionString, "System.Data.SQLite");
@ -99,7 +81,6 @@ namespace NzbDrone.Core
_kernel.Bind<HttpProvider>().ToSelf().InSingletonScope(); _kernel.Bind<HttpProvider>().ToSelf().InSingletonScope();
_kernel.Bind<SeriesProvider>().ToSelf().InSingletonScope(); _kernel.Bind<SeriesProvider>().ToSelf().InSingletonScope();
_kernel.Bind<SeasonProvider>().ToSelf().InSingletonScope(); _kernel.Bind<SeasonProvider>().ToSelf().InSingletonScope();
_kernel.Bind<RssSyncProvider>().ToSelf().InSingletonScope();
_kernel.Bind<EpisodeProvider>().ToSelf().InSingletonScope(); _kernel.Bind<EpisodeProvider>().ToSelf().InSingletonScope();
_kernel.Bind<UpcomingEpisodesProvider>().ToSelf().InSingletonScope(); _kernel.Bind<UpcomingEpisodesProvider>().ToSelf().InSingletonScope();
_kernel.Bind<DiskProvider>().ToSelf().InSingletonScope(); _kernel.Bind<DiskProvider>().ToSelf().InSingletonScope();
@ -127,12 +108,6 @@ namespace NzbDrone.Core
ForceMigration(_kernel.Get<IRepository>()); ForceMigration(_kernel.Get<IRepository>());
SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up
//Get the Timers going
var config = _kernel.Get<ConfigProvider>();
var timer = _kernel.Get<TimerProvider>();
timer.SetRssSyncTimer(Convert.ToInt32(config.GetValue("SyncFrequency", "15", true)));
timer.StartRssSyncTimer();
BindIndexers(); BindIndexers();
} }
} }
@ -140,6 +115,7 @@ namespace NzbDrone.Core
private static void BindIndexers() private static void BindIndexers()
{ {
_kernel.Bind<IndexerProviderBase>().To<NzbsOrgProvider>().InSingletonScope(); _kernel.Bind<IndexerProviderBase>().To<NzbsOrgProvider>().InSingletonScope();
var indexers = _kernel.GetAll<IndexerProviderBase>(); var indexers = _kernel.GetAll<IndexerProviderBase>();
_kernel.Get<IndexerProvider>().InitializeIndexers(indexers.ToList()); _kernel.Get<IndexerProvider>().InitializeIndexers(indexers.ToList());
} }
@ -154,7 +130,7 @@ namespace NzbDrone.Core
} }
/// <summary> /// <summary>
/// This method forces IISExpress process to exit with the host application /// Forces IISExpress process to exit with the host application
/// </summary> /// </summary>
public static void DedicateToHost() public static void DedicateToHost()
{ {
@ -187,7 +163,6 @@ namespace NzbDrone.Core
Process.GetCurrentProcess().Kill(); Process.GetCurrentProcess().Kill();
} }
private static void SetupDefaultQualityProfiles(IRepository repository) private static void SetupDefaultQualityProfiles(IRepository repository)
{ {
var sd = new QualityProfile var sd = new QualityProfile

@ -1,14 +0,0 @@
using System;
namespace NzbDrone.Core.Helpers
{
public static class ServerHelper
{
public static string GetServerHostname()
{
//Both these seem to return the same result... Is on better than the other?
return Environment.MachineName;
//return Dns.GetHostName();
}
}
}

@ -163,14 +163,17 @@
<Compile Include="Helpers\EpisodeRenameHelper.cs" /> <Compile Include="Helpers\EpisodeRenameHelper.cs" />
<Compile Include="Helpers\EpisodeSortingHelper.cs" /> <Compile Include="Helpers\EpisodeSortingHelper.cs" />
<Compile Include="Helpers\SceneNameHelper.cs" /> <Compile Include="Helpers\SceneNameHelper.cs" />
<Compile Include="Helpers\ServerHelper.cs" />
<Compile Include="Instrumentation\LogLevel.cs" /> <Compile Include="Instrumentation\LogLevel.cs" />
<Compile Include="Instrumentation\LogProvider.cs" /> <Compile Include="Instrumentation\LogProvider.cs" />
<Compile Include="Instrumentation\SubsonicTarget.cs" /> <Compile Include="Instrumentation\SubsonicTarget.cs" />
<Compile Include="Instrumentation\ExceptioneerTarget.cs" /> <Compile Include="Instrumentation\ExceptioneerTarget.cs" />
<Compile Include="Instrumentation\NlogWriter.cs" /> <Compile Include="Instrumentation\NlogWriter.cs" />
<Compile Include="Providers\Timers\TimerProvider.cs" />
<Compile Include="Providers\Indexer\NzbMatrixFeedProvider.cs" /> <Compile Include="Providers\Indexer\NzbMatrixFeedProvider.cs" />
<Compile Include="Providers\Indexer\NzbsRUsFeedProvider.cs" /> <Compile Include="Providers\Indexer\NzbsRUsFeedProvider.cs" />
<Compile Include="Providers\Timers\ITimer.cs" />
<Compile Include="Providers\Timers\RssSyncTimer.cs" />
<Compile Include="Repository\TimerSetting.cs" />
<Compile Include="Repository\IndexerSetting.cs" /> <Compile Include="Repository\IndexerSetting.cs" />
<Compile Include="Model\EpisodeParseResult.cs" /> <Compile Include="Model\EpisodeParseResult.cs" />
<Compile Include="Model\EpisodeRenameModel.cs" /> <Compile Include="Model\EpisodeRenameModel.cs" />
@ -187,12 +190,10 @@
<Compile Include="Providers\HistoryProvider.cs" /> <Compile Include="Providers\HistoryProvider.cs" />
<Compile Include="Providers\BacklogProvider.cs" /> <Compile Include="Providers\BacklogProvider.cs" />
<Compile Include="Providers\IndexerProvider.cs" /> <Compile Include="Providers\IndexerProvider.cs" />
<Compile Include="Providers\RssSyncProvider.cs" />
<Compile Include="Providers\PostProcessingProvider.cs" /> <Compile Include="Providers\PostProcessingProvider.cs" />
<Compile Include="Providers\QualityProvider.cs" /> <Compile Include="Providers\QualityProvider.cs" />
<Compile Include="Providers\RenameProvider.cs" /> <Compile Include="Providers\RenameProvider.cs" />
<Compile Include="Providers\RootDirProvider.cs" /> <Compile Include="Providers\RootDirProvider.cs" />
<Compile Include="Providers\TimerProvider.cs" />
<Compile Include="Providers\UpcomingEpisodesProvider.cs" /> <Compile Include="Providers\UpcomingEpisodesProvider.cs" />
<Compile Include="Providers\XbmcProvider.cs" /> <Compile Include="Providers\XbmcProvider.cs" />
<Compile Include="Repository\EpisodeFile.cs" /> <Compile Include="Repository\EpisodeFile.cs" />

@ -116,7 +116,7 @@ namespace NzbDrone.Core
if (match.Count != 0) if (match.Count != 0)
{ {
var seriesName = NormalizeTitle(match[0].Groups["title"].Value); var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
var year = 0; int year;
Int32.TryParse(match[0].Groups["year"].Value, out year); Int32.TryParse(match[0].Groups["year"].Value, out year);
if (year < 1900 || year > DateTime.Now.Year + 1) if (year < 1900 || year > DateTime.Now.Year + 1)
@ -130,12 +130,11 @@ namespace NzbDrone.Core
{ {
SeriesTitle = seriesName, SeriesTitle = seriesName,
SeasonNumber = seasonNumber, SeasonNumber = seasonNumber,
Year = year Year = year,
Quality = ParseQuality(title)
}; };
result.Quality = ParseQuality(title);
Logger.Trace("Season Parsed. {0}", result); Logger.Trace("Season Parsed. {0}", result);
return result; return result;
} }
@ -160,14 +159,7 @@ namespace NzbDrone.Core
if (match.Count != 0) if (match.Count != 0)
{ {
var seriesName = NormalizeTitle(match[0].Groups["title"].Value); var seriesName = NormalizeTitle(match[0].Groups["title"].Value);
var year = 0;
Int32.TryParse(match[0].Groups["year"].Value, out year);
if (year < 1900 || year > DateTime.Now.Year + 1)
{
year = 0;
}
Logger.Trace("Series Parsed. {0}", seriesName); Logger.Trace("Series Parsed. {0}", seriesName);
return seriesName; return seriesName;
} }

@ -48,7 +48,7 @@ namespace NzbDrone.Core.Providers
return _repository.Single<IndexerSetting>(s => s.IndexProviderType == type.ToString()); return _repository.Single<IndexerSetting>(s => s.IndexProviderType == type.ToString());
} }
public IndexerSetting GetSettings(int id) public virtual IndexerSetting GetSettings(int id)
{ {
return _repository.Single<IndexerSetting>(s => s.Id == id); return _repository.Single<IndexerSetting>(s => s.Id == id);
} }

@ -1,9 +0,0 @@
namespace NzbDrone.Core.Providers
{
public class RssSyncProvider
{
public virtual void Begin()
{
}
}
}

@ -51,7 +51,7 @@ namespace NzbDrone.Core.Providers
XDocument xDoc = XDocument.Parse(response); XDocument xDoc = XDocument.Parse(response);
//If an Error Occurred, retuyrn) //If an Error Occurred, return)
if (xDoc.Descendants("error").Count() != 0) if (xDoc.Descendants("error").Count() != 0)
return false; return false;

@ -1,130 +0,0 @@
using System;
using System.Timers;
using NLog;
namespace NzbDrone.Core.Providers
{
public class TimerProvider
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly EpisodeProvider _episodeProvider;
private readonly MediaFileProvider _mediaFileProvider;
private readonly Timer _minuteTimer;
private readonly RssSyncProvider _rssSyncProvider;
private readonly Timer _rssSyncTimer;
private readonly SeasonProvider _seasonProvider;
private readonly SeriesProvider _seriesProvider;
private DateTime _rssSyncNextInterval;
public TimerProvider(RssSyncProvider rssSyncProvider, SeriesProvider seriesProvider,
SeasonProvider seasonProvider, EpisodeProvider episodeProvider,
MediaFileProvider mediaFileProvider)
{
_rssSyncProvider = rssSyncProvider;
_seriesProvider = seriesProvider;
_seasonProvider = seasonProvider;
_episodeProvider = episodeProvider;
_mediaFileProvider = mediaFileProvider;
_rssSyncTimer = new Timer();
_minuteTimer = new Timer(60000);
}
public virtual void ResetRssSyncTimer()
{
double interval = _rssSyncTimer.Interval;
_rssSyncTimer.Interval = interval;
}
public virtual void StartRssSyncTimer()
{
if (_rssSyncTimer.Interval < 900000)
//If Timer is less than 15 minutes, throw an error! This should also be handled when saving the config, though a user could by-pass it by editing the DB directly... TNO (Trust No One)
{
Logger.Error("RSS Sync Frequency is invalid, please set the interval first");
throw new InvalidOperationException("RSS Sync Frequency Invalid");
}
_rssSyncTimer.Elapsed += RunRssSync;
_rssSyncTimer.Start();
_rssSyncNextInterval = DateTime.Now.AddMilliseconds(_rssSyncTimer.Interval);
}
public virtual void StopRssSyncTimer()
{
_rssSyncTimer.Stop();
}
public virtual void SetRssSyncTimer(int minutes)
{
long ms = minutes*60*1000;
_rssSyncTimer.Interval = ms;
}
public virtual TimeSpan RssSyncTimeLeft()
{
return _rssSyncNextInterval.Subtract(DateTime.Now);
}
public virtual DateTime NextRssSyncTime()
{
return _rssSyncNextInterval;
}
public virtual void StartMinuteTimer()
{
_minuteTimer.Elapsed += MinuteTimer_Elapsed;
_minuteTimer.Start();
}
public virtual void StopMinuteTimer()
{
_minuteTimer.Stop();
}
private void RunRssSync(object obj, ElapsedEventArgs args)
{
_rssSyncNextInterval = DateTime.Now.AddMilliseconds(_rssSyncTimer.Interval);
_rssSyncProvider.Begin();
}
private void MinuteTimer_Elapsed(object obj, ElapsedEventArgs args)
{
//Check to see if anything should be run at this time, if so run it
var now = DateTime.Now;
//Daily (Except Sunday) 03:00 - Update the lastest season for all TV Shows
if (now.Hour == 3 && now.Minute == 0 && now.DayOfWeek != DayOfWeek.Sunday)
{
foreach (var series in _seriesProvider.GetAllSeries())
{
var season = _seasonProvider.GetLatestSeason(series.SeriesId);
_episodeProvider.RefreshEpisodeInfo(season);
}
}
//Sunday 03:00 - Update all TV Shows
if (now.Hour == 3 && now.Minute == 0 && now.DayOfWeek == DayOfWeek.Sunday)
{
foreach (var series in _seriesProvider.GetAllSeries())
{
_episodeProvider.RefreshEpisodeInfo(series.SeriesId);
}
}
//Daily 00:00 (Midnight) - Cleanup (removed) EpisodeFiles + Scan for New EpisodeFiles
if (now.Hour == 0 && now.Minute == 0)
{
foreach (var series in _seriesProvider.GetAllSeries())
{
_mediaFileProvider.CleanUp(series.EpisodeFiles);
_mediaFileProvider.Scan(series);
}
}
throw new NotImplementedException();
}
}
}

@ -0,0 +1,11 @@
namespace NzbDrone.Core.Providers.Timers
{
public interface ITimer
{
string Name { get; }
int DefaultInterval { get; }
void Start();
}
}

@ -0,0 +1,39 @@
using System.Linq;
using NLog;
namespace NzbDrone.Core.Providers.Timers
{
public class RssSyncTimer : ITimer
{
private readonly IndexerProvider _indexerProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public RssSyncTimer(IndexerProvider indexerProvider)
{
_indexerProvider = indexerProvider;
}
public string Name
{
get { return "RSS Sync"; }
}
public int DefaultInterval
{
get { return 15; }
}
public void Start()
{
Logger.Info("Doing Things!!!!");
var indexers = _indexerProvider.AllIndexers().Where(c => c.Enable);
foreach (var indexerSetting in indexers)
{
}
}
}
}

@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NLog;
using NzbDrone.Core.Repository;
using SubSonic.Repository;
namespace NzbDrone.Core.Providers.Timers
{
public class TimerProvider
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly IRepository _repository;
private readonly IEnumerable<ITimer> _timerJobs;
private static readonly object ExecutionLock = new object();
private static bool _isRunning;
public TimerProvider(IRepository repository, IEnumerable<ITimer> timerJobs)
{
_repository = repository;
_timerJobs = timerJobs;
}
public TimerProvider() { }
public virtual List<TimerSetting> All()
{
return _repository.All<TimerSetting>().ToList();
}
public virtual void SaveSettings(TimerSetting settings)
{
if (settings.Id == 0)
{
Logger.Debug("Adding timer settings for {0}", settings.Name);
_repository.Add(settings);
}
else
{
Logger.Debug("Updating timer settings for {0}", settings.Name);
_repository.Update(settings);
}
}
public virtual void Run()
{
lock (ExecutionLock)
{
if (_isRunning)
{
Logger.Info("Another instance of timer is already running. Ignoring request.");
return;
}
_isRunning = true;
}
Logger.Trace("Getting list of timers needing to be executed");
var pendingTimers = All().Where(
t => t.Enable &&
(DateTime.Now - t.LastExecution) > TimeSpan.FromMinutes(t.Interval)
);
foreach (var pendingTimer in pendingTimers)
{
Logger.Info("Attempting to start timer [{0}]. Last executing {1}", pendingTimer.Name, pendingTimer.LastExecution);
var timerClass = _timerJobs.Where(t => t.GetType().ToString() == pendingTimer.TypeName).FirstOrDefault();
ForceExecute(timerClass.GetType());
}
}
public void ForceExecute(Type timerType)
{
var timerClass = _timerJobs.Where(t => t.GetType() == timerType).FirstOrDefault();
if (timerClass == null)
{
Logger.Error("Unable to locate implantation for [{0}]. Make sure its properly registered.", timerType.ToString());
return;
}
try
{
var sw = Stopwatch.StartNew();
timerClass.Start();
sw.Stop();
Logger.Info("timer [{0}] finished executing successfully. Duration {1}", timerClass.Name, sw.Elapsed.ToString());
}
catch (Exception e)
{
Logger.Error("An error has occurred while executing timer job " + timerClass.Name, e);
}
}
public virtual void Initialize()
{
Logger.Info("Initializing timer jobs. Count {0}", _timerJobs.Count());
var currentTimer = All();
foreach (var timer in _timerJobs)
{
var timerProviderLocal = timer;
if (!currentTimer.Exists(c => c.TypeName == timerProviderLocal.GetType().ToString()))
{
var settings = new TimerSetting()
{
Enable = true,
TypeName = timer.GetType().ToString(),
Name = timerProviderLocal.Name,
Interval = timerProviderLocal.DefaultInterval,
LastExecution = DateTime.MinValue
};
SaveSettings(settings);
}
}
}
}
}

@ -23,13 +23,13 @@ namespace NzbDrone.Core.Providers
public virtual void Notify(string header, string message) public virtual void Notify(string header, string message)
{ {
//Get time in seconds and convert to ms //Get time in seconds and convert to ms
var time = Convert.ToInt32(_configProvider.GetValue("XbmcDisplayTime", "3", true))*1000; var time = Convert.ToInt32(_configProvider.GetValue("XbmcDisplayTime", "3", true)) * 1000;
var command = String.Format("ExecBuiltIn(Notification({0},{1},{2}))", header, message, time); var command = String.Format("ExecBuiltIn(Notification({0},{1},{2}))", header, message, time);
if (Convert.ToBoolean(_configProvider.GetValue("XbmcNotificationImage", false, true))) if (Convert.ToBoolean(_configProvider.GetValue("XbmcNotificationImage", false, true)))
{ {
//Todo: Get the actual port that NzbDrone is running on... //Todo: Get the actual port that NzbDrone is running on...
var serverInfo = String.Format("http://{0}:{1}", ServerHelper.GetServerHostname(), "8989"); var serverInfo = String.Format("http://{0}:{1}", Environment.MachineName, "8989");
var imageUrl = String.Format("{0}/Content/XbmcNotification.png", serverInfo); var imageUrl = String.Format("{0}/Content/XbmcNotification.png", serverInfo);
command = String.Format("ExecBuiltIn(Notification({0},{1},{2}, {3}))", header, message, time, imageUrl); command = String.Format("ExecBuiltIn(Notification({0},{1},{2}, {3}))", header, message, time, imageUrl);

@ -18,9 +18,9 @@ namespace NzbDrone.Core.Repository
public DayOfWeek? LastDiskSync { get; set; } public DayOfWeek? LastDiskSync { get; set; }
[SubSonicToManyRelation] [SubSonicToManyRelation]
public virtual List<Episode> Episodes { get; private set; } public virtual List<Episode> Episodes { get; protected set; }
[SubSonicToOneRelation(ThisClassContainsJoinKey = true)] [SubSonicToOneRelation(ThisClassContainsJoinKey = true)]
public virtual Series Series { get; private set; } public virtual Series Series { get; protected set; }
} }
} }

@ -45,15 +45,15 @@ namespace NzbDrone.Core.Repository
public DateTime? LastDiskSync { get; set; } public DateTime? LastDiskSync { get; set; }
[SubSonicToOneRelation(ThisClassContainsJoinKey = true, JoinKeyName = "QualityProfileId")] [SubSonicToOneRelation(ThisClassContainsJoinKey = true, JoinKeyName = "QualityProfileId")]
public virtual QualityProfile QualityProfile { get; private set; } public virtual QualityProfile QualityProfile { get; protected set; }
[SubSonicToManyRelation] [SubSonicToManyRelation]
public virtual List<Season> Seasons { get; private set; } public virtual List<Season> Seasons { get; protected set; }
[SubSonicToManyRelation] [SubSonicToManyRelation]
public virtual List<Episode> Episodes { get; private set; } public virtual List<Episode> Episodes { get; protected set; }
[SubSonicToManyRelation] [SubSonicToManyRelation]
public virtual List<EpisodeFile> EpisodeFiles { get; private set; } public virtual List<EpisodeFile> EpisodeFiles { get; protected set; }
} }
} }

@ -0,0 +1,23 @@
using System;
using SubSonic.SqlGeneration.Schema;
namespace NzbDrone.Core.Repository
{
public class TimerSetting
{
[SubSonicPrimaryKey(true)]
public Int32 Id { get; set; }
public Boolean Enable { get; set; }
public String TypeName { get; set; }
public String Name { get; set; }
public Int32 Interval { get; set; }
public DateTime LastExecution { get; set; }
public Boolean Success { get; set; }
}
}

@ -1,134 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Web.Models;
namespace NzbDrone.Web.Controllers
{
public class AddSeriesController : Controller
{
public IConfigProvider ConfigProvider { get; set; }
private readonly SyncProvider _syncProvider;
private readonly RootDirProvider _rootFolderProvider;
private readonly IConfigProvider _configProvider;
private readonly QualityProvider _qualityProvider;
private readonly TvDbProvider _tvDbProvider;
private readonly SeriesProvider _seriesProvider;
public AddSeriesController(SyncProvider syncProvider, RootDirProvider rootFolderProvider, IConfigProvider configProvider,
QualityProvider qualityProvider, TvDbProvider tvDbProvider, SeriesProvider seriesProvider)
{
ConfigProvider = configProvider;
_syncProvider = syncProvider;
_rootFolderProvider = rootFolderProvider;
_configProvider = configProvider;
_qualityProvider = qualityProvider;
_tvDbProvider = tvDbProvider;
_seriesProvider = seriesProvider;
}
[HttpPost]
public JsonResult ScanNewSeries()
{
_syncProvider.BeginUpdateNewSeries();
return new JsonResult();
}
public ActionResult AddNew()
{
ViewData["RootDirs"] = _rootFolderProvider.GetAll();
ViewData["DirSep"] = Path.DirectorySeparatorChar;
var profiles = _qualityProvider.GetAllProfiles();
var selectList = new SelectList(profiles, "QualityProfileId", "Name");
var defaultQuality = Convert.ToInt32(_configProvider.DefaultQualityProfile);
var model = new AddNewSeriesModel
{
DirectorySeparatorChar = Path.DirectorySeparatorChar.ToString(),
RootDirectories = _rootFolderProvider.GetAll(),
QualityProfileId = defaultQuality,
QualitySelectList = selectList
};
return View(model);
}
public ActionResult AddExisting()
{
var unmappedList = new List<String>();
var profiles = _qualityProvider.GetAllProfiles();
var defaultQuality = Convert.ToInt32(_configProvider.DefaultQualityProfile);
var selectList = new SelectList(profiles, "QualityProfileId", "Name", defaultQuality);
ViewData["qualities"] = selectList;
foreach (var folder in _rootFolderProvider.GetAll())
{
unmappedList.AddRange(_syncProvider.GetUnmappedFolders(folder.Path));
}
return View(unmappedList);
}
public ActionResult RenderPartial(string path)
{
var suggestions = GetSuggestionList(new DirectoryInfo(path).Name);
ViewData["guid"] = Guid.NewGuid();
ViewData["path"] = path;
ViewData["javaPath"] = path.Replace(Path.DirectorySeparatorChar, '|').Replace(Path.VolumeSeparatorChar, '^');
var defaultQuality = _configProvider.DefaultQualityProfile;
var qualityProfiles = _qualityProvider.GetAllProfiles();
ViewData["quality"] = new SelectList(
qualityProfiles,
"QualityProfileId",
"Name",
defaultQuality); ;
return PartialView("AddSeriesItem", suggestions);
}
public JsonResult AddSeries(string path, int seriesId, int qualityProfileId)
{
//Get TVDB Series Name
//Create new folder for series
//Add the new series to the Database
_seriesProvider.AddSeries(path.Replace('|', Path.DirectorySeparatorChar).Replace('^', Path.VolumeSeparatorChar), seriesId, qualityProfileId);
ScanNewSeries();
return new JsonResult() { Data = "ok" };
}
[HttpPost]
public ActionResult _textLookUp(string text, int? filterMode)
{
var suggestions = GetSuggestionList(text);
return new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = suggestions
};
}
public SelectList GetSuggestionList(string searchString)
{
var dataVal = _tvDbProvider.SearchSeries(searchString);
//var bestResult = _tvDbProvider.GetBestMatch(dataVal.ToList(), searchString);
return new SelectList(dataVal, "Id", "SeriesName", dataVal[0].Id);
}
}
}

@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Web.Mvc; using System.Web.Mvc;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Timers;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Web.Models; using NzbDrone.Web.Models;
using Telerik.Web.Mvc; using Telerik.Web.Mvc;
@ -19,28 +20,28 @@ namespace NzbDrone.Web.Controllers
private readonly QualityProvider _qualityProvider; private readonly QualityProvider _qualityProvider;
private readonly RenameProvider _renameProvider; private readonly RenameProvider _renameProvider;
private readonly RootDirProvider _rootDirProvider; private readonly RootDirProvider _rootDirProvider;
private readonly RssSyncProvider _rssSyncProvider;
private readonly SeriesProvider _seriesProvider; private readonly SeriesProvider _seriesProvider;
private readonly SyncProvider _syncProvider; private readonly SyncProvider _syncProvider;
private readonly TvDbProvider _tvDbProvider; private readonly TvDbProvider _tvDbProvider;
private readonly TimerProvider _timerProvider;
// //
// GET: /Series/ // GET: /Series/
public SeriesController(SyncProvider syncProvider, SeriesProvider seriesProvider, public SeriesController(SyncProvider syncProvider, SeriesProvider seriesProvider,
EpisodeProvider episodeProvider, RssSyncProvider rssSyncProvider, EpisodeProvider episodeProvider,
QualityProvider qualityProvider, MediaFileProvider mediaFileProvider, QualityProvider qualityProvider, MediaFileProvider mediaFileProvider,
RenameProvider renameProvider, RootDirProvider rootDirProvider, RenameProvider renameProvider, RootDirProvider rootDirProvider,
TvDbProvider tvDbProvider) TvDbProvider tvDbProvider, TimerProvider timerProvider)
{ {
_seriesProvider = seriesProvider; _seriesProvider = seriesProvider;
_episodeProvider = episodeProvider; _episodeProvider = episodeProvider;
_syncProvider = syncProvider; _syncProvider = syncProvider;
_rssSyncProvider = rssSyncProvider;
_qualityProvider = qualityProvider; _qualityProvider = qualityProvider;
_mediaFileProvider = mediaFileProvider; _mediaFileProvider = mediaFileProvider;
_renameProvider = renameProvider; _renameProvider = renameProvider;
_rootDirProvider = rootDirProvider; _rootDirProvider = rootDirProvider;
_tvDbProvider = tvDbProvider; _tvDbProvider = tvDbProvider;
_timerProvider = timerProvider;
} }
public ActionResult Index() public ActionResult Index()
@ -52,13 +53,13 @@ namespace NzbDrone.Web.Controllers
public ActionResult RssSync() public ActionResult RssSync()
{ {
_rssSyncProvider.Begin(); _timerProvider.ForceExecute(typeof(RssSyncTimer));
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
public ActionResult UnMapped(string path) public ActionResult UnMapped(string path)
{ {
return View(_syncProvider.GetUnmappedFolders(path).Select(c => new MappingModel {Id = 1, Path = c}).ToList()); return View(_syncProvider.GetUnmappedFolders(path).Select(c => new MappingModel { Id = 1, Path = c }).ToList());
} }
public ActionResult LoadEpisodes(int seriesId) public ActionResult LoadEpisodes(int seriesId)
@ -121,7 +122,7 @@ namespace NzbDrone.Web.Controllers
//We still want to show this series as unmapped, but we don't know what it will be when mapped //We still want to show this series as unmapped, but we don't know what it will be when mapped
//Todo: Provide the user with a way to manually map a folder to a TvDb series (or make them rename the folder...) //Todo: Provide the user with a way to manually map a folder to a TvDb series (or make them rename the folder...)
if (tvDbSeries == null) if (tvDbSeries == null)
tvDbSeries = new TvdbSeries {Id = 0, SeriesName = String.Empty}; tvDbSeries = new TvdbSeries { Id = 0, SeriesName = String.Empty };
unmappedList.Add(new AddExistingSeriesModel unmappedList.Add(new AddExistingSeriesModel
{ {
@ -263,7 +264,7 @@ namespace NzbDrone.Web.Controllers
var series = _seriesProvider.GetSeries(seriesId); var series = _seriesProvider.GetSeries(seriesId);
_mediaFileProvider.Scan(series); _mediaFileProvider.Scan(series);
return RedirectToAction("Details", new {seriesId}); return RedirectToAction("Details", new { seriesId });
} }
public ActionResult RenameAll() public ActionResult RenameAll()
@ -275,7 +276,7 @@ namespace NzbDrone.Web.Controllers
public ActionResult RenameSeries(int seriesId) public ActionResult RenameSeries(int seriesId)
{ {
_renameProvider.RenameSeries(seriesId); _renameProvider.RenameSeries(seriesId);
return RedirectToAction("Details", new {seriesId}); return RedirectToAction("Details", new { seriesId });
} }
public ActionResult RenameSeason(int seasonId) public ActionResult RenameSeason(int seasonId)

@ -1,5 +1,7 @@
using System.Web.Mvc; using System;
using System.Web.Mvc;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Timers;
namespace NzbDrone.Web.Controllers namespace NzbDrone.Web.Controllers
{ {
@ -20,7 +22,7 @@ namespace NzbDrone.Web.Controllers
[ChildActionOnly] [ChildActionOnly]
public ActionResult Footer() public ActionResult Footer()
{ {
ViewData["RssTimer"] = _timerProvider.NextRssSyncTime().ToString("yyyyMMddHHmmss"); ViewData["RssTimer"] = DateTime.Now.ToString("yyyyMMddHHmmss");
//ViewData["RssTimer"] = DateTime.Now.AddMinutes(61).AddSeconds(10).ToString("yyyyMMddHHmmss"); //ViewData["RssTimer"] = DateTime.Now.AddMinutes(61).AddSeconds(10).ToString("yyyyMMddHHmmss");
return PartialView(); return PartialView();
} }

Loading…
Cancel
Save