diff --git a/0001-Do-not-assume-SQLite-works-and-do-not-terminate-on-e.patch b/0001-Do-not-assume-SQLite-works-and-do-not-terminate-on-e.patch new file mode 100644 index 0000000..43716aa --- /dev/null +++ b/0001-Do-not-assume-SQLite-works-and-do-not-terminate-on-e.patch @@ -0,0 +1,225 @@ +From 9b47babb6c4172535be0630141d6f8c6047c2724 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ivan=20=C4=8Cuki=C4=87?= +Date: Wed, 7 Mar 2018 23:15:49 +0100 +Subject: [PATCH 1/5] Do not assume SQLite works and do not terminate on errors + +The SQLite database gets corrupted more often than expected. +Instead of assuming that it works flawlessly and asserting +that it does, just report the issue to the terminal, and +just give empty results. +--- + src/common/database/Database.cpp | 8 +++++--- + src/resultmodel.cpp | 2 ++ + src/resultset.cpp | 44 ++++++++++++++++++++-------------------- + src/resultwatcher.cpp | 12 +++++++---- + 4 files changed, 37 insertions(+), 29 deletions(-) + +diff --git a/src/common/database/Database.cpp b/src/common/database/Database.cpp +index 1dafeca..e21d267 100644 +--- a/src/common/database/Database.cpp ++++ b/src/common/database/Database.cpp +@@ -202,9 +202,11 @@ 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 +diff --git a/src/resultmodel.cpp b/src/resultmodel.cpp +index 7290b95..077edc8 100644 +--- a/src/resultmodel.cpp ++++ b/src/resultmodel.cpp +@@ -891,6 +891,8 @@ public: + //_ Title and mimetype functions + void fillTitleAndMimetype(ResultSet::Result &result) + { ++ if (!database) return; ++ + auto query = database->execQuery( + "SELECT " + "title, mimetype " +diff --git a/src/resultset.cpp b/src/resultset.cpp +index 744bb61..2fc081b 100644 +--- a/src/resultset.cpp ++++ b/src/resultset.cpp +@@ -134,10 +134,8 @@ public: + : QString())); + + if (query.lastError().isValid()) { +- qDebug() << "Error: " << query.lastError(); ++ qWarning() << "[Error at ResultSetPrivate::initQuery]: " << query.lastError(); + } +- +- Q_ASSERT_X(query.isActive(), "ResultSet initQuery", "Query is not valid"); + } + + QString agentClause(const QString &agent) const +@@ -245,13 +243,13 @@ public: + QStringList mimetypeFilter = transformedList( + queryDefinition.types(), &ResultSetPrivate::mimetypeClause); + +- auto query = _query; ++ auto queryString = _query; + +- query.replace("ORDER_BY_CLAUSE", "ORDER BY $orderingColumn resource ASC") +- .replace("LIMIT_CLAUSE", limitOffsetSuffix()); ++ queryString.replace("ORDER_BY_CLAUSE", "ORDER BY $orderingColumn resource ASC") ++ .replace("LIMIT_CLAUSE", limitOffsetSuffix()); + + return kamd::utils::debug_and_return(DEBUG_QUERIES, "Query: ", +- query ++ queryString + .replace(QLatin1String("$orderingColumn"), orderingColumn) + .replace(QLatin1String("$agentsFilter"), agentsFilter.join(QStringLiteral(" OR "))) + .replace(QLatin1String("$activitiesFilter"), activitiesFilter.join(QStringLiteral(" OR "))) +@@ -265,7 +263,7 @@ public: + // TODO: We need to correct the scores based on the time that passed + // since the cache was last updated, although, for this query, + // scores are not that important. +- static const QString query = ++ static const QString queryString = + R"sql( + SELECT + rl.targettedResource as resource +@@ -302,14 +300,14 @@ public: + )sql" + ; + +- return query; ++ return queryString; + } + + static const QString &usedResourcesQuery() + { + // TODO: We need to correct the scores based on the time that passed + // since the cache was last updated +- static const QString query = ++ static const QString queryString = + R"sql( + SELECT + rsc.targettedResource as resource +@@ -341,7 +339,7 @@ public: + )sql" + ; + +- return query; ++ return queryString; + } + + static const QString &allResourcesQuery() +@@ -349,7 +347,7 @@ public: + // TODO: We need to correct the scores based on the time that passed + // since the cache was last updated, although, for this query, + // scores are not that important. +- static const QString query = ++ static const QString queryString = + R"sql( + WITH + LinkedResourcesResults AS ( +@@ -431,12 +429,15 @@ public: + )sql" + ; + +- return query; ++ return queryString; + } + + ResultSet::Result currentResult() const + { + ResultSet::Result result; ++ ++ if (!database || !query.isActive()) return result; ++ + result.setResource(query.value(QStringLiteral("resource")).toString()); + result.setTitle(query.value(QStringLiteral("title")).toString()); + result.setMimetype(query.value(QStringLiteral("mimetype")).toString()); +@@ -448,19 +449,19 @@ public: + result.setLinkStatus( + (ResultSet::Result::LinkStatus)query.value(QStringLiteral("linkStatus")).toInt()); + +- auto query = database->createQuery(); ++ auto linkedActivitiesQuery = database->createQuery(); + +- query.prepare(R"sql( ++ linkedActivitiesQuery.prepare(R"sql( + SELECT usedActivity + FROM ResourceLink + WHERE targettedResource = :resource + )sql"); + +- query.bindValue(":resource", result.resource()); +- query.exec(); ++ linkedActivitiesQuery.bindValue(":resource", result.resource()); ++ linkedActivitiesQuery.exec(); + + QStringList linkedActivities; +- for (const auto &item: query) { ++ for (const auto &item: linkedActivitiesQuery) { + linkedActivities << item[0].toString(); + } + +@@ -471,7 +472,7 @@ public: + } + }; + +-ResultSet::ResultSet(Query query) ++ResultSet::ResultSet(Query queryDefinition) + : d(new ResultSetPrivate()) + { + using namespace Common; +@@ -483,10 +484,9 @@ ResultSet::ResultSet(Query query) + "that you do not have the Activity Manager running, or that " + "something else is broken on your system. Recent documents and " + "alike will not work!"; +- Q_ASSERT_X((bool)d->database, "ResultSet constructor", "Database is NULL"); + } + +- d->queryDefinition = query; ++ d->queryDefinition = queryDefinition; + + d->initQuery(); + } +@@ -515,7 +515,7 @@ ResultSet::~ResultSet() + + ResultSet::Result ResultSet::at(int index) const + { +- Q_ASSERT_X(d->query.isActive(), "ResultSet::at", "Query is not active"); ++ if (!d->query.isActive()) return Result(); + + d->query.seek(index); + +diff --git a/src/resultwatcher.cpp b/src/resultwatcher.cpp +index 32ffe29..5cf3b4c 100644 +--- a/src/resultwatcher.cpp ++++ b/src/resultwatcher.cpp +@@ -159,11 +159,15 @@ public: + auto type = kamd::utils::make_lazy_val([&] () -> QString { + using Common::Database; + +- auto query ++ auto database + = Database::instance(Database::ResourcesDatabase, +- Database::ReadOnly) +- ->execQuery("SELECT mimetype FROM ResourceInfo WHERE " +- "targettedResource = '" + resource + "'"); ++ Database::ReadOnly); ++ ++ if (!database) return QString(); ++ ++ auto query ++ = database->execQuery("SELECT mimetype FROM ResourceInfo WHERE " ++ "targettedResource = '" + resource + "'"); + + for (const auto &item : query) { + return item[0].toString(); +-- +2.14.3 + diff --git a/kf5-kactivities-stats.spec b/kf5-kactivities-stats.spec index 3bcb5cf..f68ffd4 100644 --- a/kf5-kactivities-stats.spec +++ b/kf5-kactivities-stats.spec @@ -3,20 +3,23 @@ Name: kf5-%{framework} Summary: A KDE Frameworks 5 Tier 3 library for accessing the usage data collected by the activities system Version: 5.44.0 -Release: 1%{?dist} +Release: 2%{?dist} # KDE e.V. may determine that future GPL versions are accepted License: LGPLv2 or LGPLv3 URL: https://cgit.kde.org/%{framework}.git -%global versiondir %(echo %{version} | cut -d. -f1-2) +%global majmin %(echo %{version} | cut -d. -f1-2) %global revision %(echo %{version} | cut -d. -f3) %if %{revision} >= 50 %global stable unstable %else %global stable stable %endif -Source0: http://download.kde.org/%{stable}/frameworks/%{versiondir}/%{framework}-%{version}.tar.xz +Source0: http://download.kde.org/%{stable}/frameworks/%{majmin}/%{framework}-%{version}.tar.xz + +## upstream patches +Patch1: 0001-Do-not-assume-SQLite-works-and-do-not-terminate-on-e.patch BuildRequires: boost-devel BuildRequires: extra-cmake-modules >= %{version} @@ -27,9 +30,6 @@ BuildRequires: pkgconfig BuildRequires: qt5-qtdeclarative-devel BuildRequires: qt5-qtbase-devel - -Requires: kf5-filesystem >= %{version} - %description %{summary}. @@ -52,7 +52,7 @@ pushd %{_target_platform} -DBUILD_TESTING=ON popd -make %{?_smp_mflags} -C %{_target_platform} +%make_build -C %{_target_platform} %install @@ -64,8 +64,7 @@ make install/fast DESTDIR=%{buildroot} -C %{_target_platform} make test -C %{_target_platform} -%post -p /sbin/ldconfig -%postun -p /sbin/ldconfig +%ldconfig_scriptlets %files %doc MAINTAINER README.developers TODO @@ -82,6 +81,10 @@ make test -C %{_target_platform} %changelog +* Mon Mar 26 2018 Rex Dieter - 5.44.0-2 +- pull in upstream fix for sqlite wal mode crashes (fail gracefully instead) +- use %%make_build %%ldconfig_scriptlets + * Sat Mar 03 2018 Rex Dieter - 5.44.0-1 - 5.44.0