From c8a8be88941dfbc85a53b6f8555459498f48a96c Mon Sep 17 00:00:00 2001 From: vfedosevich Date: Wed, 29 May 2013 15:52:13 +0300 Subject: [PATCH] Fixes Schedulers bugs --- .../Scheduling/Scheduler.cs | 3 +- .../Scheduling/SchedulerController.cs | 19 +++++++- .../Scheduling/SchedulerJob.cs | 1 + .../Tasks/TaskController.cs | 3 +- .../Tasks/TaskManager.cs | 23 ++++++---- .../WebsitePanel/Schedules.ascx | 13 +++++- .../WebsitePanel/Schedules.ascx.designer.cs | 46 ++++++++----------- 7 files changed, 65 insertions(+), 43 deletions(-) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/Scheduler.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/Scheduler.cs index ae4a819a..b882ff82 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/Scheduler.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/Scheduler.cs @@ -110,7 +110,7 @@ namespace WebsitePanel.EnterpriseServer { var taskThread = new Thread(() => RunBackgroundTask(task)) { Priority = ThreadPriority.Highest }; taskThread.Start(); - TaskManager.AddTaskThread(task, taskThread); + TaskManager.AddTaskThread(task.Id, taskThread); } } @@ -132,6 +132,7 @@ namespace WebsitePanel.EnterpriseServer var objTask = (SchedulerTask)Activator.CreateInstance(Type.GetType(schedule.Task.TaskType)); objTask.DoWork(); + // Thread.Sleep(40000); } catch (Exception ex) { diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/SchedulerController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/SchedulerController.cs index e6eb34cd..220d1fea 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/SchedulerController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/SchedulerController.cs @@ -160,24 +160,39 @@ namespace WebsitePanel.EnterpriseServer if (schedule == null) return 0; + if (TaskController.GetScheduleTasks(scheduleId).Any(x => x.Status == BackgroundTaskStatus.Run + || x.Status == BackgroundTaskStatus.Starting)) + return 0; + var parameters = schedule.ScheduleInfo.Parameters.Select( prm => new BackgroundTaskParameter(prm.ParameterId, prm.ParameterValue)).ToList(); + var packageInfo = PackageController.GetPackage(schedule.ScheduleInfo.PackageId); var backgroundTask = new BackgroundTask( Guid.NewGuid(), Guid.NewGuid().ToString("N"), SecurityContext.User.UserId, SecurityContext.User.IsPeer ? SecurityContext.User.OwnerId - : SecurityContext.User.UserId, "SCHEDULER", "RUN_SCHEDULE", + : packageInfo.UserId, "SCHEDULER", "RUN_SCHEDULE", schedule.ScheduleInfo.ScheduleName, schedule.ScheduleInfo.ScheduleId, schedule.ScheduleInfo.ScheduleId, schedule.ScheduleInfo.PackageId, schedule.ScheduleInfo.MaxExecutionTime, parameters) { Status = BackgroundTaskStatus.Starting }; - + TaskController.AddTask(backgroundTask); + // update next run (if required) + CalculateNextStartTime(schedule.ScheduleInfo); + + // disable run once task + if (schedule.ScheduleInfo.ScheduleType == ScheduleType.OneTime) + schedule.ScheduleInfo.Enabled = false; + + schedule.ScheduleInfo.LastRun = DateTime.Now; + UpdateSchedule(schedule.ScheduleInfo); + return 0; } diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/SchedulerJob.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/SchedulerJob.cs index 688442cc..a27d7c34 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/SchedulerJob.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Scheduling/SchedulerJob.cs @@ -109,6 +109,7 @@ namespace WebsitePanel.EnterpriseServer else throw new Exception(String.Format("Could not create scheduled task of '{0}' type", task.TaskType)); + // Thread.Sleep(40000); } catch (Exception ex) { diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Tasks/TaskController.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Tasks/TaskController.cs index b85ced39..f19c4e13 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Tasks/TaskController.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Tasks/TaskController.cs @@ -69,7 +69,7 @@ namespace WebsitePanel.EnterpriseServer return task; } - public static void AddTask(BackgroundTask task) + public static int AddTask(BackgroundTask task) { int taskId = DataProvider.AddBackgroundTask(task.Guid, task.TaskId, task.ScheduleId, task.PackageId, task.UserId, task.EffectiveUserId, task.TaskName, task.ItemId, task.ItemName, @@ -80,6 +80,7 @@ namespace WebsitePanel.EnterpriseServer AddTaskParams(taskId, task.Params); DataProvider.AddBackgroundTaskStack(taskId); + return taskId; } public static void UpdateTask(BackgroundTask task) diff --git a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Tasks/TaskManager.cs b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Tasks/TaskManager.cs index ecf5d5f3..4f838220 100644 --- a/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Tasks/TaskManager.cs +++ b/WebsitePanel/Sources/WebsitePanel.EnterpriseServer.Code/Tasks/TaskManager.cs @@ -27,6 +27,7 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; +using System.Collections.Concurrent; using System.IO; using System.Threading; using System.Collections; @@ -46,7 +47,7 @@ namespace WebsitePanel.EnterpriseServer { private static Hashtable eventHandlers = null; //using id instead of guid - private static Dictionary _taskThreadsDictionary = new Dictionary(); + private static ConcurrentDictionary _taskThreadsDictionary = new ConcurrentDictionary(); // purge timer, used for killing old tasks from the hash static Timer purgeTimer = new Timer(new TimerCallback(PurgeCompletedTasks), @@ -162,11 +163,9 @@ namespace WebsitePanel.EnterpriseServer String itemNameStr = itemName != null ? itemName.ToString() : String.Empty; - BackgroundTask task = new BackgroundTask(Guid, taskId, userId, effectiveUserId, source, taskName, itemNameStr, itemId, scheduleId, packageId, maximumExecutionTime, parameters); - AddTaskThread(task, Thread.CurrentThread); List tasks = TaskController.GetTasks(Guid); @@ -188,7 +187,8 @@ namespace WebsitePanel.EnterpriseServer // call event handler CallTaskEventHandler(task, false); - TaskController.AddTask(task); + int newTaskId = TaskController.AddTask(task); + AddTaskThread(newTaskId, Thread.CurrentThread); } public static void WriteParameter(string parameterName, object parameterValue) @@ -551,12 +551,12 @@ namespace WebsitePanel.EnterpriseServer task.NotifyOnComplete = true; } - internal static void AddTaskThread(BackgroundTask task, Thread taskThread) + internal static void AddTaskThread(int taskId, Thread taskThread) { - if (_taskThreadsDictionary.ContainsKey(task.Id)) - _taskThreadsDictionary[task.Id] = taskThread; + if (_taskThreadsDictionary.ContainsKey(taskId)) + _taskThreadsDictionary[taskId] = taskThread; else - _taskThreadsDictionary.Add(task.Id, taskThread); + _taskThreadsDictionary.AddOrUpdate(taskId, taskThread, (key, oldValue) => taskThread); } public static void StopTask(string taskId) @@ -579,8 +579,11 @@ namespace WebsitePanel.EnterpriseServer { if (_taskThreadsDictionary.ContainsKey(key)) { - _taskThreadsDictionary[key].Abort(); - _taskThreadsDictionary.Remove(key); + if (_taskThreadsDictionary[key] != null) + if (_taskThreadsDictionary[key].IsAlive) + _taskThreadsDictionary[key].Abort(); + Thread deleted; + _taskThreadsDictionary.TryRemove(key,out deleted); } } diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Schedules.ascx b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Schedules.ascx index 7e6c19f5..9c718a88 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Schedules.ascx +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Schedules.ascx @@ -5,6 +5,8 @@ <%@ Register Src="UserControls/Quota.ascx" TagName="Quota" TagPrefix="uc4" %> <%@ Import Namespace="WebsitePanel.Portal" %> + +
@@ -15,6 +17,12 @@
+ + + + + + - \ No newline at end of file + + + + \ No newline at end of file diff --git a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Schedules.ascx.designer.cs b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Schedules.ascx.designer.cs index 93e0d3c0..f7cffb9e 100644 --- a/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Schedules.ascx.designer.cs +++ b/WebsitePanel/Sources/WebsitePanel.WebPortal/DesktopModules/WebsitePanel/Schedules.ascx.designer.cs @@ -1,31 +1,3 @@ -// Copyright (c) 2012, Outercurve Foundation. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// - Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// - Neither the name of the Outercurve Foundation nor the names of its -// contributors may be used to endorse or promote products derived from this -// software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - //------------------------------------------------------------------------------ // // This code was generated by a tool. @@ -40,6 +12,15 @@ namespace WebsitePanel.Portal { public partial class Schedules { + /// + /// tasksTimer control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.Timer tasksTimer; + /// /// btnAddItem control. /// @@ -67,6 +48,15 @@ namespace WebsitePanel.Portal { /// protected global::WebsitePanel.Portal.SearchBox searchBox; + /// + /// schedulesUpdatePanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.UpdatePanel schedulesUpdatePanel; + /// /// gvSchedules control. ///