Added timeout to poll function in dbus mainloop
[profile/ivi/persistence-client-library.git] / src / persistence_client_library_dbus_service.c
1 /******************************************************************************
2  * Project         Persistency
3  * (c) copyright   2012
4  * Company         XS Embedded GmbH
5  *****************************************************************************/
6 /******************************************************************************
7  * This Source Code Form is subject to the terms of the
8  * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed
9  * with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 ******************************************************************************/
11  /**
12  * @file           persistence_client_library_dbus_service.c
13  * @ingroup        Persistence client library
14  * @author         Ingo Huerner
15  * @brief          Implementation of the persistence client library dbus service.
16  * @see
17  */
18
19
20 #include "persistence_client_library_dbus_service.h"
21 #include "persistence_client_library_lc_interface.h"
22 #include "persistence_client_library_pas_interface.h"
23 #include "persistence_client_library_dbus_cmd.h"
24 #include "persistence_client_library_data_organization.h"
25
26
27 #include <stdio.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32
33
34 pthread_cond_t  gDbusInitializedCond = PTHREAD_COND_INITIALIZER;
35 pthread_mutex_t gDbusInitializedMtx  = PTHREAD_MUTEX_INITIALIZER;
36
37 pthread_mutex_t gDbusPendingRegMtx   = PTHREAD_MUTEX_INITIALIZER;
38
39
40 pthread_mutex_t gDeliverpMtx         = PTHREAD_MUTEX_INITIALIZER;
41
42 pthread_mutex_t gMainCondMtx         = PTHREAD_MUTEX_INITIALIZER;
43 pthread_cond_t  gMainLoopCond        = PTHREAD_COND_INITIALIZER;
44
45 pthread_t gMainLoopThread;
46
47
48 int gEfds;  // communication channel int dbus mainloop
49
50
51 typedef enum EDBusObjectType
52 {
53    OT_NONE = 0,
54    OT_WATCH,
55    OT_TIMEOUT
56 } tDBusObjectType;
57
58
59 typedef struct SObjectEntry
60 {
61    tDBusObjectType objtype; /** libdbus' object */
62    union
63    {
64       DBusWatch * watch;      /** watch "object" */
65       DBusTimeout * timeout;  /** timeout "object" */
66    };
67 } tObjectEntry;
68
69
70
71 /// polling structure
72 typedef struct SPollInfo
73 {
74    int nfds;
75    struct pollfd fds[10];
76    tObjectEntry objects[10];
77 } tPollInfo;
78
79
80 /// polling information
81 static tPollInfo gPollInfo;
82
83 int bContinue = 0;
84
85 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
86
87
88 /* function to unregister ojbect path message handler */
89 static void unregisterMessageHandler(DBusConnection *connection, void *user_data)
90 {
91    (void)connection;
92    (void)user_data;
93    DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("unregisterObjectPath\n"));
94 }
95
96 /* catches messages not directed to any registered object path ("garbage collector") */
97 static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connection, DBusMessage * message, void * user_data)
98 {
99    DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
100    (void)user_data;
101
102    // org.genivi.persistence.admin  S I G N A L
103    if((0==strcmp("org.genivi.persistence.admin", dbus_message_get_interface(message))))
104    {
105       if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
106       {
107          if((0==strcmp("PersistenceModeChanged", dbus_message_get_member(message))))
108          {
109             // to do handle signal
110             result = signal_persModeChange(connection, message);
111          }
112          else
113          {
114             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback -> unknown signal:"), DLT_STRING(dbus_message_get_interface(message)) );
115          }
116       }
117    }
118    // org.genivi.persistence.admin  S I G N A L
119    else if((0==strcmp("org.genivi.persistence.adminconsumer", dbus_message_get_interface(message))))
120    {
121       if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
122       {
123          pclNotification_s notifyStruct;
124          int validMessage = 0;
125
126          if((0==strcmp("PersistenceResChange", dbus_message_get_member(message))))
127          {
128             notifyStruct.pclKeyNotify_Status = pclNotifyStatus_changed;
129             validMessage = 1;
130          }
131          else if((0==strcmp("PersistenceResDelete", dbus_message_get_member(message))))
132          {
133             notifyStruct.pclKeyNotify_Status = pclNotifyStatus_deleted;
134             validMessage = 1;
135          }
136          else if((0==strcmp("PersistenceRes", dbus_message_get_member(message))))
137          {
138             notifyStruct.pclKeyNotify_Status = pclNotifyStatus_created;
139             validMessage = 1;
140          }
141
142          if(validMessage == 1)
143          {
144             DBusError error;
145             DBusMessage *reply;
146             dbus_error_init (&error);
147             char* ldbid;
148             char* user_no;
149             char* seat_no;
150
151             if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &notifyStruct.resource_id,
152                                                          DBUS_TYPE_STRING, &ldbid,
153                                                          DBUS_TYPE_STRING, &user_no,
154                                                          DBUS_TYPE_STRING, &seat_no,
155                                                          DBUS_TYPE_INVALID))
156             {
157                reply = dbus_message_new_error(message, error.name, error.message);
158
159                if (reply == 0)
160                {
161                   DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback => DBus No memory"), DLT_STRING(dbus_message_get_interface(message)) );
162                }
163
164                if (!dbus_connection_send(connection, reply, 0))
165                {
166                   DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback => DBus No memory"), DLT_STRING(dbus_message_get_interface(message)) );
167                }
168
169                result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;;
170                dbus_message_unref(reply);
171             }
172             else
173             {
174                notifyStruct.ldbid       = atoi(ldbid);
175                notifyStruct.user_no     = atoi(user_no);
176                notifyStruct.seat_no     = atoi(seat_no);
177
178                // call the registered callback function
179                if(gChangeNotifyCallback != NULL )
180                {
181                   gChangeNotifyCallback(&notifyStruct);
182                }
183                else
184                {
185                   DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback => gChangeNotifyCallback is not set (possibly NULL)") );
186                }
187                result = DBUS_HANDLER_RESULT_HANDLED;
188             }
189             dbus_connection_flush(connection);
190          }
191       }
192    }
193    // org.genivi.persistence.admin  P R O P E R T Y
194    else  if((0==strcmp("org.freedesktop.DBus.Properties", dbus_message_get_interface(message))))
195    {
196       if(dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
197       {
198          if((0==strcmp("EggDBusChanged", dbus_message_get_member(message))))
199          {
200             DBusMessageIter array;
201             DBusMessageIter dict;
202             DBusMessageIter variant;
203
204             char* dictString = NULL;
205             int value = 0;
206
207             dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, 0, &dict);
208             dbus_message_iter_get_basic(&dict, &dictString);
209
210             dbus_message_iter_open_container(&dict,DBUS_TYPE_VARIANT, NULL, &variant);
211             dbus_message_iter_get_basic(&dict, &value);
212
213             dbus_message_iter_close_container(&dict, &variant);
214             dbus_message_iter_close_container(&array, &dict);
215
216             // to do handle signal
217             result = DBUS_HANDLER_RESULT_HANDLED;
218          }
219          else
220          {
221             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback -> unknown property:"), DLT_STRING(dbus_message_get_interface(message)) );
222          }
223       }
224       else
225       {
226          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("handleObjectPathMessageFallback -> not a signal:"), DLT_STRING(dbus_message_get_member(message)) );
227       }
228    }
229    return result;
230 }
231
232
233
234 static void  unregisterObjectPathFallback(DBusConnection *connection, void *user_data)
235 {
236    (void)connection;
237    (void)user_data;
238    DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("unregisterObjectPathFallback\n"));
239 }
240
241
242
243 void* run_mainloop(void* dataPtr)
244 {
245    // persistence admin message
246    static const struct DBusObjectPathVTable vtablePersAdmin
247       = {unregisterMessageHandler, checkPersAdminMsg, NULL, NULL, NULL, NULL};
248
249    // lifecycle message
250    static const struct DBusObjectPathVTable vtableLifecycle
251       = {unregisterMessageHandler, checkLifecycleMsg, NULL, NULL, NULL, NULL};
252
253    // fallback
254    static const struct DBusObjectPathVTable vtableFallback
255       = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, NULL, NULL, NULL};
256
257    // setup the dbus
258    mainLoop(vtablePersAdmin, vtableLifecycle, vtableFallback, dataPtr);
259
260    return NULL;
261 }
262
263
264
265 int setup_dbus_mainloop(void)
266 {
267    int rval = 0;
268    DBusError err;
269    DBusConnection* conn = NULL;
270
271    const char *pAddress = getenv("PERS_CLIENT_DBUS_ADDRESS");
272
273    dbus_error_init(&err);
274
275    // wait until dbus main loop has been setup and running
276    pthread_mutex_lock(&gDbusInitializedMtx);
277
278    // Connect to the bus and check for errors
279    if(pAddress != NULL)
280    {
281       DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("setup_dbus_mainloop -> Use specific dbus address:"), DLT_STRING(pAddress) );
282
283       conn = dbus_connection_open_private(pAddress, &err);
284
285       if(conn != NULL)
286       {
287          if(!dbus_bus_register(conn, &err))
288          {
289             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("dbus_bus_register() Error :"), DLT_STRING(err.message) );
290             dbus_error_free (&err);
291             pthread_mutex_unlock(&gDbusInitializedMtx);
292             return -1;
293          }
294       }
295       else
296       {
297          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("dbus_connection_open_private() Error :"), DLT_STRING(err.message) );
298          dbus_error_free(&err);
299          pthread_mutex_unlock(&gDbusInitializedMtx);
300          return -1;
301       }
302    }
303    else
304    {
305       DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Use default dbus bus (DBUS_BUS_SYSTEM)"));
306
307       conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
308    }
309
310    // create here the dbus connection and pass to main loop
311    rval = pthread_create(&gMainLoopThread, NULL, run_mainloop, conn);
312    if(rval)
313    {
314      DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pthread_create( DBUS run_mainloop ) returned an error:"), DLT_INT(rval) );
315      pthread_mutex_unlock(&gDbusInitializedMtx);
316      return -1;
317    }
318
319    // wait for condition variable
320    pthread_cond_wait(&gDbusInitializedCond, &gDbusInitializedMtx);
321
322    pthread_mutex_unlock(&gDbusInitializedMtx);
323    return rval;
324 }
325
326
327
328
329
330 static dbus_bool_t addWatch(DBusWatch *watch, void *data)
331 {
332    dbus_bool_t result = FALSE;
333    (void)data;
334
335    if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
336    {
337       int flags = dbus_watch_get_flags(watch);
338
339       tObjectEntry * const pEntry = &gPollInfo.objects[gPollInfo.nfds];
340       pEntry->objtype = OT_WATCH;
341       pEntry->watch = watch;
342
343       gPollInfo.fds[gPollInfo.nfds].fd = dbus_watch_get_unix_fd(watch);
344
345       if (TRUE==dbus_watch_get_enabled(watch))
346       {
347          if (flags&DBUS_WATCH_READABLE)
348          {
349             gPollInfo.fds[gPollInfo.nfds].events |= POLLIN;
350          }
351          if (flags&DBUS_WATCH_WRITABLE)
352          {
353             gPollInfo.fds[gPollInfo.nfds].events |= POLLOUT;
354          }
355
356          ++gPollInfo.nfds;
357       }
358
359       result = TRUE;
360    }
361
362    return result;
363 }
364
365
366
367 static void removeWatch(DBusWatch *watch, void *data)
368 {
369    void* w_data = dbus_watch_get_data(watch);
370
371    (void)data;
372
373    DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("removeWatch called "), DLT_INT( (int)watch) );
374
375    if(w_data)
376       free(w_data);
377
378    dbus_watch_set_data(watch, NULL, NULL);
379 }
380
381
382
383 static void watchToggled(DBusWatch *watch, void *data)
384 {
385    (void)data;
386    DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("watchToggled called "), DLT_INT( (int)watch) );
387
388    if(dbus_watch_get_enabled(watch))
389       addWatch(watch, data);
390    else
391       removeWatch(watch, data);
392 }
393
394
395
396 static dbus_bool_t addTimeout(DBusTimeout *timeout, void *data)
397 {
398    (void)data;
399    dbus_bool_t ret = FALSE;
400
401    if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
402    {
403       const int interval = dbus_timeout_get_interval(timeout);
404       if ((0<interval)&&(TRUE==dbus_timeout_get_enabled(timeout)))
405       {
406          const int tfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
407          if (-1!=tfd)
408          {
409             const struct itimerspec its = { .it_value= {interval/1000, interval%1000} };
410             if (-1!=timerfd_settime(tfd, 0, &its, NULL))
411             {
412                tObjectEntry * const pEntry = &gPollInfo.objects[gPollInfo.nfds];
413                pEntry->objtype = OT_TIMEOUT;
414                pEntry->timeout = timeout;
415                gPollInfo.fds[gPollInfo.nfds].fd = tfd;
416                gPollInfo.fds[gPollInfo.nfds].events |= POLLIN;
417                ++gPollInfo.nfds;
418                ret = TRUE;
419             }
420             else
421             {
422                DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("addTimeout => timerfd_settime() failed"), DLT_STRING(strerror(errno)) );
423             }
424          }
425          else
426          {
427             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("addTimeout => timerfd_create() failed"), DLT_STRING(strerror(errno)) );
428          }
429       }
430    }
431    else
432    {
433       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("addTimeout => cannot create another fd to be poll()'ed"));
434    }
435
436    return ret;
437 }
438
439
440
441 static void removeTimeout(DBusTimeout *timeout, void *data)
442 {
443    int i = gPollInfo.nfds;
444    (void)data;
445
446    while ((0<i--)&&(timeout!=gPollInfo.objects[i].timeout));
447
448    if (0<i)
449    {
450       if (-1==close(gPollInfo.fds[i].fd))
451       {
452          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("removeTimeout => close() timerfd"), DLT_STRING(strerror(errno)) );
453       }
454
455       --gPollInfo.nfds;
456       while (gPollInfo.nfds>i)
457       {
458          gPollInfo.fds[i] = gPollInfo.fds[i+1];
459          gPollInfo.objects[i] = gPollInfo.objects[i+1];
460          ++i;
461       }
462
463       gPollInfo.fds[gPollInfo.nfds].fd = -1;
464       gPollInfo.objects[gPollInfo.nfds].objtype = OT_NONE;
465    }
466 }
467
468
469
470 /** callback for libdbus' when timeout changed */
471 static void timeoutToggled(DBusTimeout *timeout, void *data)
472 {
473    int i = gPollInfo.nfds;
474    (void)data;
475
476    while ((0<i--)&&(timeout!=gPollInfo.objects[i].timeout));
477    DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("timeoutToggled") );
478    if (0<i)
479    {
480       const int interval = (TRUE==dbus_timeout_get_enabled(timeout))?dbus_timeout_get_interval(timeout):0;
481       const struct itimerspec its = { .it_value= {interval/1000, interval%1000} };
482       if (-1!=timerfd_settime(gPollInfo.fds[i].fd, 0, &its, NULL))
483       {
484          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("timeoutToggled => timerfd_settime()"), DLT_STRING(strerror(errno)) );
485       }
486    }
487 }
488
489
490
491 int mainLoop(DBusObjectPathVTable vtable, DBusObjectPathVTable vtable2,
492              DBusObjectPathVTable vtableFallback, void* userData)
493 {
494    DBusError err;
495    // lock mutex to make sure dbus main loop is running
496    pthread_mutex_lock(&gDbusInitializedMtx);
497
498    DBusConnection* conn = (DBusConnection*)userData;
499    dbus_error_init(&err);
500
501    if (dbus_error_is_set(&err))
502    {
503       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => Connection Error:"), DLT_STRING(err.message) );
504       dbus_error_free(&err);
505    }
506    else if (NULL != conn)
507    {
508       dbus_connection_set_exit_on_disconnect(conn, FALSE);
509       if (-1 == (gEfds = eventfd(0, 0)))
510       {
511          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => eventfd() failed w/ errno:"), DLT_INT(errno) );
512       }
513       else
514       {
515          int ret;
516          memset(&gPollInfo, 0 , sizeof(gPollInfo));
517
518          gPollInfo.nfds = 1;
519          gPollInfo.fds[0].fd = gEfds;
520          gPollInfo.fds[0].events = POLLIN;
521
522          dbus_bus_add_match(conn, "type='signal',interface='org.genivi.persistence.admin',member='PersistenceModeChanged',path='/org/genivi/persistence/admin'", &err);
523
524          // register for messages
525          if (   (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/NodeStateManager/LifeCycleConsumer", &vtable2, userData))
526 #if USE_PASINTERFACE == 1
527              && (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/persistence/adminconsumer", &vtable, userData))
528 #endif
529              && (TRUE==dbus_connection_register_fallback(conn, "/", &vtableFallback, userData)) )
530          {
531             if(   (TRUE!=dbus_connection_set_watch_functions(conn, addWatch, removeWatch, watchToggled, NULL, NULL))
532                || (TRUE!=dbus_connection_set_timeout_functions(conn, addTimeout, removeTimeout, timeoutToggled, NULL, NULL)) )
533             {
534                DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => dbus_connection_set_watch_functions() failed"));
535             }
536             else
537             {
538                pthread_cond_signal(&gDbusInitializedCond);
539                pthread_mutex_unlock(&gDbusInitializedMtx);
540                do
541                {
542                   bContinue = 0; /* assume error */
543
544                   while (DBUS_DISPATCH_DATA_REMAINS==dbus_connection_dispatch(conn));
545
546                   while ((-1==(ret=poll(gPollInfo.fds, gPollInfo.nfds, 750)))&&(EINTR==errno));
547
548                   if (0>ret)
549                   {
550                      DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => poll() failed w/ errno "), DLT_INT(errno) );
551                   }
552                   else if (0==ret)
553                   {
554                      /* poll time-out */
555                   }
556                   else
557                   {
558                      int i;
559
560                      for (i=0; gPollInfo.nfds>i; ++i)
561                      {
562                         /* anything to do */
563                         if (0!=gPollInfo.fds[i].revents)
564                         {
565                            if (OT_TIMEOUT==gPollInfo.objects[i].objtype)
566                            {
567                               /* time-out occured */
568                               unsigned long long nExpCount = 0;
569                               if ((ssize_t)sizeof(nExpCount)!=read(gPollInfo.fds[i].fd, &nExpCount, sizeof(nExpCount)))
570                               {
571                                  DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => read failed"));
572                               }
573                               DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => timeout"));
574
575                               if (FALSE==dbus_timeout_handle(gPollInfo.objects[i].timeout))
576                               {
577                                  DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => dbus_timeout_handle() failed!?"));
578                               }
579                               bContinue = TRUE;
580                            }
581                            else if (gPollInfo.fds[i].fd == gEfds)
582                            {
583                               /* internal command */
584                               if (0!=(gPollInfo.fds[i].revents & POLLIN))
585                               {
586                                  uint16_t buf[64];
587                                  bContinue = TRUE;
588                                  while ((-1==(ret = read(gPollInfo.fds[i].fd, buf, 64)))&&(EINTR == errno));
589                                  if(ret < 0)
590                                  {
591                                     DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => read() failed"), DLT_STRING(strerror(errno)) );
592                                  }
593                                  else
594                                  {
595                                     pthread_mutex_lock(&gMainCondMtx);
596                                     switch (buf[0])
597                                     {
598                                        case CMD_PAS_BLOCK_AND_WRITE_BACK:
599                                           process_block_and_write_data_back((buf[2]), buf[1]);
600                                           process_send_pas_request(conn, (buf[2]), buf[1]);
601                                           break;
602                                        case CMD_LC_PREPARE_SHUTDOWN:
603                                           process_prepare_shutdown(Shutdown_Full);
604                                           process_send_lifecycle_request(conn, (buf[2]), buf[1]);
605                                           break;
606                                        case CMD_SEND_NOTIFY_SIGNAL:
607                                           process_send_notification_signal(conn);
608                                           break;
609                                        case CMD_REG_NOTIFY_SIGNAL:
610                                           process_reg_notification_signal(conn);
611                                           break;
612                                        case CMD_SEND_PAS_REGISTER:
613                                           process_send_pas_register(conn, (buf[1]), buf[2]);
614                                           break;
615                                        case CMD_SEND_LC_REGISTER:
616                                           process_send_lifecycle_register(conn, (buf[1]), buf[2]);
617                                           break;
618                                        case CMD_QUIT:
619                                           bContinue = 0;
620                                           break;
621
622                                        // ******************************************************
623                                        /*
624                                        case CMD_SEND_LC_REQUEST:  // remove
625                                          process_send_lifecycle_request(conn, (buf[2]), buf[1]);
626                                          break;
627                                       case CMD_SEND_PAS_REQUEST: /// remove
628                                          process_send_pas_request(conn, (buf[2]), buf[1]);
629                                          break;
630                                        */
631                                        // ******************************************************
632                                        default:
633                                           DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("mainLoop => command not handled"), DLT_INT(buf[0]) );
634                                           break;
635                                     }
636                                     pthread_cond_signal(&gMainLoopCond);
637                                     pthread_mutex_unlock(&gMainCondMtx);
638                                  }
639                               }
640                            }
641                            else
642                            {
643                               int flags = 0;
644                               if (0!=(gPollInfo.fds[i].revents & POLLIN))
645                               {
646                                  flags |= DBUS_WATCH_READABLE;
647                               }
648                               if (0!=(gPollInfo.fds[i].revents & POLLOUT))
649                               {
650                                  flags |= DBUS_WATCH_WRITABLE;
651                               }
652                               if (0!=(gPollInfo.fds[i].revents & POLLERR))
653                               {
654                                  flags |= DBUS_WATCH_ERROR;
655                               }
656                               if (0!=(gPollInfo.fds[i].revents & POLLHUP))
657                               {
658                                  flags |= DBUS_WATCH_HANGUP;
659                               }
660
661                               bContinue = dbus_watch_handle(gPollInfo.objects[i].watch, flags);
662                            }
663                         }
664                      }
665                   }
666                }
667                while (0!=bContinue);
668             }
669 #if USE_PASINTERFACE == 1
670             dbus_connection_unregister_object_path(conn, "/org/genivi/persistence/adminconsumer");
671 #endif
672             dbus_connection_unregister_object_path(conn, "/org/genivi/NodeStateManager/LifeCycleConsumer");
673             dbus_connection_unregister_object_path(conn, "/");
674          }
675          close(gEfds);
676       }
677       dbus_connection_close(conn);
678       dbus_connection_unref(conn);
679       dbus_shutdown();
680    }
681
682    pthread_cond_signal(&gDbusInitializedCond);
683    pthread_mutex_unlock(&gDbusInitializedMtx);
684    return 0;
685 }
686
687
688
689 int deliverToMainloop(tCmd mainloopCmd, unsigned int param1, unsigned int param2)
690 {
691    int rval = 0;
692
693    pthread_mutex_lock(&gDeliverpMtx);
694
695
696    pthread_mutex_lock(&gMainCondMtx);
697
698    deliverToMainloop_NM(mainloopCmd, param1, param2);
699
700    pthread_cond_wait(&gMainLoopCond, &gMainCondMtx);
701    pthread_mutex_unlock(&gMainCondMtx);
702
703
704    pthread_mutex_unlock(&gDeliverpMtx);
705
706    return rval;
707 }
708
709 int deliverToMainloop_NM(tCmd mainloopCmd, unsigned int param1, unsigned int param2)
710 {
711    int rval = 0;
712    uint64_t cmd;
713
714    cmd = ( ((uint64_t)param2 << 32) | ((uint64_t)param1 << 16) | mainloopCmd);
715
716    if(-1 == write(gEfds, &cmd, (sizeof(uint64_t))))
717    {
718      DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("deliverToMainloop => failed to write to pipe"), DLT_INT(errno));
719      rval = -1;
720    }
721
722    return rval;
723 }
724