using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Model.Events; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Tasks; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace MediaBrowser.Common.Implementations.ScheduledTasks { /// /// Class TaskManager /// public class TaskManager : ITaskManager { public event EventHandler> TaskExecuting; public event EventHandler TaskCompleted; /// /// Gets the list of Scheduled Tasks /// /// The scheduled tasks. public IScheduledTaskWorker[] ScheduledTasks { get; private set; } /// /// The _task queue /// private readonly SortedDictionary _taskQueue = new SortedDictionary(); /// /// Gets or sets the json serializer. /// /// The json serializer. private IJsonSerializer JsonSerializer { get; set; } /// /// Gets or sets the application paths. /// /// The application paths. private IApplicationPaths ApplicationPaths { get; set; } /// /// Gets the logger. /// /// The logger. private ILogger Logger { get; set; } /// /// Initializes a new instance of the class. /// /// The application paths. /// The json serializer. /// The logger. /// kernel public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger) { ApplicationPaths = applicationPaths; JsonSerializer = jsonSerializer; Logger = logger; ScheduledTasks = new IScheduledTaskWorker[] { }; } /// /// Cancels if running and queue. /// /// /// Task options. public void CancelIfRunningAndQueue(TaskExecutionOptions options) where T : IScheduledTask { var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T)); ((ScheduledTaskWorker)task).CancelIfRunning(); QueueScheduledTask(options); } public void CancelIfRunningAndQueue() where T : IScheduledTask { CancelIfRunningAndQueue(new TaskExecutionOptions()); } /// /// Cancels if running /// /// public void CancelIfRunning() where T : IScheduledTask { var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T)); ((ScheduledTaskWorker)task).CancelIfRunning(); } /// /// Queues the scheduled task. /// /// /// Task options public void QueueScheduledTask(TaskExecutionOptions options) where T : IScheduledTask { var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T)); QueueScheduledTask(scheduledTask, options); } public void QueueScheduledTask() where T : IScheduledTask { QueueScheduledTask(new TaskExecutionOptions()); } /// /// Queues the scheduled task. /// /// The task. /// The task options. public void QueueScheduledTask(IScheduledTask task, TaskExecutionOptions options) { var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == task.GetType()); QueueScheduledTask(scheduledTask, options); } /// /// Queues the scheduled task. /// /// The task. /// The task options. private void QueueScheduledTask(IScheduledTaskWorker task, TaskExecutionOptions options) { var type = task.ScheduledTask.GetType(); lock (_taskQueue) { // If it's idle just execute immediately if (task.State == TaskState.Idle) { Execute(task, options); return; } if (!_taskQueue.ContainsKey(type)) { Logger.Info("Queueing task {0}", type.Name); _taskQueue.Add(type, options); } else { _taskQueue[type] = options; Logger.Info("Task already queued: {0}", type.Name); } } } /// /// Adds the tasks. /// /// The tasks. public void AddTasks(IEnumerable tasks) { var myTasks = ScheduledTasks.ToList(); var list = tasks.ToList(); myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger))); ScheduledTasks = myTasks.ToArray(); } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool dispose) { foreach (var task in ScheduledTasks) { task.Dispose(); } } public void Cancel(IScheduledTaskWorker task) { ((ScheduledTaskWorker)task).Cancel(); } public Task Execute(IScheduledTaskWorker task, TaskExecutionOptions options) { return ((ScheduledTaskWorker)task).Execute(options); } /// /// Called when [task executing]. /// /// The task. internal void OnTaskExecuting(IScheduledTaskWorker task) { EventHelper.FireEventIfNotNull(TaskExecuting, this, new GenericEventArgs { Argument = task }, Logger); } /// /// Called when [task completed]. /// /// The task. /// The result. internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result) { EventHelper.FireEventIfNotNull(TaskCompleted, task, new TaskCompletionEventArgs { Result = result, Task = task }, Logger); ExecuteQueuedTasks(); } /// /// Executes the queued tasks. /// private void ExecuteQueuedTasks() { // Execute queued tasks lock (_taskQueue) { foreach (var enqueuedType in _taskQueue.ToList()) { var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == enqueuedType.Key); if (scheduledTask.State == TaskState.Idle) { Execute(scheduledTask, enqueuedType.Value); _taskQueue.Remove(enqueuedType.Key); } } } } } }