Commit 66c8f9ae authored by Ivan Čukić's avatar Ivan Čukić 👁
Browse files

Allowing KAMD to run without a database backend

Summary:
On systems without the support for shared memory which sqlite wal
can not run on, just disable the sqlite plugin instead of killing KAMD.

Also, before we have a proper way to handle database corruption,
this will at least allow KAMD to be started in this case.

Reviewers: davidedmundson

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D12577
parent 6d12b52b
......@@ -181,7 +181,7 @@ Database::Ptr Database::instance(Source source, OpenMode openMode)
ptr->d->database.reset(new QSqlDatabaseWrapper(info));
if (!ptr->d->database->isOpen()) {
return Q_NULLPTR;
return nullptr;
}
databases[info] = ptr;
......@@ -202,9 +202,10 @@ Database::Ptr Database::instance(Source source, OpenMode openMode)
auto walResult = ptr->pragma(QStringLiteral("journal_mode = WAL"));
if (walResult != "wal") {
qFatal("KActivities: Database can not be opened in WAL mode. Check the "
"SQLite version (required >3.7.0). And whether your filesystem "
"supports shared memory");
qWarning() << "KActivities: Database can not be opened in WAL mode. Check the "
"SQLite version (required >3.7.0). And whether your filesystem "
"supports shared memory";
return nullptr;
}
// We don't have a big database, lets flush the WAL when
......
......@@ -185,13 +185,20 @@ bool Application::Private::loadPlugin(const KPluginMetaData& plugin)
auto &modules = Module::get();
if (pluginInstance) {
pluginInstance->init(modules);
bool success = pluginInstance->init(modules);
pluginIds << plugin.pluginId();
plugins << pluginInstance;
if (success) {
pluginIds << plugin.pluginId();
plugins << pluginInstance;
qCDebug(KAMD_LOG_APPLICATION) << "[ OK ] loaded: " << plugin.pluginId();
return true;
qCDebug(KAMD_LOG_APPLICATION) << "[ OK ] loaded: " << plugin.pluginId();
return true;
} else {
qCWarning(KAMD_LOG_APPLICATION) << "[ FAILED ] init: " << plugin.pluginId() << loader.errorString();
// TODO: Show a notification for a plugin that failed to load
delete pluginInstance;
return false;
}
} else {
qCWarning(KAMD_LOG_APPLICATION) << "[ FAILED ] loading: " << plugin.pluginId() << loader.errorString();
......
......@@ -53,35 +53,13 @@ public:
};
Common::Database &resourcesDatabase()
Common::Database::Ptr resourcesDatabase()
{
static ResourcesDatabaseMigrator instance;
return *(instance.d->database);
}
void ResourcesDatabaseMigrator::migrateDatabase(const QString &newDatabaseFile) const
{
// Checking whether we need to transfer the KActivities/KDE4
// sqlite database file to the new location.
if (QFile(newDatabaseFile).exists()) {
return;
}
// Testing for kdehome
Kdelibs4Migration migration;
if (!migration.kdeHomeFound()) {
return;
}
QString oldDatabaseFile(
migration.locateLocal("data", "activitymanager/resources/database"));
if (!oldDatabaseFile.isEmpty()) {
QFile(oldDatabaseFile).copy(newDatabaseFile);
}
return instance.d->database;
}
ResourcesDatabaseMigrator::ResourcesDatabaseMigrator()
: d()
{
const QString databaseDir
= QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
......@@ -94,18 +72,13 @@ ResourcesDatabaseMigrator::ResourcesDatabaseMigrator()
qWarning() << "Database folder can not be created!";
}
const QString newDatabaseFile = databaseDir + QStringLiteral("database");
migrateDatabase(newDatabaseFile);
d->database = Common::Database::instance(
Common::Database::ResourcesDatabase,
Common::Database::ReadWrite);
Q_ASSERT_X(d->database, "SQLite plugin/Database constructor",
"Database could not be opened");
Common::ResourcesDatabaseSchema::initSchema(*d->database);
if (d->database) {
Common::ResourcesDatabaseSchema::initSchema(*d->database);
}
}
ResourcesDatabaseMigrator::~ResourcesDatabaseMigrator()
......
......@@ -33,6 +33,7 @@
// Local
#include <Debug.h>
#include <common/database/Database.h>
class QDateTime;
class QSqlDatabase;
......@@ -56,9 +57,9 @@ private:
D_PTR;
friend Common::Database &resourcesDatabase();
friend Common::Database::Ptr resourcesDatabase();
};
Common::Database &resourcesDatabase();
Common::Database::Ptr resourcesDatabase();
#endif // PLUGINS_SQLITE_RESOURCESDATABASE_H
......@@ -87,7 +87,7 @@ void ResourceLinking::LinkResourceToActivity(QString initiatingAgent,
"ResourceLinking::LinkResourceToActivity",
"Resource shoud not be empty");
Utils::prepare(resourcesDatabase(), linkResourceToActivityQuery,
Utils::prepare(*resourcesDatabase(), linkResourceToActivityQuery,
QStringLiteral(
"INSERT OR REPLACE INTO ResourceLink"
" (usedActivity, initiatingAgent, targettedResource) "
......@@ -98,7 +98,7 @@ void ResourceLinking::LinkResourceToActivity(QString initiatingAgent,
")"
));
DATABASE_TRANSACTION(resourcesDatabase());
DATABASE_TRANSACTION(*resourcesDatabase());
Utils::exec(Utils::FailOnError, *linkResourceToActivityQuery,
":usedActivity" , usedActivity,
......@@ -147,7 +147,7 @@ void ResourceLinking::UnlinkResourceFromActivity(QString initiatingAgent,
QSqlQuery *query = nullptr;
if (usedActivity == ":any") {
Utils::prepare(resourcesDatabase(), unlinkResourceFromAllActivitiesQuery,
Utils::prepare(*resourcesDatabase(), unlinkResourceFromAllActivitiesQuery,
QStringLiteral(
"DELETE FROM ResourceLink "
"WHERE "
......@@ -156,7 +156,7 @@ void ResourceLinking::UnlinkResourceFromActivity(QString initiatingAgent,
));
query = unlinkResourceFromAllActivitiesQuery.get();
} else {
Utils::prepare(resourcesDatabase(), unlinkResourceFromActivityQuery,
Utils::prepare(*resourcesDatabase(), unlinkResourceFromActivityQuery,
QStringLiteral(
"DELETE FROM ResourceLink "
"WHERE "
......@@ -167,7 +167,7 @@ void ResourceLinking::UnlinkResourceFromActivity(QString initiatingAgent,
query = unlinkResourceFromActivityQuery.get();
}
DATABASE_TRANSACTION(resourcesDatabase());
DATABASE_TRANSACTION(*resourcesDatabase());
Utils::exec(Utils::FailOnError, *query,
":usedActivity" , usedActivity,
......@@ -213,7 +213,7 @@ bool ResourceLinking::IsResourceLinkedToActivity(QString initiatingAgent,
"ResourceLinking::IsResourceLinkedToActivity",
"Resource shoud not be empty");
Utils::prepare(resourcesDatabase(), isResourceLinkedToActivityQuery,
Utils::prepare(*resourcesDatabase(), isResourceLinkedToActivityQuery,
QStringLiteral(
"SELECT * FROM ResourceLink "
"WHERE "
......
......@@ -38,13 +38,13 @@
class ResourceScoreCache::Queries {
private:
Queries()
: createResourceScoreCacheQuery(resourcesDatabase().createQuery())
, getResourceScoreCacheQuery(resourcesDatabase().createQuery())
, updateResourceScoreCacheQuery(resourcesDatabase().createQuery())
, getScoreAdditionQuery(resourcesDatabase().createQuery())
: createResourceScoreCacheQuery(resourcesDatabase()->createQuery())
, getResourceScoreCacheQuery(resourcesDatabase()->createQuery())
, updateResourceScoreCacheQuery(resourcesDatabase()->createQuery())
, getScoreAdditionQuery(resourcesDatabase()->createQuery())
{
Utils::prepare(resourcesDatabase(),
Utils::prepare(*resourcesDatabase(),
createResourceScoreCacheQuery, QStringLiteral(
"INSERT INTO ResourceScoreCache "
"VALUES (:usedActivity, :initiatingAgent, :targettedResource, "
......@@ -53,7 +53,7 @@ private:
":firstUpdate)"
));
Utils::prepare(resourcesDatabase(),
Utils::prepare(*resourcesDatabase(),
getResourceScoreCacheQuery, QStringLiteral(
"SELECT cachedScore, lastUpdate, firstUpdate FROM ResourceScoreCache "
"WHERE "
......@@ -62,7 +62,7 @@ private:
":targettedResource = targettedResource "
));
Utils::prepare(resourcesDatabase(),
Utils::prepare(*resourcesDatabase(),
updateResourceScoreCacheQuery, QStringLiteral(
"UPDATE ResourceScoreCache SET "
"cachedScore = :cachedScore, "
......@@ -73,7 +73,7 @@ private:
":targettedResource = targettedResource "
));
Utils::prepare(resourcesDatabase(),
Utils::prepare(*resourcesDatabase(),
getScoreAdditionQuery, QStringLiteral(
"SELECT start, end "
"FROM ResourceEvent "
......@@ -153,7 +153,7 @@ void ResourceScoreCache::update()
QDateTime currentTime = QDateTime::currentDateTime();
qreal score = 0;
DATABASE_TRANSACTION(resourcesDatabase());
DATABASE_TRANSACTION(*resourcesDatabase());
qDebug() << "Creating the cache for: " << d->resource;
......
......@@ -69,14 +69,15 @@ bool StatsPlugin::init(QHash<QString, QObject *> &modules)
{
Plugin::init(modules);
if (!resourcesDatabase()) {
return false;
}
m_activities = modules[QStringLiteral("activities")];
m_resources = modules[QStringLiteral("resources")];
m_resourceLinking->init();
// Initializing the database
resourcesDatabase();
connect(m_resources, SIGNAL(ProcessedResourceEvents(EventList)),
this, SLOT(addEvents(EventList)));
connect(m_resources, SIGNAL(RegisteredResourceMimetype(QString, QString)),
......@@ -165,7 +166,7 @@ void StatsPlugin::openResourceEvent(const QString &usedActivity,
detectResourceInfo(targettedResource);
Utils::prepare(resourcesDatabase(), openResourceEventQuery, QStringLiteral(
Utils::prepare(*resourcesDatabase(), openResourceEventQuery, QStringLiteral(
"INSERT INTO ResourceEvent"
" (usedActivity, initiatingAgent, targettedResource, start, end) "
"VALUES (:usedActivity, :initiatingAgent, :targettedResource, :start, :end)"
......@@ -195,7 +196,7 @@ void StatsPlugin::closeResourceEvent(const QString &usedActivity,
"StatsPlugin::closeResourceEvent",
"Resource shoud not be empty");
Utils::prepare(resourcesDatabase(), closeResourceEventQuery, QStringLiteral(
Utils::prepare(*resourcesDatabase(), closeResourceEventQuery, QStringLiteral(
"UPDATE ResourceEvent "
"SET end = :end "
"WHERE "
......@@ -236,7 +237,7 @@ void StatsPlugin::detectResourceInfo(const QString &_uri)
bool StatsPlugin::insertResourceInfo(const QString &uri)
{
Utils::prepare(resourcesDatabase(), getResourceInfoQuery, QStringLiteral(
Utils::prepare(*resourcesDatabase(), getResourceInfoQuery, QStringLiteral(
"SELECT targettedResource FROM ResourceInfo WHERE "
" targettedResource = :targettedResource "
));
......@@ -248,7 +249,7 @@ bool StatsPlugin::insertResourceInfo(const QString &uri)
return false;
}
Utils::prepare(resourcesDatabase(), insertResourceInfoQuery, QStringLiteral(
Utils::prepare(*resourcesDatabase(), insertResourceInfoQuery, QStringLiteral(
"INSERT INTO ResourceInfo( "
" targettedResource"
", title"
......@@ -276,9 +277,9 @@ void StatsPlugin::saveResourceTitle(const QString &uri, const QString &title,
{
insertResourceInfo(uri);
DATABASE_TRANSACTION(resourcesDatabase());
DATABASE_TRANSACTION(*resourcesDatabase());
Utils::prepare(resourcesDatabase(), saveResourceTitleQuery, QStringLiteral(
Utils::prepare(*resourcesDatabase(), saveResourceTitleQuery, QStringLiteral(
"UPDATE ResourceInfo SET "
" title = :title"
", autoTitle = :autoTitle "
......@@ -299,9 +300,9 @@ void StatsPlugin::saveResourceMimetype(const QString &uri,
{
insertResourceInfo(uri);
DATABASE_TRANSACTION(resourcesDatabase());
DATABASE_TRANSACTION(*resourcesDatabase());
Utils::prepare(resourcesDatabase(), saveResourceMimetypeQuery, QStringLiteral(
Utils::prepare(*resourcesDatabase(), saveResourceMimetypeQuery, QStringLiteral(
"UPDATE ResourceInfo SET "
" mimetype = :mimetype"
", autoMimetype = :autoMimetype "
......@@ -392,7 +393,7 @@ void StatsPlugin::addEvents(const EventList &events)
if (eventsToProcess.begin() == eventsToProcess.end()) return;
DATABASE_TRANSACTION(resourcesDatabase());
DATABASE_TRANSACTION(*resourcesDatabase());
for (auto event : eventsToProcess) {
......@@ -444,19 +445,19 @@ void StatsPlugin::DeleteRecentStats(const QString &activity, int count,
// If we need to delete everything,
// no need to bother with the count and the date
DATABASE_TRANSACTION(resourcesDatabase());
DATABASE_TRANSACTION(*resourcesDatabase());
if (what == QStringLiteral("everything")) {
// Instantiating these every time is not a big overhead
// since this method is rarely executed.
auto removeEventsQuery = resourcesDatabase().createQuery();
auto removeEventsQuery = resourcesDatabase()->createQuery();
removeEventsQuery.prepare(
"DELETE FROM ResourceEvent "
"WHERE usedActivity = COALESCE(:usedActivity, usedActivity)"
);
auto removeScoreCachesQuery = resourcesDatabase().createQuery();
auto removeScoreCachesQuery = resourcesDatabase()->createQuery();
removeScoreCachesQuery.prepare(
"DELETE FROM ResourceScoreCache "
"WHERE usedActivity = COALESCE(:usedActivity, usedActivity)");
......@@ -480,14 +481,14 @@ void StatsPlugin::DeleteRecentStats(const QString &activity, int count,
// if something was accessed before, and the user did not
// remove the history, it is not really a secret.
auto removeEventsQuery = resourcesDatabase().createQuery();
auto removeEventsQuery = resourcesDatabase()->createQuery();
removeEventsQuery.prepare(
"DELETE FROM ResourceEvent "
"WHERE usedActivity = COALESCE(:usedActivity, usedActivity) "
"AND end > :since"
);
auto removeScoreCachesQuery = resourcesDatabase().createQuery();
auto removeScoreCachesQuery = resourcesDatabase()->createQuery();
removeScoreCachesQuery.prepare(
"DELETE FROM ResourceScoreCache "
"WHERE usedActivity = COALESCE(:usedActivity, usedActivity) "
......@@ -515,20 +516,20 @@ void StatsPlugin::DeleteEarlierStats(const QString &activity, int months)
// Deleting a specified length of time
DATABASE_TRANSACTION(resourcesDatabase());
DATABASE_TRANSACTION(*resourcesDatabase());
const auto time = QDateTime::currentDateTime().addMonths(-months);
const auto usedActivity = activity.isEmpty() ? QVariant()
: QVariant(activity);
auto removeEventsQuery = resourcesDatabase().createQuery();
auto removeEventsQuery = resourcesDatabase()->createQuery();
removeEventsQuery.prepare(
"DELETE FROM ResourceEvent "
"WHERE usedActivity = COALESCE(:usedActivity, usedActivity) "
"AND start < :time"
);
auto removeScoreCachesQuery = resourcesDatabase().createQuery();
auto removeScoreCachesQuery = resourcesDatabase()->createQuery();
removeScoreCachesQuery.prepare(
"DELETE FROM ResourceScoreCache "
"WHERE usedActivity = COALESCE(:usedActivity, usedActivity) "
......@@ -564,7 +565,7 @@ void StatsPlugin::DeleteStatsForResource(const QString &activity,
"StatsPlugin::DeleteStatsForResource",
"We can not handle CURRENT_AGENT_TAG here");
DATABASE_TRANSACTION(resourcesDatabase());
DATABASE_TRANSACTION(*resourcesDatabase());
// Check against sql injection
if (activity.contains('\'') || client.contains('\'')) return;
......@@ -580,7 +581,7 @@ void StatsPlugin::DeleteStatsForResource(const QString &activity,
client == ANY_AGENT_TAG ? " 1 " :
QStringLiteral(" initiatingAgent = '%1' ").arg(client);
auto removeEventsQuery = resourcesDatabase().createQuery();
auto removeEventsQuery = resourcesDatabase()->createQuery();
removeEventsQuery.prepare(
"DELETE FROM ResourceEvent "
"WHERE "
......@@ -589,7 +590,7 @@ void StatsPlugin::DeleteStatsForResource(const QString &activity,
+ "targettedResource LIKE :targettedResource ESCAPE '\\'"
);
auto removeScoreCachesQuery = resourcesDatabase().createQuery();
auto removeScoreCachesQuery = resourcesDatabase()->createQuery();
removeScoreCachesQuery.prepare(
"DELETE FROM ResourceScoreCache "
"WHERE "
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment