[arch-commits] Commit in kdelibs/kde-unstable (PKGBUILD udisks2-fixes.patch)

Andrea Scarpino andrea at archlinux.org
Wed Dec 5 11:44:32 UTC 2012


    Date: Wednesday, December 5, 2012 @ 06:44:31
  Author: andrea
Revision: 172767

Add git patches that improve udisks2 performances

Added:
  kdelibs/kde-unstable/udisks2-fixes.patch
Modified:
  kdelibs/kde-unstable/PKGBUILD

---------------------+
 PKGBUILD            |   11 
 udisks2-fixes.patch |  812 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 820 insertions(+), 3 deletions(-)

Modified: PKGBUILD
===================================================================
--- PKGBUILD	2012-12-05 11:05:17 UTC (rev 172766)
+++ PKGBUILD	2012-12-05 11:44:31 UTC (rev 172767)
@@ -4,7 +4,7 @@
 
 pkgname=kdelibs
 pkgver=4.9.90
-pkgrel=1
+pkgrel=2
 pkgdesc="KDE Core Libraries"
 arch=('i686' 'x86_64')
 url='https://projects.kde.org/projects/kde/kdelibs'
@@ -17,10 +17,12 @@
 makedepends=('cmake' 'automoc4' 'avahi' 'libgl' 'hspell' 'mesa')
 install=${pkgname}.install
 source=("http://download.kde.org/unstable/${pkgver}/src/${pkgname}-${pkgver}.tar.xz"
-        'kde-applications-menu.patch' 'archlinux-menu.patch')
+        'kde-applications-menu.patch' 'archlinux-menu.patch'
+        'udisks2-fixes.patch')
 sha1sums=('57a75fe32a76dc36877283d90fbb35529e54a69c'
           '86ee8c8660f19de8141ac99cd6943964d97a1ed7'
-          '63a850ab4196b9d06934f2b4a13acd9f7739bc67')
+          '63a850ab4196b9d06934f2b4a13acd9f7739bc67'
+          'c270bc3c9248fc5921cbc9e38dbfb141b49c8a4c')
 
 build() {
        cd "${srcdir}"/${pkgname}-${pkgver}
@@ -30,6 +32,9 @@
        # add Archlinux menu entry
        patch -p1 -i "${srcdir}"/archlinux-menu.patch
 
+       # Already fixed upstream, improve udisks2 performances
+       patch -p1 -i "${srcdir}"/udisks2-fixes.patch
+
        cd "${srcdir}"
        mkdir build
        cd build

Added: udisks2-fixes.patch
===================================================================
--- udisks2-fixes.patch	                        (rev 0)
+++ udisks2-fixes.patch	2012-12-05 11:44:31 UTC (rev 172767)
@@ -0,0 +1,812 @@
+diff --git a/solid/solid/backends/udisks2/udisksblock.cpp b/solid/solid/backends/udisks2/udisksblock.cpp
+index 027ea03..f3cd1e8 100644
+--- a/solid/solid/backends/udisks2/udisksblock.cpp
++++ b/solid/solid/backends/udisks2/udisksblock.cpp
+@@ -30,8 +30,7 @@
+ using namespace Solid::Backends::UDisks2;
+ 
+ Block::Block(Device *dev)
+-    : DeviceInterface(dev),
+-    m_connection(QDBusConnection::connectToBus(QDBusConnection::SystemBus, "Solid::Udisks2::Block::" + dev->udi()))
++    : DeviceInterface(dev)
+ {
+     m_devNum = m_device->prop("DeviceNumber").toULongLong();
+     m_devFile = QFile::decodeName(m_device->prop("Device").toByteArray());
+@@ -41,7 +40,7 @@ Block::Block(Device *dev)
+         const QString path = "/org/freedesktop/UDisks2/block_devices";
+         QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path,
+                                                            DBUS_INTERFACE_INTROSPECT, "Introspect");
+-        QDBusPendingReply<QString> reply = m_connection.asyncCall(call);
++        QDBusPendingReply<QString> reply = QDBusConnection::systemBus().asyncCall(call);
+         reply.waitForFinished();
+ 
+         if (reply.isValid()) {
+diff --git a/solid/solid/backends/udisks2/udisksblock.h b/solid/solid/backends/udisks2/udisksblock.h
+index 65ef2b8..19cb70a 100644
+--- a/solid/solid/backends/udisks2/udisksblock.h
++++ b/solid/solid/backends/udisks2/udisksblock.h
+@@ -45,7 +45,6 @@ public:
+     virtual int deviceMinor() const;
+     virtual int deviceMajor() const;
+ private:
+-    QDBusConnection m_connection;
+     dev_t m_devNum;
+     QString m_devFile;
+ };
+diff --git a/solid/solid/backends/udisks2/udisksdevice.cpp b/solid/solid/backends/udisks2/udisksdevice.cpp
+index 3508d57..2a4313a 100644
+--- a/solid/solid/backends/udisks2/udisksdevice.cpp
++++ b/solid/solid/backends/udisks2/udisksdevice.cpp
+@@ -20,6 +20,7 @@
+ */
+ 
+ #include "udisksdevice.h"
++#include "udisksdevicebackend.h"
+ #include "udisksblock.h"
+ #include "udisksdeviceinterface.h"
+ #include "udisksstoragevolume.h"
+@@ -91,29 +92,72 @@ static QString formatByteSize(double size)
+ 
+ Device::Device(const QString &udi)
+     : Solid::Ifaces::Device()
+-    , m_udi(udi)
+-    , m_connection(QDBusConnection::connectToBus(QDBusConnection::SystemBus, "Solid::Udisks2::Device::" + udi))
++    , m_backend(DeviceBackend::backendForUDI(udi))
+ {
+-    m_device = new QDBusInterface(UD2_DBUS_SERVICE, m_udi,
+-                                  QString(), // no interface, we aggregate them
+-                                  m_connection);
++    if (m_backend) {
++        connect(m_backend, SIGNAL(changed()), this, SIGNAL(changed()));
++        connect(m_backend, SIGNAL(propertyChanged(QMap<QString,int>)), this, SIGNAL(propertyChanged(QMap<QString,int>)));
++    } else {
++        qDebug() << "Created invalid Device for udi" << udi;
++    }
++}
++
++Device::~Device()
++{
++}
++
++QString Device::udi() const
++{
++    if (m_backend) {
++        return m_backend->udi();
++    }
++
++    return QString();
++}
+ 
+-    if (m_device->isValid()) {
+-        m_connection.connect(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
+-                                             SLOT(slotPropertiesChanged(QString,QVariantMap,QStringList)));
++QVariant Device::prop(const QString &key) const
++{
++    if (m_backend) {
++        return m_backend->prop(key);
++    }
+ 
+-        m_connection.connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesAdded",
+-                                             this, SLOT(slotInterfacesAdded(QDBusObjectPath,QVariantMapMap)));
+-        m_connection.connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesRemoved",
+-                                             this, SLOT(slotInterfacesRemoved(QDBusObjectPath,QStringList)));
++    return QVariant();
++}
+ 
+-        initInterfaces();
++bool Device::propertyExists(const QString &key) const
++{
++    if (m_backend) {
++        return m_backend->propertyExists(key);
+     }
++
++    return false;
+ }
+ 
+-Device::~Device()
++QVariantMap Device::allProperties() const
+ {
+-    delete m_device;
++    if (m_backend) {
++        return m_backend->allProperties();
++    }
++
++    return QVariantMap();
++}
++
++bool Device::hasInterface(const QString &name) const
++{
++    if (m_backend) {
++        return m_backend->interfaces().contains(name);
++    }
++
++    return false;
++}
++
++QStringList Device::interfaces() const
++{
++    if (m_backend) {
++        return m_backend->interfaces();
++    }
++
++    return QStringList();
+ }
+ 
+ QObject* Device::createDeviceInterface(const Solid::DeviceInterface::Type& type)
+@@ -637,11 +681,6 @@ QString Device::vendor() const
+     return prop("Vendor").toString();
+ }
+ 
+-QString Device::udi() const
+-{
+-    return m_udi;
+-}
+-
+ QString Device::parentUdi() const
+ {
+     QString parent;
+@@ -656,139 +695,6 @@ QString Device::parentUdi() const
+     return parent;
+ }
+ 
+-void Device::checkCache(const QString &key) const
+-{
+-    if (m_cache.isEmpty()) // recreate the cache
+-        allProperties();
+-
+-    if (m_cache.contains(key))
+-        return;
+-
+-    QVariant reply = m_device->property(key.toUtf8());
+-
+-    if (reply.isValid()) {
+-        m_cache.insert(key, reply);
+-    } else {
+-        //qDebug() << "got invalid reply for cache:" << key;
+-    }
+-}
+-
+-QString Device::introspect() const
+-{
+-    QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi,
+-                                                       DBUS_INTERFACE_INTROSPECT, "Introspect");
+-    QDBusPendingReply<QString> reply = m_connection.asyncCall(call);
+-    reply.waitForFinished();
+-
+-    if (reply.isValid())
+-        return reply.value();
+-    else {
+-        return QString();
+-    }
+-}
+-
+-QVariant Device::prop(const QString &key) const
+-{
+-    checkCache(key);
+-    return m_cache.value(key);
+-}
+-
+-bool Device::propertyExists(const QString &key) const
+-{
+-    checkCache(key);
+-    return m_cache.contains(key);
+-}
+-
+-QVariantMap Device::allProperties() const
+-{
+-    QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "GetAll");
+-
+-    Q_FOREACH (const QString & iface, m_interfaces) {
+-        if (iface.startsWith("org.freedesktop.DBus"))
+-            continue;
+-        call.setArguments(QVariantList() << iface);
+-        QDBusPendingReply<QVariantMap> reply = m_connection.asyncCall(call);
+-        reply.waitForFinished();
+-
+-        if (reply.isValid())
+-            m_cache.unite(reply.value());
+-        else
+-            qWarning() << "Error getting props:" << reply.error().name() << reply.error().message();
+-        //qDebug() << "After iface" << iface << ", cache now contains" << m_cache.size() << "items";
+-    }
+-
+-    return m_cache;
+-}
+-
+-bool Device::hasInterface(const QString &name) const
+-{
+-    return m_interfaces.contains(name);
+-}
+-
+-QStringList Device::interfaces() const
+-{
+-    return m_interfaces;
+-}
+-
+-void Device::initInterfaces()
+-{
+-    m_interfaces.clear();
+-    const QString xmlData = introspect();
+-    QDomDocument dom;
+-    dom.setContent(xmlData);
+-    QDomNodeList ifaceNodeList = dom.elementsByTagName("interface");
+-    for (int i = 0; i < ifaceNodeList.count(); i++) {
+-        QDomElement ifaceElem = ifaceNodeList.item(i).toElement();
+-        if (!ifaceElem.isNull())
+-            m_interfaces.append(ifaceElem.attribute("name"));
+-    }
+-    //qDebug() << "Device" << m_udi << "has interfaces:" << m_interfaces;
+-}
+-
+-void Device::slotPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps)
+-{
+-    //Q_UNUSED(ifaceName);
+-
+-    qDebug() << m_udi << "'s interface" << ifaceName << "changed props:";
+-
+-    QMap<QString, int> changeMap;
+-
+-    Q_FOREACH(const QString & key, invalidatedProps) {
+-        m_cache.remove(key);
+-        changeMap.insert(key, Solid::GenericInterface::PropertyRemoved);
+-        qDebug() << "\t invalidated:" << key;
+-    }
+-
+-    QMapIterator<QString, QVariant> i(changedProps);
+-    while (i.hasNext()) {
+-        i.next();
+-        const QString key = i.key();
+-        m_cache.insert(key, i.value());  // replace the value
+-        changeMap.insert(key, Solid::GenericInterface::PropertyModified);
+-        qDebug() << "\t modified:" << key << ":" << m_cache.value(key);
+-    }
+-
+-    Q_EMIT propertyChanged(changeMap);
+-    Q_EMIT changed();
+-}
+-
+-void Device::slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties)
+-{
+-    if (object_path.path() == m_udi) {
+-        m_interfaces.append(interfaces_and_properties.keys());
+-    }
+-}
+-
+-void Device::slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces)
+-{
+-    if (object_path.path() == m_udi) {
+-        Q_FOREACH(const QString & iface, interfaces) {
+-            m_interfaces.removeAll(iface);
+-        }
+-    }
+-}
+-
+-
+ QString Device::errorToString(const QString & error) const
+ {
+     if (error == UD2_ERROR_UNAUTHORIZED || error == UD2_ERROR_NOT_AUTHORIZED)
+diff --git a/solid/solid/backends/udisks2/udisksdevice.h b/solid/solid/backends/udisks2/udisksdevice.h
+index ee6bc1b..6038178 100644
+--- a/solid/solid/backends/udisks2/udisksdevice.h
++++ b/solid/solid/backends/udisks2/udisksdevice.h
+@@ -39,6 +39,8 @@ namespace Backends
+ namespace UDisks2
+ {
+ 
++class DeviceBackend;
++
+ class Device: public Solid::Ifaces::Device
+ {
+     Q_OBJECT
+@@ -87,25 +89,12 @@ Q_SIGNALS:
+     void changed();
+     void propertyChanged(const QMap<QString,int> &changes);
+ 
+-private Q_SLOTS:
+-    void slotPropertiesChanged(const QString & ifaceName, const QVariantMap & changedProps, const QStringList & invalidatedProps);
+-    void slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties);
+-    void slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
++protected:
++    QPointer<DeviceBackend> m_backend;
+ 
+ private:
+     QString storageDescription() const;
+     QString volumeDescription() const;
+-    mutable QDBusInterface *m_device;
+-    QString m_udi;
+-    mutable QVariantMap m_cache;
+-
+-    void initInterfaces();
+-    QStringList m_interfaces;
+-
+-    void checkCache(const QString &key) const;
+-    QString introspect() const;
+-
+-    QDBusConnection m_connection;
+ };
+ 
+ }
+diff --git a/solid/solid/backends/udisks2/udisksdevicebackend.cpp b/solid/solid/backends/udisks2/udisksdevicebackend.cpp
+new file mode 100644
+index 0000000..8131cb5
+--- /dev/null
++++ b/solid/solid/backends/udisks2/udisksdevicebackend.cpp
+@@ -0,0 +1,239 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++    Copyright 2012 Dan Vrátil <dvratil at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 of the License, or (at your option) version 3, or any
++    later version accepted by the membership of KDE e.V. (or its
++    successor approved by the membership of KDE e.V.), which shall
++    act as a proxy defined in Section 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "udisksdevicebackend.h"
++
++#include <QtDBus/QDBusConnection>
++#include <QtDBus/QDBusInterface>
++#include <QtXml/QDomDocument>
++
++#include "solid/deviceinterface.h"
++#include "solid/genericinterface.h"
++
++using namespace Solid::Backends::UDisks2;
++
++/* Static cache for DeviceBackends for all UDIs */
++QMap<QString /* UDI */, DeviceBackend*> DeviceBackend::s_backends;
++
++DeviceBackend* DeviceBackend::backendForUDI(const QString& udi)
++{
++    DeviceBackend *backend = 0;
++    if (udi.isEmpty()) {
++        return backend;
++    }
++
++    if (s_backends.contains(udi)) {
++        backend = s_backends.value(udi);
++    } else {
++        backend = new DeviceBackend(udi);
++        s_backends.insert(udi, backend);
++    }
++
++    return backend;
++}
++
++void DeviceBackend::destroyBackend(const QString& udi)
++{
++    if (s_backends.contains(udi)) {
++        DeviceBackend *backend = s_backends.value(udi);
++        s_backends.remove(udi);
++        delete backend;
++    }
++}
++
++DeviceBackend::DeviceBackend(const QString& udi)
++    : m_udi(udi)
++{
++    qDebug() << "Creating backend for device" << m_udi;
++    m_device = new QDBusInterface(UD2_DBUS_SERVICE, m_udi,
++                                  QString(), // no interface, we aggregate them
++                                  QDBusConnection::systemBus(), this);
++
++    if (m_device->isValid()) {
++        QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
++                                            SLOT(slotPropertiesChanged(QString,QVariantMap,QStringList)));
++        QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesAdded",
++                                            this, SLOT(slotInterfacesAdded(QDBusObjectPath,QVariantMapMap)));
++        QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, UD2_DBUS_PATH, DBUS_INTERFACE_MANAGER, "InterfacesRemoved",
++                                            this, SLOT(slotInterfacesRemoved(QDBusObjectPath,QStringList)));
++
++        initInterfaces();
++    }
++}
++
++DeviceBackend::~DeviceBackend()
++{
++    qDebug() << "Destroying backend for device" << m_udi;
++}
++
++void DeviceBackend::initInterfaces()
++{
++    m_interfaces.clear();
++
++    const QString xmlData = introspect();
++    if (xmlData.isEmpty()) {
++        qDebug() << m_udi << "has no interfaces!";
++        return;
++    }
++
++    QDomDocument dom;
++    dom.setContent(xmlData);
++
++    QDomNodeList ifaceNodeList = dom.elementsByTagName("interface");
++    for (int i = 0; i < ifaceNodeList.count(); i++) {
++        QDomElement ifaceElem = ifaceNodeList.item(i).toElement();
++        /* Accept only org.freedesktop.UDisks2.* interfaces so that when the device is unplugged,
++         * m_interfaces goes empty and we can easily verify that the device is gone. */
++        if (!ifaceElem.isNull() && ifaceElem.attribute("name").startsWith(UD2_DBUS_SERVICE)) {
++            m_interfaces.append(ifaceElem.attribute("name"));
++        }
++    }
++
++    qDebug() << m_udi << "has interfaces:" << m_interfaces;
++}
++
++QStringList DeviceBackend::interfaces() const
++{
++    return m_interfaces;
++}
++
++const QString& DeviceBackend::udi() const
++{
++    return m_udi;
++}
++
++QVariant DeviceBackend::prop(const QString& key) const
++{
++    checkCache(key);
++    return m_propertyCache.value(key);
++}
++
++bool DeviceBackend::propertyExists(const QString& key) const
++{
++    checkCache(key);
++    /* checkCache() will put an invalid QVariant in cache when the property
++     * does not exist, so check for validity, not for an actual presence. */
++    return m_propertyCache.value(key).isValid();
++}
++
++QVariantMap DeviceBackend::allProperties() const
++{
++    QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi, DBUS_INTERFACE_PROPS, "GetAll");
++
++    Q_FOREACH (const QString & iface, m_interfaces) {
++        call.setArguments(QVariantList() << iface);
++        QDBusPendingReply<QVariantMap> reply = QDBusConnection::systemBus().call(call);
++
++        if (reply.isValid()) {
++            m_propertyCache.unite(reply.value());
++        } else {
++            qWarning() << "Error getting props:" << reply.error().name() << reply.error().message();
++        }
++        //qDebug() << "After iface" << iface << ", cache now contains" << m_cache.size() << "items";
++    }
++
++    return m_propertyCache;
++}
++
++QString DeviceBackend::introspect() const
++{
++    QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, m_udi,
++                                                    DBUS_INTERFACE_INTROSPECT, "Introspect");
++    QDBusPendingReply<QString> reply = QDBusConnection::systemBus().call(call);
++
++    if (reply.isValid())
++        return reply.value();
++    else {
++        return QString();
++    }
++}
++
++void DeviceBackend::checkCache(const QString& key) const
++{
++    if (m_propertyCache.isEmpty()) { // recreate the cache
++        allProperties();
++    }
++
++    if (m_propertyCache.contains(key)) {
++        return;
++    }
++
++    QVariant reply = m_device->property(key.toUtf8());
++    m_propertyCache.insert(key, reply);
++
++    if (!reply.isValid()) {
++        /* Store the item in the cache anyway so next time we don't have to
++         * do the DBus call to find out it does not exist but just check whether
++         * prop(key).isValid() */
++        qDebug() << m_udi << ": property" << key << "does not exist";
++    }
++}
++
++void DeviceBackend::slotPropertiesChanged(const QString& ifaceName, const QVariantMap& changedProps, const QStringList& invalidatedProps)
++{
++    qDebug() << m_udi << "'s interface" << ifaceName << "changed props:";
++
++    QMap<QString, int> changeMap;
++
++    Q_FOREACH(const QString & key, invalidatedProps) {
++        m_propertyCache.remove(key);
++        changeMap.insert(key, Solid::GenericInterface::PropertyRemoved);
++        qDebug() << "\t invalidated:" << key;
++    }
++
++    QMapIterator<QString, QVariant> i(changedProps);
++    while (i.hasNext()) {
++        i.next();
++        const QString key = i.key();
++        m_propertyCache.insert(key, i.value());  // replace the value
++        changeMap.insert(key, Solid::GenericInterface::PropertyModified);
++        qDebug() << "\t modified:" << key << ":" << m_propertyCache.value(key);
++    }
++
++    Q_EMIT propertyChanged(changeMap);
++    Q_EMIT changed();
++}
++
++void DeviceBackend::slotInterfacesAdded(const QDBusObjectPath& object_path, const QVariantMapMap& interfaces_and_properties)
++{
++    if (object_path.path() != m_udi) {
++        return;
++    }
++
++    Q_FOREACH(const QString & iface, interfaces_and_properties.keys()) {
++        /* Don't store generic DBus interfaces */
++        if (iface.startsWith(UD2_DBUS_SERVICE)) {
++            m_interfaces.append(interfaces_and_properties.keys());
++        }
++    }
++}
++
++void DeviceBackend::slotInterfacesRemoved(const QDBusObjectPath& object_path, const QStringList& interfaces)
++{
++    if (object_path.path() != m_udi) {
++        return;
++    }
++
++    Q_FOREACH(const QString & iface, interfaces) {
++        m_interfaces.removeAll(iface);
++    }
++}
+diff --git a/solid/solid/backends/udisks2/udisksdevicebackend.h b/solid/solid/backends/udisks2/udisksdevicebackend.h
+new file mode 100644
+index 0000000..829fa41
+--- /dev/null
++++ b/solid/solid/backends/udisks2/udisksdevicebackend.h
+@@ -0,0 +1,84 @@
++/*
++    Copyright 2010 Michael Zanetti <mzanetti at kde.org>
++    Copyright 2010-2012 Lukáš Tinkl <ltinkl at redhat.com>
++    Copyright 2012 Dan Vrátil <dvratil at redhat.com>
++
++    This library is free software; you can redistribute it and/or
++    modify it under the terms of the GNU Lesser General Public
++    License as published by the Free Software Foundation; either
++    version 2.1 of the License, or (at your option) version 3, or any
++    later version accepted by the membership of KDE e.V. (or its
++    successor approved by the membership of KDE e.V.), which shall
++    act as a proxy defined in Section 6 of version 3 of the license.
++
++    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
++    Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public
++    License along with this library. If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef UDISKSDEVICEBACKEND_H
++#define UDISKSDEVICEBACKEND_H
++
++#include <QObject>
++#include <QtDBus/QDBusConnection>
++#include <QtDBus/QDBusObjectPath>
++#include <QtDBus/QDBusInterface>
++#include <QStringList>
++
++#include "udisks2.h"
++
++namespace Solid {
++namespace Backends {
++namespace UDisks2 {
++
++class DeviceBackend: public QObject {
++
++    Q_OBJECT
++
++  public:
++    static DeviceBackend* backendForUDI(const QString &udi);
++    static void destroyBackend(const QString &udi);
++
++    DeviceBackend(const QString &udi);
++    ~DeviceBackend();
++
++    QVariant prop(const QString &key) const;
++    bool propertyExists(const QString &key) const;
++    QVariantMap allProperties() const;
++
++    QStringList interfaces() const;
++    const QString & udi() const;
++
++  Q_SIGNALS:
++    void propertyChanged(const QMap<QString, int> &changeMap);
++    void changed();
++
++  private Q_SLOTS:
++    void slotInterfacesAdded(const QDBusObjectPath &object_path, const QVariantMapMap &interfaces_and_properties);
++    void slotInterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
++    void slotPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps);
++
++  private:
++    void initInterfaces();
++    QString introspect() const;
++    void checkCache(const QString &key) const;
++
++    QDBusInterface *m_device;
++
++    mutable QVariantMap m_propertyCache;
++    QStringList m_interfaces;
++    QString m_udi;
++
++    static QMap<QString, DeviceBackend*> s_backends;
++
++};
++
++} /* namespace UDisks2 */
++} /* namespace Backends */
++} /* namespace Solid */
++
++#endif /* UDISKSDEVICEBACKEND_H */
+\ No newline at end of file
+diff --git a/solid/solid/backends/udisks2/udisksmanager.cpp b/solid/solid/backends/udisks2/udisksmanager.cpp
+index e781abb..ecb9add 100644
+--- a/solid/solid/backends/udisks2/udisksmanager.cpp
++++ b/solid/solid/backends/udisks2/udisksmanager.cpp
+@@ -19,6 +19,7 @@
+ */
+ 
+ #include "udisksmanager.h"
++#include "udisksdevicebackend.h"
+ 
+ #include <QtCore/QCoreApplication>
+ #include <QtCore/QDebug>
+@@ -32,10 +33,9 @@ using namespace Solid::Backends::Shared;
+ 
+ Manager::Manager(QObject *parent)
+     : Solid::Ifaces::DeviceManager(parent),
+-      m_connection(QDBusConnection::connectToBus(QDBusConnection::SystemBus, "Solid::Udisks2")),
+       m_manager(UD2_DBUS_SERVICE,
+                 UD2_DBUS_PATH,
+-                m_connection)
++                QDBusConnection::systemBus())
+ {
+     m_supportedInterfaces
+             << Solid::DeviceInterface::GenericInterface
+@@ -60,9 +60,9 @@ Manager::Manager(QObject *parent)
+                                                               "org.freedesktop.DBus",
+                                                               "ListActivatableNames");
+ 
+-        QDBusReply<QStringList> reply = m_connection.call(message);
++        QDBusReply<QStringList> reply = QDBusConnection::systemBus().call(message);
+         if (reply.isValid() && reply.value().contains(UD2_DBUS_SERVICE)) {
+-            m_connection.interface()->startService(UD2_DBUS_SERVICE);
++            QDBusConnection::systemBus().interface()->startService(UD2_DBUS_SERVICE);
+             serviceFound = true;
+         }
+     }
+@@ -77,6 +77,10 @@ Manager::Manager(QObject *parent)
+ 
+ Manager::~Manager()
+ {
++    while (!m_deviceCache.isEmpty()) {
++        QString udi = m_deviceCache.takeFirst();
++        DeviceBackend::destroyBackend(udi);
++    }
+ }
+ 
+ QObject* Manager::createDevice(const QString& udi)
+@@ -128,7 +132,11 @@ QStringList Manager::devicesFromQuery(const QString& parentUdi, Solid::DeviceInt
+ 
+ QStringList Manager::allDevices()
+ {
+-    m_deviceCache.clear();
++    /* Clear the cache, destroy all backends */
++    while (!m_deviceCache.isEmpty()) {
++        QString udi= m_deviceCache.takeFirst();
++        DeviceBackend::destroyBackend(udi);
++    }
+ 
+     introspect("/org/freedesktop/UDisks2/block_devices", true /*checkOptical*/);
+     introspect("/org/freedesktop/UDisks2/drives");
+@@ -140,8 +148,7 @@ void Manager::introspect(const QString & path, bool checkOptical)
+ {
+     QDBusMessage call = QDBusMessage::createMethodCall(UD2_DBUS_SERVICE, path,
+                                                        DBUS_INTERFACE_INTROSPECT, "Introspect");
+-    QDBusPendingReply<QString> reply = QDBusConnection::systemBus().asyncCall(call);
+-    reply.waitForFinished();
++    QDBusPendingReply<QString> reply = QDBusConnection::systemBus().call(call);
+ 
+     if (reply.isValid()) {
+         QDomDocument dom;
+@@ -155,7 +162,7 @@ void Manager::introspect(const QString & path, bool checkOptical)
+                 if (checkOptical) {
+                     Device device(udi);
+                     if (device.mightBeOpticalDisc()) {
+-                        m_connection.connect(UD2_DBUS_SERVICE, udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
++                        QDBusConnection::systemBus().connect(UD2_DBUS_SERVICE, udi, DBUS_INTERFACE_PROPS, "PropertiesChanged", this,
+                                                              SLOT(slotMediaChanged(QDBusMessage)));
+                         if (!device.isOpticalDisc())  // skip empty CD disc
+                             continue;
+@@ -184,6 +191,11 @@ void Manager::slotInterfacesAdded(const QDBusObjectPath &object_path, const QVar
+ {
+     const QString udi = object_path.path();
+ 
++    /* Ignore jobs */
++    if (udi.startsWith(UD2_DBUS_PATH_JOBS)) {
++        return;
++    }
++
+     qDebug() << udi << "has new interfaces:" << interfaces_and_properties.keys();
+ 
+     // new device, we don't know it yet
+@@ -197,6 +209,11 @@ void Manager::slotInterfacesRemoved(const QDBusObjectPath &object_path, const QS
+ {
+     const QString udi = object_path.path();
+ 
++    /* Ignore jobs */
++    if (udi.startsWith(UD2_DBUS_PATH_JOBS)) {
++        return;
++    }
++
+     qDebug() << udi << "lost interfaces:" << interfaces;
+ 
+     Device device(udi);
+@@ -204,6 +221,7 @@ void Manager::slotInterfacesRemoved(const QDBusObjectPath &object_path, const QS
+     if (!udi.isEmpty() && (interfaces.isEmpty() || device.interfaces().isEmpty() || device.interfaces().contains(UD2_DBUS_INTERFACE_FILESYSTEM))) {
+         Q_EMIT deviceRemoved(udi);
+         m_deviceCache.removeAll(udi);
++        DeviceBackend::destroyBackend(udi);
+     }
+ }
+ 
+@@ -226,6 +244,7 @@ void Manager::slotMediaChanged(const QDBusMessage & msg)
+     if (m_deviceCache.contains(udi) && size == 0) {  // we know the optdisc, got removed
+         Q_EMIT deviceRemoved(udi);
+         m_deviceCache.removeAll(udi);
++        DeviceBackend::destroyBackend(udi);
+     }
+ }
+ 
+diff --git a/solid/solid/backends/udisks2/udisksmanager.h b/solid/solid/backends/udisks2/udisksmanager.h
+index bf74703..fb929ce 100644
+--- a/solid/solid/backends/udisks2/udisksmanager.h
++++ b/solid/solid/backends/udisks2/udisksmanager.h
+@@ -60,7 +60,6 @@ private:
+     const QStringList &deviceCache();
+     void introspect(const QString & path, bool checkOptical = false);
+     QSet<Solid::DeviceInterface::Type> m_supportedInterfaces;
+-    QDBusConnection m_connection;
+     org::freedesktop::DBus::ObjectManager m_manager;
+     QStringList m_deviceCache;
+ };
+diff --git a/solid/solid/backends/udisks2/udisksopticaldrive.cpp b/solid/solid/backends/udisks2/udisksopticaldrive.cpp
+index 8ad3df0..4df18b1 100644
+--- a/solid/solid/backends/udisks2/udisksopticaldrive.cpp
++++ b/solid/solid/backends/udisks2/udisksopticaldrive.cpp
+@@ -38,7 +38,11 @@
+ using namespace Solid::Backends::UDisks2;
+ 
+ OpticalDrive::OpticalDrive(Device *device)
+-    : StorageDrive(device), m_ejectInProgress(false), m_readSpeed(0), m_writeSpeed(0), m_speedsInit(false)
++    : StorageDrive(device)
++    , m_ejectInProgress(false)
++    , m_readSpeed(0)
++    , m_writeSpeed(0)
++    , m_speedsInit(false)
+ {
+     m_device->registerAction("eject", this,
+                              SLOT(slotEjectRequested()),




More information about the arch-commits mailing list