Tracing: Move event storage out of trace manager

This is a step toward making the trace manager non-virtual. It should
just juggle the storages for types and events, and manage the threads to
access them. It doesn't need to know what exactly it stores.

Change-Id: I45093c60d8ae921e68aeb09bd48d24d5877ce306
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Ulf Hermann
2018-05-07 13:26:05 +02:00
parent e6d583913e
commit 916883e70f
17 changed files with 218 additions and 136 deletions

View File

@@ -74,19 +74,37 @@ private:
std::vector<QmlEventType> m_types;
};
class QmlProfilerEventStorage : public Timeline::TraceEventStorage
{
Q_DECLARE_TR_FUNCTIONS(QmlProfilerEventStorage)
public:
using ErrorHandler = std::function<void(const QString &)>;
QmlProfilerEventStorage(const ErrorHandler &errorHandler);
int append(Timeline::TraceEvent &&event) override;
int size() const override;
void clear() override;
bool replay(const std::function<bool(Timeline::TraceEvent &&)> &receiver) const override;
void finalize() override;
ErrorHandler errorHandler() const;
void setErrorHandler(const ErrorHandler &errorHandler);
private:
Timeline::TraceStashFile<QmlEvent> m_file;
std::function<void(const QString &)> m_errorHandler;
int m_size = 0;
};
class QmlProfilerModelManager::QmlProfilerModelManagerPrivate
{
public:
QmlProfilerModelManagerPrivate() : file("qmlprofiler-data") {}
Internal::QmlProfilerTextMarkModel *textMarkModel = nullptr;
Internal::QmlProfilerDetailsRewriter *detailsRewriter = nullptr;
Timeline::TraceStashFile<QmlEvent> file;
bool isRestrictedToRange = false;
void writeToStream(const QmlEvent &event);
void addEventType(const QmlEventType &eventType);
void handleError(const QString &message);
@@ -94,7 +112,10 @@ public:
};
QmlProfilerModelManager::QmlProfilerModelManager(QObject *parent) :
Timeline::TimelineTraceManager(std::make_unique<QmlProfilerEventTypeStorage>(), parent),
Timeline::TimelineTraceManager(
std::make_unique<QmlProfilerEventStorage>(
std::bind(&Timeline::TimelineTraceManager::error, this, std::placeholders::_1)),
std::make_unique<QmlProfilerEventTypeStorage>(), parent),
d(new QmlProfilerModelManagerPrivate)
{
setNotesModel(new QmlProfilerNotesModel(this));
@@ -106,9 +127,6 @@ QmlProfilerModelManager::QmlProfilerModelManager(QObject *parent) :
connect(d->detailsRewriter, &Internal::QmlProfilerDetailsRewriter::eventDetailsChanged,
this, &QmlProfilerModelManager::typeDetailsFinished);
if (!d->file.open())
emit error(tr("Cannot open temporary trace file to store events."));
quint64 allFeatures = 0;
for (quint8 i = 0; i <= MaximumProfileFeature; ++i)
allFeatures |= (1ull << i);
@@ -138,12 +156,6 @@ void QmlProfilerModelManager::registerFeatures(quint64 features, QmlEventLoader
finalizer, clearer);
}
void QmlProfilerModelManager::addEvents(const QVector<QmlEvent> &events)
{
for (const QmlEvent &event : events)
addEvent(event);
}
const QmlEventType &QmlProfilerModelManager::eventType(int typeId) const
{
return static_cast<const QmlEventType &>(TimelineTraceManager::eventType(typeId));
@@ -174,31 +186,19 @@ void QmlProfilerModelManager::replayQmlEvents(QmlEventLoader loader,
if (initializer)
initializer();
const auto result = d->file.replay([&](const QmlEvent &event) {
const auto result = eventStorage()->replay([&](Timeline::TraceEvent &&event) {
if (future.isCanceled())
return false;
loader(event, eventType(event.typeIndex()));
loader(static_cast<QmlEvent &&>(event), eventType(event.typeIndex()));
return true;
});
switch (result) {
case Timeline::TraceStashFile<QmlEvent>::ReplaySuccess:
if (finalizer)
finalizer();
break;
case Timeline::TraceStashFile<QmlEvent>::ReplayOpenFailed:
if (errorHandler)
errorHandler(tr("Could not re-open temporary trace file"));
break;
case Timeline::TraceStashFile<QmlEvent>::ReplayLoadFailed:
if (errorHandler)
errorHandler(tr("Could not load events from temporary trace file"));
break;
case Timeline::TraceStashFile<QmlEvent>::ReplayReadPastEnd:
if (errorHandler)
errorHandler(tr("Read past end in temporary trace file"));
break;
if (!result && errorHandler) {
errorHandler(future.isCanceled() ? QString()
: tr("Failed to replay QML events from stash file."));
} else if (result && finalizer) {
finalizer();
}
}
@@ -236,11 +236,6 @@ static QString getInitialDetails(const QmlEventType &event)
return details;
}
void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::writeToStream(const QmlEvent &event)
{
file.append(event);
}
void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::handleError(const QString &message)
{
// What to do here?
@@ -254,8 +249,6 @@ const char *QmlProfilerModelManager::featureName(ProfileFeature feature)
void QmlProfilerModelManager::finalize()
{
if (!d->file.flush())
emit error(tr("Failed to flush temporary trace file"));
d->detailsRewriter->reloadDocuments();
// Load notes after the timeline models have been initialized ...
@@ -299,14 +292,6 @@ void QmlProfilerModelManager::restrictByFilter(QmlProfilerModelManager::QmlEvent
});
}
void QmlProfilerModelManager::clearEventStorage()
{
TimelineTraceManager::clearEventStorage();
d->file.clear();
if (!d->file.open())
emit error(tr("Failed to reset temporary trace file"));
}
int QmlProfilerModelManager::appendEventType(QmlEventType &&type)
{
type.setDisplayName(getDisplayName(type));
@@ -351,10 +336,9 @@ void QmlProfilerModelManager::setEventType(int typeIndex, QmlEventType &&type)
}
void QmlProfilerModelManager::addEvent(const QmlEvent &event)
void QmlProfilerModelManager::appendEvent(QmlEvent &&event)
{
d->writeToStream(event);
TimelineTraceManager::addEvent(event);
TimelineTraceManager::appendEvent(std::move(event));
}
void QmlProfilerModelManager::restrictToRange(qint64 start, qint64 end)
@@ -480,4 +464,67 @@ void QmlProfilerEventTypeStorage::clear()
m_types.clear();
}
QmlProfilerEventStorage::QmlProfilerEventStorage(
const std::function<void (const QString &)> &errorHandler)
: m_file("qmlprofiler-data"), m_errorHandler(errorHandler)
{
if (!m_file.open())
errorHandler(tr("Cannot open temporary trace file to store events."));
}
int QmlProfilerEventStorage::append(Timeline::TraceEvent &&event)
{
m_file.append(std::move(static_cast<QmlEvent &&>(event)));
return m_size++;
}
int QmlProfilerEventStorage::size() const
{
return m_size;
}
void QmlProfilerEventStorage::clear()
{
m_size = 0;
m_file.clear();
if (!m_file.open())
m_errorHandler(tr("Failed to reset temporary trace file"));
}
void QmlProfilerEventStorage::finalize()
{
if (!m_file.flush())
m_errorHandler(tr("Failed to flush temporary trace file"));
}
QmlProfilerEventStorage::ErrorHandler QmlProfilerEventStorage::errorHandler() const
{
return m_errorHandler;
}
void QmlProfilerEventStorage::setErrorHandler(
const QmlProfilerEventStorage::ErrorHandler &errorHandler)
{
m_errorHandler = errorHandler;
}
bool QmlProfilerEventStorage::replay(
const std::function<bool (Timeline::TraceEvent &&)> &receiver) const
{
switch (m_file.replay(receiver)) {
case Timeline::TraceStashFile<QmlEvent>::ReplaySuccess:
return true;
case Timeline::TraceStashFile<QmlEvent>::ReplayOpenFailed:
m_errorHandler(tr("Could not re-open temporary trace file"));
break;
case Timeline::TraceStashFile<QmlEvent>::ReplayLoadFailed:
// Happens if the loader rejects an event. Not an actual error
break;
case Timeline::TraceStashFile<QmlEvent>::ReplayReadPastEnd:
m_errorHandler(tr("Read past end in temporary trace file"));
break;
}
return false;
}
} // namespace QmlProfiler