add subscribe/unsubscribe methods for DBusServiceRegistry
authorAleksandar Kanchev <kanchev@itestra.com>
Wed, 27 Feb 2013 16:03:42 +0000 (17:03 +0100)
committerAleksandar Kanchev <kanchev@itestra.com>
Wed, 27 Feb 2013 16:03:42 +0000 (17:03 +0100)
src/CommonAPI/DBus/DBusProxy.cpp
src/CommonAPI/DBus/DBusProxy.h
src/CommonAPI/DBus/DBusServiceRegistry.cpp
src/CommonAPI/DBus/DBusServiceRegistry.h
src/CommonAPI/DBus/DBusServiceStatusEvent.cpp

index e6e1e53..842e258 100644 (file)
@@ -10,7 +10,6 @@
 #endif
 
 #include "DBusProxy.h"
-#include "DBusServiceRegistry.h"
 #include "DBusUtils.h"
 
 #include <cassert>
@@ -46,12 +45,15 @@ DBusProxy::DBusProxy(const std::string& commonApiAddress,
     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 {
index 385dbd2..76e1526 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "DBusProxyBase.h"
 #include "DBusAttribute.h"
+#include "DBusServiceRegistry.h"
 
 #include <functional>
 #include <memory>
@@ -53,6 +54,7 @@ class DBusProxy: public DBusProxyBase {
     void onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus);
 
     DBusProxyStatusEvent dbusProxyStatusEvent_;
+    DBusServiceRegistry::Subscription dbusServiceRegistrySubscription_;
     DBusServiceStatusEvent::Subscription dbusServiceStatusEventSubscription_;
     AvailabilityStatus availabilityStatus_;
 
index 84c1382..7b8ff19 100644 (file)
@@ -6,10 +6,7 @@
  * 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 {
@@ -231,7 +228,8 @@ DBusServiceStatusEvent& DBusServiceRegistry::getServiceStatusEvent() {
     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;
@@ -270,8 +268,8 @@ void DBusServiceRegistry::registerAvailabilityListener(const std::string& common
         dbusInstanceAvailabilityStatus = AvailabilityStatus::NOT_AVAILABLE;
     }
 
-    dbusServiceListenerList.push_back(serviceListener);
-
+    Subscription listenerSubscription = dbusServiceListenerList.insert(
+                    dbusServiceListenerList.end(), serviceListener);
 
     switch (dbusServiceState) {
         case DBusServiceState::AVAILABLE:
@@ -283,6 +281,45 @@ void DBusServiceRegistry::registerAvailabilityListener(const std::string& common
             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) {
index 854139d..e86147c 100644 (file)
@@ -47,7 +47,22 @@ class DBusDaemonProxy;
 
 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();
 
@@ -57,7 +72,10 @@ class 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");
@@ -65,20 +83,6 @@ class DBusServiceRegistry {
     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;
 
index 8127ded..99ef03e 100644 (file)
@@ -25,8 +25,7 @@ void DBusServiceStatusEvent::availabilityEvent(const std::string& commonApiServi
 
 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,