Domanda

Con un proxy Qt DBus basato su QDbusAbstractInterface (tramite qdbusxml2cpp), qual è il modo migliore per gestire il servizio / oggetto che si desidera interfacciare per non essere disponibile all'avvio? Nota: non mi interessa semplicemente conoscerlo (è possibile utilizzare BlahService.isValid () per scoprirlo); Voglio essere in grado di sapere se è valido e sapere quando diventa valido in modo da poter cambiare stato (e trasmettere quel cambiamento di stato con un segnale), e su quel cambiamento di stato fare altre cose. Al contrario, voglio sapere quando non è più valido per motivi simili.

Senza tenere traccia dello stato del servizio:

#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?
}

Probabilmente dobbiamo guardare NameOwnerChanged sull'oggetto di connessione DBus - a meno che il codice dbus di QT non lo faccia per noi - e quindi quando otteniamo quel cambiamento di stato del segnale e, se necessario, connettere o disconnettere i segnali dall'oggetto.

Tutti gli esempi che trovo ignorano il problema o semplicemente escono se l'oggetto server non esiste e non affrontano la scomparsa. L'esempio Qt per auto / controller rileva almeno se il server si spegne e stampa "Disconnesso" se isValid () diventa falso durante l'uso, ma il polling isValid ().

Aggiunto:

Notare che QtDbusAbtractInterface registra le modifiche alla proprietà del server (NameOwnerChanged) e aggiorna isValid () quando si verificano delle modifiche. Quindi sospetto che tu possa connetterti direttamente a quel segnale ServerOwnerChanged per scoprire le modifiche alla proprietà e utilizzarlo come indicatore per riprovare - anche se non sarai in grado di fidarti di isValid poiché potrebbe essere aggiornato prima o dopo aver ricevuto la segnalazione.

In alternativa (brutto) puoi impostare un timer e un sondaggio per isValid ().

È stato utile?

Soluzione

Ok, dato che nessuno ha risposto, nel frattempo ho trovato la risposta:

Vuoi guardare 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)));

e

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();
        }
    }
}

Nota che potrebbero esserci condizioni di gara nel fare metodi su FooService dall'interno di serviceOwnerChanged - Non sono ancora sicuro se siano un effetto collaterale dell'associazione (dbus-c ++ nel mio test caso), o inerente alla progettazione di dbus (possibile - no sulla lista di indirizzi dbus risponderà alla domanda). Se esiste una vera condizione di gara, puoi attendere un segnale Ready () / qualunque, se controlli l'API DBus. Se non controlli l'altra estremità, puoi aggiungere un ritardo molto breve oppure puoi anche guardare AddMatch () per assicurarti che anche il nuovo proprietario abbia aggiunto una corrispondenza sul nome.

Altri suggerimenti

Con Qt 5.3, serviceOwnerChanged è obsoleto. Utilizza QDBusServiceWatcher che consente di cercare un servizio specifico invece di tutti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top