~ubuntu-branches/ubuntu/trusty/eclipse-linuxtools/trusty

« back to all changes in this revision

Viewing changes to oprofile/org.eclipse.linuxtools.oprofile.core/src/org/eclipse/linuxtools/internal/oprofile/core/opxml/modeldata/ModelDataAdapter.java

  • Committer: Package Import Robot
  • Author(s): Jakub Adam
  • Date: 2012-06-29 12:07:30 UTC
  • Revision ID: package-import@ubuntu.com-20120629120730-bfri1xys1i71dpn6
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 * Copyright (c) 2010 Red Hat, Inc.
 
3
 * All rights reserved. This program and the accompanying materials
 
4
 * are made available under the terms of the Eclipse Public License v1.0
 
5
 * which accompanies this distribution, and is available at
 
6
 * http://www.eclipse.org/legal/epl-v10.html
 
7
 *
 
8
 * Contributors:
 
9
 *    Red Hat - initial API and implementation
 
10
 *******************************************************************************/
 
11
package org.eclipse.linuxtools.internal.oprofile.core.opxml.modeldata;
 
12
 
 
13
import java.io.IOException;
 
14
import java.io.InputStream;
 
15
import java.util.ArrayList;
 
16
import java.util.Comparator;
 
17
import java.util.HashMap;
 
18
import java.util.TreeSet;
 
19
 
 
20
import javax.xml.parsers.DocumentBuilder;
 
21
import javax.xml.parsers.DocumentBuilderFactory;
 
22
import javax.xml.parsers.ParserConfigurationException;
 
23
 
 
24
import org.eclipse.linuxtools.internal.oprofile.core.opxml.AbstractDataAdapter;
 
25
import org.eclipse.linuxtools.internal.oprofile.core.opxml.info.InfoAdapter;
 
26
import org.w3c.dom.Document;
 
27
import org.w3c.dom.Element;
 
28
import org.w3c.dom.NodeList;
 
29
import org.xml.sax.SAXException;
 
30
 
 
31
/**
 
32
 * This class takes the XML that is output from 'opreport -X --details' for
 
33
 * the current session, and uses that data to modify it into the format
 
34
 * expected by the SAX parser.
 
35
 */
 
36
public class ModelDataAdapter extends AbstractDataAdapter {
 
37
        
 
38
        public final static String ID = "id"; //$NON-NLS-1$
 
39
        public final static String IDREF = "idref"; //$NON-NLS-1$
 
40
        public final static String NAME = "name"; //$NON-NLS-1$
 
41
        public final static String COUNT = "count"; //$NON-NLS-1$
 
42
        public final static String SAMPLE = "sample"; //$NON-NLS-1$
 
43
        public final static String LINE = "line"; //$NON-NLS-1$
 
44
        
 
45
        public final static String SYMBOL_DATA = "symboldata"; //$NON-NLS-1$
 
46
        public final static String SYMBOL_DETAILS = "symboldetails"; //$NON-NLS-1$
 
47
        public final static String SYMBOL = "symbol"; //$NON-NLS-1$
 
48
        
 
49
        public final static String FILE = "file"; //$NON-NLS-1$
 
50
        
 
51
        public final static String SETUP = "setup"; //$NON-NLS-1$
 
52
        public final static String EVENT_SETUP = "eventsetup"; //$NON-NLS-1$
 
53
        public final static String TIMER_SETUP = "timersetup"; //$NON-NLS-1$
 
54
        public final static String SETUP_COUNT = "setupcount"; //$NON-NLS-1$
 
55
        public final static String EVENT_NAME = "eventname"; //$NON-NLS-1$
 
56
        public final static String RTC_INTERRUPTS = "rtcinterrupts"; //$NON-NLS-1$
 
57
        
 
58
        public final static String PROFILE = "profile"; //$NON-NLS-1$
 
59
        public final static String MODEL_DATA = "model-data"; //$NON-NLS-1$
 
60
        
 
61
        public final static String MODULE = "module"; //$NON-NLS-1$
 
62
        public final static String DEPENDENT = "dependent"; //$NON-NLS-1$
 
63
        
 
64
        public final static String BINARY = "binary"; //$NON-NLS-1$
 
65
        public final static String IMAGE = "image"; //$NON-NLS-1$
 
66
        
 
67
        public final static String SYMBOLS = "symbols"; //$NON-NLS-1$
 
68
        public final static String SYMBOL_TABLE = "symboltable"; //$NON-NLS-1$
 
69
        public final static String DETAIL_TABLE = "detailtable"; //$NON-NLS-1$
 
70
        
 
71
        public final static String DETAIL_DATA = "detaildata"; //$NON-NLS-1$
 
72
        
 
73
        private boolean isParseable;
 
74
        private Document newDoc; // the document we intend to build
 
75
        private Element oldRoot; // the root of the document with data from opreport
 
76
        private Element newRoot; // the root of the document we intent to build
 
77
        
 
78
        public ModelDataAdapter(InputStream is) {
 
79
                isParseable = true;
 
80
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 
81
                DocumentBuilder builder;
 
82
                try {
 
83
                        builder = factory.newDocumentBuilder();
 
84
                        try {
 
85
                                Document oldDoc = builder.parse(is);
 
86
                                Element elem = (Element) oldDoc.getElementsByTagName(PROFILE).item(0);
 
87
                                oldRoot = elem;
 
88
                                
 
89
                                newDoc = builder.newDocument();
 
90
                                newRoot = newDoc.createElement(MODEL_DATA);
 
91
                                newDoc.appendChild(newRoot);
 
92
                        } catch (IOException e) {
 
93
                                isParseable = false;
 
94
                        } catch (SAXException e) {
 
95
                                isParseable = false;
 
96
                        }
 
97
                } catch (ParserConfigurationException e1) {
 
98
                        e1.printStackTrace();
 
99
                }
 
100
        }
 
101
        
 
102
        @Override
 
103
        public void process (){
 
104
                createXML();
 
105
        }
 
106
 
 
107
        private void createXML() {
 
108
                
 
109
                // get the binary name and the image count
 
110
                Element oldImage = (Element) oldRoot.getElementsByTagName(BINARY).item(0);
 
111
                Element newImage = newDoc.createElement(IMAGE);
 
112
                
 
113
                String binName = oldImage.getAttribute(NAME);
 
114
                newImage.setAttribute(NAME, binName);
 
115
                
 
116
                Element countTag = (Element) oldImage.getElementsByTagName(COUNT).item(0);
 
117
                String imageCount = countTag.getTextContent().trim();
 
118
                newImage.setAttribute(COUNT, imageCount);
 
119
                
 
120
                // There is no setup count in timer mode
 
121
                if (!InfoAdapter.hasTimerSupport()){
 
122
                        // get the count that was used to profile
 
123
                        Element setupTag = (Element) oldRoot.getElementsByTagName(SETUP).item(0);
 
124
                        Element eventSetupTag = (Element) setupTag.getElementsByTagName(EVENT_SETUP).item(0);
 
125
                        String setupcount = eventSetupTag.getAttribute(SETUP_COUNT);
 
126
                        newImage.setAttribute(SETUP_COUNT, setupcount);
 
127
                }
 
128
                
 
129
                // these elements contain the data needed to populate the new symbol table
 
130
                Element oldSymbolTableTag = (Element) oldRoot.getElementsByTagName(SYMBOL_TABLE).item(0);
 
131
                NodeList oldSymbolDataList = oldSymbolTableTag.getElementsByTagName(SYMBOL_DATA);
 
132
                
 
133
                Element oldDetailTableTag = (Element) oldRoot.getElementsByTagName(DETAIL_TABLE).item(0);
 
134
                NodeList oldDetailTableList = oldDetailTableTag.getElementsByTagName(SYMBOL_DETAILS);
 
135
                
 
136
                // parse the data into HashMaps for O(1) lookup time, as opposed to O(n).
 
137
                HashMap<String, HashMap<String, String>> oldSymbolDataListMap = parseDataList (oldSymbolDataList);
 
138
                HashMap<String, NodeList> oldDetailTableListMap = parseDetailTable (oldDetailTableList);
 
139
                
 
140
                // An ArrayList to hold the binary and other modules
 
141
                ArrayList<Element> oldImageList = new ArrayList<Element>();
 
142
                // The first element is the original binary!
 
143
                oldImageList.add(oldImage); 
 
144
                
 
145
                NodeList oldModuleList = oldImage.getElementsByTagName(MODULE);
 
146
                // Set up the dependent tag for any modules run by this binary
 
147
                Element dependentTag = newDoc.createElement(DEPENDENT);
 
148
                if (oldModuleList.getLength() > 0){
 
149
                        dependentTag.setAttribute(COUNT, "0"); //$NON-NLS-1$
 
150
                        
 
151
                        for (int t = 0; t < oldModuleList.getLength(); t++){
 
152
                                oldImageList.add((Element)oldModuleList.item(t));
 
153
                        }
 
154
                }
 
155
                
 
156
                // iterate through all (binary/modules)
 
157
                for (Element oldImg : oldImageList) {
 
158
                        Element newImg;
 
159
                        if (oldImg.getTagName().equals(BINARY)){
 
160
                                newImg = newImage;
 
161
                        }else{
 
162
                                newImg = newDoc.createElement(IMAGE);
 
163
                                
 
164
                                String imgName = oldImg.getAttribute(NAME);
 
165
                                newImg.setAttribute(NAME, imgName);
 
166
                                
 
167
                                Element modCountTag = (Element) oldImg.getElementsByTagName(COUNT).item(0);
 
168
                                String imgCount = modCountTag.getTextContent().trim();
 
169
                                newImg.setAttribute(COUNT, imgCount);
 
170
                        }
 
171
 
 
172
                        Element newSymbolsTag = newDoc.createElement(SYMBOLS);
 
173
 
 
174
                        // these elements contain the data needed to populate the new symbol table
 
175
                        NodeList oldSymbolList = oldImg.getElementsByTagName(SYMBOL);
 
176
 
 
177
                        // iterate through all symbols
 
178
                        for (int i = 0; i < oldSymbolList.getLength(); i++) {
 
179
                                Element oldSymbol = (Element) oldSymbolList.item(i);
 
180
                                
 
181
                                /**
 
182
                                 * The original binary is a parent for all symbols
 
183
                                 * We only want library function calls under their respective
 
184
                                 * modules, and not under the original binary as well.
 
185
                                 */
 
186
                                if (!oldSymbol.getParentNode().isSameNode(oldImg)){
 
187
                                        continue;
 
188
                                }
 
189
                                
 
190
                                Element newSymbol = newDoc.createElement(SYMBOL);
 
191
                                String idref = oldSymbol.getAttribute(IDREF);
 
192
                                String symbolCount = ((Element) oldSymbol.getElementsByTagName(COUNT).item(0)).getTextContent().trim();
 
193
                                newSymbol.setAttribute(COUNT, symbolCount);
 
194
 
 
195
                                // get the symboltable entry corresponding to the id of this symbol
 
196
                                HashMap<String, String> symbolData = oldSymbolDataListMap.get(idref);
 
197
                                newSymbol.setAttribute(NAME, symbolData.get(NAME));
 
198
                                newSymbol.setAttribute(FILE, symbolData.get(FILE));
 
199
                                newSymbol.setAttribute(LINE, symbolData.get(LINE));
 
200
 
 
201
                                // get the symboldetails entry corresponding to the id of this symbol
 
202
                                NodeList detailDataList = oldDetailTableListMap.get(idref);
 
203
 
 
204
                                // go through the detail data of each symbol's details
 
205
                                HashMap<String, Element> tmp = new HashMap<String, Element>();
 
206
                                // temporary place to store the elements for sorting
 
207
                                TreeSet<Element> sorted = new TreeSet<Element>(SAMPLE_COUNT_ORDER);
 
208
                                for (int l = 0; l < detailDataList.getLength(); l++) {
 
209
 
 
210
                                        Element detailData = (Element) detailDataList.item(l);
 
211
                                        String sampleFile = detailData.getAttribute(FILE);
 
212
                                        String sampleLine = detailData.getAttribute(LINE);
 
213
 
 
214
                                        // The sample has a line number but no file
 
215
                                        // This means that the file is the same as the symbol (parent)
 
216
                                        if (sampleFile.equals("") && !sampleLine.equals("")){ //$NON-NLS-1$ $NON-NLS-2$
 
217
                                                sampleFile = symbolData.get(FILE);
 
218
                                        }else{
 
219
                                                if (sampleFile.equals("")){ //$NON-NLS-1$
 
220
                                                        sampleFile = "??"; //$NON-NLS-1$
 
221
                                                }
 
222
                                                if (sampleLine.equals("")){ //$NON-NLS-1$
 
223
                                                        sampleLine = "0"; //$NON-NLS-1$
 
224
                                                }
 
225
                                        }
 
226
                                        Element detailDataCount = (Element) detailData.getElementsByTagName(COUNT).item(0);
 
227
                                        String count = detailDataCount.getTextContent().trim();
 
228
 
 
229
                                        // if a sample at this line already exists then increase count for that line.
 
230
                                        if (tmp.containsKey(sampleLine)) {
 
231
                                                Element elem = (Element) tmp.get(sampleLine).getElementsByTagName(COUNT).item(0);
 
232
                                                int val = Integer.parseInt(elem.getTextContent().trim()) + Integer.parseInt(count);
 
233
                                                elem.setTextContent(String.valueOf(val));
 
234
                                        } else {
 
235
                                                Element sampleTag = newDoc.createElement(SAMPLE);
 
236
 
 
237
                                                Element fileTag = newDoc.createElement(FILE);
 
238
                                                fileTag.setTextContent(sampleFile);
 
239
 
 
240
                                                Element lineTag = newDoc.createElement(LINE);
 
241
                                                lineTag.setTextContent(sampleLine);
 
242
 
 
243
                                                Element sampleCountTag = newDoc.createElement(COUNT);
 
244
                                                sampleCountTag.setTextContent(count);
 
245
 
 
246
                                                sampleTag.appendChild(fileTag);
 
247
                                                sampleTag.appendChild(lineTag);
 
248
                                                sampleTag.appendChild(sampleCountTag);
 
249
 
 
250
                                                tmp.put(sampleLine, sampleTag);
 
251
                                        }
 
252
                                }
 
253
 
 
254
                                // add the elements to the sorter
 
255
                                for (Element elem : tmp.values()) {
 
256
                                        sorted.add(elem);
 
257
                                }
 
258
 
 
259
                                // append the elements in sorted order
 
260
                                for (Element e : sorted) {
 
261
                                        newSymbol.appendChild(e);
 
262
                                }
 
263
 
 
264
                                newSymbolsTag.appendChild(newSymbol);
 
265
                        }
 
266
                        
 
267
                        newImg.appendChild(newSymbolsTag);
 
268
                        // If this is a module, attach it to the dependent tag
 
269
                        if (oldImg.getTagName().equals(MODULE)){
 
270
                                dependentTag.appendChild(newImg);
 
271
                                int currVal =  Integer.parseInt(dependentTag.getAttribute(COUNT));
 
272
                                int val =  Integer.parseInt(newImg.getAttribute(COUNT));
 
273
                                dependentTag.setAttribute(COUNT, String.valueOf(currVal + val));
 
274
                        }else{
 
275
                                newRoot.appendChild(newImg);
 
276
                        }
 
277
                }
 
278
                
 
279
                if (oldModuleList.getLength() > 0){
 
280
                        newImage.appendChild(dependentTag);
 
281
                }
 
282
        
 
283
        }
 
284
 
 
285
        /**
 
286
         * 
 
287
         * @param oldDetailTableList the list of 'symboldetails' tags within detailtable
 
288
         * @return a HashMap where the key is a function id and the value is a NodeList
 
289
         * containing a list of the 'detaildata' tags that contain sample information.
 
290
         */
 
291
        private HashMap<String, NodeList> parseDetailTable(NodeList oldDetailTableList) {
 
292
                HashMap<String, NodeList> ret = new HashMap<String, NodeList> ();
 
293
                for (int i = 0; i < oldDetailTableList.getLength(); i++){
 
294
                        Element symbolDetails = (Element) oldDetailTableList.item(i);
 
295
                        String id = symbolDetails.getAttribute(ID);
 
296
                        NodeList detailDataList = symbolDetails.getElementsByTagName(DETAIL_DATA);
 
297
                        ret.put(id, detailDataList);
 
298
                }
 
299
                return ret;
 
300
        }
 
301
 
 
302
        /**
 
303
         * 
 
304
         * @param oldSymbolDataList the list of 'symboldata' tags within symboltable
 
305
         * @return a Hashmap where the key is a function id and the value is a HashMap
 
306
         * with various parameters of data
 
307
         */
 
308
        private HashMap<String, HashMap<String, String>> parseDataList(NodeList oldSymbolDataList) {
 
309
                HashMap<String, HashMap<String,String>> ret = new HashMap<String, HashMap<String, String>> ();
 
310
                for (int j = 0; j < oldSymbolDataList.getLength(); j++){
 
311
                        HashMap<String,String> tmp = new HashMap<String,String> ();
 
312
                        Element symbolData = (Element) oldSymbolDataList.item(j);
 
313
                        String id = symbolData.getAttribute(ID);
 
314
                        String name = symbolData.getAttribute(NAME);
 
315
                        String file = symbolData.getAttribute(FILE);
 
316
                        if (file.equals("")){ //$NON-NLS-1$
 
317
                                file = "??"; //$NON-NLS-1$
 
318
                        }
 
319
                        String line = symbolData.getAttribute(LINE);
 
320
                        if (line.equals("")){ //$NON-NLS-1$
 
321
                                line = "0"; //$NON-NLS-1$
 
322
                        }
 
323
                        tmp.put(NAME, name);
 
324
                        tmp.put(FILE, file);
 
325
                        tmp.put(LINE, line);
 
326
                        ret.put(id, tmp);
 
327
                }
 
328
                return ret;
 
329
        }
 
330
 
 
331
        @Override
 
332
        public Document getDocument() {
 
333
                return newDoc;
 
334
        }
 
335
        
 
336
        /**
 
337
         * Helper class to sort the samples of a given symbol in descending order from largest
 
338
         * to smallest
 
339
         */
 
340
        public static final Comparator<Element> SAMPLE_COUNT_ORDER = new Comparator<Element>()
 
341
    {
 
342
                public int compare(Element a, Element b) {
 
343
                        // sort from largest to smallest count in descending order
 
344
                        // items with the same count are sorted by line number from smallest
 
345
                        // to largest in descending order
 
346
                        Element a_countTag = (Element) a.getElementsByTagName(COUNT).item(0);
 
347
                        Element b_countTag = (Element) b.getElementsByTagName(COUNT).item(0);
 
348
                        Element a_LineTag = (Element) a.getElementsByTagName(LINE).item(0);
 
349
                        Element b_LineTag = (Element) b.getElementsByTagName(LINE).item(0);
 
350
                        
 
351
                        Integer a_count = Integer.parseInt(a_countTag.getTextContent().trim());
 
352
                        Integer b_count = Integer.parseInt(b_countTag.getTextContent().trim());
 
353
                        Integer a_line = Integer.parseInt(a_LineTag.getTextContent().trim());
 
354
                        Integer b_line = Integer.parseInt(b_LineTag.getTextContent().trim());
 
355
                        
 
356
                        if (a_count.compareTo(b_count) == 0){
 
357
                                return a_line.compareTo(b_line);
 
358
                        }
 
359
                        return -a_count.compareTo(b_count);
 
360
                }
 
361
    };
 
362
 
 
363
        public boolean isParseable() {
 
364
                return isParseable;
 
365
        }
 
366
        
 
367
}