#endif
#include "DBusProxy.h"
-#include "DBusServiceRegistry.h"
#include "DBusUtils.h"
#include <cassert>
const std::string commonApiDomain = split(commonApiAddress, ':')[0];
assert(commonApiDomain == "local");
- dbusConnection->getDBusServiceRegistry()->registerAvailabilityListener(
+ dbusServiceRegistrySubscription_ = dbusConnection->getDBusServiceRegistry()->subscribeAvailabilityListener(
commonApiAddress,
std::bind(&DBusProxy::onDBusServiceInstanceStatus, this, std::placeholders::_1));
}
DBusProxy::~DBusProxy() {
+ getDBusConnection()->getDBusServiceRegistry()->unsubscribeAvailabilityListener(
+ getAddress(),
+ dbusServiceRegistrySubscription_);
}
bool DBusProxy::isAvailable() const {
#include "DBusProxyBase.h"
#include "DBusAttribute.h"
+#include "DBusServiceRegistry.h"
#include <functional>
#include <memory>
void onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus);
DBusProxyStatusEvent dbusProxyStatusEvent_;
+ DBusServiceRegistry::Subscription dbusServiceRegistrySubscription_;
DBusServiceStatusEvent::Subscription dbusServiceStatusEventSubscription_;
AvailabilityStatus availabilityStatus_;
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DBusFunctionalHash.h"
#include "DBusServiceRegistry.h"
-#include "DBusInputStream.h"
#include "DBusDaemonProxy.h"
-#include "DBusProxyConnection.h"
-#include "DBusUtils.h"
#include "DBusProxyAsyncCallbackHandler.h"
namespace CommonAPI {
return serviceStatusEvent_;
}
-void DBusServiceRegistry::registerAvailabilityListener(const std::string& commonApiAddress, DBusServiceListener serviceListener) {
+DBusServiceRegistry::Subscription DBusServiceRegistry::subscribeAvailabilityListener(const std::string& commonApiAddress,
+ DBusServiceListener serviceListener) {
std::string dbusInterfaceName;
std::string dbusServiceName;
std::string dbusObjectPath;
dbusInstanceAvailabilityStatus = AvailabilityStatus::NOT_AVAILABLE;
}
- dbusServiceListenerList.push_back(serviceListener);
-
+ Subscription listenerSubscription = dbusServiceListenerList.insert(
+ dbusServiceListenerList.end(), serviceListener);
switch (dbusServiceState) {
case DBusServiceState::AVAILABLE:
serviceListener(dbusInstanceAvailabilityStatus);
break;
}
+
+ return listenerSubscription;
+}
+
+void DBusServiceRegistry::unsubscribeAvailabilityListener(const std::string& commonApiAddress,
+ Subscription& listenerSubscription) {
+ std::string dbusInterfaceName;
+ std::string dbusServiceName;
+ std::string dbusObjectPath;
+
+ DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, dbusInterfaceName, dbusServiceName, dbusObjectPath);
+
+ std::lock_guard<std::mutex> dbusServicesLock(dbusServicesMutex_);
+ auto dbusServiceIterator = dbusServices_.find(dbusServiceName);
+
+ if (dbusServiceIterator == dbusServices_.end()) {
+ return;
+ }
+
+ DBusServiceState& dbusServiceState = dbusServiceIterator->second.first;
+ DBusInstanceList& dbusInstanceList = dbusServiceIterator->second.second;
+
+ auto dbusInstanceIterator = dbusInstanceList.find({ dbusObjectPath, dbusInterfaceName });
+ if (dbusInstanceIterator == dbusInstanceList.end()) {
+ return;
+ }
+
+ const AvailabilityStatus& dbusServiceAvailabilityStatus = dbusInstanceIterator->second.first;
+ DBusServiceListenerList& dbusServiceListenerList = dbusInstanceIterator->second.second;
+
+ dbusServiceListenerList.erase(listenerSubscription);
+
+ if (dbusServiceListenerList.empty() && dbusServiceAvailabilityStatus != AvailabilityStatus::AVAILABLE) {
+ dbusInstanceList.erase(dbusInstanceIterator);
+
+ if (dbusInstanceList.empty() && dbusServiceState == DBusServiceState::UNKNOWN) {
+ dbusServices_.erase(dbusServiceIterator);
+ }
+ }
}
SubscriptionStatus DBusServiceRegistry::onDBusDaemonProxyStatusEvent(const AvailabilityStatus& availabilityStatus) {
class DBusServiceRegistry {
public:
+ enum class DBusServiceState {
+ UNKNOWN,
+ AVAILABLE,
+ RESOLVING,
+ RESOLVED,
+ NOT_AVAILABLE
+ };
+
typedef std::function<void(const AvailabilityStatus& availabilityStatus)> DBusServiceListener;
+ typedef std::list<DBusServiceListener> DBusServiceListenerList;
+ typedef DBusServiceListenerList::iterator Subscription;
+
+ typedef std::pair<std::string, std::string> DBusObjectInterfacePair;
+ typedef std::unordered_map<DBusObjectInterfacePair, std::pair<AvailabilityStatus, DBusServiceListenerList> > DBusInstanceList;
+ typedef std::unordered_map<std::string, std::pair<DBusServiceState, DBusInstanceList> > DBusServiceList;
+
DBusServiceRegistry();
bool isServiceInstanceAlive(const std::string& dbusInterfaceName, const std::string& dbusConnectionName, const std::string& dbusObjectPath);
- void registerAvailabilityListener(const std::string& commonApiAddress, DBusServiceListener serviceListener);
+ Subscription subscribeAvailabilityListener(const std::string& commonApiAddress,
+ DBusServiceListener serviceListener);
+ void unsubscribeAvailabilityListener(const std::string& commonApiAddress,
+ Subscription& listenerSubscription);
virtual std::vector<std::string> getAvailableServiceInstances(const std::string& interfaceName,
const std::string& domainName = "local");
virtual DBusServiceStatusEvent& getServiceStatusEvent();
private:
- enum class DBusServiceState {
- UNKNOWN,
- AVAILABLE,
- RESOLVING,
- RESOLVED,
- NOT_AVAILABLE
- };
-
- typedef std::list<DBusServiceListener> DBusServiceListenerList;
- typedef std::pair<std::string, std::string> DBusObjectInterfacePair;
- typedef std::unordered_map<DBusObjectInterfacePair, std::pair<AvailabilityStatus, DBusServiceListenerList> > DBusInstanceList;
- typedef std::unordered_map<std::string, std::pair<DBusServiceState, DBusInstanceList> > DBusServiceList;
-
-
DBusServiceRegistry(const DBusServiceRegistry&) = delete;
DBusServiceRegistry& operator=(const DBusServiceRegistry&) = delete;
void DBusServiceStatusEvent::onListenerAdded(const std::string& commonApiServiceName, const Listener& listener) {
if (registry_) {
-
- registry_->registerAvailabilityListener(commonApiServiceName, std::bind(
+ registry_->subscribeAvailabilityListener(commonApiServiceName, std::bind(
&DBusServiceStatusEvent::availabilityEvent,
this,
commonApiServiceName,