Changeset 2602


Ignore:
Timestamp:
3/30/2012 11:16:14 AM (3 years ago)
Author:
lowjoel
Message:

Make the LogSink? a base class (LogSinkBase?) and implement a normal LogSink? (API compatible with the old LogSink?) and a new LazyLogSink? class which will load a log from disk as required.
As a result of this change, Task will have two WriteXml? functions: The default will continue to generate the same code; the new overload will place references to logs if the logs are larger than a certain threshold. This is to optimize the task list for size when loading/unloading.

Location:
branches/eraser6/XmlTaskLists
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/eraser6/XmlTaskLists/Eraser.Manager/Task.cs

    r2599 r2602  
    5050            Targets = (ErasureTargetCollection)info.GetValue("Targets", typeof(ErasureTargetCollection)); 
    5151            Targets.Owner = this; 
    52             Log = (List<LogSink>)info.GetValue("Log", typeof(List<LogSink>)); 
     52            Log = (List<LogSinkBase>)info.GetValue("Log", typeof(List<LogSinkBase>)); 
    5353            Canceled = false; 
    5454 
     
    9898                        break; 
    9999 
    100                     case "ArrayOfArrayOfLogEntry": 
     100                    case "Logs": 
    101101                        ReadLog(reader); 
    102102                        break; 
     
    143143        private void ReadLog(XmlReader reader) 
    144144        { 
    145             XmlSerializer logSerializer = new XmlSerializer(Log.GetType()); 
    146             Log = (List<LogSink>)logSerializer.Deserialize(reader); 
    147         } 
    148  
    149         public void WriteXml(XmlWriter writer) 
     145            //We can either have a ArrayOfLogEntry or LogRef element as children. 
     146            Log = new List<LogSinkBase>(); 
     147            while (reader.Read() && reader.NodeType != XmlNodeType.EndElement) 
     148            { 
     149                if (reader.Name == "LogRef") 
     150                { 
     151                    Log.Add(new LazyLogSink(reader.ReadString())); 
     152                } 
     153                else if (reader.Name == "ArrayOfLogEntry") 
     154                { 
     155                    XmlSerializer logSerializer = new XmlSerializer(typeof(LogSink)); 
     156                    Log.Add((LogSink)logSerializer.Deserialize(reader)); 
     157                } 
     158            } 
     159        } 
     160 
     161        /// <summary> 
     162        /// Writes the common part of the Task XML Element. 
     163        /// </summary> 
     164        /// <param name="writer">The XML Writer instance to write to.</param> 
     165        private void WriteXmlCommon(XmlWriter writer) 
    150166        { 
    151167            writer.WriteAttributeString("name", Name); 
     
    168184            XmlSerializer targetsSerializer = new XmlSerializer(Targets.GetType()); 
    169185            targetsSerializer.Serialize(writer, Targets); 
    170  
    171             XmlSerializer logSerializer = new XmlSerializer(Log.GetType()); 
    172             logSerializer.Serialize(writer, Log); 
     186        } 
     187 
     188        public void WriteXml(XmlWriter writer) 
     189        { 
     190            WriteXmlCommon(writer); 
     191 
     192            writer.WriteStartElement("Logs"); 
     193            foreach (LogSinkBase log in Log) 
     194            { 
     195                XmlSerializer logSerializer = new XmlSerializer(log.GetType()); 
     196                logSerializer.Serialize(writer, log); 
     197            } 
     198            writer.WriteEndElement(); 
     199        } 
     200 
     201        /// <summary> 
     202        /// Writes an XML element with the Log entries linked instead of embedded 
     203        /// in the task list. 
     204        /// </summary> 
     205        /// <param name="writer">The XML Writer instance to write to.</param> 
     206        /// <param name="logPaths">The path to a folder to store logs in.</param> 
     207        public void WriteSeparatedXml(XmlWriter writer, string logPaths) 
     208        { 
     209            WriteXmlCommon(writer); 
     210 
     211            writer.WriteStartElement("Logs"); 
     212            foreach (LogSinkBase log in Log) 
     213            { 
     214                //If we have a file-backed log, retain that. 
     215                if (log is LazyLogSink) 
     216                { 
     217                    writer.WriteElementString("LogRef", ((LazyLogSink)log).SavePath); 
     218                } 
     219                 
     220                //Otherwise, decide if we want to store the log inline (if small) or 
     221                //link to the log file. 
     222                else if (log.Count < 5) 
     223                { 
     224                    //Small log, keep it inline. 
     225                    XmlSerializer logSerializer = new XmlSerializer(log.GetType()); 
     226                    logSerializer.Serialize(writer, log); 
     227                } 
     228                else 
     229                { 
     230                    string savePath; 
     231                    do 
     232                    { 
     233                        savePath = Path.Combine(logPaths, Guid.NewGuid().ToString() + ".log"); 
     234                    } 
     235                    while (File.Exists(savePath)); 
     236 
     237                    log.Save(savePath); 
     238                    writer.WriteElementString("LogRef", savePath); 
     239                } 
     240            } 
     241            writer.WriteEndElement(); 
    173242        } 
    174243        #endregion 
     
    183252            Schedule = Schedule.RunNow; 
    184253            Canceled = false; 
    185             Log = new List<LogSink>(); 
     254            Log = new List<LogSinkBase>(); 
    186255        } 
    187256 
     
    282351        /// The log entries which this task has accumulated. 
    283352        /// </summary> 
    284         public List<LogSink> Log { get; private set; } 
     353        public List<LogSinkBase> Log { get; private set; } 
    285354 
    286355        /// <summary> 
  • branches/eraser6/XmlTaskLists/Eraser.Util/Logger.cs

    r2594 r2602  
    601601    /// <remarks>Instance functions of this class are thread-safe.</remarks> 
    602602    [Serializable] 
    603     public class LogSink : ISerializable, ILogTarget, IList<LogEntry> 
    604     { 
    605         public LogSink() 
     603    public abstract class LogSinkBase : ISerializable, ILogTarget, IList<LogEntry> 
     604    { 
     605        public LogSinkBase() 
    606606        { 
    607607        } 
     
    609609        #region ISerializable Members 
    610610 
    611         public LogSink(SerializationInfo info, StreamingContext context) 
    612         { 
    613             List = (List<LogEntry>)info.GetValue("List", typeof(List<LogEntry>)); 
     611        public LogSinkBase(SerializationInfo info, StreamingContext context) 
     612        { 
    614613        } 
    615614 
    616615        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] 
    617         public void GetObjectData(SerializationInfo info, StreamingContext context) 
    618         { 
    619             info.AddValue("List", List); 
    620         } 
    621  
    622         #endregion 
     616        public abstract void GetObjectData(SerializationInfo info, StreamingContext context); 
     617 
     618        #endregion  
    623619 
    624620        #region ILoggerTarget Members 
     
    791787 
    792788        /// <summary> 
     789        /// Saves the log to the given path in an XML format which can be read 
     790        /// by <see cref="LazyLogSink"/>. 
     791        /// </summary> 
     792        /// <param name="path">The path to save the log contents to.</param> 
     793        public void Save(string path) 
     794        { 
     795            using (FileStream stream = new FileStream(path, FileMode.OpenOrCreate)) 
     796                Save(stream); 
     797        } 
     798 
     799        public void Save(Stream stream) 
     800        { 
     801            IList<LogEntry> list = List; 
     802            lock (list) 
     803            { 
     804                XmlRootAttribute root = new XmlRootAttribute("Log"); 
     805                XmlSerializer serializer = new XmlSerializer(list.GetType(), root); 
     806 
     807                serializer.Serialize(stream, list); 
     808            } 
     809        } 
     810 
     811        /// <summary> 
    793812        /// The backing store of this session. 
    794813        /// </summary> 
    795         private List<LogEntry> List = new List<LogEntry>(); 
     814        protected abstract IList<LogEntry> List 
     815        { 
     816            get; 
     817        } 
     818    } 
     819 
     820    [Serializable] 
     821    public class LogSink : LogSinkBase 
     822    { 
     823        public LogSink() 
     824        { 
     825            list = new List<LogEntry>(); 
     826        } 
     827 
     828        #region ISerializable Members 
     829 
     830        public LogSink(SerializationInfo info, StreamingContext context) 
     831            : base(info, context) 
     832        { 
     833            list = (List<LogEntry>)info.GetValue("List", typeof(List<LogEntry>)); 
     834        } 
     835 
     836        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] 
     837        public override void GetObjectData(SerializationInfo info, StreamingContext context) 
     838        { 
     839            info.AddValue("List", List); 
     840        } 
     841 
     842        #endregion  
     843 
     844        protected override IList<LogEntry> List 
     845        { 
     846            get { return list; } 
     847        } 
     848        private List<LogEntry> list; 
     849    } 
     850 
     851    [Serializable] 
     852    public class LazyLogSink : LogSinkBase 
     853    { 
     854        /// <summary> 
     855        /// Constructor. 
     856        /// </summary> 
     857        /// <param name="path">The path to the log file.</param> 
     858        public LazyLogSink(string path) 
     859        { 
     860            SavePath = path; 
     861        } 
     862 
     863        #region ISerializable Members 
     864 
     865        public LazyLogSink(SerializationInfo info, StreamingContext context) 
     866            : base(info, context) 
     867        { 
     868            SavePath = (string)info.GetValue("SavePath", typeof(string)); 
     869        } 
     870 
     871        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] 
     872        public override void GetObjectData(SerializationInfo info, StreamingContext context) 
     873        { 
     874            info.AddValue("SavePath", SavePath); 
     875        } 
     876 
     877        #endregion 
     878 
     879        private void LoadList() 
     880        { 
     881            lock (Synchronise) 
     882            { 
     883                XmlRootAttribute root = new XmlRootAttribute("Log"); 
     884                XmlSerializer serializer = new XmlSerializer(typeof(List<LogEntry>), root); 
     885 
     886                using (FileStream stream = new FileStream(SavePath, FileMode.Open)) 
     887                    list = (List<LogEntry>)serializer.Deserialize(stream); 
     888            } 
     889        } 
     890 
     891        /// <summary> 
     892        /// The path the log was saved to. 
     893        /// </summary> 
     894        public string SavePath 
     895        { 
     896            get; 
     897            private set; 
     898        } 
     899 
     900        protected override IList<LogEntry> List 
     901        { 
     902            get 
     903            { 
     904                if (list == null) 
     905                    LoadList(); 
     906                return list; 
     907            } 
     908        } 
     909 
     910        private List<LogEntry> list; 
     911 
     912        /// <summary> 
     913        /// Private object to makw sure LoadList is not called on multiple threads. 
     914        /// </summary> 
     915        private object Synchronise = new object(); 
    796916    } 
    797917} 
  • branches/eraser6/XmlTaskLists/Eraser/LogForm.cs

    r2516 r2602  
    321321 
    322322            Application.UseWaitCursor = true; 
    323             LogSink sink = Task.Log[filterSessionCombobox.SelectedIndex]; 
     323            LogSinkBase sink = Task.Log[filterSessionCombobox.SelectedIndex]; 
    324324            EntryCache.Clear(); 
    325325            SelectedEntries.Clear(); 
Note: See TracChangeset for help on using the changeset viewer.