glsledit.cpp
imageviewer.cpp
jumpwidget.cpp
- loaderthread.cpp
mainwindow.cpp
main.cpp
retracer.cpp
#include "apitrace.h"
-#include "loaderthread.h"
+#include "traceloader.h"
#include "saverthread.h"
#include <QDir>
+#include <QThread>
ApiTrace::ApiTrace()
: m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
m_needsSaving(false)
{
- m_loader = new LoaderThread(this);
- connect(m_loader, SIGNAL(parsedFrames(const QList<ApiTraceFrame*>)),
+ m_loader = new TraceLoader();
+ connect(this, SIGNAL(loadTrace(QString)),
+ m_loader, SLOT(loadTrace(QString)));
+ connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)),
this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
- connect(m_loader, SIGNAL(started()),
+ connect(m_loader, SIGNAL(frameLoaded(int,QVector<ApiTraceCall*>,quint64)),
+ this, SLOT(fillFrame(int,QVector<ApiTraceCall*>,quint64)));
+
+ connect(m_loader, SIGNAL(startedParsing()),
this, SIGNAL(startedLoadingTrace()));
- connect(m_loader, SIGNAL(finished()),
+ connect(m_loader, SIGNAL(parsed(int)),
+ this, SIGNAL(loaded(int)));
+ connect(m_loader, SIGNAL(finishedParsing()),
this, SIGNAL(finishedLoadingTrace()));
+
m_saver = new SaverThread(this);
connect(m_saver, SIGNAL(traceSaved()),
this, SLOT(slotSaved()));
connect(m_saver, SIGNAL(traceSaved()),
this, SIGNAL(saved()));
+
+ m_loaderThread = new QThread();
+ m_loader->moveToThread(m_loaderThread);
+ m_loaderThread->start();
}
ApiTrace::~ApiTrace()
{
+ m_loaderThread->quit();
+ m_loaderThread->deleteLater();
qDeleteAll(m_calls);
qDeleteAll(m_frames);
delete m_loader;
if (m_fileName != name) {
m_fileName = name;
- if (m_loader->isRunning()) {
- m_loader->terminate();
- m_loader->wait();
- }
m_frames.clear();
m_calls.clear();
m_errors.clear();
m_needsSaving = false;
emit invalidated();
- m_loader->loadFile(m_fileName);
+// m_loader->loadTrace(m_fileName);
+ emit loadTrace(m_fileName);
}
}
int currentCalls = m_calls.count();
int numNewCalls = 0;
foreach(ApiTraceFrame *frame, frames) {
- Q_ASSERT(this == frame->parentTrace());
+ frame->setParentTrace(this);
numNewCalls += frame->numChildren();
calls += frame->calls();
}
return !m_errors.isEmpty();
}
-ApiTraceCallSignature * ApiTrace::signature(unsigned id)
-{
- if (id >= m_signatures.count()) {
- m_signatures.resize(id + 1);
- return NULL;
- } else {
- return m_signatures[id];
- }
-}
-
-void ApiTrace::addSignature(unsigned id, ApiTraceCallSignature *signature)
-{
- m_signatures[id] = signature;
-}
-
-ApiTraceEnumSignature * ApiTrace::enumSignature(unsigned id)
-{
- if (id >= m_enumSignatures.count()) {
- m_enumSignatures.resize(id + 1);
- return NULL;
- } else {
- return m_enumSignatures[id];
- }
-}
-
-void ApiTrace::addEnumSignature(unsigned id, ApiTraceEnumSignature *signature)
+void ApiTrace::fillFrame(int frameIdx, const QVector<ApiTraceCall *> &calls,
+ quint64 binaryDataSize)
{
- m_enumSignatures[id] = signature;
}
#include "apitrace.moc"
#include <QObject>
#include <QSet>
-class LoaderThread;
+class TraceLoader;
class SaverThread;
+class QThread;
class ApiTrace : public QObject
{
ApiTraceState defaultState() const;
- ApiTraceCallSignature *signature(unsigned id);
- void addSignature(unsigned id, ApiTraceCallSignature *signature);
-
- ApiTraceEnumSignature *enumSignature(unsigned id);
- void addEnumSignature(unsigned id, ApiTraceEnumSignature *signature);
-
-
QVector<ApiTraceCall*> calls() const;
ApiTraceCall *callAt(int idx) const;
ApiTraceCall *callWithIndex(int idx) const;
void save();
signals:
+ void loadTrace(const QString &name);
void startedLoadingTrace();
+ void loaded(int percent);
void finishedLoadingTrace();
void invalidated();
void framesInvalidated();
private slots:
void addFrames(const QList<ApiTraceFrame*> &frames);
+ void fillFrame(int frameIdx, const QVector<ApiTraceCall*> &calls,
+ quint64 binaryDataSize);
void slotSaved();
private:
void detectFrames();
FrameMarker m_frameMarker;
- LoaderThread *m_loader;
+ TraceLoader *m_loader;
+ QThread *m_loaderThread;
SaverThread *m_saver;
QSet<ApiTraceCall*> m_editedCalls;
bool m_needsSaving;
QSet<ApiTraceCall*> m_errors;
- QVector<ApiTraceCallSignature*> m_signatures;
- QVector<ApiTraceEnumSignature*> m_enumSignatures;
};
#endif
#include "apitracecall.h"
#include "apitrace.h"
+#include "traceloader.h"
#include "trace_model.hpp"
#include <QDebug>
{
ApiTraceEnumSignature *sig = 0;
- if (m_trace) {
- sig = m_trace->enumSignature(e->sig->id);
+ if (m_loader) {
+ sig = m_loader->enumSignature(e->sig->id);
}
if (!sig) {
sig = new ApiTraceEnumSignature(
QString::fromStdString(e->sig->name),
QVariant(e->sig->value));
- if (m_trace) {
- m_trace->addEnumSignature(e->sig->id, sig);
+ if (m_loader) {
+ m_loader->addEnumSignature(e->sig->id, sig);
}
}
m_state = state;
}
-ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, const Trace::Call *call)
+ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame,
+ TraceLoader *loader,
+ const Trace::Call *call)
: ApiTraceEvent(ApiTraceEvent::Call),
m_parentFrame(parentFrame)
{
- ApiTrace *trace = parentTrace();
-
- Q_ASSERT(trace);
-
m_index = call->no;
- m_signature = trace->signature(call->sig->id);
+ m_signature = loader->signature(call->sig->id);
if (!m_signature) {
QString name = QString::fromStdString(call->sig->name);
argNames += QString::fromStdString(call->sig->arg_names[i]);
}
m_signature = new ApiTraceCallSignature(name, argNames);
- trace->addSignature(call->sig->id, m_signature);
+ loader->addSignature(call->sig->id, m_signature);
}
if (call->ret) {
- VariantVisitor retVisitor(trace);
+ VariantVisitor retVisitor(loader);
call->ret->visit(retVisitor);
m_returnValue = retVisitor.variant();
}
m_argValues.reserve(call->args.size());
for (int i = 0; i < call->args.size(); ++i) {
- VariantVisitor argVisitor(trace);
+ VariantVisitor argVisitor(loader);
call->args[i]->visit(argVisitor);
m_argValues.append(argVisitor.variant());
if (m_argValues[i].type() == QVariant::ByteArray) {
{
m_callsToLoad = num;
}
+
+void ApiTraceFrame::setParentTrace(ApiTrace *parent)
+{
+ m_parentTrace = parent;
+}
class ApiTrace;
+class TraceLoader;
class VariantVisitor : public Trace::Visitor
{
public:
- VariantVisitor(ApiTrace *trace)
- : m_trace(trace)
+ VariantVisitor(TraceLoader *loader)
+ : m_loader(loader)
{}
virtual void visit(Trace::Null *);
virtual void visit(Trace::Bool *node);
return m_variant;
}
private:
- ApiTrace *m_trace;
+ TraceLoader *m_loader;
QVariant m_variant;
};
class ApiTraceCall : public ApiTraceEvent
{
public:
- ApiTraceCall(ApiTraceFrame *parentFrame, const Trace::Call *tcall);
+ ApiTraceCall(ApiTraceFrame *parentFrame, TraceLoader *loader,
+ const Trace::Call *tcall);
~ApiTraceCall();
int index() const;
class ApiTraceFrame : public ApiTraceEvent
{
public:
- ApiTraceFrame(ApiTrace *parent);
+ ApiTraceFrame(ApiTrace *parent=0);
int number;
bool isEmpty() const;
+ void setParentTrace(ApiTrace *parent);
ApiTrace *parentTrace() const;
void setNumChildren(int num);
#include "apitracemodel.h"
#include "apitracecall.h"
-#include "loaderthread.h"
+#include "traceloader.h"
#include "trace_parser.hpp"
#include <QDebug>
m_ui.callView->setContextMenuPolicy(Qt::CustomContextMenu);
m_progressBar = new QProgressBar();
- m_progressBar->setRange(0, 0);
+ m_progressBar->setRange(0, 100);
statusBar()->addPermanentWidget(m_progressBar);
m_progressBar->hide();
{
connect(m_trace, SIGNAL(startedLoadingTrace()),
this, SLOT(startedLoadingTrace()));
+ connect(m_trace, SIGNAL(loaded(int)),
+ this, SLOT(loadProgess(int)));
connect(m_trace, SIGNAL(finishedLoadingTrace()),
this, SLOT(finishedLoadingTrace()));
connect(m_trace, SIGNAL(startedSaving()),
statusBar()->showMessage( tr("Saved '%1'").arg(fileName), 5000);
}
+void MainWindow::loadProgess(int percent)
+{
+ m_progressBar->setValue(percent);
+}
+
#include "mainwindow.moc"
void replayStateFound(ApiTraceState *state);
void replayError(const QString &msg);
void startedLoadingTrace();
+ void loadProgess(int percent);
void finishedLoadingTrace();
void lookupState();
void showSettings();
static ApiTraceCall *
apiCallFromTraceCall(const Trace::Call *call,
const QHash<QString, QUrl> &helpHash,
- ApiTraceFrame *frame)
+ ApiTraceFrame *frame,
+ TraceLoader *loader)
{
- ApiTraceCall *apiCall = new ApiTraceCall(frame, call);
+ ApiTraceCall *apiCall = new ApiTraceCall(frame, loader, call);
apiCall->setHelpUrl(helpHash.value(apiCall->name()));
return apiCall;
}
-TraceLoader::TraceLoader(ApiTrace *parent)
+TraceLoader::TraceLoader(QObject *parent)
: QObject(parent),
- m_trace(parent),
m_frameMarker(ApiTrace::FrameMarker_SwapBuffers)
{
}
qDebug() << "error: failed to open " << filename;
return;
}
-
+ qDebug()<<"load trace with "<<filename;
emit startedParsing();
+ qDebug() <<"\t support offsets = "<<m_parser.supportsOffsets();
if (m_parser.supportsOffsets()) {
scanTrace();
} else {
frameOffset.numberOfCalls = numOfCalls;
frameOffset.callNumber = callNum;
- currentFrame = new ApiTraceFrame(m_trace);
+ currentFrame = new ApiTraceFrame();
currentFrame->number = numOfFrames;
currentFrame->setNumChildren(numOfCalls);
frames.append(currentFrame);
frameOffset.numberOfCalls = numOfCalls;
frameOffset.callNumber = callNum;
- currentFrame = new ApiTraceFrame(m_trace);
+ currentFrame = new ApiTraceFrame();
currentFrame->number = numOfFrames;
currentFrame->setNumChildren(numOfCalls);
frames.append(currentFrame);
while (call) {
//std::cout << *call;
if (!currentFrame) {
- currentFrame = new ApiTraceFrame(m_trace);
+ currentFrame = new ApiTraceFrame();
currentFrame->number = frameCount;
++frameCount;
}
ApiTraceCall *apiCall =
- apiCallFromTraceCall(call, m_helpHash, currentFrame);
+ apiCallFromTraceCall(call, m_helpHash, currentFrame, this);
calls.append(apiCall);
if (apiCall->hasBinaryData()) {
QByteArray data =
frames.clear();
}
if (m_parser.percentRead() - lastPercentReport >= 5) {
+ qDebug()<<"emitting = " << m_parser.percentRead();
emit parsed(m_parser.percentRead());
lastPercentReport = m_parser.percentRead();
}
}
+ApiTraceCallSignature * TraceLoader::signature(unsigned id)
+{
+ if (id >= m_signatures.count()) {
+ m_signatures.resize(id + 1);
+ return NULL;
+ } else {
+ return m_signatures[id];
+ }
+}
+
+void TraceLoader::addSignature(unsigned id, ApiTraceCallSignature *signature)
+{
+ m_signatures[id] = signature;
+}
+
+ApiTraceEnumSignature * TraceLoader::enumSignature(unsigned id)
+{
+ if (id >= m_enumSignatures.count()) {
+ m_enumSignatures.resize(id + 1);
+ return NULL;
+ } else {
+ return m_enumSignatures[id];
+ }
+}
+
+void TraceLoader::addEnumSignature(unsigned id, ApiTraceEnumSignature *signature)
+{
+ m_enumSignatures[id] = signature;
+}
+
#include "traceloader.moc"
{
Q_OBJECT
public:
- TraceLoader(ApiTrace *parent);
+ TraceLoader(QObject *parent=0);
~TraceLoader();
+
+ ApiTraceCallSignature *signature(unsigned id);
+ void addSignature(unsigned id, ApiTraceCallSignature *signature);
+
+ ApiTraceEnumSignature *enumSignature(unsigned id);
+ void addEnumSignature(unsigned id, ApiTraceEnumSignature *signature);
+
public slots:
void loadTrace(const QString &filename);
void loadFrame(int frameIdx);
signals:
void startedParsing();
- void parsed(float percent);
+ void parsed(int percent);
void finishedParsing();
void framesLoaded(const QList<ApiTraceFrame*> &frames);
void loadHelpFile();
void scanTrace();
void parseTrace();
+
private:
- ApiTrace *m_trace;
Trace::Parser m_parser;
QString m_fileName;
ApiTrace::FrameMarker m_frameMarker;
FrameOffsets m_frameOffsets;
QHash<QString, QUrl> m_helpHash;
+
+ QVector<ApiTraceCallSignature*> m_signatures;
+ QVector<ApiTraceEnumSignature*> m_enumSignatures;
};
#endif
return (byte1 == SNAPPY_BYTE1 && byte2 == SNAPPY_BYTE2);
}
+typedef struct gz_stream {
+ z_stream stream;
+ int z_err; /* error code for last stream operation */
+ int z_eof; /* set if end of input file */
+ FILE *file; /* .gz file */
+} gz_dummy_stream;
ZLibFile::ZLibFile(const std::string &filename,
File::Mode mode)
(mode == File::Write) ? "wb" : "rb");
if (mode == File::Read && m_gzFile) {
- m_endOffset = gzseek(m_gzFile, 0, SEEK_END);
- gzrewind(m_gzFile);
+ //XXX: unfortunately zlib doesn't support
+ // SEEK_END or we could've done:
+ //m_endOffset = gzseek(m_gzFile, 0, SEEK_END);
+ //gzrewind(m_gzFile);
+ gz_dummy_stream *stream = (gz_dummy_stream *)m_gzFile;
+ long loc = ftell(stream->file);
+ fseek(stream->file,0,SEEK_END);
+ m_endOffset = ftell(stream->file);
+ fseek(stream->file, loc, SEEK_SET);
}
return m_gzFile != NULL;
int ZLibFile::rawPercentRead()
{
- return 100 * (gztell(m_gzFile) / m_endOffset);
+ gz_dummy_stream *stream = (gz_dummy_stream *)m_gzFile;
+ return 100 * (ftell(stream->file) / m_endOffset);
}
file = NULL;
next_call_no = 0;
version = 0;
+ m_supportsSeeking = false;
}
if (!file->open(filename, File::Read)) {
return false;
}
+ m_supportsSeeking = file->supportsOffsets();
version = read_uint();
if (version > TRACE_VERSION) {
size_t id = read_uint();
FunctionSig *sig = lookup(functions, id);
- const File::Offset offset = file->currentOffset();
- bool callWithSig = callWithSignature(offset);
+
+
+ File::Offset offset;
+ bool callWithSig = false;
+ if (m_supportsSeeking) {
+ offset = file->currentOffset();
+ callWithSig = callWithSignature(offset);
+ }
+
if (!sig || callWithSig) {
if (!sig) {
sig = new FunctionSig;
}
sig->arg_names = arg_names;
functions[id] = sig;
- m_callSigOffsets.insert(offset);
+ if (m_supportsSeeking) {
+ m_callSigOffsets.insert(offset);
+ }
} else {
/* skip over the signature */
skip_string(); /* name */
Value *Parser::parse_enum() {
size_t id = read_uint();
EnumSig *sig = lookup(enums, id);
- const File::Offset offset = file->currentOffset();
- bool enumWithSig = enumWithSignature(offset);
+ File::Offset offset;
+ bool enumWithSig = false;
+
+ if (m_supportsSeeking) {
+ offset = file->currentOffset();
+ enumWithSig = enumWithSignature(offset);
+ }
+
if (!sig || enumWithSig) {
if (!sig) {
sig = new EnumSig;
sig->value = value->toSInt();
delete value;
enums[id] = sig;
- m_enumSigOffsets.insert(offset);
+ if (m_supportsSeeking) {
+ m_enumSigOffsets.insert(offset);
+ }
} else {
skip_string(); /*name*/
scan_value();
Value *Parser::parse_bitmask() {
size_t id = read_uint();
BitmaskSig *sig = lookup(bitmasks, id);
- const File::Offset offset = file->currentOffset();
- bool bitmaskWithSig = bitmaskWithSignature(offset);
+ File::Offset offset;
+ bool bitmaskWithSig = false;
+
+ if (m_supportsSeeking) {
+ offset = file->currentOffset();
+ bitmaskWithSig = bitmaskWithSignature(offset);
+ }
+
if (!sig || bitmaskWithSig) {
if (!sig) {
sig = new BitmaskSig;
}
sig->flags = flags;
bitmasks[id] = sig;
- m_bitmaskSigOffsets.insert(offset);
+ if (m_supportsSeeking) {
+ m_bitmaskSigOffsets.insert(offset);
+ }
} else {
int num_flags = read_uint();
for (int i = 0; i < num_flags; ++i) {
size_t id = read_uint();
StructSig *sig = lookup(structs, id);
- const File::Offset offset = file->currentOffset();
- bool structWithSig = structWithSignature(offset);
+ File::Offset offset;
+ bool structWithSig = false;
+
+ if (m_supportsSeeking) {
+ offset = file->currentOffset();
+ structWithSig = structWithSignature(offset);
+ }
+
if (!sig || structWithSig) {
if (!sig) {
sig = new StructSig;
}
sig->member_names = member_names;
structs[id] = sig;
- m_structSigOffsets.insert(offset);
+ if (m_supportsSeeking) {
+ m_structSigOffsets.insert(offset);
+ }
} else {
skip_string(); /* name */
unsigned num_members = read_uint();
Call * Parser::scan_call()
{
+ assert(m_supportsSeeking);
do {
int c = read_byte();
switch(c) {
typedef std::map<File::Offset, unsigned> CallNumOffsets;
CallNumOffsets m_callNumOffsets;
+ bool m_supportsSeeking;
+
unsigned next_call_no;
public: