1 commit 992096665110674e8e9bc5be6e91c5b78249266e
2 Author: David Faure <faure@kde.org>
3 Date: Fri Jan 20 00:23:55 2012 +0100
5 New cleanup in "akonadictl fsck": clean up orphan resources from the DB
7 The only way this can ever happen is when hacking agentsrc and removing
8 resources from it (or removing the whole ~/.config). But then you get
9 dead collection trees in kmail, always red, always unusable, and this is
10 the only way to clean this up.
12 diff --git a/server/src/storagejanitor.cpp b/server/src/storagejanitor.cpp
13 index ea520a8..0e26596 100644
14 --- a/server/src/storagejanitor.cpp
15 +++ b/server/src/storagejanitor.cpp
18 #include "storage/datastore.h"
19 #include "storage/selectquerybuilder.h"
20 +#include "resourcemanager.h"
25 #include <libs/protocol_p.h>
26 #include <libs/xdgbasedirs_p.h>
28 +#include <agentmanagerinterface.h>
30 #include <QStringBuilder>
31 #include <QtDBus/QDBusConnection>
32 #include <QtSql/QSqlQuery>
33 @@ -70,8 +73,11 @@ StorageJanitor::~StorageJanitor()
34 DataStore::self()->close();
37 -void StorageJanitor::check()
38 +void StorageJanitor::check() // implementation of `akonadictl fsck`
40 + inform( "Looking for resources in the DB not matching a configured resource..." );
41 + findOrphanedResources();
43 inform( "Looking for collections not belonging to a valid resource..." );
44 findOrphanedCollections();
46 @@ -106,6 +112,43 @@ void StorageJanitor::check()
47 inform( "Consistency check done." );
50 +void StorageJanitor::findOrphanedResources()
52 + SelectQueryBuilder<Resource> qbres;
53 + OrgFreedesktopAkonadiAgentManagerInterface iface(
54 + AkDBus::serviceName(AkDBus::Control),
55 + QLatin1String( "/AgentManager" ),
56 + QDBusConnection::sessionBus(),
59 + if (!iface.isValid()) {
60 + inform( QString::fromLatin1("ERROR: Couldn't talk to %1").arg(AkDBus::Control) );
63 + const QStringList knownResources = iface.agentInstances();
64 + if (knownResources.isEmpty()) {
65 + inform( QString::fromLatin1("ERROR: no known resources. This must be a mistake?") );
68 + akDebug() << "Known resources:" << knownResources;
69 + qbres.addValueCondition( Resource::nameFullColumnName(), Query::NotIn, QVariant(knownResources) );
70 + qbres.addValueCondition( Resource::idFullColumnName(), Query::NotEquals, 1 ); // skip akonadi_search_resource
72 + //akDebug() << "SQL:" << qbres.query().lastQuery();
73 + const Resource::List orphanResources = qbres.result();
74 + if ( orphanResources.size() > 0 ) {
75 + QStringList resourceNames;
76 + foreach ( const Resource& resource, orphanResources ) {
77 + resourceNames.append(resource.name());
79 + inform( QString::fromLatin1( "Found %1 orphan resources: %2" ).arg( orphanResources.size() ). arg( resourceNames.join(QLatin1String(",")) ) );
80 + foreach ( const QString& resourceName, resourceNames ) {
81 + inform( QString::fromLatin1( "Removing resource %1" ).arg( resourceName ) );
82 + ResourceManager::self()->removeResourceInstance( resourceName );
87 void StorageJanitor::findOrphanedCollections()
89 SelectQueryBuilder<Collection> qb;
90 @@ -137,7 +180,7 @@ void StorageJanitor::checkPathToRoot(const Akonadi::Collection& col)
91 + QLatin1Literal( ") belongs to a different resource than its parent." ) );
92 // can/should we actually fix that?
96 checkPathToRoot( parent );
99 diff --git a/server/src/storagejanitor.h b/server/src/storagejanitor.h
100 index afc79c6..be3442e 100644
101 --- a/server/src/storagejanitor.h
102 +++ b/server/src/storagejanitor.h
103 @@ -63,6 +63,11 @@ class StorageJanitor : public QObject
104 void inform( const QString &msg );
107 + * Look for resources in the DB not existing in reality.
109 + void findOrphanedResources();
112 * Look for collections belonging to non-existent resources.
114 void findOrphanedCollections();