Akonadi

preprocessormanager.h
1/******************************************************************************
2 *
3 * File : preprocessormanager.h
4 * Creation date : Sat 18 Jul 2009 01:58:50
5 *
6 * SPDX-FileCopyrightText: 2009 Szymon Stefanek <s.stefanek at gmail dot com>
7 *
8 * SPDX-License-Identifier: LGPL-2.0-or-later
9 *
10 *****************************************************************************/
11
12#pragma once
13
14#include <QHash>
15#include <QList>
16#include <QMutex>
17#include <QObject>
18
19#include <deque>
20
21class QTimer;
22
23#include "preprocessorinstance.h"
24
25namespace Akonadi
26{
27namespace Server
28{
29class PimItem;
30class DataStore;
31class Tracer;
32
33/**
34 * \class PreprocessorManager
35 * \brief The manager for preprocessor agents
36 *
37 * This class takes care of synchronizing the preprocessor agents.
38 *
39 * The preprocessors see the incoming PimItem objects before the user
40 * can see them (as long as the UI applications honor the hidden attribute).
41 * The items are marked as hidden (by the Append and AkAppend
42 * handlers) and then enqueued to the preprocessor chain via this class.
43 * Once all the preprocessors have done their work the item is unhidden again.
44 *
45 * Preprocessing isn't designed for critical tasks. There may
46 * be circumstances under that the Akonadi server fails to push an item
47 * to all the preprocessors. Most notably after a server restart all
48 * the items for that preprocessing was interrupted are just unhidden
49 * without any attempt to resume the preprocessor jobs.
50 *
51 * The enqueue requests may or may not arrive from "inside" a database
52 * transaction. The uncommitted transaction would "hide" the newly created items
53 * from the preprocessor instances (which are separate processes).
54 * This class, then, takes care of holding the newly arrived items
55 * in a wait queue until their transaction is committed (or rolled back).
56 */
58{
59 friend class PreprocessorInstance;
60
62 Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Akonadi.PreprocessorManager")
63
64protected:
65 /**
66 * The hashtable of transaction wait queues. There is one wait
67 * queue for each DataStore that is currently in a transaction.
68 */
70
71 /**
72 * The preprocessor chain.
73 * The pointers inside the list are owned.
74 *
75 * In all the algorithms we assume that this list is actually very short
76 * (say 3-4 elements) and reverse lookup (pointer->index) is really fast.
77 */
79
80 /**
81 * Is preprocessing enabled at all in this Akonadi server instance?
82 * This is true by default and can be set via setEnabled().
83 * Mainly used to disable preprocessing via configuration file.
84 */
85 bool mEnabled = false;
86
87 /**
88 * The mutex used to protect the internals of this class (mainly
89 * the mPreprocessorChain member).
90 */
92
93 /**
94 * The heartbeat timer. Used mainly to expire preprocessor jobs.
95 */
97
98 Tracer &mTracer;
99
100public:
101 /**
102 * Creates an instance of PreprocessorManager
103 */
104 explicit PreprocessorManager(Tracer &tracer);
105
106 /**
107 * Destroys the instance of PreprocessorManager
108 * and frees all the relevant resources
109 */
110 ~PreprocessorManager() override;
111
112 /**
113 * Returns true if preprocessing is active in this Akonadi server.
114 * This means that we have at least one active preprocessor and
115 * preprocessing hasn't been explicitly disabled via configuration
116 * (so if isActive() returns true then also isEnabled() will return true).
117 *
118 * This function is thread-safe.
119 */
120 bool isActive();
121
122 /**
123 * Returns true if this preprocessor hasn't been explicitly disabled
124 * via setEnabled( false ). This is used to disable preprocessing
125 * via configuration even if we have a valid chain of preprocessors.
126 *
127 * Please note that this flag doesn't tell if we actually have
128 * some registered preprocessors and thus we can do some meaningful job.
129 * You should use isActive() for this purpose.
130 */
131 bool isEnabled() const
132 {
133 return mEnabled;
134 }
135
136 /**
137 * Explicitly enables or disables the preprocessing in this Akonadi server.
138 * The PreprocessorManager starts in enabled state but can be disabled
139 * at a later stage: this is mainly used to disable preprocessing via
140 * configuration.
141 *
142 * Please note that setting this to true doesn't interrupt the currently
143 * running preprocessing jobs. Anything that was enqueued will be processed
144 * anyway. However, in Akonadi this is only invoked very early,
145 * when no preprocessors are alive yet.
146 */
147 void setEnabled(bool enabled)
148 {
149 mEnabled = enabled;
150 }
151
152 /**
153 * Trigger the preprocessor chain for the specified item.
154 * The item should have been added to the Akonadi database via
155 * the specified DataStore object. If the DataStore is in a
156 * transaction then this class will put the item in a wait
157 * queue until the transaction is committed. If the transaction
158 * is rolled back the whole wait queue will be discarded.
159 * If the DataStore is not in a transaction then the item
160 * will be pushed directly to the preprocessing chain.
161 *
162 * You should make sure that the preprocessor chain isActive()
163 * before calling this method. The items you pass to this method,
164 * also, should have the hidden attribute set.
165 *
166 * This function is thread-safe.
167 */
168 void beginHandleItem(const PimItem &item, const DataStore *dataStore);
169
170 /**
171 * This is called via D-Bus from AgentManager to register a preprocessor instance.
172 *
173 * This function is thread-safe.
174 */
175 void registerInstance(const QString &id);
176
177 /**
178 * This is called via D-Bus from AgentManager to unregister a preprocessor instance.
179 *
180 * This function is thread-safe.
181 */
182 void unregisterInstance(const QString &id);
183
184protected:
185 /**
186 * This is called by PreprocessorInstance to signal that a certain preprocessor has finished
187 * handling an item.
188 *
189 * This function is thread-safe.
190 */
192
193private:
194 /**
195 * Finds the preprocessor instance by its identifier.
196 *
197 * This must be called with mMutex locked.
198 */
199 PreprocessorInstance *lockedFindInstance(const QString &id);
200
201 /**
202 * Pushes the specified item to the first preprocessor.
203 * The caller *MUST* make sure that there is at least one preprocessor in the chain.
204 */
205 void lockedActivateFirstPreprocessor(qint64 itemId);
206
207 /**
208 * This is called internally to terminate the pre-processing
209 * chain for the specified Item. All the preprocessors have
210 * been triggered for it.
211 *
212 * This must be called with mMutex locked.
213 */
214 void lockedEndHandleItem(qint64 itemId);
215
216 /**
217 * This is the unprotected core of the unregisterInstance() function above.
218 */
219 void lockedUnregisterInstance(const QString &id);
220
221 /**
222 * Kill the wait queue for the specific DataStore object.
223 */
224 void lockedKillWaitQueue(const DataStore *dataStore, bool disconnectSlots);
225
226private Q_SLOTS:
227
228 /**
229 * Connected to the mHeartbeatTimer. Triggered every minute or something like that :D
230 * Mainly used to expire preprocessor jobs.
231 */
232 void heartbeat();
233
234 /**
235 * This is used to handle database transactions and wait queues.
236 * The call to this slot usually comes from a queued signal/slot connection
237 * (i.e. from the *Append handler thread).
238 */
239 void dataStoreDestroyed();
240
241 /**
242 * This is used to handle database transactions and wait queues.
243 * The call to this slot usually comes from a queued signal/slot connection
244 * (i.e. from the *Append handler thread).
245 */
246 void dataStoreTransactionCommitted();
247
248 /**
249 * This is used to handle database transactions and wait queues.
250 * The call to this slot usually comes from a queued signal/slot connection
251 * (i.e. from the *Append handler thread).
252 */
253 void dataStoreTransactionRolledBack();
254
255}; // class PreprocessorManager
256
257} // namespace Server
258} // namespace Akonadi
This class handles all the database access.
Definition datastore.h:95
A single preprocessor (agent) instance.
The manager for preprocessor agents.
void setEnabled(bool enabled)
Explicitly enables or disables the preprocessing in this Akonadi server.
void unregisterInstance(const QString &id)
This is called via D-Bus from AgentManager to unregister a preprocessor instance.
void preProcessorFinishedHandlingItem(PreprocessorInstance *preProcessor, qint64 itemId)
This is called by PreprocessorInstance to signal that a certain preprocessor has finished handling an...
QList< PreprocessorInstance * > mPreprocessorChain
The preprocessor chain.
bool isActive()
Returns true if preprocessing is active in this Akonadi server.
bool mEnabled
Is preprocessing enabled at all in this Akonadi server instance? This is true by default and can be s...
void beginHandleItem(const PimItem &item, const DataStore *dataStore)
Trigger the preprocessor chain for the specified item.
PreprocessorManager(Tracer &tracer)
Creates an instance of PreprocessorManager.
~PreprocessorManager() override
Destroys the instance of PreprocessorManager and frees all the relevant resources.
bool isEnabled() const
Returns true if this preprocessor hasn't been explicitly disabled via setEnabled( false ).
void registerInstance(const QString &id)
This is called via D-Bus from AgentManager to register a preprocessor instance.
QHash< const DataStore *, std::deque< qint64 > * > mTransactionWaitQueueHash
The hashtable of transaction wait queues.
QMutex mMutex
The mutex used to protect the internals of this class (mainly the mPreprocessorChain member).
QTimer * mHeartbeatTimer
The heartbeat timer.
The global tracer instance where all akonadi components can send their tracing information to.
Definition tracer.h:38
Helper integration between Akonadi and Qt.
Q_CLASSINFO(Name, Value)
Q_OBJECTQ_OBJECT
Q_SLOTSQ_SLOTS
T qobject_cast(QObject *object)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jun 21 2024 11:57:49 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.