using MediaBrowser.Common.Kernel; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Tasks; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace MediaBrowser.Common.Implementations.ScheduledTasks { /// /// Class TaskManager /// public class TaskManager : ITaskManager { /// /// Gets the list of Scheduled Tasks /// /// The scheduled tasks. public IScheduledTask[] ScheduledTasks { get; private set; } /// /// The _task queue /// private readonly List _taskQueue = new List(); /// /// The _logger /// private readonly ILogger _logger; /// /// The _application paths /// private readonly IApplicationPaths _applicationPaths; /// /// The _json serializer /// private readonly IJsonSerializer _jsonSerializer; /// /// Initializes a new instance of the class. /// /// The application paths. /// The json serializer. /// The logger. /// kernel public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger) { if (applicationPaths == null) { throw new ArgumentException("applicationPaths"); } if (jsonSerializer == null) { throw new ArgumentException("jsonSerializer"); } if (logger == null) { throw new ArgumentException("logger"); } _applicationPaths = applicationPaths; _jsonSerializer = jsonSerializer; _logger = logger; ScheduledTasks = new IScheduledTask[] {}; } /// /// Cancels if running and queue. /// /// public void CancelIfRunningAndQueue() where T : IScheduledTask { ScheduledTasks.OfType().First().CancelIfRunning(); QueueScheduledTask(); } /// /// Queues the scheduled task. /// /// public void QueueScheduledTask() where T : IScheduledTask { var scheduledTask = ScheduledTasks.OfType().First(); QueueScheduledTask(scheduledTask); } /// /// Queues the scheduled task. /// /// The task. public void QueueScheduledTask(IScheduledTask task) { var type = task.GetType(); var scheduledTask = ScheduledTasks.First(t => t.GetType() == type); lock (_taskQueue) { // If it's idle just execute immediately if (scheduledTask.State == TaskState.Idle) { scheduledTask.Execute(); return; } if (!_taskQueue.Contains(type)) { _logger.Info("Queueing task {0}", type.Name); _taskQueue.Add(type); } else { _logger.Info("Task already queued: {0}", type.Name); } } } /// /// Called when [task completed]. /// /// The task. public void OnTaskCompleted(IScheduledTask task) { // Execute queued tasks lock (_taskQueue) { var copy = _taskQueue.ToList(); foreach (var type in copy) { var scheduledTask = ScheduledTasks.First(t => t.GetType() == type); if (scheduledTask.State == TaskState.Idle) { scheduledTask.Execute(); _taskQueue.Remove(type); } } } } /// /// Adds the tasks. /// /// The tasks. public void AddTasks(IEnumerable tasks) { var myTasks = ScheduledTasks.ToList(); myTasks.AddRange(tasks); ScheduledTasks = myTasks.ToArray(); } /// /// The _scheduled tasks configuration directory /// private string _scheduledTasksConfigurationDirectory; /// /// Gets the scheduled tasks configuration directory. /// /// The scheduled tasks configuration directory. private string ScheduledTasksConfigurationDirectory { get { if (_scheduledTasksConfigurationDirectory == null) { _scheduledTasksConfigurationDirectory = Path.Combine(_applicationPaths.ConfigurationDirectoryPath, "ScheduledTasks"); if (!Directory.Exists(_scheduledTasksConfigurationDirectory)) { Directory.CreateDirectory(_scheduledTasksConfigurationDirectory); } } return _scheduledTasksConfigurationDirectory; } } /// /// The _scheduled tasks data directory /// private string _scheduledTasksDataDirectory; /// /// Gets the scheduled tasks data directory. /// /// The scheduled tasks data directory. private string ScheduledTasksDataDirectory { get { if (_scheduledTasksDataDirectory == null) { _scheduledTasksDataDirectory = Path.Combine(_applicationPaths.DataPath, "ScheduledTasks"); if (!Directory.Exists(_scheduledTasksDataDirectory)) { Directory.CreateDirectory(_scheduledTasksDataDirectory); } } return _scheduledTasksDataDirectory; } } /// /// Gets the history file path. /// /// The history file path. private string GetHistoryFilePath(IScheduledTask task) { return Path.Combine(ScheduledTasksDataDirectory, task.Id + ".js"); } /// /// Gets the configuration file path. /// /// The task. /// System.String. private string GetConfigurationFilePath(IScheduledTask task) { return Path.Combine(ScheduledTasksConfigurationDirectory, task.Id + ".js"); } /// /// Called when [task completed]. /// /// The task. /// The start time. /// The end time. /// The status. public void OnTaskCompleted(IScheduledTask task, DateTime startTime, DateTime endTime, TaskCompletionStatus status) { var elapsedTime = endTime - startTime; _logger.Info("{0} {1} after {2} minute(s) and {3} seconds", task.Name, status, Math.Truncate(elapsedTime.TotalMinutes), elapsedTime.Seconds); var result = new TaskResult { StartTimeUtc = startTime, EndTimeUtc = endTime, Status = status, Name = task.Name, Id = task.Id }; _jsonSerializer.SerializeToFile(result, GetHistoryFilePath(task)); //task.LastExecutionResult = result; } /// /// Gets the last execution result. /// /// The task. /// TaskResult. public TaskResult GetLastExecutionResult(IScheduledTask task) { return _jsonSerializer.DeserializeFromFile(GetHistoryFilePath(task)); } /// /// Loads the triggers. /// /// The task. /// IEnumerable{BaseTaskTrigger}. public IEnumerable LoadTriggers(IScheduledTask task) { try { return _jsonSerializer.DeserializeFromFile>(GetConfigurationFilePath(task)) .Select(ScheduledTaskHelpers.GetTrigger) .ToList(); } catch (IOException) { // File doesn't exist. No biggie. Return defaults. return task.GetDefaultTriggers(); } } /// /// Saves the triggers. /// /// The task. /// The triggers. public void SaveTriggers(IScheduledTask task, IEnumerable triggers) { _jsonSerializer.SerializeToFile(triggers.Select(ScheduledTaskHelpers.GetTriggerInfo), GetConfigurationFilePath(task)); } /// /// 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(); } } } }