Multiple connection names from one factory
authorJohannes Schanda <schanda@itestra.de>
Tue, 11 Jun 2013 15:34:44 +0000 (17:34 +0200)
committerJohannes Schanda <schanda@itestra.de>
Tue, 11 Jun 2013 15:34:44 +0000 (17:34 +0200)
- Corrects the obsolete check for multiple connection name claims when
registering stubs
- Moves claimedNames set in to DBusConnection
- DBusConnection now handles whether or not it needs to claim or release
names, users can safely call the provided methods without external
checks
- when releasing the last stub using a particular connection name, the
name is released also

src/CommonAPI/DBus/DBusConnection.cpp
src/CommonAPI/DBus/DBusConnection.h
src/CommonAPI/DBus/DBusFactory.cpp
src/CommonAPI/DBus/DBusFactory.h
src/CommonAPI/DBus/DBusProxyConnection.h
src/CommonAPI/DBus/DBusStubAdapter.cpp

index 01cd689..b549884 100644 (file)
@@ -67,7 +67,8 @@ DBusConnection::DBusConnection(BusType busType) :
                 pauseDispatching_(false),
                 dispatchThread_(NULL),
                 dbusObjectMessageHandler_(),
-                watchContext_(NULL)  {
+                watchContext_(NULL),
+                connectionNameCount_() {
     dbus_threads_init_default();
 }
 
@@ -79,7 +80,8 @@ DBusConnection::DBusConnection(::DBusConnection* libDbusConnection) :
                 pauseDispatching_(false),
                 dispatchThread_(NULL),
                 dbusObjectMessageHandler_(),
-                watchContext_(NULL) {
+                watchContext_(NULL),
+                connectionNameCount_() {
     dbus_threads_init_default();
 }
 
@@ -338,30 +340,52 @@ const std::shared_ptr<DBusObjectManager> DBusConnection::getDBusObjectManager()
 
 bool DBusConnection::requestServiceNameAndBlock(const std::string& serviceName) const {
     DBusError dbusError;
+    bool isServiceNameAcquired = false;
+    std::lock_guard<std::mutex> dbusConnectionLock(libdbusConnectionGuard_);
+    auto conIter = connectionNameCount_.find(serviceName);
+    if (conIter == connectionNameCount_.end()) {
+        suspendDispatching();
 
-    suspendDispatching();
-
-    const int libdbusStatus = dbus_bus_request_name(libdbusConnection_,
-                                                    serviceName.c_str(),
-                                                    DBUS_NAME_FLAG_DO_NOT_QUEUE,
-                                                    &dbusError.libdbusError_);
+        const int libdbusStatus = dbus_bus_request_name(libdbusConnection_,
+                        serviceName.c_str(),
+                        DBUS_NAME_FLAG_DO_NOT_QUEUE,
+                        &dbusError.libdbusError_);
 
-    resumeDispatching();
+        resumeDispatching();
 
-    const bool isServiceNameAcquired = (libdbusStatus == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+        isServiceNameAcquired = (libdbusStatus == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+        if (isServiceNameAcquired) {
+            connectionNameCount_.insert({serviceName, (uint16_t)1});
+        }
+    } else {
+        conIter->second = conIter->second + 1;
+        isServiceNameAcquired = true;
+    }
 
     return isServiceNameAcquired;
 }
 
 bool DBusConnection::releaseServiceName(const std::string& serviceName) const {
     DBusError dbusError;
-    suspendDispatching();
-    const int libdbusStatus = dbus_bus_release_name(libdbusConnection_,
-                                                    serviceName.c_str(),
-                                                    &dbusError.libdbusError_);
-    resumeDispatching();
-    const bool isServiceNameReleased = (libdbusStatus == DBUS_RELEASE_NAME_REPLY_RELEASED);
-
+    bool isServiceNameReleased = false;
+    std::lock_guard<std::mutex> dbusConnectionLock(libdbusConnectionGuard_);
+    auto conIter = connectionNameCount_.find(serviceName);
+    if (conIter != connectionNameCount_.end()) {
+        if (conIter->second == 1) {
+            suspendDispatching();
+            const int libdbusStatus = dbus_bus_release_name(libdbusConnection_,
+                            serviceName.c_str(),
+                            &dbusError.libdbusError_);
+            resumeDispatching();
+            isServiceNameReleased = (libdbusStatus == DBUS_RELEASE_NAME_REPLY_RELEASED);
+            if (isServiceNameReleased) {
+                connectionNameCount_.erase(conIter);
+            }
+        } else {
+            conIter->second = conIter->second - 1;
+            isServiceNameReleased = true;
+        }
+    }
     return isServiceNameReleased;
 }
 
index 5f19d7b..83d02a4 100644 (file)
@@ -166,7 +166,7 @@ class DBusConnection: public DBusProxyConnection, public std::enable_shared_from
     static void onWakeupMainContext(void* data);
 
     ::DBusConnection* libdbusConnection_;
-    std::mutex libdbusConnectionGuard_;
+    mutable std::mutex libdbusConnectionGuard_;
     std::mutex signalGuard_;
     std::mutex objectManagerGuard_;
     std::mutex serviceRegistryGuard_;
@@ -192,6 +192,8 @@ class DBusConnection: public DBusProxyConnection, public std::enable_shared_from
     static DBusObjectPathVTable libdbusObjectPathVTable_;
 
     DBusObjectPathMessageHandler dbusObjectMessageHandler_;
+
+    mutable std::unordered_map<std::string, uint16_t> connectionNameCount_;
 };
 
 std::shared_ptr<DBusConnection> DBusConnection::getBus(const BusType& busType) {
index f28ef2f..39bfb7a 100644 (file)
@@ -45,7 +45,6 @@ void DBusFactory::registerAdapterFactoryMethod(std::string interfaceName, DBusAd
 DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext) :
                 CommonAPI::Factory(runtime, middlewareInfo),
                 dbusConnection_(CommonAPI::DBus::DBusConnection::getSessionBus()),
-                acquiredConnectionName_(""),
                 mainLoopContext_(mainLoopContext) {
     bool startDispatchThread = !mainLoopContext_;
     dbusConnection_->connect(startDispatchThread);
@@ -158,13 +157,8 @@ bool DBusFactory::registerAdapter(std::shared_ptr<StubBase> stubBase,
 
     DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
 
-    if(acquiredConnectionName_ == "") {
-        bool isServiceNameAcquired = dbusConnection_->requestServiceNameAndBlock(connectionName);
-        if(!isServiceNameAcquired) {
-            return false;
-        }
-        acquiredConnectionName_ = connectionName;
-    } else if (acquiredConnectionName_ != connectionName) {
+    bool isServiceNameAcquired = dbusConnection_->requestServiceNameAndBlock(connectionName);
+    if (!isServiceNameAcquired) {
         return false;
     }
 
index 7516d9a..3775944 100644 (file)
@@ -60,7 +60,6 @@ class DBusFactory: public Factory {
     SubscriptionStatus isServiceInstanceAliveCallbackThunk(Factory::IsServiceInstanceAliveCallback callback, const AvailabilityStatus& status);
 
     std::shared_ptr<CommonAPI::DBus::DBusConnection> dbusConnection_;
-    std::string acquiredConnectionName_;
     std::shared_ptr<MainLoopContext> mainLoopContext_;
 };
 
index 19140f2..c346c44 100644 (file)
@@ -95,6 +95,9 @@ class DBusProxyConnection {
     virtual void registerObjectPath(const std::string& objectPath) = 0;
     virtual void unregisterObjectPath(const std::string& objectPath) = 0;
 
+    virtual bool requestServiceNameAndBlock(const std::string& serviceName) const = 0;
+    virtual bool releaseServiceName(const std::string& serviceName) const = 0;
+
     typedef std::function<bool(const DBusMessage&)> DBusObjectPathMessageHandler;
 
     virtual void setObjectPathMessageHandler(DBusObjectPathMessageHandler) = 0;
index 050ed40..90e04b4 100644 (file)
@@ -47,6 +47,7 @@ void DBusStubAdapter::deinit() {
 
        if (isInitialized_) {
                dbusConnection_->getDBusObjectManager()->unregisterDBusStubAdapter(dbusInterfaceHandlerToken_);
+               dbusConnection_->releaseServiceName(dbusBusName_);
                isInitialized_ = false;
        }
 }