Akonadi

preprocessorinstance.cpp
1 /******************************************************************************
2  *
3  * File : preprocessorinstance.cpp
4  * Creation date : Sat 18 Jul 2009 02:50:39
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 #include "preprocessorinstance.h"
13 #include "akonadiserver_debug.h"
14 #include "preprocessorinterface.h"
15 #include "preprocessormanager.h"
16 
17 #include "entities.h"
18 
19 #include "agentcontrolinterface.h"
20 #include "agentmanagerinterface.h"
21 
22 #include "tracer.h"
23 
24 #include <private/dbus_p.h>
25 
26 using namespace Akonadi;
27 using namespace Akonadi::Server;
28 
30  : mManager(manager)
31  , mTracer(tracer)
32  , mId(id)
33 {
34  Q_ASSERT(!id.isEmpty());
35 }
36 
38 
40 {
41  Q_ASSERT(!mBusy); // must be called very early
42  Q_ASSERT(!mInterface);
43 
44  mInterface = new OrgFreedesktopAkonadiPreprocessorInterface(DBus::agentServiceName(mId, DBus::Preprocessor),
45  QStringLiteral("/Preprocessor"),
47  this);
48 
49  if (!mInterface || !mInterface->isValid()) {
50  mTracer.warning(
51  QStringLiteral("PreprocessorInstance"),
52  QStringLiteral("Could not connect to pre-processor instance '%1': %2").arg(mId, mInterface ? mInterface->lastError().message() : QString()));
53  delete mInterface;
54  mInterface = nullptr;
55  return false;
56  }
57 
58  QObject::connect(mInterface, &OrgFreedesktopAkonadiPreprocessorInterface::itemProcessed, this, &PreprocessorInstance::itemProcessed);
59 
60  return true;
61 }
62 
64 {
65  qCDebug(AKONADISERVER_LOG) << "PreprocessorInstance::enqueueItem(" << itemId << ")";
66 
67  mItemQueue.push_back(itemId);
68 
69  // If the preprocessor is already busy processing another item then do nothing.
70  if (mBusy) {
71  // The "head" item is the one being processed and we have just added another one.
72  Q_ASSERT(mItemQueue.size() > 1);
73  return;
74  }
75 
76  // Not busy: handle the item.
77  processHeadItem();
78 }
79 
80 void PreprocessorInstance::processHeadItem()
81 {
82  // We shouldn't be called if there are no items in the queue
83  Q_ASSERT(!mItemQueue.empty());
84  // We shouldn't be here with no interface
85  Q_ASSERT(mInterface);
86 
87  qint64 itemId = mItemQueue.front();
88 
89  // Fetch the actual item data (as it may have changed since it was enqueued)
90  // The fetch will hit the cache if the item wasn't changed.
91 
92  PimItem actualItem = PimItem::retrieveById(itemId);
93 
94  while (!actualItem.isValid()) {
95  // hum... item is gone ?
96  mManager.preProcessorFinishedHandlingItem(this, itemId);
97 
98  mItemQueue.pop_front();
99  if (mItemQueue.empty()) {
100  // nothing more to process for this instance: jump out
101  mBusy = false;
102  return;
103  }
104 
105  // try the next one in the queue
106  itemId = mItemQueue.front();
107  actualItem = PimItem::retrieveById(itemId);
108  }
109 
110  // Ok.. got a valid item to process: collection and mimetype is known.
111 
112  qCDebug(AKONADISERVER_LOG) << "PreprocessorInstance::processHeadItem(): about to begin processing item " << itemId;
113 
114  mBusy = true;
115 
116  mItemProcessingStartDateTime = QDateTime::currentDateTime();
117 
118  // The beginProcessItem() D-Bus call is asynchronous (marked with NoReply attribute)
119  mInterface->beginProcessItem(itemId, actualItem.collectionId(), actualItem.mimeType().name());
120 
121  qCDebug(AKONADISERVER_LOG) << "PreprocessorInstance::processHeadItem(): processing started for item " << itemId;
122 }
123 
125 {
126  if (!mBusy) {
127  return -1; // nothing being processed
128  }
129 
130  return mItemProcessingStartDateTime.secsTo(QDateTime::currentDateTime());
131 }
132 
134 {
135  Q_ASSERT_X(mBusy, "PreprocessorInstance::abortProcessing()", "You shouldn't call this method when isBusy() returns false");
136 
137  OrgFreedesktopAkonadiAgentControlInterface iface(DBus::agentServiceName(mId, DBus::Agent), QStringLiteral("/"), QDBusConnection::sessionBus(), this);
138 
139  if (!iface.isValid()) {
140  mTracer.warning(QStringLiteral("PreprocessorInstance"),
141  QStringLiteral("Could not connect to pre-processor instance '%1': %2").arg(mId, iface.lastError().message()));
142  return false;
143  }
144 
145  // We don't check the return value.. as this is a "warning"
146  // The preprocessor manager will check again in a while and eventually
147  // terminate the agent at all...
148  iface.abort();
149 
150  return true;
151 }
152 
154 {
155  Q_ASSERT_X(mBusy, "PreprocessorInstance::invokeRestart()", "You shouldn't call this method when isBusy() returns false");
156 
157  OrgFreedesktopAkonadiAgentManagerInterface iface(DBus::serviceName(DBus::Control), QStringLiteral("/AgentManager"), QDBusConnection::sessionBus(), this);
158 
159  if (!iface.isValid()) {
160  mTracer.warning(
161  QStringLiteral("PreprocessorInstance"),
162  QStringLiteral("Could not connect to the AgentManager in order to restart pre-processor instance '%1': %2").arg(mId, iface.lastError().message()));
163  return false;
164  }
165 
166  iface.restartAgentInstance(mId);
167 
168  return true;
169 }
170 
171 void PreprocessorInstance::itemProcessed(qlonglong id)
172 {
173  qCDebug(AKONADISERVER_LOG) << "PreprocessorInstance::itemProcessed(" << id << ")";
174 
175  // We shouldn't be called if there are no items in the queue
176  if (mItemQueue.empty()) {
177  mTracer.warning(QStringLiteral("PreprocessorInstance"),
178  QStringLiteral("Pre-processor instance '%1' emitted itemProcessed(%2) but we actually have no item in the queue").arg(mId).arg(id));
179  mBusy = false;
180  return; // preprocessor is buggy (FIXME: What now ?)
181  }
182 
183  // We should be busy now: this is more likely our fault, not the preprocessor's one.
184  Q_ASSERT(mBusy);
185 
186  qlonglong itemId = mItemQueue.front();
187 
188  if (itemId != id) {
189  mTracer.warning(
190  QStringLiteral("PreprocessorInstance"),
191  QStringLiteral("Pre-processor instance '%1' emitted itemProcessed(%2) but the head item in the queue has id %3").arg(mId).arg(id).arg(itemId));
192 
193  // FIXME: And what now ?
194  }
195 
196  mItemQueue.pop_front();
197 
198  mManager.preProcessorFinishedHandlingItem(this, itemId);
199 
200  if (mItemQueue.empty()) {
201  // Nothing more to do
202  mBusy = false;
203  return;
204  }
205 
206  // Stay busy and process next item in the queue
207  processHeadItem();
208 }
bool init()
This is called by PreprocessorManager just after the construction in order to connect to the preproce...
bool invokeRestart()
Attempts to invoke the preprocessor slave restart via AgentManager.
~PreprocessorInstance() override
Destroy this instance of the PreprocessorInstance descriptor.
QDateTime currentDateTime()
The global tracer instance where all akonadi components can send their tracing information to.
Definition: tracer.h:37
PreprocessorInstance(const QString &id, PreprocessorManager &manager, Tracer &tracer)
Create an instance of a PreprocessorInstance descriptor.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QDBusConnection sessionBus()
void warning(const QString &componentName, const QString &msg) override
This method is called whenever a component wants to output a warning.
Definition: tracer.cpp:117
qint64 secsTo(const QDateTime &other) const const
bool abortProcessing()
Attempts to abort the processing of the current item.
void enqueueItem(qint64 itemId)
This is called by PreprocessorManager to enqueue a PimItem for processing by this preprocessor instan...
qint64 currentProcessingTime()
Returns the time in seconds elapsed since the current item was submitted to the slave preprocessor in...
void preProcessorFinishedHandlingItem(PreprocessorInstance *preProcessor, qint64 itemId)
This is called by PreprocessorInstance to signal that a certain preprocessor has finished handling an...
Helper integration between Akonadi and Qt.
The manager for preprocessor agents.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jul 2 2022 06:41:48 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.