1 /******************************************************************************
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 ******************************************************************************/
12 * @file persistence_admin_service_mockup.c
13 * @ingroup Persistence client library test
14 * @author Ingo Huerner
15 * @brief Persistence Administration Serivce mockup
23 #include <unistd.h> /* exit */
28 #include <dbus/dbus.h>
31 #include <sys/eventfd.h>
34 /// command definitions for main loop
37 CMD_NONE = 0, /// command none
38 CMD_PAS_BLOCK_AND_WRITE_BACK, /// command block access and write data back
39 CMD_LC_PREPARE_SHUTDOWN, /// command to prepare shutdown
40 CMD_QUIT, /// quit command
45 /// pipe file descriptors
50 pthread_mutex_t gDbusInitializedMtx = PTHREAD_MUTEX_INITIALIZER;
51 pthread_cond_t gDbusInitializedCond = PTHREAD_COND_INITIALIZER;
54 typedef struct SPollInfo
57 struct pollfd fds[10];
58 DBusWatch * watches[10];
62 /// polling information
63 static tPollInfo gPollInfo;
67 DBusConnection* gDbusConn = NULL;
70 DBusConnection* get_dbus_connection(void)
75 //------------------------------------------------------------------------
76 // debugging only until "correct" exit of main loop is possible!!!!!
77 //------------------------------------------------------------------------
79 static int endLoop = 0;
81 void sigHandler(int signo)
85 //------------------------------------------------------------------------
89 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
93 int checkAdminMsg(DBusConnection *connection, DBusMessage *message, int reg)
97 int32_t notificationFlag = 0;
98 uint32_t gTimeoutMs = 0;
99 int msgReturn = 123321;
103 dbus_error_init (&error);
107 if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &busName, // bus name
108 DBUS_TYPE_STRING, &objName,
109 DBUS_TYPE_UINT32, ¬ificationFlag,
110 DBUS_TYPE_UINT32, &gTimeoutMs,
113 reply = dbus_message_new_error(message, error.name, error.message);
117 //DLT_LOG(mgrContext, DLT_LOG_ERROR, DLT_STRING("DBus No memory"));
118 printf("DBus No memory\n");
121 if (!dbus_connection_send(connection, reply, 0))
123 //DLT_LOG(mgrContext, DLT_LOG_ERROR, DLT_STRING("DBus No memory"));
124 printf("DBus No memory\n");
127 dbus_message_unref(reply);
129 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
134 if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &busName, // bus name
135 DBUS_TYPE_STRING, &objName,
136 DBUS_TYPE_UINT32, ¬ificationFlag,
139 reply = dbus_message_new_error(message, error.name, error.message);
143 //DLT_LOG(mgrContext, DLT_LOG_ERROR, DLT_STRING("DBus No memory"));
144 printf("DBus No memory\n");
147 if (!dbus_connection_send(connection, reply, 0))
149 //DLT_LOG(mgrContext, DLT_LOG_ERROR, DLT_STRING("DBus No memory"));
150 printf("DBus No memory\n");
153 dbus_message_unref(reply);
155 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
160 printf(" checkAdminMsg ==> busName: %s | objName: %s | notificationFlag: %u | gTimeoutMs: %d\n\n", busName, objName, notificationFlag, gTimeoutMs);
161 reply = dbus_message_new_method_return(message);
165 //DLT_LOG(mgrContext, DLT_LOG_ERROR, DLT_STRING("DBus No memory"));
166 printf("DBus No memory\n");
169 if (!dbus_message_append_args(reply, DBUS_TYPE_INT32, &msgReturn, DBUS_TYPE_INVALID))
171 //DLT_LOG(mgrContext, DLT_LOG_ERROR, DLT_STRING("DBus No memory"));
172 printf("DBus No memory\n");
175 if (!dbus_connection_send(connection, reply, NULL))
177 //DLT_LOG(mgrContext, DLT_LOG_ERROR, DLT_STRING("DBus No memory"));
178 printf("DBus No memory\n");
181 dbus_connection_flush(connection);
182 dbus_message_unref(reply);
184 return DBUS_HANDLER_RESULT_HANDLED;
189 DBusHandlerResult checkPersAdminMsg(DBusConnection * connection, DBusMessage * message, void * user_data)
191 DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
193 //printf("checkPersAdminMsg '%s' -> '%s'\n", dbus_message_get_interface(message), dbus_message_get_member(message));
194 if((0==strcmp("org.genivi.NodeStateManager.LifeCycleConsumer", dbus_message_get_interface(message))))
196 if((0==strcmp("RegisterShutdownClient", dbus_message_get_member(message))))
198 printf(" ==> org.genivi.NodeStateManager.LifeCycleConsumer - received - ==> RegisterShutdownClient \n");
200 result = checkAdminMsg(connection, message, 1);
202 else if((0==strcmp("UnRegisterShutdownClient", dbus_message_get_member(message))))
204 printf(" ==> org.genivi.NodeStateManager.LifeCycleConsumer - received - ==> UnRegisterShutdownClient \n");
206 result = checkAdminMsg(connection, message, 0);
208 else if((0==strcmp("LifecycleRequestComplete", dbus_message_get_member(message))))
210 printf(" ==> org.genivi.NodeStateManager.LifeCycleConsumer - received - ==> LifecycleRequestComplete \n");
212 result = checkAdminMsg(connection, message, 0);
217 printf(" ==> org.genivi.NodeStateManager.LifeCycleConsumer - received U N KN O W N-'%s'\n", dbus_message_get_interface(message));
222 printf(" ==> org.genivi.NodeStateManager - received U N KN O W N-'%s'\n", dbus_message_get_interface(message));
228 /* function to unregister ojbect path message handler */
229 static void unregisterMessageHandler(DBusConnection *connection, void *user_data)
231 printf("unregisterObjectPath\n");
234 /* catches messages not directed to any registered object path ("garbage collector") */
235 static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connection, DBusMessage * message, void * user_data)
237 DBusHandlerResult result = DBUS_HANDLER_RESULT_HANDLED;
239 printf("handleObjectPathMessageFallback Object: '%s' -> Interface: '%s' -> Message: '%s'\n",
240 dbus_message_get_sender(message), dbus_message_get_interface(message), dbus_message_get_member(message) );
247 static void unregisterObjectPathFallback(DBusConnection *connection, void *user_data)
249 printf("unregisterObjectPathFallback\n");
257 static dbus_bool_t addWatch(DBusWatch *watch, void *data)
259 dbus_bool_t result = FALSE;
261 //printf("addWatch called @%08x flags: %08x enabled: %c\n", (unsigned int)watch, dbus_watch_get_flags(watch), TRUE==dbus_watch_get_enabled(watch)?'x':'-');
263 if (ARRAY_SIZE(gPollInfo.fds)>gPollInfo.nfds)
265 int flags = dbus_watch_get_flags(watch);
267 gPollInfo.watches[gPollInfo.nfds] = watch;
269 gPollInfo.fds[gPollInfo.nfds].fd = dbus_watch_get_unix_fd(watch);
271 if (TRUE==dbus_watch_get_enabled(watch))
273 if (flags&DBUS_WATCH_READABLE)
275 gPollInfo.fds[gPollInfo.nfds].events |= POLLIN;
277 if (flags&DBUS_WATCH_WRITABLE)
279 gPollInfo.fds[gPollInfo.nfds].events |= POLLOUT;
283 /* wakeup main-loop, just in case */
284 static const uint64_t cmd = CMD_REQUEST_NAME;
285 if (sizeof(uint64_t)!=write(gEfds, &cmd, sizeof(uint64_t)))
287 fprintf(stderr, "write failed w/ errno %d\n", errno);
298 static void removeWatch(DBusWatch *watch, void *data)
300 void* w_data = dbus_watch_get_data(watch);
302 printf("removeWatch called @0x%08x\n", (int)watch);
307 dbus_watch_set_data(watch, NULL, NULL);
311 static void watchToggled(DBusWatch *watch, void *data)
313 printf("watchToggled called @0x%08x\n", (int)watch);
315 if(dbus_watch_get_enabled(watch))
316 addWatch(watch, data);
318 removeWatch(watch, data);
323 int mainLoop(DBusObjectPathVTable vtable, DBusObjectPathVTable vtableFallback, void* userData)
326 // lock mutex to make sure dbus main loop is running
327 pthread_mutex_lock(&gDbusInitializedMtx);
329 signal(SIGTERM, sigHandler);
330 signal(SIGQUIT, sigHandler);
331 signal(SIGINT, sigHandler);
333 DBusConnection* conn = (DBusConnection*)userData;
334 dbus_error_init(&err);
336 if (dbus_error_is_set(&err))
338 printf("Connection Error (%s)\n", err.message);
339 dbus_error_free(&err);
341 else if (NULL != conn)
343 dbus_connection_set_exit_on_disconnect (conn, FALSE);
344 printf("connected as '%s'\n", dbus_bus_get_unique_name(conn));
345 if (-1 == (gEfds = eventfd(0, 0)))
347 printf("eventfd() failed w/ errno %d\n", errno);
353 memset(&gPollInfo, 0 , sizeof(gPollInfo));
356 gPollInfo.fds[0].fd = gEfds;
357 gPollInfo.fds[0].events = POLLIN;
359 // register for messages
360 if ( (TRUE==dbus_connection_register_object_path(conn, "/org/genivi/NodeStateManager", &vtable, userData))
361 && (TRUE==dbus_connection_register_fallback(conn, "/", &vtableFallback, userData)) )
363 if (TRUE!=dbus_connection_set_watch_functions(conn, addWatch, removeWatch, watchToggled, NULL, NULL))
365 printf("dbus_connection_set_watch_functions() failed\n");
371 pthread_cond_signal(&gDbusInitializedCond);
372 pthread_mutex_unlock(&gDbusInitializedMtx);
375 bContinue = 0; /* assume error */
377 while(DBUS_DISPATCH_DATA_REMAINS==dbus_connection_dispatch(conn));
379 while((-1==(ret=poll(gPollInfo.fds, gPollInfo.nfds, 500)))&&(EINTR==errno));
383 printf("poll() failed w/ errno %d\n", errno);
390 for (i=0; gPollInfo.nfds>i; ++i)
392 if (0!=gPollInfo.fds[i].revents)
394 if (gPollInfo.fds[i].fd==gEfds)
396 if (0!=(gPollInfo.fds[i].revents & POLLIN))
399 while ((-1==(ret=read(gPollInfo.fds[i].fd, buf, 64)))&&(EINTR==errno));
402 printf("read() failed w/ errno %d | %s\n", errno, strerror(errno));
408 case CMD_REQUEST_NAME:
409 if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER !=dbus_bus_request_name(conn, "org.genivi.NodeStateManager", DBUS_NAME_FLAG_DO_NOT_QUEUE, &err))
411 fprintf(stderr, "Cannot acquire name 'org.genivi.NodeStateManager': \n \"(%s)\". Bailing out!\n", err.message);
412 dbus_error_free(&err);
420 printf("command %d not handled!\n", buf[0]);
429 if (0!=(gPollInfo.fds[i].revents & POLLIN))
431 flags |= DBUS_WATCH_READABLE;
433 if (0!=(gPollInfo.fds[i].revents & POLLOUT))
435 flags |= DBUS_WATCH_WRITABLE;
437 if (0!=(gPollInfo.fds[i].revents & POLLERR))
439 flags |= DBUS_WATCH_ERROR;
441 if (0!=(gPollInfo.fds[i].revents & POLLHUP))
443 flags |= DBUS_WATCH_HANGUP;
445 //printf("handle watch @0x%08x flags: %04x\n", (int)gPollInfo.watches[i], flags);
446 bContinue = dbus_watch_handle(gPollInfo.watches[i], flags);
454 while (0!=bContinue);
456 dbus_connection_unregister_object_path(conn, "/org/genivi/NodeStateManager");
457 dbus_connection_unregister_object_path(conn, "/");
461 dbus_connection_close(conn);
462 dbus_connection_unref(conn);
466 pthread_cond_signal(&gDbusInitializedCond);
467 pthread_mutex_unlock(&gDbusInitializedMtx);
472 void* run_mainloop(void* dataPtr)
474 // persistence admin message
475 static const struct DBusObjectPathVTable vtablePersAdmin
476 = {unregisterMessageHandler, checkPersAdminMsg, NULL, };
479 static const struct DBusObjectPathVTable vtableFallback
480 = {unregisterObjectPathFallback, handleObjectPathMessageFallback, NULL, };
483 mainLoop(vtablePersAdmin, vtableFallback, dataPtr);
485 printf("Exit dbus main loop!!!!\n");
491 int setup_dbus_mainloop(void)
496 const char *pAddress = getenv("PERS_CLIENT_DBUS_ADDRESS");
497 dbus_error_init(&err);
499 // enable locking of data structures in the D-Bus library for multi threading.
500 dbus_threads_init_default();
502 // Connect to the bus and check for errors
505 printf("Use specific dbus address: %s\n !", pAddress);
506 gDbusConn = dbus_connection_open_private(pAddress, &err);
508 if(gDbusConn != NULL)
510 if(!dbus_bus_register(gDbusConn, &err))
512 printf("dbus_bus_register() Error %s\n", err.message);
513 dbus_error_free (&err);
518 printf("Registered connection successfully !\n");
523 printf("dbus_connection_open() Error %s\n",err.message);
524 dbus_error_free(&err);
529 printf("Use default dbus bus!!!!!!\n");
530 gDbusConn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
533 // wain until dbus main loop has been setup and running
534 pthread_mutex_lock(&gDbusInitializedMtx);
536 // create here the dbus connection and pass to main loop
537 rval = pthread_create(&thread, NULL, run_mainloop, gDbusConn);
540 fprintf(stderr, "Server: - ERROR! pthread_create( run_mainloop ) returned: %d\n", rval);
543 // wait for condition variable
544 pthread_cond_wait(&gDbusInitializedCond, &gDbusInitializedMtx);
546 pthread_mutex_unlock(&gDbusInitializedMtx);
552 int main(int argc, char *argv[])
554 setup_dbus_mainloop();
556 printf("Wait, press enter to exit!!\n");
558 printf("Exiting Persistence Lifecycle mockup!!\n");