Akonadi

storagedebugger.cpp
1 /*
2  * SPDX-FileCopyrightText: 2013 Daniel Vr├ítil <[email protected]>
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 
17 Akonadi::Server::StorageDebugger *Akonadi::Server::StorageDebugger::mSelf = nullptr;
18 QMutex Akonadi::Server::StorageDebugger::mMutex;
19 
20 using namespace Akonadi::Server;
21 
22 Q_DECLARE_METATYPE(QList<QList<QVariant>>)
23 Q_DECLARE_METATYPE(DbConnection)
24 Q_DECLARE_METATYPE(QVector<DbConnection>)
25 
26 QDBusArgument &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 
34 const 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 
42 namespace
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 
53 StorageDebugger *StorageDebugger::instance()
54 {
55  mMutex.lock();
56  if (mSelf == nullptr) {
57  mSelf = new StorageDebugger();
58  }
59  mMutex.unlock();
60 
61  return mSelf;
62 }
63 
64 StorageDebugger::StorageDebugger()
65 {
66  qDBusRegisterMetaType<QList<QList<QVariant>>>();
67  qDBusRegisterMetaType<DbConnection>();
68  qDBusRegisterMetaType<QVector<DbConnection>>();
69  new StorageDebuggerAdaptor(this);
70  QDBusConnection::sessionBus().registerObject(QStringLiteral("/storageDebug"), this, QDBusConnection::ExportAdaptors);
71 }
72 
73 StorageDebugger::~StorageDebugger() = default;
74 
75 void StorageDebugger::enableSQLDebugging(bool enable)
76 {
77  mEnabled = enable;
78 }
79 
80 void StorageDebugger::writeToFile(const QString &file)
81 {
82  mFile = std::make_unique<QFile>(file);
83  mFile->open(QIODevice::WriteOnly);
84 }
85 
86 void 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 
96 void 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 
110 void 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 
124 void 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 
139 void 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 
154 QVector<DbConnection> StorageDebugger::connections() const
155 {
156  return mConnections;
157 }
158 
159 void 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  QSqlQuery q(query);
180  QList<QVariantList> result;
181 
182  if (q.first()) {
183  const QSqlRecord record = q.record();
184  QVariantList row;
185  const int numRecords = record.count();
186  row.reserve(numRecords);
187  for (int i = 0; i < numRecords; ++i) {
188  row << record.fieldName(i);
189  }
190  result << row;
191 
192  int cnt = 0;
193  do {
194  const QSqlRecord record = q.record();
195  QVariantList row;
196  const int numRecords = record.count();
197  row.reserve(numRecords);
198  for (int i = 0; i < numRecords; ++i) {
199  row << record.value(i);
200  }
201  result << row;
202  } while (q.next() && ++cnt < 1000);
203  }
204 
205  const int querySize = query.isSelect() ? query.size() : query.numRowsAffected();
206  Q_EMIT queryExecuted(seq,
207  connectionId,
209  duration,
210  query.executedQuery(),
211  query.boundValues(),
212  querySize,
213  result,
214  QString());
215 
216  if (mFile && mFile->isOpen()) {
217  QTextStream out(mFile.get());
218  out << query.executedQuery() << " " << duration << "ms\n";
219  }
220 
221  // Reset the query
222  q.seek(-1, false);
223 }
QVector::iterator begin()
qint64 currentMSecsSinceEpoch()
bool registerObject(const QString &path, QObject *object, QDBusConnection::RegisterOptions options)
Definition: item.h:32
QVariant value(int index) const const
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
int size() const const
QDBusConnection sessionBus()
QVector::iterator end()
QString name(StandardShortcut id)
void beginStructure()
NETWORKMANAGERQT_EXPORT NetworkManager::Connection::Ptr findConnection(const QString &path)
void endStructure()
QString fieldName(int index) const const
int count() const const
QDataStream & operator>>(QDataStream &in, KDateTime &dateTime)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jun 30 2022 03:51:47 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.