Implement a Lock/Unlock Queue API calls. 74/41874/7
authorLukasz Pawelczyk <l.pawelczyk@samsung.com>
Thu, 18 Jun 2015 13:21:38 +0000 (15:21 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Tue, 30 Jun 2015 09:01:28 +0000 (02:01 -0700)
[Feature]       Calls that make it possible to lock a queue exclusively
                to one client (IPC/DBUS) which can then order few calls
                in a row with a guarantee that no other client will
                interrupt.
[Cause]         n/a
[Solution]      n/a
[Verification]  Built, installed, run tests. Also see below.

Additional features implemented in this commit to support the above:
- DBus client disconnected notification. Adds a new callback to
  registerObject() that's called when a client that previously talked to
  the server gets disconnected.
- ZoneManager level client disconnect notification using the
  aforementioned DBus and already implemented IPC functionalities.
- Changed SwitchToDefault from signal to a method so we can return an
  error code when the queue is locked.
- MethodResultBuilder's getID() call that returns ipc independent
  identifier that client connections can be identified with (using
  getPeerID and getPeerName from IPC and DBus specific classes
  respectively).
- mGuard fixed in the DbusConnection class. Now it really does protect
  mConnection and mNameID as well as newly introduced mWatchedClients.
- Various half-related fixes/changes here and there (whitespaces,
  duplicate definition of PROXY_CALL in the DBus interface, etc).

There are no tests in this commit for the DBus features and the
Lock/Unlock queue. They will follow in the later commits.

To somewhat test the disconnect notifications (both, DBus level and
ZoneManager level) one can connect to the server using appropriate APIs
and watch the DEBUG/TRACE logs. This can be achieved using the following
commands:

$ dbus-send --system --dest=org.tizen.vasum.host \
            --type=method_call --print-reply \
            /org/tizen/vasum/host \
            org.tizen.vasum.host.manager.GetZoneIds
$ vasum-cli get_zone_ids

WARNING: this commit breaks API/ABI of libSimpleDbus

Change-Id: Ic0ed2371e563c34340ad41d66dd943a1abc8eb48

25 files changed:
client/vasum-client-impl.cpp
client/vasum-client-impl.hpp
client/vasum-client.cpp
client/vasum-client.h
common/api/dbus-method-result-builder.hpp
common/api/ipc-method-result-builder.cpp
common/api/ipc-method-result-builder.hpp
common/api/method-result-builder.hpp
libs/dbus/connection.cpp
libs/dbus/connection.hpp
libs/ipc/method-result.cpp
libs/ipc/method-result.hpp
server/common-definitions.hpp
server/host-dbus-connection.cpp
server/host-dbus-connection.hpp
server/host-dbus-definitions.hpp
server/host-ipc-connection.cpp
server/host-ipc-connection.hpp
server/host-ipc-definitions.hpp
server/zones-manager.cpp
server/zones-manager.hpp
tests/unit_tests/dbus/test-server.cpp
tests/unit_tests/dbus/ut-connection.cpp
tests/unit_tests/server/ut-zones-manager.cpp
zone-daemon/daemon-connection.cpp

index f9a15b8..343fd1b 100644 (file)
@@ -308,6 +308,24 @@ VsmStatus Client::vsm_get_zone_dbuses(VsmArrayString* /*keys*/, VsmArrayString*
     });
 }
 
+VsmStatus Client::vsm_lock_queue() noexcept
+{
+    return coverException([&] {
+        *mClient->callSync<api::Void, api::Void>(
+            vasum::api::ipc::METHOD_LOCK_QUEUE,
+            std::make_shared<api::Void>());
+    });
+}
+
+VsmStatus Client::vsm_unlock_queue() noexcept
+{
+    return coverException([&] {
+        *mClient->callSync<api::Void, api::Void>(
+            vasum::api::ipc::METHOD_UNLOCK_QUEUE,
+            std::make_shared<api::Void>());
+    });
+}
+
 VsmStatus Client::vsm_get_zone_ids(VsmArrayString* array) noexcept
 {
     return coverException([&] {
index 854c32c..845cf29 100644 (file)
@@ -123,6 +123,16 @@ public:
     VsmStatus vsm_get_zone_dbuses(VsmArrayString* keys, VsmArrayString* values) noexcept;
 
     /**
+     *  @see ::vsm_lock_queue
+     */
+    VsmStatus vsm_lock_queue() noexcept;
+
+    /**
+     *  @see ::vsm_unlock_queue
+     */
+    VsmStatus vsm_unlock_queue() noexcept;
+
+    /**
      *  @see ::vsm_get_zone_ids
      */
     VsmStatus vsm_get_zone_ids(VsmArrayString* array) noexcept;
index f36c1ed..4acd82a 100644 (file)
@@ -45,6 +45,16 @@ Client& getClient(VsmClient client)
 
 } // namespace
 
+API VsmStatus vsm_lock_queue(VsmClient client)
+{
+    return getClient(client).vsm_lock_queue();
+}
+
+API VsmStatus vsm_unlock_queue(VsmClient client)
+{
+    return getClient(client).vsm_unlock_queue();
+}
+
 API VsmStatus vsm_get_poll_fd(VsmClient client, int* fd)
 {
     return getClient(client).vsm_get_poll_fd(fd);
index 3832d23..9216ce9 100644 (file)
@@ -404,6 +404,22 @@ typedef void (*VsmZoneDbusStateCallback)(const char* zoneId,
                                              void* data);
 
 /**
+ * Lock the command queue exclusively.
+ *
+ * @param[in] client vasum-server's client
+ * @return status of this function call
+ */
+VsmStatus vsm_lock_queue(VsmClient client);
+
+/**
+ * Unlock the command queue.
+ *
+ * @param[in] client vasum-server's client
+ * @return status of this function call
+ */
+VsmStatus vsm_unlock_queue(VsmClient client);
+
+/**
  * Get dbus address of each zone.
  *
  * @param[in] client vasum-server's client
index c6422dc..7673b65 100644 (file)
@@ -39,6 +39,8 @@
 namespace vasum {
 namespace api {
 
+const std::string DBUS_CONNECTION_PREFIX = "dbus://";
+
 template<typename Data>
 class DbusMethodResultBuilder: public MethodResultBuilder {
 public:
@@ -49,6 +51,7 @@ private:
     void setImpl(const std::shared_ptr<void>& data) override;
     void setVoid() override;
     void setError(const std::string& name, const std::string& message) override;
+    std::string getID() const;
 
     ::dbus::MethodResultBuilder::Pointer mMethodResultBuilderPtr;
     std::function<GVariant*(std::shared_ptr<void>)> mSerialize;
@@ -82,6 +85,12 @@ void DbusMethodResultBuilder<Data>::setError(const std::string& name, const std:
     mMethodResultBuilderPtr->setError(name, message);
 }
 
+template<typename Data>
+std::string DbusMethodResultBuilder<Data>::getID() const
+{
+    return DBUS_CONNECTION_PREFIX + mMethodResultBuilderPtr->getPeerName();
+}
+
 } // namespace result
 } // namespace vasum
 
index 4ea2845..d7ac681 100644 (file)
@@ -48,6 +48,11 @@ void IPCMethodResultBuilder::setError(const std::string& , const std::string& me
     mMethodResultPtr->setError(1, message);
 }
 
+std::string IPCMethodResultBuilder::getID() const
+{
+    return IPC_CONNECTION_PREFIX + std::to_string(mMethodResultPtr->getPeerID());
+}
+
 } // namespace result
 } // namespace vasum
 
index 7b03ece..0b0ddd3 100644 (file)
@@ -36,6 +36,8 @@
 namespace vasum {
 namespace api {
 
+const std::string IPC_CONNECTION_PREFIX = "ipc://";
+
 class IPCMethodResultBuilder: public MethodResultBuilder {
 public:
     IPCMethodResultBuilder(const ipc::MethodResult::Pointer& methodResult);
@@ -45,6 +47,7 @@ private:
     void setImpl(const std::shared_ptr<void>& data) override;
     void setVoid() override;
     void setError(const std::string& name, const std::string& message) override;
+    std::string getID() const;
 
     ipc::MethodResult::Pointer mMethodResultPtr;
 };
index 89aa7a9..ca31feb 100644 (file)
@@ -43,6 +43,7 @@ public:
     virtual ~MethodResultBuilder() {}
     virtual void setVoid() = 0;
     virtual void setError(const std::string& name, const std::string& message) = 0;
+    virtual std::string getID() const = 0;
 
     template<typename Data>
     void set(const std::shared_ptr<Data>& data)
@@ -52,7 +53,7 @@ public:
     }
 
 private:
-    virtual void setImpl(const std::shared_ptr<void>& data) =0;
+    virtual void setImpl(const std::shared_ptr<void>& data) = 0;
 
 };
 
index 60b3225..ee4cea9 100644 (file)
@@ -65,6 +65,10 @@ public:
         g_dbus_method_invocation_return_dbus_error(mInvocation, name.c_str(), message.c_str());
         mResultSet = true;
     }
+    std::string getPeerName()
+    {
+        return std::string(g_dbus_method_invocation_get_sender(mInvocation));
+    }
 private:
     GDBusMethodInvocation* mInvocation;
     bool mResultSet;
@@ -146,16 +150,19 @@ DbusConnection::DbusConnection(const std::string& address)
 DbusConnection::~DbusConnection()
 {
     // Close connection in a glib thread (because of a bug in glib)
-    GDBusConnection* connection = mConnection;
-    guint nameId = mNameId;
+    auto closeConnection = [this]() {
+        for (auto client : mWatchedClients) {
+            LOGT("Stopped watching the client: " << client.first);
+            g_bus_unwatch_name(client.second);
+        }
 
-    auto closeConnection = [=]() {
-        if (nameId) {
-            g_bus_unown_name(nameId);
+        if (mNameId) {
+            g_bus_unown_name(mNameId);
         }
-        g_object_unref(connection);
+        g_object_unref(mConnection);
         LOGT("Connection deleted");
     };
+
     executeInGlibThread(closeConnection, mGuard);
 }
 
@@ -268,7 +275,8 @@ std::string DbusConnection::introspect(const std::string& busName, const std::st
 
 void DbusConnection::registerObject(const std::string& objectPath,
                                     const std::string& objectDefinitionXml,
-                                    const MethodCallCallback& callback)
+                                    const MethodCallCallback& methodCall,
+                                    const ClientVanishedCallback& clientVanished)
 {
     ScopedGError error;
     GDBusNodeInfo* nodeInfo = g_dbus_node_info_new_for_xml(objectDefinitionXml.c_str(), &error);
@@ -297,8 +305,10 @@ void DbusConnection::registerObject(const std::string& objectPath,
                                       objectPath.c_str(),
                                       interfaceInfo,
                                       &vtable,
-                                      createCallbackWrapper(callback, mGuard.spawn()),
-                                      &deleteCallbackWrapper<MethodCallCallback>,
+                                      createCallbackWrapper(
+                                          MethodCallbacks(methodCall, clientVanished, this),
+                                          mGuard.spawn()),
+                                      &deleteCallbackWrapper<MethodCallbacks>,
                                       &error);
     g_dbus_node_info_unref(nodeInfo);
     if (error) {
@@ -308,7 +318,7 @@ void DbusConnection::registerObject(const std::string& objectPath,
     }
 }
 
-void DbusConnection::onMethodCall(GDBusConnection*,
+void DbusConnection::onMethodCall(GDBusConnection* connection,
                                   const gchar*,
                                   const gchar* objectPath,
                                   const gchar* interface,
@@ -317,14 +327,54 @@ void DbusConnection::onMethodCall(GDBusConnection*,
                                   GDBusMethodInvocation* invocation,
                                   gpointer userData)
 {
-    const MethodCallCallback& callback = getCallbackFromPointer<MethodCallCallback>(userData);
+    const MethodCallbacks& callbacks = getCallbackFromPointer<MethodCallbacks>(userData);
 
     LOGD("MethodCall: " << objectPath << "; " << interface << "; " << method);
 
+    const gchar *sender = g_dbus_method_invocation_get_sender(invocation);
+    ClientsMap &watchedClients = callbacks.dbusConn->mWatchedClients;
+
+    if (watchedClients.find(sender) == watchedClients.end()) {
+        LOGT("Watching the client: " << sender);
+        guint id = g_bus_watch_name_on_connection(connection,
+                                                  sender,
+                                                  G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                                  NULL,
+                                                  &DbusConnection::onClientVanish,
+                                                  createCallbackWrapper(
+                                                      VanishedCallbacks(callbacks.clientVanished,
+                                                                        watchedClients),
+                                                      callbacks.dbusConn->mGuard.spawn()),
+                                                  &deleteCallbackWrapper<VanishedCallbacks>);
+
+        watchedClients[sender] = id;
+    }
+
     MethodResultBuilder::Pointer resultBuilder(new MethodResultBuilderImpl(invocation));
-    if (callback) {
-        callback(objectPath, interface, method, parameters, resultBuilder);
+    if (callbacks.methodCall) {
+        callbacks.methodCall(objectPath, interface, method, parameters, resultBuilder);
+    }
+}
+
+void DbusConnection::onClientVanish(GDBusConnection*,
+                                    const gchar *name,
+                                    gpointer userData)
+{
+    const VanishedCallbacks& callbacks = getCallbackFromPointer<VanishedCallbacks>(userData);
+
+    LOGI("ClientVanished: " << name);
+
+    guint id = callbacks.watchedClients[name];
+    callbacks.watchedClients.erase(name);
+
+    if (callbacks.clientVanished) {
+        callbacks.clientVanished(name);
     }
+
+    LOGT("Stopped watching the client: " << name);
+
+    // after this line we cannot use the *name pointer, this call frees it
+    g_bus_unwatch_name(id);
 }
 
 GVariantPtr DbusConnection::callMethod(const std::string& busName,
index 5248d2e..fc7f1f7 100644 (file)
@@ -30,6 +30,7 @@
 #include <memory>
 #include <string>
 #include <functional>
+#include <map>
 #include <gio/gio.h>
 
 
@@ -49,6 +50,7 @@ public:
     virtual void set(GVariant* parameters) = 0;
     virtual void setVoid() = 0;
     virtual void setError(const std::string& name, const std::string& message) = 0;
+    virtual std::string getPeerName() = 0;
 };
 
 /**
@@ -80,6 +82,9 @@ public:
                                MethodResultBuilder::Pointer result
                               )> MethodCallCallback;
 
+    typedef std::function<void(const std::string& name
+                              )> ClientVanishedCallback;
+
     typedef std::function<void(const std::string& senderBusName,
                                const std::string& objectPath,
                                const std::string& interface,
@@ -142,7 +147,8 @@ public:
      */
     void registerObject(const std::string& objectPath,
                         const std::string& objectDefinitionXml,
-                        const MethodCallCallback& callback);
+                        const MethodCallCallback& method,
+                        const ClientVanishedCallback& vanish);
 
     /**
      * Call a dbus method
@@ -181,9 +187,34 @@ private:
             : nameAcquired(acquired), nameLost(lost) {}
     };
 
-    utils::CallbackGuard mGuard;
+    typedef std::map<std::string, guint> ClientsMap;
+
+    struct MethodCallbacks {
+        MethodCallCallback methodCall;
+        ClientVanishedCallback clientVanished;
+        DbusConnection *dbusConn;
+
+        MethodCallbacks(const MethodCallCallback& method,
+                        const ClientVanishedCallback& vanish,
+                        DbusConnection *dbus)
+            : methodCall(method), clientVanished(vanish), dbusConn(dbus) {}
+    };
+
+    struct VanishedCallbacks {
+        ClientVanishedCallback clientVanished;
+        ClientsMap &watchedClients;
+
+        VanishedCallbacks(const ClientVanishedCallback& vanish, ClientsMap& clients)
+            : clientVanished(vanish), watchedClients(clients) {}
+    };
+
     GDBusConnection* mConnection;
     guint mNameId;
+    // It's only ever modified in the glib thread
+    ClientsMap mWatchedClients;
+    // Guard must be destroyed before objects it protects
+    // (e.g. all of the above, see the destructor)
+    utils::CallbackGuard mGuard;
 
     DbusConnection(const std::string& address);
 
@@ -207,6 +238,9 @@ private:
     static void onAsyncReady(GObject* source,
                              GAsyncResult* asyncResult,
                              gpointer userData);
+    static void onClientVanish(GDBusConnection* connection,
+                               const gchar *name,
+                               gpointer userData);
 };
 
 
index ffb97a8..97eb450 100644 (file)
@@ -54,4 +54,9 @@ void MethodResult::setError(const int code, const std::string& message)
     mProcessor.sendError(mPeerID, mMessageID, code, message);
 }
 
+PeerID MethodResult::getPeerID()
+{
+    return mPeerID;
+}
+
 } // namespace ipc
index bd9d10f..26369ed 100644 (file)
@@ -51,6 +51,7 @@ public:
 
     void setVoid();
     void setError(const int code, const std::string& message);
+    PeerID getPeerID();
 
 private:
     Processor& mProcessor;
index cf8bfe4..b7b22ed 100644 (file)
@@ -43,6 +43,7 @@ const std::string ERROR_INVALID_STATE      = "org.tizen.vasum.Error.InvalidState
 const std::string ERROR_INTERNAL           = "org.tizen.vasum.Error.Internal";
 const std::string ERROR_ZONE_NOT_RUNNING   = "org.tizen.vasum.Error.ZonesNotRunning";
 const std::string ERROR_CREATE_FILE_FAILED = "org.tizen.vasum.Error.CreateFileFailed";
+const std::string ERROR_QUEUE              = "org.tizen.vasum.Error.Queue";
 ///@}
 
 } // namespace api
index ba4e9ee..20cffd9 100644 (file)
@@ -70,7 +70,9 @@ HostDbusConnection::HostDbusConnection(ZonesManager* zonesManagerPtr)
     mDbusConnection->registerObject(api::dbus::OBJECT_PATH,
                                     api::dbus::DEFINITION,
                                     std::bind(&HostDbusConnection::onMessageCall,
-                                              this, _1, _2, _3, _4, _5));
+                                              this, _1, _2, _3, _4, _5),
+                                    std::bind(&HostDbusConnection::onClientVanished,
+                                              this, _1));
 
     mSubscriptionId = mDbusConnection->signalSubscribe(std::bind(&HostDbusConnection::onSignalCall,
                                                                  this, _1, _2, _3, _4, _5),
@@ -168,6 +170,18 @@ void HostDbusConnection::onMessageCall(const std::string& objectPath,
         return;
     }
 
+    if (methodName == api::dbus::METHOD_LOCK_QUEUE) {
+        auto rb = std::make_shared<api::DbusMethodResultBuilder<api::Void>>(result);
+        mZonesManagerPtr->handleLockQueueCall(rb);
+        return;
+    }
+
+    if (methodName == api::dbus::METHOD_UNLOCK_QUEUE) {
+        auto rb = std::make_shared<api::DbusMethodResultBuilder<api::Void>>(result);
+        mZonesManagerPtr->handleUnlockQueueCall(rb);
+        return;
+    }
+
     if (methodName == api::dbus::METHOD_GET_ZONE_ID_LIST) {
         auto rb = std::make_shared<api::DbusMethodResultBuilder<api::ZoneIds>>(result);
         mZonesManagerPtr->handleGetZoneIdsCall(rb);
@@ -403,21 +417,29 @@ void HostDbusConnection::onMessageCall(const std::string& objectPath,
         mZonesManagerPtr->handleCreateFileCall(data, rb);
         return;
     }
+
+    if (methodName == api::dbus::METHOD_SWITCH_TO_DEFAULT) {
+        auto rb = std::make_shared<api::DbusMethodResultBuilder<api::Void>>(result);
+        mZonesManagerPtr->handleSwitchToDefaultCall(EMPTY_CALLER, rb);
+        return;
+    }
+}
+
+void HostDbusConnection::onClientVanished(const std::string& name)
+{
+    const std::string id = api::DBUS_CONNECTION_PREFIX + name;
+    mZonesManagerPtr->disconnectedCallback(id);
 }
 
 void HostDbusConnection::onSignalCall(const std::string& /* senderBusName */,
                                       const std::string& objectPath,
                                       const std::string& interface,
-                                      const std::string& signalName,
+                                      const std::string& /* signalName */,
                                       GVariant* /* parameters */)
 {
     if (objectPath != api::dbus::OBJECT_PATH || interface != api::dbus::INTERFACE) {
         return;
     }
-
-    if (signalName == api::dbus::SIGNAL_SWITCH_TO_DEFAULT) {
-        mZonesManagerPtr->handleSwitchToDefaultCall(EMPTY_CALLER);
-    }
 }
 
 void HostDbusConnection::proxyCallAsync(const std::string& busName,
index 23bb9d9..2b4d2a3 100644 (file)
@@ -97,6 +97,7 @@ private:
                        const std::string& methodName,
                        GVariant* parameters,
                        dbus::MethodResultBuilder::Pointer result);
+    void onClientVanished(const std::string& name);
     void onSignalCall(const std::string& senderBusName,
                       const std::string& objectPath,
                       const std::string& interface,
index 9b74ab2..caa333b 100644 (file)
@@ -63,11 +63,13 @@ const std::string METHOD_GRANT_DEVICE             = "GrantDevice";
 const std::string METHOD_REVOKE_DEVICE            = "RevokeDevice";
 const std::string METHOD_PROXY_CALL               = "ProxyCall";
 const std::string METHOD_CREATE_FILE              = "CreateFile";
+const std::string METHOD_LOCK_QUEUE               = "LockQueue";
+const std::string METHOD_UNLOCK_QUEUE             = "UnlockQueue";
+const std::string METHOD_SWITCH_TO_DEFAULT        = "SwitchToDefault";
 
 const std::string METHOD_NOTIFY_ACTIVE_ZONE         = "NotifyActiveZone";
 const std::string METHOD_FILE_MOVE_REQUEST          = "FileMoveRequest";
 const std::string SIGNAL_NOTIFICATION               = "Notification";
-const std::string SIGNAL_SWITCH_TO_DEFAULT          = "SwitchToDefault";
 
 const std::string FILE_MOVE_DESTINATION_NOT_FOUND   = "FILE_MOVE_DESTINATION_NOT_FOUND";
 const std::string FILE_MOVE_WRONG_DESTINATION       = "FILE_MOVE_WRONG_DESTINATION";
@@ -80,14 +82,9 @@ const std::string FILE_MOVE_SUCCEEDED               = "FILE_MOVE_SUCCEEDED";
 const std::string DEFINITION =
     "<node>"
     "  <interface name='" + INTERFACE + "'>"
-    "    <method name='" + METHOD_PROXY_CALL + "'>"
-    "      <arg type='s' name='target' direction='in'/>"
-    "      <arg type='s' name='busName' direction='in'/>"
-    "      <arg type='s' name='objectPath' direction='in'/>"
-    "      <arg type='s' name='interface' direction='in'/>"
-    "      <arg type='s' name='method' direction='in'/>"
-    "      <arg type='v' name='parameters' direction='in'/>"
-    "      <arg type='v' name='result' direction='out'/>"
+    "    <method name='" + METHOD_LOCK_QUEUE + "'>"
+    "    </method>"
+    "    <method name='" + METHOD_UNLOCK_QUEUE + "'>"
     "    </method>"
     "    <method name='" + METHOD_GET_ZONE_ID_LIST + "'>"
     "      <arg type='as' name='result' direction='out'/>"
@@ -227,13 +224,13 @@ const std::string DEFINITION =
     "      <arg type='v' name='parameters' direction='in'/>"
     "      <arg type='v' name='result' direction='out'/>"
     "    </method>"
+    "    <method name='" + METHOD_SWITCH_TO_DEFAULT + "'>"
+    "    </method>"
     "    <signal name='" + SIGNAL_NOTIFICATION + "'>"
     "      <arg type='s' name='zone'/>"
     "      <arg type='s' name='application'/>"
     "      <arg type='s' name='message'/>"
     "    </signal>"
-    "    <signal name='" + SIGNAL_SWITCH_TO_DEFAULT + "'>"
-    "    </signal>"
     "  </interface>"
     "</node>";
 
index c389919..f110999 100644 (file)
@@ -39,9 +39,22 @@ HostIPCConnection::HostIPCConnection(ZonesManager* zonesManagerPtr)
     : mZonesManagerPtr(zonesManagerPtr)
 {
     LOGT("Connecting to host IPC socket");
-    mService.reset(new ipc::Service(mDispatcher.getPoll(), HOST_IPC_SOCKET));
+
+    ipc::PeerCallback removedCallback = [this](const ipc::PeerID peerID,
+                                               const ipc::FileDescriptor) {
+        std::string id = api::IPC_CONNECTION_PREFIX + std::to_string(peerID);
+        mZonesManagerPtr->disconnectedCallback(id);
+    };
+    mService.reset(new ipc::Service(mDispatcher.getPoll(), HOST_IPC_SOCKET,
+                                    nullptr, removedCallback));
 
     using namespace std::placeholders;
+    setLockQueueCallback(std::bind(&ZonesManager::handleLockQueueCall,
+                                   mZonesManagerPtr, _1));
+
+    setUnlockQueueCallback(std::bind(&ZonesManager::handleUnlockQueueCall,
+                                     mZonesManagerPtr, _1));
+
     setGetZoneIdsCallback(std::bind(&ZonesManager::handleGetZoneIdsCall,
                                     mZonesManagerPtr, _1));
 
@@ -121,7 +134,7 @@ HostIPCConnection::HostIPCConnection(ZonesManager* zonesManagerPtr)
                                           mZonesManagerPtr, "", _1, _2));
 
     setSwitchToDefaultCallback(std::bind(&ZonesManager::handleSwitchToDefaultCall,
-                                         mZonesManagerPtr, ""));
+                                         mZonesManagerPtr, "", _1));
 
     setFileMoveCallback(std::bind(&ZonesManager::handleFileMoveCall,
                                   mZonesManagerPtr, "", _1, _2));
@@ -141,13 +154,28 @@ void HostIPCConnection::start()
     LOGD("Connected");
 }
 
+void HostIPCConnection::setLockQueueCallback(const Method<api::Void>::type& callback)
+{
+    typedef IPCMethodWrapper<api::Void> Callback;
+    mService->setMethodHandler<Callback::out, Callback::in>(
+        api::ipc::METHOD_LOCK_QUEUE,
+        Callback::getWrapper(callback));
+}
+
+void HostIPCConnection::setUnlockQueueCallback(const Method<api::Void>::type& callback)
+{
+    typedef IPCMethodWrapper<api::Void> Callback;
+    mService->setMethodHandler<Callback::out, Callback::in>(
+        api::ipc::METHOD_UNLOCK_QUEUE,
+        Callback::getWrapper(callback));
+}
+
 void HostIPCConnection::setGetZoneIdsCallback(const Method<api::ZoneIds>::type& callback)
 {
     typedef IPCMethodWrapper<api::ZoneIds> Callback;
     mService->setMethodHandler<Callback::out, Callback::in>(
         api::ipc::METHOD_GET_ZONE_ID_LIST,
         Callback::getWrapper(callback));
-
 }
 
 void HostIPCConnection::setGetActiveZoneIdCallback(const Method<api::ZoneId>::type& callback)
@@ -156,7 +184,6 @@ void HostIPCConnection::setGetActiveZoneIdCallback(const Method<api::ZoneId>::ty
     mService->setMethodHandler<Callback::out, Callback::in>(
         api::ipc::METHOD_GET_ACTIVE_ZONE_ID,
         Callback::getWrapper(callback));
-
 }
 
 void HostIPCConnection::setGetZoneInfoCallback(const Method<const api::ZoneId, api::ZoneInfoOut>::type& callback)
@@ -352,12 +379,12 @@ void HostIPCConnection::setNotifyActiveZoneCallback(
         Method::getWrapper(callback));
 }
 
-void HostIPCConnection::setSwitchToDefaultCallback(const Signal<const api::Void>::type& callback)
+void HostIPCConnection::setSwitchToDefaultCallback(const Method<api::Void>::type& callback)
 {
-    typedef IPCSignalWrapper<const api::Void> Signal;
-    mService->setSignalHandler<Signal::in>(
-        api::ipc::SIGNAL_SWITCH_TO_DEFAULT,
-        Signal::getWrapper(callback));
+    typedef IPCMethodWrapper<api::Void> Callback;
+    mService->setMethodHandler<Callback::out, Callback::in>(
+        api::ipc::METHOD_SWITCH_TO_DEFAULT,
+        Callback::getWrapper(callback));
 }
 
 void HostIPCConnection::setFileMoveCallback(const Method<const api::FileMoveRequestIn,
index 44fe356..28e3725 100644 (file)
@@ -56,6 +56,8 @@ public:
     void sendNotification(const api::Notification& notification);
 
 private:
+    void setLockQueueCallback(const Method<api::Void>::type& callback);
+    void setUnlockQueueCallback(const Method<api::Void>::type& callback);
     void setGetZoneIdsCallback(const Method<api::ZoneIds>::type& callback);
     void setGetZoneConnectionsCallback(const Method<api::Connections>::type& callback);
     void setGetActiveZoneIdCallback(const Method<api::ZoneId>::type& callback);
@@ -83,7 +85,7 @@ private:
     void setGrantDeviceCallback(const Method<const api::GrantDeviceIn>::type& callback);
     void setRevokeDeviceCallback(const Method<const api::RevokeDeviceIn>::type& callback);
     void setNotifyActiveZoneCallback(const Method<const vasum::api::NotifActiveZoneIn>::type& callback);
-    void setSwitchToDefaultCallback(const Signal<const api::Void>::type& callback);
+    void setSwitchToDefaultCallback(const Method<api::Void>::type& callback);
     void setFileMoveCallback(const Method<const api::FileMoveRequestIn,
                              api::FileMoveRequestStatus>::type& callback);
     void setCreateFileCallback(const Method<const api::CreateFileIn, api::CreateFileOut>::type& callback);
index d1251eb..74cf534 100644 (file)
@@ -57,11 +57,13 @@ const ::ipc::MethodID METHOD_UNLOCK_ZONE              = 24;
 const ::ipc::MethodID METHOD_GRANT_DEVICE             = 25;
 const ::ipc::MethodID METHOD_REVOKE_DEVICE            = 26;
 const ::ipc::MethodID METHOD_CREATE_FILE              = 27;
+const ::ipc::MethodID METHOD_LOCK_QUEUE               = 28;
+const ::ipc::MethodID METHOD_UNLOCK_QUEUE             = 29;
+const ::ipc::MethodID METHOD_SWITCH_TO_DEFAULT        = 30;
 
 const ::ipc::MethodID METHOD_NOTIFY_ACTIVE_ZONE         = 100;
 const ::ipc::MethodID METHOD_FILE_MOVE_REQUEST          = 101;
 const ::ipc::MethodID SIGNAL_NOTIFICATION               = 102;
-const ::ipc::MethodID SIGNAL_SWITCH_TO_DEFAULT          = 103;
 
 const std::string FILE_MOVE_DESTINATION_NOT_FOUND   = "FILE_MOVE_DESTINATION_NOT_FOUND";
 const std::string FILE_MOVE_WRONG_DESTINATION       = "FILE_MOVE_WRONG_DESTINATION";
index d28c9b4..a0a0205 100644 (file)
@@ -116,6 +116,7 @@ ZonesManager::ZonesManager(const std::string& configPath)
     : mWorker(utils::Worker::create())
     , mHostIPCConnection(this)
     , mDetachOnExit(false)
+    , mExclusiveIDLock(INVALID_CONNECTION_ID)
 #ifdef DBUS_CONNECTION
     , mHostDbusConnection(this)
 #endif
@@ -251,6 +252,25 @@ void ZonesManager::insertZone(const std::string& zoneId, const std::string& zone
     }
 }
 
+void ZonesManager::tryAddTask(const utils::Worker::Task& task, api::MethodResultBuilder::Pointer result, bool wait)
+{
+    {
+        Lock lock(mExclusiveIDMutex);
+
+        if (mExclusiveIDLock != INVALID_CONNECTION_ID &&
+            mExclusiveIDLock != result->getID()) {
+            result->setError(api::ERROR_QUEUE, "Queue is locked by another client");
+            return;
+        }
+    }
+
+    if (wait) {
+        mWorker->addTaskAndWait(task);
+    } else {
+        mWorker->addTask(task);
+    }
+}
+
 void ZonesManager::destroyZone(const std::string& zoneId)
 {
     Lock lock(mMutex);
@@ -465,7 +485,21 @@ void ZonesManager::setZonesDetachOnExit()
     }
 }
 
-void ZonesManager::handleSwitchToDefaultCall(const std::string& /*caller*/)
+void ZonesManager::disconnectedCallback(const std::string& id)
+{
+    LOGD("Client Disconnected: " << id);
+
+    {
+        Lock lock(mExclusiveIDMutex);
+
+        if (mExclusiveIDLock == id) {
+            mExclusiveIDLock = INVALID_CONNECTION_ID;
+        }
+    }
+}
+
+void ZonesManager::handleSwitchToDefaultCall(const std::string& /*caller*/,
+                                             api::MethodResultBuilder::Pointer result)
 {
     auto handler = [&, this] {
         // get config of currently set zone and switch if switchToDefaultAfterTimeout is true
@@ -482,9 +516,10 @@ void ZonesManager::handleSwitchToDefaultCall(const std::string& /*caller*/)
             LOGI("Switching to default zone " << mDynamicConfig.defaultId);
             focusInternal(defaultIter);
         }
+        result->setVoid();
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 #ifdef ZONE_CONNECTION
@@ -512,7 +547,7 @@ void ZonesManager::handleNotifyActiveZoneCall(const std::string& caller,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleFileMoveCall(const std::string& srcZoneId,
@@ -606,7 +641,7 @@ void ZonesManager::handleFileMoveCall(const std::string& srcZoneId,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 #else
 void ZonesManager::handleNotifyActiveZoneCall(const std::string& /* caller */,
@@ -652,7 +687,7 @@ void ZonesManager::handleCreateFileCall(const api::CreateFileIn& request,
         result->set(retValue);
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 #ifdef DBUS_CONNECTION
@@ -703,10 +738,53 @@ void ZonesManager::handleProxyCall(const std::string& caller,
                                            asyncResultCallback);
     };
 
+    // This call cannot be locked by lock/unlock queue
     mWorker->addTaskAndWait(handler);
 }
 #endif //DBUS_CONNECTION
 
+void ZonesManager::handleLockQueueCall(api::MethodResultBuilder::Pointer result)
+{
+    Lock lock(mExclusiveIDMutex);
+    std::string id = result->getID();
+
+    LOGI("Lock Queue: " << id);
+
+    if (mExclusiveIDLock == id) {
+        result->setError(api::ERROR_QUEUE, "Queue already locked");
+        return;
+    }
+
+    if (mExclusiveIDLock != INVALID_CONNECTION_ID) {
+        result->setError(api::ERROR_QUEUE, "Queue locked by another connection");
+        return;
+    }
+
+    mExclusiveIDLock = id;
+    result->setVoid();
+}
+
+void ZonesManager::handleUnlockQueueCall(api::MethodResultBuilder::Pointer result)
+{
+    Lock lock(mExclusiveIDMutex);
+    std::string id = result->getID();
+
+    LOGI("Unlock Queue: " << id);
+
+    if (mExclusiveIDLock == INVALID_CONNECTION_ID) {
+        result->setError(api::ERROR_QUEUE, "Queue not locked");
+        return;
+    }
+
+    if (mExclusiveIDLock != id) {
+        result->setError(api::ERROR_QUEUE, "Queue locked by another connection");
+        return;
+    }
+
+    mExclusiveIDLock = INVALID_CONNECTION_ID;
+    result->setVoid();
+}
+
 void ZonesManager::handleGetZoneIdsCall(api::MethodResultBuilder::Pointer result)
 {
     auto handler = [&, this] {
@@ -722,6 +800,7 @@ void ZonesManager::handleGetZoneIdsCall(api::MethodResultBuilder::Pointer result
         result->set(zoneIds);
     };
 
+    // This call cannot be locked by lock/unlock queue
     mWorker->addTaskAndWait(handler);
 }
 
@@ -735,6 +814,7 @@ void ZonesManager::handleGetActiveZoneIdCall(api::MethodResultBuilder::Pointer r
         result->set(zoneId);
     };
 
+    // This call cannot be locked by lock/unlock queue
     mWorker->addTaskAndWait(handler);
 }
 
@@ -774,6 +854,7 @@ void ZonesManager::handleGetZoneInfoCall(const api::ZoneId& zoneId,
         result->set(zoneInfo);
     };
 
+    // This call cannot be locked by lock/unlock queue
     mWorker->addTaskAndWait(handler);
 }
 
@@ -803,7 +884,7 @@ void ZonesManager::handleSetNetdevAttrsCall(const api::SetNetDevAttrsIn& data,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleGetNetdevAttrsCall(const api::GetNetDevAttrsIn& data,
@@ -830,7 +911,7 @@ void ZonesManager::handleGetNetdevAttrsCall(const api::GetNetDevAttrsIn& data,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleGetNetdevListCall(const api::ZoneId& zoneId,
@@ -853,7 +934,7 @@ void ZonesManager::handleGetNetdevListCall(const api::ZoneId& zoneId,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleCreateNetdevVethCall(const api::CreateNetDevVethIn& data,
@@ -876,7 +957,7 @@ void ZonesManager::handleCreateNetdevVethCall(const api::CreateNetDevVethIn& dat
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleCreateNetdevMacvlanCall(const api::CreateNetDevMacvlanIn& data,
@@ -898,7 +979,7 @@ void ZonesManager::handleCreateNetdevMacvlanCall(const api::CreateNetDevMacvlanI
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleCreateNetdevPhysCall(const api::CreateNetDevPhysIn& data,
@@ -921,7 +1002,7 @@ void ZonesManager::handleCreateNetdevPhysCall(const api::CreateNetDevPhysIn& dat
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleDestroyNetdevCall(const api::DestroyNetDevIn& data,
@@ -944,7 +1025,7 @@ void ZonesManager::handleDestroyNetdevCall(const api::DestroyNetDevIn& data,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleDeleteNetdevIpAddressCall(const api::DeleteNetdevIpAddressIn& data,
@@ -966,7 +1047,7 @@ void ZonesManager::handleDeleteNetdevIpAddressCall(const api::DeleteNetdevIpAddr
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleDeclareFileCall(const api::DeclareFileIn& data,
@@ -989,7 +1070,7 @@ void ZonesManager::handleDeclareFileCall(const api::DeclareFileIn& data,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleDeclareMountCall(const api::DeclareMountIn& data,
@@ -1012,7 +1093,7 @@ void ZonesManager::handleDeclareMountCall(const api::DeclareMountIn& data,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleDeclareLinkCall(const api::DeclareLinkIn& data,
@@ -1035,7 +1116,7 @@ void ZonesManager::handleDeclareLinkCall(const api::DeclareLinkIn& data,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleGetDeclarationsCall(const api::ZoneId& zoneId,
@@ -1058,7 +1139,7 @@ void ZonesManager::handleGetDeclarationsCall(const api::ZoneId& zoneId,
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleRemoveDeclarationCall(const api::RemoveDeclarationIn& data,
@@ -1080,7 +1161,7 @@ void ZonesManager::handleRemoveDeclarationCall(const api::RemoveDeclarationIn& d
         }
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleSetActiveZoneCall(const api::ZoneId& zoneId,
@@ -1109,7 +1190,7 @@ void ZonesManager::handleSetActiveZoneCall(const api::ZoneId& zoneId,
         result->setVoid();
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 
@@ -1255,7 +1336,7 @@ void ZonesManager::handleCreateZoneCall(const api::CreateZoneIn& data,
         }
     };
 
-    mWorker->addTaskAndWait(creator);
+    tryAddTask(creator, result, true);
 }
 
 void ZonesManager::handleDestroyZoneCall(const api::ZoneId& zoneId,
@@ -1276,7 +1357,7 @@ void ZonesManager::handleDestroyZoneCall(const api::ZoneId& zoneId,
         result->setVoid();
     };
 
-    mWorker->addTask(destroyer);
+    tryAddTask(destroyer, result, false);
 }
 
 void ZonesManager::handleShutdownZoneCall(const api::ZoneId& zoneId,
@@ -1305,7 +1386,7 @@ void ZonesManager::handleShutdownZoneCall(const api::ZoneId& zoneId,
         }
     };
 
-    mWorker->addTask(shutdown);
+    tryAddTask(shutdown, result, false);
 }
 
 void ZonesManager::handleStartZoneCall(const api::ZoneId& zoneId,
@@ -1332,7 +1413,7 @@ void ZonesManager::handleStartZoneCall(const api::ZoneId& zoneId,
             result->setError(api::ERROR_INTERNAL, "Failed to start zone");
         }
     };
-    mWorker->addTask(startAsync);
+    tryAddTask(startAsync, result, false);
 }
 
 void ZonesManager::handleLockZoneCall(const api::ZoneId& zoneId,
@@ -1371,7 +1452,7 @@ void ZonesManager::handleLockZoneCall(const api::ZoneId& zoneId,
         result->setVoid();
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleUnlockZoneCall(const api::ZoneId& zoneId,
@@ -1408,7 +1489,7 @@ void ZonesManager::handleUnlockZoneCall(const api::ZoneId& zoneId,
         result->setVoid();
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleGrantDeviceCall(const api::GrantDeviceIn& data,
@@ -1451,7 +1532,7 @@ void ZonesManager::handleGrantDeviceCall(const api::GrantDeviceIn& data,
         result->setVoid();
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 void ZonesManager::handleRevokeDeviceCall(const api::RevokeDeviceIn& data,
@@ -1492,7 +1573,7 @@ void ZonesManager::handleRevokeDeviceCall(const api::RevokeDeviceIn& data,
         result->setVoid();
     };
 
-    mWorker->addTaskAndWait(handler);
+    tryAddTask(handler, result, true);
 }
 
 } // namespace vasum
index 55e7023..e7b6675 100644 (file)
@@ -45,6 +45,8 @@
 
 namespace vasum {
 
+const std::string INVALID_CONNECTION_ID = "invalid://";
+
 class ZonesManager final {
 
 public:
@@ -115,7 +117,14 @@ public:
      */
     void setZonesDetachOnExit();
 
+    /**
+     * Callback on a client (ipc/dbus) disconnect
+     */
+    void disconnectedCallback(const std::string& id);
+
     // Handlers --------------------------------------------------------
+    void handleLockQueueCall(api::MethodResultBuilder::Pointer result);
+    void handleUnlockQueueCall(api::MethodResultBuilder::Pointer result);
     void handleGetZoneIdsCall(api::MethodResultBuilder::Pointer result);
     void handleGetActiveZoneIdCall(api::MethodResultBuilder::Pointer result);
     void handleGetZoneInfoCall(const api::ZoneId& data,
@@ -171,7 +180,8 @@ public:
     void handleNotifyActiveZoneCall(const std::string& caller,
                                     const api::NotifActiveZoneIn& notif,
                                     api::MethodResultBuilder::Pointer result);
-    void handleSwitchToDefaultCall(const std::string& caller);
+    void handleSwitchToDefaultCall(const std::string& caller,
+                                   api::MethodResultBuilder::Pointer result);
     void handleFileMoveCall(const std::string& srcZoneId,
                             const api::FileMoveRequestIn& request,
                             api::MethodResultBuilder::Pointer result);
@@ -193,6 +203,8 @@ private:
     Zones mZones;
     std::string mActiveZoneId;
     bool mDetachOnExit;
+    std::string mExclusiveIDLock;
+    Mutex mExclusiveIDMutex; // used to protect mExclusiveIDLock
 
     Zones::iterator findZone(const std::string& id);
     Zone& getZone(const std::string& id);
@@ -209,6 +221,7 @@ private:
     std::string getTemplatePathForExistingZone(const std::string& id);
     int getVTForNewZone();
     void insertZone(const std::string& zoneId, const std::string& templatePath);
+    void tryAddTask(const utils::Worker::Task& task, api::MethodResultBuilder::Pointer result, bool wait);
 
 #ifdef DBUS_CONNECTION
     HostDbusConnection mHostDbusConnection;
index a0fee4c..03a4046 100644 (file)
@@ -50,7 +50,8 @@ DbusTestServer::DbusTestServer()
     using namespace std::placeholders;
     mConnection->registerObject(TESTAPI_OBJECT_PATH,
                                 TESTAPI_DEFINITION,
-                                std::bind(&DbusTestServer::onMessageCall, this, _1, _2, _3, _4, _5));
+                                std::bind(&DbusTestServer::onMessageCall, this, _1, _2, _3, _4, _5),
+                                nullptr);
 }
 
 bool DbusTestServer::waitForName()
index 98154df..6cefb1c 100644 (file)
@@ -265,13 +265,13 @@ BOOST_AUTO_TEST_CASE(RegisterObject)
     ScopedGlibLoop loop;
     DbusConnection::Pointer conn = DbusConnection::create(DBUS_ADDRESS);
     DbusConnection::MethodCallCallback callback;
-    BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "<invalid", callback),
+    BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "<invalid", callback, nullptr),
                       DbusInvalidArgumentException);
-    BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "", callback),
+    BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "", callback, nullptr),
                       DbusInvalidArgumentException);
-    BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "<node></node>", callback),
+    BOOST_CHECK_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, "<node></node>", callback, nullptr),
                       DbusInvalidArgumentException);
-    BOOST_CHECK_NO_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, callback));
+    BOOST_CHECK_NO_THROW(conn->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, callback, nullptr));
 }
 
 BOOST_AUTO_TEST_CASE(IntrospectSystem)
@@ -298,7 +298,8 @@ BOOST_AUTO_TEST_CASE(Introspect)
     BOOST_REQUIRE(nameAcquired.wait(EVENT_TIMEOUT));
     conn1->registerObject(TESTAPI_OBJECT_PATH,
                           TESTAPI_DEFINITION,
-                          DbusConnection::MethodCallCallback());
+                          DbusConnection::MethodCallCallback(),
+                          nullptr);
     std::string xml = conn2->introspect(TESTAPI_BUS_NAME, TESTAPI_OBJECT_PATH);
     std::string iface = getInterfaceFromIntrospectionXML(xml, TESTAPI_INTERFACE);
     BOOST_REQUIRE(!iface.empty());
@@ -343,7 +344,7 @@ BOOST_AUTO_TEST_CASE(MethodCall)
             result->setError("org.tizen.vasum.Error.Test", "msg: " + std::to_string(arg));
         }
     };
-    conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler);
+    conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler, nullptr);
 
     GVariantPtr result1 = conn2->callMethod(TESTAPI_BUS_NAME,
                                             TESTAPI_OBJECT_PATH,
@@ -407,7 +408,7 @@ BOOST_AUTO_TEST_CASE(MethodAsyncCall)
             result->setError("org.tizen.vasum.Error.Test", "msg: " + std::to_string(arg));
         }
     };
-    conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler);
+    conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler, nullptr);
 
     auto asyncResult1 = [&](dbus::AsyncMethodCallResult& asyncMethodCallResult) {
         if (g_variant_is_of_type(asyncMethodCallResult.get(), G_VARIANT_TYPE_UNIT)) {
@@ -491,7 +492,7 @@ BOOST_AUTO_TEST_CASE(MethodAsyncCallAsyncHandler)
             handlerDone.set();
         }
     };
-    conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler);
+    conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler, nullptr);
 
     auto asyncResult = [&](dbus::AsyncMethodCallResult& asyncMethodCallResult) {
         const gchar* ret = NULL;
@@ -528,7 +529,8 @@ BOOST_AUTO_TEST_CASE(MethodCallException)
     BOOST_REQUIRE(nameAcquired.wait(EVENT_TIMEOUT));
     conn1->registerObject(TESTAPI_OBJECT_PATH,
                           TESTAPI_DEFINITION,
-                          DbusConnection::MethodCallCallback());
+                          DbusConnection::MethodCallCallback(),
+                          nullptr);
     BOOST_CHECK_THROW(conn2->callMethod(TESTAPI_BUS_NAME,
                                         TESTAPI_OBJECT_PATH,
                                         TESTAPI_INTERFACE,
index 375f212..125d857 100644 (file)
@@ -192,13 +192,14 @@ public:
         mClient->signalSubscribe(handler, api::dbus::BUS_NAME);
     }
 
-    void signalSwitchToDefault()
+    void callSwitchToDefault()
     {
-        // emit signal from dbus connection
-        mClient->emitSignal(api::dbus::OBJECT_PATH,
+        mClient->callMethod(api::dbus::BUS_NAME,
+                            api::dbus::OBJECT_PATH,
                             api::dbus::INTERFACE,
-                            api::dbus::SIGNAL_SWITCH_TO_DEFAULT,
-                            nullptr);
+                            api::dbus::METHOD_SWITCH_TO_DEFAULT,
+                            NULL,
+                            "()");
     }
 
     void callMethodNotify()
@@ -244,7 +245,7 @@ public:
                 }
             }
         };
-        mClient->registerObject(testapi::OBJECT_PATH, testapi::DEFINITION, handler);
+        mClient->registerObject(testapi::OBJECT_PATH, testapi::DEFINITION, handler, nullptr);
     }
 
     std::string testApiProxyCall(const std::string& target, const std::string& argument)
@@ -598,9 +599,11 @@ public:
                                                     callbackWrapper);
     }
 
-    void signalSwitchToDefault()
+    void callSwitchToDefault()
     {
-        mClient.signal<api::Void>(api::ipc::SIGNAL_SWITCH_TO_DEFAULT, std::make_shared<api::Void>());
+        mClient.callSync<api::Void, api::Void>(api::ipc::METHOD_SWITCH_TO_DEFAULT,
+                                               std::make_shared<api::Void>(),
+                                               EVENT_TIMEOUT*10); //Prevent from IPCTimeoutException see LockUnlockZone
     }
 
     void callMethodNotify()
@@ -912,7 +915,7 @@ MULTI_FIXTURE_TEST_CASE(SwitchToDefault, F, ACCESSORS)
 
     cm.focus("zone3");
 
-    host.signalSwitchToDefault();
+    host.callSwitchToDefault();
 
     // check if default zone has focus
     BOOST_CHECK(spinWaitFor(EVENT_TIMEOUT, isDefaultFocused));
@@ -936,7 +939,7 @@ MULTI_FIXTURE_TEST_CASE(AllowSwitchToDefault, F, ACCESSORS)
     // focus non-default zone with allowed switching
     cm.focus("zone3");
 
-    host.signalSwitchToDefault();
+    host.callSwitchToDefault();
 
     // check if default zone has focus
     BOOST_CHECK(spinWaitFor(EVENT_TIMEOUT, isDefaultFocused));
@@ -944,7 +947,7 @@ MULTI_FIXTURE_TEST_CASE(AllowSwitchToDefault, F, ACCESSORS)
     // focus non-default zone with disabled switching
     cm.focus("zone2");
 
-    host.signalSwitchToDefault();
+    host.callSwitchToDefault();
 
     // now default zone should not be focused
     // TODO uncomment this after adding an api to change 'switchToDefaultAfterTimeout'
index 94a84a8..3fb40ac 100644 (file)
@@ -72,7 +72,8 @@ DaemonConnection::DaemonConnection(const NameLostCallback& nameLostCallback,
     mDbusConnection->registerObject(zone_daemon::api::OBJECT_PATH,
                                     zone_daemon::api::DEFINITION,
                                     std::bind(&DaemonConnection::onMessageCall,
-                                              this, _1, _2, _3, _4, _5));
+                                              this, _1, _2, _3, _4, _5),
+                                    nullptr);
     LOGD("Connected");
 }