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.
19 #include "persistence_client_library_dbus_cmd.h"
21 #include "persistence_client_library_handle.h"
22 #include "persistence_client_library_itzam_errors.h"
23 #include "persistence_client_library_custom_loader.h"
24 #include "persistence_client_library_prct_access.h"
26 #include "../include_protected/persistence_client_library_data_organization.h"
27 #include "../include_protected/persistence_client_library_db_access.h"
33 void msg_pending_func(DBusPendingCall *call, void *data);
37 void process_reg_notification_signal(DBusConnection* conn)
39 char ruleChanged[DbusMatchRuleSize] = {0};
40 char ruleDeleted[DbusMatchRuleSize] = {0};
41 char ruleCreated[DbusMatchRuleSize] = {0};
43 // add match for c h a n g e
44 snprintf(ruleChanged, DbusMatchRuleSize,
45 "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResChange',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
46 gRegNotifykey, gRegNotifyLdbid, gRegNotifyUserNo, gRegNotifySeatNo);
48 // add match for d e l e t e
49 snprintf(ruleDeleted, DbusMatchRuleSize,
50 "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResDelete',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
51 gRegNotifykey, gRegNotifyLdbid, gRegNotifyUserNo, gRegNotifySeatNo);
53 // add match for c r e a t e
54 snprintf(ruleCreated, DbusMatchRuleSize,
55 "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResCreate',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
56 gRegNotifykey, gRegNotifyLdbid, gRegNotifyUserNo, gRegNotifySeatNo);
58 if(gRegNotifyPolicy == Notify_register)
60 dbus_bus_add_match(conn, ruleChanged, NULL);
61 dbus_bus_add_match(conn, ruleDeleted, NULL);
62 dbus_bus_add_match(conn, ruleCreated, NULL);
64 else if(gRegNotifyPolicy == 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);
71 dbus_connection_flush(conn); // flush the connection to add the match
76 void process_send_notification_signal(DBusConnection* conn)
80 const char* notifyReason = NULL;
82 char ldbidArray[DbusSubMatchSize] = {0};
83 char userArray[DbusSubMatchSize] = {0};
84 char seatArray[DbusSubMatchSize] = {0};
85 char* pldbidArra = ldbidArray;
86 char* puserArray = userArray;
87 char* pseatArray = seatArray;
88 char* pnotifyKey = gSendNotifykey;
90 switch(gSendNotifyReason)
92 case pclNotifyStatus_deleted:
93 notifyReason = gDeleteSignal;
95 case pclNotifyStatus_created:
96 notifyReason = gCreateSignal;
98 case pclNotifyStatus_changed:
99 notifyReason = gChangeSignal;
106 if(notifyReason != NULL)
108 // dbus_bus_add_match is used for the notification mechanism,
109 // and this works only for type DBUS_TYPE_STRING as message arguments
110 // this is the reason to use string instead of integer types directly
111 snprintf(ldbidArray, DbusSubMatchSize, "%d", gSendNotifyLdbid);
112 snprintf(userArray, DbusSubMatchSize, "%d", gSendNotifyUserNo);
113 snprintf(seatArray, DbusSubMatchSize, "%d", gSendNotifySeatNo);
115 //printf("process_send_Notification_Signal => key: %s | lbid: %d | gUserNo: %d | gSeatNo: %d | gReason: %d \n", gNotifykey, gLdbid, gUserNo, gSeatNo, gReason);
116 message = dbus_message_new_signal("/org/genivi/persistence/adminconsumer", // const char *path,
117 "org.genivi.persistence.adminconsumer", // const char *interface,
118 notifyReason); // const char *name
120 ret = dbus_message_append_args(message, DBUS_TYPE_STRING, &pnotifyKey,
121 DBUS_TYPE_STRING, &pldbidArra,
122 DBUS_TYPE_STRING, &puserArray,
123 DBUS_TYPE_STRING, &pseatArray,
130 if(dbus_connection_send(conn, message, 0) == TRUE)
132 // Free the signal now we have finished with it
133 dbus_message_unref(message);
137 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> failed to send dbus message!!"));
142 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> E R R O R C O N E C T I O N NULL!!"));
147 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> ERROR dbus_message_append_args"));
152 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> ERROR invalid notification reason"));
158 void process_block_and_write_data_back(unsigned int requestID, unsigned int status)
160 // lock persistence data access
162 // sync data back to memory device
164 // send complete notification
165 pers_admin_service_data_sync_complete(requestID, status);
170 void process_prepare_shutdown(unsigned char requestId, unsigned int status)
173 //GvdbTable* resourceTable = NULL;
174 itzam_btree* resourceTable = NULL;
175 itzam_state state = ITZAM_FAILED;
180 // flush open files to disk
181 for(i=0; i<MaxPersHandle; i++)
184 if(gOpenFdArray[tmp] == FileOpen)
191 // close open gvdb persistence resource configuration table
192 for(i=0; i< PrctDbTableSize; i++)
194 resourceTable = get_resource_cfg_table_by_idx(i);
195 // dereference opend database
196 if(resourceTable != NULL)
198 state = itzam_btree_close(resourceTable);
199 if (state != ITZAM_OKAY)
201 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("process_prepare_shutdown => itzam_btree_close: Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
206 //close opend database
210 // unload custom client libraries
211 for(i=0; i<PersCustomLib_LastEntry; i++)
213 if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
215 // deinitialize plugin
216 gPersCustomFuncs[i].custom_plugin_deinit();
217 // close library handle
218 dlclose(gPersCustomFuncs[i].handle);
222 // notify lifecycle shutdown OK
223 send_prepare_shutdown_complete((int)requestId, (int)status);
228 void process_send_pas_request(DBusConnection* conn, unsigned int requestID, int status)
231 DBusPendingCall* pending = NULL;
232 dbus_error_init (&error);
235 DBusMessage* message = dbus_message_new_method_call("org.genivi.persistence.admin", // destination
236 "/org/genivi/persistence/admin", // path
237 "org.genivi.persistence.admin", // interface
238 "PersistenceAdminRequestCompleted"); // method
241 dbus_message_append_args(message, DBUS_TYPE_UINT32, &requestID,
242 DBUS_TYPE_INT32, &status,
247 //replyMsg = dbus_connection_send_with_reply_and_block(conn, message, gTimeoutMs, &error);
248 dbus_connection_send_with_reply(conn, // the connection
249 message, // the message to write
251 gTimeoutMs); // timeout in milliseconds or -1 for default
253 dbus_connection_flush(conn);
255 if(!dbus_pending_call_set_notify(pending, msg_pending_func, "PersistenceAdminRequestCompleted", NULL))
257 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_pas_request => dbus_pending_call_set_notify: FAILED\n"));
259 dbus_pending_call_unref(pending);
263 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request => ERROR: Invalid connection") );
265 dbus_message_unref(message);
269 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request => ERROR: Invalid message") );
274 void process_send_pas_register(DBusConnection* conn, int regType, int notificationFlag)
277 dbus_error_init (&error);
278 DBusPendingCall* pending = NULL;
283 method = "UnRegisterPersAdminNotification";
284 else if(regType == 1)
285 method = "RegisterPersAdminNotification";
289 const char* objName = "/org/genivi/persistence/adminconsumer";
290 const char* busName = dbus_bus_get_unique_name(conn);
294 DBusMessage* message = dbus_message_new_method_call("org.genivi.persistence.admin", // destination
295 "/org/genivi/persistence/admin", // path
296 "org.genivi.persistence.admin", // interface
301 dbus_message_append_args(message, DBUS_TYPE_STRING, &busName, // bus name
302 DBUS_TYPE_STRING, &objName,
303 DBUS_TYPE_INT32, ¬ificationFlag,
304 DBUS_TYPE_UINT32, &gTimeoutMs,
307 dbus_connection_send_with_reply(conn, // the connection
308 message, // the message to write
310 gTimeoutMs); // timeout in milliseconds or -1 for default
312 dbus_connection_flush(conn);
314 if(!dbus_pending_call_set_notify(pending, msg_pending_func, method, NULL))
316 printf("process_send_pas_register => dbus_pending_call_set_notify: FAILED\n");
318 dbus_pending_call_unref(pending);
322 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register => ERROR: Invalid message") );
324 dbus_message_unref(message);
328 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register => ERROR: Invalid busname") );
333 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register => ERROR: Invalid connection") );
338 void process_send_lifecycle_register(DBusConnection* conn, int regType, int shutdownMode)
343 dbus_error_init (&error);
348 method = "RegisterShutdownClient";
349 else if(regType == 0)
350 method = "UnRegisterShutdownClient";
354 const char* objName = "/org/genivi/NodeStateManager/LifeCycleConsumer";
355 const char* busName = dbus_bus_get_unique_name(conn);
357 DBusMessage* message = dbus_message_new_method_call("org.genivi.NodeStateManager", // destination
358 "/org/genivi/NodeStateManager/Consumer", // path
359 "org.genivi.NodeStateManager.Consumer", // interface
363 if(regType == 1) // register
365 dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,
366 DBUS_TYPE_STRING, &objName,
367 DBUS_TYPE_UINT32, &shutdownMode,
368 DBUS_TYPE_UINT32, &gTimeoutMs, DBUS_TYPE_INVALID);
372 dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,
373 DBUS_TYPE_STRING, &objName,
374 DBUS_TYPE_UINT32, &shutdownMode, DBUS_TYPE_INVALID);
379 if(!dbus_connection_send(conn, message, 0))
381 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => Access denied"), DLT_STRING(error.message) );
384 dbus_connection_flush(conn);
388 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => ERROR: Invalid connection"));
391 dbus_message_unref(message);
395 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => ERROR: Invalid message"));
400 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => ERROR: connection isn NULL"));
406 void process_send_lifecycle_request(DBusConnection* conn, int requestId, int status)
410 dbus_error_init (&error);
414 DBusMessage* message = dbus_message_new_method_call("org.genivi.NodeStateManager", // destination
415 "/org/genivi/NodeStateManager/Consumer", // path
416 "org.genivi.NodeStateManager.Consumer", // interface
417 "LifecycleRequestComplete"); // method
420 dbus_message_append_args(message, DBUS_TYPE_INT32, &requestId,
421 DBUS_TYPE_INT32, &status,
426 if(!dbus_connection_send(conn, message, 0))
428 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => Access denied"), DLT_STRING(error.message) );
432 dbus_connection_flush(conn);
436 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => ERROR: Invalid connection"));
439 dbus_message_unref(message);
443 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => ERROR: Invalid message"));
449 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => ERROR: connection isn NULL"));
456 void msg_pending_func(DBusPendingCall *call, void *data)
460 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(gDLTContext, 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);