Added timeout to poll function in dbus mainloop
[profile/ivi/persistence-client-library.git] / src / persistence_client_library_dbus_service.c
index dc10017..baa1906 100644 (file)
@@ -4,23 +4,9 @@
  * Company         XS Embedded GmbH
  *****************************************************************************/
 /******************************************************************************
-   Permission is hereby granted, free of charge, to any person obtaining
-   a copy of this software and associated documentation files (the "Software"),
-   to deal in the Software without restriction, including without limitation
-   the rights to use, copy, modify, merge, publish, distribute, sublicense,
-   and/or sell copies of the Software, and to permit persons to whom the
-   Software is furnished to do so, subject to the following conditions:
-
-   The above copyright notice and this permission notice shall be included
-   in all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-   DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-   OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed
+ * with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 ******************************************************************************/
  /**
  * @file           persistence_client_library_dbus_service.c
  * @see
  */
 
-//#include "persistence_client_service_dbus_service.h"
 
 #include "persistence_client_library_dbus_service.h"
 #include "persistence_client_library_lc_interface.h"
 #include "persistence_client_library_pas_interface.h"
+#include "persistence_client_library_dbus_cmd.h"
+#include "persistence_client_library_data_organization.h"
+
 
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <pthread.h>
 
 
-/// polling structure
-typedef struct SPollInfo
-{
-   int nfds;
-   struct pollfd fds[10];
-   DBusWatch * watches[10];
-} tPollInfo;
+pthread_cond_t  gDbusInitializedCond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t gDbusInitializedMtx  = PTHREAD_MUTEX_INITIALIZER;
 
+pthread_mutex_t gDbusPendingRegMtx   = PTHREAD_MUTEX_INITIALIZER;
 
-/// polling information
-static tPollInfo gPollInfo;
 
+pthread_mutex_t gDeliverpMtx         = PTHREAD_MUTEX_INITIALIZER;
+
+pthread_mutex_t gMainCondMtx         = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t  gMainLoopCond        = PTHREAD_COND_INITIALIZER;
+
+pthread_t gMainLoopThread;
 
-/// dbus connection
-DBusConnection* gDbusConn = NULL;
 
+int gEfds;  // communication channel int dbus mainloop
 
-DBusConnection* get_dbus_connection()
+
+typedef enum EDBusObjectType
 {
-   return gDbusConn;
-}
+   OT_NONE = 0,
+   OT_WATCH,
+   OT_TIMEOUT
+} tDBusObjectType;
 
-//------------------------------------------------------------------------
-// debugging only until "correct" exit of main loop is possible!!!!!
-//------------------------------------------------------------------------
-#include "signal.h"
-static int endLoop = 0;
 
-void sigHandler(int signo)
+typedef struct SObjectEntry
 {
-   endLoop = 1;
-}
-//------------------------------------------------------------------------
+   tDBusObjectType objtype; /** libdbus' object */
+   union
+   {
+      DBusWatch * watch;      /** watch "object" */
+      DBusTimeout * timeout;  /** timeout "object" */
+   };
+} tObjectEntry;
 
-//const char* gPersDbusAdminInterface    =  "org.genivi.persistence.admin";
-//const char* gPersDbusAdminPath         = "/org/genivi/persistence/admin";
 
 
+/// polling structure
+typedef struct SPollInfo
+{
+   int nfds;
+   struct pollfd fds[10];
+   tObjectEntry objects[10];
+} tPollInfo;
+
+
+/// polling information
+static tPollInfo gPollInfo;
+
+int bContinue = 0;
 
 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
 
@@ -89,21 +88,154 @@ void sigHandler(int signo)
 /* function to unregister ojbect path message handler */
 static void unregisterMessageHandler(DBusConnection *connection, void *user_data)
 {
-   printf("unregisterObjectPath\n");
+   (void)connection;
+   (void)user_data;
+   DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("unregisterObjectPath\n"));
 }
 
 /* catches messages not directed to any registered object path ("garbage collector") */
 static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connection, DBusMessage * message, void * user_data)
 {
-   printf("handleObjectPathMessageFallback '%s' -> '%s'\n", dbus_message_get_interface(message), dbus_message_get_member(message) );
-   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+   DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
+   (void)user_data;
+
+   // org.genivi.persistence.admin  S I G N A L
+   if((0==strcmp("org.genivi.persistence.admin", dbus_message_get_interface(message))))
+   {
+      if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
+      {
+         if((0==strcmp("PersistenceModeChanged", dbus_message_get_member(message))))
+         {
+            // to do handle signal
+            result = signal_persModeChange(connection, message);
+         }
+         else
+         {
+            DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback -> unknown signal:"), DLT_STRING(dbus_message_get_interface(message)) );
+         }
+      }
+   }
+   // org.genivi.persistence.admin  S I G N A L
+   else if((0==strcmp("org.genivi.persistence.adminconsumer", dbus_message_get_interface(message))))
+   {
+      if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
+      {
+         pclNotification_s notifyStruct;
+         int validMessage = 0;
+
+         if((0==strcmp("PersistenceResChange", dbus_message_get_member(message))))
+         {
+            notifyStruct.pclKeyNotify_Status = pclNotifyStatus_changed;
+            validMessage = 1;
+         }
+         else if((0==strcmp("PersistenceResDelete", dbus_message_get_member(message))))
+         {
+            notifyStruct.pclKeyNotify_Status = pclNotifyStatus_deleted;
+            validMessage = 1;
+         }
+         else if((0==strcmp("PersistenceRes", dbus_message_get_member(message))))
+         {
+            notifyStruct.pclKeyNotify_Status = pclNotifyStatus_created;
+            validMessage = 1;
+         }
+
+         if(validMessage == 1)
+         {
+            DBusError error;
+            DBusMessage *reply;
+            dbus_error_init (&error);
+            char* ldbid;
+            char* user_no;
+            char* seat_no;
+
+            if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &notifyStruct.resource_id,
+                                                         DBUS_TYPE_STRING, &ldbid,
+                                                         DBUS_TYPE_STRING, &user_no,
+                                                         DBUS_TYPE_STRING, &seat_no,
+                                                         DBUS_TYPE_INVALID))
+            {
+               reply = dbus_message_new_error(message, error.name, error.message);
+
+               if (reply == 0)
+               {
+                  DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback => DBus No memory"), DLT_STRING(dbus_message_get_interface(message)) );
+               }
+
+               if (!dbus_connection_send(connection, reply, 0))
+               {
+                  DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback => DBus No memory"), DLT_STRING(dbus_message_get_interface(message)) );
+               }
+
+               result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;;
+               dbus_message_unref(reply);
+            }
+            else
+            {
+               notifyStruct.ldbid       = atoi(ldbid);
+               notifyStruct.user_no     = atoi(user_no);
+               notifyStruct.seat_no     = atoi(seat_no);
+
+               // call the registered callback function
+               if(gChangeNotifyCallback != NULL )
+               {
+                  gChangeNotifyCallback(&notifyStruct);
+               }
+               else
+               {
+                  DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback => gChangeNotifyCallback is not set (possibly NULL)") );
+               }
+               result = DBUS_HANDLER_RESULT_HANDLED;
+            }
+            dbus_connection_flush(connection);
+         }
+      }
+   }
+   // org.genivi.persistence.admin  P R O P E R T Y
+   else  if((0==strcmp("org.freedesktop.DBus.Properties", dbus_message_get_interface(message))))
+   {
+      if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
+      {
+         if((0==strcmp("EggDBusChanged", dbus_message_get_member(message))))
+         {
+            DBusMessageIter array;
+            DBusMessageIter dict;
+            DBusMessageIter variant;
+
+            char* dictString = NULL;
+            int value = 0;
+
+            dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
+            dbus_message_iter_get_basic(&dict, &dictString);
+
+            dbus_message_iter_open_container(&dict,DBUS_TYPE_VARIANT, NULL, &variant);
+            dbus_message_iter_get_basic(&dict, &value);
+
+            dbus_message_iter_close_container(&dict, &variant);
+            dbus_message_iter_close_container(&array, &dict);
+
+            // to do handle signal
+            result = DBUS_HANDLER_RESULT_HANDLED;
+         }
+         else
+         {
+            DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback -> unknown property:"), DLT_STRING(dbus_message_get_interface(message)) );
+         }
+      }
+      else
+      {
+         DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback -> not a signal:"), DLT_STRING(dbus_message_get_member(message)) );
+      }
+   }
+   return result;
 }
 
 
 
 static void  unregisterObjectPathFallback(DBusConnection *connection, void *user_data)
 {
-   printf("unregisterObjectPathFallback\n");
+   (void)connection;
+   (void)user_data;
+   DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("unregisterObjectPathFallback\n"));
 }
 
 
@@ -112,72 +244,82 @@ void* run_mainloop(void* dataPtr)
 {
    // persistence admin message
    static const struct DBusObjectPathVTable vtablePersAdmin
-      = {unregisterMessageHandler, checkPersAdminMsg, NULL, };
+      = {unregisterMessageHandler, checkPersAdminMsg, NULL, NULL, NULL, NULL};
 
    // lifecycle message
    static const struct DBusObjectPathVTable vtableLifecycle
-      = {unregisterMessageHandler, checkLifecycleMsg, NULL, };
+      = {unregisterMessageHandler, checkLifecycleMsg, NULL, NULL, NULL, NULL};
 
    // fallback
    static const struct DBusObjectPathVTable vtableFallback
-      = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, };
+      = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, NULL, NULL, NULL};
 
    // setup the dbus
    mainLoop(vtablePersAdmin, vtableLifecycle, vtableFallback, dataPtr);
 
-   printf("Exit dbus main loop!!!!\n");
-
    return NULL;
 }
 
 
 
-int setup_dbus_mainloop()
+int setup_dbus_mainloop(void)
 {
    int rval = 0;
-   pthread_t thread;
    DBusError err;
+   DBusConnection* conn = NULL;
+
    const char *pAddress = getenv("PERS_CLIENT_DBUS_ADDRESS");
+
    dbus_error_init(&err);
 
+   // wait until dbus main loop has been setup and running
+   pthread_mutex_lock(&gDbusInitializedMtx);
+
    // Connect to the bus and check for errors
    if(pAddress != NULL)
    {
-      printf("Use specific dbus address: %s\n !", pAddress);
-      gDbusConn = dbus_connection_open(pAddress, &err);
+      DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("setup_dbus_mainloop -> Use specific dbus address:"), DLT_STRING(pAddress) );
 
-      if(gDbusConn != NULL)
+      conn = dbus_connection_open_private(pAddress, &err);
+
+      if(conn != NULL)
       {
-         if(!dbus_bus_register(gDbusConn, &err))
+         if(!dbus_bus_register(conn, &err))
          {
-            printf("dbus_bus_register() Error %s\n", err.message);
+            DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("dbus_bus_register() Error :"), DLT_STRING(err.message) );
             dbus_error_free (&err);
+            pthread_mutex_unlock(&gDbusInitializedMtx);
             return -1;
          }
-         else
-         {
-            printf("Registered connection successfully !\n");
-         }
       }
       else
       {
-         printf("dbus_connection_open() Error %s\n",err.message);
+         DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("dbus_connection_open_private() Error :"), DLT_STRING(err.message) );
          dbus_error_free(&err);
+         pthread_mutex_unlock(&gDbusInitializedMtx);
+         return -1;
       }
    }
    else
    {
-      printf("Use default dbus bus!!!!!!\n");
-      gDbusConn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+      DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Use default dbus bus (DBUS_BUS_SYSTEM)"));
+
+      conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
    }
 
    // create here the dbus connection and pass to main loop
-   rval = pthread_create(&thread, NULL, run_mainloop, gDbusConn);
-
-   if (rval)
+   rval = pthread_create(&gMainLoopThread, NULL, run_mainloop, conn);
+   if(rval)
    {
-     fprintf(stderr, "Server: - ERROR! pthread_create( run_mainloop ) returned: %d\n", rval);
+     DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pthread_create( DBUS run_mainloop ) returned an error:"), DLT_INT(rval) );
+     pthread_mutex_unlock(&gDbusInitializedMtx);
+     return -1;
    }
+
+   // wait for condition variable
+   pthread_cond_wait(&gDbusInitializedCond, &gDbusInitializedMtx);
+
+   pthread_mutex_unlock(&gDbusInitializedMtx);
    return rval;
 }
 
@@ -188,14 +330,15 @@ int setup_dbus_mainloop()
 static dbus_bool_t addWatch(DBusWatch *watch, void *data)
 {
    dbus_bool_t result = FALSE;
-
-   //printf("addWatch called @%08x flags: %08x enabled: %c\n", (unsigned int)watch, dbus_watch_get_flags(watch), TRUE==dbus_watch_get_enabled(watch)?'x':'-');
+   (void)data;
 
    if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
    {
       int flags = dbus_watch_get_flags(watch);
 
-      gPollInfo.watches[gPollInfo.nfds] = watch;
+      tObjectEntry * const pEntry = &gPollInfo.objects[gPollInfo.nfds];
+      pEntry->objtype = OT_WATCH;
+      pEntry->watch = watch;
 
       gPollInfo.fds[gPollInfo.nfds].fd = dbus_watch_get_unix_fd(watch);
 
@@ -211,12 +354,6 @@ static dbus_bool_t addWatch(DBusWatch *watch, void *data)
          }
 
          ++gPollInfo.nfds;
-
-         static const int cmd = CMD_REQUEST_NAME;
-         if (sizeof(int)!=write(gPipefds[1], &cmd, sizeof(int)))
-         {
-            printf("write failed w/ errno %d\n", errno);
-         }
       }
 
       result = TRUE;
@@ -229,14 +366,124 @@ static dbus_bool_t addWatch(DBusWatch *watch, void *data)
 
 static void removeWatch(DBusWatch *watch, void *data)
 {
-   printf("removeWatch called @0x%08x\n", (int)watch);
+   void* w_data = dbus_watch_get_data(watch);
+
+   (void)data;
+
+   DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("removeWatch called "), DLT_INT( (int)watch) );
+
+   if(w_data)
+      free(w_data);
+
+   dbus_watch_set_data(watch, NULL, NULL);
 }
 
 
 
 static void watchToggled(DBusWatch *watch, void *data)
 {
-   printf("watchToggled called @0x%08x\n", (int)watch);
+   (void)data;
+   DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("watchToggled called "), DLT_INT( (int)watch) );
+
+   if(dbus_watch_get_enabled(watch))
+      addWatch(watch, data);
+   else
+      removeWatch(watch, data);
+}
+
+
+
+static dbus_bool_t addTimeout(DBusTimeout *timeout, void *data)
+{
+   (void)data;
+   dbus_bool_t ret = FALSE;
+
+   if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
+   {
+      const int interval = dbus_timeout_get_interval(timeout);
+      if ((0<interval)&&(TRUE==dbus_timeout_get_enabled(timeout)))
+      {
+         const int tfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+         if (-1!=tfd)
+         {
+            const struct itimerspec its = { .it_value= {interval/1000, interval%1000} };
+            if (-1!=timerfd_settime(tfd, 0, &its, NULL))
+            {
+               tObjectEntry * const pEntry = &gPollInfo.objects[gPollInfo.nfds];
+               pEntry->objtype = OT_TIMEOUT;
+               pEntry->timeout = timeout;
+               gPollInfo.fds[gPollInfo.nfds].fd = tfd;
+               gPollInfo.fds[gPollInfo.nfds].events |= POLLIN;
+               ++gPollInfo.nfds;
+               ret = TRUE;
+            }
+            else
+            {
+               DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("addTimeout => timerfd_settime() failed"), DLT_STRING(strerror(errno)) );
+            }
+         }
+         else
+         {
+            DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("addTimeout => timerfd_create() failed"), DLT_STRING(strerror(errno)) );
+         }
+      }
+   }
+   else
+   {
+      DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("addTimeout => cannot create another fd to be poll()'ed"));
+   }
+
+   return ret;
+}
+
+
+
+static void removeTimeout(DBusTimeout *timeout, void *data)
+{
+   int i = gPollInfo.nfds;
+   (void)data;
+
+   while ((0<i--)&&(timeout!=gPollInfo.objects[i].timeout));
+
+   if (0<i)
+   {
+      if (-1==close(gPollInfo.fds[i].fd))
+      {
+         DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("removeTimeout => close() timerfd"), DLT_STRING(strerror(errno)) );
+      }
+
+      --gPollInfo.nfds;
+      while (gPollInfo.nfds>i)
+      {
+         gPollInfo.fds[i] = gPollInfo.fds[i+1];
+         gPollInfo.objects[i] = gPollInfo.objects[i+1];
+         ++i;
+      }
+
+      gPollInfo.fds[gPollInfo.nfds].fd = -1;
+      gPollInfo.objects[gPollInfo.nfds].objtype = OT_NONE;
+   }
+}
+
+
+
+/** callback for libdbus' when timeout changed */
+static void timeoutToggled(DBusTimeout *timeout, void *data)
+{
+   int i = gPollInfo.nfds;
+   (void)data;
+
+   while ((0<i--)&&(timeout!=gPollInfo.objects[i].timeout));
+   DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("timeoutToggled") );
+   if (0<i)
+   {
+      const int interval = (TRUE==dbus_timeout_get_enabled(timeout))?dbus_timeout_get_interval(timeout):0;
+      const struct itimerspec its = { .it_value= {interval/1000, interval%1000} };
+      if (-1!=timerfd_settime(gPollInfo.fds[i].fd, 0, &its, NULL))
+      {
+         DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("timeoutToggled => timerfd_settime()"), DLT_STRING(strerror(errno)) );
+      }
+   }
 }
 
 
@@ -245,120 +492,149 @@ int mainLoop(DBusObjectPathVTable vtable, DBusObjectPathVTable vtable2,
              DBusObjectPathVTable vtableFallback, void* userData)
 {
    DBusError err;
-
-   signal(SIGTERM, sigHandler);
-   signal(SIGQUIT, sigHandler);
-   signal(SIGINT,  sigHandler);
+   // lock mutex to make sure dbus main loop is running
+   pthread_mutex_lock(&gDbusInitializedMtx);
 
    DBusConnection* conn = (DBusConnection*)userData;
-
    dbus_error_init(&err);
 
    if (dbus_error_is_set(&err))
    {
-      printf("Connection Error (%s)\n", err.message);
+      DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => Connection Error:"), DLT_STRING(err.message) );
       dbus_error_free(&err);
    }
    else if (NULL != conn)
    {
-      dbus_connection_set_exit_on_disconnect (conn, FALSE);
-
-      printf("connected as '%s'\n", dbus_bus_get_unique_name(conn));
-
-      if (0!=pipe(gPipefds))
+      dbus_connection_set_exit_on_disconnect(conn, FALSE);
+      if (-1 == (gEfds = eventfd(0, 0)))
       {
-         printf("pipe() failed w/ errno %d\n", errno);
+         DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => eventfd() failed w/ errno:"), DLT_INT(errno) );
       }
       else
       {
          int ret;
-         int bContinue = 0;
          memset(&gPollInfo, 0 , sizeof(gPollInfo));
 
          gPollInfo.nfds = 1;
-         gPollInfo.fds[0].fd = gPipefds[0];
+         gPollInfo.fds[0].fd = gEfds;
          gPollInfo.fds[0].events = POLLIN;
 
-         if (   (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/persistence/adminconsumer", &vtable, userData))
-             && (TRUE==dbus_connection_register_object_path(conn, "/com/contiautomotive/NodeStateManager/LifecycleConsumer", &vtable2, userData))
+         dbus_bus_add_match(conn, "type='signal',interface='org.genivi.persistence.admin',member='PersistenceModeChanged',path='/org/genivi/persistence/admin'", &err);
+
+         // register for messages
+         if (   (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/NodeStateManager/LifeCycleConsumer", &vtable2, userData))
+#if USE_PASINTERFACE == 1
+             && (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/persistence/adminconsumer", &vtable, userData))
+#endif
              && (TRUE==dbus_connection_register_fallback(conn, "/", &vtableFallback, userData)) )
          {
-            if (TRUE!=dbus_connection_set_watch_functions(conn, addWatch, removeWatch, watchToggled, NULL, NULL))
+            if(   (TRUE!=dbus_connection_set_watch_functions(conn, addWatch, removeWatch, watchToggled, NULL, NULL))
+               || (TRUE!=dbus_connection_set_timeout_functions(conn, addTimeout, removeTimeout, timeoutToggled, NULL, NULL)) )
             {
-               printf("dbus_connection_set_watch_functions() failed\n");
+               DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => dbus_connection_set_watch_functions() failed"));
             }
             else
             {
-               char buf[64];
-
+               pthread_cond_signal(&gDbusInitializedCond);
+               pthread_mutex_unlock(&gDbusInitializedMtx);
                do
                {
                   bContinue = 0; /* assume error */
 
                   while (DBUS_DISPATCH_DATA_REMAINS==dbus_connection_dispatch(conn));
 
-                  while ((-1==(ret=poll(gPollInfo.fds, gPollInfo.nfds, 500)))&&(EINTR==errno));
+                  while ((-1==(ret=poll(gPollInfo.fds, gPollInfo.nfds, 750)))&&(EINTR==errno));
 
-                  if(0>ret)
+                  if (0>ret)
                   {
-                     printf("poll() failed w/ errno %d\n", errno);
+                     DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => poll() failed w/ errno "), DLT_INT(errno) );
+                  }
+                  else if (0==ret)
+                  {
+                     /* poll time-out */
                   }
                   else
                   {
                      int i;
-                     bContinue = 1;
 
                      for (i=0; gPollInfo.nfds>i; ++i)
                      {
+                        /* anything to do */
                         if (0!=gPollInfo.fds[i].revents)
                         {
-                           if (gPollInfo.fds[i].fd==gPipefds[0])
+                           if (OT_TIMEOUT==gPollInfo.objects[i].objtype)
+                           {
+                              /* time-out occured */
+                              unsigned long long nExpCount = 0;
+                              if ((ssize_t)sizeof(nExpCount)!=read(gPollInfo.fds[i].fd, &nExpCount, sizeof(nExpCount)))
+                              {
+                                 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => read failed"));
+                              }
+                              DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => timeout"));
+
+                              if (FALSE==dbus_timeout_handle(gPollInfo.objects[i].timeout))
+                              {
+                                 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => dbus_timeout_handle() failed!?"));
+                              }
+                              bContinue = TRUE;
+                           }
+                           else if (gPollInfo.fds[i].fd == gEfds)
                            {
+                              /* internal command */
                               if (0!=(gPollInfo.fds[i].revents & POLLIN))
                               {
+                                 uint16_t buf[64];
                                  bContinue = TRUE;
-                                 while ((-1==(ret=read(gPollInfo.fds[i].fd, buf, 64)))&&(EINTR==errno));
-                                 if (0>ret)
+                                 while ((-1==(ret = read(gPollInfo.fds[i].fd, buf, 64)))&&(EINTR == errno));
+                                 if(ret < 0)
                                  {
-                                    printf("read() failed w/ errno %d\n", errno);
+                                    DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => read() failed"), DLT_STRING(strerror(errno)) );
                                  }
-                                 else if (sizeof(int)==ret)
+                                 else
                                  {
+                                    pthread_mutex_lock(&gMainCondMtx);
                                     switch (buf[0])
                                     {
-                                       case CMD_REQUEST_NAME:
-                                          if(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
-                                             != dbus_bus_request_name(conn, "org.genivi.persistence.adminconsumer", DBUS_NAME_FLAG_DO_NOT_QUEUE, &err))
-                                          {
-                                             printf("*** Cannot acquire name '%s' (%s). Bailing out!\n", "org.genivi.persistence.admin\n", err.message);
-                                             dbus_error_free(&err);
-                                             bContinue = FALSE;
-                                          }
-                                          if(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
-                                             != dbus_bus_request_name(conn, "com.contiautomotive.NodeStateManager.LifecycleConsumer", DBUS_NAME_FLAG_DO_NOT_QUEUE, &err))
-                                          {
-                                             printf("*** Cannot acquire name '%s' (%s). Bailing out!\n", "com.contiautomotive.NodeStateManager.LifecycleConsumer\n", err.message);
-                                             dbus_error_free(&err);
-                                             bContinue = FALSE;
-                                          }
-                                          break;
                                        case CMD_PAS_BLOCK_AND_WRITE_BACK:
-                                          process_block_and_write_data_back();
+                                          process_block_and_write_data_back((buf[2]), buf[1]);
+                                          process_send_pas_request(conn, (buf[2]), buf[1]);
                                           break;
                                        case CMD_LC_PREPARE_SHUTDOWN:
-                                          process_prepare_shutdown(buf[1]);
+                                          process_prepare_shutdown(Shutdown_Full);
+                                          process_send_lifecycle_request(conn, (buf[2]), buf[1]);
+                                          break;
+                                       case CMD_SEND_NOTIFY_SIGNAL:
+                                          process_send_notification_signal(conn);
+                                          break;
+                                       case CMD_REG_NOTIFY_SIGNAL:
+                                          process_reg_notification_signal(conn);
+                                          break;
+                                       case CMD_SEND_PAS_REGISTER:
+                                          process_send_pas_register(conn, (buf[1]), buf[2]);
+                                          break;
+                                       case CMD_SEND_LC_REGISTER:
+                                          process_send_lifecycle_register(conn, (buf[1]), buf[2]);
                                           break;
                                        case CMD_QUIT:
-                                          bContinue = FALSE;
+                                          bContinue = 0;
                                           break;
+
+                                       // ******************************************************
+                                       /*
+                                       case CMD_SEND_LC_REQUEST:  // remove
+                                         process_send_lifecycle_request(conn, (buf[2]), buf[1]);
+                                         break;
+                                      case CMD_SEND_PAS_REQUEST: /// remove
+                                         process_send_pas_request(conn, (buf[2]), buf[1]);
+                                         break;
+                                       */
+                                       // ******************************************************
                                        default:
-                                          printf("command %d not handled!\n", buf[0]);
+                                          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => command not handled"), DLT_INT(buf[0]) );
                                           break;
                                     }
-                                 }
-                                 else
-                                 {
-                                    printf("read() returned %d (%s)\n", ret, buf);
+                                    pthread_cond_signal(&gMainLoopCond);
+                                    pthread_mutex_unlock(&gMainCondMtx);
                                  }
                               }
                            }
@@ -381,27 +657,68 @@ int mainLoop(DBusObjectPathVTable vtable, DBusObjectPathVTable vtable2,
                               {
                                  flags |= DBUS_WATCH_HANGUP;
                               }
-                              //printf("handle watch @0x%08x flags: %04x\n", (int)gPollInfo.watches[i], flags);
-                              bContinue = dbus_watch_handle(gPollInfo.watches[i], flags);
+
+                              bContinue = dbus_watch_handle(gPollInfo.objects[i].watch, flags);
                            }
                         }
                      }
                   }
-                  if(endLoop == 1)
-                     break;
                }
                while (0!=bContinue);
             }
+#if USE_PASINTERFACE == 1
             dbus_connection_unregister_object_path(conn, "/org/genivi/persistence/adminconsumer");
-            //dbus_connection_unregister_object_path(conn, "/com/");
+#endif
+            dbus_connection_unregister_object_path(conn, "/org/genivi/NodeStateManager/LifeCycleConsumer");
             dbus_connection_unregister_object_path(conn, "/");
          }
-         close(gPipefds[1]);
-         close(gPipefds[0]);
+         close(gEfds);
       }
+      dbus_connection_close(conn);
       dbus_connection_unref(conn);
       dbus_shutdown();
    }
+
+   pthread_cond_signal(&gDbusInitializedCond);
+   pthread_mutex_unlock(&gDbusInitializedMtx);
    return 0;
 }
 
+
+
+int deliverToMainloop(tCmd mainloopCmd, unsigned int param1, unsigned int param2)
+{
+   int rval = 0;
+
+   pthread_mutex_lock(&gDeliverpMtx);
+
+
+   pthread_mutex_lock(&gMainCondMtx);
+
+   deliverToMainloop_NM(mainloopCmd, param1, param2);
+
+   pthread_cond_wait(&gMainLoopCond, &gMainCondMtx);
+   pthread_mutex_unlock(&gMainCondMtx);
+
+
+   pthread_mutex_unlock(&gDeliverpMtx);
+
+   return rval;
+}
+
+int deliverToMainloop_NM(tCmd mainloopCmd, unsigned int param1, unsigned int param2)
+{
+   int rval = 0;
+   uint64_t cmd;
+
+   cmd = ( ((uint64_t)param2 << 32) | ((uint64_t)param1 << 16) | mainloopCmd);
+
+   if(-1 == write(gEfds, &cmd, (sizeof(uint64_t))))
+   {
+     DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("deliverToMainloop => failed to write to pipe"), DLT_INT(errno));
+     rval = -1;
+   }
+
+   return rval;
+}
+