File 0f511184-kderuntime-nepomuk-47branch-memleak.diff of Package kdebase4-runtime
commit 0f511184ae25364618ba244f6afda5570b02c388
Author: Sebastian Trueg <trueg@kde.org>
Date: Mon Oct 24 17:47:25 2011 +0200
Run the MetaDataMover with an event loop.
It is using the exact same approach as the file indexer does: a new
thread is created and started and the MetaDataMover is then
QObject::moveToThread'ed to it.
This fixes mem leaks caused by DBus events that are not cleaned up.
BUG: 226676
diff --git a/nepomuk/services/filewatch/metadatamover.cpp b/nepomuk/services/filewatch/metadatamover.cpp
index 36ff533..f247fa5 100644
--- a/nepomuk/services/filewatch/metadatamover.cpp
+++ b/nepomuk/services/filewatch/metadatamover.cpp
@@ -1,5 +1,5 @@
/* This file is part of the KDE Project
- Copyright (c) 2009-2010 Sebastian Trueg <trueg@kde.org>
+ Copyright (c) 2009-2011 Sebastian Trueg <trueg@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -34,42 +34,44 @@
Nepomuk::MetadataMover::MetadataMover( Soprano::Model* model, QObject* parent )
- : QThread( parent ),
- m_stopped(false),
+ : QObject( parent ),
+ m_queueMutex(QMutex::Recursive),
m_model( model )
{
- QTimer* timer = new QTimer( this );
- connect( timer, SIGNAL( timeout() ), this, SLOT( slotClearRecentlyFinishedRequests() ) );
- timer->setInterval( 30000 );
- timer->start();
-}
-
+ // setup the main update queue timer
+ m_queueTimer = new QTimer(this);
+ connect(m_queueTimer, SIGNAL(timeout()),
+ this, SLOT(slotWorkUpdateQueue()),
+ Qt::DirectConnection);
-Nepomuk::MetadataMover::~MetadataMover()
-{
+ // setup the cleanup timer which removes requests that are done
+ m_recentlyFinishedRequestsTimer = new QTimer(this);
+ connect( m_recentlyFinishedRequestsTimer, SIGNAL( timeout() ),
+ this, SLOT( slotClearRecentlyFinishedRequests() ),
+ Qt::DirectConnection );
+ m_recentlyFinishedRequestsTimer->setInterval( 30000 );
}
-void Nepomuk::MetadataMover::stop()
+Nepomuk::MetadataMover::~MetadataMover()
{
- QMutexLocker lock( &m_queueMutex );
- m_stopped = true;
- m_queueWaiter.wakeAll();
}
void Nepomuk::MetadataMover::moveFileMetadata( const KUrl& from, const KUrl& to )
{
- kDebug() << from << to;
+// kDebug() << from << to;
Q_ASSERT( !from.path().isEmpty() && from.path() != "/" );
Q_ASSERT( !to.path().isEmpty() && to.path() != "/" );
- m_queueMutex.lock();
+
+ QMutexLocker lock(&m_queueMutex);
+
UpdateRequest req( from, to );
if ( !m_updateQueue.contains( req ) &&
!m_recentlyFinishedRequests.contains( req ) )
m_updateQueue.enqueue( req );
- m_queueMutex.unlock();
- m_queueWaiter.wakeAll();
+
+ QTimer::singleShot(0, this, SLOT(slotStartUpdateTimer()));
}
@@ -83,79 +85,68 @@ void Nepomuk::MetadataMover::removeFileMetadata( const KUrl& file )
void Nepomuk::MetadataMover::removeFileMetadata( const KUrl::List& files )
{
kDebug() << files;
- m_queueMutex.lock();
+ QMutexLocker lock(&m_queueMutex);
+
foreach( const KUrl& file, files ) {
UpdateRequest req( file );
if ( !m_updateQueue.contains( req ) &&
!m_recentlyFinishedRequests.contains( req ) )
m_updateQueue.enqueue( req );
}
- m_queueMutex.unlock();
- m_queueWaiter.wakeAll();
+
+ QTimer::singleShot(0, this, SLOT(slotStartUpdateTimer()));
}
-// FIXME: somehow detect when the nepomuk storage service is down and wait for it to come up again (how about having methods for that in Nepomuk::Service?)
-void Nepomuk::MetadataMover::run()
+void Nepomuk::MetadataMover::slotWorkUpdateQueue()
{
- m_stopped = false;
- while( !m_stopped ) {
-
- // lock for initial iteration
- m_queueMutex.lock();
-
- // work the queue
- while( !m_updateQueue.isEmpty() ) {
- UpdateRequest updateRequest = m_updateQueue.dequeue();
- m_recentlyFinishedRequests.insert( updateRequest );
-
- // unlock after queue utilization
- m_queueMutex.unlock();
+ // lock for initial iteration
+ QMutexLocker lock(&m_queueMutex);
- kDebug() << "========================= handling" << updateRequest.source() << updateRequest.target();
+ // work the queue
+ if( !m_updateQueue.isEmpty() ) {
+ UpdateRequest updateRequest = m_updateQueue.dequeue();
+ m_recentlyFinishedRequests.insert( updateRequest );
- // an empty second url means deletion
- if( updateRequest.target().isEmpty() ) {
- KUrl url = updateRequest.source();
- removeMetadata( url );
- }
- else {
- KUrl from = updateRequest.source();
- KUrl to = updateRequest.target();
+ // unlock after queue utilization
+ lock.unlock();
- // We do NOT get deleted messages for overwritten files! Thus, we
- // have to remove all metadata for overwritten files first.
- removeMetadata( to );
+// kDebug() << "========================= handling" << updateRequest.source() << updateRequest.target();
- // and finally update the old statements
- updateMetadata( from, to );
- }
+ // an empty second url means deletion
+ if( updateRequest.target().isEmpty() ) {
+ removeMetadata( updateRequest.source() );
+ }
+ else {
+ const KUrl from = updateRequest.source();
+ const KUrl to = updateRequest.target();
- kDebug() << "========================= done with" << updateRequest.source() << updateRequest.target();
+ // We do NOT get deleted messages for overwritten files! Thus, we
+ // have to remove all metadata for overwritten files first.
+ removeMetadata( to );
- // lock for next iteration
- m_queueMutex.lock();
+ // and finally update the old statements
+ updateMetadata( from, to );
}
- // wait for more input
- kDebug() << "Waiting...";
- m_queueWaiter.wait( &m_queueMutex );
- m_queueMutex.unlock();
- kDebug() << "Woke up.";
+// kDebug() << "========================= done with" << updateRequest.source() << updateRequest.target();
+ }
+ else {
+ kDebug() << "All update requests handled. Stopping timer.";
+ m_queueTimer->stop();
}
}
void Nepomuk::MetadataMover::removeMetadata( const KUrl& url )
{
- kDebug() << url;
+// kDebug() << url;
if ( url.isEmpty() ) {
kDebug() << "empty path. Looks like a bug somewhere...";
}
else {
const bool isFolder = url.url().endsWith('/');
- kDebug() << "removing metadata for file" << url;
Nepomuk::removeResources(QList<QUrl>() << url);
if( isFolder ) {
@@ -173,7 +164,6 @@ void Nepomuk::MetadataMover::removeMetadata( const KUrl& url )
"}" )
.arg( Soprano::Node::resourceToN3( Nepomuk::Vocabulary::NIE::url() ),
url.url(KUrl::AddTrailingSlash) );
- kDebug() << query;
//
// We cannot use one big loop since our updateMetadata calls below can change the iterator
@@ -232,6 +222,23 @@ void Nepomuk::MetadataMover::slotClearRecentlyFinishedRequests()
++it;
}
}
+
+ if(m_recentlyFinishedRequests.isEmpty()) {
+ kDebug() << "No more old requests. Stopping timer.";
+ m_recentlyFinishedRequestsTimer->stop();
+ }
+}
+
+
+// start the timer in the update thread
+void Nepomuk::MetadataMover::slotStartUpdateTimer()
+{
+ if(!m_queueTimer->isActive()) {
+ m_queueTimer->start();
+ }
+ if(!m_recentlyFinishedRequestsTimer->isActive()) {
+ m_recentlyFinishedRequestsTimer->start();
+ }
}
#include "metadatamover.moc"
diff --git a/nepomuk/services/filewatch/metadatamover.h b/nepomuk/services/filewatch/metadatamover.h
index 9697abe..1e96dac 100644
--- a/nepomuk/services/filewatch/metadatamover.h
+++ b/nepomuk/services/filewatch/metadatamover.h
@@ -1,5 +1,5 @@
/* This file is part of the KDE Project
- Copyright (c) 2009 Sebastian Trueg <trueg@kde.org>
+ Copyright (c) 2009-2011 Sebastian Trueg <trueg@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -19,9 +19,7 @@
#ifndef _NEPOMUK_METADATA_MOVER_H_
#define _NEPOMUK_METADATA_MOVER_H_
-#include <QtCore/QThread>
#include <QtCore/QMutex>
-#include <QtCore/QWaitCondition>
#include <QtCore/QQueue>
#include <QtCore/QSet>
#include <QtCore/QDateTime>
@@ -30,12 +28,14 @@
#include "updaterequest.h"
+class QTimer;
+
namespace Soprano {
class Model;
}
namespace Nepomuk {
- class MetadataMover : public QThread
+ class MetadataMover : public QObject
{
Q_OBJECT
@@ -48,8 +48,6 @@ namespace Nepomuk {
void removeFileMetadata( const KUrl& file );
void removeFileMetadata( const KUrl::List& files );
- void stop();
-
Q_SIGNALS:
/**
* Emitted for files (and folders) that have been moved but
@@ -62,10 +60,14 @@ namespace Nepomuk {
private Q_SLOTS:
void slotClearRecentlyFinishedRequests();
+ void slotWorkUpdateQueue();
- private:
- void run();
+ /**
+ * Start the update queue from the main thread.
+ */
+ void slotStartUpdateTimer();
+ private:
/**
* Remove the metadata for file \p url
*/
@@ -89,8 +91,9 @@ namespace Nepomuk {
QSet<UpdateRequest> m_recentlyFinishedRequests;
QMutex m_queueMutex;
- QWaitCondition m_queueWaiter;
- bool m_stopped;
+
+ QTimer* m_queueTimer;
+ QTimer* m_recentlyFinishedRequestsTimer;
Soprano::Model* m_model;
};
diff --git a/nepomuk/services/filewatch/nepomukfilewatch.cpp b/nepomuk/services/filewatch/nepomukfilewatch.cpp
index 3f038db..6d4e56e 100644
--- a/nepomuk/services/filewatch/nepomukfilewatch.cpp
+++ b/nepomuk/services/filewatch/nepomukfilewatch.cpp
@@ -1,5 +1,5 @@
/* This file is part of the KDE Project
- Copyright (c) 2007-2010 Sebastian Trueg <trueg@kde.org>
+ Copyright (c) 2007-2011 Sebastian Trueg <trueg@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -130,11 +130,13 @@ Nepomuk::FileWatch::FileWatch( QObject* parent, const QList<QVariant>& )
m_pathExcludeRegExpCache->rebuildCacheFromFilterList( defaultExcludeFilterList() );
// start the mover thread
- m_metadataMover = new MetadataMover( mainModel(), this );
+ m_metadataMoverThread = new QThread(this);
+ m_metadataMoverThread->start();
+ m_metadataMover = new MetadataMover( mainModel() );
connect( m_metadataMover, SIGNAL(movedWithoutData(QString)),
this, SLOT(slotMovedWithoutData(QString)),
Qt::QueuedConnection );
- m_metadataMover->start();
+ m_metadataMover->moveToThread(m_metadataMoverThread);
m_fileModificationQueue = new ActiveFileQueue(this);
connect(m_fileModificationQueue, SIGNAL(urlTimeout(KUrl)),
@@ -187,8 +189,8 @@ Nepomuk::FileWatch::FileWatch( QObject* parent, const QList<QVariant>& )
Nepomuk::FileWatch::~FileWatch()
{
kDebug();
- m_metadataMover->stop();
- m_metadataMover->wait();
+ m_metadataMoverThread->quit();
+ m_metadataMoverThread->wait();
}
@@ -207,11 +209,8 @@ void Nepomuk::FileWatch::watchFolder( const QString& path )
void Nepomuk::FileWatch::slotFileMoved( const QString& urlFrom, const QString& urlTo )
{
if( !ignorePath( urlFrom ) || !ignorePath( urlTo ) ) {
- KUrl from( urlFrom );
- KUrl to( urlTo );
-
- kDebug() << from << to;
-
+ const KUrl from( urlFrom );
+ const KUrl to( urlTo );
m_metadataMover->moveFileMetadata( from, to );
}
}
diff --git a/nepomuk/services/filewatch/nepomukfilewatch.h b/nepomuk/services/filewatch/nepomukfilewatch.h
index a6f4e2c..fbebfb8 100644
--- a/nepomuk/services/filewatch/nepomukfilewatch.h
+++ b/nepomuk/services/filewatch/nepomukfilewatch.h
@@ -1,5 +1,5 @@
/* This file is part of the KDE Project
- Copyright (c) 2007-2010 Sebastian Trueg <trueg@kde.org>
+ Copyright (c) 2007-2011 Sebastian Trueg <trueg@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -38,6 +38,7 @@ class KInotify;
class KUrl;
class RegExpCache;
class ActiveFileQueue;
+class QThread;
namespace Nepomuk {
@@ -108,6 +109,7 @@ namespace Nepomuk {
*/
bool ignorePath( const QString& path );
+ QThread* m_metadataMoverThread;
MetadataMover* m_metadataMover;
#ifdef BUILD_KINOTIFY