Akonadi

datastore.h
1/***************************************************************************
2 * SPDX-FileCopyrightText: 2006 Andreas Gungl <a.gungl@gmx.de> *
3 * *
4 * SPDX-License-Identifier: LGPL-2.0-or-later *
5 ***************************************************************************/
6
7#pragma once
8
9#include <QList>
10#include <QMutex>
11#include <QObject>
12#include <QSqlDatabase>
13#include <QThreadStorage>
14
15class QSqlQuery;
16class QTimer;
17
18#include "entities.h"
19#include "notificationcollector.h"
20
21#include <memory>
22
23namespace Akonadi
24{
25namespace Server
26{
27class DbConfig;
28class DataStore;
29class DataStoreFactory
30{
31public:
32 virtual ~DataStoreFactory() = default;
33 virtual DataStore *createStore() = 0;
34
35protected:
36 explicit DataStoreFactory() = default;
37
38private:
39 Q_DISABLE_COPY_MOVE(DataStoreFactory)
40};
41
42class NotificationCollector;
43
44/**
45 This class handles all the database access.
46
47 <h4>Database configuration</h4>
48
49 You can select between various database backends during runtime using the
50 @c $HOME/.config/akonadi/akonadiserverrc configuration file.
51
52 Example:
53@verbatim
54[%General]
55Driver=QMYSQL
56
57[QMYSQL_EMBEDDED]
58Name=akonadi
59Options=SERVER_DATADIR=/home/foo/.local/share/akonadi/db_data
60
61[QMYSQL]
62Name=akonadi
63Host=localhost
64User=foo
65Password=*****
66#Options=UNIX_SOCKET=/home/foo/.local/share/akonadi/socket-bar/mysql.socket
67StartServer=true
68ServerPath=/usr/sbin/mysqld
69
70[QSQLITE]
71Name=/home/foo/.local/share/akonadi/akonadi.db
72@endverbatim
73
74 Use @c General/Driver to select the QSql driver to use for database
75 access. The following drivers are currently supported, other might work
76 but are untested:
77
78 - QMYSQL
79 - QMYSQL_EMBEDDED
80 - QSQLITE
81
82 The options for each driver are read from the corresponding group.
83 The following options are supported, dependent on the driver not all of them
84 might have an effect:
85
86 - Name: Database name, for sqlite that's the file name of the database.
87 - Host: Hostname of the database server
88 - User: Username for the database server
89 - Password: Password for the database server
90 - Options: Additional options, format is driver-dependent
91 - StartServer: Start the database locally just for Akonadi instead of using an existing one
92 - ServerPath: Path to the server executable
93*/
94class DataStore : public QObject
95{
97public:
98 const constexpr static bool Silent = true;
99
100 static void setFactory(std::unique_ptr<DataStoreFactory> factory);
101
102 /**
103 * Returns DataStore associated with the given database connection.
104 */
106
107 /**
108 Closes the database connection and destroys the DataStore object.
109 */
110 ~DataStore() override;
111
112 /**
113 Opens the database connection.
114 */
115 virtual void open();
116
117 /**
118 Closes the database connection.
119 */
120 void close();
121
122 /**
123 Initializes the database. Should be called during startup by the main thread.
124 */
125 virtual bool init();
126
127 /**
128 Per thread singleton.
129 */
130 static DataStore *self();
131
132 /**
133 * Returns whether per thread DataStore has been created.
134 */
135 static bool hasDataStore();
136
137 /* --- ItemFlags ----------------------------------------------------- */
138 virtual bool setItemsFlags(const PimItem::List &items,
139 const QList<Flag> *currentFlags,
140 const QList<Flag> &newFlags,
141 bool *flagsChanged = nullptr,
142 const Collection &col = Collection(),
143 bool silent = false);
144 virtual bool appendItemsFlags(const PimItem::List &items,
145 const QList<Flag> &flags,
146 bool *flagsChanged = nullptr,
147 bool checkIfExists = true,
148 const Collection &col = Collection(),
149 bool silent = false);
150 virtual bool removeItemsFlags(const PimItem::List &items,
151 const QList<Flag> &flags,
152 bool *tagsChanged = nullptr,
153 const Collection &collection = Collection(),
154 bool silent = false);
155
156 /* --- ItemTags ----------------------------------------------------- */
157 virtual bool setItemsTags(const PimItem::List &items, const Tag::List &tags, bool *tagsChanged = nullptr, bool silent = false);
158 virtual bool appendItemsTags(const PimItem::List &items,
159 const Tag::List &tags,
160 bool *tagsChanged = nullptr,
161 bool checkIfExists = true,
162 const Collection &col = Collection(),
163 bool silent = false);
164 virtual bool removeItemsTags(const PimItem::List &items, const Tag::List &tags, bool *tagsChanged = nullptr, bool silent = false);
165 virtual bool removeTags(const Tag::List &tags, bool silent = false);
166
167 /* --- ItemParts ----------------------------------------------------- */
168 virtual bool removeItemParts(const PimItem &item, const QSet<QByteArray> &parts);
169
170 // removes all payload parts for this item.
171 virtual bool invalidateItemCache(const PimItem &item);
172
173 /* --- Collection ------------------------------------------------------ */
174 virtual bool appendCollection(Collection &collection, const QStringList &mimeTypes, const QMap<QByteArray, QByteArray> &attributes);
175
176 /// removes the given collection and all its content
177 virtual bool cleanupCollection(Collection &collection);
178
179 /// moves the collection @p collection to @p newParent.
180 virtual bool moveCollection(Collection &collection, const Collection &newParent);
181
182 virtual bool appendMimeTypeForCollection(qint64 collectionId, const QStringList &mimeTypes);
183
184 static QString collectionDelimiter()
185 {
186 return QStringLiteral("/");
187 }
188
189 /**
190 Determines the active cache policy for this Collection.
191 The active cache policy is set in the corresponding Collection fields.
192 */
193 virtual void activeCachePolicy(Collection &col);
194
195 /// Returns all virtual collections the @p item is linked to
196 QList<Collection> virtualCollections(const PimItem &item);
197
198 QMap<Server::Entity::Id, QList<PimItem>> virtualCollections(const Akonadi::Server::PimItem::List &items);
199
200 /* --- PimItem ------------------------------------------------------- */
201 virtual bool appendPimItem(QList<Part> &parts,
202 const QList<Flag> &flags,
203 const MimeType &mimetype,
204 const Collection &collection,
205 const QDateTime &dateTime,
206 const QString &remote_id,
207 const QString &remoteRevision,
208 const QString &gid,
209 PimItem &pimItem);
210 /**
211 * Removes the pim item and all referenced data ( e.g. flags )
212 */
213 virtual bool cleanupPimItems(const PimItem::List &items, bool silent = false);
214
215 /**
216 * Unhides the specified PimItem. Emits the itemAdded() notification as
217 * the hidden flag is assumed to have been set by appendPimItem() before
218 * pushing the item to the preprocessor chain. The hidden item had his
219 * notifications disabled until now (so for the clients the "unhide" operation
220 * is actually a new item arrival).
221 *
222 * This function does NOT verify if the item was *really* hidden: this is
223 * responsibility of the caller.
224 */
225 virtual bool unhidePimItem(PimItem &pimItem);
226
227 /**
228 * Unhides all the items which have the "hidden" flag set.
229 * This function doesn't emit any notification about the items
230 * being unhidden so it's meant to be called only in rare circumstances.
231 * The most notable call to this function is at server startup
232 * when we attempt to restore a clean state of the database.
233 */
234 virtual bool unhideAllPimItems();
235
236 /* --- Collection attributes ------------------------------------------ */
237 virtual bool addCollectionAttribute(const Collection &col, const QByteArray &key, const QByteArray &value, bool silent = false);
238 /**
239 * Removes the given collection attribute for @p col.
240 * @throws HandlerException on database errors
241 * @returns @c true if the attribute existed, @c false otherwise
242 */
243 virtual bool removeCollectionAttribute(const Collection &col, const QByteArray &key);
244
245 /* --- Helper functions ---------------------------------------------- */
246
247 /**
248 Begins a transaction. No changes will be written to the database and
249 no notification signal will be emitted unless you call commitTransaction().
250 @return @c true if successful.
251 */
252 virtual bool beginTransaction(const QString &name);
253
254 /**
255 Reverts all changes within the current transaction.
256 */
257 virtual bool rollbackTransaction();
258
259 /**
260 Commits all changes within the current transaction and emits all
261 collected notification signals. If committing fails, the transaction
262 will be rolled back.
263 */
264 virtual bool commitTransaction();
265
266 /**
267 Returns true if there is a transaction in progress.
268 */
269 bool inTransaction() const;
270
271 /**
272 Returns the notification collector of this DataStore object.
273 Use this to listen to change notification signals.
274 */
276
277 /**
278 Returns the QSqlDatabase object. Use this for generating queries yourself.
279
280 Will [re-]open the database, if it is closed.
281 */
283
284 /**
285 Sets the current session id.
286 */
287 void setSessionId(const QByteArray &sessionId)
288 {
289 mSessionId = sessionId;
290 }
291
292 /**
293 Returns if the database is currently open
294 */
295 bool isOpened() const
296 {
297 return m_dbOpened;
298 }
299
300 bool doRollback();
301 void transactionKilledByDB();
302
304 /**
305 Emitted if a transaction has been successfully committed.
306 */
308 /**
309 Emitted if a transaction has been aborted.
310 */
312
313protected:
314 /**
315 Creates a new DataStore object and opens it.
316 */
317 DataStore(AkonadiServer *akonadi, DbConfig *dbConfig);
318 explicit DataStore(DbConfig *config);
319
320 void debugLastDbError(QStringView actionDescription) const;
321 void debugLastQueryError(const QSqlQuery &query, const char *actionDescription) const;
322
323private:
324 bool doAppendItemsFlag(const PimItem::List &items, const Flag &flag, const QSet<PimItem::Id> &existing, const Collection &col, bool silent);
325
326 bool doAppendItemsTag(const PimItem::List &items, const Tag &tag, const QSet<Entity::Id> &existing, const Collection &col, bool silent);
327
328 /** Converts the given date/time to the database format, i.e.
329 "YYYY-MM-DD HH:MM:SS".
330 @param dateTime the date/time in UTC
331 @return the date/time in database format
332 @see dateTimeToQDateTime
333 */
334 static QString dateTimeFromQDateTime(const QDateTime &dateTime);
335
336 /** Converts the given date/time from database format to QDateTime.
337 @param dateTime the date/time in database format
338 @return the date/time as QDateTime
339 @see dateTimeFromQDateTime
340 */
341 static QDateTime dateTimeToQDateTime(const QByteArray &dateTime);
342
343private Q_SLOTS:
344 void sendKeepAliveQuery();
345
346protected:
347 static std::unique_ptr<DataStoreFactory> sFactory;
348 std::unique_ptr<NotificationCollector> mNotificationCollector;
349 AkonadiServer *const m_akonadi = nullptr;
350 DbConfig *const m_dbConfig = nullptr;
351
352private:
353 Q_DISABLE_COPY_MOVE(DataStore)
354
355 void cleanupAfterRollback();
356 QString m_connectionName;
357 QSqlDatabase m_database;
358 bool m_dbOpened;
359 bool m_transactionKilledByDB = false;
360 uint m_transactionLevel;
361 struct TransactionQuery {
362 QString query;
363 QList<QVariant> boundValues;
364 bool isBatch;
365 };
366 QByteArray mSessionId;
367 QTimer *m_keepAliveTimer = nullptr;
368
369 friend class DataStoreFactory;
370};
371
372} // namespace Server
373} // namespace Akonadi
Represents a collection of PIM items.
Definition collection.h:62
This class handles all the database access.
Definition datastore.h:95
virtual bool beginTransaction(const QString &name)
Begins a transaction.
QList< Collection > virtualCollections(const PimItem &item)
Returns all virtual collections the item is linked to.
virtual bool moveCollection(Collection &collection, const Collection &newParent)
moves the collection collection to newParent.
virtual bool cleanupPimItems(const PimItem::List &items, bool silent=false)
Removes the pim item and all referenced data ( e.g.
void close()
Closes the database connection.
virtual bool cleanupCollection(Collection &collection)
removes the given collection and all its content
virtual bool rollbackTransaction()
Reverts all changes within the current transaction.
bool inTransaction() const
Returns true if there is a transaction in progress.
static DataStore * self()
Per thread singleton.
bool isOpened() const
Returns if the database is currently open.
Definition datastore.h:295
void setSessionId(const QByteArray &sessionId)
Sets the current session id.
Definition datastore.h:287
~DataStore() override
Closes the database connection and destroys the DataStore object.
void transactionRolledBack()
Emitted if a transaction has been aborted.
virtual bool unhideAllPimItems()
Unhides all the items which have the "hidden" flag set.
void transactionCommitted()
Emitted if a transaction has been successfully committed.
virtual bool unhidePimItem(PimItem &pimItem)
Unhides the specified PimItem.
NotificationCollector * notificationCollector()
Returns the notification collector of this DataStore object.
virtual void open()
Opens the database connection.
DataStore(AkonadiServer *akonadi, DbConfig *dbConfig)
Creates a new DataStore object and opens it.
virtual bool init()
Initializes the database.
static bool hasDataStore()
Returns whether per thread DataStore has been created.
static DataStore * dataStoreForDatabase(const QSqlDatabase &db)
Returns DataStore associated with the given database connection.
Definition datastore.cpp:94
QSqlDatabase database()
Returns the QSqlDatabase object.
virtual bool removeCollectionAttribute(const Collection &col, const QByteArray &key)
Removes the given collection attribute for col.
virtual bool commitTransaction()
Commits all changes within the current transaction and emits all collected notification signals.
virtual void activeCachePolicy(Collection &col)
Determines the active cache policy for this Collection.
A base class that provides an unique access layer to configuration and initialization of different da...
Definition dbconfig.h:21
Part of the DataStore, collects change notifications and emits them after the current transaction has...
An Akonadi Tag.
Definition tag.h:26
Helper integration between Akonadi and Qt.
Q_OBJECTQ_OBJECT
Q_SIGNALSQ_SIGNALS
Q_SLOTSQ_SLOTS
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.