source: trunk/eraser/Eraser.Manager/Task.cs @ 2275

Revision 2275, 9.8 KB checked in by lowjoel, 4 years ago (diff)

Fixed crash at task finish (error introduced in r2268)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008-2010 The Eraser Project
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;
26using System.Runtime.Serialization;
27using System.Security.Permissions;
28using System.Threading;
29
30using Eraser.Util;
31using Eraser.Util.ExtensionMethods;
32
33namespace Eraser.Manager
34{
35    /// <summary>
36    /// Deals with an erase task.
37    /// </summary>
38    [Serializable]
39    public class Task : ISerializable
40    {
41        #region Serialization code
42        protected Task(SerializationInfo info, StreamingContext context)
43        {
44            Name = (string)info.GetValue("Name", typeof(string));
45            Executor = context.Context as Executor;
46            Targets = (ErasureTargetsCollection)info.GetValue("Targets", typeof(ErasureTargetsCollection));
47            Targets.Owner = this;
48            Log = (List<LogSink>)info.GetValue("Log", typeof(List<LogSink>));
49            Canceled = false;
50
51            Schedule schedule = (Schedule)info.GetValue("Schedule", typeof(Schedule));
52            if (schedule.GetType() == Schedule.RunManually.GetType())
53                Schedule = Schedule.RunManually;
54            else if (schedule.GetType() == Schedule.RunNow.GetType())
55                Schedule = Schedule.RunNow;
56            else if (schedule.GetType() == Schedule.RunOnRestart.GetType())
57                Schedule = Schedule.RunOnRestart;
58            else if (schedule is RecurringSchedule)
59                Schedule = schedule;
60            else
61                throw new InvalidDataException(S._("An invalid type was found when loading " +
62                    "the task schedule"));
63        }
64
65        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
66        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
67        {
68            info.AddValue("Name", Name);
69            info.AddValue("Schedule", Schedule);
70            info.AddValue("Targets", Targets);
71            info.AddValue("Log", Log);
72        }
73        #endregion
74
75        /// <summary>
76        /// Constructor.
77        /// </summary>
78        public Task()
79        {
80            Name = string.Empty;
81            Targets = new ErasureTargetsCollection(this);
82            Schedule = Schedule.RunNow;
83            Canceled = false;
84            Log = new List<LogSink>();
85        }
86
87        /// <summary>
88        /// Cancels the task from running, or, if the task is queued for running,
89        /// removes the task from the queue.
90        /// </summary>
91        public void Cancel()
92        {
93            Executor.UnqueueTask(this);
94            Canceled = true;
95        }
96
97        /// <summary>
98        /// The Executor object which is managing this task.
99        /// </summary>
100        public Executor Executor { get; internal set; }
101
102        /// <summary>
103        /// The name for this task. This is just an opaque value for the user to
104        /// recognize the task.
105        /// </summary>
106        public string Name { get; set; }
107
108        /// <summary>
109        /// The name of the task, used for display in UI elements.
110        /// </summary>
111        public string UIText
112        {
113            get
114            {
115                //Simple case, the task name was given by the user.
116                if (!string.IsNullOrEmpty(Name))
117                    return Name;
118
119                string result = string.Empty;
120                if (Targets.Count == 0)
121                    return result;
122                else if (Targets.Count < 5)
123                {
124                    //Simpler case, small set of data.
125                    foreach (ErasureTarget tgt in Targets)
126                        result += S._("{0}, ", tgt.UIText);
127
128                    return result.Remove(result.Length - 2);
129                }
130                else
131                {
132                    //Ok, we've quite a few entries, get the first, the mid and the end.
133                    result = S._("{0}, ", Targets[0].UIText);
134                    result += S._("{0}, ", Targets[Targets.Count / 2].UIText);
135                    result += Targets[Targets.Count - 1].UIText;
136
137                    return S._("{0} and {1} other targets", result, Targets.Count - 3);
138                }
139            }
140        }
141
142        /// <summary>
143        /// Gets the status of the task - whether it is being executed.
144        /// </summary>
145        public bool Executing { get; private set; }
146
147        /// <summary>
148        /// Gets whether this task is currently queued to run. This is true only
149        /// if the queue it is in is an explicit request, i.e will run when the
150        /// executor is idle.
151        /// </summary>
152        public bool Queued
153        {
154            get
155            {
156                return Executor.IsTaskQueued(this);
157            }
158        }
159
160        /// <summary>
161        /// Gets whether the task has been cancelled from execution.
162        /// </summary>
163        public bool Canceled
164        {
165            get;
166            internal set;
167        }
168
169        /// <summary>
170        /// The set of data to erase when this task is executed.
171        /// </summary>
172        public ErasureTargetsCollection Targets { get; private set; }
173
174        /// <summary>
175        /// The schedule for running the task.
176        /// </summary>
177        public Schedule Schedule
178        {
179            get
180            {
181                return schedule;
182            }
183            set
184            {
185                if (value.Owner != null)
186                    throw new ArgumentException("The schedule provided can only " +
187                        "belong to one task at a time");
188
189                if (schedule is RecurringSchedule)
190                    ((RecurringSchedule)schedule).Owner = null;
191                schedule = value;
192                if (schedule is RecurringSchedule)
193                    ((RecurringSchedule)schedule).Owner = this;
194                OnTaskEdited();
195            }
196        }
197
198        /// <summary>
199        /// The log entries which this task has accumulated.
200        /// </summary>
201        public List<LogSink> Log { get; private set; }
202
203        /// <summary>
204        /// The progress manager object which manages the progress of this task.
205        /// </summary>
206        public SteppedProgressManager Progress
207        {
208            get
209            {
210                if (!Executing)
211                    throw new InvalidOperationException("The progress of an erasure can only " +
212                        "be queried when the task is being executed.");
213
214                return progress;
215            }
216            private set
217            {
218                progress = value;
219            }
220        }
221
222        private Schedule schedule;
223        private SteppedProgressManager progress;
224
225        #region Events
226        /// <summary>
227        /// The task has been edited.
228        /// </summary>
229        public EventHandler TaskEdited { get; set; }
230
231        /// <summary>
232        /// The start of the execution of a task.
233        /// </summary>
234        public EventHandler TaskStarted { get; set; }
235
236        /// <summary>
237        /// The event object holding all event handlers.
238        /// </summary>
239        public EventHandler<ProgressChangedEventArgs> ProgressChanged { get; set; }
240
241        /// <summary>
242        /// The completion of the execution of a task.
243        /// </summary>
244        public EventHandler TaskFinished { get; set; }
245
246        /// <summary>
247        /// Broadcasts the task edited event.
248        /// </summary>
249        internal void OnTaskEdited()
250        {
251            if (TaskEdited != null)
252                TaskEdited(this, EventArgs.Empty);
253        }
254
255        /// <summary>
256        /// Broadcasts the task execution start event.
257        /// </summary>
258        internal void OnTaskStarted()
259        {
260            if (TaskStarted != null)
261                TaskStarted(this, EventArgs.Empty);
262            Executing = true;
263            Progress = new SteppedProgressManager();
264        }
265
266        /// <summary>
267        /// Broadcasts a ProgressChanged event. The sender will be the erasure target
268        /// which broadcast this event; e.UserState will contain extra information
269        /// about the progress which is stored as a TaskProgressChangedEventArgs
270        /// object.
271        /// </summary>
272        /// <param name="sender">The <see cref="ErasureTarget"/> which is reporting
273        /// progress.</param>
274        /// <param name="e">The new progress value.</param>
275        /// <exception cref="ArgumentException">e.UserState must be of the type
276        /// <see cref="TaskProgressEventargs"/></exception>
277        /// <exception cref="ArgumentNullException">Both sender and e cannot be null.</exception>
278        internal void OnProgressChanged(ErasureTarget sender, ProgressChangedEventArgs e)
279        {
280            if (sender == null)
281                throw new ArgumentNullException("sender");
282            if (e == null)
283                throw new ArgumentNullException("sender");
284            if (e.UserState.GetType() != typeof(TaskProgressChangedEventArgs))
285                throw new ArgumentException("The Task.OnProgressChanged event expects a " +
286                    "TaskProgressEventArgs argument for the ProgressChangedEventArgs' UserState " +
287                    "object.", "e");
288
289            if (ProgressChanged != null)
290                ProgressChanged(sender, e);
291        }
292
293        /// <summary>
294        /// Broadcasts the task execution completion event.
295        /// </summary>
296        internal void OnTaskFinished()
297        {
298            Progress = null;
299            Executing = false;
300            if (TaskFinished != null)
301                TaskFinished(this, EventArgs.Empty);
302        }
303        #endregion
304    }
305
306    /// <summary>
307    /// A base event class for all event arguments involving a task.
308    /// </summary>
309    public class TaskEventArgs : EventArgs
310    {
311        /// <summary>
312        /// Constructor.
313        /// </summary>
314        /// <param name="task">The task being referred to by this event.</param>
315        public TaskEventArgs(Task task)
316        {
317            Task = task;
318        }
319
320        /// <summary>
321        /// The executing task.
322        /// </summary>
323        public Task Task { get; private set; }
324    }
325
326    /// <summary>
327    /// Stores extra information in the <see cref="ProgressChangedEventArgs"/>
328    /// structure that is not conveyed in the ProgressManagerBase classes.
329    /// </summary>
330    public class TaskProgressChangedEventArgs
331    {
332        /// <summary>
333        /// Constructor.
334        /// </summary>
335        /// <param name="itemName">The item whose erasure progress is being erased.</param>
336        /// <param name="itemPass">The current pass number for this item.</param>
337        /// <param name="itemTotalPasses">The total number of passes to complete erasure
338        /// of this item.</param>
339        public TaskProgressChangedEventArgs(string itemName, int itemPass,
340            int itemTotalPasses)
341        {
342            ItemName = itemName;
343            ItemPass = itemPass;
344            ItemTotalPasses = itemTotalPasses;
345        }
346
347        /// <summary>
348        /// The file name of the item being erased.
349        /// </summary>
350        public string ItemName { get; private set; }
351
352        /// <summary>
353        /// The pass number of a multi-pass erasure method.
354        /// </summary>
355        public int ItemPass { get; private set; }
356
357        /// <summary>
358        /// The total number of passes to complete before this erasure method is
359        /// completed.
360        /// </summary>
361        public int ItemTotalPasses { get; private set; }
362    }
363}
Note: See TracBrowser for help on using the repository browser.