source: branches/eraser6/pluginsRewrite/Eraser.Manager/Task.cs @ 2499

Revision 2499, 10.3 KB checked in by lowjoel, 2 years ago (diff)

Oops, allow removal of tasks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
RevLine 
[1359]1/*
2 * $Id$
[1675]3 * Copyright 2008-2010 The Eraser Project
[1359]4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Text;
25using System.IO;
[2019]26using System.Runtime.Serialization;
[1359]27using System.Security.Permissions;
28using System.Threading;
29
[1802]30using Eraser.Util;
31using Eraser.Util.ExtensionMethods;
[2406]32using Eraser.Plugins;
[2366]33using Eraser.Plugins.ExtensionPoints;
[1802]34
[1359]35namespace Eraser.Manager
36{
37    /// <summary>
38    /// Deals with an erase task.
39    /// </summary>
40    [Serializable]
[2467]41    public class Task : ITask, ISerializable
[1359]42    {
43        #region Serialization code
44        protected Task(SerializationInfo info, StreamingContext context)
45        {
46            Name = (string)info.GetValue("Name", typeof(string));
47            Executor = context.Context as Executor;
[2364]48            Targets = (ErasureTargetCollection)info.GetValue("Targets", typeof(ErasureTargetCollection));
[1359]49            Targets.Owner = this;
[1802]50            Log = (List<LogSink>)info.GetValue("Log", typeof(List<LogSink>));
[1359]51            Canceled = false;
52
53            Schedule schedule = (Schedule)info.GetValue("Schedule", typeof(Schedule));
54            if (schedule.GetType() == Schedule.RunManually.GetType())
55                Schedule = Schedule.RunManually;
56            else if (schedule.GetType() == Schedule.RunNow.GetType())
57                Schedule = Schedule.RunNow;
58            else if (schedule.GetType() == Schedule.RunOnRestart.GetType())
59                Schedule = Schedule.RunOnRestart;
60            else if (schedule is RecurringSchedule)
61                Schedule = schedule;
62            else
63                throw new InvalidDataException(S._("An invalid type was found when loading " +
64                    "the task schedule"));
65        }
66
67        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
68        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
69        {
70            info.AddValue("Name", Name);
71            info.AddValue("Schedule", Schedule);
72            info.AddValue("Targets", Targets);
73            info.AddValue("Log", Log);
74        }
75        #endregion
76
77        /// <summary>
78        /// Constructor.
79        /// </summary>
80        public Task()
81        {
82            Name = string.Empty;
[2364]83            Targets = new ErasureTargetCollection(this);
[1359]84            Schedule = Schedule.RunNow;
85            Canceled = false;
[1802]86            Log = new List<LogSink>();
[1359]87        }
88
89        /// <summary>
90        /// The Executor object which is managing this task.
91        /// </summary>
[2484]92        public Executor Executor
93        {
94            get
95            {
96                return executor;
97            }
98            internal set
99            {
[2499]100                if (executor != null && value != null)
[2491]101                    throw new InvalidOperationException("A task can only belong to one " +
102                        "executor at any one time");
[1359]103
[2484]104                executor = value;
105            }
106        }
107
[1359]108        /// <summary>
109        /// The name for this task. This is just an opaque value for the user to
110        /// recognize the task.
111        /// </summary>
112        public string Name { get; set; }
113
114        /// <summary>
115        /// The name of the task, used for display in UI elements.
116        /// </summary>
[2485]117        public override string ToString()
[1359]118        {
[2484]119            //Simple case, the task name was given by the user.
120            if (!string.IsNullOrEmpty(Name))
121                return Name;
122
123            string result = string.Empty;
124            if (Targets.Count == 0)
125                return result;
126            else if (Targets.Count < 5)
[1359]127            {
[2484]128                //Simpler case, small set of data.
129                foreach (IErasureTarget tgt in Targets)
130                    result += S._("{0}, ", tgt);
[1359]131
[2484]132                return result.Remove(result.Length - 2);
133            }
134            else
135            {
136                //Ok, we've quite a few entries, get the first, the mid and the end.
137                result = S._("{0}, ", Targets[0]);
138                result += S._("{0}, ", Targets[Targets.Count / 2]);
139                result += Targets[Targets.Count - 1];
[1497]140
[2484]141                return S._("{0} and {1} other targets", result, Targets.Count - 3);
[1359]142            }
143        }
144
145        /// <summary>
146        /// The set of data to erase when this task is executed.
147        /// </summary>
[2364]148        public ErasureTargetCollection Targets { get; private set; }
[1359]149
150        /// <summary>
[2467]151        /// <see cref="Targets"/>
152        /// </summary>
153        ICollection<IErasureTarget> ITask.Targets
154        {
155            get { return Targets; }
156        }
157
158        /// <summary>
[1359]159        /// The schedule for running the task.
160        /// </summary>
161        public Schedule Schedule
162        {
163            get
164            {
165                return schedule;
166            }
167            set
168            {
169                if (value.Owner != null)
[1802]170                    throw new ArgumentException("The schedule provided can only " +
171                        "belong to one task at a time");
[1359]172
173                if (schedule is RecurringSchedule)
174                    ((RecurringSchedule)schedule).Owner = null;
175                schedule = value;
176                if (schedule is RecurringSchedule)
177                    ((RecurringSchedule)schedule).Owner = this;
178                OnTaskEdited();
179            }
180        }
181
182        /// <summary>
183        /// The log entries which this task has accumulated.
184        /// </summary>
[1802]185        public List<LogSink> Log { get; private set; }
[1359]186
[1515]187        /// <summary>
188        /// The progress manager object which manages the progress of this task.
189        /// </summary>
190        public SteppedProgressManager Progress
191        {
192            get
193            {
194                if (!Executing)
195                    throw new InvalidOperationException("The progress of an erasure can only " +
196                        "be queried when the task is being executed.");
197
198                return progress;
199            }
200            private set
201            {
202                progress = value;
203            }
204        }
205
[2487]206        /// <summary>
207        /// Gets the status of the task - whether it is being executed.
208        /// </summary>
209        public bool Executing { get; private set; }
210
211        /// <summary>
212        /// Gets whether this task is currently queued to run. This is true only
213        /// if the queue it is in is an explicit request, i.e will run when the
214        /// executor is idle.
215        /// </summary>
216        public bool Queued
217        {
218            get
219            {
220                if (Executor == null)
221                    throw new InvalidOperationException();
222
223                return Executor.IsTaskQueued(this);
224            }
225        }
226
227        /// <summary>
228        /// Gets whether the task has been cancelled from execution.
229        /// </summary>
230        public bool Canceled
231        {
232            get;
233            private set;
234        }
235
236        /// <summary>
237        /// Cancels the task from running, or, if the task is queued for running,
238        /// removes the task from the queue.
239        /// </summary>
240        public void Cancel()
241        {
242            Executor.UnqueueTask(this);
243            Canceled = true;
244        }
245
246        /// <summary>
247        /// Executes the task in the context of the calling thread.
248        /// </summary>
249        public void Execute()
250        {
251            OnTaskStarted();
252            Executing = true;
253            Canceled = false;
254            Progress = new SteppedProgressManager();
255
256            try
257            {
258                //Run the task
259                foreach (IErasureTarget target in Targets)
260                    try
261                    {
262                        Progress.Steps.Add(new ErasureTargetProgressManagerStep(
263                            target, Targets.Count));
264                        target.Execute();
265                    }
266                    catch (FatalException)
267                    {
268                        throw;
269                    }
270                    catch (OperationCanceledException)
271                    {
272                        throw;
273                    }
274                    catch (SharingViolationException)
275                    {
276                    }
277            }
278            catch (FatalException e)
279            {
280                Logger.Log(e.Message, LogLevel.Fatal);
281            }
282            catch (OperationCanceledException e)
283            {
284                Logger.Log(e.Message, LogLevel.Fatal);
285            }
286            catch (SharingViolationException)
287            {
288            }
289            finally
290            {
291                //If the task is a recurring task, reschedule it since we are done.
292                if (Schedule is RecurringSchedule)
293                {
294                    ((RecurringSchedule)Schedule).Reschedule(DateTime.Now);
295                }
296
297                //If the task is an execute on restart task or run immediately task, it is
298                //only run once and can now be restored to a manually run task
299                if (Schedule == Schedule.RunOnRestart || Schedule == Schedule.RunNow)
300                    Schedule = Schedule.RunManually;
301
302                Progress = null;
303                Executing = false;
304                OnTaskFinished();
305            }
306        }
307
[2484]308        private Executor executor;
[1359]309        private Schedule schedule;
[1515]310        private SteppedProgressManager progress;
[1359]311
312        #region Events
313        /// <summary>
314        /// The task has been edited.
315        /// </summary>
[1802]316        public EventHandler TaskEdited { get; set; }
[1359]317
318        /// <summary>
319        /// The start of the execution of a task.
320        /// </summary>
[1802]321        public EventHandler TaskStarted { get; set; }
[1359]322
323        /// <summary>
324        /// The completion of the execution of a task.
325        /// </summary>
[1802]326        public EventHandler TaskFinished { get; set; }
[1359]327
328        /// <summary>
329        /// Broadcasts the task edited event.
330        /// </summary>
331        internal void OnTaskEdited()
332        {
333            if (TaskEdited != null)
[1802]334                TaskEdited(this, EventArgs.Empty);
[1359]335        }
336
337        /// <summary>
338        /// Broadcasts the task execution start event.
339        /// </summary>
[2487]340        private void OnTaskStarted()
[1359]341        {
342            if (TaskStarted != null)
[1802]343                TaskStarted(this, EventArgs.Empty);
[1359]344        }
345
346        /// <summary>
347        /// Broadcasts the task execution completion event.
348        /// </summary>
[2487]349        private void OnTaskFinished()
[1359]350        {
351            if (TaskFinished != null)
[1802]352                TaskFinished(this, EventArgs.Empty);
[1359]353        }
354        #endregion
355    }
356
357    /// <summary>
[2488]358    /// Returns the progress of an erasure target, since that comprises the
359    /// steps of the Task Progress.
360    /// </summary>
361    public class ErasureTargetProgressManagerStep : SteppedProgressManagerStepBase
362    {
363        /// <summary>
364        /// Constructor.
365        /// </summary>
366        /// <param name="target">The erasure target represented by this object.</param>
367        /// <param name="steps">The number of targets in the task.</param>
368        public ErasureTargetProgressManagerStep(IErasureTarget target, int targets)
369            : base(1.0f / targets)
370        {
371            Target = target;
372        }
373
374        public override ProgressManagerBase Progress
375        {
376            get
377            {
[2497]378                ProgressManagerBase targetProgress = Target.Progress;
379                if (targetProgress != null)
380                    TargetProgress = targetProgress;
381
382                return TargetProgress;
[2488]383            }
384            set
385            {
386                throw new InvalidOperationException();
387            }
388        }
389
390        /// <summary>
391        /// The erasure target represented by this step.
392        /// </summary>
393        public IErasureTarget Target
394        {
395            get;
396            private set;
397        }
[2497]398
399        /// <summary>
400        /// Caches a copy of the progress object for the Target. This is so that
401        /// for as long we our object is alive we can give valid information
402        /// (as required by the SteppedProgressManager class)
403        /// </summary>
404        private ProgressManagerBase TargetProgress;
[2488]405    }
406
407    /// <summary>
[1359]408    /// A base event class for all event arguments involving a task.
409    /// </summary>
410    public class TaskEventArgs : EventArgs
411    {
412        /// <summary>
413        /// Constructor.
414        /// </summary>
415        /// <param name="task">The task being referred to by this event.</param>
416        public TaskEventArgs(Task task)
417        {
418            Task = task;
419        }
420
421        /// <summary>
422        /// The executing task.
423        /// </summary>
424        public Task Task { get; private set; }
425    }
[1022]426}
Note: See TracBrowser for help on using the repository browser.