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_client_library_dbus_cmd.c
13 * @ingroup Persistence client library
14 * @author Ingo Huerner
15 * @brief Implementation of the persistence client library dbus commands.
20 #include <dlfcn.h> /* For dlclose() */
21 #include "persistence_client_library_dbus_cmd.h"
23 #include "persistence_client_library_handle.h"
24 #include "persistence_client_library_custom_loader.h"
25 #include "persistence_client_library_prct_access.h"
26 #include "persistence_client_library_pas_interface.h"
27 #include "persistence_client_library_data_organization.h"
28 #include "persistence_client_library_db_access.h"
32 void msg_pending_func(DBusPendingCall *call, void *data);
36 void process_reg_notification_signal(DBusConnection* conn)
38 char ruleChanged[DbusMatchRuleSize] = {[0 ... DbusMatchRuleSize-1] = 0};
39 char ruleDeleted[DbusMatchRuleSize] = {[0 ... DbusMatchRuleSize-1] = 0};
40 char ruleCreated[DbusMatchRuleSize] = {[0 ... DbusMatchRuleSize-1] = 0};
42 // add match for c h a n g e
43 snprintf(ruleChanged, DbusMatchRuleSize,
44 "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResChange',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
45 gNotifykey, gNotifyLdbid, gNotifyUserNo, gNotifySeatNo);
47 // add match for d e l e t e
48 snprintf(ruleDeleted, DbusMatchRuleSize,
49 "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResDelete',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
50 gNotifykey, gNotifyLdbid, gNotifyUserNo, gNotifySeatNo);
52 // add match for c r e a t e
53 snprintf(ruleCreated, DbusMatchRuleSize,
54 "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResCreate',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
55 gNotifykey, gNotifyLdbid, gNotifyUserNo, gNotifySeatNo);
57 if(gNotifyPolicy == Notify_register)
59 dbus_bus_add_match(conn, ruleChanged, NULL);
60 dbus_bus_add_match(conn, ruleDeleted, NULL);
61 dbus_bus_add_match(conn, ruleCreated, NULL);
62 DLT_LOG(gPclDLTContext, DLT_LOG_VERBOSE, DLT_STRING("Registered for change notifications:"), DLT_STRING(ruleChanged));
64 else if(gNotifyPolicy == Notify_unregister)
66 dbus_bus_remove_match(conn, ruleChanged, NULL);
67 dbus_bus_remove_match(conn, ruleDeleted, NULL);
68 dbus_bus_remove_match(conn, ruleCreated, NULL);
69 DLT_LOG(gPclDLTContext, DLT_LOG_VERBOSE, DLT_STRING("Unregistered for change notifications:"), DLT_STRING(ruleChanged));
72 dbus_connection_flush(conn); // flush the connection to add the match
77 void process_send_notification_signal(DBusConnection* conn)
81 const char* notifyReason = NULL;
83 char ldbidArray[DbusSubMatchSize] = {[0 ... DbusSubMatchSize-1] = 0};
84 char userArray[DbusSubMatchSize] = {[0 ... DbusSubMatchSize-1] = 0};
85 char seatArray[DbusSubMatchSize] = {[0 ... DbusSubMatchSize-1] = 0};
86 char* pldbidArra = ldbidArray;
87 char* puserArray = userArray;
88 char* pseatArray = seatArray;
89 char* pnotifyKey = gNotifykey;
93 case pclNotifyStatus_deleted:
94 notifyReason = gDeleteSignal;
96 case pclNotifyStatus_created:
97 notifyReason = gCreateSignal;
99 case pclNotifyStatus_changed:
100 notifyReason = gChangeSignal;
107 if(notifyReason != NULL)
109 // dbus_bus_add_match is used for the notification mechanism,
110 // and this works only for type DBUS_TYPE_STRING as message arguments
111 // this is the reason to use string instead of integer types directly
112 snprintf(ldbidArray, DbusSubMatchSize, "%u", gNotifyLdbid);
113 snprintf(userArray, DbusSubMatchSize, "%u", gNotifyUserNo);
114 snprintf(seatArray, DbusSubMatchSize, "%u", gNotifySeatNo);
116 //printf("process_send_Notification_Signal => key: %s | lbid: %d | gUserNo: %d | gSeatNo: %d | gReason: %d \n", gNotifykey, gLdbid, gUserNo, gSeatNo, gReason);
117 message = dbus_message_new_signal("/org/genivi/persistence/adminconsumer", // const char *path,
118 "org.genivi.persistence.adminconsumer", // const char *interface,
119 notifyReason); // const char *name
121 ret = dbus_message_append_args(message, DBUS_TYPE_STRING, &pnotifyKey,
122 DBUS_TYPE_STRING, &pldbidArra,
123 DBUS_TYPE_STRING, &puserArray,
124 DBUS_TYPE_STRING, &pseatArray,
131 if(dbus_connection_send(conn, message, 0) == TRUE)
133 // Free the signal now we have finished with it
134 dbus_message_unref(message);
138 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> failed to send dbus message!!"));
143 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> E R R O R C O N E C T I O N NULL!!"));
148 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> ERROR dbus_message_append_args"));
153 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> ERROR invalid notification reason"));
159 void process_block_and_write_data_back(unsigned int requestID, unsigned int status)
163 // lock persistence data access
165 // sync data back to memory device
170 void process_prepare_shutdown(int complete)
177 // flush open files to disk
178 for(i=0; i<MaxPersHandle; i++)
180 if(gOpenFdArray[i] == FileOpen)
184 if(complete == Shutdown_Full)
186 rval = pfcCloseFile(i);
188 else if(complete == Shutdown_Partial)
190 pfcWriteBackAndSync(i);
193 if(complete == Shutdown_Full)
197 else if(complete == Shutdown_Partial)
204 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_prepare_shutdown => failed to close file: "), DLT_STRING(strerror(errno)) );
210 // close all opend rct
211 pers_rct_close_all();
213 // close opend database
214 database_close_all();
218 close_all_persistence_handle();
224 // unload custom client libraries
225 for(i=0; i<PersCustomLib_LastEntry; i++)
227 if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
229 // deinitialize plugin
230 gPersCustomFuncs[i].custom_plugin_deinit();
231 // close library handle
232 dlclose(gPersCustomFuncs[i].handle);
234 invalidate_custom_plugin(i);
242 void process_send_pas_request(DBusConnection* conn, unsigned int requestID, int status)
245 dbus_error_init (&error);
247 DBusMessage* message = dbus_message_new_method_call("org.genivi.persistence.admin", // destination
248 "/org/genivi/persistence/admin", // path
249 "org.genivi.persistence.admin", // interface
250 "PersistenceAdminRequestCompleted"); // method
255 dbus_message_append_args(message, DBUS_TYPE_UINT32, &requestID,
256 DBUS_TYPE_INT32, &status,
259 if(!dbus_connection_send(conn, message, 0))
261 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => Access denied"), DLT_STRING(error.message) );
264 dbus_connection_flush(conn);
265 dbus_message_unref(message);
269 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request => ERROR: Invalid message") );
274 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request => ERROR: Invalid connection") );
279 void process_send_pas_register(DBusConnection* conn, int regType, int notificationFlag)
282 dbus_error_init (&error);
283 DBusPendingCall* pending = NULL;
288 method = "UnRegisterPersAdminNotification";
289 else if(regType == 1)
290 method = "RegisterPersAdminNotification";
294 const char* objName = "/org/genivi/persistence/adminconsumer";
295 const char* busName = dbus_bus_get_unique_name(conn);
299 DBusMessage* message = dbus_message_new_method_call("org.genivi.persistence.admin", // destination
300 "/org/genivi/persistence/admin", // path
301 "org.genivi.persistence.admin", // interface
306 dbus_message_append_args(message, DBUS_TYPE_STRING, &busName, // bus name
307 DBUS_TYPE_STRING, &objName,
308 DBUS_TYPE_INT32, ¬ificationFlag,
309 DBUS_TYPE_UINT32, &gTimeoutMs,
312 dbus_connection_send_with_reply(conn, // the connection
313 message, // the message to write
315 gTimeoutMs); // timeout in milliseconds or -1 for default
317 dbus_connection_flush(conn);
319 if(!dbus_pending_call_set_notify(pending, msg_pending_func, method, NULL))
321 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_pas_register => dbus_pending_call_set_notify: FAILED\n") );
323 dbus_pending_call_unref(pending);
327 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register => ERROR: Invalid message") );
329 dbus_message_unref(message);
333 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register => ERROR: Invalid busname") );
338 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register => ERROR: Invalid connection") );
343 void process_send_lifecycle_register(DBusConnection* conn, int regType, int shutdownMode)
346 dbus_error_init (&error);
351 method = "RegisterShutdownClient";
352 else if(regType == 0)
353 method = "UnRegisterShutdownClient";
357 const char* objName = "/org/genivi/NodeStateManager/LifeCycleConsumer";
358 const char* busName = dbus_bus_get_unique_name(conn);
360 DBusMessage* message = dbus_message_new_method_call("org.genivi.NodeStateManager", // destination
361 "/org/genivi/NodeStateManager/Consumer", // path
362 "org.genivi.NodeStateManager.Consumer", // interface
366 if(regType == 1) // register
368 dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,
369 DBUS_TYPE_STRING, &objName,
370 DBUS_TYPE_UINT32, &shutdownMode,
371 DBUS_TYPE_UINT32, &gTimeoutMs, DBUS_TYPE_INVALID);
375 dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,
376 DBUS_TYPE_STRING, &objName,
377 DBUS_TYPE_UINT32, &shutdownMode, DBUS_TYPE_INVALID);
380 if(!dbus_connection_send(conn, message, 0))
382 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => Access denied"), DLT_STRING(error.message) );
384 dbus_connection_flush(conn);
385 dbus_message_unref(message);
389 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => ERROR: Invalid message"));
394 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => ERROR: connection isn NULL"));
400 void process_send_lifecycle_request(DBusConnection* conn, unsigned int requestId, unsigned int status)
403 dbus_error_init (&error);
407 DBusMessage* message = dbus_message_new_method_call("org.genivi.NodeStateManager", // destination
408 "/org/genivi/NodeStateManager/Consumer", // path
409 "org.genivi.NodeStateManager.Consumer", // interface
410 "LifecycleRequestComplete"); // method
413 dbus_message_append_args(message, DBUS_TYPE_INT32, &requestId,
414 DBUS_TYPE_INT32, &status,
418 if(!dbus_connection_send(conn, message, 0))
420 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => Access denied"), DLT_STRING(error.message) );
423 dbus_connection_flush(conn);
424 dbus_message_unref(message);
428 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => ERROR: Invalid message"));
433 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => ERROR: connection isn NULL"));
439 void msg_pending_func(DBusPendingCall *call, void *data)
443 dbus_error_init(&err);
447 DBusMessage *message = dbus_pending_call_steal_reply(call);
449 if (dbus_set_error_from_message(&err, message))
451 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msg_pending_func ==> Access denied") );
455 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("msg_pending_func ==> UNlock mutex") );
456 dbus_message_get_args(message, &err, DBUS_TYPE_INT32, &replyArg, DBUS_TYPE_INVALID);
459 gDbusPendingRvalue = replyArg; // set the return value
460 dbus_message_unref(message);
462 // unlock the mutex because we have received the reply to the dbus message
463 pthread_mutex_unlock(&gDbusPendingRegMtx);