From: Zack Rusin Date: Tue, 6 Sep 2011 21:44:43 +0000 (-0400) Subject: Switch the gui to the on-demand-loader. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=ebf971eec6c3a5f98885cc418e04690ba213b645;p=apitrace Switch the gui to the on-demand-loader. Doesn't yet do actual on demand loading, but a lot of the code is in place. --- diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index e0cfe44..777bc92 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -12,7 +12,6 @@ set(qapitrace_SRCS glsledit.cpp imageviewer.cpp jumpwidget.cpp - loaderthread.cpp mainwindow.cpp main.cpp retracer.cpp diff --git a/gui/apitrace.cpp b/gui/apitrace.cpp index 9a68e63..d6a9e41 100644 --- a/gui/apitrace.cpp +++ b/gui/apitrace.cpp @@ -1,31 +1,46 @@ #include "apitrace.h" -#include "loaderthread.h" +#include "traceloader.h" #include "saverthread.h" #include +#include ApiTrace::ApiTrace() : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers), m_needsSaving(false) { - m_loader = new LoaderThread(this); - connect(m_loader, SIGNAL(parsedFrames(const QList)), + m_loader = new TraceLoader(); + connect(this, SIGNAL(loadTrace(QString)), + m_loader, SLOT(loadTrace(QString))); + connect(m_loader, SIGNAL(framesLoaded(const QList)), this, SLOT(addFrames(const QList))); - connect(m_loader, SIGNAL(started()), + connect(m_loader, SIGNAL(frameLoaded(int,QVector,quint64)), + this, SLOT(fillFrame(int,QVector,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; @@ -118,10 +133,6 @@ void ApiTrace::setFileName(const QString &name) 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(); @@ -129,7 +140,8 @@ void ApiTrace::setFileName(const QString &name) m_needsSaving = false; emit invalidated(); - m_loader->loadFile(m_fileName); +// m_loader->loadTrace(m_fileName); + emit loadTrace(m_fileName); } } @@ -157,7 +169,7 @@ void ApiTrace::addFrames(const QList &frames) 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(); } @@ -290,34 +302,9 @@ bool ApiTrace::hasErrors() const 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 &calls, + quint64 binaryDataSize) { - m_enumSignatures[id] = signature; } #include "apitrace.moc" diff --git a/gui/apitrace.h b/gui/apitrace.h index 036a84c..3b737e0 100644 --- a/gui/apitrace.h +++ b/gui/apitrace.h @@ -6,8 +6,9 @@ #include #include -class LoaderThread; +class TraceLoader; class SaverThread; +class QThread; class ApiTrace : public QObject { @@ -33,13 +34,6 @@ public: ApiTraceState defaultState() const; - ApiTraceCallSignature *signature(unsigned id); - void addSignature(unsigned id, ApiTraceCallSignature *signature); - - ApiTraceEnumSignature *enumSignature(unsigned id); - void addEnumSignature(unsigned id, ApiTraceEnumSignature *signature); - - QVector calls() const; ApiTraceCall *callAt(int idx) const; ApiTraceCall *callWithIndex(int idx) const; @@ -67,7 +61,9 @@ public slots: void save(); signals: + void loadTrace(const QString &name); void startedLoadingTrace(); + void loaded(int percent); void finishedLoadingTrace(); void invalidated(); void framesInvalidated(); @@ -81,6 +77,8 @@ signals: private slots: void addFrames(const QList &frames); + void fillFrame(int frameIdx, const QVector &calls, + quint64 binaryDataSize); void slotSaved(); private: void detectFrames(); @@ -93,7 +91,8 @@ private: FrameMarker m_frameMarker; - LoaderThread *m_loader; + TraceLoader *m_loader; + QThread *m_loaderThread; SaverThread *m_saver; QSet m_editedCalls; @@ -101,8 +100,6 @@ private: bool m_needsSaving; QSet m_errors; - QVector m_signatures; - QVector m_enumSignatures; }; #endif diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp index 680d22a..d1de5a8 100644 --- a/gui/apitracecall.cpp +++ b/gui/apitracecall.cpp @@ -1,6 +1,7 @@ #include "apitracecall.h" #include "apitrace.h" +#include "traceloader.h" #include "trace_model.hpp" #include @@ -175,15 +176,15 @@ void VariantVisitor::visit(Trace::Enum *e) { 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); } } @@ -600,17 +601,15 @@ void ApiTraceEvent::setState(ApiTraceState *state) 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); @@ -620,16 +619,16 @@ ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, const Trace::Call *call) 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) { @@ -1035,3 +1034,8 @@ void ApiTraceFrame::setNumChildren(int num) { m_callsToLoad = num; } + +void ApiTraceFrame::setParentTrace(ApiTrace *parent) +{ + m_parentTrace = parent; +} diff --git a/gui/apitracecall.h b/gui/apitracecall.h index 5a5a64b..865f60c 100644 --- a/gui/apitracecall.h +++ b/gui/apitracecall.h @@ -12,12 +12,13 @@ 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); @@ -37,7 +38,7 @@ public: return m_variant; } private: - ApiTrace *m_trace; + TraceLoader *m_loader; QVariant m_variant; }; @@ -233,7 +234,8 @@ Q_DECLARE_METATYPE(ApiTraceEvent*); 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; @@ -284,11 +286,12 @@ Q_DECLARE_METATYPE(ApiTraceCall*); 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); diff --git a/gui/apitracemodel.cpp b/gui/apitracemodel.cpp index 5860cf9..800b5c7 100644 --- a/gui/apitracemodel.cpp +++ b/gui/apitracemodel.cpp @@ -1,7 +1,7 @@ #include "apitracemodel.h" #include "apitracecall.h" -#include "loaderthread.h" +#include "traceloader.h" #include "trace_parser.hpp" #include diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 591c557..e5f6d9b 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -647,7 +647,7 @@ void MainWindow::initObjects() 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(); @@ -682,6 +682,8 @@ void MainWindow::initConnections() { 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()), @@ -1159,4 +1161,9 @@ void MainWindow::saveSelectedSurface() statusBar()->showMessage( tr("Saved '%1'").arg(fileName), 5000); } +void MainWindow::loadProgess(int percent) +{ + m_progressBar->setValue(percent); +} + #include "mainwindow.moc" diff --git a/gui/mainwindow.h b/gui/mainwindow.h index f3e3181..00fe04b 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -46,6 +46,7 @@ private slots: void replayStateFound(ApiTraceState *state); void replayError(const QString &msg); void startedLoadingTrace(); + void loadProgess(int percent); void finishedLoadingTrace(); void lookupState(); void showSettings(); diff --git a/gui/traceloader.cpp b/gui/traceloader.cpp index 40609ad..0303ee7 100644 --- a/gui/traceloader.cpp +++ b/gui/traceloader.cpp @@ -8,18 +8,18 @@ static ApiTraceCall * apiCallFromTraceCall(const Trace::Call *call, const QHash &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) { } @@ -39,9 +39,10 @@ void TraceLoader::loadTrace(const QString &filename) qDebug() << "error: failed to open " << filename; return; } - + qDebug()<<"load trace with "< &frames); @@ -53,8 +60,8 @@ private: void loadHelpFile(); void scanTrace(); void parseTrace(); + private: - ApiTrace *m_trace; Trace::Parser m_parser; QString m_fileName; ApiTrace::FrameMarker m_frameMarker; @@ -63,6 +70,9 @@ private: FrameOffsets m_frameOffsets; QHash m_helpHash; + + QVector m_signatures; + QVector m_enumSignatures; }; #endif diff --git a/trace_file.cpp b/trace_file.cpp index 517e221..45473b3 100644 --- a/trace_file.cpp +++ b/trace_file.cpp @@ -97,6 +97,12 @@ bool File::isSnappyCompressed(const std::string &filename) 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) @@ -115,8 +121,15 @@ bool ZLibFile::rawOpen(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; @@ -163,5 +176,6 @@ bool ZLibFile::rawSkip(size_t) 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); } diff --git a/trace_parser.cpp b/trace_parser.cpp index 95dbec5..2ef77b6 100644 --- a/trace_parser.cpp +++ b/trace_parser.cpp @@ -43,6 +43,7 @@ Parser::Parser() { file = NULL; next_call_no = 0; version = 0; + m_supportsSeeking = false; } @@ -62,6 +63,7 @@ bool Parser::open(const char *filename) { if (!file->open(filename, File::Read)) { return false; } + m_supportsSeeking = file->supportsOffsets(); version = read_uint(); if (version > TRACE_VERSION) { @@ -146,8 +148,15 @@ void Parser::parse_enter(void) { 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; @@ -160,7 +169,9 @@ void Parser::parse_enter(void) { } 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 */ @@ -336,8 +347,14 @@ Value *Parser::parse_string() { 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; @@ -347,7 +364,9 @@ Value *Parser::parse_enum() { 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(); @@ -361,8 +380,14 @@ Value *Parser::parse_enum() { 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; @@ -378,7 +403,9 @@ Value *Parser::parse_bitmask() { } 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) { @@ -419,8 +446,14 @@ Value *Parser::parse_struct() { 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; @@ -433,7 +466,9 @@ Value *Parser::parse_struct() { } 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(); @@ -528,6 +563,7 @@ inline bool Parser::bitmaskWithSignature(const File::Offset &offset) const Call * Parser::scan_call() { + assert(m_supportsSeeking); do { int c = read_byte(); switch(c) { diff --git a/trace_parser.hpp b/trace_parser.hpp index f50cf9a..15b0ccb 100644 --- a/trace_parser.hpp +++ b/trace_parser.hpp @@ -67,6 +67,8 @@ protected: typedef std::map CallNumOffsets; CallNumOffsets m_callNumOffsets; + bool m_supportsSeeking; + unsigned next_call_no; public: