Question

Avec un proxy Qt DBus construit sur QDbusAbstractInterface (via qdbusxml2cpp), quel est le meilleur moyen de gérer le service / objet que vous souhaitez interfacer pour qu’il ne soit pas disponible au démarrage? Note: Je ne suis pas intéressé à simplement le savoir (vous pouvez utiliser BlahService.isValid () pour le savoir); Je veux pouvoir savoir s'il est valide et quand il le deviendra afin que je puisse changer d'état (et diffuser ce changement d'état avec un signal), puis effectuer d'autres modifications. Inversement, je veux savoir quand ce n'est plus valable pour des raisons similaires.

Sans suivre l'état du service:

#define CONNECT_DBUS_SIG(x,y) connect(blah,SIGNAL(x),this,SLOT(y))

// FIX - should watch for service, and also handle it going away and
// coming back
blah = new BlahService("com.xyzzy.BlahService", "/com/xyzzy/BlahService",
                           QDBusConnection::sessionBus(), this);
if (!blah)
    return 0;
if (blah.isValid())
{
    CONNECT_DBUS_SIG(foo(),Event_foo());
}
else
{
    // Since we aren't watching for registration, what can we do but exit?
}

Nous devons probablement surveiller NameOwnerChanged sur l'objet de connexion DBus - à moins que le code dbus de QT ne le fasse pour nous - et ensuite, lorsque nous obtenons l'état de changement de signal et, si nécessaire, connecter ou déconnecter les signaux de l'objet.

Tous les exemples que je trouve ignorent le problème ou disparaissent simplement si l'objet serveur n'existe pas et ne s'en occupent pas. L’exemple Car / Controller Qt indique au moins si le serveur s’éloigne et imprime " Déconnecté " Si isValid () devient faux lors de son utilisation, mais qu'il interroge isValid ().

Ajouté:

Notez que QtDbusAbtractInterface enregistre les modifications de propriété du serveur (NameOwnerChanged) et met à jour isValid () lorsque des modifications sont apportées. Je suppose donc que vous pouvez vous connecter directement à ce signal serverOwnerChanged pour connaître les modifications apportées à la propriété et l'utiliser comme indicateur pour réessayer, même si vous ne pourrez pas faire confiance à isValid car il peut être mis à jour avant ou après avoir été signalé.

Alternativement (moche), vous pouvez configurer une minuterie et interroger isValid ().

Était-ce utile?

La solution

D'accord, puisque personne n'a répondu, j'ai trouvé la réponse entre-temps:

Vous souhaitez regarder NameOwnerChanged:

// subscribe to notifications about when a service is registered/unregistered
   connect(QDBusConnection::sessionBus().interface(),
           SIGNAL(serviceOwnerChanged(QString,QString,QString)),
           this,SLOT(serviceOwnerChanged(QString,QString,QString)));

et

void 
VcsApplicationController::serviceOwnerChanged(const QString &name,
                                              const QString &oldOwner,
                                              const QString &newOwner)
{
    Q_UNUSED(oldOwner);
    if (name == "com.foo.bar.FooService")
    {
        qLog(Whatever) << "serviceOwnerChanged" << name << oldOwner << newOwner;
        if (!newOwner.isEmpty())
        {
            // New owner in town
            emit Initialized();
            // or if you control the interface and both sides, you can wait for
            // a "Ready()" signal before declaring FooService ready for business.
        }
        else
        {
            // indicate we've lost connection, etc
            emit Uninitialized();
        }
    }
}

Notez qu'il peut exister des conditions de concurrence lorsque vous utilisez des méthodes sur FooService depuis ServiceOwnerChanged - je ne sais pas encore s'il s'agit d'un effet secondaire de la liaison (dbus-c ++ dans mon test). cas), ou inhérente à la conception de dbus (possible - aucun sur la liste de diffusion dbus ne répondra à la question). Si il y a une situation de concurrence réelle, vous pouvez attendre un signal Ready () / quel que soit le signal choisi, si vous contrôlez l'API DBus. Si vous ne contrôlez pas l'autre extrémité, vous pouvez ajouter un très court délai ou regarder AddMatch () pour vous assurer que le nouveau propriétaire a également ajouté une correspondance pour le nom.

Autres conseils

Avec Qt 5.3, serviceOwnerChanged est obsolète. Utilisez QDBusServiceWatcher qui permet de rechercher un service spécifique au lieu de tous.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top