source: branches/eraser6/Manager/Task.cs @ 987

Revision 987, 24.8 KB checked in by lowjoel, 5 years ago (diff)

Pass the task list owner to the deserialisation constructor for each task so they can get the Executor instance automatically.

  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008 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.Text.RegularExpressions;
27using System.Runtime.Serialization;
28using System.ComponentModel;
29using Eraser.Util;
30using System.Security.Permissions;
31
32namespace Eraser.Manager
33{
34    /// <summary>
35    /// Deals with an erase task.
36    /// </summary>
37    [Serializable]
38    public class Task : ISerializable
39    {
40        #region Serialization code
41        protected Task(SerializationInfo info, StreamingContext context)
42        {
43            Name = (string)info.GetValue("Name", typeof(string));
44            Executor = context.Context as Executor;
45            Targets = (ErasureTargetsCollection)info.GetValue("Targets", typeof(ErasureTargetsCollection));
46            Targets.Owner = this;
47            Log = (Logger)info.GetValue("Log", typeof(Logger));
48
49            Schedule schedule = (Schedule)info.GetValue("Schedule", typeof(Schedule));
50            if (schedule.GetType() == Schedule.RunNow.GetType())
51                Schedule = Schedule.RunNow;
52            else if (schedule.GetType() == Schedule.RunOnRestart.GetType())
53                Schedule = Schedule.RunOnRestart;
54            else if (schedule is RecurringSchedule)
55                Schedule = schedule;
56            else
57                throw new InvalidDataException(S._("An invalid type was found when loading " +
58                    "the task schedule"));
59        }
60
61        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
62        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
63        {
64            info.AddValue("Name", Name);
65            info.AddValue("Schedule", Schedule);
66            info.AddValue("Targets", Targets);
67
68            lock (Log)
69                info.AddValue("Log", Log);
70        }
71        #endregion
72
73        /// <summary>
74        /// Constructor.
75        /// </summary>
76        public Task()
77        {
78            Name = string.Empty;
79            Targets = new ErasureTargetsCollection(this);
80            Schedule = Schedule.RunNow;
81            Log = new Logger();
82        }
83
84        /// <summary>
85        /// Cancels the task from running, or, if the task is queued for running,
86        /// removes the task from the queue.
87        /// </summary>
88        public void Cancel()
89        {
90            Executor.UnqueueTask(this);
91            Canceled = true;
92        }
93
94        /// <summary>
95        /// The Executor object which is managing this task.
96        /// </summary>
97        public Executor Executor { get; internal set; }
98
99        /// <summary>
100        /// The name for this task. This is just an opaque value for the user to
101        /// recognize the task.
102        /// </summary>
103        public string Name { get; set; }
104
105        /// <summary>
106        /// The name of the task, used for display in UI elements.
107        /// </summary>
108        public string UIText
109        {
110            get
111            {
112                //Simple case, the task name was given by the user.
113                if (Name.Length != 0)
114                    return Name;
115
116                string result = string.Empty;
117                if (Targets.Count < 3)
118                    //Simpler case, small set of data.
119                    foreach (ErasureTarget tgt in Targets)
120                        result += tgt.UIText + ", ";
121                else
122                    //Ok, we've quite a few entries, get the first, the mid and the end.
123                    for (int i = 0; i < Targets.Count; i += Targets.Count / 3)
124                        result += Targets[i].UIText + ", ";
125                return result.Substring(0, result.Length - 2);
126            }
127        }
128
129        /// <summary>
130        /// Gets the status of the task - whether it is being executed.
131        /// </summary>
132        public bool Executing { get; private set; }
133
134        /// <summary>
135        /// Gets whether this task is currently queued to run. This is true only
136        /// if the queue it is in is an explicit request, i.e will run when the
137        /// executor is idle.
138        /// </summary>
139        public bool Queued { get; internal set; }
140
141        /// <summary>
142        /// Gets whether the task has been cancelled from execution.
143        /// </summary>
144        public bool Canceled { get; internal set; }
145
146        /// <summary>
147        /// The set of data to erase when this task is executed.
148        /// </summary>
149        public ErasureTargetsCollection Targets { get; private set; }
150
151        /// <summary>
152        /// The schedule for running the task.
153        /// </summary>
154        public Schedule Schedule { get; set; }
155
156        /// <summary>
157        /// The log entries which this task has accumulated.
158        /// </summary>
159        public Logger Log { get; private set; }
160
161        #region Events
162        /// <summary>
163        /// The start of the execution of a task.
164        /// </summary>
165        public EventHandler<TaskEventArgs> TaskStarted { get; set; }
166
167        /// <summary>
168        /// The event object holding all event handlers.
169        /// </summary>
170        public EventHandler<TaskProgressEventArgs> ProgressChanged { get; set; }
171
172        /// <summary>
173        /// The completion of the execution of a task.
174        /// </summary>
175        public EventHandler<TaskEventArgs> TaskFinished { get; set; }
176
177        /// <summary>
178        /// Broadcasts the task execution start event.
179        /// </summary>
180        /// <param name="e"></param>
181        internal void OnTaskStarted(TaskEventArgs e)
182        {
183            if (TaskStarted != null)
184                TaskStarted(this, e);
185            Executing = true;
186        }
187
188        /// <summary>
189        /// Broadcasts a ProgressChanged event.
190        /// </summary>
191        /// <param name="e">The new progress value.</param>
192        internal void OnProgressChanged(TaskProgressEventArgs e)
193        {
194            if (ProgressChanged != null)
195                ProgressChanged(this, e);
196        }
197
198        /// <summary>
199        /// Broadcasts the task execution completion event.
200        /// </summary>
201        /// <param name="e"></param>
202        internal void OnTaskFinished(TaskEventArgs e)
203        {
204            if (TaskFinished != null)
205                TaskFinished(this, e);
206            Executing = false;
207        }
208        #endregion
209    }
210
211    /// <summary>
212    /// Represents a generic target of erasure
213    /// </summary>
214    [Serializable]
215    public abstract class ErasureTarget : ISerializable
216    {
217        #region Serialization code
218        protected ErasureTarget(SerializationInfo info, StreamingContext context)
219        {
220            Guid methodGuid = (Guid)info.GetValue("Method", typeof(Guid));
221            if (methodGuid == Guid.Empty)
222                method = ErasureMethodManager.Default;
223            else
224                method = ErasureMethodManager.GetInstance(methodGuid);
225        }
226
227        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
228        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
229        {
230            info.AddValue("Method", method.Guid);
231        }
232        #endregion
233
234        /// <summary>
235        /// Constructor.
236        /// </summary>
237        protected ErasureTarget()
238        {
239        }
240
241        /// <summary>
242        /// The method used for erasing the file. If the variable is equal to
243        /// ErasureMethodManager.Default then the default is queried for the
244        /// task type.
245        /// </summary>
246        public abstract ErasureMethod Method
247        {
248            get;
249            set;
250        }
251
252        /// <summary>
253        /// Checks whether a method has been selected for this target. This is
254        /// because the Method property will return non-default erasure methods
255        /// only.
256        /// </summary>
257        public bool MethodDefined
258        {
259            get
260            {
261                return method != ErasureMethodManager.Default;
262            }
263        }
264
265        /// <summary>
266        /// The task which owns this target.
267        /// </summary>
268        public Task Task { get; internal set; }
269
270        /// <summary>
271        /// Retrieves the text to display representing this task.
272        /// </summary>
273        public abstract string UIText
274        {
275            get;
276        }
277
278        /// <summary>
279        /// Retrieves the amount of data that needs to be written in order to
280        /// complete the erasure.
281        /// </summary>
282        public abstract long TotalData
283        {
284            get;
285        }
286
287        /// <summary>
288        /// Erasure method to use for the target.
289        /// </summary>
290        protected ErasureMethod method { get; set; }
291    }
292
293    /// <summary>
294    /// Class representing a tangible object (file/folder) to be erased.
295    /// </summary>
296    [Serializable]
297    public abstract class FileSystemObjectTarget : ErasureTarget
298    {
299        #region Serialization code
300        protected FileSystemObjectTarget(SerializationInfo info, StreamingContext context)
301            : base(info, context)
302        {
303            path = (string)info.GetValue("Path", typeof(string));
304        }
305
306        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
307        public override void GetObjectData(SerializationInfo info, StreamingContext context)
308        {
309            base.GetObjectData(info, context);
310            info.AddValue("Path", path);
311        }
312        #endregion
313
314        /// <summary>
315        /// Constructor.
316        /// </summary>
317        protected FileSystemObjectTarget()
318        {
319        }
320
321        /// <summary>
322        /// Retrieves the list of files/folders to erase as a list.
323        /// </summary>
324        /// <param name="totalSize">Returns the total size in bytes of the
325        /// items.</param>
326        /// <returns>A list containing the paths to all the files to be erased.</returns>
327        internal abstract List<string> GetPaths(out long totalSize);
328
329        /// <summary>
330        /// Adds ADSes of the given file to the list.
331        /// </summary>
332        /// <param name="list">The list to add the ADS paths to.</param>
333        /// <param name="file">The file to look for ADSes</param>
334        protected void GetPathADSes(ICollection<string> list, out long totalSize, string file)
335        {
336            totalSize = 0;
337
338            try
339            {
340                //Get the ADS names
341                ICollection<string> adses = Util.File.GetADSes(new FileInfo(file));
342
343                //Then prepend the path.
344                foreach (string adsName in adses)
345                {
346                    string adsPath = file + ':' + adsName;
347                    list.Add(adsPath);
348                    Util.StreamInfo info = new Util.StreamInfo(adsPath);
349                    totalSize += info.Length;
350                }
351            }
352            catch (UnauthorizedAccessException e)
353            {
354                //The system cannot read the file, assume no ADSes for lack of
355                //more information.
356                Task.Log.LastSessionEntries.Add(new LogEntry(e.Message, LogLevel.Error));
357            }
358        }
359
360        /// <summary>
361        /// The path to the file or folder referred to by this object.
362        /// </summary>
363        public string Path
364        {
365            get { return path; }
366            set { path = value; }
367        }
368
369        public override ErasureMethod Method
370        {
371            get
372            {
373                if (method != ErasureMethodManager.Default)
374                    return method;
375                return ErasureMethodManager.GetInstance(
376                    ManagerLibrary.Settings.DefaultFileErasureMethod);
377            }
378            set
379            {
380                method = value;
381            }
382        }
383
384        public override string UIText
385        {
386            get { return Path; }
387        }
388
389        public override long TotalData
390        {
391            get
392            {
393                long totalSize = 0;
394                List<string> paths = GetPaths(out totalSize);
395                return Method.CalculateEraseDataSize(paths, totalSize);
396            }
397        }
398
399        private string path;
400    }
401
402    /// <summary>
403    /// Class representing a unused space erase.
404    /// </summary>
405    [Serializable]
406    public class UnusedSpaceTarget : ErasureTarget
407    {
408        #region Serialization code
409        protected UnusedSpaceTarget(SerializationInfo info, StreamingContext context)
410            : base(info, context)
411        {
412            Drive = (string)info.GetValue("Drive", typeof(string));
413            EraseClusterTips = (bool)info.GetValue("EraseClusterTips", typeof(bool));
414        }
415
416        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
417        public override void GetObjectData(SerializationInfo info, StreamingContext context)
418        {
419            base.GetObjectData(info, context);
420            info.AddValue("Drive", Drive);
421            info.AddValue("EraseClusterTips", EraseClusterTips);
422        }
423        #endregion
424
425        /// <summary>
426        /// Constructor.
427        /// </summary>
428        public UnusedSpaceTarget()
429        {
430        }
431
432        public override ErasureMethod Method
433        {
434            get
435            {
436                if (method != ErasureMethodManager.Default)
437                    return method;
438                return ErasureMethodManager.GetInstance(
439                    ManagerLibrary.Settings.DefaultUnusedSpaceErasureMethod);
440            }
441            set
442            {
443                method = value;
444            }
445        }
446
447        public override string UIText
448        {
449            get { return S._("Unused disk space ({0})", Drive); }
450        }
451
452        public override long TotalData
453        {
454            get
455            {
456                VolumeInfo info = VolumeInfo.FromMountpoint(Drive);
457                return Method.CalculateEraseDataSize(null, info.AvailableFreeSpace);
458            }
459        }
460
461        /// <summary>
462        /// The drive to erase
463        /// </summary>
464        public string Drive { get; set; }
465
466        /// <summary>
467        /// Whether cluster tips should be erased.
468        /// </summary>
469        public bool EraseClusterTips { get; set; }
470    }
471
472    /// <summary>
473    /// Class representing a file to be erased.
474    /// </summary>
475    [Serializable]
476    public class FileTarget : FileSystemObjectTarget
477    {
478        #region Serialization code
479        protected FileTarget(SerializationInfo info, StreamingContext context)
480            : base(info, context)
481        {
482        }
483        #endregion
484
485        /// <summary>
486        /// Constructor.
487        /// </summary>
488        public FileTarget()
489        {
490        }
491
492        internal override List<string> GetPaths(out long totalSize)
493        {
494            List<string> result = new List<string>();
495            totalSize = 0;
496            GetPathADSes(result, out totalSize, Path);
497
498            totalSize += new FileInfo(Path).Length;
499            result.Add(Path);
500            return result;
501        }
502    }
503
504    /// <summary>
505    /// Represents a folder and its files which are to be erased.
506    /// </summary>
507    [Serializable]
508    public class FolderTarget : FileSystemObjectTarget
509    {
510        #region Serialization code
511        protected FolderTarget(SerializationInfo info, StreamingContext context)
512            : base(info, context)
513        {
514            includeMask = (string)info.GetValue("IncludeMask", typeof(string));
515            excludeMask = (string)info.GetValue("ExcludeMask", typeof(string));
516            deleteIfEmpty = (bool)info.GetValue("DeleteIfEmpty", typeof(bool));
517        }
518
519        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
520        public override void GetObjectData(SerializationInfo info, StreamingContext context)
521        {
522            base.GetObjectData(info, context);
523            info.AddValue("IncludeMask", includeMask);
524            info.AddValue("ExcludeMask", excludeMask);
525            info.AddValue("DeleteIfEmpty", deleteIfEmpty);
526        }
527        #endregion
528
529        /// <summary>
530        /// Constructor.
531        /// </summary>
532        public FolderTarget()
533        {
534        }
535
536        internal override List<string> GetPaths(out long totalSize)
537        {
538            //Get a list to hold all the resulting paths.
539            List<string> result = new List<string>();
540
541            //Open the root of the search, including every file matching the pattern
542            DirectoryInfo dir = new DirectoryInfo(Path);
543
544            //List recursively all the files which match the include pattern.
545            FileInfo[] files = GetFiles(dir);
546
547            //Then exclude each file and finalize the list and total file size
548            totalSize = 0;
549            if (ExcludeMask.Length != 0)
550            {
551                string regex = Regex.Escape(ExcludeMask).Replace("\\*", ".*").
552                    Replace("\\?", ".");
553                Regex excludePattern = new Regex(regex, RegexOptions.IgnoreCase);
554                foreach (FileInfo file in files)
555                    if ((file.Attributes & FileAttributes.ReparsePoint) == 0 &&
556                        excludePattern.Matches(file.FullName).Count == 0)
557                    {
558                        totalSize += file.Length;
559                        GetPathADSes(result, out totalSize, file.FullName);
560                        result.Add(file.FullName);
561                    }
562            }
563            else
564                foreach (FileInfo file in files)
565                {
566                    if ((file.Attributes & FileAttributes.ReparsePoint) != 0)
567                        continue;
568
569                    totalSize += file.Length;
570                    GetPathADSes(result, out totalSize, file.FullName);
571                    result.Add(file.FullName);
572                }
573
574            //Return the filtered list.
575            return result;
576        }
577
578        /// <summary>
579        /// Gets all files in the provided directory.
580        /// </summary>
581        /// <param name="info">The directory to look files in.</param>
582        /// <returns>A list of files found in the directory matching the IncludeMask
583        /// property.</returns>
584        private FileInfo[] GetFiles(DirectoryInfo info)
585        {
586            List<FileInfo> result = new List<FileInfo>();
587            foreach (DirectoryInfo dir in info.GetDirectories())
588                try
589                {
590                    result.AddRange(GetFiles(dir));
591                }
592                catch (Exception e)
593                {
594                    //Ignore, but log.
595                    Task.Log.LastSessionEntries.Add(new LogEntry(S._("Could not erase {0} because {1}",
596                        dir.FullName, e.Message), LogLevel.Error));
597                }
598
599            if (includeMask.Length == 0)
600                result.AddRange(info.GetFiles());
601            else
602                result.AddRange(info.GetFiles(includeMask, SearchOption.TopDirectoryOnly));
603            return result.ToArray();
604        }
605
606        /// <summary>
607        /// A wildcard expression stating the condition for the set of files to include.
608        /// The include mask is applied before the exclude mask is applied. If this value
609        /// is empty, all files and folders within the folder specified is included.
610        /// </summary>
611        public string IncludeMask
612        {
613            get { return includeMask; }
614            set { includeMask = value; }
615        }
616
617        /// <summary>
618        /// A wildcard expression stating the condition for removing files from the set
619        /// of included files. If this value is omitted, all files and folders extracted
620        /// by the inclusion mask is erased.
621        /// </summary>
622        public string ExcludeMask
623        {
624            get { return excludeMask; }
625            set { excludeMask = value; }
626        }
627
628        /// <summary>
629        /// Determines if Eraser should delete the folder after the erase process.
630        /// </summary>
631        public bool DeleteIfEmpty
632        {
633            get { return deleteIfEmpty; }
634            set { deleteIfEmpty = value; }
635        }
636
637        private string includeMask = string.Empty;
638        private string excludeMask = string.Empty;
639        private bool deleteIfEmpty = true;
640    }
641
642    [Serializable]
643    public class RecycleBinTarget : FileSystemObjectTarget
644    {
645        #region Serialization code
646        protected RecycleBinTarget(SerializationInfo info, StreamingContext context)
647            : base(info, context)
648        {
649        }
650        #endregion
651
652        public RecycleBinTarget()
653        {
654        }
655
656        internal override List<string> GetPaths(out long totalSize)
657        {
658            totalSize = 0;
659            List<string> result = new List<string>();
660            string[] rootDirectory = new string[] {
661                    "$RECYCLE.BIN",
662                    "RECYCLER"
663                };
664
665            foreach (DriveInfo drive in DriveInfo.GetDrives())
666            {
667                foreach (string rootDir in rootDirectory)
668                {
669                    DirectoryInfo dir = new DirectoryInfo(
670                        System.IO.Path.Combine(
671                            System.IO.Path.Combine(drive.Name, rootDir),
672                            System.Security.Principal.WindowsIdentity.GetCurrent().
673                                User.ToString()));
674                    if (!dir.Exists)
675                        continue;
676
677                    GetRecyclerFiles(dir, ref result, ref totalSize);
678                }
679            }
680
681            return result;
682        }
683
684        /// <summary>
685        /// Retrieves all files within this folder, without exclusions.
686        /// </summary>
687        /// <param name="info">The DirectoryInfo object representing the folder to traverse.</param>
688        /// <param name="paths">The list of files to store path information in.</param>
689        /// <param name="totalSize">Receives the total size of the files.</param>
690        private void GetRecyclerFiles(DirectoryInfo info, ref List<string> paths,
691            ref long totalSize)
692        {
693            try
694            {
695                foreach (FileSystemInfo fsInfo in info.GetFileSystemInfos())
696                {
697                    if (fsInfo is FileInfo)
698                    {
699                        paths.Add(fsInfo.FullName);
700                        totalSize += ((FileInfo)fsInfo).Length;
701                        GetPathADSes(paths, out totalSize, fsInfo.FullName);
702                    }
703                    else
704                        GetRecyclerFiles((DirectoryInfo)fsInfo, ref paths, ref totalSize);
705                }
706            }
707            catch (UnauthorizedAccessException e)
708            {
709                Task.Log.LastSessionEntries.Add(new LogEntry(e.Message, LogLevel.Error));
710            }
711        }
712
713        /// <summary>
714        /// Retrieves the text to display representing this task.
715        /// </summary>
716        public override string UIText
717        {
718            get
719            {
720                return S._("Recycle Bin");
721            }
722        }
723    }
724
725    /// <summary>
726    /// Maintains a collection of erasure targets.
727    /// </summary>
728    [Serializable]
729    public class ErasureTargetsCollection : IList<ErasureTarget>, ICollection<ErasureTarget>,
730        IEnumerable<ErasureTarget>, ISerializable
731    {
732        #region Constructors
733        internal ErasureTargetsCollection(Task owner)
734        {
735            this.list = new List<ErasureTarget>();
736            this.owner = owner;
737        }
738
739        internal ErasureTargetsCollection(Task owner, int capacity)
740            : this(owner)
741        {
742            list.Capacity = capacity;
743        }
744
745        internal ErasureTargetsCollection(Task owner, IEnumerable<ErasureTarget> targets)
746            : this(owner)
747        {
748            list.AddRange(targets);
749        }
750        #endregion
751
752        #region Serialization Code
753        protected ErasureTargetsCollection(SerializationInfo info, StreamingContext context)
754        {
755            list = (List<ErasureTarget>)info.GetValue("list", typeof(List<ErasureTarget>));
756        }
757
758        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
759        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
760        {
761            info.AddValue("list", list);
762        }
763        #endregion
764
765        #region IEnumerable<ErasureTarget> Members
766        public IEnumerator<ErasureTarget> GetEnumerator()
767        {
768            return list.GetEnumerator();
769        }
770        #endregion
771
772        #region IEnumerable Members
773        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
774        {
775            return GetEnumerator();
776        }
777        #endregion
778
779        #region ICollection<ErasureTarget> Members
780        public void Add(ErasureTarget item)
781        {
782            item.Task = owner;
783            list.Add(item);
784        }
785
786        public void Clear()
787        {
788            foreach (ErasureTarget item in list)
789                Remove(item);
790        }
791
792        public bool Contains(ErasureTarget item)
793        {
794            return list.Contains(item);
795        }
796
797        public void CopyTo(ErasureTarget[] array, int arrayIndex)
798        {
799            list.CopyTo(array, arrayIndex);
800        }
801
802        public int Count
803        {
804            get
805            {
806                return list.Count;
807            }
808        }
809
810        public bool IsReadOnly
811        {
812            get
813            {
814                return false;
815            }
816        }
817
818        public bool Remove(ErasureTarget item)
819        {
820            int index = list.IndexOf(item);
821            if (index < 0)
822                return false;
823
824            RemoveAt(index);
825            return true;
826        }
827        #endregion
828
829        #region IList<ErasureTarget> Members
830        public int IndexOf(ErasureTarget item)
831        {
832            return list.IndexOf(item);
833        }
834
835        public void Insert(int index, ErasureTarget item)
836        {
837            item.Task = owner;
838            list.Insert(index, item);
839        }
840
841        public void RemoveAt(int index)
842        {
843            list.RemoveAt(index);
844        }
845
846        public ErasureTarget this[int index]
847        {
848            get
849            {
850                return list[index];
851            }
852            set
853            {
854                list[index] = value;
855            }
856        }
857        #endregion
858
859        /// <summary>
860        /// The owner of this list of targets.
861        /// </summary>
862        public Task Owner
863        {
864            get
865            {
866                return owner;
867            }
868            internal set
869            {
870                owner = value;
871                foreach (ErasureTarget target in list)
872                    target.Task = owner;
873            }
874        }
875
876        /// <summary>
877        /// The owner of this list of targets. All targets added to this list
878        /// will have the owner set to this object.
879        /// </summary>
880        private Task owner;
881
882        /// <summary>
883        /// The list bring the data store behind this object.
884        /// </summary>
885        private List<ErasureTarget> list;
886    }
887
888    /// <summary>
889    /// A base event class for all event arguments involving a task.
890    /// </summary>
891    public class TaskEventArgs : EventArgs
892    {
893        /// <summary>
894        /// Constructor.
895        /// </summary>
896        /// <param name="task">The task being referred to by this event.</param>
897        public TaskEventArgs(Task task)
898        {
899            Task = task;
900        }
901
902        /// <summary>
903        /// The executing task.
904        /// </summary>
905        public Task Task { get; private set; }
906    }
907
908    /// <summary>
909    /// A Event argument object containing the progress of the task.
910    /// </summary>
911    public class TaskProgressEventArgs : TaskEventArgs
912    {
913        /// <summary>
914        /// Constructor.
915        /// </summary>
916        /// <param name="task">The task being run.</param>
917        public TaskProgressEventArgs(Task task)
918            : base(task)
919        {
920            CurrentItemPass = 1;
921        }
922
923        /// <summary>
924        /// A number from 0 to 1 detailing the overall progress of the task.
925        /// </summary>
926        public float OverallProgress
927        {
928            get { return overallProgress; }
929        }
930
931        /// <summary>
932        /// The amount of time left for the operation to complete, in seconds.
933        /// </summary>
934        public TimeSpan TimeLeft { get; internal set; }
935
936        /// <summary>
937        /// The current erasure target - the current item being erased.
938        /// </summary>
939        public ErasureTarget CurrentTarget { get; internal set; }
940
941        /// <summary>
942        /// The current index of the target.
943        /// </summary>
944        public int CurrentTargetIndex { get; internal set; }
945
946        /// <summary>
947        /// The total number of passes to complete before this erasure method is
948        /// completed.
949        /// </summary>
950        public int CurrentTargetTotalPasses { get; internal set; }
951
952        /// <summary>
953        /// A number from 0 to 1 detailing the overall progress of the item.
954        /// </summary>
955        public float CurrentItemProgress { get; internal set; }
956
957        /// <summary>
958        /// The file name of the item being erased.
959        /// </summary>
960        public string CurrentItemName { get; internal set; }
961
962        /// <summary>
963        /// The pass number of a multi-pass erasure method.
964        /// </summary>
965        public int CurrentItemPass { get; internal set; }
966
967        /// <summary>
968        /// The progress made by the current target.
969        /// </summary>
970        internal float CurrentTargetProgress
971        {
972            set
973            {
974                overallProgress = Math.Min(
975                    (value + (float)(CurrentTargetIndex - 1)) / Task.Targets.Count,
976                    1.0f);
977            }
978        }
979
980        private float overallProgress;
981    }
982}
Note: See TracBrowser for help on using the repository browser.