222 lines
7.9 KiB
C#
222 lines
7.9 KiB
C#
// 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.
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.ServiceProcess;
|
|
using System.Threading;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Data.SqlClient;
|
|
|
|
namespace WebsitePanel.EnterpriseServer
|
|
{
|
|
public delegate void ScheduleFinished(SchedulerJob schedule);
|
|
|
|
public sealed class Scheduler
|
|
{
|
|
public static SchedulerJob nextSchedule = null;
|
|
private static Timer timer = new Timer(ScheduleTasks, null, 30000, 30000);
|
|
|
|
public static void Start()
|
|
{
|
|
ScheduleTasks();
|
|
}
|
|
|
|
public static bool IsScheduleActive(int scheduleId)
|
|
{
|
|
Dictionary<int, BackgroundTask> scheduledTasks = TaskManager.GetScheduledTasks();
|
|
|
|
return scheduledTasks.ContainsKey(scheduleId);
|
|
}
|
|
|
|
public static void StartSchedule(SchedulerJob schedule)
|
|
{
|
|
if (IsScheduleActive(schedule.ScheduleInfo.ScheduleId))
|
|
return;
|
|
|
|
// run schedule
|
|
RunSchedule(schedule, false);
|
|
}
|
|
|
|
public static void StopSchedule(SchedulerJob schedule)
|
|
{
|
|
Dictionary<int, BackgroundTask> scheduledTasks = TaskManager.GetScheduledTasks();
|
|
if (!scheduledTasks.ContainsKey(schedule.ScheduleInfo.ScheduleId))
|
|
return;
|
|
|
|
BackgroundTask activeTask = scheduledTasks[schedule.ScheduleInfo.ScheduleId];
|
|
TaskManager.StopTask(activeTask.TaskId);
|
|
}
|
|
|
|
public static void ScheduleTasks()
|
|
{
|
|
ScheduleTasks(null);
|
|
}
|
|
|
|
public static void ScheduleTasks(object obj)
|
|
{
|
|
RunManualTasks();
|
|
nextSchedule = SchedulerController.GetNextSchedule();
|
|
|
|
if (nextSchedule != null)
|
|
{
|
|
if (nextSchedule.ScheduleInfo.NextRun <= DateTime.Now)
|
|
{
|
|
RunNextSchedule(null);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void RunManualTasks()
|
|
{
|
|
var tasks = TaskController.GetProcessTasks(BackgroundTaskStatus.Starting);
|
|
|
|
foreach (var task in tasks)
|
|
{
|
|
new Thread(() => RunBackgroundTask(task)) {Priority = ThreadPriority.Highest}.Start();
|
|
}
|
|
|
|
tasks = TaskController.GetProcessTasks(BackgroundTaskStatus.Stopping);
|
|
|
|
foreach (var task in tasks)
|
|
{
|
|
TaskManager.StopTask(task);
|
|
}
|
|
}
|
|
|
|
private static void RunBackgroundTask(BackgroundTask backgroundTask)
|
|
{
|
|
UserInfo user = PackageController.GetPackageOwner(backgroundTask.PackageId);
|
|
|
|
SecurityContext.SetThreadPrincipal(user.UserId);
|
|
|
|
var schedule = SchedulerController.GetScheduleComplete(backgroundTask.ScheduleId);
|
|
|
|
backgroundTask.Guid = TaskManager.Guid;
|
|
backgroundTask.Status = BackgroundTaskStatus.Run;
|
|
|
|
TaskController.UpdateTask(backgroundTask);
|
|
|
|
try
|
|
{
|
|
var objTask = (SchedulerTask)Activator.CreateInstance(Type.GetType(schedule.Task.TaskType));
|
|
|
|
objTask.DoWork();
|
|
|
|
Thread.Sleep(100000);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
TaskManager.WriteError(ex, "Error executing scheduled task");
|
|
}
|
|
finally
|
|
{
|
|
try
|
|
{
|
|
TaskManager.CompleteTask();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
// call back for the timer function
|
|
static void RunNextSchedule(object obj) // obj ignored
|
|
{
|
|
if (nextSchedule == null)
|
|
return;
|
|
|
|
RunSchedule(nextSchedule, true);
|
|
|
|
// schedule next task
|
|
ScheduleTasks();
|
|
}
|
|
|
|
static void RunSchedule(SchedulerJob schedule, bool changeNextRun)
|
|
{
|
|
try
|
|
{
|
|
// update next run (if required)
|
|
if (changeNextRun)
|
|
{
|
|
SchedulerController.CalculateNextStartTime(schedule.ScheduleInfo);
|
|
}
|
|
|
|
// disable run once task
|
|
if (schedule.ScheduleInfo.ScheduleType == ScheduleType.OneTime)
|
|
schedule.ScheduleInfo.Enabled = false;
|
|
|
|
Dictionary<int, BackgroundTask> scheduledTasks = TaskManager.GetScheduledTasks();
|
|
if (!scheduledTasks.ContainsKey(schedule.ScheduleInfo.ScheduleId))
|
|
// this task should be run, so
|
|
// update its last run
|
|
schedule.ScheduleInfo.LastRun = DateTime.Now;
|
|
|
|
// update schedule
|
|
int MAX_RETRY_COUNT = 10;
|
|
int counter = 0;
|
|
while (counter < MAX_RETRY_COUNT)
|
|
{
|
|
try
|
|
{
|
|
SchedulerController.UpdateSchedule(schedule.ScheduleInfo);
|
|
break;
|
|
}
|
|
catch (SqlException)
|
|
{
|
|
System.Threading.Thread.Sleep(1000);
|
|
}
|
|
|
|
counter++;
|
|
}
|
|
|
|
// skip execution if the current task is still running
|
|
scheduledTasks = TaskManager.GetScheduledTasks();
|
|
if (!scheduledTasks.ContainsKey(schedule.ScheduleInfo.ScheduleId))
|
|
{
|
|
// run the schedule in the separate thread
|
|
schedule.Run();
|
|
}
|
|
}
|
|
catch (Exception Ex)
|
|
{
|
|
try
|
|
{
|
|
TaskManager.WriteError(string.Format("RunSchedule Error : {0}", Ex.Message));
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|