diff options
Diffstat (limited to 'src/corelib/tracing/qctflib.cpp')
-rw-r--r-- | src/corelib/tracing/qctflib.cpp | 303 |
1 files changed, 0 insertions, 303 deletions
diff --git a/src/corelib/tracing/qctflib.cpp b/src/corelib/tracing/qctflib.cpp deleted file mode 100644 index 2fbb02132f..0000000000 --- a/src/corelib/tracing/qctflib.cpp +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#define BUILD_LIBRARY -#include <qstring.h> -#include <qthread.h> -#include <stdio.h> -#include <qjsondocument.h> -#include <qjsonarray.h> -#include <qjsonobject.h> -#include <qfileinfo.h> -#include <qrect.h> -#include <qsize.h> -#include <qmetaobject.h> -#include <qendian.h> -#include "qctflib_p.h" - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(lcDebugTrace, "qt.core.ctf"); - -static const size_t packetHeaderSize = 24 + 6 * 8 + 4; -static const size_t packetSize = 4096; - -static const char traceMetadataTemplate[] = -#include "metadata_template.h" -; -static const size_t traceMetadataSize = sizeof(traceMetadataTemplate); - -template <typename T> -QByteArray &operator << (QByteArray &arr, T val) -{ - arr.append((char *)&val, sizeof(val)); - return arr; -} - -QCtfLibImpl *QCtfLibImpl::s_instance = nullptr; - -QCtfLib *QCtfLibImpl::instance() -{ - if (!s_instance) - s_instance = new QCtfLibImpl(); - return s_instance; -} - -QCtfLibImpl::QCtfLibImpl() -{ - QString location = QString::fromUtf8(qgetenv("QTRACE_LOCATION")); - if (location.isEmpty()) { - qCWarning (lcDebugTrace) << "QTRACE_LOCATION not set"; - return; - } - FILE *file = nullptr; - file = fopen(qPrintable(location + QStringLiteral("/session.json")), "rb"); - if (!file) { - qCWarning (lcDebugTrace) << "unable to open session file: " << (location + QStringLiteral("/session.json")); - m_location = location; - m_session.tracepoints.append(QStringLiteral("all")); - m_session.name = QStringLiteral("default"); - } else { - QByteArray data; - fseek(file, 0, SEEK_END); - long pos = ftell(file); - fseek(file, 0, SEEK_SET); - data.resize(pos); - long size = (long)fread(data.data(), pos, 1, file); - fclose(file); - if (size != 1) - return; - QJsonDocument json(QJsonDocument::fromJson(data)); - - QJsonObject obj = json.object(); - QJsonValue value = *obj.begin(); - if (value.isNull() || !value.isArray()) - return; - m_session.name = obj.begin().key(); - QJsonArray arr = value.toArray(); - for (auto var : arr) - m_session.tracepoints.append(var.toString()); - - m_location = location + QStringLiteral("/ust"); - } - m_session.all = m_session.tracepoints.contains(QStringLiteral("all")); - - auto datetime = QDateTime::currentDateTime(); - QString mhn = QSysInfo::machineHostName(); - QString metadata = QString::fromUtf8(traceMetadataTemplate, traceMetadataSize); - metadata.replace(QStringLiteral("$TRACE_UUID"), s_TraceUuid.toString(QUuid::WithoutBraces)); - metadata.replace(QStringLiteral("$ARC_BIT_WIDTH"), QString::number(Q_PROCESSOR_WORDSIZE * 8)); - metadata.replace(QStringLiteral("$SESSION_NAME"), m_session.name); - metadata.replace(QStringLiteral("$CREATION_TIME"), datetime.toString()); - metadata.replace(QStringLiteral("$HOST_NAME"), mhn); - metadata.replace(QStringLiteral("$CLOCK_FREQUENCY"), m_timer.isMonotonic() ? QStringLiteral("1000000000") : QStringLiteral("1000")); - metadata.replace(QStringLiteral("$CLOCK_NAME"), m_timer.isMonotonic() ? QStringLiteral("monotonic") : QStringLiteral("system")); - metadata.replace(QStringLiteral("$CLOCK_TYPE"), m_timer.isMonotonic() ? QStringLiteral("Monotonic clock") : QStringLiteral("System clock")); - metadata.replace(QStringLiteral("$CLOCK_OFFSET"), QString::number(datetime.toMSecsSinceEpoch() * 1000000)); -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - metadata.replace(QStringLiteral("$ENDIANNESS"), QStringLiteral("be")); -#else - metadata.replace(QStringLiteral("$ENDIANNESS"), QStringLiteral("le")); -#endif - writeMetadata(metadata.toUtf8(), true); - - m_timer.start(); -} - -void QCtfLibImpl::writeMetadata(const QByteArray &data, bool overwrite) -{ - FILE *file = nullptr; - file = fopen(qPrintable(m_location + QStringLiteral("/metadata")), overwrite ? "w+b": "ab"); - if (!file) - return; - - if (!overwrite) - fputs("\n", file); - fwrite(data.data(), data.size() - 1, 1, file); - fclose(file); -} - -void QCtfLibImpl::writeCtfPacket(QCtfLibImpl::Channel &ch) -{ - FILE *file = nullptr; - file = fopen(ch.channelName, "ab"); - if (file) { - /* Each packet contains header and context, which are defined in the metadata.txt */ - QByteArray packet; - packet << s_CtfHeaderMagic; - /* Uuid is array of bytes hence implicitely big endian. */ - packet << qToBigEndian(s_TraceUuid.data1); - packet << qToBigEndian(s_TraceUuid.data2); - packet << qToBigEndian(s_TraceUuid.data3); - for (int i = 0; i < 8; i++) - packet << s_TraceUuid.data4[i]; - - packet << quint32(0); - packet << ch.minTimestamp; - packet << ch.maxTimestamp; - packet << quint64(ch.data.size() + packetHeaderSize + ch.threadNameLength) * 8u; - packet << quint64(packetSize) * 8u; - packet << ch.seqnumber++; - packet << quint64(0); - packet << ch.threadIndex; - if (ch.threadName.size()) - packet.append(ch.threadName); - packet << (char)0; - - Q_ASSERT(ch.data.size() + packetHeaderSize + ch.threadNameLength <= packetSize); - Q_ASSERT(packet.size() == qsizetype(packetHeaderSize + ch.threadNameLength)); - fwrite(packet.data(), packet.size(), 1, file); - ch.data.resize(packetSize - packet.size(), 0); - fwrite(ch.data.data(), ch.data.size(), 1, file); - } - fclose(file); -} - -QCtfLibImpl::~QCtfLibImpl() -{ - qDeleteAll(m_eventPrivs); -} - -bool QCtfLibImpl::tracepointEnabled(const QCtfTracePointEvent &point) -{ - return m_session.all || m_session.tracepoints.contains(point.provider.provider); -} - -QCtfLibImpl::Channel::~Channel() -{ - if (data.size()) - QCtfLibImpl::writeCtfPacket(*this); -} - -static QString toMetadata(const QString &provider, const QString &name, const QString &metadata, quint32 eventId) -{ -/* - generates event structure: -event { - name = provider:tracepoint_name; - id = eventId; - stream_id = 0; - loglevel = 13; - fields := struct { - metadata - }; -}; -*/ - QString ret; - ret = QStringLiteral("event {\n name = \"") + provider + QLatin1Char(':') + name + QStringLiteral("\";\n"); - ret += QStringLiteral(" id = ") + QString::number(eventId) + QStringLiteral(";\n"); - ret += QStringLiteral(" stream_id = 0;\n loglevel = 13;\n fields := struct {\n "); - ret += metadata + QStringLiteral("\n };\n};\n"); - return ret; -} - -QCtfTracePointPrivate *QCtfLibImpl::initializeTracepoint(const QCtfTracePointEvent &point) -{ - QMutexLocker lock(&m_mutex); - QCtfTracePointPrivate *priv = point.d; - if (!point.d) { - if (const auto &it = m_eventPrivs.find(point.eventName); it != m_eventPrivs.end()) { - priv = *it; - } else { - priv = new QCtfTracePointPrivate(); - m_eventPrivs.insert(point.eventName, priv); - priv->id = eventId(); - priv->metadata = toMetadata(point.provider.provider, point.eventName, point.metadata, priv->id); - } - } - return priv; -} - -void QCtfLibImpl::doTracepoint(const QCtfTracePointEvent &point, const QByteArray &arr) -{ - QCtfTracePointPrivate *priv = point.d; - quint64 timestamp = 0; - QThread *thread = nullptr; - { - QMutexLocker lock(&m_mutex); - if (!priv->metadataWritten) { - priv->metadataWritten = true; - auto providerMetadata = point.provider.metadata; - while (providerMetadata) { - registerMetadata(*providerMetadata); - providerMetadata = providerMetadata->next; - } - if (m_newAdditionalMetadata.size()) { - for (const QString &name : m_newAdditionalMetadata) - writeMetadata(m_additionalMetadata[name]->metadata.toUtf8()); - m_newAdditionalMetadata.clear(); - } - writeMetadata(priv->metadata.toUtf8()); - } - timestamp = m_timer.nsecsElapsed(); - } - if (arr.size() != point.size) { - if (arr.size() < point.size) - return; - if (arr.size() > point.size && !point.variableSize && !point.metadata.isEmpty()) - return; - } - - thread = QThread::currentThread(); - if (thread == nullptr) - return; - - Channel &ch = m_threadData.localData(); - - if (ch.channelName[0] == 0) { - m_threadIndices.insert(thread, m_threadIndices.size()); - sprintf(ch.channelName, "%s/channel_%d", qPrintable(m_location), m_threadIndices[thread]); - FILE *f = nullptr; - f = fopen(ch.channelName, "wb"); - fclose(f); - ch.minTimestamp = ch.maxTimestamp = timestamp; - ch.thread = thread; - ch.threadIndex = m_threadIndices[thread]; - ch.threadName = thread->objectName().toUtf8(); - if (ch.threadName.isEmpty()) { - const QMetaObject *obj = thread->metaObject(); - ch.threadName = QByteArray(obj->className()); - } - ch.threadNameLength = ch.threadName.size() + 1; - } - if (ch.locked) - return; - Q_ASSERT(ch.thread == thread); - ch.locked = true; - - QByteArray event; - event << priv->id << timestamp; - if (!point.metadata.isEmpty()) - event.append(arr); - - if (ch.threadNameLength + ch.data.size() + event.size() + packetHeaderSize >= packetSize) { - writeCtfPacket(ch); - ch.data = event; - ch.minTimestamp = ch.maxTimestamp = timestamp; - } else { - ch.data.append(event); - } - - ch.locked = false; - ch.maxTimestamp = timestamp; -} - -bool QCtfLibImpl::sessionEnabled() -{ - return !m_session.name.isEmpty(); -} - -int QCtfLibImpl::eventId() -{ - return m_eventId++; -} - -void QCtfLibImpl::registerMetadata(const QCtfTraceMetadata &metadata) -{ - if (m_additionalMetadata.contains(metadata.name)) - return; - - m_additionalMetadata.insert(metadata.name, &metadata); - m_newAdditionalMetadata.insert(metadata.name); -} - -QT_END_NAMESPACE |