2009-09-14 18 views
11

Con un proxy Qt DBus creado en QDbusAbstractInterface (a través de qdbusxml2cpp), ¿cuál es la mejor forma de manejar el servicio/objeto que desea que no esté disponible cuando se inicia? Nota: no me interesa simplemente saberlo (puede usar BlahService.isValid() para descubrirlo); Quiero poder saber si es válido y saber cuándo se convierte en válido para poder cambiar el estado (y transmitir ese cambio de estado con una señal), y en ese cambio de estado hacer otras cosas. Por el contrario, quiero saber cuándo ya no es válido por razones similares.Esperando a que esté disponible un servicio DBus en Qt

sin el seguimiento del estado del servicio:

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

Probablemente tenemos que mirar para NameOwnerChanged en el objeto de conexión Enlace con el Bus - a no ser que el código dbus de QT hace esto por nosotros - y luego, cuando tenemos ese estado de cambio de señal y, si es necesario, conecta o desconecta las señales del objeto.

Todos los ejemplos que encuentro ignoran el problema o simplemente lo cierran si el objeto del servidor no existe y no lo solucionan. El ejemplo de Car/Controller Qt al menos avisa si el servidor desaparece e imprime "Desconectado" si isValid() se convierte en falso durante el uso, pero el sondeo es Valido().

Agregado:

Tenga en cuenta que QtDbusAbtractInterface registra los cambios de propiedad del servidor (NameOwnerChanged), y actualizaciones isValid() cuando se producen cambios. Así que sospecho que puede conectarse directamente a esa señal serverOwnerChanged para conocer los cambios en la propiedad y usar eso como indicador para volver a intentarlo, aunque no podrá confiar en isValid ya que puede actualizarse antes o después de que se le envíe una señal.

Alternativamente (feo) puede configurar un temporizador y una encuesta para isValid().

Respuesta

9

Ok, ya que nadie respondió, he encontrado la respuesta en el ínterin:

quiere ver 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))); 

y

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 que hay puede ser condiciones de carrera con hacer métodos en FooService desde serviceOwnerChanged - No estoy seguro aún si son un efecto secundario de la unión (dbus-C++ en mi caso de prueba), o inherente en el diseño de dbus (posible - no en la lista de correo de dbus responderá la pregunta). Si hay es una condición de carrera real, puede esperar con una señal de Ready()/cualquier señal, si controla la API de DBus. Si no controla el otro extremo, puede agregar un retraso muy corto o también puede ver AddMatch() para asegurarse de que el nuevo propietario también haya agregado una coincidencia en el nombre.

+0

Utilizo esta línea para obtener solo la señal del servicio que deseo: 'QDBusConnection :: systemBus(). Connect (" org.freedesktop.DBus ","/org/freedesktop/DBus "," org.freedesktop. DBus ", " NameOwnerChanged ", QStringList() <<" org.freedesktop.Avahi "," sss ", esto, SLOT (AvahiNameOwnerChanged (QString, QString, QString)));' En cuanto a la condición de carrera, I eliminar mi interfaz anterior y obtener una nueva una vez que reciba esta señal. – Harvey

3

Con Qt 5.3, serviceOwnerChanged está obsoleto. Use QDBusServiceWatcher, lo que le permite ver un servicio específico en vez de todo.

Cuestiones relacionadas