Fixes Schedulers bugs

This commit is contained in:
vfedosevich 2013-05-29 15:52:13 +03:00
parent e8ed10a67b
commit c8a8be8894
7 changed files with 65 additions and 43 deletions

View file

@ -110,7 +110,7 @@ namespace WebsitePanel.EnterpriseServer
{ {
var taskThread = new Thread(() => RunBackgroundTask(task)) { Priority = ThreadPriority.Highest }; var taskThread = new Thread(() => RunBackgroundTask(task)) { Priority = ThreadPriority.Highest };
taskThread.Start(); 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)); var objTask = (SchedulerTask)Activator.CreateInstance(Type.GetType(schedule.Task.TaskType));
objTask.DoWork(); objTask.DoWork();
// Thread.Sleep(40000);
} }
catch (Exception ex) catch (Exception ex)
{ {

View file

@ -160,24 +160,39 @@ namespace WebsitePanel.EnterpriseServer
if (schedule == null) if (schedule == null)
return 0; return 0;
if (TaskController.GetScheduleTasks(scheduleId).Any(x => x.Status == BackgroundTaskStatus.Run
|| x.Status == BackgroundTaskStatus.Starting))
return 0;
var parameters = schedule.ScheduleInfo.Parameters.Select( var parameters = schedule.ScheduleInfo.Parameters.Select(
prm => new BackgroundTaskParameter(prm.ParameterId, prm.ParameterValue)).ToList(); prm => new BackgroundTaskParameter(prm.ParameterId, prm.ParameterValue)).ToList();
var packageInfo = PackageController.GetPackage(schedule.ScheduleInfo.PackageId);
var backgroundTask = new BackgroundTask( var backgroundTask = new BackgroundTask(
Guid.NewGuid(), Guid.NewGuid(),
Guid.NewGuid().ToString("N"), Guid.NewGuid().ToString("N"),
SecurityContext.User.UserId, SecurityContext.User.UserId,
SecurityContext.User.IsPeer SecurityContext.User.IsPeer
? SecurityContext.User.OwnerId ? SecurityContext.User.OwnerId
: SecurityContext.User.UserId, "SCHEDULER", "RUN_SCHEDULE", : packageInfo.UserId, "SCHEDULER", "RUN_SCHEDULE",
schedule.ScheduleInfo.ScheduleName, schedule.ScheduleInfo.ScheduleName,
schedule.ScheduleInfo.ScheduleId, schedule.ScheduleInfo.ScheduleId,
schedule.ScheduleInfo.ScheduleId, schedule.ScheduleInfo.ScheduleId,
schedule.ScheduleInfo.PackageId, schedule.ScheduleInfo.PackageId,
schedule.ScheduleInfo.MaxExecutionTime, parameters) { Status = BackgroundTaskStatus.Starting }; schedule.ScheduleInfo.MaxExecutionTime, parameters) { Status = BackgroundTaskStatus.Starting };
TaskController.AddTask(backgroundTask); 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; return 0;
} }

View file

@ -109,6 +109,7 @@ namespace WebsitePanel.EnterpriseServer
else else
throw new Exception(String.Format("Could not create scheduled task of '{0}' type", throw new Exception(String.Format("Could not create scheduled task of '{0}' type",
task.TaskType)); task.TaskType));
// Thread.Sleep(40000);
} }
catch (Exception ex) catch (Exception ex)
{ {

View file

@ -69,7 +69,7 @@ namespace WebsitePanel.EnterpriseServer
return task; 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, int taskId = DataProvider.AddBackgroundTask(task.Guid, task.TaskId, task.ScheduleId, task.PackageId, task.UserId,
task.EffectiveUserId, task.TaskName, task.ItemId, task.ItemName, task.EffectiveUserId, task.TaskName, task.ItemId, task.ItemName,
@ -80,6 +80,7 @@ namespace WebsitePanel.EnterpriseServer
AddTaskParams(taskId, task.Params); AddTaskParams(taskId, task.Params);
DataProvider.AddBackgroundTaskStack(taskId); DataProvider.AddBackgroundTaskStack(taskId);
return taskId;
} }
public static void UpdateTask(BackgroundTask task) public static void UpdateTask(BackgroundTask task)

View file

@ -27,6 +27,7 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System; using System;
using System.Collections.Concurrent;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Collections; using System.Collections;
@ -46,7 +47,7 @@ namespace WebsitePanel.EnterpriseServer
{ {
private static Hashtable eventHandlers = null; private static Hashtable eventHandlers = null;
//using id instead of guid //using id instead of guid
private static Dictionary<int, Thread> _taskThreadsDictionary = new Dictionary<int, Thread>(); private static ConcurrentDictionary<int, Thread> _taskThreadsDictionary = new ConcurrentDictionary<int, Thread>();
// purge timer, used for killing old tasks from the hash // purge timer, used for killing old tasks from the hash
static Timer purgeTimer = new Timer(new TimerCallback(PurgeCompletedTasks), static Timer purgeTimer = new Timer(new TimerCallback(PurgeCompletedTasks),
@ -162,11 +163,9 @@ namespace WebsitePanel.EnterpriseServer
String itemNameStr = itemName != null String itemNameStr = itemName != null
? itemName.ToString() ? itemName.ToString()
: String.Empty; : String.Empty;
BackgroundTask task = new BackgroundTask(Guid, taskId, userId, effectiveUserId, source, taskName, itemNameStr, BackgroundTask task = new BackgroundTask(Guid, taskId, userId, effectiveUserId, source, taskName, itemNameStr,
itemId, scheduleId, packageId, maximumExecutionTime, parameters); itemId, scheduleId, packageId, maximumExecutionTime, parameters);
AddTaskThread(task, Thread.CurrentThread);
List<BackgroundTask> tasks = TaskController.GetTasks(Guid); List<BackgroundTask> tasks = TaskController.GetTasks(Guid);
@ -188,7 +187,8 @@ namespace WebsitePanel.EnterpriseServer
// call event handler // call event handler
CallTaskEventHandler(task, false); CallTaskEventHandler(task, false);
TaskController.AddTask(task); int newTaskId = TaskController.AddTask(task);
AddTaskThread(newTaskId, Thread.CurrentThread);
} }
public static void WriteParameter(string parameterName, object parameterValue) public static void WriteParameter(string parameterName, object parameterValue)
@ -551,12 +551,12 @@ namespace WebsitePanel.EnterpriseServer
task.NotifyOnComplete = true; task.NotifyOnComplete = true;
} }
internal static void AddTaskThread(BackgroundTask task, Thread taskThread) internal static void AddTaskThread(int taskId, Thread taskThread)
{ {
if (_taskThreadsDictionary.ContainsKey(task.Id)) if (_taskThreadsDictionary.ContainsKey(taskId))
_taskThreadsDictionary[task.Id] = taskThread; _taskThreadsDictionary[taskId] = taskThread;
else else
_taskThreadsDictionary.Add(task.Id, taskThread); _taskThreadsDictionary.AddOrUpdate(taskId, taskThread, (key, oldValue) => taskThread);
} }
public static void StopTask(string taskId) public static void StopTask(string taskId)
@ -579,8 +579,11 @@ namespace WebsitePanel.EnterpriseServer
{ {
if (_taskThreadsDictionary.ContainsKey(key)) if (_taskThreadsDictionary.ContainsKey(key))
{ {
_taskThreadsDictionary[key].Abort(); if (_taskThreadsDictionary[key] != null)
_taskThreadsDictionary.Remove(key); if (_taskThreadsDictionary[key].IsAlive)
_taskThreadsDictionary[key].Abort();
Thread deleted;
_taskThreadsDictionary.TryRemove(key,out deleted);
} }
} }

View file

@ -5,6 +5,8 @@
<%@ Register Src="UserControls/Quota.ascx" TagName="Quota" TagPrefix="uc4" %> <%@ Register Src="UserControls/Quota.ascx" TagName="Quota" TagPrefix="uc4" %>
<%@ Import Namespace="WebsitePanel.Portal" %> <%@ Import Namespace="WebsitePanel.Portal" %>
<asp:Timer runat="server" Interval="5000" ID="tasksTimer" />
<div class="FormButtonsBar"> <div class="FormButtonsBar">
<div class="Left"> <div class="Left">
<asp:Button ID="btnAddItem" runat="server" meta:resourcekey="btnAddItem" Text="Add Scheduled Task" CssClass="Button3" OnClick="btnAddItem_Click" /> <asp:Button ID="btnAddItem" runat="server" meta:resourcekey="btnAddItem" Text="Add Scheduled Task" CssClass="Button3" OnClick="btnAddItem_Click" />
@ -15,6 +17,12 @@
<uc1:SearchBox ID="searchBox" runat="server" /> <uc1:SearchBox ID="searchBox" runat="server" />
</div> </div>
</div> </div>
<asp:UpdatePanel runat="server" ID="schedulesUpdatePanel" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="tasksTimer" EventName="Tick" />
</Triggers>
<ContentTemplate>
<asp:GridView id="gvSchedules" runat="server" AutoGenerateColumns="False" <asp:GridView id="gvSchedules" runat="server" AutoGenerateColumns="False"
DataSourceID="odsSchedules" AllowPaging="True" AllowSorting="True" EmptyDataText="gvSchedules" DataSourceID="odsSchedules" AllowPaging="True" AllowSorting="True" EmptyDataText="gvSchedules"
OnRowCommand="gvSchedules_RowCommand" CssSelectorClass="NormalGridView" OnRowCommand="gvSchedules_RowCommand" CssSelectorClass="NormalGridView"
@ -86,4 +94,7 @@
<asp:ControlParameter ControlID="searchBox" Name="filterColumn" PropertyName="FilterColumn" /> <asp:ControlParameter ControlID="searchBox" Name="filterColumn" PropertyName="FilterColumn" />
<asp:ControlParameter ControlID="searchBox" Name="filterValue" PropertyName="FilterValue" /> <asp:ControlParameter ControlID="searchBox" Name="filterValue" PropertyName="FilterValue" />
</SelectParameters> </SelectParameters>
</asp:ObjectDataSource> </asp:ObjectDataSource>
</ContentTemplate>
</asp:UpdatePanel>

View file

@ -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.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
@ -40,6 +12,15 @@ namespace WebsitePanel.Portal {
public partial class Schedules { public partial class Schedules {
/// <summary>
/// tasksTimer control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.Timer tasksTimer;
/// <summary> /// <summary>
/// btnAddItem control. /// btnAddItem control.
/// </summary> /// </summary>
@ -67,6 +48,15 @@ namespace WebsitePanel.Portal {
/// </remarks> /// </remarks>
protected global::WebsitePanel.Portal.SearchBox searchBox; protected global::WebsitePanel.Portal.SearchBox searchBox;
/// <summary>
/// schedulesUpdatePanel control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.UpdatePanel schedulesUpdatePanel;
/// <summary> /// <summary>
/// gvSchedules control. /// gvSchedules control.
/// </summary> /// </summary>