Hello community,

here is the log from the commit of package akonadi-runtime for openSUSE:Factory 
checked in at 2014-03-30 07:50:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/akonadi-runtime (Old)
 and      /work/SRC/openSUSE:Factory/.akonadi-runtime.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "akonadi-runtime"

Changes:
--------
--- /work/SRC/openSUSE:Factory/akonadi-runtime/akonadi-runtime.changes  
2014-03-18 17:16:44.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.akonadi-runtime.new/akonadi-runtime.changes     
2014-03-30 07:54:02.000000000 +0200
@@ -1,0 +2,28 @@
+Thu Mar 27 17:34:53 UTC 2014 - [email protected]
+
+- Update to 1.12.0
+  - KDE 4.13 RC release
+   * See http://www.kde.org/announcements/announce-4.13-beta3.php
+
+- Drop upstreamed patch do-not-emit-itemchanged.diff.
+
+-------------------------------------------------------------------
+Sun Mar 23 12:44:34 UTC 2014 - [email protected]
+
+- Add upstream patch do-not-emit-itemchanged.diff to prevent 
+  baloo from constantly indexing the maildir
+
+-------------------------------------------------------------------
+Thu Mar 20 17:59:08 UTC 2014 - [email protected]
+
+- Update to 1.11.90
+   * KDE 4.13 Beta 3  release
+   * See http://www.kde.org/announcements/announce-4.13-beta3.php
+
+- Drop upstreamed patches:
+  * janitor-move-parts-as-required-during-check.diff
+  * fix-postgresql-query.diff
+  * fix-mailrefresh.diff
+  * fix-postgresql-2.diff
+
+-------------------------------------------------------------------
@@ -10,2 +38,3 @@
-- Add upstream patch fix-postgresql-query.diff to fix the issue
-  when migrating an existing PostgreSQL database
+- Add upstream patches fix-postgresql-query.diff, 
+  fix-postgresql-2.diff to fix the issue when migrating an existing 
+  PostgreSQL database
@@ -18 +47 @@
-- Update to 4.12.80
+- Update to 1.11.80

Old:
----
  akonadi-1.11.80.tar.bz2
  fix-mailrefresh.diff
  fix-postgresql-2.diff
  fix-postgresql-query.diff
  janitor-move-parts-as-required-during-check.diff

New:
----
  akonadi-1.12.0.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ akonadi-runtime.spec ++++++
--- /var/tmp/diff_new_pack.AynEGz/_old  2014-03-30 07:57:13.000000000 +0200
+++ /var/tmp/diff_new_pack.AynEGz/_new  2014-03-30 07:57:13.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           akonadi-runtime
-Version:        1.11.80
+Version:        1.12.0
 Release:        0
 %define rversion %{version}
 %define rname   akonadi
@@ -26,14 +26,6 @@
 Group:          System/GUI/KDE
 Url:            http://akonadi-project.org
 Source:         
http://download.kde.org/stable/%{rname}/src/%{rname}-%{version}.tar.bz2
-# PATCH-FIX-UPSTREAM Fix wrong query statement for migration of a PostgreSQL DB
-Patch1:         fix-postgresql-query.diff
-# PATCH-FIX-UPSTREAM Fix issue that folders are not automatically 
refreshed/checked for new emails
-Patch2:         fix-mailrefresh.diff
-# PATCH-FIX-UPSTREAM Fix another issue with the PostgreSQL DB migration
-Patch3:         fix-postgresql-2.diff
-# PATCH-FIX-UPSTREAM Akonadi 1.13 -- Move parts to/from database when 
SizeTreshold is changed
-Patch4:         janitor-move-parts-as-required-during-check.diff
 BuildRequires:  boost-devel
 BuildRequires:  cmake >= 2.8.8
 BuildRequires:  fdupes
@@ -77,10 +69,6 @@
 
 %prep
 %setup -q -n %{rname}-%{rversion}
-%patch1 -p1
-%patch2 -p1
-%patch3 -p1
-%patch4 -p1
 
 %build
   %cmake_kde4 -d build -- -DCONFIG_INSTALL_DIR=/etc 
-DINSTALL_QSQLITE_IN_QT_PREFIX=TRUE -DWITH_SOPRANO=FALSE

++++++ akonadi-1.11.80.tar.bz2 -> akonadi-1.12.0.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/CMakeLists.txt 
new/akonadi-1.12.0/CMakeLists.txt
--- old/akonadi-1.11.80/CMakeLists.txt  2014-02-28 22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/CMakeLists.txt   2014-03-25 14:32:48.000000000 +0100
@@ -49,8 +49,8 @@
 ############### The Akonadi version (used in AkonadiConfig.cmake) 
###############
 
 set(AKONADI_VERSION_MAJOR "1")
-set(AKONADI_VERSION_MINOR "11")
-set(AKONADI_VERSION_PATCH "80")
+set(AKONADI_VERSION_MINOR "12")
+set(AKONADI_VERSION_PATCH "0")
 
 set(AKONADI_VERSION 
"${AKONADI_VERSION_MAJOR}.${AKONADI_VERSION_MINOR}.${AKONADI_VERSION_PATCH}")
 set(AKONADI_VERSION_STRING "${AKONADI_VERSION}")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/NEWS new/akonadi-1.12.0/NEWS
--- old/akonadi-1.11.80/NEWS    2014-02-28 22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/NEWS     2014-03-25 14:32:48.000000000 +0100
@@ -1,3 +1,18 @@
+1.12.0                           25-March-2014
+----------------------------------------------
+- Improved 'akonadictl status' command output
+- Fixed indexing of items in collections with short cache expiration
+- Fixed building Akonadi in subdirectory
+- Fixed deadlock in SearchManager
+- Fixed runtime warnings
+
+1.11.90                          19-March-2014
+----------------------------------------------
+- Fixed collection scheduling
+- Fixed indexing of expired items from local resources
+- Fixed database schema update with PostgreSQL
+- Fixes in searching and search updates
+
 1.11.80                       28-February-2014
 ----------------------------------------------
 - Server-search support
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/CMakeLists.txt 
new/akonadi-1.12.0/server/CMakeLists.txt
--- old/akonadi-1.11.80/server/CMakeLists.txt   2014-02-28 22:38:09.000000000 
+0100
+++ new/akonadi-1.12.0/server/CMakeLists.txt    2014-03-25 14:32:48.000000000 
+0100
@@ -44,18 +44,18 @@
           --stringparam code header
           --stringparam className ${_className}
           --stringparam fileName ${_fileBaseName}
-          ${CMAKE_SOURCE_DIR}/server/src/storage/schema.xsl
+          ${Akonadi_SOURCE_DIR}/server/src/storage/schema.xsl
           ${_schemaXml}
   COMMAND ${XSLTPROC_EXECUTABLE}
           --output ${CMAKE_CURRENT_BINARY_DIR}/${_fileBaseName}.cpp
           --stringparam code source
           --stringparam className ${_className}
           --stringparam fileName ${_fileBaseName}
-          ${CMAKE_SOURCE_DIR}/server/src/storage/schema.xsl
+          ${Akonadi_SOURCE_DIR}/server/src/storage/schema.xsl
           ${_schemaXml}
-  DEPENDS ${CMAKE_SOURCE_DIR}/server/src/storage/schema.xsl
-          ${CMAKE_SOURCE_DIR}/server/src/storage/schema-header.xsl
-          ${CMAKE_SOURCE_DIR}/server/src/storage/schema-source.xsl
+  DEPENDS ${Akonadi_SOURCE_DIR}/server/src/storage/schema.xsl
+          ${Akonadi_SOURCE_DIR}/server/src/storage/schema-header.xsl
+          ${Akonadi_SOURCE_DIR}/server/src/storage/schema-source.xsl
           ${_schemaXml}
 )
 endmacro()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/akonadictl/main.cpp 
new/akonadi-1.12.0/server/akonadictl/main.cpp
--- old/akonadi-1.11.80/server/akonadictl/main.cpp      2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/akonadictl/main.cpp       2014-03-25 
14:32:48.000000000 +0100
@@ -38,6 +38,7 @@
 #include "controlmanagerinterface.h"
 #include "akonadistarter.h"
 #include "xdgbasedirs_p.h"
+#include <QSettings>
 
 #if defined(HAVE_UNISTD_H) && !defined(Q_WS_WIN)
 #include <unistd.h>
@@ -119,11 +120,40 @@
   return true;
 }
 
+static bool checkAvailableAgentTypes()
+{
+  const QStringList dirs = Akonadi::XdgBaseDirs::findAllResourceDirs( "data", 
QLatin1String( "akonadi/agents" ) );
+  QStringList types;
+  Q_FOREACH ( const QString &pluginDir, dirs ) {
+    QDir dir( pluginDir );
+    const QStringList plugins = dir.entryList( QStringList() << QLatin1String( 
"*.desktop" ), QDir::Files );
+    Q_FOREACH ( const QString &plugin, plugins ) {
+      QSettings pluginInfo( pluginDir + QLatin1String("/") + plugin, 
QSettings::IniFormat );
+      pluginInfo.beginGroup( QLatin1String( "Desktop Entry" ) );
+      types << pluginInfo.value( QLatin1String( "X-Akonadi-Identifier" ) 
).toString();
+    }
+  }
+
+  // Remove duplicates from multiple pluginDirs
+  types.removeDuplicates();
+  types.sort();
+
+  fprintf( stderr, "Available Agent Types: ");
+  if ( types.isEmpty() ) {
+    fprintf( stderr, "No agent types found! \n");
+  } else {
+    fprintf( stderr, "%s\n", qPrintable( types.join( QLatin1String( ", " ) ) ) 
);
+  }
+
+  return true;
+}
+
 static bool statusServer()
 {
   checkAkonadiControlStatus();
   checkAkonadiServerStatus();
   checkSearchSupportStatus();
+  checkAvailableAgentTypes();
   return true;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/akonadi.cpp 
new/akonadi-1.12.0/server/src/akonadi.cpp
--- old/akonadi-1.11.80/server/src/akonadi.cpp  2014-02-28 22:38:09.000000000 
+0100
+++ new/akonadi-1.12.0/server/src/akonadi.cpp   2014-03-25 14:32:48.000000000 
+0100
@@ -200,7 +200,8 @@
     const QStringList searchManagers = settings.value( QLatin1String( 
"Search/Manager" ),
                                                        QStringList() << 
QLatin1String( "Nepomuk" )
                                                                      << 
QLatin1String( "Agent" ) ).toStringList();
-    mSearchManager = new SearchManager( searchManagers, this );
+    mSearchManager = new SearchManagerThread( searchManagers, this );
+    mSearchManager->start();
 
     new ServerAdaptor( this );
     QDBusConnection::sessionBus().registerObject( QLatin1String( "/Server" ), 
this );
@@ -260,6 +261,7 @@
     quitThread( mItemRetrievalThread );
     mAgentSearchManagerThread->stop();
     quitThread( mAgentSearchManagerThread );
+    quitThread( mSearchManager );
 
     delete mSearchManager;
     mSearchManager = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/akonadi.h 
new/akonadi-1.12.0/server/src/akonadi.h
--- old/akonadi-1.11.80/server/src/akonadi.h    2014-02-28 22:38:09.000000000 
+0100
+++ new/akonadi-1.12.0/server/src/akonadi.h     2014-03-25 14:32:48.000000000 
+0100
@@ -32,7 +32,7 @@
 
 class Connection;
 class CacheCleaner;
-class SearchManager;
+class SearchManagerThread;
 class ItemRetrievalThread;
 class SearchTaskManagerThread;
 class StorageJanitorThread;
@@ -75,7 +75,7 @@
     SearchTaskManagerThread *mAgentSearchManagerThread;
     QProcess *mDatabaseProcess;
     QVector< QPointer<Connection> > mConnections;
-    SearchManager *mSearchManager;
+    SearchManagerThread *mSearchManager;
     bool mAlreadyShutdown;
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/cachecleaner.cpp 
new/akonadi-1.12.0/server/src/cachecleaner.cpp
--- old/akonadi-1.11.80/server/src/cachecleaner.cpp     2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/cachecleaner.cpp      2014-03-25 
14:32:48.000000000 +0100
@@ -93,8 +93,12 @@
       akDebug() << "found" << parts.count() << "item parts to expire in 
collection" << collection.name();
       // clear data field
       Q_FOREACH ( Part part, parts ) {
-        if ( !PartHelper::truncate( part ) ) {
-          akDebug() << "failed to update item part" << part.id();
+        try {
+          if ( !PartHelper::truncate( part ) ) {
+            akDebug() << "failed to update item part" << part.id();
+          }
+        } catch ( const PartHelperException &e ) {
+            akError() << e.type() << e.what();
         }
       }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/collectionscheduler.cpp 
new/akonadi-1.12.0/server/src/collectionscheduler.cpp
--- old/akonadi-1.11.80/server/src/collectionscheduler.cpp      2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/collectionscheduler.cpp       2014-03-25 
14:32:48.000000000 +0100
@@ -65,7 +65,8 @@
 
 void CollectionScheduler::collectionAdded( qint64 collectionId )
 {
-  const Collection collection = Collection::retrieveById( collectionId );
+  Collection collection = Collection::retrieveById( collectionId );
+  DataStore::self()->activeCachePolicy( collection );
   if ( shouldScheduleCollection( collection ) ) {
     QMetaObject::invokeMethod( this, "scheduleCollection",
                                Qt::QueuedConnection,
@@ -79,6 +80,7 @@
   Q_FOREACH ( const Collection &collection, mSchedule ) {
     if ( collection.id() == collectionId ) {
       Collection changed = Collection::retrieveById( collectionId );
+      DataStore::self()->activeCachePolicy( changed );
       if ( hasChanged( collection, changed ) ) {
         if ( shouldScheduleCollection( changed ) ) {
           locker.unlock();
@@ -94,6 +96,9 @@
       return;
     }
   }
+
+  // We don't know the collection yet, but maybe now it can be scheduled
+  collectionAdded( collectionId );
 }
 
 void CollectionScheduler::collectionRemoved( qint64 collectionId )
@@ -127,10 +132,11 @@
 
   // Get next collection to expire and start the timer
   const uint next = mSchedule.constBegin().key();
-  mScheduler->start( ( next - QDateTime::currentDateTime().toTime_t() ) * 1000 
);
+  // cast next - now() to int, so that we get negative result when next is in 
the past
+  mScheduler->start( qMax( 0, ( int ) ( next - 
QDateTime::currentDateTime().toTime_t() ) * 1000 ) );
 }
 
-void CollectionScheduler::scheduleCollection( Collection collection )
+void CollectionScheduler::scheduleCollection( Collection collection, bool 
shouldStartScheduler )
 {
   QMutexLocker locker( &mScheduleLock );
   if ( mSchedule.values().contains( collection ) ) {
@@ -164,7 +170,7 @@
   }
 
   mSchedule.insert( nextCheck, collection );
-  if ( !mScheduler->isActive() ) {
+  if ( shouldStartScheduler && !mScheduler->isActive() ) {
     mScheduleLock.unlock();
     startScheduler();
   }
@@ -188,11 +194,9 @@
   mSchedule.remove( timestamp );
   mScheduleLock.unlock();
 
-  const QDateTime now = QDateTime::currentDateTime();
-
   Q_FOREACH ( const Collection &collection, collections ) {
     collectionExpired( collection );
-    scheduleCollection( collection );
+    scheduleCollection( collection, false );
   }
 
   startScheduler();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/collectionscheduler.h 
new/akonadi-1.12.0/server/src/collectionscheduler.h
--- old/akonadi-1.11.80/server/src/collectionscheduler.h        2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/collectionscheduler.h 2014-03-25 
14:32:48.000000000 +0100
@@ -70,7 +70,7 @@
     void initScheduler();
     void schedulerTimeout();
     void startScheduler();
-    void scheduleCollection( /*sic!*/ Collection collection );
+    void scheduleCollection( /*sic!*/ Collection collection, bool 
shouldStartScheduler = true );
 
   protected:
     QMutex mScheduleLock;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/handler/fetchhelper.cpp 
new/akonadi-1.12.0/server/src/handler/fetchhelper.cpp
--- old/akonadi-1.11.80/server/src/handler/fetchhelper.cpp      2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/handler/fetchhelper.cpp       2014-03-25 
14:32:48.000000000 +0100
@@ -20,6 +20,7 @@
 #include "fetchhelper.h"
 
 #include "akdebug.h"
+#include "akdbus.h"
 #include "connection.h"
 #include "handler.h"
 #include "handlerhelper.h"
@@ -36,6 +37,7 @@
 #include "storage/transaction.h"
 #include "utils.h"
 #include "intervalcheck.h"
+#include "agentmanagerinterface.h"
 
 #include <QtCore/QLocale>
 #include <QtCore/QStringList>
@@ -221,10 +223,58 @@
   return tagQuery.query();
 }
 
+bool FetchHelper::isScopeLocal( const Scope &scope )
+{
+  // Get list of all resources that own all items in the scope
+  QueryBuilder qb( PimItem::tableName(), QueryBuilder::Select );
+  qb.setDistinct( true );
+  qb.addColumn( Resource::nameFullColumnName() );
+  qb.addJoin( QueryBuilder::LeftJoin, Collection::tableName(), 
PimItem::collectionIdFullColumnName(), Collection::idFullColumnName() );
+  qb.addJoin( QueryBuilder::LeftJoin, Resource::tableName(), 
Collection::resourceIdFullColumnName(), Resource::idFullColumnName() );
+  ItemQueryHelper::scopeToQuery( scope, mConnection, qb );
+  if ( mConnection->resourceContext().isValid() ) {
+    qb.addValueCondition( Resource::nameFullColumnName(), Query::NotEquals, 
mConnection->resourceContext().name() );
+  }
+
+  if ( !qb.exec() ) {
+    throw HandlerException( "Failed to query database" );
+    return false;
+  }
+
+  // If there is more than one resource, i.e. this is a fetch from multiple
+  // collections, then don't bother and just return FALSE. This case is aimed
+  // specifically on Baloo, which fetches items from each collection 
independently,
+  // so it will pass this check.
+  QSqlQuery query = qb.query();
+  if ( query.size() != 1) {
+    return false;
+  }
+
+  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 );
+  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();
+}
+
 bool FetchHelper::fetchItems( const QByteArray &responseIdentifier )
 {
   // retrieve missing parts
-  if ( !mFetchScope.cacheOnly() ) {
+  // HACK: isScopeLocal() is a workaround for resources that have cache 
expiration
+  // because when the cache expires, Baloo is not able to content of the 
items. So
+  // we allow fetch of items that belong to local resources (like maildir) to 
ignore
+  // cacheOnly and retrieve missing parts from the resource. However 
ItemRetriever
+  // is painfully slow with many items and is generally designed to fetch a few
+  // messages, not all of them. In the long term, we need a better way to do 
this.
+  if ( !mFetchScope.cacheOnly() || isScopeLocal( mScope ) ) {
     // trigger a collection sync if configured to do so
     triggerOnDemandFetch();
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/handler/fetchhelper.h 
new/akonadi-1.12.0/server/src/handler/fetchhelper.h
--- old/akonadi-1.11.80/server/src/handler/fetchhelper.h        2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/handler/fetchhelper.h 2014-03-25 
14:32:48.000000000 +0100
@@ -74,6 +74,7 @@
     QStack<Collection> ancestorsForItem( Collection::Id parentColId );
     static bool needsAccessTimeUpdate( const QVector<QByteArray> &parts );
     QVariant extractQueryResult( const QSqlQuery &query, ItemQueryColumns 
column ) const;
+    bool isScopeLocal( const Scope &scope );
 
   private:
     ImapStreamParser *mStreamParser;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/handler/modify.cpp 
new/akonadi-1.12.0/server/src/handler/modify.cpp
--- old/akonadi-1.11.80/server/src/handler/modify.cpp   2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/handler/modify.cpp    2014-03-25 
14:32:48.000000000 +0100
@@ -209,7 +209,7 @@
         collection.setQueryCollections( queryCollections );
         collection.setQueryAttributes( queryAttributes );
 
-        SearchManager::instance()->updateSearch( collection, 
db->notificationCollector() );
+        SearchManager::instance()->updateSearch( collection );
 
         changes.append( AKONADI_PARAM_PERSISTENTSEARCH );
       }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/akonadi-1.11.80/server/src/handler/searchpersistent.cpp 
new/akonadi-1.12.0/server/src/handler/searchpersistent.cpp
--- old/akonadi-1.11.80/server/src/handler/searchpersistent.cpp 2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/handler/searchpersistent.cpp  2014-03-25 
14:32:48.000000000 +0100
@@ -112,7 +112,7 @@
     return failureResponse( "Unable to commit transaction" );
   }
 
-  SearchManager::instance()->updateSearchAsync( col, 
DataStore::self()->notificationCollector() );
+  SearchManager::instance()->updateSearchAsync( col );
 
   const QByteArray b = HandlerHelper::collectionToByteArray( col );
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/handler/store.cpp 
new/akonadi-1.12.0/server/src/handler/store.cpp
--- old/akonadi-1.11.80/server/src/handler/store.cpp    2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/handler/store.cpp     2014-03-25 
14:32:48.000000000 +0100
@@ -186,6 +186,7 @@
   bool invalidateCache = false;
   bool undirty = false;
   bool silent = false;
+  bool notify = true;
 
   // apply modifications
   m_streamParser->beginList();
@@ -291,6 +292,8 @@
       undirty = true;
     } else if ( command == AKONADI_PARAM_INVALIDATECACHE ) {
       invalidateCache = true;
+    } else if ( command == AKONADI_PARAM_SILENT ) {
+      notify = false;
     } else if ( command == AKONADI_PARAM_SIZE ) {
       mSize = m_streamParser->readNumber();
       changes << AKONADI_PARAM_SIZE;
@@ -359,7 +362,9 @@
 
       // flags change notification went separatly during command parsing
       // GID-only changes are ignored to prevent resources from updating their 
storage when no actual change happened
-      if ( !changes.isEmpty() && !onlyFlagsChanged && !onlyGIDChanged ) {
+      if ( notify && !changes.isEmpty() && !onlyFlagsChanged && 
!onlyGIDChanged ) {
+        // Don't send FLAGS notification in itemChanged
+        changes.remove( AKONADI_PARAM_FLAGS );
         store->notificationCollector()->itemChanged( item, changes );
       }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/intervalcheck.cpp 
new/akonadi-1.12.0/server/src/intervalcheck.cpp
--- old/akonadi-1.11.80/server/src/intervalcheck.cpp    2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/intervalcheck.cpp     2014-03-25 
14:32:48.000000000 +0100
@@ -48,7 +48,7 @@
 
 void IntervalCheck::requestCollectionSync( const Collection &collection )
 {
-  QMetaObject::invokeMethod( this, "scheduleCollection",
+  QMetaObject::invokeMethod( this, "collectionExpired",
                              Qt::QueuedConnection,
                              Q_ARG( Collection, collection ) );
 }
@@ -80,10 +80,8 @@
     const int interval = qMax( MINIMUM_COLTREESYNC_INTERVAL, 
collection.cachePolicyCheckInterval() );
 
     const QDateTime lastExpectedCheck = now.addSecs( interval * -60 );
-    QMutexLocker locker( &m_lastSyncMutex );
     if ( !mLastCollectionTreeSyncs.contains( resourceName ) || 
mLastCollectionTreeSyncs.value( resourceName ) < lastExpectedCheck ) {
       mLastCollectionTreeSyncs.insert( resourceName, now );
-      locker.unlock();
       QMetaObject::invokeMethod( ItemRetrievalManager::instance(), 
"triggerCollectionTreeSync",
                                  Qt::QueuedConnection,
                                  Q_ARG( QString, resourceName ) );
@@ -94,12 +92,10 @@
   const int interval = qMax( MINIMUM_AUTOSYNC_INTERVAL, 
collection.cachePolicyCheckInterval() );
 
   const QDateTime lastExpectedCheck = now.addSecs( interval * -60 );
-  QMutexLocker locker( &m_lastSyncMutex );
   if ( mLastChecks.contains( collection.id() ) && mLastChecks.value( 
collection.id() ) > lastExpectedCheck ) {
     return;
   }
   mLastChecks.insert( collection.id(), now );
-  locker.unlock();
   QMetaObject::invokeMethod( ItemRetrievalManager::instance(), 
"triggerCollectionSync",
                              Qt::QueuedConnection,
                              Q_ARG( QString, collection.resource().name() ),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/intervalcheck.h 
new/akonadi-1.12.0/server/src/intervalcheck.h
--- old/akonadi-1.11.80/server/src/intervalcheck.h      2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/intervalcheck.h       2014-03-25 
14:32:48.000000000 +0100
@@ -53,10 +53,11 @@
     int collectionScheduleInterval( const Collection &collection );
     bool hasChanged( const Collection &collection, const Collection &changed );
     bool shouldScheduleCollection( const Collection &collection );
+
+  protected Q_SLOTS:
     void collectionExpired( const Collection &collection );
 
   private:
-    QMutex m_lastSyncMutex;
     QHash<int, QDateTime> mLastChecks;
     QHash<QString, QDateTime> mLastCollectionTreeSyncs;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/search/searchmanager.cpp 
new/akonadi-1.12.0/server/src/search/searchmanager.cpp
--- old/akonadi-1.11.80/server/src/search/searchmanager.cpp     2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/search/searchmanager.cpp      2014-03-25 
14:32:48.000000000 +0100
@@ -25,9 +25,9 @@
 #include "akdebug.h"
 #include "agentsearchengine.h"
 #include "nepomuksearchengine.h"
+#include "notificationmanager.h"
 #include "searchrequest.h"
 #include "searchtaskmanager.h"
-#include "storage/notificationcollector.h"
 #include "storage/datastore.h"
 #include "storage/querybuilder.h"
 #include "storage/transaction.h"
@@ -51,28 +51,41 @@
 
 Q_DECLARE_METATYPE( Collection )
 Q_DECLARE_METATYPE( QSet<qint64> )
+Q_DECLARE_METATYPE( QWaitCondition* )
+
+SearchManagerThread::SearchManagerThread( const QStringList &searchEngines, 
QObject *parent )
+  : QThread( parent )
+  , mSearchEngines( searchEngines )
+{
+  Q_ASSERT( QThread::currentThread() == QCoreApplication::instance()->thread() 
);
+}
+
+SearchManagerThread::~SearchManagerThread()
+{
+}
+
+void SearchManagerThread::run()
+{
+  SearchManager *manager = new SearchManager( mSearchEngines );
+  exec();
+  delete manager;
+}
 
 SearchManager::SearchManager( const QStringList &searchEngines, QObject 
*parent )
   : QObject( parent )
-  , mDBusConnection( QDBusConnection::connectToBus(
-          QDBusConnection::SessionBus,
-          QString::fromLatin1( "AkonadiServerSearchManager" ) ) )
 {
   qRegisterMetaType< QSet<qint64> >();
+  qRegisterMetaType<Collection>();
+  qRegisterMetaType<QWaitCondition*>();
 
-  Q_ASSERT( QThread::currentThread() == QCoreApplication::instance()->thread() 
);
   Q_ASSERT( sInstance == 0 );
   sInstance = this;
 
-  qRegisterMetaType<Collection>();
-
   mEngines.reserve( searchEngines.size() );
   Q_FOREACH ( const QString &engineName, searchEngines ) {
     if ( engineName == QLatin1String( "Nepomuk" ) ) {
 #ifdef HAVE_SOPRANO
       m_engines.append( new NepomukSearchEngine );
-#else
-      akError() << "Akonadi has been built without Nepomuk support!";
 #endif
     } else if ( engineName == QLatin1String( "Agent" ) ) {
       mEngines.append( new AgentSearchEngine );
@@ -90,23 +103,21 @@
       this,
       QDBusConnection::ExportAdaptors );
 
-
-  NotificationCollector *collector = 
DataStore::self()->notificationCollector();
-  connect( collector, SIGNAL(notify(Akonadi::NotificationMessageV3::List)),
-           this, 
SLOT(scheduleSearchUpdate(Akonadi::NotificationMessageV3::List)) );
-
-  // The timer will tick 30 seconds after last change notification. If a new 
notification
+  // The timer will tick 15 seconds after last change notification. If a new 
notification
   // is delivered in the meantime, the timer is reset
   mSearchUpdateTimer = new QTimer( this );
-  mSearchUpdateTimer->setInterval( 30 * 1000 );
+  mSearchUpdateTimer->setInterval( 15 * 1000 );
   mSearchUpdateTimer->setSingleShot( true );
   connect( mSearchUpdateTimer, SIGNAL(timeout()),
            this, SLOT(searchUpdateTimeout()) );
+
+  DataStore::self();
 }
 
 SearchManager::~SearchManager()
 {
   qDeleteAll( mEngines );
+  DataStore::self()->close();
   sInstance = 0;
 }
 
@@ -133,6 +144,7 @@
 
 void SearchManager::loadSearchPlugins()
 {
+  QStringList loadedPlugins;
   const QString pluginOverride = QString::fromLatin1( qgetenv( 
"AKONADI_OVERRIDE_SEARCHPLUGIN" ) );
   if ( !pluginOverride.isEmpty() ) {
     akDebug() << "Overriding the search plugins with: " << pluginOverride;
@@ -152,6 +164,10 @@
       }
 
       const QString libraryName = desktop.value( QLatin1String( 
"X-Akonadi-Library" ) ).toString();
+      if ( loadedPlugins.contains( libraryName ) ) {
+        qDebug() << "Already loaded one version of this plugin, skipping: " << 
libraryName;
+        continue;
+      }
       // When search plugin override is active, ignore all plugins except for 
the override
       if ( !pluginOverride.isEmpty() ) {
         if ( libraryName != pluginOverride ) {
@@ -179,33 +195,15 @@
 
       qDebug() << "SearchManager: loaded search plugin" << libraryName;
       mPlugins << plugin;
+      loadedPlugins << libraryName;
     }
   }
 }
 
-void SearchManager::scheduleSearchUpdate( const NotificationMessageV3::List 
&notifications )
+void SearchManager::scheduleSearchUpdate()
 {
-  QList<Entity::Id> newChanges;
-
-  Q_FOREACH ( const NotificationMessageV2 &msg, notifications ) {
-    // we don't care about collections changes
-    if ( msg.type() == NotificationMessageV2::Collections ) {
-      continue;
-    }
-
-    // Only these two operations can cause item to be added or removed from a
-    // persistent search (removal is handled automatically)
-    if ( msg.operation() == NotificationMessageV2::Add ||
-         msg.operation() == NotificationMessageV2::Modify )
-    {
-      newChanges << msg.uids();
-    }
-  }
-
-  if ( !newChanges.isEmpty() ) {
-    mPendingSearchUpdateIds << newChanges;
-    mSearchUpdateTimer->start();
-  }
+  // Reset if the timer is active
+  mSearchUpdateTimer->start();
 }
 
 void SearchManager::searchUpdateTimeout()
@@ -213,26 +211,61 @@
   // Get all search collections, that is subcollections of "Search", which 
always has ID 1
   const Collection::List collections = Collection::retrieveFiltered( 
Collection::parentIdFullColumnName(), 1 );
   Q_FOREACH ( const Collection &collection, collections ) {
-    updateSearch( collection, DataStore::self()->notificationCollector() );
+    updateSearchAsync( collection );
   }
 }
 
-void SearchManager::updateSearchAsync(const Collection& collection, 
NotificationCollector* collector)
+void SearchManager::updateSearchAsync( const Collection& collection )
 {
-  QMetaObject::invokeMethod( this, "updateSearch",
+  QMetaObject::invokeMethod( this, "updateSearchImpl",
                              Qt::QueuedConnection,
                              Q_ARG( Collection, collection ),
-                             Q_ARG( NotificationCollector*, collector ) );
+                             Q_ARG( QWaitCondition*, 0 ) );
 }
 
-bool SearchManager::updateSearch( const Collection &collection, 
NotificationCollector *collector )
+void SearchManager::updateSearch( const Collection &collection )
+{
+  QMutex mutex;
+  QWaitCondition cond;
+
+  mLock.lock();
+  if ( mUpdatingCollections.contains( collection.id() ) ) {
+    mLock.unlock();
+    return;
+  }
+  mUpdatingCollections.insert( collection.id() );
+  mLock.unlock();
+
+  QMetaObject::invokeMethod( this, "updateSearchImpl",
+                             Qt::QueuedConnection,
+                             Q_ARG( Collection, collection ),
+                             Q_ARG( QWaitCondition*, &cond ) );
+
+  // Now wait for updateSearchImpl to wake us.
+  mutex.lock();
+  cond.wait( &mutex );
+  mutex.unlock();
+
+  mLock.lock();
+  mUpdatingCollections.remove( collection.id() );
+  mLock.unlock();
+}
+
+#define wakeUpCaller(cond) \
+  if (cond) { \
+    cond->wakeAll(); \
+  }
+
+void SearchManager::updateSearchImpl( const Collection &collection, 
QWaitCondition *cond )
 {
   if ( collection.queryString().size() >= 32768 ) {
     qWarning() << "The query is at least 32768 chars long, which is the 
maximum size supported by the akonadi db schema. The query is therefore most 
likely truncated and will not be executed.";
-    return false;
+    wakeUpCaller(cond);
+    return;
   }
   if ( collection.queryString().isEmpty() ) {
-    return false;
+    wakeUpCaller(cond);
+    return;
   }
 
   const QStringList queryAttributes = collection.queryAttributes().split( 
QLatin1Char (' ') );
@@ -261,6 +294,13 @@
     queryCollections = queryAncestors;
   }
 
+  //This happens if we try to search a virtual collection in recursive mode 
(because virtual collections are excluded from listCollectionsRecursive)
+  if ( queryCollections.isEmpty() ) {
+    akDebug() << "No collections to search, you're probably trying to search a 
virtual collection.";
+    wakeUpCaller(cond);
+    return;
+  }
+
   // Query all plugins for search results
   SearchRequest request( "searchUpdate-" + QByteArray::number( 
QDateTime::currentDateTime().toTime_t() ) );
   request.setCollections( queryCollections );
@@ -269,7 +309,6 @@
   request.setRemoteSearch( remoteSearch );
   request.setStoreResults( true );
   request.setProperty( "SearchCollection", QVariant::fromValue( collection ) );
-  request.setProperty( "NotificationCollector", QVariant::fromValue( collector 
) );
   connect( &request, SIGNAL(resultsAvailable(QSet<qint64>)),
            this, SLOT(searchUpdateResultsAvailable(QSet<qint64>)) );
   request.exec(); // blocks until all searches are done
@@ -281,7 +320,8 @@
   qb.addColumn( CollectionPimItemRelation::rightColumn() );
   qb.addValueCondition( CollectionPimItemRelation::leftColumn(), 
Query::Equals, collection.id() );
   if ( !qb.exec() ) {
-    return false;
+    wakeUpCaller(cond);
+    return;
   }
 
   DataStore::self()->beginTransaction();
@@ -297,31 +337,32 @@
   }
 
   if ( !DataStore::self()->commitTransaction() ) {
-    return false;
+    wakeUpCaller(cond);
+    return;
   }
 
   if ( !toRemove.isEmpty() ) {
     SelectQueryBuilder<PimItem> qb;
     qb.addValueCondition( PimItem::idFullColumnName(), Query::In, toRemove );
     if ( !qb.exec() ) {
-      return false;
+      wakeUpCaller(cond);
+      return;
     }
 
     const QVector<PimItem> removedItems = qb.result();
-    collector->itemsUnlinked( removedItems, collection );
+    DataStore::self()->notificationCollector()->itemsUnlinked( removedItems, 
collection );
   }
 
   akDebug() << "Search update finished";
   akDebug() << "All results:" << results.count();
   akDebug() << "Removed results:" << toRemove.count();
 
-  return true;
+  wakeUpCaller(cond);
 }
 
 void SearchManager::searchUpdateResultsAvailable( const QSet<qint64> &results )
 {
   const Collection collection = sender()->property( "SearchCollection" 
).value<Collection>();
-  NotificationCollector *collector = sender()->property( 
"NotificationCollector" ).value<NotificationCollector *>();
   akDebug() << "searchUpdateResultsAvailable" << collection.id() << 
results.count() << "results";
 
   QSet<qint64> newMatches = results;
@@ -371,8 +412,8 @@
       return ;
     }
     const QVector<PimItem> newItems = qb.result();
-    collector->itemsLinked( newItems, collection );
+    DataStore::self()->notificationCollector()->itemsLinked( newItems, 
collection );
     // Force collector to dispatch the notification now
-    collector->dispatchNotifications();
+    DataStore::self()->notificationCollector()->dispatchNotifications();
   }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/search/searchmanager.h 
new/akonadi-1.12.0/server/src/search/searchmanager.h
--- old/akonadi-1.11.80/server/src/search/searchmanager.h       2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/search/searchmanager.h        2014-03-25 
14:32:48.000000000 +0100
@@ -21,12 +21,14 @@
 #ifndef SEARCHMANAGER_H
 #define SEARCHMANAGER_H
 
-#include <QObject>
+#include <QThread>
 #include <QVector>
+#include <QMutex>
 #include <QDBusConnection>
 
 #include <libs/notificationmessagev3_p.h>
 
+class QWaitCondition;
 class QTimer;
 
 namespace Akonadi {
@@ -39,6 +41,20 @@
 class AbstractSearchEngine;
 class Collection;
 
+
+class SearchManagerThread : public QThread
+{
+  public:
+    SearchManagerThread( const QStringList &searchEngines, QObject *parent = 0 
);
+    ~SearchManagerThread();
+
+    void run();
+
+  private:
+    QStringList mSearchEngines;
+};
+
+
 /**
  * SearchManager creates and deletes persistent searches for all currently
  * active search engines.
@@ -73,27 +89,35 @@
     /**
      * Updates the search query asynchronously. Returns immediately
      */
-    void updateSearchAsync( const Collection &collection, 
NotificationCollector *collector );
+    void updateSearchAsync( const Collection &collection );
 
     /**
-     * Returns currently available search plugins.
+     * Updates the search query synchronously.
      */
-    QVector<AbstractSearchPlugin *> searchPlugins() const;
+    void updateSearch( const Collection &collection );
 
-  public Q_SLOTS:
     /**
-     * Update the search query of the given collection synchronously.
-     *
-     * This method blocks until all search queries are finished.
+     * Returns currently available search plugins.
      */
-    bool updateSearch( const Collection &collection, NotificationCollector 
*collector );
+    QVector<AbstractSearchPlugin *> searchPlugins() const;
 
+  public Q_SLOTS:
+    void scheduleSearchUpdate();
 
   private Q_SLOTS:
-    void scheduleSearchUpdate( const Akonadi::NotificationMessageV3::List 
&notifications );
     void searchUpdateTimeout();
     void searchUpdateResultsAvailable( const QSet<qint64> &results );
 
+    /**
+     * Actual implementation of search updates.
+     *
+     * Since caller invokes this method from a different thread, they use
+     * QMetaObject::invokeMethod(). To still make it possible for callers to 
behave
+     * synchrounously, we can pass in a QWaitCondition that the code will wake 
up
+     * once the search update is completed.
+     */
+    void updateSearchImpl( const Collection &collection, QWaitCondition *cond 
);
+
   private:
     void loadSearchPlugins();
 
@@ -102,11 +126,10 @@
     QVector<AbstractSearchEngine *> mEngines;
     QVector<AbstractSearchPlugin *> mPlugins;
 
-    // agents dbus interface cache
-    QDBusConnection mDBusConnection;
-
-    QList<qint64> mPendingSearchUpdateIds;
     QTimer *mSearchUpdateTimer;
+
+    QMutex mLock;
+    QSet<qint64> mUpdatingCollections;
 };
 
 } // namespace Server
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/akonadi-1.11.80/server/src/search/searchtaskmanager.cpp 
new/akonadi-1.12.0/server/src/search/searchtaskmanager.cpp
--- old/akonadi-1.11.80/server/src/search/searchtaskmanager.cpp 2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/search/searchtaskmanager.cpp  2014-03-25 
14:32:48.000000000 +0100
@@ -108,6 +108,7 @@
   qb.addColumn( Collection::idFullColumnName() );
   qb.addColumn( Resource::nameFullColumnName() );
 
+  Q_ASSERT(!task->collections.isEmpty());
   QVariantList list;
   Q_FOREACH ( qint64 collection, task->collections ) {
     list << collection;
@@ -128,9 +129,11 @@
     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 ( !mAgentManager.agentInstanceOnline( resourceId ) ) {
       akDebug() << "Agent" << resourceId << "is offline, skipping";
-    } else*/ {
+    } else if ( mAgentManager.agentInstanceStatus( resourceId ) > 2 ) { // 2 
== Broken, 3 == Not Configured
+      akDebug() << "Agent" << resourceId << "is broken or not configured";
+    } else {
       const qint64 collectionId = query.value( 0 ).toLongLong();
       akDebug() << "Enqueued search query (" << resourceId << ", " << 
collectionId << ")";
       task->queries << qMakePair( resourceId,  collectionId );
@@ -193,12 +196,14 @@
   ResourceTask *task = iter.value();
   SearchTask *parentTask = task->parentTask;
   QMutexLocker locker(&parentTask->sharedLock);
+  //erase the task before allResourceTasksCompleted
+  SearchTaskManager::TasksMap::Iterator it = mRunningTasks.erase( iter );
   // We're not clearing the results since we don't want to clear successful 
results from other resources
   parentTask->complete = allResourceTasksCompleted( parentTask );
   parentTask->notifier.wakeAll();
   delete task;
 
-  return mRunningTasks.erase( iter );
+  return it;
 }
 
 void SearchTaskManager::searchLoop()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/akonadi-1.11.80/server/src/storage/dbupdater.cpp 
new/akonadi-1.12.0/server/src/storage/dbupdater.cpp
--- old/akonadi-1.11.80/server/src/storage/dbupdater.cpp        2014-02-28 
22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/storage/dbupdater.cpp 2014-03-25 
14:32:48.000000000 +0100
@@ -361,7 +361,7 @@
                                    "       PartTable.datasize, 
PartTable.version, PartTable.external "
                                    "FROM PartTable "
                                    "LEFT JOIN PartTypeTable ON "
-                                   "       PartTable.name = 
CONCAT(encode(PartTypeTable.ns, 'escape'), ':', encode(PartTypeTable.name, 
'escape'))"  );
+                                   "          PartTable.name = 
CONCAT(PartTypeTable.ns, ':', PartTypeTable.name)"  );
     } else if ( dbType == DbType::MySQL ) {
       queryString = QLatin1String( "INSERT INTO PartTable_new (id, pimItemId, 
partTypeId, data, datasize, version, external) "
                                    "SELECT PartTable.id, PartTable.pimItemId, 
PartTypeTable.id, PartTable.data, "
@@ -390,28 +390,30 @@
 
     if ( dbType == DbType::PostgreSQL  || dbType == DbType::Sqlite ) {
       if ( dbType == DbType::PostgreSQL ) {
-        DataStore::self()->database().transaction();
+        DataStore::self()->beginTransaction();
       }
 
       if ( !query.exec( QLatin1String( "ALTER TABLE PartTable RENAME TO 
PartTable_old" ) ) ) {
         akError() << query.lastError().text();
-        DataStore::self()->database().rollback();
+        DataStore::self()->rollbackTransaction();
         return false;
       }
 
       // If this fails in SQLite (i.e. without transaction), we can still 
recover on next start)
       if ( !query.exec( QLatin1String( "ALTER TABLE PartTable_new RENAME TO 
PartTable" ) ) ) {
         akError() << query.lastError().text();
-        DataStore::self()->database().rollback();
+        if ( DataStore::self()->inTransaction() ) {
+          DataStore::self()->rollbackTransaction();
+        }
         return false;
       }
 
       if ( dbType == DbType::PostgreSQL ) {
-        DataStore::self()->database().commit();
+        DataStore::self()->commitTransaction();
       }
     } else { // MySQL cannot do rename in transaction, but supports atomic 
renames
-      if ( !query.exec( QLatin1String( "RENAME TABLE PartTable     TO 
PartTable_old,"
-                                            "             PartTable_new TO 
PartTable" ) ) ) {
+      if ( !query.exec( QLatin1String( "RENAME TABLE PartTable TO 
PartTable_old,"
+                                       "             PartTable_new TO 
PartTable" ) ) ) {
         akError() << query.lastError().text();
         return false;
       }
@@ -428,6 +430,20 @@
     }
   }
 
+  // Fine tuning for PostgreSQL
+  akDebug() << "Final tuning of new PartTable";
+  {
+    QSqlQuery query( DataStore::self()->database() );
+    if ( dbType == DbType::PostgreSQL ) {
+      query.exec( QLatin1String( "ALTER TABLE PartTable RENAME CONSTRAINT 
parttable_new_pkey TO parttable_pkey" ) );
+      query.exec( QLatin1String( "ALTER SEQUENCE parttable_new_id_seq RENAME 
TO parttable_id_seq" ) );
+      query.exec( QLatin1String( "SELECT setval('parttable_id_seq', MAX(id) + 
1) FROM PartTable") );
+    } else if ( dbType == DbType::MySQL ) {
+      // 0 will automatically reset AUTO_INCREMENT to SELECT MAX(id) + 1 FROM 
PartTable
+      query.exec( QLatin1String( "ALTER TABLE PartTable AUTO_INCREMENT = 0" ) 
);
+    }
+  }
+
   akDebug() << "Update done in" << ttotal.elapsed() << "ms";
 
   // Foreign keys and constraints will be reconstructed automatically once
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/akonadi-1.11.80/server/src/storage/notificationcollector.cpp 
new/akonadi-1.12.0/server/src/storage/notificationcollector.cpp
--- old/akonadi-1.11.80/server/src/storage/notificationcollector.cpp    
2014-02-28 22:38:09.000000000 +0100
+++ new/akonadi-1.12.0/server/src/storage/notificationcollector.cpp     
2014-03-25 14:32:48.000000000 +0100
@@ -23,6 +23,8 @@
 #include "handlerhelper.h"
 #include "cachecleaner.h"
 #include "intervalcheck.h"
+#include "search/searchmanager.h"
+#include <search.h>
 
 #include <QtCore/QDebug>
 
@@ -51,6 +53,7 @@
                                        const Collection &collection,
                                        const QByteArray &resource )
 {
+  SearchManager::instance()->scheduleSearchUpdate();
   itemNotification( NotificationMessageV2::Add, item, collection, 
Collection(), resource );
 }
 
@@ -59,6 +62,7 @@
                                          const Collection &collection,
                                          const QByteArray &resource )
 {
+  SearchManager::instance()->scheduleSearchUpdate();
   itemNotification( NotificationMessageV2::Modify, item, collection, 
Collection(), resource, changedParts );
 }
 
@@ -85,6 +89,7 @@
                                         const Collection &collectionDest,
                                         const QByteArray &sourceResource )
 {
+  SearchManager::instance()->scheduleSearchUpdate();
   itemNotification( NotificationMessageV2::Move, items, collectionSrc, 
collectionDest, sourceResource );
 }
 

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to