From 30d38eead6f569c899fcf1114e57c9e6c8e4753e Mon Sep 17 00:00:00 2001 From: Keivan Date: Sun, 10 Oct 2010 12:00:07 -0700 Subject: [PATCH] fixed ninjet's race condition --- NzbDrone.Core/CentralDispatch.cs | 51 +++++++--- NzbDrone.Core/NzbDrone.Core.csproj | 1 + .../Fakes/FakeNotificationProvider.cs | 56 +++++++++++ NzbDrone.Web/Content/ui.notify.css | 13 +++ NzbDrone.Web/Global.asax.cs | 6 +- NzbDrone.Web/NzbDrone.Web.csproj | 3 + NzbDrone.Web/Scripts/Notifications.js | 12 +++ NzbDrone.Web/Scripts/jquery.msg.js | 97 +++++++++++++++++++ NzbDrone.Web/Views/Shared/Site.Master | 62 ++++++------ NzbDrone/Program.cs | 11 +-- NzbDrone/app.config | 10 +- 11 files changed, 259 insertions(+), 63 deletions(-) create mode 100644 NzbDrone.Core/Providers/Fakes/FakeNotificationProvider.cs create mode 100644 NzbDrone.Web/Content/ui.notify.css create mode 100644 NzbDrone.Web/Scripts/Notifications.js create mode 100644 NzbDrone.Web/Scripts/jquery.msg.js diff --git a/NzbDrone.Core/CentralDispatch.cs b/NzbDrone.Core/CentralDispatch.cs index 6f51f9304..55c7c2cdd 100644 --- a/NzbDrone.Core/CentralDispatch.cs +++ b/NzbDrone.Core/CentralDispatch.cs @@ -7,6 +7,7 @@ using NLog.Targets; using NzbDrone.Core.Entities; using NzbDrone.Core.Entities.Episode; using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.Fakes; using SubSonic.DataProviders; using SubSonic.Repository; using NLog; @@ -15,24 +16,33 @@ namespace NzbDrone.Core { public static class CentralDispatch { + private static IKernel _kernel; + private static readonly Object kernelLock = new object(); + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static void BindKernel(IKernel kernel) + public static void BindKernel() { - string connectionString = String.Format("Data Source={0};Version=3;", Path.Combine(AppPath, "nzbdrone.db")); - var provider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite"); - provider.Log = new SonicTrace(); - provider.LogParams = true; + lock (kernelLock) + { + Logger.Debug("Binding Ninject's Kernel"); + _kernel = new StandardKernel(); - kernel.Bind().To().InSingletonScope(); - kernel.Bind().To(); - kernel.Bind().To(); - kernel.Bind().To(); - kernel.Bind().To(); - kernel.Bind().To().InSingletonScope(); - kernel.Bind().To().InSingletonScope(); - kernel.Bind().ToMethod(c => new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope(); + string connectionString = String.Format("Data Source={0};Version=3;", Path.Combine(AppPath, "nzbdrone.db")); + var provider = ProviderFactory.GetProvider(connectionString, "System.Data.SQLite"); + provider.Log = new SonicTrace(); + provider.LogParams = true; - ForceMigration(kernel.Get()); + _kernel.Bind().To().InSingletonScope(); + _kernel.Bind().To(); + _kernel.Bind().To(); + _kernel.Bind().To(); + _kernel.Bind().To(); + _kernel.Bind().To().InSingletonScope(); + _kernel.Bind().To().InSingletonScope(); + _kernel.Bind().ToMethod(c => new SimpleRepository(provider, SimpleRepositoryOptions.RunMigrations)).InSingletonScope(); + + ForceMigration(_kernel.Get()); + } } public static String AppPath @@ -48,6 +58,19 @@ namespace NzbDrone.Core } + public static IKernel NinjectKernel + { + get + { + + if (_kernel == null) + { + BindKernel(); + } + + return _kernel; + } + } public static void ConfigureNlog() { diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index b7ecf9687..854a6a7ce 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -149,6 +149,7 @@ + diff --git a/NzbDrone.Core/Providers/Fakes/FakeNotificationProvider.cs b/NzbDrone.Core/Providers/Fakes/FakeNotificationProvider.cs new file mode 100644 index 000000000..9c5560b26 --- /dev/null +++ b/NzbDrone.Core/Providers/Fakes/FakeNotificationProvider.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using NzbDrone.Core.Entities.Notification; + +namespace NzbDrone.Core.Providers.Fakes +{ + class FakeNotificationProvider : INotificationProvider + { + private readonly Dictionary _basicNotifications = new Dictionary(); + private readonly Dictionary _progressNotification = new Dictionary(); + private readonly Object _lock = new object(); + + + ProgressNotification fakeNotification = new ProgressNotification("Updating Series"); + public void Register(ProgressNotification notification) + { + _progressNotification.Add(notification.Id, notification); + } + + public void Register(BasicNotification notification) + { + _basicNotifications.Add(notification.Id, notification); + } + + public List BasicNotifications + { + get { return new List(_basicNotifications.Values); } + } + + public List ProgressNotifications + { + + get + { + fakeNotification.Status = NotificationStatus.InProgress; + fakeNotification.CurrentStatus = DateTime.Now.ToString(); + return new List { fakeNotification }; + } + } + + public void Dismiss(Guid notificationId) + { + lock (_lock) + { + if (_basicNotifications.ContainsKey(notificationId)) + { + _basicNotifications.Remove(notificationId); + } + else if (_progressNotification.ContainsKey(notificationId)) + { + _progressNotification.Remove(notificationId); + } + } + } + } +} \ No newline at end of file diff --git a/NzbDrone.Web/Content/ui.notify.css b/NzbDrone.Web/Content/ui.notify.css new file mode 100644 index 000000000..dcd2823b9 --- /dev/null +++ b/NzbDrone.Web/Content/ui.notify.css @@ -0,0 +1,13 @@ +.ui-notify { width:350px; position:fixed; top:10px; right:10px; } +.ui-notify-message { padding:10px; margin-bottom:15px; -moz-border-radius:8px; -webkit-border-radius:8px; border-radius:8px } +.ui-notify-message h1 { font-size:14px; margin:0; padding:0 } +.ui-notify-message p { margin:3px 0; padding:0; line-height:18px } +.ui-notify-message:last-child { margin-bottom:0 } +.ui-notify-message-style { background:#000; background:rgba(0,0,0,0.8); -moz-box-shadow: 0 0 6px #000; -webkit-box-shadow: 0 0 6px #000; box-shadow: 0 0 6px #000; } +.ui-notify-message-style h1 { color:#fff; font-weight:bold } +.ui-notify-message-style p { color:#fff } +.ui-notify-close { color:#fff; text-decoration:underline } +.ui-notify-click { cursor:pointer } +.ui-notify-cross { margin-top:-4px; float:right; cursor:pointer; text-decoration:none; font-size:12px; font-weight:bold; text-shadow:0 1px 1px #fff; padding:2px } +.ui-notify-cross:hover { color:#ffffab } +.ui-notify-cross:active { position:relative; top:1px } diff --git a/NzbDrone.Web/Global.asax.cs b/NzbDrone.Web/Global.asax.cs index 4b0b61353..5f3cc374b 100644 --- a/NzbDrone.Web/Global.asax.cs +++ b/NzbDrone.Web/Global.asax.cs @@ -9,7 +9,6 @@ namespace NzbDrone.Web { public class MvcApplication : NinjectHttpApplication { - private StandardKernel _kernel; public static void RegisterRoutes(RouteCollection routes) { @@ -35,9 +34,8 @@ namespace NzbDrone.Web protected override IKernel CreateKernel() { - _kernel = new StandardKernel(); - CentralDispatch.BindKernel(_kernel); - return _kernel; + return CentralDispatch.NinjectKernel; + } diff --git a/NzbDrone.Web/NzbDrone.Web.csproj b/NzbDrone.Web/NzbDrone.Web.csproj index a1cdcf7b7..f8436a9d6 100644 --- a/NzbDrone.Web/NzbDrone.Web.csproj +++ b/NzbDrone.Web/NzbDrone.Web.csproj @@ -161,6 +161,7 @@ + @@ -201,6 +202,8 @@ + + diff --git a/NzbDrone.Web/Scripts/Notifications.js b/NzbDrone.Web/Scripts/Notifications.js new file mode 100644 index 000000000..6da5a0f1d --- /dev/null +++ b/NzbDrone.Web/Scripts/Notifications.js @@ -0,0 +1,12 @@ +/// +$(function () { + alert("Notification"); + + var container = $("#container-bottom").notify({ stack: 'above' }); + container.notify("create", { + title: 'Look ma, two containers!', + text: 'This container is positioned on the bottom of the screen. Notifications will stack on top of each other with the position attribute set to above.' + }, { expires: false }); + + +}); \ No newline at end of file diff --git a/NzbDrone.Web/Scripts/jquery.msg.js b/NzbDrone.Web/Scripts/jquery.msg.js new file mode 100644 index 000000000..419ca26c2 --- /dev/null +++ b/NzbDrone.Web/Scripts/jquery.msg.js @@ -0,0 +1,97 @@ +/* +Copyright (c) 2010 Diego Uría Martínez + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/** + * Add a message to the body. + * + * Example: + * $('a').click(function() { + * $.fn.jQueryMsg({ + * msg: 'Hello world!!' + * }); + * }); + * + * TODO: + * - don't set 'speed' too high, it may loose some events + * - option: message tag + * - option: content tag + */ +(function($,undefined){ + var name = 'jQueryMsg'; + var timeout; + + $.fn.jQueryMsg = function(params) + { + var settings = $.extend( + {}, + { + msgClass : 'jquerymsgclass', //container class + speed : 0, //effects' speed + delay: 100, //delay between messages + timeout: 3000, //maximum time the message is shown on the screen. 0 for permanent + fx: 'none' //effect: set it to none, fade or slide + }, + params); + + if(typeof(settings.msg) === 'string') + { + var show = {width: 'show', height: 'show'}; + var hide = {width: 'hide', height: 'hide'}; + switch(settings.fx) { + case 'fade': + show = {opacity: 'show'}; + hide = {opacity: 'hide'}; + break; + case 'slide': + show = {height: 'show'}; + hide = {height: 'hide'}; + break; + } + + var msg; + if($('p.'+name).size() > 0) { + msg = $('p.'+name); + msg.click().delay(settings.delay); + } + else { + msg = $('

'); + msg.hide().appendTo('body'); + } + + clearTimeout(timeout); + + msg.one('click',function() { + msg.animate(hide, settings.speed, function() { + msg.removeClass().addClass(name); + }); + }).queue(function() { + msg.html(settings.msg).addClass(settings.msgClass).animate(show, settings.speed).dequeue(); + + if(settings.timeout > 0) { + timeout = setTimeout(function() { + msg.click(); + }, settings.timeout); + } + }); + } + } +})(jQuery); \ No newline at end of file diff --git a/NzbDrone.Web/Views/Shared/Site.Master b/NzbDrone.Web/Views/Shared/Site.Master index d96a220ac..d86d6cb71 100644 --- a/NzbDrone.Web/Views/Shared/Site.Master +++ b/NzbDrone.Web/Views/Shared/Site.Master @@ -1,10 +1,4 @@ -<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> - -<%@ Import Namespace="Helpers" %> -<%@ Import Namespace="Telerik.Web.Mvc.UI" %> - - - + +<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> + +<%@ Import Namespace="Helpers" %> +<%@ Import Namespace="Telerik.Web.Mvc.UI" %> + + - NZBDrone + NZBDrone <% Html.Telerik().StyleSheetRegistrar().DefaultGroup(group => group.Add("telerik.common.css").Add("telerik.sitefinity.css")).Render(); %> + + - + - +