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"
31 #include <persistence_file_cache.h>
35 * write back from cache to non volatile memory device
37 * THIS FUNCTION IS NOT INTENDED TO BE USED BY A NORMAL APPLICATION.
38 * ONLY SPECIAL APPLICATION ARE ALLOWED TO USING USE THIS FUNCTION
40 extern int pfcWriteBackAndSync(int handle);
45 void msg_pending_func(DBusPendingCall *call, void *data);
49 void process_reg_notification_signal(DBusConnection* conn, unsigned int notifyLdbid, unsigned int notifyUserNo,
50 unsigned int notifySeatNo, unsigned int notifyPolicy, const char* notifyKey)
52 char ruleChanged[DbusMatchRuleSize] = {[0 ... DbusMatchRuleSize-1] = 0};
53 char ruleDeleted[DbusMatchRuleSize] = {[0 ... DbusMatchRuleSize-1] = 0};
54 char ruleCreated[DbusMatchRuleSize] = {[0 ... DbusMatchRuleSize-1] = 0};
56 // add match for c h a n g e
57 snprintf(ruleChanged, DbusMatchRuleSize,
58 "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResChange',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
59 notifyKey, notifyLdbid, notifyUserNo, notifySeatNo);
61 // add match for d e l e t e
62 snprintf(ruleDeleted, DbusMatchRuleSize,
63 "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResDelete',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
64 notifyKey, notifyLdbid, notifyUserNo, notifySeatNo);
66 // add match for c r e a t e
67 snprintf(ruleCreated, DbusMatchRuleSize,
68 "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResCreate',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
69 notifyKey, notifyLdbid, notifyUserNo, notifySeatNo);
71 if(notifyPolicy == Notify_register)
73 dbus_bus_add_match(conn, ruleChanged, NULL);
74 dbus_bus_add_match(conn, ruleDeleted, NULL);
75 dbus_bus_add_match(conn, ruleCreated, NULL);
76 DLT_LOG(gPclDLTContext, DLT_LOG_VERBOSE, DLT_STRING("Registered for change notifications:"), DLT_STRING(ruleChanged));
78 else if(notifyPolicy == Notify_unregister)
80 dbus_bus_remove_match(conn, ruleChanged, NULL);
81 dbus_bus_remove_match(conn, ruleDeleted, NULL);
82 dbus_bus_remove_match(conn, ruleCreated, NULL);
83 DLT_LOG(gPclDLTContext, DLT_LOG_VERBOSE, DLT_STRING("Unregistered for change notifications:"), DLT_STRING(ruleChanged));
86 dbus_connection_flush(conn); // flush the connection to add the match
91 void process_send_notification_signal(DBusConnection* conn, unsigned int notifyLdbid, unsigned int notifyUserNo,
92 unsigned int notifySeatNo, unsigned int notifyReason, const char* notifyKey)
96 const char* notifyReasonString = NULL;
98 char ldbidArray[DbusSubMatchSize] = {[0 ... DbusSubMatchSize-1] = 0};
99 char userArray[DbusSubMatchSize] = {[0 ... DbusSubMatchSize-1] = 0};
100 char seatArray[DbusSubMatchSize] = {[0 ... DbusSubMatchSize-1] = 0};
101 char* pldbidArra = ldbidArray;
102 char* puserArray = userArray;
103 char* pseatArray = seatArray;
104 char* pnotifyKey = (char*)notifyKey;
108 case pclNotifyStatus_deleted:
109 notifyReasonString = gDeleteSignal;
111 case pclNotifyStatus_created:
112 notifyReasonString = gCreateSignal;
114 case pclNotifyStatus_changed:
115 notifyReasonString = gChangeSignal;
118 notifyReasonString = NULL;
122 if(notifyReasonString != NULL)
124 // dbus_bus_add_match is used for the notification mechanism,
125 // and this works only for type DBUS_TYPE_STRING as message arguments
126 // this is the reason to use string instead of integer types directly
127 snprintf(ldbidArray, DbusSubMatchSize, "%u", notifyLdbid);
128 snprintf(userArray, DbusSubMatchSize, "%u", notifyUserNo);
129 snprintf(seatArray, DbusSubMatchSize, "%u", notifySeatNo);
131 //printf("process_send_Notification_Signal => key: %s | lbid: %d | gUserNo: %d | gSeatNo: %d | gReason: %d \n", notifyKey, notifyLdbid, notifyUserNo, notifySeatNo, notifyReason);
132 message = dbus_message_new_signal(gPersAdminConsumerPath,
133 gDbusPersAdminConsInterface,
136 ret = dbus_message_append_args(message, DBUS_TYPE_STRING, &pnotifyKey,
137 DBUS_TYPE_STRING, &pldbidArra,
138 DBUS_TYPE_STRING, &puserArray,
139 DBUS_TYPE_STRING, &pseatArray,
146 if(dbus_connection_send(conn, message, 0) == TRUE)
148 // Free the signal now we have finished with it
149 dbus_message_unref(message);
153 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal - failed to send dbus message!!"));
158 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal - C O N E C T I O N NULL!!"));
163 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal - dbus_message_append_args"));
168 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal - invalid notification reason"));
174 void process_block_and_write_data_back(unsigned int requestID, unsigned int status)
178 // lock persistence data access
180 // sync data back to memory device
185 void process_prepare_shutdown(int complete)
189 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("process_prepare_shutdown - writing down all changed data and closing all handles"));
194 // flush open files to disk
195 for(i=0; i<MaxPersHandle; i++)
197 if(gOpenFdArray[i] == FileOpen)
201 if(complete == Shutdown_Full)
203 rval = pfcCloseFile(i);
205 else if(complete == Shutdown_Partial)
207 pfcWriteBackAndSync(i);
210 if(complete == Shutdown_Full)
214 else if(complete == Shutdown_Partial)
221 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_prepare_shutdown - failed to close file: "), DLT_STRING(strerror(errno)) );
227 // close all opend rct
228 pers_rct_close_all();
230 // close opend database
231 database_close_all();
235 close_all_persistence_handle();
241 // unload custom client libraries
242 for(i=0; i<PersCustomLib_LastEntry; i++)
244 if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
246 // deinitialize plugin
247 gPersCustomFuncs[i].custom_plugin_deinit();
248 // close library handle
249 dlclose(gPersCustomFuncs[i].handle);
251 invalidate_custom_plugin(i);
259 void process_send_pas_request(DBusConnection* conn, unsigned int requestID, int status)
262 dbus_error_init (&error);
264 DBusMessage* message = dbus_message_new_method_call(gDbusPersAdminInterface, // destination
265 gDbusPersAdminPath, // path
266 gDbusPersAdminInterface, // interface
267 "PersistenceAdminRequestCompleted"); // method
272 dbus_message_append_args(message, DBUS_TYPE_UINT32, &requestID,
273 DBUS_TYPE_INT32, &status,
276 if(!dbus_connection_send(conn, message, 0))
278 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register - Access denied"), DLT_STRING(error.message) );
281 dbus_connection_flush(conn);
282 dbus_message_unref(message);
286 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request - Invalid message") );
291 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request - Invalid connection") );
296 void process_send_pas_register(DBusConnection* conn, int regType, int notificationFlag)
299 dbus_error_init (&error);
300 DBusPendingCall* pending = NULL;
305 method = "UnRegisterPersAdminNotification";
306 else if(regType == 1)
307 method = "RegisterPersAdminNotification";
311 const char* busName = dbus_bus_get_unique_name(conn);
315 DBusMessage* message = dbus_message_new_method_call(gDbusPersAdminInterface, // destination
316 gDbusPersAdminPath, // path
317 gDbusPersAdminInterface, // interface
322 dbus_message_append_args(message, DBUS_TYPE_STRING, &busName, // bus name
323 DBUS_TYPE_STRING, &gPersAdminConsumerPath,
324 DBUS_TYPE_INT32, ¬ificationFlag,
325 DBUS_TYPE_UINT32, &gTimeoutMs,
328 dbus_connection_send_with_reply(conn, // the connection
329 message, // the message to write
331 gTimeoutMs); // timeout in milliseconds or -1 for default
333 dbus_connection_flush(conn);
335 if(!dbus_pending_call_set_notify(pending, msg_pending_func, method, NULL))
337 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_pas_register - dbus_pending_call_set_notify: FAILED\n") );
339 dbus_pending_call_unref(pending);
343 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register - Invalid message") );
345 dbus_message_unref(message);
349 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register - Invalid busname") );
354 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register - Invalid connection") );
359 void process_send_lifecycle_register(DBusConnection* conn, int regType, int shutdownMode)
362 dbus_error_init (&error);
367 method = "RegisterShutdownClient";
368 else if(regType == 0)
369 method = "UnRegisterShutdownClient";
373 const char* busName = dbus_bus_get_unique_name(conn);
375 DBusMessage* message = dbus_message_new_method_call(gDbusLcConsDest, // destination
377 gDbusLcInterface, // interface
381 if(regType == 1) // register
383 dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,
384 DBUS_TYPE_STRING, &gDbusLcConsPath,
385 DBUS_TYPE_UINT32, &shutdownMode,
386 DBUS_TYPE_UINT32, &gTimeoutMs, DBUS_TYPE_INVALID);
390 dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,
391 DBUS_TYPE_STRING, &gDbusLcConsPath,
392 DBUS_TYPE_UINT32, &shutdownMode, DBUS_TYPE_INVALID);
395 if(!dbus_connection_send(conn, message, 0))
397 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register - Access denied"), DLT_STRING(error.message) );
399 dbus_connection_flush(conn);
400 dbus_message_unref(message);
404 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register - Invalid message"));
409 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register - connection isn NULL"));
415 void process_send_lifecycle_request(DBusConnection* conn, unsigned int requestId, unsigned int status)
418 dbus_error_init (&error);
422 DBusMessage* message = dbus_message_new_method_call(gDbusLcConsDest, // destination
424 gDbusLcInterface, // interface
425 "LifecycleRequestComplete"); // method
428 dbus_message_append_args(message, DBUS_TYPE_INT32, &requestId,
429 DBUS_TYPE_INT32, &status,
433 if(!dbus_connection_send(conn, message, 0))
435 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request - Access denied"), DLT_STRING(error.message) );
438 dbus_connection_flush(conn);
439 dbus_message_unref(message);
443 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request - Invalid message"));
448 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request - connection isn NULL"));
454 void msg_pending_func(DBusPendingCall *call, void *data)
458 dbus_error_init(&err);
462 DBusMessage *message = dbus_pending_call_steal_reply(call);
464 if (dbus_set_error_from_message(&err, message))
466 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msg_pending_func - Access denied") );
470 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("msg_pending_func ==> UNlock mutex") );
471 dbus_message_get_args(message, &err, DBUS_TYPE_INT32, &replyArg, DBUS_TYPE_INVALID);
474 gDbusPendingRvalue = replyArg; // set the return value
475 dbus_message_unref(message);
477 // unlock the mutex because we have received the reply to the dbus message
478 pthread_mutex_unlock(&gDbusPendingRegMtx);