From 04b405e17543fe1888431a127eff73355fad733b Mon Sep 17 00:00:00 2001 From: Rex Dieter Date: Aug 04 2014 23:39:05 +0000 Subject: 1.12.91 --- diff --git a/.gitignore b/.gitignore index c30bf02..5cfbff8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -/akonadi-1.12.1.tar.bz2 +/akonadi-1.12.91.tar.bz2 diff --git a/0001-Use-per-thread-QDBusConnections.patch b/0001-Use-per-thread-QDBusConnections.patch deleted file mode 100644 index ccb0e62..0000000 --- a/0001-Use-per-thread-QDBusConnections.patch +++ /dev/null @@ -1,485 +0,0 @@ -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/0002-Remove-the-invalid-GID-part-from-PartTable-before-st.patch b/0002-Remove-the-invalid-GID-part-from-PartTable-before-st.patch deleted file mode 100644 index dac2e31..0000000 --- a/0002-Remove-the-invalid-GID-part-from-PartTable-before-st.patch +++ /dev/null @@ -1,47 +0,0 @@ -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 deleted file mode 100644 index 4bb61f7..0000000 --- a/0003-Fix-retrieving-of-GID-from-SQL-query-result-in-Fetch.patch +++ /dev/null @@ -1,32 +0,0 @@ -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 deleted file mode 100644 index 4c2d3b9..0000000 --- a/0004-Fix-PostgreSQL-startup-when-akonadiserverrc-contains.patch +++ /dev/null @@ -1,85 +0,0 @@ -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 deleted file mode 100644 index 80dded8..0000000 --- a/0005-Fix-PostgreSQL-start-when-postmaster.pid-is-not-remo.patch +++ /dev/null @@ -1,71 +0,0 @@ -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 deleted file mode 100644 index 35dcdd7..0000000 --- a/0006-Remove-space-from-an-argument-passed-to-postgres-ser.patch +++ /dev/null @@ -1,34 +0,0 @@ -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 deleted file mode 100644 index a401e82..0000000 --- a/0007-PostgreSQL-Don-t-listen-for-TCP-IP-connections.patch +++ /dev/null @@ -1,33 +0,0 @@ -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/0012-Enable-concurrency-in-our-copy-of-QSQLITE-driver.patch b/0012-Enable-concurrency-in-our-copy-of-QSQLITE-driver.patch deleted file mode 100644 index 5717639..0000000 --- a/0012-Enable-concurrency-in-our-copy-of-QSQLITE-driver.patch +++ /dev/null @@ -1,190 +0,0 @@ -diff --git a/qsqlite/src/qsql_sqlite.cpp b/qsqlite/src/qsql_sqlite.cpp -index c1e9508..5da232f 100644 ---- a/qsqlite/src/qsql_sqlite.cpp -+++ b/qsqlite/src/qsql_sqlite.cpp -@@ -528,7 +528,7 @@ static int qGetSqliteOpenMode(QString opts) - return SQLITE_OPEN_READONLY; - } - // The SQLITE_OPEN_NOMUTEX flag causes the database connection to be in the multi-thread mode -- return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX; -+ return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE; - } - - /* -@@ -543,8 +543,10 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c - if (db.isEmpty()) - return false; - -+ sqlite3_enable_shared_cache(1); - if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, qGetSqliteOpenMode(conOpts), NULL) == SQLITE_OK) { - sqlite3_busy_timeout(d->access, qGetSqliteTimeout(conOpts)); -+ sqlite3_extended_result_codes(d->access, 1); - setOpen(true); - setOpenError(false); - return true; -diff --git a/qsqlite/src/sqlite_blocking.cpp b/qsqlite/src/sqlite_blocking.cpp -index c0fe3f2..180685c 100644 ---- a/qsqlite/src/sqlite_blocking.cpp -+++ b/qsqlite/src/sqlite_blocking.cpp -@@ -1,63 +1,94 @@ -+/* -+ Copyright (c) 2009 Bertjan Broeksema -+ Copyright (c) 2014 Daniel Vrátil -+ -+ 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 "sqlite_blocking.h" - - #include --#ifndef _WIN32 --#include --#else --#include --#define usleep(x) Sleep(x/1000) --#endif -- --#include "qdebug.h" -+ -+#include -+#include - #include "qstringbuilder.h" - #include "qthread.h" -+#include -+ -+/* Based on example in http://www.sqlite.org/unlock_notify.html */ - --QString debugString() -+struct UnlockNotification { -+ bool fired; -+ QWaitCondition cond; -+ QMutex mutex; -+}; -+ -+static void qSqlite3UnlockNotifyCb(void **apArg, int nArg) - { -- return QString( QLatin1Literal("[QSQLITE3: ") + QString::number( quint64( QThread::currentThreadId() ) ) + QLatin1Literal("] ") ); -+ for (int i = 0; i < nArg; ++i) { -+ UnlockNotification *ntf = static_cast(apArg[i]); -+ ntf->mutex.lock(); -+ ntf->fired = true; -+ ntf->cond.wakeOne(); -+ ntf->mutex.unlock(); -+ } - } - --int sqlite3_blocking_step( sqlite3_stmt *pStmt ) -+static int qSqlite3WaitForUnlockNotify(sqlite3 *db) - { -- // NOTE: The example at http://www.sqlite.org/unlock_notify.html says to wait -- // for SQLITE_LOCK but for some reason I don't understand I get -- // SQLITE_BUSY. -- int rc = sqlite3_step( pStmt ); -- -- QThread::currentThreadId(); -- if ( rc == SQLITE_BUSY ) -- qDebug() << debugString() << "sqlite3_blocking_step: Entering while loop"; -- -- while( rc == SQLITE_BUSY ) { -- usleep(5000); -- sqlite3_reset( pStmt ); -- rc = sqlite3_step( pStmt ); -- -- if ( rc != SQLITE_BUSY ) { -- qDebug() << debugString() << "sqlite3_blocking_step: Leaving while loop"; -+ int rc; -+ UnlockNotification un; -+ un.fired = false; -+ -+ rc = sqlite3_unlock_notify(db, qSqlite3UnlockNotifyCb, (void *)&un); -+ Q_ASSERT(rc == SQLITE_LOCKED || rc == SQLITE_OK); -+ -+ if (rc == SQLITE_OK) { -+ un.mutex.lock(); -+ if (!un.fired) { -+ un.cond.wait(&un.mutex); - } -+ un.mutex.unlock(); - } - - return rc; - } - --int sqlite3_blocking_prepare16_v2( sqlite3 *db, /* Database handle. */ -- const void *zSql, /* SQL statement, UTF-16 encoded */ -- int nSql, /* Length of zSql in bytes. */ -- sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ -- const void **pzTail /* OUT: Pointer to unused portion of zSql */ ) -+int sqlite3_blocking_step(sqlite3_stmt *pStmt) - { -- int rc = sqlite3_prepare16_v2( db, zSql, nSql, ppStmt, pzTail ); -- -- if ( rc == SQLITE_BUSY ) -- qDebug() << debugString() << "sqlite3_blocking_prepare16_v2: Entering while loop"; -+ int rc; -+ while (SQLITE_LOCKED_SHAREDCACHE == (rc = sqlite3_step(pStmt))) { -+ rc = qSqlite3WaitForUnlockNotify(sqlite3_db_handle(pStmt)); -+ if (rc != SQLITE_OK) { -+ break; -+ } -+ sqlite3_reset(pStmt); -+ } - -- while( rc == SQLITE_BUSY ) { -- usleep(500000); -- rc = sqlite3_prepare16_v2( db, zSql, nSql, ppStmt, pzTail ); -+ return rc; -+} - -- if ( rc != SQLITE_BUSY ) { -- qDebug() << debugString() << "sqlite3_prepare16_v2: Leaving while loop"; -+int sqlite3_blocking_prepare16_v2(sqlite3 *db, const void *zSql, int nSql, -+ sqlite3_stmt **ppStmt, const void **pzTail) -+{ -+ int rc; -+ while (SQLITE_LOCKED_SHAREDCACHE == (rc = sqlite3_prepare16_v2(db, zSql, nSql, ppStmt, pzTail))) { -+ rc = qSqlite3WaitForUnlockNotify(db); -+ if (rc != SQLITE_OK) { -+ break; - } - } - -diff --git a/qsqlite/src/sqlite_blocking.h b/qsqlite/src/sqlite_blocking.h -index 0d6f6a0..9f13946 100644 ---- a/qsqlite/src/sqlite_blocking.h -+++ b/qsqlite/src/sqlite_blocking.h -@@ -1,3 +1,22 @@ -+/* -+ Copyright (c) 2009 Bertjan Broeksema -+ -+ 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 SQLITE_BLOCKING_H - #define SQLITE_BLOCKING_H diff --git a/0013-Disable-global-transaction-mutex-for-QSQLITE3-and-en.patch b/0013-Disable-global-transaction-mutex-for-QSQLITE3-and-en.patch deleted file mode 100644 index 34de4e1..0000000 --- a/0013-Disable-global-transaction-mutex-for-QSQLITE3-and-en.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 24413dc44b0637d6c64e6b2105c2bcf1b99849a5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Dan=20Vr=C3=A1til?= -Date: Sun, 6 Apr 2014 19:50:38 +0200 -Subject: [PATCH 13/16] Disable global transaction mutex for QSQLITE3 and - enable transaction recording - -Our QSQLITE3 driver now supports concurrency, so we don't need to serialize -transactions in DataStore anymore. It is however still needed for the -QSQLITE driver shipped with Qt. - -Secondary, concurrency support also means possible transactions deadlocks and -timeouts, so we also need to enable transaction recording and replaying for -the QSQLITE3 backend. ---- - server/src/storage/datastore.cpp | 18 +++++++++++------- - server/src/storage/datastore.h | 2 +- - server/src/storage/dbtype.cpp | 5 +++++ - server/src/storage/dbtype.h | 3 +++ - server/src/storage/querybuilder.cpp | 20 ++++++++++++++++---- - server/src/storage/querybuilder.h | 2 +- - 6 files changed, 37 insertions(+), 13 deletions(-) - -diff --git a/server/src/storage/datastore.cpp b/server/src/storage/datastore.cpp -index 57d1e4e..0f04fa5 100644 ---- a/server/src/storage/datastore.cpp -+++ b/server/src/storage/datastore.cpp -@@ -61,8 +61,8 @@ using namespace Akonadi::Server; - static QMutex sTransactionMutex; - bool DataStore::s_hasForeignKeyConstraints = false; - --#define TRANSACTION_MUTEX_LOCK if ( DbType::type( m_database ) == DbType::Sqlite ) sTransactionMutex.lock() --#define TRANSACTION_MUTEX_UNLOCK if ( DbType::type( m_database ) == DbType::Sqlite ) sTransactionMutex.unlock() -+#define TRANSACTION_MUTEX_LOCK if ( DbType::isSystemSQLite( m_database ) ) sTransactionMutex.lock() -+#define TRANSACTION_MUTEX_UNLOCK if ( DbType::isSystemSQLite( m_database ) ) sTransactionMutex.unlock() - - /*************************************************************************** - * DataStore * -@@ -1083,23 +1083,27 @@ QDateTime DataStore::dateTimeToQDateTime( const QByteArray &dateTime ) - - void DataStore::addQueryToTransaction( const QSqlQuery &query, bool isBatch ) - { -- DbType::Type dbType = DbType::type( m_database ); - // This is used for replaying deadlocked transactions, so only record queries - // for backends that support concurrent transactions. -- if ( !inTransaction() || ( dbType != DbType::MySQL && dbType != DbType::PostgreSQL ) ) { -+ if ( !inTransaction() || DbType::isSystemSQLite( m_database ) ) { - return; - } - - m_transactionQueries.append( qMakePair( query, isBatch ) ); - } - --QSqlQuery DataStore::retryLastTransaction() -+QSqlQuery DataStore::retryLastTransaction( bool rollbackFirst ) - { -- DbType::Type dbType = DbType::type( m_database ); -- if ( !inTransaction() || ( dbType != DbType::MySQL && dbType != DbType::PostgreSQL ) ) { -+ if ( !inTransaction() || DbType::isSystemSQLite( m_database ) ) { - return QSqlQuery(); - } - -+ if ( rollbackFirst ) { -+ // In some cases the SQL database won't rollback the failed transaction, so -+ // we need to do it manually -+ m_database.driver()->rollbackTransaction(); -+ } -+ - // The database has rolled back the actual transaction, so reset the counter - // to 0 and start a new one in beginTransaction(). Then restore the level - // because this has to be completely transparent to the original caller -diff --git a/server/src/storage/datastore.h b/server/src/storage/datastore.h -index 8b4a2b7..8a0fe01 100644 ---- a/server/src/storage/datastore.h -+++ b/server/src/storage/datastore.h -@@ -317,7 +317,7 @@ protected: - * @return Returns an invalid query when error occurs, or the last replayed - * query on success. - */ -- QSqlQuery retryLastTransaction(); -+ QSqlQuery retryLastTransaction( bool rollbackFirst ); - - private Q_SLOTS: - void sendKeepAliveQuery(); -diff --git a/server/src/storage/dbtype.cpp b/server/src/storage/dbtype.cpp -index 495f532..7df2fb1 100644 ---- a/server/src/storage/dbtype.cpp -+++ b/server/src/storage/dbtype.cpp -@@ -39,3 +39,8 @@ DbType::Type DbType::typeForDriverName( const QString &driverName ) - } - return Unknown; - } -+ -+bool DbType::isSystemSQLite( const QSqlDatabase &db ) -+{ -+ return db.driverName() == QLatin1String( "QSQLITE" ); -+} -diff --git a/server/src/storage/dbtype.h b/server/src/storage/dbtype.h -index a95a833..3595604 100644 ---- a/server/src/storage/dbtype.h -+++ b/server/src/storage/dbtype.h -@@ -42,6 +42,9 @@ namespace DbType - /** Returns the type for the given driver name. */ - Type typeForDriverName( const QString &driverName ); - -+ /** Returns true when using QSQLITE driver shipped with Qt, FALSE otherwise */ -+ bool isSystemSQLite( const QSqlDatabase &db ); -+ - } // namespace DbType - } // namespace Server - } // namespace Akonadi -diff --git a/server/src/storage/querybuilder.cpp b/server/src/storage/querybuilder.cpp -index 0abad4a..0530b11 100644 ---- a/server/src/storage/querybuilder.cpp -+++ b/server/src/storage/querybuilder.cpp -@@ -320,10 +320,10 @@ QString QueryBuilder::buildQuery() - return statement; - } - --bool QueryBuilder::retryLastTransaction() -+bool QueryBuilder::retryLastTransaction( bool rollback ) - { - #ifndef QUERYBUILDER_UNITTEST -- mQuery = DataStore::self()->retryLastTransaction(); -+ mQuery = DataStore::self()->retryLastTransaction( rollback ); - return !mQuery.lastError().isValid(); - #else - return true; -@@ -400,9 +400,21 @@ bool QueryBuilder::exec() - akDebug() << mQuery.lastError().text(); - return retryLastTransaction(); - } -+ } else if ( mDatabaseType == DbType::Sqlite && !DbType::isSystemSQLite( DataStore::self()->database() ) ) { -+ const int error = mQuery.lastError().number(); -+ if ( error == 6 /* SQLITE_LOCKED */ ) { -+ akDebug() << "QueryBuilder::exec(): database reported transaction deadlock, retrying transaction"; -+ akDebug() << mQuery.lastError().text(); -+ return retryLastTransaction(); -+ } else if ( error == 5 /* SQLITE_BUSY */ ) { -+ akDebug() << "QueryBuilder::exec(): database reported transaction timeout, retrying transaction"; -+ akDebug() << mQuery.lastError().text(); -+ return retryLastTransaction( true ); -+ } - } else if ( mDatabaseType == DbType::Sqlite ) { -- // We can't have a transaction deadlock in SQLite, because it does not support -- // concurrent transactions and DataStore serializes them through a global lock. -+ // We can't have a transaction deadlock in SQLite when using driver shipped -+ // with Qt, because it does not support concurrent transactions and DataStore -+ // serializes them through a global lock. - } - - akError() << "DATABASE ERROR:"; -diff --git a/server/src/storage/querybuilder.h b/server/src/storage/querybuilder.h -index 235a099..b380f93 100644 ---- a/server/src/storage/querybuilder.h -+++ b/server/src/storage/querybuilder.h -@@ -244,7 +244,7 @@ class QueryBuilder - */ - void sqliteAdaptUpdateJoin( Query::Condition &cond ); - -- bool retryLastTransaction(); -+ bool retryLastTransaction( bool rollback = false); - - private: - QString mTable; --- -1.9.0 - diff --git a/akonadi.spec b/akonadi.spec index 9a1befe..6fa614c 100644 --- a/akonadi.spec +++ b/akonadi.spec @@ -18,8 +18,8 @@ Summary: PIM Storage Service Name: akonadi -Version: 1.12.1 -Release: 10%{?dist} +Version: 1.12.91 +Release: 1%{?dist} License: LGPLv2+ URL: http://community.kde.org/KDE_PIM/Akonadi @@ -38,20 +38,8 @@ Source10: akonadiserverrc.mysql ## upstreamable patches ## upstream patches -# 1.12 branch -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 -Patch213: 0013-Disable-global-transaction-mutex-for-QSQLITE3-and-en.patch - -%define mysql_conf_timestamp 20140415 +%define mysql_conf_timestamp 20140709 BuildRequires: automoc4 BuildRequires: boost-devel @@ -106,16 +94,6 @@ See also: %{_sysconfdir}/akonadi/mysql-global.conf %prep %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 - %build mkdir -p %{_target_platform} @@ -223,6 +201,9 @@ fi %changelog +* Mon Aug 04 2014 Rex Dieter 1.12.91-1 +- 1.12.91 + * Tue Jul 08 2014 Rex Dieter 1.12.1-10 - scriptlet polish diff --git a/sources b/sources index 7eb8642..2f7d2b1 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -9a4a99d10e003a267a515fc60de4f817 akonadi-1.12.1.tar.bz2 +6ba7a7329ac48495d44b410b00bc27b5 akonadi-1.12.91.tar.bz2