diff --git a/0001-Use-per-thread-QDBusConnections.patch b/0001-Use-per-thread-QDBusConnections.patch new file mode 100644 index 0000000..ccb0e62 --- /dev/null +++ b/0001-Use-per-thread-QDBusConnections.patch @@ -0,0 +1,485 @@ +From a5542751bc147c7f74131006339b55e6339b3e9f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Vr=C3=A1til?= +Date: Thu, 17 Apr 2014 15:11:57 +0200 +Subject: [PATCH 1/7] Use per-thread QDBusConnections + +This moves DBusConnectionPool from Nepomuk search code to Akonadi and makes +use of it in search infrastructure and couple other classes that interact +with DBus from non-main thread. + +QDBusConnection is not thread-safe in Qt 4, so we need to workaround it by +having a connection for each thread. Qt 5 should be OK, so we can remove this +in Frameworks. + +This should fix random crashes I've been seeing when SearchTaskManager::addTask() +was called from multiple threads simultaneously. +--- + server/CMakeLists.txt | 2 +- + server/src/dbusconnectionpool.cpp | 62 +++++++++++++++++++++++++++++ + server/src/dbusconnectionpool.h | 41 +++++++++++++++++++ + server/src/handler/fetchhelper.cpp | 9 ++--- + server/src/nepomuk/dbusconnectionpool.cpp | 59 --------------------------- + server/src/nepomuk/dbusconnectionpool.h | 38 ------------------ + server/src/nepomuk/queryserviceclient.cpp | 4 +- + server/src/search/agentsearchinstance.cpp | 5 ++- + server/src/search/searchmanager.cpp | 3 +- + server/src/search/searchtaskmanager.cpp | 11 ++--- + server/src/search/searchtaskmanager.h | 2 - + server/src/storage/itemretrievalmanager.cpp | 6 +-- + server/src/storagejanitor.cpp | 3 +- + 13 files changed, 124 insertions(+), 121 deletions(-) + create mode 100644 server/src/dbusconnectionpool.cpp + create mode 100644 server/src/dbusconnectionpool.h + delete mode 100644 server/src/nepomuk/dbusconnectionpool.cpp + delete mode 100644 server/src/nepomuk/dbusconnectionpool.h + +diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt +index 571bead..1709348 100644 +--- a/server/CMakeLists.txt ++++ b/server/CMakeLists.txt +@@ -106,6 +106,7 @@ set(libakonadiprivate_SRCS + src/collectionscheduler.cpp + src/clientcapabilities.cpp + src/clientcapabilityaggregator.cpp ++ src/dbusconnectionpool.cpp + src/handler.cpp + src/handlerhelper.cpp + src/intervalcheck.cpp +@@ -206,7 +207,6 @@ if (Soprano_FOUND) + src/search/nepomuksearchengine.cpp + src/nepomuk/dbusoperators.cpp + src/nepomuk/queryserviceclient.cpp +- src/nepomuk/dbusconnectionpool.cpp + src/nepomuk/result.cpp + ) + +diff --git a/server/src/dbusconnectionpool.cpp b/server/src/dbusconnectionpool.cpp +new file mode 100644 +index 0000000..9aede4f +--- /dev/null ++++ b/server/src/dbusconnectionpool.cpp +@@ -0,0 +1,62 @@ ++/* ++ * Copyright (C) 2010 Sebastian Trueg ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public License ++ * along with this library; see the file COPYING.LIB. If not, write to ++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ++ * Boston, MA 02110-1301, USA. ++ */ ++ ++#include "dbusconnectionpool.h" ++#include ++#include ++#include ++ ++namespace { ++QAtomicInt s_connectionCounter; ++ ++class DBusConnectionPoolPrivate ++{ ++public: ++ DBusConnectionPoolPrivate() ++ : m_connection( QDBusConnection::connectToBus( ++ QDBusConnection::SessionBus, ++ QString::fromLatin1("AkonadiServer-%1").arg(newNumber()) ) ) ++ { ++ } ++ ~DBusConnectionPoolPrivate() { ++ QDBusConnection::disconnectFromBus( m_connection.name() ); ++ } ++ ++ QDBusConnection connection() const { return m_connection; } ++ ++private: ++ static int newNumber() { ++ return s_connectionCounter.fetchAndAddAcquire( 1 ); ++ } ++ QDBusConnection m_connection; ++}; ++} ++ ++QThreadStorage s_perThreadConnection; ++ ++QDBusConnection Akonadi::Server::DBusConnectionPool::threadConnection() ++{ ++ if ( !QCoreApplication::instance() || QCoreApplication::instance()->thread() == QThread::currentThread() ) { ++ return QDBusConnection::sessionBus(); // main thread, use the default session bus ++ } ++ if ( !s_perThreadConnection.hasLocalData() ) { ++ s_perThreadConnection.setLocalData( new DBusConnectionPoolPrivate ); ++ } ++ return s_perThreadConnection.localData()->connection(); ++} +diff --git a/server/src/dbusconnectionpool.h b/server/src/dbusconnectionpool.h +new file mode 100644 +index 0000000..4f8a93e +--- /dev/null ++++ b/server/src/dbusconnectionpool.h +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (C) 2010 Sebastian Trueg ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public License ++ * along with this library; see the file COPYING.LIB. If not, write to ++ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ++ * Boston, MA 02110-1301, USA. ++ */ ++ ++#ifndef DBUSCONNECTIONPOOL_H ++#define DBUSCONNECTIONPOOL_H ++ ++#include ++ ++namespace Akonadi { ++namespace Server { ++namespace DBusConnectionPool { ++ ++/** ++ * Returns a new QDBusConnection for each thread, because QDBusConnection is ++ * not thread-safe in Qt 4. ++ * ++ * FIXME: Remove in KF5 ++ */ ++QDBusConnection threadConnection(); ++ ++} ++} ++} ++ ++#endif +diff --git a/server/src/handler/fetchhelper.cpp b/server/src/handler/fetchhelper.cpp +index 6284cc9..a6888a3 100644 +--- a/server/src/handler/fetchhelper.cpp ++++ b/server/src/handler/fetchhelper.cpp +@@ -38,6 +38,7 @@ + #include "utils.h" + #include "intervalcheck.h" + #include "agentmanagerinterface.h" ++#include "dbusconnectionpool.h" + + #include + #include +@@ -252,16 +253,12 @@ bool FetchHelper::isScopeLocal( const Scope &scope ) + + query.next(); + const QString resourceName = query.value( 0 ).toString(); +- // Workaround for QDBusConnectionPrivate not being thread-safe in Qt 4, fixed in Qt 5.2 +- // TODO: Remove in KF5 +- const QDBusConnection connection = QDBusConnection::connectToBus( QDBusConnection::SessionBus, +- QString::fromLatin1( mConnection->sessionId() ) ); ++ + org::freedesktop::Akonadi::AgentManager manager( AkDBus::serviceName( AkDBus::Control ), + QLatin1String( "/AgentManager" ), +- connection ); ++ DBusConnectionPool::threadConnection() ); + const QString typeIdentifier = manager.agentInstanceType( resourceName ); + const QVariantMap properties = manager.agentCustomProperties( typeIdentifier ); +- QDBusConnection::disconnectFromBus( QString::fromLatin1( mConnection->sessionId() ) ); + return properties.value( QLatin1String( "HasLocalStorage" ), false ).toBool(); + } + +diff --git a/server/src/nepomuk/dbusconnectionpool.cpp b/server/src/nepomuk/dbusconnectionpool.cpp +deleted file mode 100644 +index 598d16f..0000000 +--- a/server/src/nepomuk/dbusconnectionpool.cpp ++++ /dev/null +@@ -1,59 +0,0 @@ +-/* +- * This file is part of the Nepomuk KDE project. +- * Copyright (C) 2010 Sebastian Trueg +- * Copyright (C) 2010 David Faure +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Library General Public +- * License as published by the Free Software Foundation; either +- * version 2 of the License, or (at your option) any later version. +- * +- * This library is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * Library General Public License for more details. +- * +- * You should have received a copy of the GNU Library General Public License +- * along with this library; see the file COPYING.LIB. If not, write to +- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +- * Boston, MA 02110-1301, USA. +- */ +- +-#include "dbusconnectionpool.h" +-#include +- +-namespace { +-QAtomicInt s_connectionCounter; +- +-class DBusConnectionPoolPrivate +-{ +-public: +- DBusConnectionPoolPrivate() +- : m_connection( QDBusConnection::connectToBus( +- QDBusConnection::SessionBus, +- QString::fromLatin1( "NepomukQueryServiceConnection%1" ).arg( newNumber() ) ) ) +- { +- } +- ~DBusConnectionPoolPrivate() { +- QDBusConnection::disconnectFromBus( m_connection.name() ); +- } +- +- QDBusConnection connection() const { return m_connection; } +- +-private: +- static int newNumber() { +- return s_connectionCounter.fetchAndAddAcquire( 1 ); +- } +- QDBusConnection m_connection; +-}; +-} +- +-QThreadStorage s_perThreadConnection; +- +-QDBusConnection DBusConnectionPool::threadConnection() +-{ +- if ( !s_perThreadConnection.hasLocalData() ) { +- s_perThreadConnection.setLocalData( new DBusConnectionPoolPrivate ); +- } +- return s_perThreadConnection.localData()->connection(); +-} +diff --git a/server/src/nepomuk/dbusconnectionpool.h b/server/src/nepomuk/dbusconnectionpool.h +deleted file mode 100644 +index c5ac746..0000000 +--- a/server/src/nepomuk/dbusconnectionpool.h ++++ /dev/null +@@ -1,38 +0,0 @@ +-/* +- * This file is part of the Nepomuk KDE project. +- * Copyright (C) 2010 Sebastian Trueg +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Library General Public +- * License as published by the Free Software Foundation; either +- * version 2 of the License, or (at your option) any later version. +- * +- * This library is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * Library General Public License for more details. +- * +- * You should have received a copy of the GNU Library General Public License +- * along with this library; see the file COPYING.LIB. If not, write to +- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +- * Boston, MA 02110-1301, USA. +- */ +- +-#ifndef _DBUS_CONNECTION_POOL_H_ +-#define _DBUS_CONNECTION_POOL_H_ +- +-#include +- +-namespace DBusConnectionPool +-{ +-/** +- * The DBusConnectionPool works around the problem +- * of QDBusConnection not being thread-safe. As soon as that +- * has been fixed (either directly in libdbus or with a work- +- * around in Qt) this method can be dropped in favor of +- * QDBusConnection::sessionBus(). +- */ +-QDBusConnection threadConnection(); +-} +- +-#endif +diff --git a/server/src/nepomuk/queryserviceclient.cpp b/server/src/nepomuk/queryserviceclient.cpp +index 089a80b..b27a751 100644 +--- a/server/src/nepomuk/queryserviceclient.cpp ++++ b/server/src/nepomuk/queryserviceclient.cpp +@@ -24,7 +24,7 @@ + #include "result.h" + #include "queryserviceinterface.h" + #include "queryinterface.h" +-#include ++#include "dbusconnectionpool.h" + + #include + #include +@@ -40,7 +40,7 @@ public: + Private() + : queryServiceInterface( 0 ), + queryInterface( 0 ), +- dbusConnection( DBusConnectionPool::threadConnection() ), ++ dbusConnection( Akonadi::Server::DBusConnectionPool::threadConnection() ), + m_queryActive( false ), + loop( 0 ) { + } +diff --git a/server/src/search/agentsearchinstance.cpp b/server/src/search/agentsearchinstance.cpp +index 54ffab0..ca6ef87 100644 +--- a/server/src/search/agentsearchinstance.cpp ++++ b/server/src/search/agentsearchinstance.cpp +@@ -21,6 +21,7 @@ + #include "agentsearchinterface.h" + #include "searchtaskmanager.h" + #include "akdbus.h" ++#include "dbusconnectionpool.h" + + using namespace Akonadi::Server; + +@@ -43,7 +44,7 @@ bool AgentSearchInstance::init() + mInterface = new OrgFreedesktopAkonadiAgentSearchInterface( + AkDBus::agentServiceName( mId, AkDBus::Agent ), + QLatin1String( "/Search" ), +- QDBusConnection::sessionBus() ); ++ DBusConnectionPool::threadConnection() ); + + if ( !mInterface || !mInterface->isValid() ) { + delete mInterface; +@@ -52,7 +53,7 @@ bool AgentSearchInstance::init() + } + + mServiceWatcher = new QDBusServiceWatcher( AkDBus::agentServiceName( mId, AkDBus::Agent ), +- QDBusConnection::sessionBus(), ++ DBusConnectionPool::threadConnection(), + QDBusServiceWatcher::WatchForOwnerChange, + this ); + connect( mServiceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), +diff --git a/server/src/search/searchmanager.cpp b/server/src/search/searchmanager.cpp +index 139d058..1eafb27 100644 +--- a/server/src/search/searchmanager.cpp ++++ b/server/src/search/searchmanager.cpp +@@ -26,6 +26,7 @@ + #include "agentsearchengine.h" + #include "nepomuksearchengine.h" + #include "notificationmanager.h" ++#include "dbusconnectionpool.h" + #include "searchrequest.h" + #include "searchtaskmanager.h" + #include "storage/datastore.h" +@@ -98,7 +99,7 @@ SearchManager::SearchManager( const QStringList &searchEngines, QObject *parent + + new SearchManagerAdaptor( this ); + +- QDBusConnection::sessionBus().registerObject( ++ DBusConnectionPool::threadConnection().registerObject( + QLatin1String( "/SearchManager" ), + this, + QDBusConnection::ExportAdaptors ); +diff --git a/server/src/search/searchtaskmanager.cpp b/server/src/search/searchtaskmanager.cpp +index 51bb516..e7980a4 100644 +--- a/server/src/search/searchtaskmanager.cpp ++++ b/server/src/search/searchtaskmanager.cpp +@@ -23,6 +23,7 @@ + #include "akdbus.h" + #include "connection.h" + #include "storage/selectquerybuilder.h" ++#include "dbusconnectionpool.h" + #include + + #include +@@ -36,9 +37,6 @@ SearchTaskManager *SearchTaskManager::sInstance = 0; + SearchTaskManager::SearchTaskManager() + : QObject() + , mShouldStop( false ) +- , mAgentManager( AkDBus::serviceName( AkDBus::Control ), QLatin1String( "/AgentManager" ), +- QDBusConnection::sessionBus() ) +- + { + sInstance = this; + +@@ -125,13 +123,16 @@ void SearchTaskManager::addTask( SearchTask *task ) + } + + mInstancesLock.lock(); ++ ++ org::freedesktop::Akonadi::AgentManager agentManager( AkDBus::serviceName( AkDBus::Control ), QLatin1String( "/AgentManager" ), ++ DBusConnectionPool::threadConnection() ); + do { + const QString resourceId = query.value( 1 ).toString(); + if ( !mInstances.contains( resourceId ) ) { + akDebug() << "Resource" << resourceId << "does not implement Search interface, skipping"; +- } else if ( !mAgentManager.agentInstanceOnline( resourceId ) ) { ++ } else if ( !agentManager.agentInstanceOnline( resourceId ) ) { + akDebug() << "Agent" << resourceId << "is offline, skipping"; +- } else if ( mAgentManager.agentInstanceStatus( resourceId ) > 2 ) { // 2 == Broken, 3 == Not Configured ++ } else if ( agentManager.agentInstanceStatus( resourceId ) > 2 ) { // 2 == Broken, 3 == Not Configured + akDebug() << "Agent" << resourceId << "is broken or not configured"; + } else { + const qint64 collectionId = query.value( 0 ).toLongLong(); +diff --git a/server/src/search/searchtaskmanager.h b/server/src/search/searchtaskmanager.h +index 06e1b52..9b7972b 100644 +--- a/server/src/search/searchtaskmanager.h ++++ b/server/src/search/searchtaskmanager.h +@@ -97,8 +97,6 @@ class SearchTaskManager : public QObject + TasksMap::Iterator cancelRunningTask( TasksMap::Iterator &iter ); + bool allResourceTasksCompleted( SearchTask* ) const; + +- org::freedesktop::Akonadi::AgentManager mAgentManager; +- + QMap mInstances; + QMutex mInstancesLock; + +diff --git a/server/src/storage/itemretrievalmanager.cpp b/server/src/storage/itemretrievalmanager.cpp +index d49ba66..ce88410 100644 +--- a/server/src/storage/itemretrievalmanager.cpp ++++ b/server/src/storage/itemretrievalmanager.cpp +@@ -20,6 +20,7 @@ + #include "itemretrievalmanager.h" + #include "itemretrievalrequest.h" + #include "itemretrievaljob.h" ++#include "dbusconnectionpool.h" + + #include "resourceinterface.h" + +@@ -40,10 +41,7 @@ ItemRetrievalManager *ItemRetrievalManager::sInstance = 0; + + ItemRetrievalManager::ItemRetrievalManager( QObject *parent ) + : QObject( parent ), +- mDBusConnection( +- QDBusConnection::connectToBus( +- QDBusConnection::SessionBus, +- QString::fromLatin1( "AkonadiServerItemRetrievalManager" ) ) ) ++ mDBusConnection( DBusConnectionPool::threadConnection() ) + { + // make sure we are created from the retrieval thread and only once + Q_ASSERT( QThread::currentThread() != QCoreApplication::instance()->thread() ); +diff --git a/server/src/storagejanitor.cpp b/server/src/storagejanitor.cpp +index ebe7a24..af1a407 100644 +--- a/server/src/storagejanitor.cpp ++++ b/server/src/storagejanitor.cpp +@@ -26,6 +26,7 @@ + #include "storage/parthelper.h" + #include "resourcemanager.h" + #include "entities.h" ++#include "dbusconnectionpool.h" + + #include + #include +@@ -63,7 +64,7 @@ void StorageJanitorThread::run() + + StorageJanitor::StorageJanitor( QObject *parent ) + : QObject( parent ) +- , m_connection( QDBusConnection::connectToBus( QDBusConnection::SessionBus, QLatin1String( staticMetaObject.className() ) ) ) ++ , m_connection( DBusConnectionPool::threadConnection() ) + , m_lostFoundCollectionId( -1 ) + { + DataStore::self(); +-- +1.9.3 + diff --git a/0001-remove-invalid-part-before-parttable-migration.patch b/0001-remove-invalid-part-before-parttable-migration.patch deleted file mode 100644 index a367067..0000000 --- a/0001-remove-invalid-part-before-parttable-migration.patch +++ /dev/null @@ -1,41 +0,0 @@ -commit 4ca8b846baaad48ebbd723f6411f9571a3b0f5ad -Author: Dan Vrátil -Date: Tue Apr 22 11:28:07 2014 +0200 - - Remove the invalid GID part from PartTable before starting PartTable migration - - More people than we expected have invalid 'GID' part in their PartTable, - which breaks migration to schema 25, because it expects all part types - to have a valid name. - - To work around this fact, we DELETE all parts with name 'GID' from PartTable - before starting the actual migration. This will not fix the migration for - people with other invalid parts, but I haven't heard of any such. To make - this completely bullet-proof, we would need to iterate through all entries, - which would be massively slower than current INSERT INTO ... SELECT FROM approach. - - Distributions, this is a good choice for backporting into 1.12.1 ;-) - - BUG: 331867 - FIXED-IN: 1.12.2 - -diff --git a/server/src/storage/dbupdater.cpp b/server/src/storage/dbupdater.cpp -index ccaf584..d6368b5 100644 ---- a/server/src/storage/dbupdater.cpp -+++ b/server/src/storage/dbupdater.cpp -@@ -261,6 +261,15 @@ bool DbUpdater::complexUpdate_25() - } - } - -+ { -+ // It appears that more users than expected have the invalid "GID" part in their -+ // PartTable, which breaks the migration below (see BKO#331867), so we apply this -+ // wanna-be fix to remove the invalid part before we start the actual migration. -+ QueryBuilder qb( QLatin1String( "PartTable" ), QueryBuilder::Delete ); -+ qb.addValueCondition( QLatin1String( "PartTable.name" ), Query::Equals, QLatin1String( "GID" ) ); -+ qb.exec(); -+ } -+ - akDebug() << "Creating a PartTable_new"; - { - TableDescription description; diff --git a/0002-Remove-the-invalid-GID-part-from-PartTable-before-st.patch b/0002-Remove-the-invalid-GID-part-from-PartTable-before-st.patch new file mode 100644 index 0000000..dac2e31 --- /dev/null +++ b/0002-Remove-the-invalid-GID-part-from-PartTable-before-st.patch @@ -0,0 +1,47 @@ +From 4ca8b846baaad48ebbd723f6411f9571a3b0f5ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Vr=C3=A1til?= +Date: Tue, 22 Apr 2014 11:28:07 +0200 +Subject: [PATCH 2/7] Remove the invalid GID part from PartTable before + starting PartTable migration + +More people than we expected have invalid 'GID' part in their PartTable, +which breaks migration to schema 25, because it expects all part types +to have a valid name. + +To work around this fact, we DELETE all parts with name 'GID' from PartTable +before starting the actual migration. This will not fix the migration for +people with other invalid parts, but I haven't heard of any such. To make +this completely bullet-proof, we would need to iterate through all entries, +which would be massively slower than current INSERT INTO ... SELECT FROM approach. + +Distributions, this is a good choice for backporting into 1.12.1 ;-) + +BUG: 331867 +FIXED-IN: 1.12.2 +--- + server/src/storage/dbupdater.cpp | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/server/src/storage/dbupdater.cpp b/server/src/storage/dbupdater.cpp +index ccaf584..d6368b5 100644 +--- a/server/src/storage/dbupdater.cpp ++++ b/server/src/storage/dbupdater.cpp +@@ -261,6 +261,15 @@ bool DbUpdater::complexUpdate_25() + } + } + ++ { ++ // It appears that more users than expected have the invalid "GID" part in their ++ // PartTable, which breaks the migration below (see BKO#331867), so we apply this ++ // wanna-be fix to remove the invalid part before we start the actual migration. ++ QueryBuilder qb( QLatin1String( "PartTable" ), QueryBuilder::Delete ); ++ qb.addValueCondition( QLatin1String( "PartTable.name" ), Query::Equals, QLatin1String( "GID" ) ); ++ qb.exec(); ++ } ++ + akDebug() << "Creating a PartTable_new"; + { + TableDescription description; +-- +1.9.3 + diff --git a/0003-Fix-retrieving-of-GID-from-SQL-query-result-in-Fetch.patch b/0003-Fix-retrieving-of-GID-from-SQL-query-result-in-Fetch.patch new file mode 100644 index 0000000..4bb61f7 --- /dev/null +++ b/0003-Fix-retrieving-of-GID-from-SQL-query-result-in-Fetch.patch @@ -0,0 +1,32 @@ +From 1d47dd274dd29bec42170d0cdf69cb9ac0b6686e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Vr=C3=A1til?= +Date: Thu, 24 Apr 2014 15:37:32 +0200 +Subject: [PATCH 3/7] Fix retrieving of GID from SQL query result in + FetchHelper + +This has been broken since the day one, but nobody noticed. I guess +we were lucky enough to always query other arguments, so that +ItemQueryPimItemGidColumn actually matched indexed of the GID column +in query. + +Another reason why we need proper unit-tests on the server... +--- + server/src/handler/fetchhelper.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/server/src/handler/fetchhelper.cpp b/server/src/handler/fetchhelper.cpp +index a6888a3..4d9f778 100644 +--- a/server/src/handler/fetchhelper.cpp ++++ b/server/src/handler/fetchhelper.cpp +@@ -367,7 +367,7 @@ bool FetchHelper::fetchItems( const QByteArray &responseIdentifier ) + } + } + if ( mFetchScope.gidRequested() ) { +- const QByteArray gid = Utils::variantToByteArray( itemQuery.value( ItemQueryPimItemGidColumn ) ); ++ const QByteArray gid = Utils::variantToByteArray( extractQueryResult( itemQuery, ItemQueryPimItemGidColumn ) ); + if ( !gid.isEmpty() ) { + attributes.append( AKONADI_PARAM_GID " " + ImapParser::quote( gid ) ); + } +-- +1.9.3 + diff --git a/0004-Fix-PostgreSQL-startup-when-akonadiserverrc-contains.patch b/0004-Fix-PostgreSQL-startup-when-akonadiserverrc-contains.patch new file mode 100644 index 0000000..4c2d3b9 --- /dev/null +++ b/0004-Fix-PostgreSQL-startup-when-akonadiserverrc-contains.patch @@ -0,0 +1,85 @@ +From f5bfc641c38ca0dbd37c8993bc74f81c7e0c9b66 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Vr=C3=A1til?= +Date: Tue, 6 May 2014 15:27:07 +0200 +Subject: [PATCH 4/7] Fix PostgreSQL startup when akonadiserverrc contains + empty values + +When there are empty configuration options in akonadiserverrc (like Host), +we would still pick them up and use them as valid values, which is wrong, +because then we work with empty socket path etc. + +Instead we always replace non-existent and empty config values with the +default ones, so that Akonadi with PostgreSQL is always able to start. +--- + server/src/storage/dbconfigpostgresql.cpp | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/server/src/storage/dbconfigpostgresql.cpp b/server/src/storage/dbconfigpostgresql.cpp +index 10460d4..66e4605 100644 +--- a/server/src/storage/dbconfigpostgresql.cpp ++++ b/server/src/storage/dbconfigpostgresql.cpp +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #include + +@@ -90,13 +91,29 @@ bool DbConfigPostgresql::init( QSettings &settings ) + // read settings for current driver + settings.beginGroup( driverName() ); + mDatabaseName = settings.value( QLatin1String( "Name" ), defaultDatabaseName() ).toString(); ++ if ( mDatabaseName.isEmpty() ) { ++ mDatabaseName = defaultDatabaseName(); ++ } + mHostName = settings.value( QLatin1String( "Host" ), defaultHostName ).toString(); ++ if ( mHostName.isEmpty() ) { ++ mHostName = defaultHostName; ++ } ++ // User, password and Options can be empty and still valid, so don't override them + mUserName = settings.value( QLatin1String( "User" ) ).toString(); + mPassword = settings.value( QLatin1String( "Password" ) ).toString(); + mConnectionOptions = settings.value( QLatin1String( "Options" ), defaultOptions ).toString(); + mServerPath = settings.value( QLatin1String( "ServerPath" ), defaultServerPath ).toString(); ++ if ( mInternalServer && mServerPath.isEmpty() ) { ++ mServerPath = defaultServerPath; ++ } + mInitDbPath = settings.value( QLatin1String( "InitDbPath" ), defaultInitDbPath ).toString(); ++ if ( mInternalServer && mInitDbPath.isEmpty() ) { ++ mInitDbPath = defaultInitDbPath; ++ } + mPgData = settings.value( QLatin1String( "PgData" ), defaultPgData ).toString(); ++ if ( mPgData.isEmpty() ) { ++ mPgData = defaultPgData; ++ } + settings.endGroup(); + + // store back the default values +@@ -104,12 +121,8 @@ bool DbConfigPostgresql::init( QSettings &settings ) + settings.setValue( QLatin1String( "Name" ), mDatabaseName ); + settings.setValue( QLatin1String( "Host" ), mHostName ); + settings.setValue( QLatin1String( "Options" ), mConnectionOptions ); +- if ( !mServerPath.isEmpty() ) { +- settings.setValue( QLatin1String( "ServerPath" ), mServerPath ); +- } +- if ( !mInitDbPath.isEmpty() ) { +- settings.setValue( QLatin1String( "InitDbPath" ), mInitDbPath ); +- } ++ settings.setValue( QLatin1String( "ServerPath" ), mServerPath ); ++ settings.setValue( QLatin1String( "InitDbPath" ), mInitDbPath ); + settings.setValue( QLatin1String( "StartServer" ), mInternalServer ); + settings.endGroup(); + settings.sync(); +@@ -203,7 +216,7 @@ void DbConfigPostgresql::startInternalServer() + break; + } + +- if ( pgCtl.waitForFinished( 500 ) ) { ++ if ( pgCtl.waitForFinished( 500 ) && pgCtl.exitCode() ) { + akError() << "Database process exited unexpectedly during initial connection!"; + akError() << "executable:" << mServerPath; + akError() << "arguments:" << arguments; +-- +1.9.3 + diff --git a/0005-Fix-PostgreSQL-start-when-postmaster.pid-is-not-remo.patch b/0005-Fix-PostgreSQL-start-when-postmaster.pid-is-not-remo.patch new file mode 100644 index 0000000..80dded8 --- /dev/null +++ b/0005-Fix-PostgreSQL-start-when-postmaster.pid-is-not-remo.patch @@ -0,0 +1,71 @@ +From f217d9e96dc8de88916e8ca0b93dd9a7500bbbc3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Vr=C3=A1til?= +Date: Tue, 6 May 2014 16:38:17 +0200 +Subject: [PATCH 5/7] Fix PostgreSQL start when postmaster.pid is not removed + after non-clean shutdown + +When PostgreSQL is not terminated nicely, a pidfile is left behind in db_data, +which will prevent pg_ctl from starting a new PostgreSQL server. + +We check for postmaster.pid file and verify that postgres server with PID +specified in the pidfile is not running anymore, then delete the pidfile to +allow pg_ctl to start a new server. If the postgres server is still running +(possibly after Akonadi server crash), we try to connect to it right away. + +BUG: 286826 +FIXED-IN: 1.12.2 +--- + server/src/storage/dbconfigpostgresql.cpp | 37 +++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +diff --git a/server/src/storage/dbconfigpostgresql.cpp b/server/src/storage/dbconfigpostgresql.cpp +index 66e4605..7b61819 100644 +--- a/server/src/storage/dbconfigpostgresql.cpp ++++ b/server/src/storage/dbconfigpostgresql.cpp +@@ -166,6 +166,43 @@ void DbConfigPostgresql::startInternalServer() + QDir().mkpath( socketDir ); + } + ++// TODO Windows support ++#ifndef Q_WS_WIN ++ // If postmaster.pid exists, check whether the postgres process still exists too, ++ // because normally we shouldn't be able to get this far if Akonadi is already ++ // running. If postgres is not running, then the pidfile was left after a system ++ // crash or something similar and we can remove it (otherwise pg_ctl won't start) ++ QFile postmaster( QString::fromLatin1( "%1/postmaster.pid" ).arg( mPgData ) ); ++ if ( postmaster.exists() && postmaster.open( QIODevice::ReadOnly ) ) { ++ qDebug() << "Found a postmaster.pid pidfile, checking whether the server is still running..."; ++ QByteArray pid = postmaster.readLine(); ++ // Remvoe newline character ++ pid.truncate(pid.size() - 1); ++ QFile proc( QString::fromLatin1( "/proc/" + pid + "/stat" ) ); ++ // Check whether the process with the PID from pidfile still exists and whether ++ // it's actually still postgres or, whether the PID has been recycled in the ++ // meanwhile. ++ if ( proc.open( QIODevice::ReadOnly ) ) { ++ const QByteArray stat = proc.readAll(); ++ const QList stats = stat.split( ' ' ); ++ if ( stats.count() > 1 ) { ++ // Make sure the PID actually belongs to postgres process ++ if ( stats[1] == "(postgres)" ) { ++ // Yup, our PostgreSQL is actually running, so pretend we started the server ++ // and try to connect to it ++ qWarning() << "PostgreSQL for Akonadi is already running, trying to connect to it."; ++ return; ++ } ++ } ++ proc.close(); ++ } ++ ++ qDebug() << "No postgres process with specified PID is running. Removing the pidfile and starting a new Postgres instance..."; ++ postmaster.close(); ++ postmaster.remove(); ++ } ++#endif ++ + if ( !QFile::exists( QString::fromLatin1( "%1/PG_VERSION" ).arg( mPgData ) ) ) { + // postgres data directory not initialized yet, so call initdb on it + +-- +1.9.3 + diff --git a/0006-Remove-space-from-an-argument-passed-to-postgres-ser.patch b/0006-Remove-space-from-an-argument-passed-to-postgres-ser.patch new file mode 100644 index 0000000..35dcdd7 --- /dev/null +++ b/0006-Remove-space-from-an-argument-passed-to-postgres-ser.patch @@ -0,0 +1,34 @@ +From 74b2d3a43e19f5262ec84ccf609925eeb071d755 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Vr=C3=A1til?= +Date: Tue, 6 May 2014 16:49:32 +0200 +Subject: [PATCH 6/7] Remove space from an argument passed to postgres server + +Some users reported problem with starting PostgreSQL when there's a space +between name and value of an argument passed to postgres. Removing the +space fixes problem for them (withouth breaking PostgreSQL for those who +didn't have a problem with the space) + +Thanks SergTruf for the patch. + +BUG: 332988 +FIXED-IN: 1.12.2 +--- + server/src/storage/dbconfigpostgresql.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/server/src/storage/dbconfigpostgresql.cpp b/server/src/storage/dbconfigpostgresql.cpp +index 7b61819..ce8067b 100644 +--- a/server/src/storage/dbconfigpostgresql.cpp ++++ b/server/src/storage/dbconfigpostgresql.cpp +@@ -223,7 +223,7 @@ void DbConfigPostgresql::startInternalServer() + << QString::fromLatin1( "--pgdata=%1" ).arg( mPgData ) + // set the directory for unix domain socket communication + // -o will pass the switch to postgres +- << QString::fromLatin1( "-o \"-k %1\"" ).arg( socketDir ); ++ << QString::fromLatin1( "-o \"-k%1\"" ).arg( socketDir ); + + QProcess pgCtl; + pgCtl.start( mServerPath, arguments ); +-- +1.9.3 + diff --git a/0007-PostgreSQL-Don-t-listen-for-TCP-IP-connections.patch b/0007-PostgreSQL-Don-t-listen-for-TCP-IP-connections.patch new file mode 100644 index 0000000..a401e82 --- /dev/null +++ b/0007-PostgreSQL-Don-t-listen-for-TCP-IP-connections.patch @@ -0,0 +1,33 @@ +From 583ec681003395d5f3c3443c7ec82404b187afb9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Dan=20Vr=C3=A1til?= +Date: Wed, 7 May 2014 14:22:13 +0200 +Subject: [PATCH 7/7] PostgreSQL: Don't listen for TCP/IP connections + +Fixes Akonadi with internal PostgreSQL not starting when system-wide PostgreSQL +server is already running. We don't need TCP/IP anyway, because we talk to our +PostgreSQL via a Unix-socket. +--- + server/src/storage/dbconfigpostgresql.cpp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/server/src/storage/dbconfigpostgresql.cpp b/server/src/storage/dbconfigpostgresql.cpp +index ce8067b..83a5f91 100644 +--- a/server/src/storage/dbconfigpostgresql.cpp ++++ b/server/src/storage/dbconfigpostgresql.cpp +@@ -221,9 +221,10 @@ void DbConfigPostgresql::startInternalServer() + << QString::fromLatin1( "-w" ) + << QString::fromLatin1( "--timeout=10" ) // default is 60 seconds. + << QString::fromLatin1( "--pgdata=%1" ).arg( mPgData ) +- // set the directory for unix domain socket communication +- // -o will pass the switch to postgres +- << QString::fromLatin1( "-o \"-k%1\"" ).arg( socketDir ); ++ // These options are passed to postgres ++ // -k - directory for unix domain socket communication ++ // -h - disable listening for TCP/IP ++ << QString::fromLatin1( "-o \"-k%1\" -h ''" ).arg( socketDir ); + + QProcess pgCtl; + pgCtl.start( mServerPath, arguments ); +-- +1.9.3 + diff --git a/akonadi.spec b/akonadi.spec index cd1a53b..dc09b2c 100644 --- a/akonadi.spec +++ b/akonadi.spec @@ -19,7 +19,7 @@ Summary: PIM Storage Service Name: akonadi Version: 1.12.1 -Release: 7%{?dist} +Release: 8%{?dist} License: LGPLv2+ URL: http://community.kde.org/KDE_PIM/Akonadi @@ -39,7 +39,13 @@ Source10: akonadiserverrc.mysql ## upstream patches # 1.12 branch -Patch101: 0001-remove-invalid-part-before-parttable-migration.patch +Patch101: 0001-Use-per-thread-QDBusConnections.patch +Patch102: 0002-Remove-the-invalid-GID-part-from-PartTable-before-st.patch +Patch103: 0003-Fix-retrieving-of-GID-from-SQL-query-result-in-Fetch.patch +Patch104: 0004-Fix-PostgreSQL-startup-when-akonadiserverrc-contains.patch +Patch105: 0005-Fix-PostgreSQL-start-when-postmaster.pid-is-not-remo.patch +Patch106: 0006-Remove-space-from-an-argument-passed-to-postgres-ser.patch +Patch107: 0007-PostgreSQL-Don-t-listen-for-TCP-IP-connections.patch # master branch Patch212: 0012-Enable-concurrency-in-our-copy-of-QSQLITE-driver.patch @@ -101,6 +107,12 @@ See also: %{_sysconfdir}/akonadi/mysql-global.conf %setup -q -n akonadi-%{version} %patch101 -p1 -b .0001 +%patch102 -p1 -b .0002 +%patch103 -p1 -b .0003 +%patch104 -p1 -b .0004 +%patch105 -p1 -b .0005 +%patch106 -p1 -b .0006 +%patch107 -p1 -b .0007 %patch212 -p1 -b .0012 %patch213 -p1 -b .0013 @@ -208,6 +220,9 @@ fi %changelog +* Mon Jun 09 2014 Rex Dieter 1.12.1-8 +- pull in latest 1.12 branch commits + * Sat Jun 07 2014 Fedora Release Engineering - 1.12.1-7 - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild