Ожидание доступности службы DBus в Qt - PullRequest
12 голосов
/ 15 сентября 2009

С прокси-сервером Qt DBus, построенным на QDbusAbstractInterface (через qdbusxml2cpp), каков наилучший способ обработки службы / объекта, к которым вы хотите подключиться, чтобы они не были доступны при запуске? Примечание: мне не интересно просто знать это (вы можете использовать BlahService.isValid (), чтобы узнать это); Я хочу знать, действительно ли он действителен, и знать, когда он станет действительным, чтобы я мог изменить состояние (и передать это изменение состояния с помощью сигнала), и с этим изменением состояния делать другие вещи. И наоборот, я хочу знать, когда он больше не действителен по аналогичным причинам.

Без отслеживания состояния услуги:

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

Вероятно, нам нужно следить за NameOwnerChanged на объекте соединения DBus - если только код dbus QT не сделает это за нас - и затем, когда мы получим это состояние изменения сигнала, и при необходимости подключим или отключим сигналы от объекта.

Все примеры, которые я нахожу, либо игнорируют проблему, либо просто завершаются, если объект сервера не существует, и не устраняют его. Пример Car / Controller Qt по крайней мере замечает, если сервер уходит, и печатает «Отключено», если isValid () становится ложным во время использования, но опрашивает isValid ().

Добавлено:

Обратите внимание, что QtDbusAbtractInterface регистрирует изменения владельца сервера (NameOwnerChanged) и обновляет isValid () при возникновении изменений. Поэтому я подозреваю, что вы можете подключиться к этому сигналу serverOwnerChanged напрямую, чтобы узнать об изменениях владельца и использовать его в качестве индикатора для повторной попытки - хотя вы не сможете доверять isValid, поскольку он может быть обновлен до или после получения сигнала.

В качестве альтернативы (безобразно) вы можете установить таймер и опросить isValid ().

Ответы [ 2 ]

10 голосов
/ 24 сентября 2009

Хорошо, поскольку никто не ответил, я тем временем нашел ответ:

Вы хотите посмотреть 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)));

и

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

Обратите внимание, что может быть условиями гонки с использованием методов на FooService из serviceOwnerChanged - я пока не уверен, является ли это побочным эффектом привязки (dbus-c ++ в моем тестовом примере ) или присуще дизайну dbus (возможно - нет ответа в списке рассылки dbus, ответит на вопрос). Если является реальным условием гонки, вы можете ожидать сигнала Ready () / любого другого, если вы управляете DBus API. Если вы не управляете другим концом, вы можете добавить очень короткую задержку или также посмотреть AddMatch (), чтобы убедиться, что новый владелец также добавил совпадение в имя.

4 голосов
/ 22 октября 2014

В Qt 5.3 serviceOwnerChanged устарело. Используйте QDBusServiceWatcher, который позволяет отслеживать конкретную услугу вместо всех.

...