Cleaned up logging code

Added udp logging
Added SyncProvider to provide async long running tasks
Refactored SyncSeries to SyncProvider
Episode Info is now fetched automatically
Optimized RefreshEpisodeInfo for better performance
This commit is contained in:
Keivan 2010-10-17 10:22:48 -07:00
parent c597363bf8
commit 273de41d23
42 changed files with 7165 additions and 33994 deletions

5
.gitignore vendored
View File

@ -26,7 +26,8 @@ obj/
_ReSharper*/ _ReSharper*/
[Tt]est[Rr]esult[s] [Tt]est[Rr]esult[s]
/[Bb]uild/ [Bb]uild/
[Ll]ogs/
/[Pp]ackage/
#NZBDrone specific #NZBDrone specific
nzbdrone.db nzbdrone.db

View File

@ -134,7 +134,7 @@
<add name="Clr2IntegratedAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" /> <add name="Clr2IntegratedAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
<add name="Clr2ClassicAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" /> <add name="Clr2ClassicAppPool" managedRuntimeVersion="v2.0" managedPipelineMode="Classic" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" />
<add name="UnmanagedClassicAppPool" managedRuntimeVersion="" managedPipelineMode="Classic" autoStart="true" />--> <add name="UnmanagedClassicAppPool" managedRuntimeVersion="" managedPipelineMode="Classic" autoStart="true" />-->
<add name="IISExpressAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" /> <add name="IISExpressAppPool" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated" CLRConfigFile="%IIS_USER_HOME%\config\aspnet.config" autoStart="true" startMode="AlwaysRunning" />
<applicationPoolDefaults managedRuntimeLoader="v4.0"> <applicationPoolDefaults managedRuntimeLoader="v4.0">
<processModel /> <processModel />
</applicationPoolDefaults> </applicationPoolDefaults>
@ -161,7 +161,7 @@
</site> </site>
<siteDefaults> <siteDefaults>
<logFile logFormat="W3C" directory="%NZBDRONE_PATH%\Logs\IIS" enabled="false" /> <logFile logFormat="W3C" directory="%NZBDRONE_PATH%\Logs\IIS" enabled="false" />
<traceFailedRequestsLogging directory="%NZBDRONE_PATH%\Logs\IIS\TraceLogFiles" enabled="true" /> <traceFailedRequestsLogging directory="Logs\IIS\TraceLogFiles" enabled="false" />
</siteDefaults> </siteDefaults>
<applicationDefaults applicationPool="IISExpressAppPool" /> <applicationDefaults applicationPool="IISExpressAppPool" />
<virtualDirectoryDefaults allowSubDirConfig="true" /> <virtualDirectoryDefaults allowSubDirConfig="true" />

View File

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using Gallio.Framework; using Gallio.Framework;
using log4net;
using MbUnit.Framework; using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers; using MbUnit.Framework.ContractVerifiers;
using Moq; using Moq;

View File

@ -1,9 +1,18 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Text; using System.Text;
using FizzWare.NBuilder;
using Gallio.Framework; using Gallio.Framework;
using MbUnit.Framework; using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers; using MbUnit.Framework.ContractVerifiers;
using Moq;
using Ninject;
using Ninject.Moq;
using NzbDrone.Core.Providers;
using SubSonic.Repository;
using TvdbLib.Data;
using SubSonic.Extensions;
namespace NzbDrone.Core.Test namespace NzbDrone.Core.Test
{ {
@ -11,6 +20,37 @@ namespace NzbDrone.Core.Test
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
public class EpisodeProviderTest public class EpisodeProviderTest
{ {
[Test]
public void BulkAddSpeedTest()
{
//Arrange
int seriesId = 71663;
int episodeCount = 500;
var fakeEpisodes = Builder<TvdbSeries>.CreateNew().With(
c => c.Episodes =
new List<TvdbEpisode>(Builder<TvdbEpisode>.CreateListOfSize(episodeCount).
WhereAll()
.Have(l => l.Language = new TvdbLanguage(0, "eng", "a"))
.Build())
).With(c => c.Id = seriesId).Build();
var tvdbMock = new Mock<ITvDbProvider>();
tvdbMock.Setup(c => c.GetSeries(seriesId, true)).Returns(fakeEpisodes).Verifiable();
var kernel = new MockingKernel();
kernel.Bind<IRepository>().ToConstant(MockLib.GetEmptyRepository(false)).InSingletonScope();
kernel.Bind<ITvDbProvider>().ToConstant(tvdbMock.Object);
kernel.Bind<IEpisodeProvider>().To<EpisodeProvider>().InSingletonScope();
//Act
var sw = Stopwatch.StartNew();
kernel.Get<IEpisodeProvider>().RefreshEpisodeInfo(seriesId);
//Assert
tvdbMock.VerifyAll();
Assert.Count(episodeCount, kernel.Get<IEpisodeProvider>().GetEpisodeBySeries(seriesId));
Console.WriteLine("Duration: " + sw.Elapsed.ToString());
}
} }
} }

View File

@ -3,7 +3,9 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Moq; using Moq;
using NLog;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using SubSonic.DataProviders; using SubSonic.DataProviders;
using SubSonic.Repository; using SubSonic.Repository;
@ -16,6 +18,7 @@ namespace NzbDrone.Core.Test
/// </summary> /// </summary>
static class MockLib static class MockLib
{ {
public static string[] StandardSeries public static string[] StandardSeries
{ {
get { return new string[] { "c:\\tv\\the simpsons", "c:\\tv\\family guy", "c:\\tv\\southpark", "c:\\tv\\24" }; } get { return new string[] { "c:\\tv\\the simpsons", "c:\\tv\\family guy", "c:\\tv\\southpark", "c:\\tv\\24" }; }
@ -23,7 +26,17 @@ namespace NzbDrone.Core.Test
public static IRepository GetEmptyRepository() public static IRepository GetEmptyRepository()
{ {
return GetEmptyRepository(true);
}
public static IRepository GetEmptyRepository(bool enableLogging)
{
Console.WriteLine("Creating an empty SQLite database");
var provider = ProviderFactory.GetProvider("Data Source=" + Guid.NewGuid() + ".testdb;Version=3;New=True", "System.Data.SQLite"); var provider = ProviderFactory.GetProvider("Data Source=" + Guid.NewGuid() + ".testdb;Version=3;New=True", "System.Data.SQLite");
if (enableLogging)
{
provider.Log = new Instrumentation.NlogWriter();
provider.LogParams = true;
}
return new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations); return new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations);
} }

View File

@ -36,10 +36,6 @@
<HintPath>Libs\FizzWare.NBuilder.dll</HintPath> <HintPath>Libs\FizzWare.NBuilder.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gallio, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" /> <Reference Include="Gallio, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" />
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\log4net.dll</HintPath>
</Reference>
<Reference Include="MbUnit, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" /> <Reference Include="MbUnit, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" />
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL"> <Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
@ -49,6 +45,7 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\Ninject.dll</HintPath> <HintPath>..\NzbDrone.Core\Libraries\Ninject.dll</HintPath>
</Reference> </Reference>
<Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL" />
<Reference Include="SubSonic.Core, Version=3.0.0.3, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SubSonic.Core, Version=3.0.0.3, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\SubSonic.Core.dll</HintPath> <HintPath>..\NzbDrone.Core\Libraries\SubSonic.Core.dll</HintPath>
@ -106,6 +103,10 @@
<None Include="App.config"> <None Include="App.config">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<Content Include="log.config">
<SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Gallio.Framework; using Gallio.Framework;
using log4net;
using MbUnit.Framework; using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers; using MbUnit.Framework.ContractVerifiers;
using Moq; using Moq;

View File

@ -0,0 +1,8 @@
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true">
<targets>
<target name="consoleTarget" xsi:type="ColoredConsole" layout="${logger}: ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="consoleTarget"/>
</rules>
</nlog>

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Web; using System.Web;
using Ninject; using Ninject;
@ -11,6 +12,7 @@ using NzbDrone.Core.Providers.Fakes;
using SubSonic.DataProviders; using SubSonic.DataProviders;
using SubSonic.Repository; using SubSonic.Repository;
using NLog; using NLog;
using System.Linq;
namespace NzbDrone.Core namespace NzbDrone.Core
{ {
@ -38,6 +40,7 @@ namespace NzbDrone.Core
_kernel.Bind<IDiskProvider>().To<DiskProvider>(); _kernel.Bind<IDiskProvider>().To<DiskProvider>();
_kernel.Bind<ITvDbProvider>().To<TvDbProvider>(); _kernel.Bind<ITvDbProvider>().To<TvDbProvider>();
_kernel.Bind<IConfigProvider>().To<ConfigProvider>().InSingletonScope(); _kernel.Bind<IConfigProvider>().To<ConfigProvider>().InSingletonScope();
_kernel.Bind<ISyncProvider>().To<SyncProvider>().InSingletonScope();
_kernel.Bind<INotificationProvider>().To<NotificationProvider>().InSingletonScope(); _kernel.Bind<INotificationProvider>().To<NotificationProvider>().InSingletonScope();
_kernel.Bind<IRepository>().ToMethod(c => new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope(); _kernel.Bind<IRepository>().ToMethod(c => new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope();
@ -75,5 +78,39 @@ namespace NzbDrone.Core
repository.GetPaged<Series>(0, 1); repository.GetPaged<Series>(0, 1);
repository.GetPaged<EpisodeInfo>(0, 1); repository.GetPaged<EpisodeInfo>(0, 1);
} }
/// <summary>
/// This method forces IISExpress process to exit with the host application
/// </summary>
public static void DedicateToHost()
{
try
{
Logger.Info("Attaching to parent process for automatic termination.");
var pc = new PerformanceCounter("Process", "Creating Process ID", Process.GetCurrentProcess().ProcessName);
var pid = (int)pc.NextValue();
var hostProcess = Process.GetProcessById(pid);
hostProcess.EnableRaisingEvents = true;
hostProcess.Exited += (delegate
{
Logger.Info("Host has been terminated. Shutting down web server.");
ShutDown();
});
Logger.Info("Successfully Attached to host. Process ID: {0}", pid);
}
catch (Exception e)
{
Logger.Fatal(e);
}
}
private static void ShutDown()
{
Logger.Info("Shutting down application.");
Process.GetCurrentProcess().Kill();
}
} }
} }

View File

@ -13,76 +13,26 @@ namespace NzbDrone.Core
{ {
public static void Setup() public static void Setup()
{ {
// Step 1. Create configuration object
var config = new LoggingConfiguration();
const string callSight = "${callsite:className=false:fileName=false:includeSourcePath=false:methodName=true}";
string layout = string.Concat("[${logger}](", callSight, "): ${message}");
// Step 2. Create targets and add them to the configuration
var debuggerTarget = new DebuggerTarget
{
Layout = layout
};
var consoleTarget = new ColoredConsoleTarget
{
Layout = layout
};
var fileTarget = new FileTarget
{
FileName = "${basedir}/test.log",
Layout = layout
};
config.AddTarget("debugger", debuggerTarget);
config.AddTarget("console", consoleTarget);
//config.AddTarget("file", fileTarget);
// Step 3. Set target properties
// Step 4. Define rules
//LoggingRule fileRule = new LoggingRule("*", LogLevel.Trace, fileTarget);
var debugRule = new LoggingRule("*", LogLevel.Trace, debuggerTarget);
var consoleRule = new LoggingRule("*", LogLevel.Trace, consoleTarget);
//config.LoggingRules.Add(fileRule);
config.LoggingRules.Add(debugRule);
config.LoggingRules.Add(consoleRule);
// Step 5. Activate the configuration
LogManager.Configuration = config;
}
public static void LogEpicException(Exception e)
{
try
{
LogManager.GetLogger("EPICFAIL").FatalException("Unhandled Exception", e);
}
catch (Exception totalFailException)
{
Console.WriteLine("TOTAL FAIL:{0}", totalFailException);
Console.WriteLine(e.ToString());
}
PublishExceptoion(e);
}
private static bool PublishExceptoion(Exception e)
{
//Don't publish exceptions when debugging the app.
if (Debugger.IsAttached) if (Debugger.IsAttached)
return false; {
LogManager.ThrowExceptions = true;
}
return new Client LogManager.Configuration = new XmlLoggingConfiguration(Path.Combine(CentralDispatch.AppPath, "log.config"), false);
{ LogManager.ConfigurationReloaded += ((s, e) => BindExceptioneer());
ApiKey = "43BBF60A-EB2A-4C1C-B09E-422ADF637265", BindExceptioneer();
ApplicationName = "NZBDrone",
CurrentException = e
}.Submit();
} }
private static void BindExceptioneer()
{
var exTarget = new ExceptioneerTarget();
LogManager.Configuration.AddTarget("Exceptioneer", exTarget);
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Error, exTarget));
LogManager.Configuration.Reload();
}
public class NlogWriter : TextWriter public class NlogWriter : TextWriter
{ {
private static readonly Logger Logger = LogManager.GetLogger("DB"); private static readonly Logger Logger = LogManager.GetLogger("DB");
@ -108,7 +58,29 @@ namespace NzbDrone.Core
get { return Encoding.Default; } get { return Encoding.Default; }
} }
} }
public class ExceptioneerTarget : Target
{
protected override void Write(LogEventInfo logEvent)
{
if (logEvent.Exception == null)
throw new InvalidOperationException(@"Missing Exception Object.. Please Use Logger.FatalException() or Logger.ErrorException() rather
than Logger.Fatal() and Logger.Error()");
if (!Debugger.IsAttached)
{
new Client
{
ApiKey = "43BBF60A-EB2A-4C1C-B09E-422ADF637265",
ApplicationName = "NZBDrone",
CurrentException = logEvent.Exception
}.Submit();
}
}
}
} }
} }

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -129,6 +129,8 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath> <HintPath>Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gallio, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" />
<Reference Include="MbUnit, Version=3.2.0.0, Culture=neutral, PublicKeyToken=eb9cfa67ee6ab36e, processorArchitecture=MSIL" />
<Reference Include="Ninject, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL" /> <Reference Include="Ninject, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL" />
<Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL" /> <Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL" />
<Reference Include="NLog.Extended, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Reference Include="NLog.Extended, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
@ -141,6 +143,7 @@
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.configuration" /> <Reference Include="System.configuration" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" /> <Reference Include="System.ServiceModel" />
<Reference Include="System.Web" /> <Reference Include="System.Web" />
@ -159,7 +162,9 @@
<Compile Include="Providers\INotificationProvider.cs" /> <Compile Include="Providers\INotificationProvider.cs" />
<Compile Include="Providers\IMediaDiscoveryProvider.cs" /> <Compile Include="Providers\IMediaDiscoveryProvider.cs" />
<Compile Include="Providers\IMediaProvider.cs" /> <Compile Include="Providers\IMediaProvider.cs" />
<Compile Include="Providers\ISyncProvider.cs" />
<Compile Include="Providers\MediaDiscoveryProvider.cs" /> <Compile Include="Providers\MediaDiscoveryProvider.cs" />
<Compile Include="Providers\SyncProvider.cs" />
<Compile Include="Providers\XBMCMediaProvider.cs" /> <Compile Include="Providers\XBMCMediaProvider.cs" />
<Compile Include="Entities\Notification\ProgressNotification.cs" /> <Compile Include="Entities\Notification\ProgressNotification.cs" />
<Compile Include="Providers\NotificationProvider.cs" /> <Compile Include="Providers\NotificationProvider.cs" />
@ -216,8 +221,6 @@
<ItemGroup> <ItemGroup>
<Content Include="Libraries\Castle.Core.dll" /> <Content Include="Libraries\Castle.Core.dll" />
<Content Include="Libraries\Exceptioneer.WindowsFormsClient.dll" /> <Content Include="Libraries\Exceptioneer.WindowsFormsClient.dll" />
<Content Include="Libraries\log4net.dll" />
<Content Include="Libraries\log4net.xml" />
<Content Include="Libraries\Ninject.dll" /> <Content Include="Libraries\Ninject.dll" />
<Content Include="Libraries\Ninject.xml" /> <Content Include="Libraries\Ninject.xml" />
<Content Include="Libraries\NLog.dll" /> <Content Include="Libraries\NLog.dll" />
@ -234,6 +237,11 @@
<Content Include="Libraries\TvdbLib.XML" /> <Content Include="Libraries\TvdbLib.XML" />
<Content Include="Libraries\UPnP.dll" /> <Content Include="Libraries\UPnP.dll" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="Libraries\nlog.xsd">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -1,8 +1,4 @@
// /* // * This program is free software: you can redistribute it and/or modify
// * Sab NzbDrone: Automatic TV Sync for SAB http://sabscripts.googlecode.com
// *
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by // * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or // * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version. // * (at your option) any later version.
@ -23,11 +19,11 @@ using System.Runtime.InteropServices;
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("NzbDrone")] [assembly: AssemblyTitle("NZBDrone.Core")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("NZBDrone Core Component")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sabscripts.googlecode.com")] [assembly: AssemblyCompany("www.nzbdrone.com")]
[assembly: AssemblyProduct("NzbDrone")] [assembly: AssemblyProduct("NZBDrone")]
[assembly: AssemblyCopyright("GNU General Public v3")] [assembly: AssemblyCopyright("GNU General Public v3")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -40,7 +36,7 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM // The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a7b979bf-7f4e-4ccf-b2c6-fa8d3dfb650e")] [assembly: Guid("3C29FEF7-4B07-49ED-822E-1C29DC49BFAB")]
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
// //
@ -53,5 +49,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.9.8.4")] [assembly: AssemblyVersion("0.2.0.*")]
[assembly: AssemblyFileVersion("0.9.8.4")]

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NLog; using NLog;
@ -89,41 +90,60 @@ namespace NzbDrone.Core.Providers
throw new NotImplementedException(); throw new NotImplementedException();
} }
public void RefreshSeries(int seriesId) public void RefreshEpisodeInfo(int seriesId)
{ {
Logger.Info("Starting episode info refresh for series:{0}", seriesId); Logger.Info("Starting episode info refresh for series:{0}", seriesId);
int successCount = 0; int successCount = 0;
int failCount = 0; int failCount = 0;
var targetSeries = _tvDb.GetSeries(seriesId, true); var targetSeries = _tvDb.GetSeries(seriesId, true);
var updateList = new List<EpisodeInfo>();
var newList = new List<EpisodeInfo>();
Logger.Debug("Updating season info for series:{0}", seriesId);
targetSeries.Episodes.Select(e => new { e.SeasonId, e.SeasonNumber })
.Distinct().ToList()
.ForEach(s => _seasons.EnsureSeason(seriesId, s.SeasonId, s.SeasonNumber));
foreach (var episode in targetSeries.Episodes) foreach (var episode in targetSeries.Episodes)
{ {
try try
{ {
_seasons.EnsureSeason(seriesId, episode.SeasonId, episode.SeasonNumber); Logger.Debug("Updating info for series:{0} - episode:{1}", seriesId, episode.Id);
var newEpisode = new EpisodeInfo() var newEpisode = new EpisodeInfo()
{
AirDate = episode.FirstAired,
EpisodeId = episode.Id,
EpisodeNumber = episode.EpisodeNumber,
Language = episode.Language.Abbriviation,
Overview = episode.Overview,
SeasonId = episode.SeasonId,
SeasonNumber = episode.SeasonNumber,
SeriesId = seriesId,
Title = episode.EpisodeName
};
if (_sonicRepo.Exists<EpisodeInfo>(e => e.EpisodeId == newEpisode.EpisodeId))
{ {
AirDate = episode.FirstAired, updateList.Add(newEpisode);
EpisodeId = episode.Id, }
EpisodeNumber = episode.EpisodeNumber, else
Language = episode.Language.Abbriviation, {
Overview = episode.Overview, newList.Add(newEpisode);
SeasonId = episode.SeasonId, }
SeasonNumber = episode.SeasonNumber,
SeriesId = episode.SeriesId,
Title = episode.EpisodeName
};
_sonicRepo.Add<EpisodeInfo>(newEpisode);
successCount++; successCount++;
} }
catch (Exception e) catch (Exception e)
{ {
Logger.FatalException(String.Format("An error has occured while updating episode info for series {0}", seriesId), e); Logger.FatalException(String.Format("An error has occurred while updating episode info for series {0}", seriesId), e);
failCount++; failCount++;
} }
} }
_sonicRepo.AddMany(newList);
_sonicRepo.UpdateMany(updateList);
Logger.Info("Finished episode refresh for series:{0}. Success:{1} - Fail:{2} ", seriesId, successCount, failCount); Logger.Info("Finished episode refresh for series:{0}. Success:{1} - Fail:{2} ", seriesId, successCount, failCount);
} }

View File

@ -19,6 +19,6 @@ namespace NzbDrone.Core.Providers
/// <returns></returns> /// <returns></returns>
bool IsNeeded(RemoteEpisode episode); bool IsNeeded(RemoteEpisode episode);
void RefreshSeries(int seriesId); void RefreshEpisodeInfo(int seriesId);
} }
} }

View File

@ -8,9 +8,8 @@ namespace NzbDrone.Core.Providers
{ {
public interface ISeriesProvider public interface ISeriesProvider
{ {
IQueryable<Series> GetSeries(); IQueryable<Series> GetAllSeries();
Series GetSeries(int seriesId); Series GetSeries(int seriesId);
void SyncSeriesWithDisk();
/// <summary> /// <summary>
/// Determines if a series is being actively watched. /// Determines if a series is being actively watched.
@ -20,7 +19,7 @@ namespace NzbDrone.Core.Providers
bool IsMonitored(long id); bool IsMonitored(long id);
TvdbSeries MapPathToSeries(string path); TvdbSeries MapPathToSeries(string path);
void RegisterSeries(string path, TvdbSeries series); void AddSeries(string path, TvdbSeries series);
List<String> GetUnmappedFolders(); List<String> GetUnmappedFolders();
} }
} }

View File

@ -0,0 +1,8 @@
namespace NzbDrone.Core.Providers
{
public interface ISyncProvider
{
void SyncUnmappedFolders();
void BeginSyncUnmappedFolders();
}
}

View File

@ -33,7 +33,7 @@ namespace NzbDrone.Core.Providers
)", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); )", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);
private readonly INotificationProvider _notificationProvider;
private readonly IConfigProvider _config; private readonly IConfigProvider _config;
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IRepository _sonioRepo; private readonly IRepository _sonioRepo;
@ -41,11 +41,8 @@ namespace NzbDrone.Core.Providers
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static readonly Regex CleanUpRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex CleanUpRegex = new Regex(@"((\s|^)the(\s|$))|((\s|^)and(\s|$))|[^a-z]", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private ProgressNotification _progress; public SeriesProvider(IDiskProvider diskProvider, IConfigProvider configProvider, IRepository dataRepository, ITvDbProvider tvDbProvider)
public SeriesProvider(INotificationProvider notificationProvider, IDiskProvider diskProvider, IConfigProvider configProvider, IRepository dataRepository, ITvDbProvider tvDbProvider)
{ {
_notificationProvider = notificationProvider;
_diskProvider = diskProvider; _diskProvider = diskProvider;
_config = configProvider; _config = configProvider;
_sonioRepo = dataRepository; _sonioRepo = dataRepository;
@ -54,7 +51,7 @@ namespace NzbDrone.Core.Providers
#region ISeriesProvider Members #region ISeriesProvider Members
public IQueryable<Series> GetSeries() public IQueryable<Series> GetAllSeries()
{ {
return _sonioRepo.All<Series>(); return _sonioRepo.All<Series>();
} }
@ -89,52 +86,12 @@ namespace NzbDrone.Core.Providers
return CleanTitleRegex.Replace(match.Groups["showName"].Value, String.Empty).Replace(".", " "); return CleanTitleRegex.Replace(match.Groups["showName"].Value, String.Empty).Replace(".", " ");
} }
public void SyncSeriesWithDisk() public List<String> GetUnmappedFolders()
{ {
if (_progress != null && _progress.Status == NotificationStatus.InProgress) Logger.Debug("Generating list of unmapped folders");
throw new InvalidOperationException("Another Task is already in progress. " + _progress.Title);
if (String.IsNullOrEmpty(_config.SeriesRoot)) if (String.IsNullOrEmpty(_config.SeriesRoot))
throw new InvalidOperationException("TV Series folder is not configured yet."); throw new InvalidOperationException("TV Series folder is not configured yet.");
using (_progress = new ProgressNotification("Updating Series From Disk"))
{
_notificationProvider.Register(_progress);
var unmappedFolders = GetUnmappedFolders();
_progress.ProgressMax = unmappedFolders.Count;
foreach (string seriesFolder in unmappedFolders)
{
_progress.CurrentStatus = String.Format("Mapping folder {0}", seriesFolder);
Logger.Info("Folder '{0}' isn't mapped to a series in the database. Trying to map it.'", seriesFolder);
var mappedSeries = MapPathToSeries(seriesFolder);
if (mappedSeries == null)
{
Logger.Warn("Unable to find a matching series for '{0}'", seriesFolder);
}
else
{
if (!_sonioRepo.Exists<Series>(s => s.SeriesId == mappedSeries.Id))
{
RegisterSeries(seriesFolder, mappedSeries);
}
else
{
Logger.Warn("Folder '{0}' mapped to '{1}' which is already another folder assigned to it.'", seriesFolder, mappedSeries.SeriesName);
}
}
_progress.ProgressValue++;
}
_progress.Status = NotificationStatus.Completed;
}
}
public List<String> GetUnmappedFolders()
{
var results = new List<String>(); var results = new List<String>();
foreach (string seriesFolder in _diskProvider.GetDirectories(_config.SeriesRoot)) foreach (string seriesFolder in _diskProvider.GetDirectories(_config.SeriesRoot))
{ {
@ -145,6 +102,7 @@ namespace NzbDrone.Core.Providers
} }
} }
Logger.Debug("{0} unmapped folders detected.", results.Count);
return results; return results;
} }
@ -160,9 +118,9 @@ namespace NzbDrone.Core.Providers
} }
public void RegisterSeries(string path, TvdbSeries series) public void AddSeries(string path, TvdbSeries series)
{ {
Logger.Info("registering '{0}' with [{1}]-{2}", path, series.Id, series.SeriesName); Logger.Info("Adding Series [{0}]:{1} Path: {2}", series.Id, series.SeriesName, path);
var repoSeries = new Series(); var repoSeries = new Series();
repoSeries.SeriesId = series.Id; repoSeries.SeriesId = series.Id;
repoSeries.Title = series.SeriesName; repoSeries.Title = series.SeriesName;

View File

@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using NLog;
using NzbDrone.Core.Entities.Notification;
namespace NzbDrone.Core.Providers
{
public class SyncProvider : ISyncProvider
{
private readonly ISeriesProvider _seriesProvider;
private readonly IEpisodeProvider _episodeProvider;
private readonly INotificationProvider _notificationProvider;
private ProgressNotification _seriesSyncNotification;
private Thread _seriesSyncThread;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public SyncProvider(ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider, INotificationProvider notificationProvider)
{
_seriesProvider = seriesProvider;
_episodeProvider = episodeProvider;
_notificationProvider = notificationProvider;
}
public void BeginSyncUnmappedFolders()
{
Logger.Debug("User has request series folder scan");
if (_seriesSyncThread == null || !_seriesSyncThread.IsAlive)
{
Logger.Debug("Initializing background scan of series folder.");
_seriesSyncThread = new Thread(SyncUnmappedFolders)
{
Name = "SyncUnmappedFolders",
Priority = ThreadPriority.BelowNormal
};
_seriesSyncThread.Start();
}
else
{
Logger.Warn("Series folder scan already in progress. Ignoring request.");
}
}
public void SyncUnmappedFolders()
{
Logger.Info("Starting Series folder scan");
try
{
using (_seriesSyncNotification = new ProgressNotification("Series folder scan"))
{
_notificationProvider.Register(_seriesSyncNotification);
var unmappedFolders = _seriesProvider.GetUnmappedFolders();
_seriesSyncNotification.ProgressMax = unmappedFolders.Count;
foreach (string seriesFolder in unmappedFolders)
{
try
{
_seriesSyncNotification.CurrentStatus = String.Format("Mapping folder \\{0}", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(new DirectoryInfo(seriesFolder).Name));
Logger.Info("Folder '{0}' isn't mapped in the database. Trying to map it.'", seriesFolder);
var mappedSeries = _seriesProvider.MapPathToSeries(seriesFolder);
if (mappedSeries == null)
{
Logger.Warn("Unable to find a matching series for '{0}'", seriesFolder);
}
else
{
//Check if series is mapped to another folder
if (_seriesProvider.GetSeries(mappedSeries.Id) == null)
{
_seriesSyncNotification.CurrentStatus = String.Format("Downloading Info for '{0}'", mappedSeries.SeriesName);
_seriesProvider.AddSeries(seriesFolder, mappedSeries);
_episodeProvider.RefreshEpisodeInfo(mappedSeries.Id);
}
else
{
Logger.Warn("Folder '{0}' mapped to '{1}' which is already another folder assigned to it.'", seriesFolder, mappedSeries.SeriesName);
}
}
}
catch (Exception e)
{
Logger.ErrorException("", e);
}
_seriesSyncNotification.ProgressValue++;
}
_seriesSyncNotification.Status = NotificationStatus.Completed;
}
Logger.Info("Series folders scan has successfully completed.");
}
catch (Exception e)
{
Logger.ErrorException("", e);
}
}
}
}

View File

@ -67,7 +67,7 @@ namespace NzbDrone.Core.Providers
/// </returns> /// </returns>
public static bool IsTitleMatch(string directoryName, string tvdbTitle) public static bool IsTitleMatch(string directoryName, string tvdbTitle)
{ {
Logger.Debug("Trying to match '{0}' and '{1}'", tvdbTitle, directoryName);
var result = false; var result = false;

View File

@ -12,39 +12,40 @@ namespace NzbDrone.Web.Controllers
{ {
private readonly ISeriesProvider _seriesProvider; private readonly ISeriesProvider _seriesProvider;
private readonly IEpisodeProvider _episodeProvider; private readonly IEpisodeProvider _episodeProvider;
private readonly ISyncProvider _syncProvider;
// //
// GET: /Series/ // GET: /Series/
public SeriesController(ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider) public SeriesController(ISyncProvider syncProvider, ISeriesProvider seriesProvider, IEpisodeProvider episodeProvider)
{ {
_seriesProvider = seriesProvider; _seriesProvider = seriesProvider;
_episodeProvider = episodeProvider; _episodeProvider = episodeProvider;
_syncProvider = syncProvider;
} }
public ActionResult Index() public ActionResult Index()
{ {
ViewData.Model = _seriesProvider.GetSeries().ToList(); ViewData.Model = _seriesProvider.GetAllSeries().ToList();
return View(); return View();
} }
public ActionResult Sync() public ActionResult Sync()
{ {
_seriesProvider.SyncSeriesWithDisk(); _syncProvider.BeginSyncUnmappedFolders();
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
public ActionResult UnMapped() public ActionResult UnMapped()
{ {
_seriesProvider.SyncSeriesWithDisk();
return View(_seriesProvider.GetUnmappedFolders()); return View(_seriesProvider.GetUnmappedFolders());
} }
public ActionResult LoadEpisodes(int seriesId) public ActionResult LoadEpisodes(int seriesId)
{ {
_episodeProvider.RefreshSeries(seriesId); _episodeProvider.RefreshEpisodeInfo(seriesId);
return RedirectToAction("Details", new return RedirectToAction("Details", new
{ {
seriesId = seriesId seriesId = seriesId
@ -82,9 +83,9 @@ namespace NzbDrone.Web.Controllers
default: default:
break; break;
} }
return Json(new { Success=true}, JsonRequestBehavior.AllowGet); return Json(new { Success = true }, JsonRequestBehavior.AllowGet);
} }
// //
// GET: /Series/Details/5 // GET: /Series/Details/5

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Routing; using System.Web.Routing;
@ -12,6 +13,7 @@ namespace NzbDrone.Web
{ {
public class MvcApplication : NinjectHttpApplication public class MvcApplication : NinjectHttpApplication
{ {
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static void RegisterRoutes(RouteCollection routes) public static void RegisterRoutes(RouteCollection routes)
{ {
@ -29,6 +31,7 @@ namespace NzbDrone.Web
protected override void OnApplicationStarted() protected override void OnApplicationStarted()
{ {
Instrumentation.Setup(); Instrumentation.Setup();
CentralDispatch.DedicateToHost();
AreaRegistration.RegisterAllAreas(); AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes); RegisterRoutes(RouteTable.Routes);
base.OnApplicationStarted(); base.OnApplicationStarted();
@ -42,7 +45,20 @@ namespace NzbDrone.Web
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
protected void Application_Error(object sender, EventArgs e) protected void Application_Error(object sender, EventArgs e)
{ {
Instrumentation.LogEpicException(Server.GetLastError()); var lastError = Server.GetLastError();
if (lastError is HttpException)
{
Logger.WarnException("", lastError);
}
else
{
Logger.FatalException("", lastError);
}
}
protected void Application_BeginRequest()
{
Thread.CurrentThread.Name = "UI";
} }

View File

@ -40,6 +40,7 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\NzbDrone.Core\Libraries\Ninject.dll</HintPath> <HintPath>..\NzbDrone.Core\Libraries\Ninject.dll</HintPath>
</Reference> </Reference>
<Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
@ -247,6 +248,11 @@
<Name>NzbDrone.Core</Name> <Name>NzbDrone.Core</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="log.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -5,12 +5,12 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("NzbDrone.Web")] [assembly: AssemblyTitle("NZBDrone.Web")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("NZBDrone Web Interface")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyCompany("www.nzbdrone.com")]
[assembly: AssemblyProduct("NzbDrone.Web")] [assembly: AssemblyProduct("NZBDrone")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] [assembly: AssemblyCopyright("GNU General Public v3")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -31,5 +31,4 @@ using System.Runtime.InteropServices;
// //
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyVersion("0.2.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,13 +1,13 @@
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<NzbDrone.Core.Entities.Series>>" %> <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<NzbDrone.Core.Entities.Series>>" %>
<%@ Import Namespace="Telerik.Web.Mvc.UI" %> <%@ Import Namespace="Telerik.Web.Mvc.UI" %>
<%@ Import Namespace="System.Globalization" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Series Series
</asp:Content> </asp:Content>
<asp:Content ID="Menue" ContentPlaceHolderID="ActionMenue" runat="server"> <asp:Content ID="Menue" ContentPlaceHolderID="ActionMenue" runat="server">
<div id="Mediabox"></div> <div id="Mediabox">
</div>
<% <%
Html.Telerik().Menu().Name("telerikGrid").Items(items => { items.Add().Text("View Unmapped Folders").Action("Unmapped", "Series"); }) Html.Telerik().Menu().Name("telerikGrid").Items(items => { items.Add().Text("View Unmapped Folders").Action("Unmapped", "Series"); })
.Items(items => items.Add().Text("Sync With Disk").Action("Sync", "Series")) .Items(items => items.Add().Text("Sync With Disk").Action("Sync", "Series"))
@ -16,7 +16,7 @@
</asp:Content> </asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% <%
Html.Telerik().Grid(Model) Html.Telerik().Grid(Model)
.Name("Grid") .Name("Grid")

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
</startup>
<appSettings /> <appSettings />
<system.web> <system.web>
<compilation debug="true" targetFramework="4.0"> <compilation debug="true" targetFramework="4.0">
@ -11,6 +14,8 @@
<!-- <add assembly="NzbDrone.Core"/>--> <!-- <add assembly="NzbDrone.Core"/>-->
</assemblies> </assemblies>
</compilation> </compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"> <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces> <namespaces>
<add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc" />
@ -21,7 +26,7 @@
<!--<add namespace="NzbDrone.Core.Repository"/>--> <!--<add namespace="NzbDrone.Core.Repository"/>-->
</namespaces> </namespaces>
</pages> </pages>
<customErrors mode="On"/> <customErrors mode="Off"/>
</system.web> </system.web>
<system.web.extensions /> <system.web.extensions />
<system.webServer> <system.webServer>

26
NzbDrone.Web/log.config Normal file
View File

@ -0,0 +1,26 @@
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true">
<targets>
<target name="consoleTarget" xsi:type="ColoredConsole" layout="${logger}: ${message}" />
<target name="debugTarget" xsi:type="Debugger" layout="${logger}: ${message}" />
<target name="udpTarget" xsi:type="Chainsaw" address="udp://127.0.0.1:7777"
includeCallSite="true" includeSourceInfo="true" includeNLogData="true" includeNDC="true" includeMDC="true">
<parameter name="exception" layout="${exception:format=ToString}" xsi:type="NLogViewerParameterInfo" />
<parameter name="processname" layout="${processname}" xsi:type="NLogViewerParameterInfo" />
<parameter name="stacktrace" layout="${stacktrace:topFrames=99}" xsi:type="NLogViewerParameterInfo" />
<parameter name="ThreadName" layout="${threadname}" xsi:type="NLogViewerParameterInfo" />
</target>
</targets>
<rules>
<logger name="IIS*" minlevel="Trace" writeTo="consoleTarget"/>
<logger name="Application" minlevel="Trace" writeTo="consoleTarget"/>
<logger name="*" minlevel="Trace" writeTo="udpTarget"/>
<!--<logger name="*" minlevel="Off" writeTo="debugTarget"/>-->
</rules>
</nlog>

Binary file not shown.

View File

@ -1,13 +1,9 @@
using System; using System;
using System.Collections.Generic;
using System.Configuration; using System.Configuration;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using NLog; using NLog;
using NLog.Config; using NLog.Config;
using NLog.Targets;
namespace NzbDrone namespace NzbDrone
{ {
@ -33,41 +29,11 @@ namespace NzbDrone
return _projectRoot; return _projectRoot;
} }
} }
internal static void ConfigureNlog() internal static void ConfigureNlog()
{ {
var config = new LoggingConfiguration(); LogManager.Configuration = new XmlLoggingConfiguration(Path.Combine(ProjectRoot, "NZBDrone.Web\\log.config"), false);
var debuggerTarget = new DebuggerTarget
{
Layout = "${logger}: ${message}"
};
var consoleTarget = new ColoredConsoleTarget
{
Layout = "${logger}: ${message}"
};
config.AddTarget("debugger", debuggerTarget);
config.AddTarget("console", consoleTarget);
//config.AddTarget("file", fileTarget);
// Step 3. Set target properties
// Step 4. Define rules
//LoggingRule fileRule = new LoggingRule("*", LogLevel.Trace, fileTarget);
var debugRule = new LoggingRule("*", LogLevel.Trace, debuggerTarget);
var consoleRule = new LoggingRule("*", LogLevel.Trace, consoleTarget);
//config.LoggingRules.Add(fileRule);
config.LoggingRules.Add(debugRule);
config.LoggingRules.Add(consoleRule);
// Step 5. Activate the configuration
LogManager.Configuration = config;
} }
internal static int Port internal static int Port

View File

@ -29,7 +29,7 @@ namespace NzbDrone
IISProcess = new Process(); IISProcess = new Process();
IISProcess.StartInfo.FileName = IISExe; IISProcess.StartInfo.FileName = IISExe;
IISProcess.StartInfo.Arguments = "/config:IISExpress\\Appserver\\applicationhost.config"; IISProcess.StartInfo.Arguments = "/config:IISExpress\\Appserver\\applicationhost.config /trace:i";
IISProcess.StartInfo.WorkingDirectory = Config.ProjectRoot; IISProcess.StartInfo.WorkingDirectory = Config.ProjectRoot;
IISProcess.StartInfo.UseShellExecute = false; IISProcess.StartInfo.UseShellExecute = false;
@ -37,9 +37,13 @@ namespace NzbDrone
IISProcess.StartInfo.RedirectStandardError = true; IISProcess.StartInfo.RedirectStandardError = true;
IISProcess.StartInfo.CreateNoWindow = true; IISProcess.StartInfo.CreateNoWindow = true;
IISProcess.OutputDataReceived += ((s, e) => IISLogger.Trace(e.Data));
IISProcess.OutputDataReceived += (OnDataReceived);
IISProcess.ErrorDataReceived += ((s, e) => IISLogger.Fatal(e.Data)); IISProcess.ErrorDataReceived += ((s, e) => IISLogger.Fatal(e.Data));
//Set Variables for the config file. //Set Variables for the config file.
Environment.SetEnvironmentVariable("NZBDRONE_PATH", Config.ProjectRoot); Environment.SetEnvironmentVariable("NZBDRONE_PATH", Config.ProjectRoot);
UpdateIISConfig(); UpdateIISConfig();
@ -52,6 +56,14 @@ namespace NzbDrone
return IISProcess; return IISProcess;
} }
private static void OnDataReceived(object s, DataReceivedEventArgs e)
{
if (e == null || e.Data == null || e.Data.StartsWith("Request started:") || e.Data.StartsWith("Request ended:") || e.Data == ("IncrementMessages called"))
return;
IISLogger.Trace(e.Data);
}
internal static void StopIIS() internal static void StopIIS()
{ {
KillProcess(IISProcess); KillProcess(IISProcess);
@ -59,11 +71,9 @@ namespace NzbDrone
internal static void KillOrphaned() internal static void KillOrphaned()
{ {
Logger.Trace("================================================");
Logger.Info("Finding orphaned IIS Processes."); Logger.Info("Finding orphaned IIS Processes.");
foreach (var process in Process.GetProcessesByName("IISExpress")) foreach (var process in Process.GetProcessesByName("IISExpress"))
{ {
Logger.Trace("-------------------------");
string processPath = process.MainModule.FileName; string processPath = process.MainModule.FileName;
Logger.Info("[{0}]IIS Process found. Path:{1}", process.Id, processPath); Logger.Info("[{0}]IIS Process found. Path:{1}", process.Id, processPath);
if (CleanPath(processPath) == CleanPath(IISExe)) if (CleanPath(processPath) == CleanPath(IISExe))
@ -75,13 +85,9 @@ namespace NzbDrone
{ {
Logger.Info("[{0}]Process has a different start-up path. skipping.", process.Id); Logger.Info("[{0}]Process has a different start-up path. skipping.", process.Id);
} }
Logger.Trace("-------------------------");
} }
Logger.Trace("================================================");
} }
private static void KillProcess(Process process) private static void KillProcess(Process process)
{ {
if (process == null) return; if (process == null) return;

View File

@ -38,6 +38,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<UseVSHostingProcess>true</UseVSHostingProcess>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>

View File

@ -2,6 +2,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading;
using Exceptioneer.WindowsFormsClient; using Exceptioneer.WindowsFormsClient;
using NLog; using NLog;
using NLog.Config; using NLog.Config;
@ -16,8 +17,12 @@ namespace NzbDrone
static void Main() static void Main()
{ {
Logger.Info(Process.GetCurrentProcess().Id);
try try
{ {
Thread.CurrentThread.Name = "Host";
AppDomain.CurrentDomain.UnhandledException += ((s, e) => AppDomainException(e)); AppDomain.CurrentDomain.UnhandledException += ((s, e) => AppDomainException(e));
AppDomain.CurrentDomain.ProcessExit += ProgramExited; AppDomain.CurrentDomain.ProcessExit += ProgramExited;
AppDomain.CurrentDomain.DomainUnload += ProgramExited; AppDomain.CurrentDomain.DomainUnload += ProgramExited;
@ -35,8 +40,8 @@ namespace NzbDrone
#if DEBUG #if DEBUG
//Manually Attach debugger to IISExpress //Manually Attach debugger to IISExpress
if (Debugger.IsAttached) if (Debugger.IsAttached)
{ {
ProcessAttacher.Attach(); ProcessAttacher.Attach();
} }
#endif #endif

View File

@ -5,10 +5,12 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("NzbDrone.Console")] [assembly: AssemblyTitle("NZBDrone")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("NZBDrone")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("NzbDrone.Console")] [assembly: AssemblyCompany("www.nzbdrone.com")]
[assembly: AssemblyProduct("NZBDrone")]
[assembly: AssemblyCopyright("GNU General Public v3")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -31,5 +33,4 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1.0.0")] [assembly: AssemblyVersion("0.2.0.*")]
[assembly: AssemblyFileVersion("0.1.0.0")]

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<setParameter name="IIS Web Application Name" value="Default Web Site/NzbDrone.Web_deploy" />
</parameters>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<sitemanifest>
<IisApp path="D:\My Dropbox\Git\NzbDrone\NzbDrone.Web\obj\Debug\Package\PackageTmp" managedRuntimeVersion="v4.0" />
<setAcl path="D:\My Dropbox\Git\NzbDrone\NzbDrone.Web\obj\Debug\Package\PackageTmp" setAclResourceType="Directory" />
<setAcl path="D:\My Dropbox\Git\NzbDrone\NzbDrone.Web\obj\Debug\Package\PackageTmp" setAclUser="anonymousAuthenticationUser" setAclResourceType="Directory" />
</sitemanifest>

View File

@ -1,57 +0,0 @@

===========================
Prerequisites :
--------------------------
To deploy this Web package, Web Deploy (msdeploy.exe) must be installed on the computer that runs the .cmd file. For information about how to install Web Deploy, see the following URL:
http://go.microsoft.com/?linkid=9278654
This batch file requires that the package file "NzbDrone.Web.zip" and optionally provided the parameters file "NzbDrone.Web.SetParameters.xml" in the same folder or destination folder by environment variable.
===========================
Usage:
--------------------------
NzbDrone.Web.deploy.cmd [/T|/Y] [/M:ComputerName] [/U:UserName] [/P:Password] [/G:UseTempAgent] [Additional msdeploy.exe flags ...]
===========================
Required Flags:
--------------------------
/T:
Calls msdeploy.exe with the "-whatif" flag, which simulates deployment. This does not deploy the package. Instead, it creates a report of what will happen when you actually deploy the package.
/Y:
Calls msdeploy.exe without the "-whatif" flag, which deploys the package to the current machine or a destination server. Use /Y after you have verified the output that was generated by using the /T flag.
Note: Do not use /T and /Y in the same command.
===========================
Optional Flags:
--------------------------
By Default, this script deploy on the current machine where this script is called with current user credential without agent service. Only pass the following value for advance scenario.
/M:<Destination server name or Service URL>
If this flag is not specified, the package is installed on the computer where the command is run. The Service URL can be in the following format:
https://<DestinationServer>:8172/MSDeploy.axd
This format requires that IIS 7 be installed on the destination server and that IIS 7 Web Management Service(WMSvc) and Web Deployment Handler be set up.
The service URL can also be in the following format:
http://<DestinationServer>/MSDeployAgentService
This format requires administrative rights on the destination server, and it requires that Web Deploy Remote Service (MsDepSvc) be installed on the destination server. IIS 7 does not have to be installed on the destination server.
/U:<UserName>
/P:<Password>
/G:<True | False>
Specifies that the package is deployed by creating a temporary listener on the destination server. This requires no special installation on the destination server, but it requires you to be an administrator on that server. The default value of this flag is False.
[Additional msdeploy.exe flags]
The msdeploy.exe command supports additional flags. You can include any of these additional flags in the "$(ProjectName).Deploy.cmd" file, and the flags are passed through to msdeploy.exe during execution.
Alternatively, you can specify additional flags by setting the "_MsDeployAdditionalFlags" environment variable. These settings are used by this batch file.
Note: Any flag value that includes an equal sign (=) must be enclosed in double quotation marks, as shown in the following example, which will skip deploying the databases that are included in the package:
"-skip:objectName=dbFullSql"
===========================
Environment-Specific Settings:
--------------------------
To customize application-specific settings for each deployment environment (for example, the IIS application name, the physical path, and any connection strings), edit the settings in the following file:
"NzbDrone.Web.SetParameters.xml"
===========================
For more information on this deploy script visit: http://go.microsoft.com/fwlink/?LinkID=183544

View File

@ -1,189 +0,0 @@
@rem ---------------------------------------------------------------------------------
@rem Copyright 2008 Microsoft Corporation. All rights reserved.
@rem This is provided as sample to deploy the package using msdeploy.exe
@rem For information about IIS Web Deploy technology,
@rem please visit http://go.microsoft.com/?linkid=9278654
@rem Note: This batch file assumes the package and setparametsrs.xml are in the same folder with this file
@rem ---------------------------------------------------------------------------------
@if %_echo%!==! echo off
setlocal
@rem ---------------------------------------------------------------------------------
@rem Please Make sure you have Web Deploy install in your machine.
@rem Alternatively, you can explicit set the MsDeployPath to the location it is on your machine
@rem set MSDeployPath="C:\Program Files (x86)\IIS\Microsoft Web Deploy\"
@rem ---------------------------------------------------------------------------------
@rem ---------------------------------------------------------------------------------
@rem if user does not set MsDeployPath environment variable, we will try to retrieve it from registry.
@rem ---------------------------------------------------------------------------------
if "%MSDeployPath%" == "" (
for /F "usebackq tokens=2*" %%i in (`reg query "HKLM\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\1" /v InstallPath`) do (
if "%%~dpj" == "%%j" (
set MSDeployPath=%%j
)))
if not exist "%MSDeployPath%\msdeploy.exe" (
echo. msdeploy.exe is not found on this machine. Please install Web Deploy before execute the script.
echo. Please visit http://go.microsoft.com/?linkid=9278654
goto :usage
)
set RootPath=%~dp0
if /I "%_DeploySetParametersFile%" == "" (
set _DeploySetParametersFile=%RootPath%NzbDrone.Web.SetParameters.xml
)
set _ArgTestDeploy=
set _ArgDestinationType=auto
set _ArgComputerName=
set _ArgUserName=
set _ArgPassword=
set _ArgEncryptPassword=
set _ArgIncludeAcls=False
set _ArgAuthType=
set _ArgtempAgent=
@rem ---------------------------------------------------------------------------------
@rem Simple Parse the arguments
@rem ---------------------------------------------------------------------------------
:NextArgument
set _ArgCurrent=%~1
if /I "%_ArgCurrent%" == "" goto :GetStarted
if /I "%_ArgCurrent%" == "/T" set _ArgTestDeploy=true&goto :ArgumentOK
if /I "%_ArgCurrent%" == "/Y" set _ArgTestDeploy=false&goto :ArgumentOK
set _ArgFlag=%_ArgCurrent:~0,3%
set _ArgValue=%_ArgCurrent:~3%
if /I "%_ArgFlag%" == "/M:" set _ArgComputerName=%_ArgValue%&goto :ArgumentOK
if /I "%_ArgFlag%" == "/U:" set _ArgUserName=%_ArgValue%&goto :ArgumentOK
if /I "%_ArgFlag%" == "/P:" set _ArgPassword=%_ArgValue%&goto :ArgumentOK
if /I "%_ArgFlag%" == "/E:" set _ArgEncryptPassword=%_ArgValue%&goto :ArgumentOK
if /I "%_ArgFlag%" == "/I:" set _ArgIncludeAcls=%_ArgValue%&goto :ArgumentOK
if /I "%_ArgFlag%" == "/A:" set _ArgAuthType=%_ArgValue%&goto :ArgumentOK
if /I "%_ArgFlag%" == "/G:" set _ArgtempAgent=%_ArgValue%&goto :ArgumentOK
@rem Any addition flags, pass through to the msdeploy
set _ArgMsDeployAdditionalFlags=%_ArgMsDeployAdditionalFlags% %_ArgCurrent%
:ArgumentOK
shift
goto :NextArgument
:GetStarted
if /I "%_ArgTestDeploy%" == "" goto :usage
if /I "%_ArgDestinationType%" == "" goto :usage
set _Destination=%_ArgDestinationType%
if not "%_ArgComputerName%" == "" set _Destination=%_Destination%,computerName='%_ArgComputerName%'
if not "%_ArgUserName%" == "" set _Destination=%_Destination%,userName='%_ArgUserName%'
if not "%_ArgPassword%" == "" set _Destination=%_Destination%,password='%_ArgPassword%'
if not "%_ArgAuthType%" == "" set _Destination=%_Destination%,authtype='%_ArgAuthType%'
if not "%_ArgEncryptPassword%" == "" set _Destination=%_Destination%,encryptPassword='%_ArgEncryptPassword%'
if not "%_ArgIncludeAcls%" == "" set _Destination=%_Destination%,includeAcls='%_ArgIncludeAcls%'
if not "%_ArgtempAgent%" == "" set _Destination=%_Destination%,tempAgent='%_ArgtempAgent%'
@rem ---------------------------------------------------------------------------------
@rem add -whatif when -T is specified
@rem ---------------------------------------------------------------------------------
if /I "%_ArgTestDeploy%" NEQ "false" (
set _MsDeployAdditionalFlags=%_MsDeployAdditionalFlags% -whatif
)
@rem ---------------------------------------------------------------------------------
@rem pass through the addition msdeploy.exe Flags
@rem ---------------------------------------------------------------------------------
set _MsDeployAdditionalFlags=%_MsDeployAdditionalFlags% %_ArgMsDeployAdditionalFlags%
@rem ---------------------------------------------------------------------------------
@rem check the existence of the package file
@rem ---------------------------------------------------------------------------------
if not exist "%RootPath%NzbDrone.Web.zip" (
echo "%RootPath%NzbDrone.Web.zip" does not exist.
echo This batch file relies on this deploy source file^(s^) in the same folder.
goto :usage
)
@rem ---------------------------------------------------------------------------------
@rem Execute msdeploy.exe command line
@rem ---------------------------------------------------------------------------------
call :CheckParameterFile
echo. Start executing msdeploy.exe
echo -------------------------------------------------------
if not exist "%_DeploySetParametersFile%" (
echo. "%MSDeployPath%\msdeploy.exe" -source:package='%RootPath%NzbDrone.Web.zip' -dest:%_Destination% -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -skip:objectname='dirPath',absolutepath='obj\\Debug\\Package\\PackageTmp\\App_Data$' %_MsDeployAdditionalFlags%
"%MSDeployPath%\msdeploy.exe" -source:package='%RootPath%NzbDrone.Web.zip' -dest:%_Destination% -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -skip:objectname='dirPath',absolutepath='obj\\Debug\\Package\\PackageTmp\\App_Data$' %_MsDeployAdditionalFlags%
) else (
echo. "%MSDeployPath%\msdeploy.exe" -source:package='%RootPath%NzbDrone.Web.zip' -dest:%_Destination% -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -skip:objectname='dirPath',absolutepath='obj\\Debug\\Package\\PackageTmp\\App_Data$' -setParamFile:"%RootPath%NzbDrone.Web.SetParameters.xml" %_MsDeployAdditionalFlags%
"%MSDeployPath%\msdeploy.exe" -source:package='%RootPath%NzbDrone.Web.zip' -dest:%_Destination% -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -skip:objectname='dirPath',absolutepath='obj\\Debug\\Package\\PackageTmp\\App_Data$' -setParamFile:"%RootPath%NzbDrone.Web.SetParameters.xml" %_MsDeployAdditionalFlags%
)
goto :eof
@rem ---------------------------------------------------------------------------------
@rem CheckParameterFile -- check if the package's setparamters.xml exists or not
@rem ---------------------------------------------------------------------------------
:CheckParameterFile
echo =========================================================
if exist "%_DeploySetParametersFile%" (
echo SetParameters from:
echo "%_DeploySetParametersFile%"
echo You can change IIS Application Name, Physical path, connectionString
echo or other deploy parameters in the above file.
) else (
echo SetParamterFiles does not exist in package location.
echo Use package embedded defaultValue to deploy.
)
echo -------------------------------------------------------
goto :eof
@rem ---------------------------------------------------------------------------------
@rem Usage
@rem ---------------------------------------------------------------------------------
:usage
echo =========================================================
if not exist "%RootPath%NzbDrone.Web.deploy-readme.txt" (
echo Usage:%~nx0 [/T^|/Y] [/M:ComputerName] [/U:userName] [/P:password] [/G:tempAgent] [additional msdeploy flags ...]
echo Required flags:
echo /T Calls msdeploy.exe with the "-whatif" flag, which simulates deployment.
echo /Y Calls msdeploy.exe without the "-whatif" flag, which deploys the package to the current machine or destination server
echo Optional flags:
echo. By Default, this script deploy to the current machine where this script is invoked which will use current user credential without tempAgent.
echo. Only pass these arguments when in advance scenario.
echo /M: Msdeploy destination name of remote computer or proxy-URL. Default is local.
echo /U: Msdeploy destination user name.
echo /P: Msdeploy destination password.
echo /G: Msdeploy destination tempAgent. True or False. Default is false.
echo.[additional msdeploy flags]: note: " is required for passing = through command line.
echo "-skip:objectName=setAcl" "-skip:objectName=dbFullSql"
echo.Alternative environment variable _MsDeployAdditionalFlags is also honored.
echo.
echo. Please make sure MSDeploy is installed in the box http://go.microsoft.com/?linkid=9278654
echo.
echo In addition, you can change IIS Application Name, Physical path,
echo connectionString and other deploy parameters in the following file:
echo "%_DeploySetParametersFile%"
echo.
echo For more information about this batch file, visit http://go.microsoft.com/fwlink/?LinkID=183544
) else (
start notepad "%RootPath%NzbDrone.Web.deploy-readme.txt"
)
echo =========================================================
goto :eof
@rem ---------------------------------------------------------------------------------
@rem CheckParameterFile -- check if the package's setparamters.xml exists or not
@rem ---------------------------------------------------------------------------------
:CheckParameterFile
echo =========================================================
if exist "%RootPath%NzbDrone.Web.SetParameters.xml" (
echo SetParameters from:
echo "%RootPath%NzbDrone.Web.SetParameters.xml"
echo You can change IIS Application Name, Physical path, connectionString
echo or other deploy parameters in the above file.
) else (
echo SetParamterFiles does not exist in package location.
echo Use package embedded defaultValue to deploy.
)
echo -------------------------------------------------------
goto :eof

Binary file not shown.