New: NzbDrone service to automatically report errors and episode parse issues.

pull/2/head
kay.one 12 years ago
parent ea86ce2fcb
commit 174f765ec9

3
.gitignore vendored

@ -45,4 +45,5 @@ config.xml
UpdateLogs/
NzbDrone.Web/MediaCover
NzbDrone.fpr
nzbdrone.log*txt
nzbdrone.log*txt
_rawPackage_service/

@ -64,6 +64,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ConfigFileProviderTest.cs" />
<Compile Include="ReportingService_ReportParseError_Fixture.cs" />
<Compile Include="PathExtentionFixture.cs" />
<Compile Include="DiskProviderFixture.cs" />
<Compile Include="EnviromentProviderTest.cs" />

@ -0,0 +1,68 @@
using System.Linq;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Contract;
using NzbDrone.Test.Common;
namespace NzbDrone.Common.Test
{
[TestFixture]
// ReSharper disable InconsistentNaming
public class ReportingService_ReportParseError_Fixture : TestBase
{
[SetUp]
public void SetUp()
{
ReportingService.ClearCache();
}
[TearDown]
public void TearDown()
{
ReportingService.ClearCache();
}
[Test]
public void report_parse_error_should_send_report_to_server()
{
const string badTitle = "Bad Title";
ReportingService.ReportParseError(badTitle);
MockedRestProvider.Verify(p => p.PostData(It.IsAny<string>(), It.Is<ParseErrorReport>(c => c.Title == badTitle)), Times.Once());
}
[Test]
public void report_parse_error_should_send_duplicated_report_once()
{
const string badTitle = "Bad Title";
ReportingService.ReportParseError(badTitle);
ReportingService.ReportParseError(badTitle);
MockedRestProvider.Verify(p => p.PostData(It.IsAny<string>(), It.IsAny<ReportBase>()), Times.Once());
}
[Test]
public void report_parse_error_should_send_duplicated_report_once_with_diffrent_casing()
{
const string badTitle = "Bad Title";
ReportingService.ReportParseError(badTitle.ToUpper());
ReportingService.ReportParseError(badTitle);
MockedRestProvider.Verify(p => p.PostData(It.IsAny<string>(), It.IsAny<ReportBase>()), Times.Once());
}
[Test]
public void report_parse_error_should_send_multiple_reports_if_titles_are_diffrent()
{
ReportingService.ReportParseError("title 1");
ReportingService.ReportParseError("title 2");
MockedRestProvider.Verify(p => p.PostData(It.IsAny<string>(), It.IsAny<ReportBase>()), Times.Exactly(2));
MockedRestProvider.Verify(p => p.PostData(It.IsAny<string>(), It.Is<ParseErrorReport>(c => c.Title == "title 1")), Times.Once());
MockedRestProvider.Verify(p => p.PostData(It.IsAny<string>(), It.Is<ParseErrorReport>(c => c.Title == "title 2")), Times.Once());
}
}
}

@ -0,0 +1,18 @@
using System.Linq;
using Newtonsoft.Json;
namespace NzbDrone.Common.Contract
{
public class ExceptionReport : ReportBase
{
[JsonProperty("t")]
public string Type { get; set; }
[JsonProperty("l")]
public string Logger { get; set; }
[JsonProperty("lm")]
public string LogMessage { get; set; }
[JsonProperty("s")]
public string String { get; set; }
}
}

@ -0,0 +1,11 @@
using System.Linq;
using Newtonsoft.Json;
namespace NzbDrone.Common.Contract
{
public class ParseErrorReport : ReportBase
{
[JsonProperty("t")]
public string Title { get; set; }
}
}

@ -0,0 +1,18 @@
using System;
using System.Linq;
using Newtonsoft.Json;
namespace NzbDrone.Common.Contract
{
public abstract class ReportBase
{
[JsonProperty("v")]
public string Version { get; set; }
[JsonProperty("p")]
public bool IsProduction { get; set; }
[JsonProperty("u")]
public Guid UGuid { get; set; }
}
}

@ -40,9 +40,11 @@ namespace NzbDrone.Common
}
}
public static Guid UGuid { get; set; }
public static bool IsNewInstall { get; set; }
public virtual bool IsUserInteractive
{
get { return Environment.UserInteractive; }

@ -3,6 +3,7 @@ using System.IO;
using NLog;
using NLog.Config;
using NLog.Targets;
using NzbDrone.Common.NlogTargets;
namespace NzbDrone.Common
{
@ -94,7 +95,7 @@ namespace NzbDrone.Common
{
var fileTarget = GetBaseTarget();
fileTarget.FileName = fileName;
LogManager.Configuration.AddTarget(Guid.NewGuid().ToString(), fileTarget);
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", level, fileTarget));
}
@ -112,7 +113,7 @@ namespace NzbDrone.Common
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", level, fileTarget));
}
public static void RegisterExceptioneer()
public static void RegisterRemote()
{
if (EnviromentProvider.IsProduction)
{
@ -121,14 +122,25 @@ namespace NzbDrone.Common
var exTarget = new ExceptioneerTarget();
LogManager.Configuration.AddTarget("Exceptioneer", exTarget);
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, exTarget));
LogManager.ConfigurationReloaded += (sender, args) => RegisterExceptioneer();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
try
{
var remoteTarget = new RemoteTarget();
LogManager.Configuration.AddTarget("RemoteTarget", remoteTarget);
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, remoteTarget));
}
catch (Exception e)
{
Console.WriteLine(e);
}
LogManager.ConfigurationReloaded += (sender, args) => RegisterRemote();
}
public static void Reload()

@ -1,10 +1,11 @@
using System;
using System.Linq;
using System;
using System.Diagnostics;
using Exceptioneer.WindowsFormsClient;
using NLog;
using NLog.Targets;
namespace NzbDrone.Common
namespace NzbDrone.Common.NlogTargets
{
public class ExceptioneerTarget : Target
{

@ -0,0 +1,21 @@
using System.Linq;
using System.Diagnostics;
using NLog;
using NLog.Targets;
namespace NzbDrone.Common.NlogTargets
{
public class RemoteTarget : Target
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
protected override void Write(LogEventInfo logEvent)
{
if (logEvent == null || logEvent.Exception == null) return;
logger.Trace("Sending Exception to Service.NzbDrone.com . Process Name: {0}", Process.GetCurrentProcess().ProcessName);
ReportingService.ReportException(logEvent);
}
}
}

@ -36,6 +36,9 @@
<Reference Include="Exceptioneer.WindowsFormsClient">
<HintPath>..\Libraries\Exceptioneer.WindowsFormsClient.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.4.0.7\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Ninject">
<HintPath>..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>
</Reference>
@ -52,17 +55,23 @@
<ItemGroup>
<Compile Include="ConfigFileProvider.cs" />
<Compile Include="ConsoleProvider.cs" />
<Compile Include="Contract\ExceptionReport.cs" />
<Compile Include="Contract\ReportBase.cs" />
<Compile Include="Contract\ParseErrorRequ.cs" />
<Compile Include="NlogTargets\RemoteTarget.cs" />
<Compile Include="IISProvider.cs" />
<Compile Include="Model\AuthenticationType.cs" />
<Compile Include="PathExtentions.cs" />
<Compile Include="DiskProvider.cs" />
<Compile Include="EnviromentProvider.cs" />
<Compile Include="ExceptioneerTarget.cs" />
<Compile Include="NlogTargets\ExceptioneerTarget.cs" />
<Compile Include="LogConfiguration.cs" />
<Compile Include="Model\ProcessInfo.cs" />
<Compile Include="ProcessProvider.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\SharedAssemblyInfo.cs" />
<Compile Include="ReportingService.cs" />
<Compile Include="RestProvider.cs" />
<Compile Include="SecurityProvider.cs" />
<Compile Include="ServiceProvider.cs" />
<Compile Include="WebClientProvider.cs" />

@ -12,5 +12,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.0.0.*")]
[assembly: AssemblyFileVersion("0.0.0.*")]
[assembly: AssemblyVersion("1.0.0.*")]
[assembly: AssemblyFileVersion("1.0.0.*")]

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Contract;
namespace NzbDrone.Common
{
public static class ReportingService
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private const string SERVICE_URL = "http://localhost.:1542/reporting";
private const string PARSE_URL = SERVICE_URL + "/parser";
private const string EXCEPTION_URL = SERVICE_URL + "/exception";
public static RestProvider RestProvider { get; set; }
private static readonly HashSet<string> parserErrorCache = new HashSet<string>();
public static void ClearCache()
{
lock (parserErrorCache)
{
parserErrorCache.Clear();
}
}
public static void ReportParseError(string title)
{
try
{
if (RestProvider == null && EnviromentProvider.IsProduction)
return;
lock (parserErrorCache)
{
if (parserErrorCache.Contains(title.ToLower())) return;
parserErrorCache.Add(title.ToLower());
}
var report = new ParseErrorReport { Title = title };
RestProvider.PostData(PARSE_URL, report);
}
catch (Exception e)
{
if (!EnviromentProvider.IsProduction)
{
throw;
}
e.Data.Add("title", title);
logger.ErrorException("Unable to report parse error", e);
}
}
public static void ReportException(LogEventInfo logEvent)
{
try
{
if (RestProvider == null && EnviromentProvider.IsProduction)
return;
var report = new ExceptionReport();
report.LogMessage = logEvent.FormattedMessage;
report.String = logEvent.Exception.ToString();
report.Logger = logEvent.LoggerName;
report.Type = logEvent.Exception.GetType().Name;
RestProvider.PostData(EXCEPTION_URL, report);
}
catch (Exception e)
{
if (!EnviromentProvider.IsProduction)
{
throw;
}
//this shouldn't log an exception since it might cause a recursive loop.
logger.Error("Unable to report exception. " + e);
}
}
}
}

@ -0,0 +1,67 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using Newtonsoft.Json;
using Ninject;
using NzbDrone.Common.Contract;
namespace NzbDrone.Common
{
public class RestProvider
{
private readonly EnviromentProvider _enviromentProvider;
[Inject]
public RestProvider(EnviromentProvider enviromentProvider)
{
_enviromentProvider = enviromentProvider;
}
public RestProvider()
{
}
private const int TIMEOUT = 10000;
private const string METHOD = "POST";
public virtual void PostData(string url, ReportBase reportBase)
{
reportBase.UGuid = EnviromentProvider.UGuid;
reportBase.Version = _enviromentProvider.Version.ToString();
reportBase.IsProduction = EnviromentProvider.IsProduction;
PostData(url, reportBase as object);
}
private static void PostData(string url, object message)
{
var json = JsonConvert.SerializeObject(message);
var request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = TIMEOUT;
request.Proxy = WebRequest.DefaultWebProxy;
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Method = METHOD;
request.ContentType = "application/json";
byte[] postBytes = Encoding.UTF8.GetBytes(json);
request.ContentLength = postBytes.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
var response = (HttpWebResponse)request.GetResponse();
var streamreader = new StreamReader(response.GetResponseStream());
streamreader.Close();
}
}
}

@ -70,9 +70,7 @@ namespace NzbDrone.Common
{
try
{
var currentIdentity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(currentIdentity);
var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch(Exception ex)

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="4.0.7" />
<package id="NLog" version="2.0.0.2000" />
</packages>

@ -33,6 +33,7 @@ namespace NzbDrone.Core.Test.Framework
TestDbHelper.CreateDataBaseTemplate();
}
private IDatabase _db;
protected IDatabase Db
{

@ -34,7 +34,7 @@ namespace NzbDrone.Core.Test.JobTests
{
Mocker.GetMock<EnviromentProvider>().SetupGet(c => c.SystemTemp).Returns(@"C:\Temp\");
Mocker.GetMock<ConfigFileProvider>().SetupGet(c => c.Guid).Returns(_clientGuid);
Mocker.GetMock<UpdateProvider>().Setup(c => c.GetAvilableUpdate()).Returns(updatePackage);
Mocker.GetMock<UpdateProvider>().Setup(c => c.GetAvilableUpdate(It.IsAny<Version>())).Returns(updatePackage);
}
@ -125,7 +125,7 @@ namespace NzbDrone.Core.Test.JobTests
[Test]
public void when_no_updates_are_available_should_return_without_error_or_warnings()
{
Mocker.GetMock<UpdateProvider>().Setup(c => c.GetAvilableUpdate()).Returns((UpdatePackage)null);
Mocker.GetMock<UpdateProvider>().Setup(c => c.GetAvilableUpdate(It.IsAny<Version>())).Returns((UpdatePackage)null);
StartUpdate();

@ -57,6 +57,10 @@
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.0.7.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.4.0.7\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Ninject, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
<HintPath>..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>
</Reference>
@ -131,6 +135,7 @@
<Compile Include="JobTests\AppUpdateJobFixture.cs" />
<Compile Include="ProviderTests\UpdateProviderTests\GetUpdateLogFixture.cs" />
<Compile Include="ProviderTests\UpdateProviderTests\GetAvilableUpdateFixture.cs" />
<Compile Include="Services\ParseErrorServiceFixture.cs" />
<Compile Include="SortHelperTest.cs" />
<Compile Include="ProviderTests\EpisodeProviderTest_DeleteInvalidEpisodes.cs" />
<Compile Include="ProviderTests\InventoryProviderTests\IsAcceptableSizeTestFixture.cs" />

@ -2,7 +2,10 @@
using System;
using System.Linq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Common.Contract;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework;
@ -50,7 +53,7 @@ namespace NzbDrone.Core.Test
[TestCase("Breaking.In.S01E07.21.0.Jump.Street.720p.WEB-DL.DD5.1.h.264-KiNGS", "Breaking In", 1, 7)]
[TestCase("CSI525", "CSI", 5, 25)]
[TestCase("King of the Hill - 10x12 - 24 Hour Propane People [SDTV]", "King of the Hill", 10, 12)]
[TestCase("Brew Masters S01E06 3 Beers For Batali DVDRip XviD SPRiNTER","Brew Masters", 1, 6)]
[TestCase("Brew Masters S01E06 3 Beers For Batali DVDRip XviD SPRiNTER", "Brew Masters", 1, 6)]
[TestCase("24 7 Flyers Rangers Road to the NHL Winter Classic Part01 720p HDTV x264 ORENJI", "24 7 Flyers Rangers Road to the NHL Winter Classic", 1, 1)]
[TestCase("24 7 Flyers Rangers Road to the NHL Winter Classic Part 02 720p HDTV x264 ORENJI", "24 7 Flyers Rangers Road to the NHL Winter Classic", 1, 2)]
[TestCase("24-7 Flyers-Rangers- Road to the NHL Winter Classic - S01E01 - Part 1", "24 7 Flyers Rangers Road to the NHL Winter Classic", 1, 1)]
@ -93,16 +96,24 @@ namespace NzbDrone.Core.Test
}
[Test]
public void unparsable_path()
public void unparsable_path_should_report_the_path()
{
Parser.ParsePath("C:\\").Should().BeNull();
MockedRestProvider.Verify(c => c.PostData(It.IsAny<string>(), It.IsAny<ParseErrorReport>()), Times.Exactly(2));
ExceptionVerification.IgnoreWarns();
}
[Test]
public void unparsable_title()
public void unparsable_title_should_report_title()
{
Parser.ParseTitle("SOMETHING").Should().BeNull();
const string TITLE = "SOMETHING";
Parser.ParseTitle(TITLE).Should().BeNull();
MockedRestProvider.Verify(c => c.PostData(It.IsAny<string>(), It.Is<ParseErrorReport>(r => r.Title == TITLE)), Times.Once());
ExceptionVerification.IgnoreWarns();
}

@ -131,8 +131,7 @@ namespace NzbDrone.Core.Test.ProviderTests
public void uguid_should_return_valid_result_on_first_call()
{
var guid = Mocker.Resolve<ConfigProvider>().UGuid;
guid.Should().NotBeBlank();
Guid.Parse(guid).ToString().Should().NotBe(new Guid().ToString());
guid.Should().NotBeEmpty();
}

@ -18,7 +18,7 @@ namespace NzbDrone.Core.Test.ProviderTests.UpdateProviderTests
private static string _latestsTestFileName = "NzbDrone.master.0.6.0.3.zip";
[SetUp]
public void setup()
public void Setup()
{
WithStrictMocker();
@ -31,9 +31,8 @@ namespace NzbDrone.Core.Test.ProviderTests.UpdateProviderTests
[TestCase("1.0.0.0")]
public void should_return_null_if_latests_is_lower_than_current_version(string currentVersion)
{
Mocker.GetMock<EnviromentProvider>().SetupGet(c => c.Version).Returns(new Version(currentVersion));
var updatePackage = Mocker.Resolve<UpdateProvider>().GetAvilableUpdate();
var updatePackage = Mocker.Resolve<UpdateProvider>().GetAvilableUpdate(new Version(currentVersion));
updatePackage.Should().BeNull();
}
@ -41,9 +40,7 @@ namespace NzbDrone.Core.Test.ProviderTests.UpdateProviderTests
[Test]
public void should_return_null_if_latests_is_equal_to_current_version()
{
Mocker.GetMock<EnviromentProvider>().SetupGet(c => c.Version).Returns(_latestsTestVersion);
var updatePackage = Mocker.Resolve<UpdateProvider>().GetAvilableUpdate();
var updatePackage = Mocker.Resolve<UpdateProvider>().GetAvilableUpdate(_latestsTestVersion);
updatePackage.Should().BeNull();
}
@ -53,9 +50,7 @@ namespace NzbDrone.Core.Test.ProviderTests.UpdateProviderTests
[TestCase("0.0.10.10")]
public void should_return_update_if_latests_is_higher_than_current_version(string currentVersion)
{
Mocker.GetMock<EnviromentProvider>().SetupGet(c => c.Version).Returns(new Version(currentVersion));
var updatePackage = Mocker.Resolve<UpdateProvider>().GetAvilableUpdate();
var updatePackage = Mocker.Resolve<UpdateProvider>().GetAvilableUpdate(new Version(currentVersion));
updatePackage.Should().NotBeNull();
updatePackage.Version.Should().Be(_latestsTestVersion);

@ -0,0 +1,30 @@
using System;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Services
{
[TestFixture]
public class ParseErrorServiceFixture : CoreTest
{
public ParseErrorServiceFixture()
{
AppDomain.CurrentDomain.AssemblyResolve +=
new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var name = new AssemblyName(args.Name);
if (name.Name == "Newtonsoft.Json")
{
return typeof(Newtonsoft.Json.JsonSerializer).Assembly;
}
return null;
}
}
}

@ -7,6 +7,7 @@
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" />
<package id="Moq" version="4.0.10827" />
<package id="NBuilder" version="3.0.1.1" />
<package id="Newtonsoft.Json" version="4.0.7" />
<package id="Ninject" version="2.2.1.4" />
<package id="NLog" version="2.0.0.2000" />
<package id="NUnit" version="2.5.10.11092" />

@ -32,7 +32,7 @@ namespace NzbDrone.Core
Kernel = new StandardKernel();
InitDatabase();
InitAnalytics();
InitReporting();
InitQuality();
InitExternalNotifications();
@ -58,13 +58,17 @@ namespace NzbDrone.Core
LogConfiguration.Reload();
}
private void InitAnalytics()
private void InitReporting()
{
EnviromentProvider.UGuid = Kernel.Get<ConfigProvider>().UGuid;
ReportingService.RestProvider = Kernel.Get<RestProvider>();
var appId = AnalyticsProvider.DESKMETRICS_TEST_ID;
if (EnviromentProvider.IsProduction)
appId = AnalyticsProvider.DESKMETRICS_PRODUCTION_ID;
var deskMetricsClient = new DeskMetricsClient(Kernel.Get<ConfigProvider>().UGuid, appId, _enviromentProvider.Version);
var deskMetricsClient = new DeskMetricsClient(Kernel.Get<ConfigProvider>().UGuid.ToString(), appId, _enviromentProvider.Version);
Kernel.Bind<IDeskMetricsClient>().ToConstant(deskMetricsClient);
Kernel.Get<AnalyticsProvider>().Checkpoint();
}

@ -5,7 +5,7 @@ using NLog;
namespace NzbDrone.Core.Datastore
{
class MigrationLogger : ILogger
public class MigrationLogger : ILogger
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

@ -0,0 +1,9 @@
using System.Linq;
namespace NzbDrone.Core.Datastore.Migrations
{
public class SchemaInfo
{
public int Version { get; set; }
}
}

@ -47,10 +47,10 @@ namespace NzbDrone.Core.Jobs
}
public virtual void Start(ProgressNotification notification, int targetId, int secondaryTargetId)
{
{
notification.CurrentMessage = "Checking for updates";
var updatePackage = _updateProvider.GetAvilableUpdate();
var updatePackage = _updateProvider.GetAvilableUpdate(_enviromentProvider.Version);
//No updates available
if (updatePackage == null)

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Collections.Generic;
using NzbDrone.Core.Repository;
@ -47,11 +48,11 @@ namespace NzbDrone.Core.Model
if (FullSeason)
return string.Format("{0} - Season {1:00}", SeriesTitle, SeasonNumber);
if (EpisodeNumbers != null)
if (EpisodeNumbers != null && EpisodeNumbers.Any())
return string.Format("{0} - S{1:00}E{2} {3}", SeriesTitle, SeasonNumber,
String.Join("-", EpisodeNumbers), Quality);
String.Join("-", EpisodeNumbers.Select(c => c.ToString("00"))), Quality);
return OriginalString;
return "[Invalid format]";
}
}

@ -195,7 +195,6 @@
<HintPath>..\Libraries\TvdbLib.dll</HintPath>
</Reference>
<Reference Include="Twitterizer2, Version=2.4.0.26532, Culture=neutral, PublicKeyToken=69d1469eac671567, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\twitterizer.2.4.0.26532\lib\net40\Twitterizer2.dll</HintPath>
</Reference>
<Reference Include="WebActivator, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
@ -222,6 +221,7 @@
<Compile Include="Datastore\Migrations\Migration20110707.cs" />
<Compile Include="Datastore\DbProviderFactory.cs" />
<Compile Include="Datastore\Migrations\NzbDroneMigration.cs" />
<Compile Include="Datastore\Migrations\SchemaInfo.cs" />
<Compile Include="Fluent.cs" />
<Compile Include="Helpers\EpisodeSortingHelper.cs" />
<Compile Include="Helpers\FileSizeFormatHelper.cs" />

@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository.Quality;
@ -113,12 +114,13 @@ namespace NzbDrone.Core
}
}
}
Logger.Warn("Unable to parse episode info. {0}", title);
}
catch (Exception e)
{
Logger.ErrorException("An error has occurred while trying to parse " + title, e);
}
Logger.Warn("Unable to parse episode info. {0}", title);
ReportingService.ReportParseError(title);
return null;
}
@ -399,12 +401,6 @@ namespace NzbDrone.Core
return LanguageType.English;
}
/// <summary>
/// Normalizes the title. removing all non-word characters as well as common tokens
/// such as 'the' and 'and'
/// </summary>
/// <param name = "title">title</param>
/// <returns></returns>
public static string NormalizeTitle(string title)
{
long number = 0;

@ -16,5 +16,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.0.0.*")]
[assembly: AssemblyFileVersion("0.0.0.*")]
[assembly: AssemblyVersion("1.0.0.*")]
[assembly: AssemblyFileVersion("1.0.0.*")]

@ -409,6 +409,11 @@ namespace NzbDrone.Core.Providers.Core
set { SetValue("AutoIgnorePreviouslyDownloadedEpisodes", value); }
}
public Guid UGuid
{
get { return Guid.Parse(GetValue("UGuid", Guid.NewGuid().ToString(), persist: true)); }
}
public virtual DownloadClientType DownloadClient
{
get { return (DownloadClientType)GetValueInt("DownloadClient"); }
@ -498,4 +503,4 @@ namespace NzbDrone.Core.Providers.Core
}
}
}
}
}

@ -113,5 +113,40 @@ namespace NzbDrone.Core.Providers.Core
return responseFromServer.Replace("&nbsp;", " ");
}
public virtual string Post(string address, string command, string username, string password)
{
Logger.Trace("Posting command: {0}, to {1}", command, address);
byte[] byteArray = Encoding.ASCII.GetBytes(command);
var request = (HttpWebRequest)WebRequest.Create(address);
request.Method = "POST";
request.Credentials = new NetworkCredential(username, password);
request.ContentType = "application/json";
request.Timeout = 2000;
request.KeepAlive = false;
//Used to hold the JSON response
string responseFromServer;
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(byteArray, 0, byteArray.Length);
using (var response = request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
responseFromServer = reader.ReadToEnd();
}
}
}
}
return responseFromServer.Replace("&nbsp;", " ");
}
}
}

@ -6,9 +6,7 @@ using Ninject;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using PetaPoco;
namespace NzbDrone.Core.Providers
{

@ -25,7 +25,7 @@ namespace NzbDrone.Core.Providers.Indexer
{
return new[]
{
"https://www.newzbin.com/browse/category/p/tv?" + URL_PARAMS
"https://www.newzbin2.es/browse/category/p/tv?" + URL_PARAMS
};
}
}
@ -50,7 +50,7 @@ namespace NzbDrone.Core.Providers.Indexer
return new List<string>
{
String.Format(
@"http://www.newzbin.com/search/query/?q={0}+{1}x{2:00}&fpn=p&searchaction=Go&category=8&{3}",
@"https://www.newzbin.es/search/query/?q={0}+{1}x{2:00}&fpn=p&searchaction=Go&category=8&{3}",
seriesTitle, seasonNumber,episodeNumber, URL_PARAMS)
};
}
@ -60,7 +60,7 @@ namespace NzbDrone.Core.Providers.Indexer
return new List<string>
{
String.Format(
@"http://www.newzbin.com/search/query/?q={0}+Season+{1}&fpn=p&searchaction=Go&category=8&{2}",
@"https://www.newzbin.es/search/query/?q={0}+Season+{1}&fpn=p&searchaction=Go&category=8&{2}",
seriesTitle, seasonNumber, URL_PARAMS)
};
}
@ -70,7 +70,7 @@ namespace NzbDrone.Core.Providers.Indexer
return new List<string>
{
String.Format(
@"http://www.newzbin.com/search/query/?q={0}+{1:yyyy-MM-dd}&fpn=p&searchaction=Go&category=8&{2}",
@"https://www.newzbin.es/search/query/?q={0}+{1:yyyy-MM-dd}&fpn=p&searchaction=Go&category=8&{2}",
seriesTitle, date, URL_PARAMS)
};
}
@ -80,7 +80,7 @@ namespace NzbDrone.Core.Providers.Indexer
return new List<string>
{
String.Format(
@"http://www.newzbin.com/search/query/?q={0}+{1}x{2}&fpn=p&searchaction=Go&category=8&{3}",
@"https://www.newzbin.es/search/query/?q={0}+{1}x{2}&fpn=p&searchaction=Go&category=8&{3}",
seriesTitle, seasonNumber, episodeWildcard, URL_PARAMS)
};
}

@ -61,13 +61,13 @@ namespace NzbDrone.Core.Providers
return updateList;
}
public virtual UpdatePackage GetAvilableUpdate()
public virtual UpdatePackage GetAvilableUpdate(Version currentVersion)
{
var latestAvailable = GetAvailablePackages().OrderByDescending(c => c.Version).FirstOrDefault();
if (latestAvailable != null && latestAvailable.Version > _enviromentProvider.Version)
if (latestAvailable != null && latestAvailable.Version > currentVersion)
{
logger.Debug("An update is available ({0}) => ({1})", _enviromentProvider.Version, latestAvailable.Version);
logger.Debug("An update is available ({0}) => ({1})", currentVersion, latestAvailable.Version);
return latestAvailable;
}

@ -0,0 +1,299 @@
/*
ELMAH - Error Logging Modules and Handlers for ASP.NET
Copyright (c) 2004-9 Atif Aziz. All rights reserved.
Author(s):
Atif Aziz, http://www.raboof.com
Phil Haacked, http://haacked.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
-- ELMAH DDL script for Microsoft SQL Server 2000 or later.
-- $Id: SQLServer.sql 677 2009-09-29 18:02:39Z azizatif $
DECLARE @DBCompatibilityLevel INT
DECLARE @DBCompatibilityLevelMajor INT
DECLARE @DBCompatibilityLevelMinor INT
SELECT
@DBCompatibilityLevel = cmptlevel
FROM
master.dbo.sysdatabases
WHERE
name = DB_NAME()
IF @DBCompatibilityLevel <> 80
BEGIN
SELECT @DBCompatibilityLevelMajor = @DBCompatibilityLevel / 10,
@DBCompatibilityLevelMinor = @DBCompatibilityLevel % 10
PRINT N'
===========================================================================
WARNING!
---------------------------------------------------------------------------
This script is designed for Microsoft SQL Server 2000 (8.0) but your
database is set up for compatibility with version '
+ CAST(@DBCompatibilityLevelMajor AS NVARCHAR(80))
+ N'.'
+ CAST(@DBCompatibilityLevelMinor AS NVARCHAR(80))
+ N'. Although
the script should work with later versions of Microsoft SQL Server,
you can ensure compatibility by executing the following statement:
ALTER DATABASE ['
+ DB_NAME()
+ N']
SET COMPATIBILITY_LEVEL = 80
If you are hosting ELMAH in the same database as your application
database and do not wish to change the compatibility option then you
should create a separate database to host ELMAH where you can set the
compatibility level more freely.
If you continue with the current setup, please report any compatibility
issues you encounter over at:
http://code.google.com/p/elmah/issues/list
===========================================================================
'
END
GO
/* ------------------------------------------------------------------------
TABLES
------------------------------------------------------------------------ */
CREATE TABLE [dbo].[ELMAH_Error]
(
[ErrorId] UNIQUEIDENTIFIER NOT NULL,
[Application] NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Host] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Type] NVARCHAR(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Source] NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Message] NVARCHAR(500) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[User] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[StatusCode] INT NOT NULL,
[TimeUtc] DATETIME NOT NULL,
[Sequence] INT IDENTITY (1, 1) NOT NULL,
[AllXml] NTEXT COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
)
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[ELMAH_Error] WITH NOCHECK ADD
CONSTRAINT [PK_ELMAH_Error] PRIMARY KEY NONCLUSTERED ([ErrorId]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[ELMAH_Error] ADD
CONSTRAINT [DF_ELMAH_Error_ErrorId] DEFAULT (NEWID()) FOR [ErrorId]
GO
CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_App_Time_Seq] ON [dbo].[ELMAH_Error]
(
[Application] ASC,
[TimeUtc] DESC,
[Sequence] DESC
)
ON [PRIMARY]
GO
/* ------------------------------------------------------------------------
STORED PROCEDURES
------------------------------------------------------------------------ */
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[ELMAH_GetErrorXml]
(
@Application NVARCHAR(60),
@ErrorId UNIQUEIDENTIFIER
)
AS
SET NOCOUNT ON
SELECT
[AllXml]
FROM
[ELMAH_Error]
WHERE
[ErrorId] = @ErrorId
AND
[Application] = @Application
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[ELMAH_GetErrorsXml]
(
@Application NVARCHAR(60),
@PageIndex INT = 0,
@PageSize INT = 15,
@TotalCount INT OUTPUT
)
AS
SET NOCOUNT ON
DECLARE @FirstTimeUTC DATETIME
DECLARE @FirstSequence INT
DECLARE @StartRow INT
DECLARE @StartRowIndex INT
SELECT
@TotalCount = COUNT(1)
FROM
[ELMAH_Error]
WHERE
[Application] = @Application
-- Get the ID of the first error for the requested page
SET @StartRowIndex = @PageIndex * @PageSize + 1
IF @StartRowIndex <= @TotalCount
BEGIN
SET ROWCOUNT @StartRowIndex
SELECT
@FirstTimeUTC = [TimeUtc],
@FirstSequence = [Sequence]
FROM
[ELMAH_Error]
WHERE
[Application] = @Application
ORDER BY
[TimeUtc] DESC,
[Sequence] DESC
END
ELSE
BEGIN
SET @PageSize = 0
END
-- Now set the row count to the requested page size and get
-- all records below it for the pertaining application.
SET ROWCOUNT @PageSize
SELECT
errorId = [ErrorId],
application = [Application],
host = [Host],
type = [Type],
source = [Source],
message = [Message],
[user] = [User],
statusCode = [StatusCode],
time = CONVERT(VARCHAR(50), [TimeUtc], 126) + 'Z'
FROM
[ELMAH_Error] error
WHERE
[Application] = @Application
AND
[TimeUtc] <= @FirstTimeUTC
AND
[Sequence] <= @FirstSequence
ORDER BY
[TimeUtc] DESC,
[Sequence] DESC
FOR
XML AUTO
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[ELMAH_LogError]
(
@ErrorId UNIQUEIDENTIFIER,
@Application NVARCHAR(60),
@Host NVARCHAR(30),
@Type NVARCHAR(100),
@Source NVARCHAR(60),
@Message NVARCHAR(500),
@User NVARCHAR(50),
@AllXml NTEXT,
@StatusCode INT,
@TimeUtc DATETIME
)
AS
SET NOCOUNT ON
INSERT
INTO
[ELMAH_Error]
(
[ErrorId],
[Application],
[Host],
[Type],
[Source],
[Message],
[User],
[AllXml],
[StatusCode],
[TimeUtc]
)
VALUES
(
@ErrorId,
@Application,
@Host,
@Type,
@Source,
@Message,
@User,
@AllXml,
@StatusCode,
@TimeUtc
)
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

@ -0,0 +1,4 @@
Please note that in order to complete the installation of ELMAH.SqlServer you will have to do the following:
1) Run the Elmah.SqlServer.sql script against your database
2) Edit your web.config with the correct settings in the elmah <connectionString> to connect to your database

@ -0,0 +1,43 @@
using NzbDrone.Services.Service.Datastore;
using PetaPoco;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Mvc;
[assembly: WebActivator.PreApplicationStartMethod(typeof(NzbDrone.Services.Service.App_Start.NinjectMVC3), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(NzbDrone.Services.Service.App_Start.NinjectMVC3), "Stop")]
namespace NzbDrone.Services.Service.App_Start
{
public static class NinjectMVC3
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestModule));
DynamicModuleUtility.RegisterModule(typeof(HttpApplicationInitializationModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
InitDb(kernel);
return kernel;
}
private static void InitDb(IKernel kernel)
{
var db = Connection.GetPetaPocoDb();
kernel.Bind<IDatabase>().ToConstant(db);
}
}
}

@ -0,0 +1,43 @@
using System.Linq;
using System.Web.Mvc;
using NzbDrone.Services.Service.Providers;
namespace NzbDrone.Services.Service.Controllers
{
public class DailySeriesController : Controller
{
private readonly DailySeriesProvider _dailySeriesProvider;
public DailySeriesController(DailySeriesProvider dailySeriesProvider)
{
_dailySeriesProvider = dailySeriesProvider;
}
[HttpGet]
[OutputCache(CacheProfile = "Cache1Hour")]
public JsonResult All()
{
var all = _dailySeriesProvider.All();
return Json(all, JsonRequestBehavior.AllowGet);
}
[HttpGet]
[OutputCache(CacheProfile = "Cache1Hour")]
public JsonResult AllIds()
{
var all = _dailySeriesProvider.AllSeriesIds();
return Json(all, JsonRequestBehavior.AllowGet);
}
[HttpGet]
[OutputCache(CacheProfile = "Cache1HourVaryBySeriesId")]
public JsonResult Check(int seriesId)
{
var result = _dailySeriesProvider.IsDaily(seriesId);
return Json(result, JsonRequestBehavior.AllowGet);
}
}
}

@ -0,0 +1,39 @@
using System;
using System.Linq;
using System.Web.Mvc;
using NzbDrone.Common;
using NzbDrone.Core.Datastore.Migrations;
using PetaPoco;
namespace NzbDrone.Services.Service.Controllers
{
public class HealthController : Controller
{
private readonly EnviromentProvider _enviromentProvider;
private readonly IDatabase _database;
public HealthController(EnviromentProvider enviromentProvider, IDatabase database)
{
_enviromentProvider = enviromentProvider;
_database = database;
}
[HttpGet]
public JsonResult Echo()
{
var stat = new
{
Service = _enviromentProvider.Version.ToString(),
Schema = _database.Fetch<SchemaInfo>().OrderByDescending(c => c.Version).First()
};
return Json(stat, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public JsonResult Exception()
{
throw new NotImplementedException();
}
}
}

@ -0,0 +1,58 @@
using System;
using System.Linq;
using System.Web.Mvc;
using NzbDrone.Common.Contract;
using NzbDrone.Services.Service.Repository.Reporting;
using PetaPoco;
namespace NzbDrone.Services.Service.Controllers
{
public class ReportingController : Controller
{
private readonly IDatabase _database;
private const string OK = "OK";
public ReportingController(IDatabase database)
{
_database = database;
}
[HttpPost]
public JsonResult ParseError(ParseErrorReport parseErrorReport)
{
if (ParseErrorExists(parseErrorReport.Title))
return Json(OK);
var row = new ParseErrorRow();
row.LoadBase(parseErrorReport);
row.Title = parseErrorReport.Title;
_database.Insert(row);
return Json(OK);
}
private bool ParseErrorExists(string title)
{
return _database.Exists<ParseErrorRow>("WHERE Title = @0", title);
}
[HttpPost]
public JsonResult ReportException(ExceptionReport exceptionReport)
{
var row = new ExceptionRow();
row.LoadBase(exceptionReport);
row.LogMessage = exceptionReport.LogMessage;
row.Logger = exceptionReport.Logger;
row.String = exceptionReport.String;
row.Type = exceptionReport.Type;
_database.Insert(row);
return Json(OK);
}
}
}

@ -0,0 +1,33 @@
using System.Linq;
using System.Web.Mvc;
using NzbDrone.Services.Service.Providers;
namespace NzbDrone.Services.Service.Controllers
{
public class SceneMappingController : Controller
{
private readonly SceneMappingProvider _sceneMappingProvider;
public SceneMappingController(SceneMappingProvider sceneMappingProvider)
{
_sceneMappingProvider = sceneMappingProvider;
}
[HttpGet]
[OutputCache(CacheProfile = "Cache1Hour")]
public JsonResult Active()
{
var mappings = _sceneMappingProvider.AllLive();
return Json(mappings, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public JsonResult Pending()
{
var mappings = _sceneMappingProvider.AllPending();
return Json(mappings, JsonRequestBehavior.AllowGet);
}
}
}

@ -0,0 +1,29 @@
using System.Configuration;
using System.Linq;
using NzbDrone.Services.Service.Migrations;
using PetaPoco;
namespace NzbDrone.Services.Service.Datastore
{
public static class Connection
{
public static string GetConnectionString
{
get { return ConfigurationManager.ConnectionStrings["SqlExpress"].ConnectionString; }
}
public static IDatabase GetPetaPocoDb()
{
MigrationsHelper.Run(GetConnectionString);
var db = new Database("SqlExpress")
{
KeepConnectionAlive = true,
ForceDateTimesToUtc = false,
};
return db;
}
}
}

@ -0,0 +1 @@
<%@ Application Codebehind="Global.asax.cs" Inherits="NzbDrone.Services.Service.MvcApplication" Language="C#" %>

@ -0,0 +1,71 @@
using System;
using System.Data.Common;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using NLog;
namespace NzbDrone.Services.Service
{
public class MvcApplication : HttpApplication
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Health", action = "Echo" } // Parameter default
);
}
private static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Clear();
ModelBinders.Binders.DefaultBinder = new JsonModelBinder();
}
// ReSharper disable InconsistentNaming
protected void Application_Error(object sender, EventArgs e)
{
var lastError = Server.GetLastError();
if (lastError is HttpException && lastError.InnerException == null)
{
logger.WarnException(String.Format("{0}. URL[{1}]", lastError.Message, Request.Path), lastError);
return;
}
logger.FatalException(lastError.Message + Environment.NewLine + Request.Url.PathAndQuery, lastError);
if (lastError is DbException)
{
logger.Warn("Restarting application");
HttpRuntime.UnloadAppDomain();
}
}
protected void Application_BeginRequest()
{
}
protected void Application_EndRequest()
{
}
}
}

@ -0,0 +1,40 @@
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Newtonsoft.Json;
namespace NzbDrone.Services.Service
{
public class JsonModelBinder : DefaultModelBinder
{
private static readonly JsonSerializer serializer = new JsonSerializer();
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
if (!IsJsonRequest(request))
{
return base.BindModel(controllerContext, bindingContext);
}
object deserializedObject;
using (var stream = request.InputStream)
{
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream))
{
deserializedObject = serializer.Deserialize(reader, bindingContext.ModelMetadata.ModelType);
}
}
return deserializedObject;
}
private static bool IsJsonRequest(HttpRequestBase request)
{
return request.ContentType.ToLower().Contains("application/json");
}
}
}

@ -0,0 +1,50 @@
using System;
using System.Data;
using Migrator.Framework;
namespace NzbDrone.Services.Service.Migrations
{
[Migration(20120201)]
public class Migration20120201 : Migration
{
public override void Up()
{
Database.AddTable("SceneMappings", new[]
{
new Column("CleanTitle", DbType.String, ColumnProperty.PrimaryKey),
new Column("Id", DbType.Int32, ColumnProperty.NotNull),
new Column("Title", DbType.String, ColumnProperty.NotNull)
});
Database.AddTable("PendingSceneMappings", new[]
{
new Column("CleanTitle", DbType.String, ColumnProperty.PrimaryKey),
new Column("Id", DbType.Int32, ColumnProperty.NotNull),
new Column("Title", DbType.String, ColumnProperty.NotNull)
});
Database.AddTable("DailySeries", new[]
{
new Column("Id", DbType.Int32, ColumnProperty.PrimaryKey),
new Column("Title", DbType.String, ColumnProperty.NotNull)
});
Database.AddTable("ParseErrorReports", new[]
{
new Column("Title", DbType.String,1000, ColumnProperty.PrimaryKey),
MigrationsHelper.UGuidColumn,
MigrationsHelper.TimestampColumn,
MigrationsHelper.VersionColumn,
MigrationsHelper.ProductionColumn
});
}
public override void Down()
{
throw new NotImplementedException();
}
}
}

@ -0,0 +1,31 @@
using System;
using System.Data;
using Migrator.Framework;
namespace NzbDrone.Services.Service.Migrations
{
[Migration(20120203)]
public class Migration20120203 : Migration
{
public override void Up()
{
Database.AddTable("ExceptionReports", new[]
{
new Column("Type", DbType.String, ColumnProperty.PrimaryKey),
new Column("Logger", DbType.String, ColumnProperty.PrimaryKey),
new Column("LogMessage", DbType.String, ColumnProperty.PrimaryKey),
new Column("String", DbType.String, 4000, ColumnProperty.PrimaryKey),
MigrationsHelper.UGuidColumn,
MigrationsHelper.TimestampColumn,
MigrationsHelper.VersionColumn,
MigrationsHelper.ProductionColumn
});
}
public override void Down()
{
throw new NotImplementedException();
}
}
}

@ -0,0 +1,55 @@
using System;
using System.Data;
using System.Reflection;
using System.Web.Hosting;
using Migrator.Framework;
using NLog;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Services.Service.Migrations
{
public class MigrationsHelper
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public static void Run(string connetionString)
{
logger.Info("Preparing to run database migration");
VerifyConnectionString(connetionString);
try
{
var migrator = new Migrator.Migrator("sqlserver", connetionString, Assembly.GetAssembly(typeof(MigrationsHelper)), true, new MigrationLogger());
migrator.MigrateToLastVersion();
logger.Info("Database migration completed");
}
catch (Exception e)
{
logger.FatalException("An error has occurred while migrating database", e);
}
}
private static void VerifyConnectionString(string connectionString)
{
if(connectionString == null) throw new ArgumentNullException("connectionString");
if (HostingEnvironment.ApplicationPhysicalPath != null && HostingEnvironment.ApplicationPhysicalPath.ToLower().Contains("stage") &&
!connectionString.ToLower().Contains("stage"))
{
throw new InvalidOperationException("Attempting to migrate production database from staging environment");
}
}
public static string GetIndexName(string tableName, params string[] columns)
{
return String.Format("IX_{0}_{1}", tableName, String.Join("_", columns));
}
public static readonly Column VersionColumn = new Column("Version", DbType.String, 10, ColumnProperty.NotNull);
public static readonly Column ProductionColumn = new Column("IsProduction", DbType.Boolean, ColumnProperty.NotNull);
public static readonly Column TimestampColumn = new Column("TimeStamp", DbType.DateTime, ColumnProperty.NotNull);
public static readonly Column UGuidColumn = new Column("UGuid", DbType.Guid, ColumnProperty.Null);
}
}

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NzbDrone.Services.Service</RootNamespace>
<AssemblyName>NzbDrone.Services.Service</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<UseIISExpress>true</UseIISExpress>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="AutoMapper">
<HintPath>..\..\packages\AutoMapper.2.0.0\lib\net40-client\AutoMapper.dll</HintPath>
</Reference>
<Reference Include="Elmah">
<HintPath>..\..\packages\elmah.corelibrary.1.2.1\lib\Elmah.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Migrator, Version=0.9.6.37051, Culture=neutral, PublicKeyToken=3b3586e9632ecfce, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Libraries\Migrator.NET\Migrator.dll</HintPath>
</Reference>
<Reference Include="Migrator.Framework, Version=0.0.0.0, Culture=neutral, PublicKeyToken=3b3586e9632ecfce, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Libraries\Migrator.NET\Migrator.Framework.dll</HintPath>
</Reference>
<Reference Include="Migrator.Providers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=3b3586e9632ecfce, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Libraries\Migrator.NET\Migrator.Providers.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.0.7.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.4.0.7\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Ninject, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
<HintPath>..\..\packages\Ninject.2.2.1.4\lib\net40-Full\Ninject.dll</HintPath>
</Reference>
<Reference Include="Ninject.Web.Mvc">
<HintPath>..\..\packages\Ninject.MVC3.2.2.2.0\lib\net40-Full\Ninject.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Core" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
<Reference Include="WebActivator, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\WebActivator.1.5\lib\net40\WebActivator.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="App_Readme\Elmah.SqlServer.sql" />
<Content Include="App_Readme\Elmah.SqlServer.txt" />
<Content Include="Global.asax" />
<Content Include="Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</Content>
<Content Include="Web.Stage.config">
<DependentUpon>Web.config</DependentUpon>
</Content>
<Content Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</Content>
</ItemGroup>
<ItemGroup>
<Compile Include="App_Start\NinjectMVC3.cs" />
<Compile Include="Datastore\Connection.cs" />
<Compile Include="Controllers\DailySeriesController.cs" />
<Compile Include="Controllers\HealthController.cs" />
<Compile Include="Controllers\ReportingController.cs" />
<Compile Include="Controllers\SceneMappingController.cs" />
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="JsonModelBinder.cs" />
<Compile Include="Migrations\Migration20120203.cs" />
<Compile Include="Migrations\Migration20120201.cs" />
<Compile Include="Migrations\MigrationHelper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Providers\DailySeriesProvider.cs" />
<Compile Include="Providers\SceneMappingProvider.cs" />
<Compile Include="Repository\DailySeries.cs" />
<Compile Include="Repository\PendingSceneMapping.cs" />
<Compile Include="Repository\Reporting\ExceptionRow.cs" />
<Compile Include="Repository\Reporting\ParseErrorRow.cs" />
<Compile Include="Repository\Reporting\ReportRowBase.cs" />
<Compile Include="Repository\SceneMapping.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\NzbDrone.Common\NzbDrone.Common.csproj">
<Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
<Name>NzbDrone.Common</Name>
</ProjectReference>
<ProjectReference Include="..\..\NzbDrone.Core\NzbDrone.Core.csproj">
<Project>{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}</Project>
<Name>NzbDrone.Core</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>1542</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:1542/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("NzbDrone.Services.Service")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NzbDrone.Services.Service")]
[assembly: AssemblyCopyright("Copyright © 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("28da3fae-e494-41a9-9e9c-4479e13d91ee")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NzbDrone.Services.Service.Repository;
using PetaPoco;
namespace NzbDrone.Services.Service.Providers
{
public class DailySeriesProvider
{
private readonly IDatabase _database;
public DailySeriesProvider(IDatabase database)
{
_database = database;
}
public IList<DailySeries> All()
{
return _database.Fetch<DailySeries>();
}
public IList<int> AllSeriesIds()
{
return _database.Fetch<int>("SELECT Id from DailySeries");
}
public bool IsDaily(int seriesId)
{
return _database.Exists<DailySeries>(seriesId);
}
}
}

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NzbDrone.Services.Service.Repository;
using PetaPoco;
namespace NzbDrone.Services.Service.Providers
{
public class SceneMappingProvider
{
private readonly IDatabase _database;
public SceneMappingProvider(IDatabase database)
{
_database = database;
}
public IList<SceneMapping> AllLive()
{
return _database.Fetch<SceneMapping>();
}
public IList<PendingSceneMapping> AllPending()
{
return _database.Fetch<PendingSceneMapping>();
}
public void Insert(SceneMapping sceneMapping)
{
_database.Insert(sceneMapping);
}
public void Insert(PendingSceneMapping pendingSceneMapping)
{
_database.Insert(pendingSceneMapping);
}
public void DeleteLive(string cleanTitle)
{
_database.Delete<SceneMapping>(cleanTitle);
}
public void DeletePending(string cleanTitle)
{
_database.Delete<PendingSceneMapping>(cleanTitle);
}
public bool Promote(string cleanTitle)
{
try
{
var pendingItem = _database.Single<PendingSceneMapping>(cleanTitle);
var mapping = new SceneMapping
{
CleanTitle = pendingItem.CleanTitle,
Id = pendingItem.Id,
Title = pendingItem.Title
};
_database.Insert(mapping);
_database.Delete(pendingItem);
}
catch (Exception ex)
{
return false;
}
return true;
}
public bool PromoteAll()
{
try
{
var pendingItems = _database.Fetch<PendingSceneMapping>();
foreach (var pendingItem in pendingItems)
{
Promote(pendingItem.Title);
}
}
catch (Exception ex)
{
return false;
}
return true;
}
}
}

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using PetaPoco;
namespace NzbDrone.Services.Service.Repository
{
[TableName("DailySeries")]
[PrimaryKey("Id", autoIncrement = false)]
public class DailySeries
{
public int Id { get; set; }
public string Title { get; set; }
}
}

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using PetaPoco;
namespace NzbDrone.Services.Service.Repository
{
[TableName("PendingSceneMappings")]
[PrimaryKey("CleanTitle", autoIncrement = false)]
public class PendingSceneMapping
{
public string CleanTitle { get; set; }
public int Id { get; set; }
public string Title { get; set; }
}
}

@ -0,0 +1,14 @@
using System.Linq;
using PetaPoco;
namespace NzbDrone.Services.Service.Repository.Reporting
{
[TableName("ExceptionReports")]
public class ExceptionRow : ReportRowBase
{
public string Type { get; set; }
public string Logger { get; set; }
public string LogMessage { get; set; }
public string String { get; set; }
}
}

@ -0,0 +1,11 @@
using System.Linq;
using PetaPoco;
namespace NzbDrone.Services.Service.Repository.Reporting
{
[TableName("ParseErrorReports")]
public class ParseErrorRow : ReportRowBase
{
public string Title { get; set; }
}
}

@ -0,0 +1,25 @@
using System;
using System.Linq;
using NzbDrone.Common.Contract;
namespace NzbDrone.Services.Service.Repository.Reporting
{
public abstract class ReportRowBase
{
public void LoadBase(ReportBase report)
{
Timestamp = DateTime.Now;
Version = report.Version;
IsProduction = report.IsProduction;
UGuid = report.UGuid;
}
public string Version { get; set; }
public DateTime Timestamp { get; set; }
public bool IsProduction { get; set; }
public Guid UGuid { get; set; }
}
}

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using PetaPoco;
namespace NzbDrone.Services.Service.Repository
{
[TableName("SceneMappings")]
[PrimaryKey("CleanTitle", autoIncrement = false)]
public class SceneMapping
{
public string CleanTitle { get; set; }
public int Id { get; set; }
public string Title { get; set; }
}
}

@ -0,0 +1,30 @@
<?xml version="1.0"?>
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an atrribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web>
<!--
In the example below, the "Replace" transform will replace the entire
<customErrors> section of your web.config file.
Note that because there is only one customErrors section under the
<system.web> node, there is no need to use the "xdt:Locator" attribute.
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>

@ -0,0 +1,32 @@
<?xml version="1.0"?>
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<!--
In the example below, the "SetAttributes" transform will change the value of
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
finds an atrribute "name" that has a value of "MyDB".
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
-->
<system.web>
<compilation debug="false" xdt:Transform="Replace" />
<customErrors mode="RemoteOnly" xdt:Transform="Replace"/>
<!--
In the example below, the "Replace" transform will replace the entire
<customErrors> section of your web.config file.
Note that because there is only one customErrors section under the
<system.web> node, there is no need to use the "xdt:Locator" attribute.
<customErrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customErrors>
-->
</system.web>
</configuration>

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="SqlExpress" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLExpress;Database=Services_Stage; Integrated Security=True" xdt:Transform="Replace"/>
</connectionStrings>
<system.web>
<compilation debug="false" xdt:Transform="Replace" />
</system.web>
</configuration>

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="elmah">
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
<section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
<section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
<section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>
</configSections>
<connectionStrings>
<clear />
<add name="SqlExpress" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLExpress;Database=Services; Integrated Security=True" />
</connectionStrings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.7.0" newVersion="4.0.7.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
<customErrors mode="Off"/>
<compilation debug="true" targetFramework="4.0" />
<httpModules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
</httpModules>
<httpHandlers>
<add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
</httpHandlers>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="Cache1Hour" duration="3600" varyByParam="none"/>
<add name="Cache1HourVaryBySeriesId" duration="3600" varyByParam="seriesId"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
<handlers>
<add name="Elmah" path="elmah.axd" verb="POST,GET,HEAD" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
</handlers>
</system.webServer>
<elmah>
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="SqlExpress" />
</elmah>
</configuration>

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="2.0.0" />
<package id="elmah" version="1.2.0.1" />
<package id="elmah.corelibrary" version="1.2.1" />
<package id="elmah.sqlserver" version="1.2" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" />
<package id="Newtonsoft.Json" version="4.0.7" />
<package id="Ninject" version="2.2.1.4" />
<package id="Ninject.MVC3" version="2.2.2.0" />
<package id="NLog" version="2.0.0.2000" />
<package id="WebActivator" version="1.5" />
</packages>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<clear />
<add name="SqlExpress" providerName="System.Data.SqlClient" connectionString="Data Source=.\SQLEXPRESS;Database=Services_Test; Integrated Security=True" />
</connectionStrings>
</configuration>

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using Migrator.Providers.SqlServer;
using NzbDrone.Services.Service.Migrations;
using NzbDrone.Test.Common;
using NzbDrone.Test.Common.AutoMoq;
using PetaPoco;
namespace NzbDrone.Services.Tests.Framework
{
public abstract class ServicesTestBase : LoggingTest
{
static readonly string connectionString = ConfigurationManager.ConnectionStrings["SqlExpress"].ConnectionString;
static ServicesTestBase()
{
}
private static void ResetDb()
{
var transformationProvider = new SqlServerTransformationProvider(new SqlServerDialect(), connectionString);
var tables = transformationProvider.GetTables();
foreach (var table in tables)
{
transformationProvider.RemoveTable(table);
}
MigrationsHelper.Run(connectionString);
}
public IDatabase Db { get; private set; }
private AutoMoqer _mocker;
protected AutoMoqer Mocker
{
get
{
if (_mocker == null)
{
_mocker = new AutoMoqer();
}
return _mocker;
}
}
protected void WithRealDb()
{
ResetDb();
Db = new Database("SqlExpress");
Mocker.SetConstant(Db);
}
}
}

@ -0,0 +1,25 @@
// ReSharper disable RedundantUsingDirective
using System.Configuration;
using System.Linq;
using System;
using System.IO;
using Migrator.Providers;
using Migrator.Providers.SqlServer;
using NzbDrone.Core.Datastore;
using PetaPoco;
using MigrationsHelper = NzbDrone.Services.Service.Migrations.MigrationsHelper;
namespace NzbDrone.Services.Tests.Framework
{
internal static class TestDbHelper
{
public static void WhipeDb()
{
}
}
}

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{12261AE5-BCC4-4DC7-A218-0764B9C30230}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NzbDrone.Services.Tests</RootNamespace>
<AssemblyName>NzbDrone.Services.Tests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FizzWare.NBuilder">
<HintPath>..\..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions">
<HintPath>..\..\packages\FluentAssertions.1.7.0\Lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="Migrator">
<HintPath>..\..\Libraries\Migrator.NET\Migrator.dll</HintPath>
</Reference>
<Reference Include="Migrator.Framework">
<HintPath>..\..\Libraries\Migrator.NET\Migrator.Framework.dll</HintPath>
</Reference>
<Reference Include="Migrator.Providers">
<HintPath>..\..\Libraries\Migrator.NET\Migrator.Providers.dll</HintPath>
</Reference>
<Reference Include="Moq">
<HintPath>..\..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="nunit.mocks">
<HintPath>..\..\packages\NUnit.2.5.10.11092\lib\nunit.mocks.dll</HintPath>
</Reference>
<Reference Include="pnunit.framework">
<HintPath>..\..\packages\NUnit.2.5.10.11092\lib\pnunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ReportingControllerFixture.cs" />
<Compile Include="Framework\ServicesTestBase.cs" />
<Compile Include="Framework\TestDbHelper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\NzbDrone.Common\NzbDrone.Common.csproj">
<Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
<Name>NzbDrone.Common</Name>
</ProjectReference>
<ProjectReference Include="..\..\NzbDrone.Core\NzbDrone.Core.csproj">
<Project>{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}</Project>
<Name>NzbDrone.Core</Name>
</ProjectReference>
<ProjectReference Include="..\..\NzbDrone.Test.Common\NzbDrone.Test.Common.csproj">
<Project>{CADDFCE0-7509-4430-8364-2074E1EEFCA2}</Project>
<Name>NzbDrone.Test.Common</Name>
</ProjectReference>
<ProjectReference Include="..\NzbDrone.Services.Service\NzbDrone.Services.Service.csproj">
<Project>{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}</Project>
<Name>NzbDrone.Services.Service</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("NzbDrone.Services.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NzbDrone.Services.Tests")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("0f63c407-65ef-4cd1-b660-78499e432daa")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -0,0 +1,123 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Contract;
using NzbDrone.Services.Service.Controllers;
using NzbDrone.Services.Service.Repository.Reporting;
using NzbDrone.Services.Tests.Framework;
namespace NzbDrone.Services.Tests
{
[TestFixture]
public class ReportingControllerFixture : ServicesTestBase
{
ReportingController Controller
{
get
{
return Mocker.Resolve<ReportingController>();
}
}
private static ParseErrorReport CreateParseErrorReport()
{
return new ParseErrorReport
{
IsProduction = true,
Title = "MyTitle",
Version = "1.1.2.3",
UGuid = Guid.NewGuid()
};
}
private static ExceptionReport CreateExceptionReport()
{
return new ExceptionReport
{
IsProduction = true,
Version = "1.1.2.3",
UGuid = Guid.NewGuid(),
Logger = "NzbDrone.Logger.Name",
LogMessage = "Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message",
String = "Long message Long message Long messageLong messageLong messageLong messageLong messageLong messageLong messageLong messageLong message",
Type = typeof(InvalidOperationException).Name
};
}
[Test]
public void parse_report_should_be_saved()
{
var parseReport = CreateParseErrorReport();
WithRealDb();
Controller.ParseError(parseReport);
var reports = Db.Fetch<ParseErrorRow>();
reports.Should().HaveCount(1);
reports.Single().Title.Should().Be(parseReport.Title);
reports.Single().IsProduction.Should().Be(parseReport.IsProduction);
reports.Single().Version.Should().Be(parseReport.Version);
reports.Single().Timestamp.Should().BeWithin(TimeSpan.FromSeconds(4)).Before(DateTime.Now);
reports.Single().UGuid.Should().Be(parseReport.UGuid);
}
[Test]
public void parse_report_should_save_report_if_title_doesnt_exist()
{
var parseReport1 = CreateParseErrorReport();
var parseReport2 = CreateParseErrorReport();
parseReport1.Title = Guid.NewGuid().ToString();
WithRealDb();
Controller.ParseError(parseReport1);
Controller.ParseError(parseReport2);
var reports = Db.Fetch<ParseErrorRow>();
reports.Should().HaveCount(2);
}
[Test]
public void parse_report_should_not_save_report_if_title_exist()
{
var parseReport1 = CreateParseErrorReport();
var parseReport2 = CreateParseErrorReport();
WithRealDb();
Controller.ParseError(parseReport1);
Controller.ParseError(parseReport2);
var reports = Db.Fetch<ParseErrorRow>();
reports.Should().HaveCount(1);
}
[Test]
public void exception_report_should_be_saved()
{
var exceptionReport = CreateExceptionReport();
WithRealDb();
Controller.ReportException(exceptionReport);
var exceptionRows = Db.Fetch<ExceptionRow>();
exceptionRows.Should().HaveCount(1);
exceptionRows.Single().IsProduction.Should().Be(exceptionReport.IsProduction);
exceptionRows.Single().Version.Should().Be(exceptionReport.Version);
exceptionRows.Single().Timestamp.Should().BeWithin(TimeSpan.FromSeconds(4)).Before(DateTime.Now);
exceptionRows.Single().UGuid.Should().Be(exceptionReport.UGuid);
exceptionRows.Single().Logger.Should().Be(exceptionReport.Logger);
exceptionRows.Single().LogMessage.Should().Be(exceptionReport.LogMessage);
exceptionRows.Single().String.Should().Be(exceptionReport.String);
exceptionRows.Single().Type.Should().Be(exceptionReport.Type);
}
}
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FluentAssertions" version="1.7.0" />
<package id="Moq" version="4.0.10827" />
<package id="NBuilder" version="3.0.1.1" />
<package id="NUnit" version="2.5.10.11092" />
</packages>

@ -13,6 +13,7 @@ namespace NzbDrone.Test.Common
protected const string INTEGRATION_TEST = "Integration Test";
private AutoMoqer _mocker;
protected AutoMoqer Mocker
{
@ -27,6 +28,9 @@ namespace NzbDrone.Test.Common
}
}
protected Mock<RestProvider> MockedRestProvider { get; private set; }
protected string VirtualPath
{
get
@ -41,6 +45,9 @@ namespace NzbDrone.Test.Common
[SetUp]
public void TestBaseSetup()
{
MockedRestProvider = new Mock<RestProvider>();
ReportingService.RestProvider = MockedRestProvider.Object;
if (Directory.Exists(TempFolder))
{
Directory.Delete(TempFolder, true);

@ -62,7 +62,7 @@ namespace NzbDrone.Update
private static void InitLoggers()
{
LogConfiguration.RegisterExceptioneer();
LogConfiguration.RegisterRemote();
LogConfiguration.RegisterConsoleLogger(LogLevel.Trace);
LogConfiguration.RegisterUdpLogger();

@ -12,5 +12,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.0.0.*")]
[assembly: AssemblyFileVersion("0.0.0.*")]
[assembly: AssemblyVersion("1.0.0.*")]
[assembly: AssemblyFileVersion("1.0.0.*")]

@ -39,7 +39,7 @@
<HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.4.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
<HintPath>..\packages\Newtonsoft.Json.4.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll</HintPath>
@ -52,9 +52,8 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WebDriver, Version=2.17.0.0, Culture=neutral, PublicKeyToken=1c2bd1631853048f, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Selenium.WebDriver.2.17.0\lib\net40\WebDriver.dll</HintPath>
<Reference Include="WebDriver">
<HintPath>..\packages\Selenium.WebDriver.2.18.0\lib\net40\WebDriver.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@ -65,9 +64,6 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="AutomationTestBase.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Drivers\chromedriver.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@ -87,6 +83,10 @@
<Name>NzbDrone</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30AD4FE6B2A6AEED" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.7.0" newVersion="4.0.7.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -2,6 +2,6 @@
<packages>
<package id="DotNetZip" version="1.9.1.8" />
<package id="FluentAssertions" version="1.7.0" />
<package id="Newtonsoft.Json" version="4.0.4" />
<package id="Selenium.WebDriver" version="2.17.0" />
<package id="Newtonsoft.Json" version="4.0.6" />
<package id="Selenium.WebDriver" version="2.18.0" />
</packages>

@ -18,7 +18,7 @@ namespace NzbDrone.Web.App_Start
LogManager.Configuration = new XmlLoggingConfiguration(enviromentProvider.GetNlogConfigPath(), false);
LogConfiguration.RegisterUdpLogger();
LogConfiguration.RegisterExceptioneer();
LogConfiguration.RegisterRemote();
LogConfiguration.RegisterConsoleLogger(LogLevel.Info, "NzbDrone.Web.MvcApplication");
LogConfiguration.RegisterConsoleLogger(LogLevel.Info, "NzbDrone.Core.CentralDispatch");
LogConfiguration.RegisterRollingFileLogger(enviromentProvider.GetLogFileName(), LogLevel.Trace);

@ -49,7 +49,7 @@ namespace NzbDrone.Web.Controllers
dirs = _diskProvider.GetDirectories(term.Substring(0, index + 1));
}
}
catch (Exception ex)
catch (Exception)
{
return Json(new List<string>(), JsonRequestBehavior.AllowGet);
//Swallow the exceptions so proper JSON is returned to the client (Empty results)

@ -28,7 +28,7 @@ namespace NzbDrone.Web.Controllers
public ActionResult Index()
{
var updateModel = new UpdateModel();
updateModel.UpdatePackage = _updateProvider.GetAvilableUpdate();
updateModel.UpdatePackage = _updateProvider.GetAvilableUpdate(_enviromentProvider.Version);
updateModel.LogFiles = _updateProvider.UpdateLogFile();
updateModel.LogFolder = _enviromentProvider.GetUpdateLogFolder();

@ -1,15 +1,19 @@
using System.Linq;
using System.Web.Mvc;
using NLog;
using NzbDrone.Web.Models;
namespace NzbDrone.Web.Filters
{
public class JsonErrorFilter : FilterAttribute, IExceptionFilter
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public void OnException(ExceptionContext filterContext)
{
filterContext.Result = JsonNotificationResult.Opps(filterContext.Exception.Message);
filterContext.ExceptionHandled = true;
logger.FatalException(filterContext.RequestContext.HttpContext.Request.RawUrl, filterContext.Exception);
}

@ -9,5 +9,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.0.0.*")]
[assembly: AssemblyFileVersion("0.0.0.*")]
[assembly: AssemblyVersion("1.0.0.*")]
[assembly: AssemblyFileVersion("1.0.0.*")]

@ -1,4 +1,3 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone", "NzbDrone\NzbDrone.csproj", "{D12F7F2F-8A3C-415F-88FA-6DD061A84869}"
@ -29,12 +28,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test.Common", "Test.Common"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.Web.UI.Automation", "NzbDrone.Web.UI.Test\NzbDrone.Web.UI.Automation.csproj", "{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServiceHelpers", "ServiceHelpers", "{F9E67978-5CD6-4A5F-827B-4249711C0B02}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WindowsServiceHelpers", "WindowsServiceHelpers", "{F9E67978-5CD6-4A5F-827B-4249711C0B02}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceInstall", "ServiceHelpers\ServiceInstall\ServiceInstall.csproj", "{6BCE712F-846D-4846-9D1B-A66B858DA755}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceUninstall", "ServiceHelpers\ServiceUninstall\ServiceUninstall.csproj", "{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.Services.Service", "NzbDrone.Services\NzbDrone.Services.Service\NzbDrone.Services.Service.csproj", "{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{5853FEE1-D6C1-49AB-B1E3-12216491DA69}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NzbDrone.Services.Tests", "NzbDrone.Services\NzbDrone.Services.Tests\NzbDrone.Services.Tests.csproj", "{12261AE5-BCC4-4DC7-A218-0764B9C30230}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -45,6 +50,10 @@ Global
Release|Mixed Platforms = Release|Mixed Platforms
Release|x64 = Release|x64
Release|x86 = Release|x86
Services|Any CPU = Services|Any CPU
Services|Mixed Platforms = Services|Mixed Platforms
Services|x64 = Services|x64
Services|x86 = Services|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Debug|Any CPU.ActiveCfg = Debug|x86
@ -59,6 +68,12 @@ Global
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Release|x64.ActiveCfg = Release|x86
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Release|x86.ActiveCfg = Release|x86
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Release|x86.Build.0 = Release|x86
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Services|Any CPU.ActiveCfg = Release|x86
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Services|Mixed Platforms.ActiveCfg = Release|x86
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Services|Mixed Platforms.Build.0 = Release|x86
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Services|x64.ActiveCfg = Release|x86
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Services|x86.ActiveCfg = Release|x86
{D12F7F2F-8A3C-415F-88FA-6DD061A84869}.Services|x86.Build.0 = Release|x86
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -75,6 +90,14 @@ Global
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Release|x64.Build.0 = Release|x64
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Release|x86.ActiveCfg = Release|x86
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Release|x86.Build.0 = Release|x86
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Services|Any CPU.ActiveCfg = Release|Any CPU
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Services|Any CPU.Build.0 = Release|Any CPU
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Services|Mixed Platforms.ActiveCfg = Release|x86
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Services|Mixed Platforms.Build.0 = Release|x86
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Services|x64.ActiveCfg = Release|x64
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Services|x64.Build.0 = Release|x64
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Services|x86.ActiveCfg = Release|x86
{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}.Services|x86.Build.0 = Release|x86
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -88,6 +111,12 @@ Global
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Release|x64.ActiveCfg = Release|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Release|x86.ActiveCfg = Release|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Services|Any CPU.ActiveCfg = Release|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Services|Any CPU.Build.0 = Release|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Services|Mixed Platforms.ActiveCfg = Release|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Services|Mixed Platforms.Build.0 = Release|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Services|x64.ActiveCfg = Release|Any CPU
{43BD3BBD-1531-4D8F-9C08-E1CD544AB2CD}.Services|x86.ActiveCfg = Release|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -101,6 +130,12 @@ Global
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Release|x64.ActiveCfg = Release|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Release|x86.ActiveCfg = Release|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Services|Any CPU.ActiveCfg = Release|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Services|Any CPU.Build.0 = Release|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Services|Mixed Platforms.ActiveCfg = Release|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Services|Mixed Platforms.Build.0 = Release|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Services|x64.ActiveCfg = Release|Any CPU
{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}.Services|x86.ActiveCfg = Release|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -113,6 +148,12 @@ Global
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|x64.ActiveCfg = Release|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Release|x86.ActiveCfg = Release|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Services|Any CPU.ActiveCfg = Release|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Services|Any CPU.Build.0 = Release|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Services|Mixed Platforms.ActiveCfg = Release|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Services|Mixed Platforms.Build.0 = Release|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Services|x64.ActiveCfg = Release|Any CPU
{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}.Services|x86.ActiveCfg = Release|Any CPU
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|Any CPU.ActiveCfg = Debug|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Debug|Mixed Platforms.Build.0 = Debug|x86
@ -125,6 +166,12 @@ Global
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|x64.ActiveCfg = Release|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|x86.ActiveCfg = Release|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Release|x86.Build.0 = Release|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Services|Any CPU.ActiveCfg = Release|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Services|Mixed Platforms.ActiveCfg = Release|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Services|Mixed Platforms.Build.0 = Release|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Services|x64.ActiveCfg = Release|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Services|x86.ActiveCfg = Release|x86
{FAFB5948-A222-4CF6-AD14-026BE7564802}.Services|x86.Build.0 = Release|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|Any CPU.ActiveCfg = Debug|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Debug|Mixed Platforms.Build.0 = Debug|x86
@ -137,6 +184,12 @@ Global
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|x64.ActiveCfg = Release|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|x86.ActiveCfg = Release|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Release|x86.Build.0 = Release|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Services|Any CPU.ActiveCfg = Release|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Services|Mixed Platforms.ActiveCfg = Release|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Services|Mixed Platforms.Build.0 = Release|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Services|x64.ActiveCfg = Release|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Services|x86.ActiveCfg = Release|x86
{4CCC53CD-8D5E-4CC4-97D2-5C9312AC2BD7}.Services|x86.Build.0 = Release|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|Any CPU.ActiveCfg = Debug|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Debug|Mixed Platforms.Build.0 = Debug|x86
@ -149,6 +202,12 @@ Global
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|x64.ActiveCfg = Release|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|x86.ActiveCfg = Release|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Release|x86.Build.0 = Release|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Services|Any CPU.ActiveCfg = Release|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Services|Mixed Platforms.ActiveCfg = Release|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Services|Mixed Platforms.Build.0 = Release|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Services|x64.ActiveCfg = Release|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Services|x86.ActiveCfg = Release|x86
{35388E8E-0CDB-4A84-AD16-E4B6EFDA5D97}.Services|x86.Build.0 = Release|x86
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -162,6 +221,12 @@ Global
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|x64.ActiveCfg = Release|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Release|x86.ActiveCfg = Release|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Services|Any CPU.ActiveCfg = Release|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Services|Any CPU.Build.0 = Release|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Services|Mixed Platforms.ActiveCfg = Release|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Services|Mixed Platforms.Build.0 = Release|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Services|x64.ActiveCfg = Release|Any CPU
{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}.Services|x86.ActiveCfg = Release|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -175,6 +240,12 @@ Global
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Release|x64.ActiveCfg = Release|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Release|x86.ActiveCfg = Release|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Services|Any CPU.ActiveCfg = Release|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Services|Any CPU.Build.0 = Release|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Services|Mixed Platforms.ActiveCfg = Release|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Services|Mixed Platforms.Build.0 = Release|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Services|x64.ActiveCfg = Release|Any CPU
{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}.Services|x86.ActiveCfg = Release|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -187,6 +258,12 @@ Global
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Release|x64.ActiveCfg = Release|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Release|x86.ActiveCfg = Release|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Services|Any CPU.ActiveCfg = Release|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Services|Any CPU.Build.0 = Release|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Services|Mixed Platforms.ActiveCfg = Release|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Services|Mixed Platforms.Build.0 = Release|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Services|x64.ActiveCfg = Release|Any CPU
{CADDFCE0-7509-4430-8364-2074E1EEFCA2}.Services|x86.ActiveCfg = Release|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -199,6 +276,12 @@ Global
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Release|x64.ActiveCfg = Release|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Release|x86.ActiveCfg = Release|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Services|Any CPU.ActiveCfg = Release|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Services|Any CPU.Build.0 = Release|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Services|Mixed Platforms.ActiveCfg = Release|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Services|Mixed Platforms.Build.0 = Release|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Services|x64.ActiveCfg = Release|Any CPU
{3CCD64E1-84DA-4853-B7EF-98B02FD4E39E}.Services|x86.ActiveCfg = Release|Any CPU
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Debug|Any CPU.ActiveCfg = Debug|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Debug|Mixed Platforms.Build.0 = Debug|x86
@ -211,6 +294,12 @@ Global
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Release|x64.ActiveCfg = Release|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Release|x86.ActiveCfg = Release|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Release|x86.Build.0 = Release|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Services|Any CPU.ActiveCfg = Release|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Services|Mixed Platforms.ActiveCfg = Release|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Services|Mixed Platforms.Build.0 = Release|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Services|x64.ActiveCfg = Release|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Services|x86.ActiveCfg = Release|x86
{6BCE712F-846D-4846-9D1B-A66B858DA755}.Services|x86.Build.0 = Release|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Debug|Any CPU.ActiveCfg = Debug|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Debug|Mixed Platforms.Build.0 = Debug|x86
@ -223,6 +312,48 @@ Global
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Release|x64.ActiveCfg = Release|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Release|x86.ActiveCfg = Release|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Release|x86.Build.0 = Release|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Services|Any CPU.ActiveCfg = Release|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Services|Mixed Platforms.ActiveCfg = Release|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Services|Mixed Platforms.Build.0 = Release|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Services|x64.ActiveCfg = Release|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Services|x86.ActiveCfg = Release|x86
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4}.Services|x86.Build.0 = Release|x86
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Debug|x64.ActiveCfg = Debug|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Debug|x86.ActiveCfg = Debug|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Release|Any CPU.Build.0 = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Release|x64.ActiveCfg = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Release|x86.ActiveCfg = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Services|Any CPU.ActiveCfg = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Services|Any CPU.Build.0 = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Services|Mixed Platforms.ActiveCfg = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Services|Mixed Platforms.Build.0 = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Services|x64.ActiveCfg = Release|Any CPU
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15}.Services|x86.ActiveCfg = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Debug|Any CPU.Build.0 = Debug|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Debug|x64.ActiveCfg = Debug|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Debug|x86.ActiveCfg = Debug|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Release|Any CPU.ActiveCfg = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Release|Any CPU.Build.0 = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Release|x64.ActiveCfg = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Release|x86.ActiveCfg = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Services|Any CPU.ActiveCfg = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Services|Any CPU.Build.0 = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Services|Mixed Platforms.ActiveCfg = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Services|Mixed Platforms.Build.0 = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Services|x64.ActiveCfg = Release|Any CPU
{12261AE5-BCC4-4DC7-A218-0764B9C30230}.Services|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -238,6 +369,8 @@ Global
{FAFB5948-A222-4CF6-AD14-026BE7564802} = {47697CDB-27B6-4B05-B4F8-0CBE6F6EDF97}
{6BCE712F-846D-4846-9D1B-A66B858DA755} = {F9E67978-5CD6-4A5F-827B-4249711C0B02}
{700D0B95-95CD-43F3-B6C9-FAA0FC1358D4} = {F9E67978-5CD6-4A5F-827B-4249711C0B02}
{63B155D7-AE78-4FEB-88BB-2F025ADD1F15} = {5853FEE1-D6C1-49AB-B1E3-12216491DA69}
{12261AE5-BCC4-4DC7-A218-0764B9C30230} = {5853FEE1-D6C1-49AB-B1E3-12216491DA69}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.0\lib\NET35

@ -49,7 +49,7 @@ namespace NzbDrone
LogConfiguration.RegisterRollingFileLogger(enviromentProvider.GetLogFileName(), LogLevel.Info);
LogConfiguration.RegisterConsoleLogger(LogLevel.Debug);
LogConfiguration.RegisterUdpLogger();
LogConfiguration.RegisterExceptioneer();
LogConfiguration.RegisterRemote();
LogConfiguration.Reload();
Logger.Info("Start-up Path:'{0}'", enviromentProvider.ApplicationPath);
}

@ -11,5 +11,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.0.0.*")]
[assembly: AssemblyFileVersion("0.0.0.*")]
[assembly: AssemblyVersion("1.0.0.*")]
[assembly: AssemblyFileVersion("1.0.0.*")]

@ -7,5 +7,5 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("13976baa-e5ba-42b2-8ad7-8d568b68a53b")]
[assembly: AssemblyVersion("0.0.0.*")]
[assembly: AssemblyFileVersion("0.0.0.*")]
[assembly: AssemblyVersion("1.0.0.*")]
[assembly: AssemblyFileVersion("1.0.0.*")]

@ -4,5 +4,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTitle("UninstallService")]
[assembly: Guid("0a964b21-9de9-40b3-9378-0474fd5f21a8")]
[assembly: AssemblyVersion("0.0.0.*")]
[assembly: AssemblyFileVersion("0.0.0.*")]
[assembly: AssemblyVersion("1.0.0.*")]
[assembly: AssemblyFileVersion("1.0.0.*")]

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>AutoMapper</name>
</assembly>
<members>
<member name="T:AutoMapper.MappingEngine.ConversionVisitor">
<summary>
This expression visitor will replace an input parameter by another one
see http://stackoverflow.com/questions/4601844/expression-tree-copy-or-convert
</summary>
</member>
</members>
</doc>

@ -0,0 +1,671 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>AutoMapper</name>
</assembly>
<members>
<member name="T:AutoMapper.MappingEngine.ConversionVisitor">
<summary>
This expression visitor will replace an input parameter by another one
see http://stackoverflow.com/questions/4601844/expression-tree-copy-or-convert
</summary>
</member>
<member name="T:TvdP.Collections.ConcurrentDictionaryKey`2">
<summary>
Search key structure for <see cref="T:TvdP.Collections.ConcurrentDictionary`2"/>
</summary>
<typeparam name="TKey">Type of the key.</typeparam>
<typeparam name="TValue">Type of the value.</typeparam>
</member>
<member name="T:TvdP.Collections.ConcurrentDictionary`2">
<summary>
A Concurrent <see cref="T:System.Collections.Generic.IDictionary`2"/> implementation.
</summary>
<typeparam name="TKey">Type of the keys.</typeparam>
<typeparam name="TValue">Type of the values.</typeparam>
<remarks>
This class is threadsafe and highly concurrent. This means that multiple threads can do lookup and insert operations
on this dictionary simultaneously.
It is not guaranteed that collisions will not occur. The dictionary is partitioned in segments. A segment contains
a set of items based on a hash of those items. The more segments there are and the beter the hash, the fewer collisions will occur.
This means that a nearly empty ConcurrentDictionary is not as concurrent as one containing many items.
</remarks>
</member>
<member name="T:TvdP.Collections.ConcurrentHashtable`2">
<summary>
Base class for concurrent hashtable implementations
</summary>
<typeparam name="TStored">Type of the items stored in the hashtable.</typeparam>
<typeparam name="TSearch">Type of the key to search with.</typeparam>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.#ctor">
<summary>
Constructor (protected)
</summary>
<remarks>Use Initialize method after construction.</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.Initialize">
<summary>
Initialize the newly created ConcurrentHashtable. Invoke in final (sealed) constructor
or Create method.
</summary>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.CreateSegmentRange(System.Int32,System.Int32)">
<summary>
Create a segment range
</summary>
<param name="segmentCount">Number of segments in range.</param>
<param name="initialSegmentSize">Number of slots allocated initialy in each segment.</param>
<returns>The created <see cref="T:TvdP.Collections.Segmentrange`2"/> instance.</returns>
</member>
<member name="F:TvdP.Collections.ConcurrentHashtable`2._NewRange">
<summary>
While adjusting the segmentation, _NewRange will hold a reference to the new range of segments.
when the adjustment is complete this reference will be copied to _CurrentRange.
</summary>
</member>
<member name="F:TvdP.Collections.ConcurrentHashtable`2._CurrentRange">
<summary>
Will hold the most current reange of segments. When busy adjusting the segmentation, this
field will hold a reference to the old range.
</summary>
</member>
<member name="F:TvdP.Collections.ConcurrentHashtable`2._SwitchPoint">
<summary>
While adjusting the segmentation this field will hold a boundary.
Clients accessing items with a key hash value below this boundary (unsigned compared)
will access _NewRange. The others will access _CurrentRange
</summary>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.GetItemHashCode(`0@)">
<summary>
Get a hashcode for given storeable item.
</summary>
<param name="item">Reference to the item to get a hash value for.</param>
<returns>The hash value as an <see cref="T:System.UInt32"/>.</returns>
<remarks>
The hash returned should be properly randomized hash. The standard GetItemHashCode methods are usually not good enough.
A storeable item and a matching search key should return the same hash code.
So the statement <code>ItemEqualsItem(storeableItem, searchKey) ? GetItemHashCode(storeableItem) == GetItemHashCode(searchKey) : true </code> should always be true;
</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.GetKeyHashCode(`1@)">
<summary>
Get a hashcode for given search key.
</summary>
<param name="key">Reference to the key to get a hash value for.</param>
<returns>The hash value as an <see cref="T:System.UInt32"/>.</returns>
<remarks>
The hash returned should be properly randomized hash. The standard GetItemHashCode methods are usually not good enough.
A storeable item and a matching search key should return the same hash code.
So the statement <code>ItemEqualsItem(storeableItem, searchKey) ? GetItemHashCode(storeableItem) == GetItemHashCode(searchKey) : true </code> should always be true;
</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.ItemEqualsKey(`0@,`1@)">
<summary>
Compares a storeable item to a search key. Should return true if they match.
</summary>
<param name="item">Reference to the storeable item to compare.</param>
<param name="key">Reference to the search key to compare.</param>
<returns>True if the storeable item and search key match; false otherwise.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.ItemEqualsItem(`0@,`0@)">
<summary>
Compares two storeable items for equality.
</summary>
<param name="item1">Reference to the first storeable item to compare.</param>
<param name="item2">Reference to the second storeable item to compare.</param>
<returns>True if the two soreable items should be regarded as equal.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.IsEmpty(`0@)">
<summary>
Indicates if a specific item reference contains a valid item.
</summary>
<param name="item">The storeable item reference to check.</param>
<returns>True if the reference doesn't refer to a valid item; false otherwise.</returns>
<remarks>The statement <code>IsEmpty(default(TStoredI))</code> should always be true.</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.GetKeyType(`0@)">
<summary>
Returns the type of the key value or object.
</summary>
<param name="item">The stored item to get the type of the key for.</param>
<returns>The actual type of the key or null if it can not be determined.</returns>
<remarks>
Used for diagnostics purposes.
</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.GetSegment(System.UInt32)">
<summary>
Gets a segment out of either _NewRange or _CurrentRange based on the hash value.
</summary>
<param name="hash"></param>
<returns></returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.GetSegmentLockedForWriting(System.UInt32)">
<summary>
Gets a LOCKED segment out of either _NewRange or _CurrentRange based on the hash value.
Unlock needs to be called on this segment before it can be used by other clients.
</summary>
<param name="hash"></param>
<returns></returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.GetSegmentLockedForReading(System.UInt32)">
<summary>
Gets a LOCKED segment out of either _NewRange or _CurrentRange based on the hash value.
Unlock needs to be called on this segment before it can be used by other clients.
</summary>
<param name="hash"></param>
<returns></returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.FindItem(`1@,`0@)">
<summary>
Finds an item in the table collection that maches the given searchKey
</summary>
<param name="searchKey">The key to the item.</param>
<param name="item">Out reference to a field that will receive the found item.</param>
<returns>A boolean that will be true if an item has been found and false otherwise.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.GetOldestItem(`0@,`0@)">
<summary>
Looks for an existing item in the table contents using an alternative copy. If it can be found it will be returned.
If not then the alternative copy will be added to the table contents and the alternative copy will be returned.
</summary>
<param name="searchKey">A copy to search an already existing instance with</param>
<param name="item">Out reference to receive the found item or the alternative copy</param>
<returns>A boolean that will be true if an existing copy was found and false otherwise.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.ReplaceItem(`1@,`0@,`0@,System.Func{`0,System.Boolean})">
<summary>
Replaces and existing item
</summary>
<param name="newItem"></param>
<param name="oldItem"></param>
<param name="sanction"></param>
<returns>true is the existing item was successfully replaced.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.InsertItem(`0@,`0@)">
<summary>
Inserts an item in the table contents possibly replacing an existing item.
</summary>
<param name="searchKey">The item to insert in the table</param>
<param name="replacedItem">Out reference to a field that will receive any possibly replaced item.</param>
<returns>A boolean that will be true if an existing copy was found and replaced and false otherwise.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.RemoveItem(`1@,`0@)">
<summary>
Removes an item from the table contents.
</summary>
<param name="searchKey">The key to find the item with.</param>
<param name="removedItem">Out reference to a field that will receive the found and removed item.</param>
<returns>A boolean that will be rue if an item was found and removed and false otherwise.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.EnumerateAmorphLockedSegments(System.Boolean)">
<summary>
Enumerates all segments in _CurrentRange and locking them before yielding them and resleasing the lock afterwards
The order in which the segments are returned is undefined.
Lock SyncRoot before using this enumerable.
</summary>
<returns></returns>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.Clear">
<summary>
Removes all items from the collection.
Aquires a lock on SyncRoot before it does it's thing.
When this method returns and multiple threads have access to this table it
is not guaranteed that the table is actually empty.
</summary>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.SegmentationAdjustmentNeeded">
<summary>
Determines if a segmentation adjustment is needed.
</summary>
<returns>True</returns>
</member>
<member name="F:TvdP.Collections.ConcurrentHashtable`2._AssessSegmentationPending">
<summary>
Bool as int (for interlocked functions) that is true if a Segmentation assesment is pending.
</summary>
</member>
<member name="F:TvdP.Collections.ConcurrentHashtable`2._AllocatedSpace">
<summary>
The total allocated number of item slots. Filled with nonempty items or not.
</summary>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.EffectTotalAllocatedSpace(System.Int32)">
<summary>
When a segment resizes it uses this method to inform the hashtable of the change in allocated space.
</summary>
<param name="effect"></param>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.ScheduleMaintenance">
<summary>
Schedule a call to the AssessSegmentation() method.
</summary>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.AssessSegmentation(System.Object)">
<summary>
Checks if segmentation needs to be adjusted and if so performs the adjustment.
</summary>
<param name="dummy"></param>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.AssessSegmentation">
<summary>
This method is called when a re-segmentation is expected to be needed. It checks if it actually is needed and, if so, performs the re-segementation.
</summary>
</member>
<member name="M:TvdP.Collections.ConcurrentHashtable`2.SetSegmentation(System.Int32,System.Int32)">
<summary>
Adjusts the segmentation to the new segment count
</summary>
<param name="newSegmentCount">The new number of segments to use. This must be a power of 2.</param>
<param name="segmentSize">The number of item slots to reserve in each segment.</param>
</member>
<member name="P:TvdP.Collections.ConcurrentHashtable`2.SyncRoot">
<summary>
Returns an object that serves as a lock for range operations
</summary>
<remarks>
Clients use this primarily for enumerating over the Tables contents.
Locking doesn't guarantee that the contents don't change, but prevents operations that would
disrupt the enumeration process.
Operations that use this lock:
Count, Clear, DisposeGarbage and AssessSegmentation.
Keeping this lock will prevent the table from re-segmenting.
</remarks>
</member>
<member name="P:TvdP.Collections.ConcurrentHashtable`2.Items">
<summary>
Gets an IEnumerable to iterate over all items in all segments.
</summary>
<returns></returns>
<remarks>
A lock should be aquired and held on SyncRoot while this IEnumerable is being used.
The order in which the items are returned is undetermined.
</remarks>
</member>
<member name="P:TvdP.Collections.ConcurrentHashtable`2.Count">
<summary>
Returns a count of all items in teh collection. This may not be
aqurate when multiple threads are accessing this table.
Aquires a lock on SyncRoot before it does it's thing.
</summary>
</member>
<member name="P:TvdP.Collections.ConcurrentHashtable`2.MinSegments">
<summary>
Gives the minimum number of segments a hashtable can contain. This should be 1 or more and always a power of 2.
</summary>
</member>
<member name="P:TvdP.Collections.ConcurrentHashtable`2.MinSegmentAllocatedSpace">
<summary>
Gives the minimum number of allocated item slots per segment. This should be 1 or more, always a power of 2
and less than 1/2 of MeanSegmentAllocatedSpace.
</summary>
</member>
<member name="P:TvdP.Collections.ConcurrentHashtable`2.MeanSegmentAllocatedSpace">
<summary>
Gives the prefered number of allocated item slots per segment. This should be 4 or more and always a power of 2.
</summary>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.#ctor">
<summary>
Constructs a <see cref="T:TvdP.Collections.ConcurrentDictionary`2"/> instance using the default <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> to compare keys.
</summary>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.#ctor(System.Collections.Generic.IEqualityComparer{`0})">
<summary>
Constructs a <see cref="T:TvdP.Collections.ConcurrentDictionary`2"/> instance using the specified <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> to compare keys.
</summary>
<param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> tp compare keys with.</param>
<exception cref="T:System.ArgumentNullException"><paramref name="comparer"/> is null.</exception>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.GetItemHashCode(System.Nullable{System.Collections.Generic.KeyValuePair{`0,`1}}@)">
<summary>
Get a hashcode for given storeable item.
</summary>
<param name="item">Reference to the item to get a hash value for.</param>
<returns>The hash value as an <see cref="T:System.UInt32"/>.</returns>
<remarks>
The hash returned should be properly randomized hash. The standard GetItemHashCode methods are usually not good enough.
A storeable item and a matching search key should return the same hash code.
So the statement <code>ItemEqualsItem(storeableItem, searchKey) ? GetItemHashCode(storeableItem) == GetItemHashCode(searchKey) : true </code> should always be true;
</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.GetKeyHashCode(TvdP.Collections.ConcurrentDictionaryKey{`0,`1}@)">
<summary>
Get a hashcode for given search key.
</summary>
<param name="key">Reference to the key to get a hash value for.</param>
<returns>The hash value as an <see cref="T:System.UInt32"/>.</returns>
<remarks>
The hash returned should be properly randomized hash. The standard GetItemHashCode methods are usually not good enough.
A storeable item and a matching search key should return the same hash code.
So the statement <code>ItemEqualsItem(storeableItem, searchKey) ? GetItemHashCode(storeableItem) == GetItemHashCode(searchKey) : true </code> should always be true;
</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.ItemEqualsKey(System.Nullable{System.Collections.Generic.KeyValuePair{`0,`1}}@,TvdP.Collections.ConcurrentDictionaryKey{`0,`1}@)">
<summary>
Compares a storeable item to a search key. Should return true if they match.
</summary>
<param name="item">Reference to the storeable item to compare.</param>
<param name="key">Reference to the search key to compare.</param>
<returns>True if the storeable item and search key match; false otherwise.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.ItemEqualsItem(System.Nullable{System.Collections.Generic.KeyValuePair{`0,`1}}@,System.Nullable{System.Collections.Generic.KeyValuePair{`0,`1}}@)">
<summary>
Compares two storeable items for equality.
</summary>
<param name="item1">Reference to the first storeable item to compare.</param>
<param name="item2">Reference to the second storeable item to compare.</param>
<returns>True if the two soreable items should be regarded as equal.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.IsEmpty(System.Nullable{System.Collections.Generic.KeyValuePair{`0,`1}}@)">
<summary>
Indicates if a specific item reference contains a valid item.
</summary>
<param name="item">The storeable item reference to check.</param>
<returns>True if the reference doesn't refer to a valid item; false otherwise.</returns>
<remarks>The statement <code>IsEmpty(default(TStoredI))</code> should always be true.</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.System#Collections#Generic#IDictionary{TKey@TValue}#Add(`0,`1)">
<summary>
Adds an element with the provided key and value to the dictionary.
</summary>
<param name="key">The object to use as the key of the element to add.</param>
<param name="value">The object to use as the value of the element to add.</param>
<exception cref="T:System.ArgumentException">An element with the same key already exists in the dictionary.</exception>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.ContainsKey(`0)">
<summary>
Determines whether the dictionary
contains an element with the specified key.
</summary>
<param name="key">The key to locate in the dictionary.</param>
<returns>true if the dictionary contains
an element with the key; otherwise, false.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.System#Collections#Generic#IDictionary{TKey@TValue}#Remove(`0)">
<summary>
Removes the element with the specified key from the dictionary.
</summary>
<param name="key">The key of the element to remove.</param>
<returns>true if the element is successfully removed; otherwise, false. This method
also returns false if key was not found in the original dictionary.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.TryGetValue(`0,`1@)">
<summary>
Gets the value associated with the specified key.
</summary>
<param name="key">The key whose value to get.</param>
<param name="value">
When this method returns, the value associated with the specified key, if
the key is found; otherwise, the default value for the type of the value
parameter. This parameter is passed uninitialized.
</param>
<returns>
true if the dictionary contains an element with the specified key; otherwise, false.
</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.System#Collections#Generic#ICollection{System#Collections#Generic#KeyValuePair{TKey@TValue}}#Add(System.Collections.Generic.KeyValuePair{`0,`1})">
<summary>
Adds an association to the dictionary.
</summary>
<param name="item">A <see cref="T:System.Collections.Generic.KeyValuePair`2"/> that represents the association to add.</param>
<exception cref="T:System.ArgumentException">An association with an equal key already exists in the dicitonary.</exception>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.Clear">
<summary>
Removes all items from the dictionary.
</summary>
<remarks>WHen working with multiple threads, that each can add items to this dictionary, it is not guaranteed that the dictionary will be empty when this method returns.</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.System#Collections#Generic#ICollection{System#Collections#Generic#KeyValuePair{TKey@TValue}}#Contains(System.Collections.Generic.KeyValuePair{`0,`1})">
<summary>
Determines whether the specified association exists in the dictionary.
</summary>
<param name="item">The key-value association to search fo in the dicionary.</param>
<returns>True if item is found in the dictionary; otherwise, false.</returns>
<remarks>
This method compares both key and value. It uses the default equality comparer to compare values.
</remarks>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.System#Collections#Generic#ICollection{System#Collections#Generic#KeyValuePair{TKey@TValue}}#CopyTo(System.Collections.Generic.KeyValuePair{`0,`1}[],System.Int32)">
<summary>
Copies all associations of the dictionary to an
<see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the associations
copied from <see cref="T:TvdP.Collections.ConcurrentDictionaryKey`2"/>. The <see cref="T:System.Array"/> must
have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
<exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null.</exception>
<exception cref="T:System.ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception>
<exception cref="T:System.ArgumentException"><paramref name="arrayIndex"/> is equal to or greater than the length of <paramref name="array"/>.</exception>
<exception cref="T:System.ArgumentException">The number of associations to be copied
is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination
<paramref name="array"/>.</exception>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.System#Collections#Generic#ICollection{System#Collections#Generic#KeyValuePair{TKey@TValue}}#Remove(System.Collections.Generic.KeyValuePair{`0,`1})">
<summary>
Removes the specified association from the <see cref="T:TvdP.Collections.ConcurrentDictionaryKey`2"/>, comparing both key and value.
</summary>
<param name="item">A <see cref="T:System.Collections.Generic.KeyValuePair`2"/> representing the association to remove.</param>
<returns>true if the association was successfully removed from the <see cref="T:TvdP.Collections.ConcurrentDictionaryKey`2"/>;
otherwise, false. This method also returns false if the association is not found in
the original <see cref="T:TvdP.Collections.ConcurrentDictionaryKey`2"/>.
</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.GetEnumerator">
<summary>
Returns an enumerator that iterates through all associations in the <see cref="T:TvdP.Collections.ConcurrentDictionaryKey`2"/> at the moment of invocation.
</summary>
<returns>A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the associations.</returns>
</member>
<member name="M:TvdP.Collections.ConcurrentDictionary`2.System#Collections#IEnumerable#GetEnumerator">
<summary>
Returns an enumerator that iterates through all associations in the <see cref="T:TvdP.Collections.ConcurrentDictionaryKey`2"/> at the moment of invocation.
</summary>
<returns>A <see cref="T:System.Collections.IEnumerator"/> that can be used to iterate through the associations.</returns>
</member>
<member name="P:TvdP.Collections.ConcurrentDictionary`2.Comparer">
<summary>
Gives the <see cref="T:System.Collections.Generic.IEqualityComparer`1"/> of TKey that is used to compare keys.
</summary>
</member>
<member name="P:TvdP.Collections.ConcurrentDictionary`2.Keys">
<summary>
Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of
the dictionary.
</summary>
<returns>An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the dictionary.</returns>
<remarks>This property takes a snapshot of the current keys collection of the dictionary at the moment of invocation.</remarks>
</member>
<member name="P:TvdP.Collections.ConcurrentDictionary`2.Values">
<summary>
Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in
the dictionary.
</summary>
<returns>
An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the dictionary.
</returns>
<remarks>This property takes a snapshot of the current keys collection of the dictionary at the moment of invocation.</remarks>
</member>
<member name="P:TvdP.Collections.ConcurrentDictionary`2.Item(`0)">
<summary>
Gets or sets the value associated with the specified key.
</summary>
<param name="key">The key of the value to get or set.</param>
<returns>The value associated with the specified key. If the specified key is not found, a get operation throws a KeyNotFoundException, and a set operation creates a new element with the specified key.</returns>
<remarks>
When working with multiple threads, that can each potentialy remove the searched for item, a <see cref="T:System.Collections.Generic.KeyNotFoundException"/> can always be expected.
</remarks>
</member>
<member name="P:TvdP.Collections.ConcurrentDictionary`2.Count">
<summary>
Gets the number of elements contained in the <see cref="T:TvdP.Collections.ConcurrentDictionaryKey`2"/>.
</summary>
</member>
<member name="P:TvdP.Collections.ConcurrentDictionary`2.System#Collections#Generic#ICollection{System#Collections#Generic#KeyValuePair{TKey@TValue}}#IsReadOnly">
<summary>
Gets a value indicating whether the <see cref="T:TvdP.Collections.ConcurrentDictionaryKey`2"/> is read-only, which is always false.
</summary>
</member>
<member name="T:TvdP.Collections.Segment`2">
<summary>
A 'single writer - multi reader' threaded segment in a hashtable.
</summary>
<typeparam name="TStored"></typeparam>
<typeparam name="TSearch"></typeparam>
<remarks>
Though each segment can be accessed by 1 writer thread simultaneously, the hashtable becomes concurrent
for writing by containing many segments so that collisions are rare. The table will be fully concurrent
for read operations as far as they are not colliding with write operations.
Each segment is itself a small hashtable that can grow and shrink individualy. This prevents blocking of
the entire hashtable when growing or shrinking is needed. Because each segment is relatively small (depending on
the quality of the hash) resizing of the individual segments should not take much time.
</remarks>
</member>
<member name="M:TvdP.Collections.Segment`2.Initialize(System.Int32)">
<summary>
Initialize the segment.
</summary>
<param name="initialSize"></param>
</member>
<member name="M:TvdP.Collections.Segment`2.Welcome(TvdP.Collections.ConcurrentHashtable{`0,`1})">
<summary>
When segment gets introduced into hashtable then its allocated space should be added to the
total allocated space.
Single threaded access or locking is needed
</summary>
<param name="traits"></param>
</member>
<member name="M:TvdP.Collections.Segment`2.Bye(TvdP.Collections.ConcurrentHashtable{`0,`1})">
<summary>
When segment gets removed from hashtable then its allocated space should be subtracted to the
total allocated space.
Single threaded access or locking is needed
</summary>
<param name="traits"></param>
</member>
<member name="F:TvdP.Collections.Segment`2._List">
<summary>
Array with 'slots'. Each slot can be filled or empty.
</summary>
</member>
<member name="M:TvdP.Collections.Segment`2.InsertItemAtIndex(System.UInt32,System.UInt32,`0,TvdP.Collections.ConcurrentHashtable{`0,`1})">
<summary>
Inserts an item into a *not empty* spot given by position i. It moves items forward until an empty spot is found.
</summary>
<param name="mask"></param>
<param name="i"></param>
<param name="itemCopy"></param>
<param name="traits"></param>
</member>
<member name="M:TvdP.Collections.Segment`2.FindItem(`1@,`0@,TvdP.Collections.ConcurrentHashtable{`0,`1})">
<summary>
Find item in segment.
</summary>
<param name="key">Reference to the search key to use.</param>
<param name="item">Out reference to store the found item in.</param>
<param name="traits">Object that tells this segment how to treat items and keys.</param>
<returns>True if an item could be found, otherwise false.</returns>
</member>
<member name="M:TvdP.Collections.Segment`2.GetOldestItem(`0@,`0@,TvdP.Collections.ConcurrentHashtable{`0,`1})">
<summary>
Find an existing item or, if it can't be found, insert a new item.
</summary>
<param name="key">Reference to the item that will be inserted if an existing item can't be found. It will also be used to search with.</param>
<param name="item">Out reference to store the found item or, if it can not be found, the new inserted item.</param>
<param name="traits">Object that tells this segment how to treat items and keys.</param>
<returns>True if an existing item could be found, otherwise false.</returns>
</member>
<member name="M:TvdP.Collections.Segment`2.InsertItem(`0@,`0@,TvdP.Collections.ConcurrentHashtable{`0,`1})">
<summary>
Inserts an item in the segment, possibly replacing an equal existing item.
</summary>
<param name="key">A reference to the item to insert.</param>
<param name="item">An out reference where any replaced item will be written to, if no item was replaced the new item will be written to this reference.</param>
<param name="traits">Object that tells this segment how to treat items and keys.</param>
<returns>True if an existing item could be found and is replaced, otherwise false.</returns>
</member>
<member name="M:TvdP.Collections.Segment`2.RemoveItem(`1@,`0@,TvdP.Collections.ConcurrentHashtable{`0,`1})">
<summary>
Removes an item from the segment.
</summary>
<param name="key">A reference to the key to search with.</param>
<param name="item">An out reference where the removed item will be stored or default(<typeparamref name="TStored"/>) if no item to remove can be found.</param>
<param name="traits">Object that tells this segment how to treat items and keys.</param>
<returns>True if an item could be found and is removed, false otherwise.</returns>
</member>
<member name="M:TvdP.Collections.Segment`2.GetNextItem(System.Int32,`0@,TvdP.Collections.ConcurrentHashtable{`0,`1})">
<summary>
Iterate over items in the segment.
</summary>
<param name="beyond">Position beyond which the next filled slot will be found and the item in that slot returned. (Starting with -1)</param>
<param name="item">Out reference where the next item will be stored or default if the end of the segment is reached.</param>
<param name="traits">Object that tells this segment how to treat items and keys.</param>
<returns>The index position the next item has been found or -1 otherwise.</returns>
</member>
<member name="F:TvdP.Collections.Segment`2._Count">
<summary>
Total numer of filled slots in _List.
</summary>
</member>
<member name="M:TvdP.Collections.Segment`2.Trim(TvdP.Collections.ConcurrentHashtable{`0,`1})">
<summary>
Remove any excess allocated space
</summary>
<param name="traits"></param>
</member>
<member name="P:TvdP.Collections.Segment`2.IsAlive">
<summary>
Boolean value indicating if this segment has not been trashed yet.
</summary>
</member>
<member name="T:TvdP.Threading.TinyReaderWriterLock">
<summary>
Tiny spin lock that allows multiple readers simultanously and 1 writer exclusively
</summary>
</member>
<member name="M:TvdP.Threading.TinyReaderWriterLock.ReleaseForReading">
<summary>
Release a reader lock
</summary>
</member>
<member name="M:TvdP.Threading.TinyReaderWriterLock.ReleaseForWriting">
<summary>
Release a writer lock
</summary>
</member>
<member name="M:TvdP.Threading.TinyReaderWriterLock.LockForReading">
<summary>
Aquire a reader lock. Wait until lock is aquired.
</summary>
</member>
<member name="M:TvdP.Threading.TinyReaderWriterLock.LockForReading(System.Boolean)">
<summary>
Aquire a reader lock.
</summary>
<param name="wait">True if to wait until lock aquired, False to return immediately.</param>
<returns>Boolean indicating if lock was successfuly aquired.</returns>
</member>
<member name="M:TvdP.Threading.TinyReaderWriterLock.LockForWriting">
<summary>
Aquire a writer lock. Wait until lock is aquired.
</summary>
</member>
<member name="M:TvdP.Threading.TinyReaderWriterLock.LockForWriting(System.Boolean)">
<summary>
Aquire a writer lock.
</summary>
<param name="wait">True if to wait until lock aquired, False to return immediately.</param>
<returns>Boolean indicating if lock was successfuly aquired.</returns>
</member>
<member name="T:System.SerializableAttribute">
<summary>
Attempts to replicate the Desktop CLR.
</summary>
</member>
</members>
</doc>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save