blob: bc2af425708f772c41a18a39181292d2ec8138d8 [file] [log] [blame]
Zack Rusin20b1f6d2011-09-06 11:50:07 -04001#include "traceloader.h"
2
Zack Rusin3176ebe2011-09-06 21:11:36 -04003#include "apitrace.h"
Zack Rusin20b1f6d2011-09-06 11:50:07 -04004#include <QDebug>
5#include <QFile>
6
7#define FRAMES_TO_CACHE 100
8
9static ApiTraceCall *
José Fonsecab4a3d142011-10-27 07:43:19 +010010apiCallFromTraceCall(const trace::Call *call,
Zack Rusin20b1f6d2011-09-06 11:50:07 -040011 const QHash<QString, QUrl> &helpHash,
Zack Rusinebf971e2011-09-06 17:44:43 -040012 ApiTraceFrame *frame,
Zack Rusind9d9d222013-10-11 18:02:26 -040013 ApiTraceCall *parentCall,
Zack Rusinebf971e2011-09-06 17:44:43 -040014 TraceLoader *loader)
Zack Rusin20b1f6d2011-09-06 11:50:07 -040015{
Zack Rusind9d9d222013-10-11 18:02:26 -040016 ApiTraceCall *apiCall;
17
18 if (parentCall)
19 apiCall = new ApiTraceCall(parentCall, loader, call);
20 else
21 apiCall = new ApiTraceCall(frame, loader, call);
Zack Rusin20b1f6d2011-09-06 11:50:07 -040022
23 apiCall->setHelpUrl(helpHash.value(apiCall->name()));
24
25 return apiCall;
26}
27
Zack Rusinebf971e2011-09-06 17:44:43 -040028TraceLoader::TraceLoader(QObject *parent)
José Fonseca5cd8d992012-03-25 23:12:20 +010029 : QObject(parent)
Zack Rusin20b1f6d2011-09-06 11:50:07 -040030{
31}
32
33TraceLoader::~TraceLoader()
34{
35 m_parser.close();
Zack Rusin081e59d2011-09-21 00:25:03 -040036 qDeleteAll(m_signatures);
Zack Rusin20b1f6d2011-09-06 11:50:07 -040037}
38
39void TraceLoader::loadTrace(const QString &filename)
40{
41 if (m_helpHash.isEmpty()) {
42 loadHelpFile();
43 }
44
Zack Rusindaf82af2011-09-24 13:42:53 -040045 if (!m_frameBookmarks.isEmpty()) {
46 qDeleteAll(m_signatures);
Zack Rusindaf82af2011-09-24 13:42:53 -040047 m_signatures.clear();
Zack Rusindaf82af2011-09-24 13:42:53 -040048 m_frameBookmarks.clear();
49 m_createdFrames.clear();
50 m_parser.close();
51 }
52
Zack Rusin20b1f6d2011-09-06 11:50:07 -040053 if (!m_parser.open(filename.toLatin1())) {
54 qDebug() << "error: failed to open " << filename;
55 return;
56 }
Zack Rusin59b79552011-09-21 00:37:03 -040057
Jose Fonseca8f0846c2015-11-10 19:53:55 +000058 if (!m_parser.supportsOffsets()) {
59 emit parseProblem(
60 "This trace in compressed in a format that does not allow random seeking.\n"
61 "Please repack the trace with `apitrace repack`."
62 );
63 m_parser.close();
64 return;
65 }
66
Zack Rusin20b1f6d2011-09-06 11:50:07 -040067 emit startedParsing();
68
69 if (m_parser.supportsOffsets()) {
Zack Rusinac92a212011-09-06 18:25:34 -040070 scanTrace();
Zack Rusin20b1f6d2011-09-06 11:50:07 -040071 } else {
Zack Rusinac92a212011-09-06 18:25:34 -040072 //Load the entire file into memory
73 parseTrace();
Zack Rusin20b1f6d2011-09-06 11:50:07 -040074 }
José Fonseca67964382012-03-27 23:54:30 +010075 emit guessedApi(static_cast<int>(m_parser.api));
Zack Rusin20b1f6d2011-09-06 11:50:07 -040076 emit finishedParsing();
77}
78
Zack Rusin3176ebe2011-09-06 21:11:36 -040079void TraceLoader::loadFrame(ApiTraceFrame *currentFrame)
Zack Rusin20b1f6d2011-09-06 11:50:07 -040080{
Zack Rusin8f98c3a2011-09-11 18:21:29 -040081 fetchFrameContents(currentFrame);
Zack Rusin20b1f6d2011-09-06 11:50:07 -040082}
83
Zack Rusin20b1f6d2011-09-06 11:50:07 -040084int TraceLoader::numberOfFrames() const
85{
José Fonseca61e61f72011-09-11 16:53:34 +010086 return m_frameBookmarks.size();
Zack Rusin20b1f6d2011-09-06 11:50:07 -040087}
88
89int TraceLoader::numberOfCallsInFrame(int frameIdx) const
90{
José Fonseca6bfa32f2012-03-22 16:26:47 +000091 if (frameIdx >= m_frameBookmarks.size()) {
Zack Rusin20b1f6d2011-09-06 11:50:07 -040092 return 0;
93 }
José Fonseca61e61f72011-09-11 16:53:34 +010094 FrameBookmarks::const_iterator itr =
95 m_frameBookmarks.find(frameIdx);
Zack Rusin20b1f6d2011-09-06 11:50:07 -040096 return itr->numberOfCalls;
97}
98
99void TraceLoader::loadHelpFile()
100{
Zack Rusinac92a212011-09-06 18:25:34 -0400101 QFile file(":/resources/glreference.tsv");
102 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
103 QString line;
104 while (!file.atEnd()) {
105 line = file.readLine();
106 QString function = line.section('\t', 0, 0).trimmed();
107 QUrl url = QUrl(line.section('\t', 1, 1).trimmed());
108 //qDebug()<<"function = "<<function<<", url = "<<url.toString();
109 m_helpHash.insert(function, url);
110 }
111 } else {
112 qWarning() << "Couldn't open reference file "
113 << file.fileName();
114 }
115 file.close();
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400116}
117
118void TraceLoader::scanTrace()
119{
Zack Rusinac92a212011-09-06 18:25:34 -0400120 QList<ApiTraceFrame*> frames;
121 ApiTraceFrame *currentFrame = 0;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400122
José Fonsecab4a3d142011-10-27 07:43:19 +0100123 trace::Call *call;
124 trace::ParseBookmark startBookmark;
Zack Rusinac92a212011-09-06 18:25:34 -0400125 int numOfFrames = 0;
126 int numOfCalls = 0;
Zack Rusinac92a212011-09-06 18:25:34 -0400127 int lastPercentReport = 0;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400128
José Fonseca61e61f72011-09-11 16:53:34 +0100129 m_parser.getBookmark(startBookmark);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400130
Zack Rusinac92a212011-09-06 18:25:34 -0400131 while ((call = m_parser.scan_call())) {
132 ++numOfCalls;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400133
José Fonseca5cd8d992012-03-25 23:12:20 +0100134 if (call->flags & trace::CALL_FLAG_END_FRAME) {
José Fonseca61e61f72011-09-11 16:53:34 +0100135 FrameBookmark frameBookmark(startBookmark);
136 frameBookmark.numberOfCalls = numOfCalls;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400137
Zack Rusinac92a212011-09-06 18:25:34 -0400138 currentFrame = new ApiTraceFrame();
139 currentFrame->number = numOfFrames;
140 currentFrame->setNumChildren(numOfCalls);
Zack Rusin851d0b02011-09-14 22:04:07 -0400141 currentFrame->setLastCallIndex(call->no);
Zack Rusinac92a212011-09-06 18:25:34 -0400142 frames.append(currentFrame);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400143
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400144 m_createdFrames.append(currentFrame);
José Fonseca61e61f72011-09-11 16:53:34 +0100145 m_frameBookmarks[numOfFrames] = frameBookmark;
Zack Rusinac92a212011-09-06 18:25:34 -0400146 ++numOfFrames;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400147
Zack Rusinac92a212011-09-06 18:25:34 -0400148 if (m_parser.percentRead() - lastPercentReport >= 5) {
149 emit parsed(m_parser.percentRead());
150 lastPercentReport = m_parser.percentRead();
151 }
José Fonseca61e61f72011-09-11 16:53:34 +0100152 m_parser.getBookmark(startBookmark);
Zack Rusinac92a212011-09-06 18:25:34 -0400153 numOfCalls = 0;
154 }
Zack Rusinac92a212011-09-06 18:25:34 -0400155 delete call;
156 }
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400157
Zack Rusinac92a212011-09-06 18:25:34 -0400158 if (numOfCalls) {
José Fonsecab4a3d142011-10-27 07:43:19 +0100159 //trace::File::Bookmark endBookmark = m_parser.currentBookmark();
José Fonseca61e61f72011-09-11 16:53:34 +0100160 FrameBookmark frameBookmark(startBookmark);
161 frameBookmark.numberOfCalls = numOfCalls;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400162
Zack Rusinac92a212011-09-06 18:25:34 -0400163 currentFrame = new ApiTraceFrame();
164 currentFrame->number = numOfFrames;
165 currentFrame->setNumChildren(numOfCalls);
166 frames.append(currentFrame);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400167
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400168 m_createdFrames.append(currentFrame);
José Fonseca61e61f72011-09-11 16:53:34 +0100169 m_frameBookmarks[numOfFrames] = frameBookmark;
Zack Rusinac92a212011-09-06 18:25:34 -0400170 ++numOfFrames;
171 }
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400172
Zack Rusinac92a212011-09-06 18:25:34 -0400173 emit parsed(100);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400174
Zack Rusinac92a212011-09-06 18:25:34 -0400175 emit framesLoaded(frames);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400176}
177
178void TraceLoader::parseTrace()
179{
Zack Rusinac92a212011-09-06 18:25:34 -0400180 QList<ApiTraceFrame*> frames;
Zack Rusinac92a212011-09-06 18:25:34 -0400181 int frameCount = 0;
Zack Rusinac92a212011-09-06 18:25:34 -0400182 int lastPercentReport = 0;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400183
Lawrence L Love59befce2014-03-20 18:47:39 -0700184 ApiTraceFrame *currentFrame = new ApiTraceFrame();
185 currentFrame->number = frameCount;
186
187 FrameContents frameCalls;
188 while (frameCalls.load(this, currentFrame, m_helpHash, m_parser)) {
189
190 if (frameCalls.topLevelCount() == frameCalls.allCallsCount()) {
191 currentFrame->setCalls(frameCalls.allCalls(),
192 frameCalls.allCalls(),
193 frameCalls.binaryDataSize());
Lawrence L Love3512d982014-03-19 15:18:45 -0700194 } else {
Lawrence L Love59befce2014-03-20 18:47:39 -0700195 currentFrame->setCalls(frameCalls.topLevelCalls(),
196 frameCalls.allCalls(),
197 frameCalls.binaryDataSize());
Zack Rusind9d9d222013-10-11 18:02:26 -0400198 }
Lawrence L Love59befce2014-03-20 18:47:39 -0700199 frames.append(currentFrame);
200 if (frames.count() >= FRAMES_TO_CACHE) {
201 emit framesLoaded(frames);
202 frames.clear();
Zack Rusind9d9d222013-10-11 18:02:26 -0400203 }
Lawrence L Love59befce2014-03-20 18:47:39 -0700204 if (m_parser.percentRead() - lastPercentReport >= 5) {
205 emit parsed(m_parser.percentRead());
206 lastPercentReport = m_parser.percentRead();
Zack Rusinac92a212011-09-06 18:25:34 -0400207 }
Lawrence L Love59befce2014-03-20 18:47:39 -0700208 ++frameCount;
209 currentFrame = new ApiTraceFrame();
210 currentFrame->number = frameCount;
211
212 frameCalls.reset();
Zack Rusinac92a212011-09-06 18:25:34 -0400213 }
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400214
Zack Rusinac92a212011-09-06 18:25:34 -0400215 //last frames won't have markers
216 // it's just a bunch of Delete calls for every object
217 // after the last SwapBuffers
Lawrence L Love59befce2014-03-20 18:47:39 -0700218 if (!frameCalls.isEmpty()) {
219 if (frameCalls.topLevelCount() == frameCalls.allCallsCount()) {
220 currentFrame->setCalls(frameCalls.allCalls(),
221 frameCalls.allCalls(),
222 frameCalls.binaryDataSize());
Zack Rusind9d9d222013-10-11 18:02:26 -0400223 } else {
Lawrence L Love59befce2014-03-20 18:47:39 -0700224 currentFrame->setCalls(frameCalls.topLevelCalls(),
225 frameCalls.allCalls(),
226 frameCalls.binaryDataSize());
Zack Rusind9d9d222013-10-11 18:02:26 -0400227 }
Zack Rusinac92a212011-09-06 18:25:34 -0400228 frames.append(currentFrame);
Zack Rusinac92a212011-09-06 18:25:34 -0400229 }
230 if (frames.count()) {
231 emit framesLoaded(frames);
232 }
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400233}
234
235
Zack Rusinebf971e2011-09-06 17:44:43 -0400236ApiTraceCallSignature * TraceLoader::signature(unsigned id)
237{
238 if (id >= m_signatures.count()) {
239 m_signatures.resize(id + 1);
240 return NULL;
241 } else {
242 return m_signatures[id];
243 }
244}
245
246void TraceLoader::addSignature(unsigned id, ApiTraceCallSignature *signature)
247{
248 m_signatures[id] = signature;
249}
250
Zack Rusinad513b32011-09-25 14:33:41 -0400251void TraceLoader::searchNext(const ApiTrace::SearchRequest &request)
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400252{
253 Q_ASSERT(m_parser.supportsOffsets());
254 if (m_parser.supportsOffsets()) {
Zack Rusinad513b32011-09-25 14:33:41 -0400255 int startFrame = m_createdFrames.indexOf(request.frame);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400256 const FrameBookmark &frameBookmark = m_frameBookmarks[startFrame];
257 m_parser.setBookmark(frameBookmark.start);
José Fonsecab4a3d142011-10-27 07:43:19 +0100258 trace::Call *call = 0;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400259 while ((call = m_parser.parse_call())) {
260
Zack Rusinad513b32011-09-25 14:33:41 -0400261 if (callContains(call, request.text, request.cs)) {
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400262 unsigned frameIdx = callInFrame(call->no);
263 ApiTraceFrame *frame = m_createdFrames[frameIdx];
264 const QVector<ApiTraceCall*> calls =
265 fetchFrameContents(frame);
266 for (int i = 0; i < calls.count(); ++i) {
267 if (calls[i]->index() == call->no) {
Zack Rusinad513b32011-09-25 14:33:41 -0400268 emit searchResult(request, ApiTrace::SearchResult_Found,
269 calls[i]);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400270 break;
271 }
272 }
273 delete call;
274 return;
275 }
276
277 delete call;
278 }
279 }
Zack Rusinad513b32011-09-25 14:33:41 -0400280 emit searchResult(request, ApiTrace::SearchResult_NotFound, 0);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400281}
282
Zack Rusinad513b32011-09-25 14:33:41 -0400283void TraceLoader::searchPrev(const ApiTrace::SearchRequest &request)
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400284{
Zack Rusin121e3162011-09-13 01:35:12 -0400285 Q_ASSERT(m_parser.supportsOffsets());
286 if (m_parser.supportsOffsets()) {
Zack Rusinad513b32011-09-25 14:33:41 -0400287 int startFrame = m_createdFrames.indexOf(request.frame);
José Fonsecab4a3d142011-10-27 07:43:19 +0100288 trace::Call *call = 0;
289 QList<trace::Call*> frameCalls;
Zack Rusin121e3162011-09-13 01:35:12 -0400290 int frameIdx = startFrame;
291
292 const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
293 int numCallsToParse = frameBookmark.numberOfCalls;
294 m_parser.setBookmark(frameBookmark.start);
295
296 while ((call = m_parser.parse_call())) {
297
298 frameCalls.append(call);
299 --numCallsToParse;
300
301 if (numCallsToParse == 0) {
302 bool foundCall = searchCallsBackwards(frameCalls,
303 frameIdx,
Zack Rusinad513b32011-09-25 14:33:41 -0400304 request);
Zack Rusin121e3162011-09-13 01:35:12 -0400305
306 qDeleteAll(frameCalls);
307 frameCalls.clear();
308 if (foundCall) {
309 return;
310 }
311
312 --frameIdx;
313
314 if (frameIdx >= 0) {
315 const FrameBookmark &frameBookmark =
316 m_frameBookmarks[frameIdx];
317 m_parser.setBookmark(frameBookmark.start);
318 numCallsToParse = frameBookmark.numberOfCalls;
319 }
320 }
321 }
322 }
Zack Rusinad513b32011-09-25 14:33:41 -0400323 emit searchResult(request, ApiTrace::SearchResult_NotFound, 0);
Zack Rusin121e3162011-09-13 01:35:12 -0400324}
325
José Fonsecab4a3d142011-10-27 07:43:19 +0100326bool TraceLoader::searchCallsBackwards(const QList<trace::Call*> &calls,
Zack Rusin121e3162011-09-13 01:35:12 -0400327 int frameIdx,
Zack Rusinad513b32011-09-25 14:33:41 -0400328 const ApiTrace::SearchRequest &request)
Zack Rusin121e3162011-09-13 01:35:12 -0400329{
330 for (int i = calls.count() - 1; i >= 0; --i) {
José Fonsecab4a3d142011-10-27 07:43:19 +0100331 trace::Call *call = calls[i];
Zack Rusinad513b32011-09-25 14:33:41 -0400332 if (callContains(call, request.text, request.cs)) {
Zack Rusin121e3162011-09-13 01:35:12 -0400333 ApiTraceFrame *frame = m_createdFrames[frameIdx];
334 const QVector<ApiTraceCall*> apiCalls =
335 fetchFrameContents(frame);
336 for (int i = 0; i < apiCalls.count(); ++i) {
337 if (apiCalls[i]->index() == call->no) {
Zack Rusinad513b32011-09-25 14:33:41 -0400338 emit searchResult(request,
339 ApiTrace::SearchResult_Found,
340 apiCalls[i]);
Zack Rusin121e3162011-09-13 01:35:12 -0400341 break;
342 }
343 }
344 return true;
345 }
346 }
347 return false;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400348}
349
350int TraceLoader::callInFrame(int callIdx) const
351{
352 unsigned numCalls = 0;
353
José Fonseca6bfa32f2012-03-22 16:26:47 +0000354 for (int frameIdx = 0; frameIdx < m_frameBookmarks.size(); ++frameIdx) {
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400355 const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
356 unsigned firstCall = numCalls;
357 unsigned endCall = numCalls + frameBookmark.numberOfCalls;
358 if (firstCall <= callIdx && endCall > callIdx) {
359 return frameIdx;
360 }
361 numCalls = endCall;
362 }
363 Q_ASSERT(!"call not in the trace");
364 return 0;
365}
366
José Fonsecab4a3d142011-10-27 07:43:19 +0100367bool TraceLoader::callContains(trace::Call *call,
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400368 const QString &str,
369 Qt::CaseSensitivity sensitivity)
370{
José Fonsecacb7c76f2014-03-27 16:57:22 +0000371 /*
372 * FIXME: do string comparison directly on trace::Call
373 */
374 ApiTraceCall *apiCall = apiCallFromTraceCall(call, m_helpHash,
375 0, 0, this);
376 bool result = apiCall->contains(str, sensitivity);
377 delete apiCall;
378 return result;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400379}
380
381QVector<ApiTraceCall*>
382TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame)
383{
384 Q_ASSERT(currentFrame);
Zack Rusin99f84fa2011-09-19 23:44:25 -0400385
Zack Rusin447f4a52011-09-19 23:45:39 -0400386 if (currentFrame->isLoaded()) {
Zack Rusin99f84fa2011-09-19 23:44:25 -0400387 return currentFrame->calls();
388 }
389
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400390 if (m_parser.supportsOffsets()) {
391 unsigned frameIdx = currentFrame->number;
392 int numOfCalls = numberOfCallsInFrame(frameIdx);
393
394 if (numOfCalls) {
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400395 const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
396
397 m_parser.setBookmark(frameBookmark.start);
398
Lawrence L Love59befce2014-03-20 18:47:39 -0700399 FrameContents frameCalls(numOfCalls);
400 frameCalls.load(this, currentFrame, m_helpHash, m_parser);
401 if (frameCalls.topLevelCount() == frameCalls.allCallsCount()) {
402 emit frameContentsLoaded(currentFrame,
403 frameCalls.allCalls(),
404 frameCalls.allCalls(),
405 frameCalls.binaryDataSize());
Zack Rusind9d9d222013-10-11 18:02:26 -0400406 } else {
Lawrence L Love59befce2014-03-20 18:47:39 -0700407 emit frameContentsLoaded(currentFrame,
408 frameCalls.topLevelCalls(),
409 frameCalls.allCalls(),
410 frameCalls.binaryDataSize());
Zack Rusind9d9d222013-10-11 18:02:26 -0400411 }
Lawrence L Love59befce2014-03-20 18:47:39 -0700412 return frameCalls.allCalls();
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400413 }
414 }
415 return QVector<ApiTraceCall*>();
416}
417
Zack Rusin93e4d152011-09-13 02:23:39 -0400418void TraceLoader::findFrameStart(ApiTraceFrame *frame)
419{
Zack Rusin99f84fa2011-09-19 23:44:25 -0400420 if (!frame->isLoaded()) {
421 loadFrame(frame);
422 }
Zack Rusin93e4d152011-09-13 02:23:39 -0400423 emit foundFrameStart(frame);
424}
425
426void TraceLoader::findFrameEnd(ApiTraceFrame *frame)
427{
Zack Rusin99f84fa2011-09-19 23:44:25 -0400428 if (!frame->isLoaded()) {
429 loadFrame(frame);
430 }
Zack Rusin93e4d152011-09-13 02:23:39 -0400431 emit foundFrameEnd(frame);
432}
433
Zack Rusinda7579b2011-09-13 17:33:05 -0400434void TraceLoader::findCallIndex(int index)
435{
436 int frameIdx = callInFrame(index);
437 ApiTraceFrame *frame = m_createdFrames[frameIdx];
438 QVector<ApiTraceCall*> calls = fetchFrameContents(frame);
439 QVector<ApiTraceCall*>::const_iterator itr;
440 ApiTraceCall *call = 0;
441 for (itr = calls.constBegin(); itr != calls.constEnd(); ++itr) {
442 if ((*itr)->index() == index) {
443 call = *itr;
Lawrence L Love53a40802014-02-12 15:26:55 -0800444 break;
Zack Rusinda7579b2011-09-13 17:33:05 -0400445 }
446 }
José Fonsecacaa84282013-04-11 18:54:06 +0100447 if (call) {
448 emit foundCallIndex(call);
449 }
Zack Rusinda7579b2011-09-13 17:33:05 -0400450}
451
Zack Rusinad513b32011-09-25 14:33:41 -0400452void TraceLoader::search(const ApiTrace::SearchRequest &request)
453{
454 if (request.direction == ApiTrace::SearchRequest::Next) {
455 searchNext(request);
456 } else {
457 searchPrev(request);
458 }
459}
460
Lawrence L Love59befce2014-03-20 18:47:39 -0700461TraceLoader::FrameContents::FrameContents(int numOfCalls)
462 : m_allCalls(numOfCalls),
463 m_binaryDataSize(0),
464 m_parsedCalls(0)
465{}
466
467
468void
469TraceLoader::FrameContents::reset()
470{
471 m_groups.clear();
472 m_allCalls.clear();
473 m_topLevelItems.clear();
474 m_binaryDataSize = 0;
475}
476
477int
478TraceLoader::FrameContents::topLevelCount() const
479{
480 return m_topLevelItems.count();
481}
482
483int
484TraceLoader::FrameContents::allCallsCount() const
485{
486 return m_allCalls.count();
487}
488
489quint64
490TraceLoader::FrameContents::binaryDataSize() const
491{
492 return m_binaryDataSize;
493}
494QVector<ApiTraceCall*>
495TraceLoader::FrameContents::topLevelCalls() const
496{
497 return m_topLevelItems;
498}
499
500QVector<ApiTraceCall*>
501TraceLoader::FrameContents::allCalls() const
502{
503 return m_allCalls;
504}
505
506bool
507TraceLoader::FrameContents::isEmpty()
508{
509 return (m_allCalls.count() == 0);
510}
511
512bool
513TraceLoader::FrameContents::load(TraceLoader *loader,
514 ApiTraceFrame *currentFrame,
515 QHash<QString, QUrl> helpHash,
516 trace::Parser &parser)
517{
518 bool bEndFrameReached = false;
519 int initNumOfCalls = m_allCalls.count();
520 trace::Call *call;
521 ApiTraceCall *apiCall = NULL;
522
523 while ((call = parser.parse_call())) {
524
525 apiCall = apiCallFromTraceCall(call, helpHash, currentFrame,
526 m_groups.isEmpty() ? 0 : m_groups.top(),
527 loader);
528 Q_ASSERT(apiCall);
529 if (initNumOfCalls) {
530 Q_ASSERT(m_parsedCalls < m_allCalls.size());
531 m_allCalls[m_parsedCalls++] = apiCall;
532 } else {
533 m_allCalls.append(apiCall);
534 }
535 if (m_groups.count() == 0) {
536 m_topLevelItems.append(apiCall);
537 } else {
538 m_groups.top()->addChild(apiCall);
539 }
540 if (call->flags & trace::CALL_FLAG_MARKER_PUSH) {
541 m_groups.push(apiCall);
542 } else if (call->flags & trace::CALL_FLAG_MARKER_POP) {
543 if (m_groups.count()) {
544 m_groups.top()->finishedAddingChildren();
545 m_groups.pop();
546 }
547 }
548 if (apiCall->hasBinaryData()) {
549 QByteArray data =
550 apiCall->arguments()[apiCall->binaryDataIndex()].
551 toByteArray();
552 m_binaryDataSize += data.size();
553 }
554
555 delete call;
556
557 if (apiCall->flags() & trace::CALL_FLAG_END_FRAME) {
558 bEndFrameReached = true;
559 break;
560 }
561 }
562 if (initNumOfCalls) {
563 // There can be fewer parsed calls when call in different
564 // threads cross the frame boundary
565 Q_ASSERT(m_parsedCalls <= initNumOfCalls);
566 Q_ASSERT(m_parsedCalls <= m_allCalls.size());
567 m_allCalls.resize(m_parsedCalls);
568 Q_ASSERT(m_parsedCalls <= currentFrame->numChildrenToLoad());
569 }
570 m_allCalls.squeeze();
571 m_topLevelItems.squeeze();
572
573 return bEndFrameReached;
574}
575
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400576#include "traceloader.moc"