Commit e454b09c authored by Daniel Vrátil's avatar Daniel Vrátil 🤖
Browse files

Remove singleton from the Tracer

parent dfa0e118
......@@ -59,8 +59,8 @@ class CollectionStatisticsTest : public QObject
{
Q_OBJECT
std::unique_ptr<DbInitializer> dbInitializer;
FakeAkonadiServer mAkonadi;
std::unique_ptr<DbInitializer> dbInitializer;
public:
CollectionStatisticsTest()
{
......
......@@ -221,7 +221,8 @@ void FakeAkonadiServer::initFake()
throw FakeAkonadiServerException("Failed to initialize datastore");
}
mPreprocessorManager = std::make_unique<PreprocessorManager>();
mTracer = std::make_unique<Tracer>();
mPreprocessorManager = std::make_unique<PreprocessorManager>(*this);
mPreprocessorManager->setEnabled(false);
mSearchManager = std::make_unique<FakeSearchManager>(*this);
mCollectionStats = std::make_unique<CollectionStatistics>();
......@@ -251,10 +252,12 @@ bool FakeAkonadiServer::quit()
qDebug() << "Skipping clean up of" << basePath();
}
mConnection.reset();
mClient.reset();
mPreprocessorManager.reset();
mCollectionStats.reset();
mSearchManager.reset();
mCollectionStats.reset();
mItemRetrieval.reset();
mIntervalCheck.reset();
......@@ -264,6 +267,9 @@ bool FakeAkonadiServer::quit()
mIntervalCheck.reset();
// Tracer should go last
mTracer.reset();
qDebug() << "==== Fake Akonadi Server shut down ====";
return true;
}
......
......@@ -208,12 +208,11 @@ bool AkonadiServer::init()
return false;
}
Tracer::self();
new DebugInterface(this);
mResourceManager = std::make_unique<ResourceManager>();
mTracer = std::make_unique<Tracer>();
mDebugInterface = std::make_unique<DebugInterface>(*this);
mResourceManager = std::make_unique<ResourceManager>(*this);
mCollectionStats = std::make_unique<CollectionStatistics>();
mPreprocessorManager = std::make_unique<PreprocessorManager>();
mPreprocessorManager = std::make_unique<PreprocessorManager>(*this);
// Forcibly disable it if configuration says so
if (settings.value(QStringLiteral("General/DisablePreprocessing"), false).toBool()) {
......@@ -278,6 +277,7 @@ bool AkonadiServer::quit()
mConnections.clear();
qCDebug(AKONADISERVER_LOG) << "terminating service threads";
mDebugInterface.reset();
mResourceManager.reset();
mCacheCleaner.reset();
mIntervalCheck.reset();
......@@ -288,6 +288,7 @@ bool AkonadiServer::quit()
mNotificationManager.reset();
mCollectionStats.reset();
mPreprocessorManager.reset();
mTracer.reset();
if (DbConfig::isConfigured()) {
if (DataStore::hasDataStore()) {
......@@ -444,6 +445,11 @@ ItemRetrievalManager &AkonadiServer::itemRetrievalManager()
return *mItemRetrieval.get();
}
Tracer &AkonadiServer::tracer()
{
return *mTracer.get();
}
QString AkonadiServer::serverPath() const
{
return StandardDirs::saveDir("config");
......
......@@ -47,6 +47,8 @@ class NotificationManager;
class ResourceManager;
class CollectionStatistics;
class PreprocessorManager;
class Tracer;
class DebugInterface;
class AkonadiServer : public QObject
{
......@@ -78,6 +80,8 @@ public:
ItemRetrievalManager &itemRetrievalManager();
Tracer &tracer();
/**
* Instance-aware server .config directory
*/
......@@ -116,6 +120,7 @@ protected:
std::unique_ptr<AkLocalServer> mNtfServer;
std::unique_ptr<ResourceManager> mResourceManager;
std::unique_ptr<DebugInterface> mDebugInterface;
std::unique_ptr<CollectionStatistics> mCollectionStats;
std::unique_ptr<PreprocessorManager> mPreprocessorManager;
std::unique_ptr<NotificationManager> mNotificationManager;
......@@ -125,6 +130,7 @@ protected:
std::unique_ptr<ItemRetrievalManager> mItemRetrieval;
std::unique_ptr<SearchTaskManager> mAgentSearchManager;
std::unique_ptr<SearchManager> mSearchManager;
std::unique_ptr<Tracer> mTracer;
std::vector<std::unique_ptr<Connection>> mConnections;
bool mAlreadyShutdown = false;
......
......@@ -117,7 +117,7 @@ void Connection::quit()
return;
}
Tracer::self()->endConnection(m_identifier, QString());
m_akonadi.tracer().endConnection(m_identifier, QString());
delete m_socket;
m_socket = nullptr;
......@@ -260,8 +260,8 @@ void Connection::handleIncomingData()
// Tag context and collection context is not persistent.
m_context.setTag(nullopt);
m_context.setCollection({});
if (Tracer::self()->currentTracer() != QLatin1String("null")) {
Tracer::self()->connectionInput(m_identifier, tag, cmd);
if (m_akonadi.tracer().currentTracer() != QLatin1String("null")) {
m_akonadi.tracer().connectionInput(m_identifier, tag, cmd);
}
m_currentHandler = findHandlerForCommand(cmd->type());
......@@ -419,7 +419,7 @@ void Connection::setState(ConnectionState state)
void Connection::setSessionId(const QByteArray &id)
{
m_identifier = QString::asprintf("%s (%p)", id.data(), static_cast<void *>(this));
Tracer::self()->beginConnection(m_identifier, QString());
m_akonadi.tracer().beginConnection(m_identifier, QString());
//m_streamParser->setTracerIdentifier(m_identifier);
m_sessionId = id;
......@@ -488,8 +488,8 @@ void Connection::reportTime() const
void Connection::sendResponse(qint64 tag, const Protocol::CommandPtr &response)
{
if (Tracer::self()->currentTracer() != QLatin1String("null")) {
Tracer::self()->connectionOutput(m_identifier, tag, response);
if (m_akonadi.tracer().currentTracer() != QLatin1String("null")) {
m_akonadi.tracer().connectionOutput(m_identifier, tag, response);
}
Protocol::DataStream stream(m_socket);
stream << tag;
......
......@@ -25,6 +25,7 @@
#include <QLocalSocket>
#include <QElapsedTimer>
#include "akonadi.h"
#include "akthread.h"
#include "entities.h"
#include "global.h"
......@@ -45,7 +46,6 @@ class Handler;
class Response;
class DataStore;
class Collection;
class AkonadiServer;
/**
An Connection represents one connection of a client to the server.
......@@ -153,8 +153,8 @@ template<typename T>
inline typename std::enable_if<std::is_base_of<Protocol::Command, T>::value>::type
Connection::sendResponse(qint64 tag, T &&response)
{
if (Tracer::self()->currentTracer() != QLatin1String("null")) {
Tracer::self()->connectionOutput(m_identifier, tag, response);
if (m_akonadi.tracer().currentTracer() != QLatin1String("null")) {
m_akonadi.tracer().connectionOutput(m_identifier, tag, response);
}
Protocol::DataStream stream(m_socket);
stream << tag;
......
......@@ -30,9 +30,7 @@ DBusTracer::DBusTracer()
QDBusConnection::sessionBus().registerObject(QStringLiteral("/tracing/notifications"), this, QDBusConnection::ExportAdaptors);
}
DBusTracer::~DBusTracer()
{
}
DBusTracer::~DBusTracer() = default;
void DBusTracer::beginConnection(const QString &identifier, const QString &msg)
{
......
......@@ -20,13 +20,15 @@
#include "debuginterface.h"
#include "debuginterfaceadaptor.h"
#include "tracer.h"
#include "akonadi.h"
#include <QDBusConnection>
using namespace Akonadi::Server;
DebugInterface::DebugInterface(QObject *parent)
: QObject(parent)
DebugInterface::DebugInterface(AkonadiServer &akonadi)
: QObject()
, m_akonadi(akonadi)
{
new DebugInterfaceAdaptor(this);
QDBusConnection::sessionBus().registerObject(QStringLiteral("/debug"),
......@@ -35,10 +37,10 @@ DebugInterface::DebugInterface(QObject *parent)
QString DebugInterface::tracer() const
{
return Tracer::self()->currentTracer();
return m_akonadi.tracer().currentTracer();
}
void DebugInterface::setTracer(const QString &tracer)
{
Tracer::self()->activateTracer(tracer);
m_akonadi.tracer().activateTracer(tracer);
}
......@@ -27,6 +27,8 @@ namespace Akonadi
namespace Server
{
class AkonadiServer;
/**
* Interface to configure and query debugging options.
*/
......@@ -36,12 +38,14 @@ class DebugInterface : public QObject
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Akonadi.DebugInterface")
public:
explicit DebugInterface(QObject *parent = nullptr);
explicit DebugInterface(AkonadiServer &akonadi);
public Q_SLOTS:
Q_SCRIPTABLE QString tracer() const;
Q_SCRIPTABLE void setTracer(const QString &tracer);
private:
AkonadiServer &m_akonadi;
};
} // namespace Server
......
......@@ -24,15 +24,12 @@
using namespace Akonadi::Server;
FileTracer::FileTracer(const QString &fileName)
: m_file(fileName)
{
m_file = new QFile(fileName);
m_file->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
m_file.open(QIODevice::WriteOnly | QIODevice::Unbuffered);
}
FileTracer::~FileTracer()
{
delete m_file;
}
FileTracer::~FileTracer() = default;
void FileTracer::beginConnection(const QString &identifier, const QString &msg)
{
......@@ -72,5 +69,5 @@ void FileTracer::error(const QString &componentName, const QString &msg)
void FileTracer::output(const QString &id, const QString &msg)
{
QString output = QStringLiteral("%1: %2: %3\r\n").arg(QTime::currentTime().toString(QStringLiteral("HH:mm:ss.zzz")), id, msg.left(msg.indexOf(QLatin1Char('\n'))));
m_file->write(output.toUtf8());
m_file.write(output.toUtf8());
}
......@@ -21,7 +21,8 @@
#define AKONADI_FILETRACER_H
#include "tracerinterface.h"
class QFile;
#include <QFile>
namespace Akonadi
{
......@@ -49,7 +50,7 @@ public:
private:
void output(const QString &id, const QString &msg);
QFile *m_file = nullptr;
QFile m_file;
};
} // namespace Server
......
......@@ -33,9 +33,7 @@ namespace Server
class NullTracer : public TracerInterface
{
public:
~NullTracer() override
{
}
~NullTracer() override = default;
void beginConnection(const QString &identifier, const QString &msg) override {
Q_UNUSED(identifier);
......
......@@ -40,9 +40,10 @@
using namespace Akonadi;
using namespace Akonadi::Server;
PreprocessorInstance::PreprocessorInstance(const QString &id, PreprocessorManager &manager)
PreprocessorInstance::PreprocessorInstance(const QString &id, PreprocessorManager &manager, Tracer &tracer)
: QObject()
, mManager(manager)
, mTracer(tracer)
, mId(id)
{
Q_ASSERT(!id.isEmpty());
......@@ -64,7 +65,7 @@ bool PreprocessorInstance::init()
this);
if (!mInterface || !mInterface->isValid()) {
Tracer::self()->warning(
mTracer.warning(
QStringLiteral("PreprocessorInstance"),
QStringLiteral("Could not connect to pre-processor instance '%1': %2")
.arg(mId,
......@@ -160,7 +161,7 @@ bool PreprocessorInstance::abortProcessing()
this);
if (!iface.isValid()) {
Tracer::self()->warning(
mTracer.warning(
QStringLiteral("PreprocessorInstance"),
QStringLiteral("Could not connect to pre-processor instance '%1': %2")
.arg(mId, iface.lastError().message()));
......@@ -186,7 +187,7 @@ bool PreprocessorInstance::invokeRestart()
this);
if (!iface.isValid()) {
Tracer::self()->warning(
mTracer.warning(
QStringLiteral("PreprocessorInstance"),
QStringLiteral("Could not connect to the AgentManager in order to restart pre-processor instance '%1': %2")
.arg(mId, iface.lastError().message()));
......@@ -204,7 +205,7 @@ void PreprocessorInstance::itemProcessed(qlonglong id)
// We shouldn't be called if there are no items in the queue
if (mItemQueue.empty()) {
Tracer::self()->warning(
mTracer.warning(
QStringLiteral("PreprocessorInstance"),
QStringLiteral("Pre-processor instance '%1' emitted itemProcessed(%2) but we actually have no item in the queue")
.arg(mId)
......@@ -219,7 +220,7 @@ void PreprocessorInstance::itemProcessed(qlonglong id)
qlonglong itemId = mItemQueue.front();
if (itemId != id) {
Tracer::self()->warning(
mTracer.warning(
QStringLiteral("PreprocessorInstance"),
QStringLiteral("Pre-processor instance '%1' emitted itemProcessed(%2) but the head item in the queue has id %3")
.arg(mId)
......
......@@ -39,6 +39,7 @@ namespace Server
class PreprocessorManager;
class AgentInstance;
class Tracer;
/**
* A single preprocessor (agent) instance.
......@@ -60,7 +61,7 @@ protected:
/**
* Create an instance of a PreprocessorInstance descriptor.
*/
PreprocessorInstance(const QString &id, PreprocessorManager &manager);
PreprocessorInstance(const QString &id, PreprocessorManager &manager, Tracer &tracer);
public: // This is public only for qDeleteAll() called from PreprocessorManager
// ...for some reason couldn't convince gcc to have it as friend...
......@@ -72,6 +73,7 @@ public: // This is public only for qDeleteAll() called from PreprocessorManager
private:
PreprocessorManager &mManager;
Tracer &mTracer;
/**
* The internal queue if item identifiers.
......
......@@ -25,6 +25,7 @@
#include "preprocessormanager.h"
#include "akonadiserver_debug.h"
#include "akonadi.h"
#include "entities.h" // Akonadi::Server::PimItem
#include "storage/datastore.h"
#include "tracer.h"
......@@ -55,10 +56,10 @@ const int gDeadlineItemProcessingTimeInSecs = 240;
using namespace Akonadi::Server;
// The one and only PreprocessorManager object
PreprocessorManager::PreprocessorManager()
PreprocessorManager::PreprocessorManager(AkonadiServer &akonadi)
: QObject()
, mEnabled(true)
, mMutex(new QMutex())
, mAkonadi(akonadi)
{
// Hook in our D-Bus interface "shell".
new PreprocessorManagerAdaptor(this);
......@@ -85,13 +86,11 @@ PreprocessorManager::~PreprocessorManager()
qDeleteAll(mPreprocessorChain);
qDeleteAll(mTransactionWaitQueueHash); // this should also disconnect all the signals from the data store objects...
delete mMutex;
}
bool PreprocessorManager::isActive()
{
QMutexLocker locker(mMutex);
QMutexLocker locker(&mMutex);
if (!mEnabled) {
return false;
......@@ -112,7 +111,7 @@ PreprocessorInstance *PreprocessorManager::lockedFindInstance(const QString &id)
void PreprocessorManager::registerInstance(const QString &id)
{
QMutexLocker locker(mMutex);
QMutexLocker locker(&mMutex);
qCDebug(AKONADISERVER_LOG) << "PreprocessorManager::registerInstance(" << id << ")";
......@@ -125,9 +124,9 @@ void PreprocessorManager::registerInstance(const QString &id)
// TODO: Maybe we need some kind of ordering here ?
// In that case we'll need to fiddle with the items that are currently enqueued for processing...
instance = new PreprocessorInstance(id, *this);
instance = new PreprocessorInstance(id, *this, mAkonadi.tracer());
if (!instance->init()) {
Tracer::self()->warning(
mAkonadi.tracer().warning(
QStringLiteral("PreprocessorManager"),
QStringLiteral("Could not initialize preprocessor instance '%1'")
.arg(id));
......@@ -142,7 +141,7 @@ void PreprocessorManager::registerInstance(const QString &id)
void PreprocessorManager::unregisterInstance(const QString &id)
{
QMutexLocker locker(mMutex);
QMutexLocker locker(&mMutex);
qCDebug(AKONADISERVER_LOG) << "PreprocessorManager::unregisterInstance(" << id << ")";
......@@ -190,7 +189,7 @@ void PreprocessorManager::beginHandleItem(const PimItem &item, const DataStore *
Q_ASSERT(item.isValid());
// This is the entry point of the pre-processing chain.
QMutexLocker locker(mMutex);
QMutexLocker locker(&mMutex);
if (!mEnabled) {
// Preprocessing is disabled: immediately end handling the item.
......@@ -283,7 +282,7 @@ void PreprocessorManager::lockedKillWaitQueue(const DataStore *dataStore, bool d
void PreprocessorManager::dataStoreDestroyed()
{
QMutexLocker locker(mMutex);
QMutexLocker locker(&mMutex);
qCDebug(AKONADISERVER_LOG) << "PreprocessorManager::dataStoreDestroyed(): killing the wait queue";
......@@ -298,7 +297,7 @@ void PreprocessorManager::dataStoreDestroyed()
void PreprocessorManager::dataStoreTransactionCommitted()
{
QMutexLocker locker(mMutex);
QMutexLocker locker(&mMutex);
qCDebug(AKONADISERVER_LOG) << "PreprocessorManager::dataStoreTransactionCommitted(): pushing items in wait queue to the preprocessing chain";
......@@ -330,7 +329,7 @@ void PreprocessorManager::dataStoreTransactionCommitted()
void PreprocessorManager::dataStoreTransactionRolledBack()
{
QMutexLocker locker(mMutex);
QMutexLocker locker(&mMutex);
qCDebug(AKONADISERVER_LOG) << "PreprocessorManager::dataStoreTransactionRolledBack(): killing the wait queue";
......@@ -345,7 +344,7 @@ void PreprocessorManager::dataStoreTransactionRolledBack()
void PreprocessorManager::preProcessorFinishedHandlingItem(PreprocessorInstance *preProcessor, qint64 itemId)
{
QMutexLocker locker(mMutex);
QMutexLocker locker(&mMutex);
int idx = mPreprocessorChain.indexOf(preProcessor);
Q_ASSERT(idx >= 0); // must be there!
......@@ -386,7 +385,7 @@ void PreprocessorManager::lockedEndHandleItem(qint64 itemId)
#endif
if (!DataStore::self()->unhidePimItem(item)) {
Tracer::self()->warning(
mAkonadi.tracer().warning(
QStringLiteral("PreprocessorManager"),
QStringLiteral("Failed to unhide the PIM item '%1': data is not lost but a server restart is required in order to unhide it")
.arg(itemId));
......@@ -395,7 +394,7 @@ void PreprocessorManager::lockedEndHandleItem(qint64 itemId)
void PreprocessorManager::heartbeat()
{
QMutexLocker locker(mMutex);
QMutexLocker locker(&mMutex);
// Loop through the processor instances and check their current processing time.
......@@ -424,7 +423,7 @@ void PreprocessorManager::heartbeat()
if (elapsedTime < gMaximumItemProcessingTimeInSecs) {
// Kindly ask the preprocessor to abort the job.
Tracer::self()->warning(
mAkonadi.tracer().warning(
QStringLiteral("PreprocessorManager"),
QStringLiteral("Preprocessor '%1' seems to be stuck... trying to abort its job.")
.arg(instance->id()));
......@@ -438,7 +437,7 @@ void PreprocessorManager::heartbeat()
if (elapsedTime < gDeadlineItemProcessingTimeInSecs) {
// Attempt to restart the preprocessor via AgentManager interface
Tracer::self()->warning(
mAkonadi.tracer().warning(
QStringLiteral("PreprocessorManager"),
QStringLiteral("Preprocessor '%1' is stuck... trying to restart it")
.arg(instance->id()));
......@@ -449,7 +448,7 @@ void PreprocessorManager::heartbeat()
// If we're here then invokeRestart() failed.
}
Tracer::self()->warning(
mAkonadi.tracer().warning(
QStringLiteral("PreprocessorManager"),
QStringLiteral("Preprocessor '%1' is broken... ignoring it from now on")
.arg(instance->id()));
......
......@@ -28,11 +28,11 @@
#include <QObject>
#include <QList>
#include <QHash>
#include <QMutex>
#include <deque>
class QTimer;
class QMutex;
#include "preprocessorinstance.h"
......@@ -43,6 +43,7 @@ namespace Server
class PimItem;
class DataStore;
class AkonadiServer;
/**
* \class PreprocessorManager
......@@ -96,24 +97,26 @@ protected:
* This is true by default and can be set via setEnabled().
* Mainly used to disable preprocessing via configuration file.
*/
bool mEnabled;
bool mEnabled = false;
/**
* The mutex used to protect the internals of this class (mainly
* the mPreprocessorChain member).
*/
QMutex *mMutex = nullptr;
QMutex mMutex;
/**
* The heartbeat timer. Used mainly to expire preprocessor jobs.
*/
QTimer *mHeartbeatTimer = nullptr;
AkonadiServer &mAkonadi;
public:
/**
* Creates an instance of PreprocessorManager
*/
explicit PreprocessorManager();
explicit PreprocessorManager(AkonadiServer &akonadi);
/**
* Destroys the instance of PreprocessorManager
......
......@@ -18,6 +18,7 @@
*/
#include "resourcemanager.h"
#include "akonadi.h"
#include "tracer.h"
#include "storage/datastore.h"
#include "storage/transaction.h"
......@@ -31,8 +32,9 @@
using namespace Akonadi::Server;
using namespace AkRanges;
ResourceManager::ResourceManager()
ResourceManager::ResourceManager(AkonadiServer &akonadi)
: QObject()
, mAkonadi(akonadi)
{
new ResourceManagerAdaptor(this);
QDBusConnection::sessionBus().registerObject(QStringLiteral("/ResourceManager"), this);
......@@ -43,7 +45,7 @@ void ResourceManager::addResourceInstance(const QString &name, const QStringList
Transaction transaction(DataStore::self(), QStringLiteral("ADD RESOURCE INSTANCE"));
Resource resource = Resource::retrieveByName(name);
if (resource.isValid()) {
Tracer::self()->error("ResourceManager", QStringLiteral("Resource '%1' already exists.").arg(name));
mAkonadi.tracer().error("ResourceManager", QStringLiteral("Resource '%1' already exists.").arg(name));
return; // resource already exists
}
......@@ -51,7 +53,7 @@ void ResourceManager::addResourceInstance(const QString &name, const QStringList
resource.setName(