Akonadi

storagedebugger.cpp
1/*
2 * SPDX-FileCopyrightText: 2013 Daniel Vrátil <dvratil@redhat.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 *
6 */
7
8#include "storagedebugger.h"
9#include "storagedebuggeradaptor.h"
10
11#include <QSqlError>
12#include <QSqlQuery>
13#include <QSqlRecord>
14
15#include <QDBusConnection>
16
17Akonadi::Server::StorageDebugger *Akonadi::Server::StorageDebugger::mSelf = nullptr;
18QMutex Akonadi::Server::StorageDebugger::mMutex;
19
20using namespace Akonadi::Server;
21
22Q_DECLARE_METATYPE(QList<QList<QVariant>>)
23Q_DECLARE_METATYPE(DbConnection)
24Q_DECLARE_METATYPE(QList<DbConnection>)
25
26QDBusArgument &operator<<(QDBusArgument &arg, const DbConnection &con)
27{
28 arg.beginStructure();
29 arg << con.id << con.name << con.start << con.trxName << con.transactionStart;
30 arg.endStructure();
31 return arg;
32}
33
34const QDBusArgument &operator>>(const QDBusArgument &arg, DbConnection &con)
35{
36 arg.beginStructure();
37 arg >> con.id >> con.name >> con.start >> con.trxName >> con.transactionStart;
38 arg.endStructure();
39 return arg;
40}
41
42namespace
43{
45{
46 return std::find_if(vec.begin(), vec.end(), [id](const DbConnection &con) {
47 return con.id == id;
48 });
49}
50
51} // namespace
52
53StorageDebugger *StorageDebugger::instance()
54{
55 mMutex.lock();
56 if (mSelf == nullptr) {
57 mSelf = new StorageDebugger();
58 }
59 mMutex.unlock();
60
61 return mSelf;
62}
63
64StorageDebugger::StorageDebugger()
65{
66 qDBusRegisterMetaType<QList<QList<QVariant>>>();
67 qDBusRegisterMetaType<DbConnection>();
68 qDBusRegisterMetaType<QList<DbConnection>>();
69 new StorageDebuggerAdaptor(this);
70 QDBusConnection::sessionBus().registerObject(QStringLiteral("/storageDebug"), this, QDBusConnection::ExportAdaptors);
71}
72
73StorageDebugger::~StorageDebugger() = default;
74
75void StorageDebugger::enableSQLDebugging(bool enable)
76{
77 mEnabled = enable;
78}
79
80void StorageDebugger::writeToFile(const QString &file)
81{
82 mFile = std::make_unique<QFile>(file);
83 mFile->open(QIODevice::WriteOnly);
84}
85
86void StorageDebugger::addConnection(qint64 id, const QString &name)
87{
88 QMutexLocker locker(&mMutex);
89 const qint64 timestamp = QDateTime::currentMSecsSinceEpoch();
90 mConnections.push_back({id, name, timestamp, QString(), 0LL});
91 if (mEnabled) {
92 Q_EMIT connectionOpened(id, timestamp, name);
93 }
94}
95
96void StorageDebugger::removeConnection(qint64 id)
97{
98 QMutexLocker locker(&mMutex);
99 auto con = findConnection(mConnections, id);
100 if (con == mConnections.end()) {
101 return;
102 }
103 mConnections.erase(con);
104
105 if (mEnabled) {
106 Q_EMIT connectionClosed(id, QDateTime::currentMSecsSinceEpoch());
107 }
108}
109
110void StorageDebugger::changeConnection(qint64 id, const QString &name)
111{
112 QMutexLocker locker(&mMutex);
113 auto con = findConnection(mConnections, id);
114 if (con == mConnections.end()) {
115 return;
116 }
117 con->name = name;
118
119 if (mEnabled) {
120 Q_EMIT connectionChanged(id, name);
121 }
122}
123
124void StorageDebugger::addTransaction(qint64 connectionId, const QString &name, uint duration, const QString &error)
125{
126 QMutexLocker locker(&mMutex);
127 auto con = findConnection(mConnections, connectionId);
128 if (con == mConnections.end()) {
129 return;
130 }
131 con->trxName = name;
132 con->transactionStart = QDateTime::currentMSecsSinceEpoch();
133
134 if (mEnabled) {
135 Q_EMIT transactionStarted(connectionId, name, con->transactionStart, duration, error);
136 }
137}
138
139void StorageDebugger::removeTransaction(qint64 connectionId, bool commit, uint duration, const QString &error)
140{
141 QMutexLocker locker(&mMutex);
142 auto con = findConnection(mConnections, connectionId);
143 if (con == mConnections.end()) {
144 return;
145 }
146 con->trxName.clear();
147 con->transactionStart = 0;
148
149 if (mEnabled) {
150 Q_EMIT transactionFinished(connectionId, commit, QDateTime::currentMSecsSinceEpoch(), duration, error);
151 }
152}
153
154QList<DbConnection> StorageDebugger::connections() const
155{
156 return mConnections;
157}
158
159void StorageDebugger::queryExecuted(qint64 connectionId, const QSqlQuery &query, int duration)
160{
161 if (!mEnabled) {
162 return;
163 }
164
165 const qint64 seq = ++mSequence;
166 if (query.lastError().isValid()) {
167 Q_EMIT queryExecuted(seq,
168 connectionId,
170 duration,
171 query.executedQuery(),
172 query.boundValues(),
173 0,
175 query.lastError().text());
176 return;
177 }
178
179 const int querySize = query.isSelect() ? query.size() : query.numRowsAffected();
180 // We cannot extract actual results from the query since QSqlQuery is no longer copyable
181 // and looping over the reference we got from caller would consume the results for the
182 // caller. Therefor we just pass an empty list for a result.
183 Q_EMIT queryExecuted(seq,
184 connectionId,
186 duration,
187 query.executedQuery(),
188 query.boundValues(),
189 querySize,
191 QString());
192
193 if (mFile && mFile->isOpen()) {
194 QTextStream out(mFile.get());
195 out << query.executedQuery() << " " << duration << "ms\n";
196 }
197}
198
199#include "moc_storagedebugger.cpp"
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
KCALENDARCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalendarCore::Alarm::Ptr &)
QString name(GameStandardAction id)
NETWORKMANAGERQT_EXPORT NetworkManager::Connection::Ptr findConnection(const QString &path)
qint64 currentMSecsSinceEpoch()
void beginStructure()
void endStructure()
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
iterator begin()
iterator end()
iterator erase(const_iterator begin, const_iterator end)
void push_back(parameter_type value)
qsizetype size() const const
void lock()
void unlock()
Q_EMITQ_EMIT
void clear()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:31:59 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.