3 #include "apitracecall.h"
8 #include <qjson/parser.h>
10 Retracer::Retracer(QObject *parent)
12 m_benchmarking(false),
13 m_doubleBuffered(true),
14 m_captureState(false),
18 QString format = QLatin1String("%1;");
20 QString format = QLatin1String("%1:");
22 QString buildPath = format.arg(APITRACE_BINARY_DIR);
23 m_processEnvironment = QProcessEnvironment::systemEnvironment();
24 m_processEnvironment.insert("PATH", buildPath +
25 m_processEnvironment.value("PATH"));
28 m_processEnvironment.value("PATH").toLatin1());
31 QString Retracer::fileName() const
36 void Retracer::setFileName(const QString &name)
41 bool Retracer::isBenchmarking() const
43 return m_benchmarking;
46 void Retracer::setBenchmarking(bool bench)
48 m_benchmarking = bench;
51 bool Retracer::isDoubleBuffered() const
53 return m_doubleBuffered;
56 void Retracer::setDoubleBuffered(bool db)
58 m_doubleBuffered = db;
61 void Retracer::setCaptureAtCallNumber(qlonglong num)
66 qlonglong Retracer::captureAtCallNumber() const
71 bool Retracer::captureState() const
73 return m_captureState;
76 void Retracer::setCaptureState(bool enable)
78 m_captureState = enable;
84 RetraceProcess *retrace = new RetraceProcess();
85 retrace->process()->setProcessEnvironment(m_processEnvironment);
87 retrace->setFileName(m_fileName);
88 retrace->setBenchmarking(m_benchmarking);
89 retrace->setDoubleBuffered(m_doubleBuffered);
90 retrace->setCaptureState(m_captureState);
91 retrace->setCaptureAtCallNumber(m_captureCall);
93 connect(retrace, SIGNAL(finished(const QString&)),
94 this, SLOT(cleanup()));
95 connect(retrace, SIGNAL(error(const QString&)),
96 this, SLOT(cleanup()));
97 connect(retrace, SIGNAL(finished(const QString&)),
98 this, SIGNAL(finished(const QString&)));
99 connect(retrace, SIGNAL(error(const QString&)),
100 this, SIGNAL(error(const QString&)));
101 connect(retrace, SIGNAL(foundState(ApiTraceState*)),
102 this, SIGNAL(foundState(ApiTraceState*)));
103 connect(retrace, SIGNAL(retraceErrors(const QList<ApiTraceError>&)),
104 this, SIGNAL(retraceErrors(const QList<ApiTraceError>&)));
110 /* means we need to kill the process */
111 if (retrace->process()->state() != QProcess::NotRunning) {
112 retrace->terminate();
119 void RetraceProcess::start()
121 QStringList arguments;
123 if (m_doubleBuffered) {
124 arguments << QLatin1String("-db");
126 arguments << QLatin1String("-sb");
129 if (m_captureState) {
130 arguments << QLatin1String("-D");
131 arguments << QString::number(m_captureCall);
133 if (m_benchmarking) {
134 arguments << QLatin1String("-b");
138 arguments << m_fileName;
140 m_process->start(QLatin1String("glretrace"), arguments);
144 void RetraceProcess::replayFinished(int exitCode, QProcess::ExitStatus exitStatus)
146 QByteArray output = m_process->readAllStandardOutput();
148 QString errStr = m_process->readAllStandardError();
151 qDebug()<<"Process finished = ";
152 qDebug()<<"\terr = "<<errStr;
153 qDebug()<<"\tout = "<<output;
156 if (exitStatus != QProcess::NormalExit) {
157 msg = QLatin1String("Process crashed");
158 } else if (exitCode != 0) {
159 msg = QLatin1String("Process exited with non zero exit code");
161 if (m_captureState) {
163 QVariantMap parsedJson = m_jsonParser->parse(output, &ok).toMap();
164 ApiTraceState *state = new ApiTraceState(parsedJson);
165 emit foundState(state);
166 msg = tr("State fetched.");
168 msg = QString::fromUtf8(output);
172 QStringList errorLines = errStr.split('\n');
173 QList<ApiTraceError> errors;
174 QRegExp regexp("(^\\d+): +(\\b\\w+\\b): (.+$)");
175 foreach(QString line, errorLines) {
176 if (regexp.indexIn(line) != -1) {
178 error.callIndex = regexp.cap(1).toInt();
179 error.type = regexp.cap(2);
180 error.message = regexp.cap(3);
181 errors.append(error);
184 if (!errors.isEmpty()) {
185 emit retraceErrors(errors);
190 void RetraceProcess::replayError(QProcess::ProcessError err)
193 * XXX: this function is likely unnecessary and should be eliminated given
194 * that replayFinished is always called, even on errors.
198 qDebug()<<"Process error = "<<err;
199 qDebug()<<"\terr = "<<m_process->readAllStandardError();
200 qDebug()<<"\tout = "<<m_process->readAllStandardOutput();
204 tr("Couldn't execute the replay file '%1'").arg(m_fileName));
207 Q_DECLARE_METATYPE(QList<ApiTraceError>);
208 RetraceProcess::RetraceProcess(QObject *parent)
211 m_process = new QProcess(this);
212 m_jsonParser = new QJson::Parser();
214 qRegisterMetaType<QList<ApiTraceError> >();
216 connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
217 this, SLOT(replayFinished(int, QProcess::ExitStatus)));
218 connect(m_process, SIGNAL(error(QProcess::ProcessError)),
219 this, SLOT(replayError(QProcess::ProcessError)));
222 QProcess * RetraceProcess::process() const
227 QString RetraceProcess::fileName() const
232 void RetraceProcess::setFileName(const QString &name)
237 bool RetraceProcess::isBenchmarking() const
239 return m_benchmarking;
242 void RetraceProcess::setBenchmarking(bool bench)
244 m_benchmarking = bench;
247 bool RetraceProcess::isDoubleBuffered() const
249 return m_doubleBuffered;
252 void RetraceProcess::setDoubleBuffered(bool db)
254 m_doubleBuffered = db;
257 void RetraceProcess::setCaptureAtCallNumber(qlonglong num)
262 qlonglong RetraceProcess::captureAtCallNumber() const
264 return m_captureCall;
267 bool RetraceProcess::captureState() const
269 return m_captureState;
272 void RetraceProcess::setCaptureState(bool enable)
274 m_captureState = enable;
277 void RetraceProcess::terminate()
280 m_process->terminate();
281 emit finished(tr("Process terminated."));
285 void Retracer::cleanup()
290 RetraceProcess::~RetraceProcess()
295 #include "retracer.moc"