|
1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * |
|
5 * Redistribution and use in source and binary forms, with or without |
|
6 * modification, are permitted provided that the following conditions are met: |
|
7 * |
|
8 * - Redistributions of source code must retain the above copyright notice, |
|
9 * this list of conditions and the following disclaimer. |
|
10 * - Redistributions in binary form must reproduce the above copyright notice, |
|
11 * this list of conditions and the following disclaimer in the documentation |
|
12 * and/or other materials provided with the distribution. |
|
13 * - Neither the name of Nokia Corporation nor the names of its contributors |
|
14 * may be used to endorse or promote products derived from this software |
|
15 * without specific prior written permission. |
|
16 * |
|
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 * POSSIBILITY OF SUCH DAMAGE. |
|
28 * |
|
29 * Initial Contributors: |
|
30 * Nokia Corporation - initial contribution. |
|
31 * |
|
32 * Contributors: |
|
33 * |
|
34 * Description: |
|
35 * |
|
36 */ |
|
37 |
|
38 using System; |
|
39 using System.Collections.Generic; |
|
40 using System.Text; |
|
41 using System.Text.RegularExpressions; |
|
42 using SymbianUtils; |
|
43 using HeapLib.Reconstructor.Misc; |
|
44 using HeapLib.Reconstructor.DataSources.Analyser.Readers; |
|
45 using HeapLib.Reconstructor.DataSources.Analyser.Extractor; |
|
46 using HeapLib.Reconstructor.DataSources.Analyser.Interpreter; |
|
47 |
|
48 namespace HeapLib.Reconstructor.DataSources.Analyser |
|
49 { |
|
50 public class DataSourceAnalyser |
|
51 { |
|
52 #region Events |
|
53 public enum TEvent |
|
54 { |
|
55 EReadingStarted = 0, |
|
56 EReadingProgress, |
|
57 EReadingComplete |
|
58 } |
|
59 |
|
60 public delegate void Observer( TEvent aEvent, DataSourceAnalyser aSender ); |
|
61 public event Observer iObserver; |
|
62 |
|
63 public delegate void ExceptionHandler( Exception aException, DataSourceAnalyser aSender ); |
|
64 public event ExceptionHandler iExceptionHandler; |
|
65 #endregion |
|
66 |
|
67 #region Constructors & destructor |
|
68 public DataSourceAnalyser( string[] aLines ) |
|
69 { |
|
70 iReader = new ReaderLines( this, aLines ); |
|
71 iReader.iObserver += new AsyncReaderBase.Observer( Reader_Observer ); |
|
72 iReader.iExceptionHandler += new AsyncReaderBase.ExceptionHandler( Reader_ExceptionHandler ); |
|
73 } |
|
74 |
|
75 public DataSourceAnalyser( string aFileName ) |
|
76 { |
|
77 iReader = new ReaderFile( this, aFileName ); |
|
78 iReader.iObserver += new AsyncReaderBase.Observer( Reader_Observer ); |
|
79 iReader.iExceptionHandler += new AsyncReaderBase.ExceptionHandler( Reader_ExceptionHandler ); |
|
80 } |
|
81 #endregion |
|
82 |
|
83 #region API |
|
84 public void Analyse() |
|
85 { |
|
86 if ( iReader is ReaderFile ) |
|
87 { |
|
88 ReaderFile reader = (ReaderFile) iReader; |
|
89 reader.StartRead(); |
|
90 } |
|
91 else if ( iReader is ReaderLines ) |
|
92 { |
|
93 ReaderLines reader = (ReaderLines) iReader; |
|
94 reader.StartRead(); |
|
95 } |
|
96 } |
|
97 #endregion |
|
98 |
|
99 #region Properties |
|
100 public bool IsReady |
|
101 { |
|
102 get { return iReader.IsReady; } |
|
103 } |
|
104 |
|
105 public int Progress |
|
106 { |
|
107 get { return iReader.Progress; } |
|
108 } |
|
109 |
|
110 public DataSourceCollection DataSources |
|
111 { |
|
112 get { return iDataSources; } |
|
113 } |
|
114 #endregion |
|
115 |
|
116 #region Reader call back method |
|
117 internal void HandleFilteredLine( string aLine, long aLineNumber ) |
|
118 { |
|
119 // The four types of data we allow. |
|
120 // |
|
121 // 1) Text data from a trace file |
|
122 // [15:21:32.719] xti2:MCU_ASCII_PRINTF; channel:0xE0; msg:HeapData - EComServer::!ecomserver - HEAP INFO FOR THREAD 'EComServer::!ecomserver' |
|
123 // |
|
124 // 2) Text data from a MemSpy heap dump file |
|
125 // HEAP INFO FOR THREAD 'ecomserver::!ecomserver' |
|
126 // |
|
127 // 3) Binary data from a trace file: |
|
128 // [14:39:24.344] xti2:MCU_ASCII_PRINTF; channel:0xE0; msg:[BinHeap:00000131]<BinHeapData:00000131:00000130:000000000001346e> |
|
129 // [14:39:24.344] xti2:MCU_ASCII_PRINTF; channel:0xE0; msg:[BinHeap:00000131]00000000: be d0 be d0 ba da ba da 00 00 00 d0 01 00 00 00 ................ |
|
130 // [14:39:24.344] xti2:MCU_ASCII_PRINTF; channel:0xE0; msg:[BinHeap:00000131]00000010: 6e 34 01 00 82 00 00 00 83 00 00 00 01 00 00 00 n4.............. |
|
131 // |
|
132 // 4) Binary data from a MemSpy heap dump file |
|
133 // <BinHeapData:00000114:00000113:0000000000001234> |
|
134 // 000ae8cc: 00 00 00 00 00 00 00 00 9d 2a 17 00 24 00 00 00 |
|
135 |
|
136 // First, try running the line past any existing extractors |
|
137 bool handled = false; |
|
138 foreach ( Extractor.Extractor ext in iActiveExtractors ) |
|
139 { |
|
140 if ( ext.ExtractFrom( aLine, false ) ) |
|
141 { |
|
142 handled = true; |
|
143 break; |
|
144 } |
|
145 } |
|
146 // |
|
147 if ( !handled ) |
|
148 { |
|
149 // Try to create a new extractor that can handle this type of line |
|
150 Extractor.Extractor extractor = iExtractorFactory.FindSuitableExtractor( aLine ); |
|
151 if ( extractor != null ) |
|
152 { |
|
153 InterpreterBase interpreter = iInterpreterFactory.FindSuitableInterpreter( extractor ); |
|
154 |
|
155 if ( interpreter != null ) |
|
156 { |
|
157 // Link up extractor and interpreter with a new data source |
|
158 string dataSourceFileName = GetSourceFileName(); |
|
159 DataSource dataSource = new DataSource( dataSourceFileName, aLineNumber ); |
|
160 interpreter.DataSource = dataSource; |
|
161 extractor.Interpreter = interpreter; |
|
162 |
|
163 // We should also initialise the interpreter now that we've |
|
164 // prepared the data source |
|
165 interpreter.PrepareToStart( extractor ); |
|
166 |
|
167 // We must fire the extractor |
|
168 extractor.ExtractFrom( aLine, true ); |
|
169 |
|
170 // Save the extractor so that we can ask it to handle future lines |
|
171 AddExtractor( extractor ); |
|
172 |
|
173 // Save the data source |
|
174 iDataSources.Add( dataSource ); |
|
175 } |
|
176 } |
|
177 } |
|
178 } |
|
179 #endregion |
|
180 |
|
181 #region Internal methods |
|
182 private void ReadingComplete() |
|
183 { |
|
184 RemoveEmptySources(); |
|
185 |
|
186 // Check if the sources that are left were all completed, and if not |
|
187 // update their error flags. |
|
188 foreach ( DataSource source in iDataSources ) |
|
189 { |
|
190 Elements.MetaData metaData = source.MetaData; |
|
191 if ( metaData.IsDataComplete == false ) |
|
192 { |
|
193 source.AddError( DataSource.TErrorTypes.EErrorTypeDataMissing ); |
|
194 } |
|
195 } |
|
196 } |
|
197 |
|
198 private string GetSourceFileName() |
|
199 { |
|
200 string fileName = "RawHeapData.txt"; |
|
201 if ( iReader is ReaderFile ) |
|
202 { |
|
203 fileName = ( (ReaderFile) iReader ).FileName; |
|
204 } |
|
205 return fileName; |
|
206 } |
|
207 |
|
208 private void RemoveEmptySources() |
|
209 { |
|
210 iDataSources.RemoveEmptySources(); |
|
211 } |
|
212 |
|
213 private void AddExtractor( Extractor.Extractor aExtractor ) |
|
214 { |
|
215 // Check whether we already have an extractor for this thread. |
|
216 string threadName = aExtractor.Interpreter.DataSource.ThreadName; |
|
217 |
|
218 // If an entry with the same thread name already exists, then we |
|
219 // remove it, and replace it with a new entry |
|
220 Extractor.Extractor existingEntry = ExtractorByThread( threadName ); |
|
221 if ( existingEntry != null ) |
|
222 { |
|
223 iActiveExtractors.Remove( existingEntry ); |
|
224 } |
|
225 |
|
226 // Save new extractor for the thread |
|
227 iActiveExtractors.Add( aExtractor ); |
|
228 } |
|
229 |
|
230 private Extractor.Extractor ExtractorByThread( string aName ) |
|
231 { |
|
232 Predicate<Extractor.Extractor> findByNamePredicate = delegate( Extractor.Extractor aExtractor ) |
|
233 { |
|
234 string entryName = aExtractor.Interpreter.DataSource.ThreadName; |
|
235 return ( entryName == aName ); |
|
236 }; |
|
237 |
|
238 Extractor.Extractor ret = iActiveExtractors.Find( findByNamePredicate ); |
|
239 return ret; |
|
240 } |
|
241 #endregion |
|
242 |
|
243 #region From AsyncReaderBase |
|
244 void Reader_ExceptionHandler( Exception aException, AsyncReaderBase aSender ) |
|
245 { |
|
246 if ( iExceptionHandler != null ) |
|
247 { |
|
248 iExceptionHandler( aException, this ); |
|
249 } |
|
250 } |
|
251 |
|
252 void Reader_Observer( AsyncReaderBase.TEvent aEvent, AsyncReaderBase aSender ) |
|
253 { |
|
254 if ( iObserver != null ) |
|
255 { |
|
256 switch ( aEvent ) |
|
257 { |
|
258 case AsyncReaderBase.TEvent.EReadingStarted: |
|
259 iObserver( TEvent.EReadingStarted, this ); |
|
260 break; |
|
261 case AsyncReaderBase.TEvent.EReadingProgress: |
|
262 iObserver( TEvent.EReadingProgress, this ); |
|
263 break; |
|
264 case AsyncReaderBase.TEvent.EReadingComplete: |
|
265 ReadingComplete(); |
|
266 iObserver( TEvent.EReadingComplete, this ); |
|
267 break; |
|
268 default: |
|
269 break; |
|
270 } |
|
271 } |
|
272 } |
|
273 #endregion |
|
274 |
|
275 #region Data members |
|
276 private readonly AsyncTextReader iReader; |
|
277 private DataSourceCollection iDataSources = new DataSourceCollection(); |
|
278 private ExtractorFactory iExtractorFactory = new ExtractorFactory(); |
|
279 private InterpreterFactory iInterpreterFactory = new InterpreterFactory(); |
|
280 private List<Extractor.Extractor> iActiveExtractors = new List<HeapLib.Reconstructor.DataSources.Analyser.Extractor.Extractor>(); |
|
281 #endregion |
|
282 } |
|
283 } |