Initial packaging.
[profile/ivi/persistence-client-library.git] / src / persistence_client_library_dbus_cmd.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_cmd.c
13  * @ingroup        Persistence client library
14  * @author         Ingo Huerner
15  * @brief          Implementation of the persistence client library dbus commands.
16  * @see
17  */
18
19 #include <errno.h>
20 #include <dlfcn.h>                                                                                                                              /* For dlclose() */
21 #include "persistence_client_library_dbus_cmd.h"
22
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"
29
30 #if USE_FILECACHE
31    #include <persistence_file_cache.h>
32
33
34         /**
35          * write back from cache to non volatile memory device
36          * ATTENTION:
37          * THIS FUNCTION IS NOT INTENDED TO BE USED BY A NORMAL APPLICATION.
38          * ONLY SPECIAL APPLICATION ARE ALLOWED TO USING USE THIS FUNCTION
39          **/
40          extern int pfcWriteBackAndSync(int handle);
41 #endif
42
43
44 // function prototype
45 void msg_pending_func(DBusPendingCall *call, void *data);
46
47
48
49 void process_reg_notification_signal(DBusConnection* conn, unsigned int notifyLdbid, unsigned int notifyUserNo,
50                                                            unsigned int notifySeatNo, unsigned int notifyPolicy, const char* notifyKey)
51 {
52    char ruleChanged[DbusMatchRuleSize] = {[0 ... DbusMatchRuleSize-1] = 0};
53    char ruleDeleted[DbusMatchRuleSize] = {[0 ... DbusMatchRuleSize-1] = 0};
54    char ruleCreated[DbusMatchRuleSize] = {[0 ... DbusMatchRuleSize-1] = 0};
55
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);
60
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);
65
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);
70
71    if(notifyPolicy == Notify_register)
72    {
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));
77    }
78    else if(notifyPolicy == Notify_unregister)
79    {
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));
84    }
85
86    dbus_connection_flush(conn);  // flush the connection to add the match
87 }
88
89
90
91 void process_send_notification_signal(DBusConnection* conn, unsigned int notifyLdbid, unsigned int notifyUserNo,
92                                                             unsigned int notifySeatNo, unsigned int notifyReason, const char* notifyKey)
93 {
94    dbus_bool_t ret;
95    DBusMessage* message;
96    const char* notifyReasonString = NULL;
97
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;
105
106    switch(notifyReason)
107    {
108       case pclNotifyStatus_deleted:
109         notifyReasonString = gDeleteSignal;
110          break;
111       case  pclNotifyStatus_created:
112         notifyReasonString = gCreateSignal;
113          break;
114       case pclNotifyStatus_changed:
115         notifyReasonString = gChangeSignal;
116          break;
117       default:
118         notifyReasonString = NULL;
119          break;
120    }
121
122    if(notifyReasonString != NULL)
123    {
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);
130
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,
134                                         notifyReasonString);
135
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,
140                                               DBUS_TYPE_INVALID);
141       if(ret == TRUE)
142       {
143          // Send the signal
144          if(conn != NULL)
145          {
146             if(dbus_connection_send(conn, message, 0) == TRUE)
147             {
148                // Free the signal now we have finished with it
149                dbus_message_unref(message);
150             }
151             else
152             {
153                DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal - failed to send dbus message!!"));
154             }
155          }
156          else
157          {
158             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal - C O N E C T I O N  NULL!!"));
159          }
160       }
161       else
162       {
163          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal - dbus_message_append_args"));
164       }
165    }
166    else
167    {
168       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal - invalid notification reason"));
169    }
170 }
171
172
173
174 void process_block_and_write_data_back(unsigned int requestID, unsigned int status)
175 {
176    (void)requestID;
177    (void)status;
178    // lock persistence data access
179    pers_lock_access();
180    // sync data back to memory device
181 }
182
183
184
185 void process_prepare_shutdown(int complete)
186 {
187    int i = 0, rval = 0;
188
189    DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("process_prepare_shutdown - writing down all changed data and closing all handles"));
190
191    // block write
192    pers_lock_access();
193
194    // flush open files to disk
195    for(i=0; i<MaxPersHandle; i++)
196    {
197       if(gOpenFdArray[i] == FileOpen)
198       {
199
200 #if USE_FILECACHE
201          if(complete == Shutdown_Full)
202          {
203                 rval = pfcCloseFile(i);
204          }
205          else if(complete == Shutdown_Partial)
206          {
207                 pfcWriteBackAndSync(i);
208          }
209 #else
210          if(complete == Shutdown_Full)
211          {
212                 rval = close(i);
213          }
214          else if(complete == Shutdown_Partial)
215          {
216                 fsync(i);
217          }
218 #endif
219          if(rval == -1)
220          {
221                 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_prepare_shutdown - failed to close file: "), DLT_STRING(strerror(errno)) );
222          }
223
224       }
225    }
226
227    // close all opend rct
228    pers_rct_close_all();
229
230    // close opend database
231    database_close_all();
232
233    if(complete > 0)
234    {
235         close_all_persistence_handle();
236    }
237
238
239    if(complete > 0)
240    {
241                 // unload custom client libraries
242                 for(i=0; i<PersCustomLib_LastEntry; i++)
243                 {
244                         if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
245                         {
246                                 // deinitialize plugin
247                                 gPersCustomFuncs[i].custom_plugin_deinit();
248                                 // close library handle
249                                 dlclose(gPersCustomFuncs[i].handle);
250
251                                 invalidate_custom_plugin(i);
252                         }
253                 }
254    }
255 }
256
257
258
259 void process_send_pas_request(DBusConnection* conn, unsigned int requestID, int status)
260 {
261    DBusError error;
262    dbus_error_init (&error);
263
264    DBusMessage* message = dbus_message_new_method_call(gDbusPersAdminInterface,                         // destination
265                                                               gDbusPersAdminPath,               // path
266                                                               gDbusPersAdminInterface,          // interface
267                                                        "PersistenceAdminRequestCompleted");  // method
268    if(conn != NULL)
269    {
270       if(message != NULL)
271       {
272          dbus_message_append_args(message, DBUS_TYPE_UINT32, &requestID,
273                                            DBUS_TYPE_INT32,  &status,
274                                            DBUS_TYPE_INVALID);
275
276          if(!dbus_connection_send(conn, message, 0))
277          {
278             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register - Access denied"), DLT_STRING(error.message) );
279          }
280
281          dbus_connection_flush(conn);
282          dbus_message_unref(message);
283       }
284       else
285       {
286          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request - Invalid message") );
287       }
288    }
289    else
290    {
291       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request - Invalid connection") );
292    }
293 }
294
295
296 void process_send_pas_register(DBusConnection* conn, int regType, int notificationFlag)
297 {
298    DBusError error;
299    dbus_error_init (&error);
300    DBusPendingCall* pending = NULL;
301
302    char* method = NULL;
303
304    if(regType == 0)
305       method = "UnRegisterPersAdminNotification";
306    else if(regType == 1)
307       method = "RegisterPersAdminNotification";
308
309    if(conn != NULL)
310    {
311       const char* busName = dbus_bus_get_unique_name(conn);
312
313       if(busName != NULL)
314       {
315          DBusMessage* message = dbus_message_new_method_call(gDbusPersAdminInterface,   // destination
316                                                                       gDbusPersAdminPath,               // path
317                                                                       gDbusPersAdminInterface,   // interface
318                                                              method);               // method
319
320          if(message != NULL)
321          {
322             dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,  // bus name
323                                               DBUS_TYPE_STRING, &gPersAdminConsumerPath,
324                                               DBUS_TYPE_INT32,  &notificationFlag,
325                                               DBUS_TYPE_UINT32, &gTimeoutMs,
326                                               DBUS_TYPE_INVALID);
327
328             dbus_connection_send_with_reply(conn,           //    the connection
329                                             message,        // the message to write
330                                             &pending,       // pending
331                                             gTimeoutMs);    // timeout in milliseconds or -1 for default
332
333             dbus_connection_flush(conn);
334
335             if(!dbus_pending_call_set_notify(pending, msg_pending_func, method, NULL))
336             {
337                DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_pas_register - dbus_pending_call_set_notify: FAILED\n") );
338             }
339             dbus_pending_call_unref(pending);
340          }
341          else
342          {
343             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register - Invalid message") );
344          }
345          dbus_message_unref(message);
346       }
347       else
348       {
349          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register - Invalid busname") );
350       }
351    }
352    else
353    {
354       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register - Invalid connection") );
355    }
356 }
357
358
359 void process_send_lifecycle_register(DBusConnection* conn, int regType, int shutdownMode)
360 {
361    DBusError error;
362    dbus_error_init (&error);
363
364    char* method = NULL;
365
366    if(regType == 1)
367       method = "RegisterShutdownClient";
368    else if(regType == 0)
369       method = "UnRegisterShutdownClient";
370
371    if(conn != NULL)
372    {
373       const char* busName = dbus_bus_get_unique_name(conn);
374
375       DBusMessage* message = dbus_message_new_method_call(gDbusLcConsDest,           // destination
376                                                               gDbusLcCons, // path
377                                                               gDbusLcInterface,  // interface
378                                                           method);                                 // method
379       if(message != NULL)
380       {
381          if(regType == 1)   // register
382          {
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);
387          }
388          else           // unregister
389          {
390             dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,
391                                               DBUS_TYPE_STRING, &gDbusLcConsPath,
392                                               DBUS_TYPE_UINT32, &shutdownMode, DBUS_TYPE_INVALID);
393          }
394
395                    if(!dbus_connection_send(conn, message, 0))
396                    {
397                       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register - Access denied"), DLT_STRING(error.message) );
398                    }
399                    dbus_connection_flush(conn);
400          dbus_message_unref(message);
401       }
402       else
403       {
404          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register - Invalid message"));
405       }
406    }
407    else
408    {
409       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register - connection isn NULL"));
410    }
411 }
412
413
414
415 void process_send_lifecycle_request(DBusConnection* conn, unsigned int requestId, unsigned int status)
416 {
417    DBusError error;
418    dbus_error_init (&error);
419
420    if(conn != NULL)
421    {
422       DBusMessage* message = dbus_message_new_method_call(gDbusLcConsDest,           // destination
423                                                               gDbusLcCons,  // path
424                                                               gDbusLcInterface,  // interface
425                                                           "LifecycleRequestComplete");             // method
426       if(message != NULL)
427       {
428          dbus_message_append_args(message, DBUS_TYPE_INT32, &requestId,
429                                            DBUS_TYPE_INT32, &status,
430                                            DBUS_TYPE_INVALID);
431
432
433          if(!dbus_connection_send(conn, message, 0))
434          {
435             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request - Access denied"), DLT_STRING(error.message) );
436           }
437
438           dbus_connection_flush(conn);
439           dbus_message_unref(message);
440       }
441       else
442       {
443          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request - Invalid message"));
444       }
445    }
446    else
447    {
448       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request - connection isn NULL"));
449    }
450 }
451
452
453
454 void msg_pending_func(DBusPendingCall *call, void *data)
455 {
456    int replyArg = -1;
457    DBusError err;
458    dbus_error_init(&err);
459
460    (void)data;
461
462    DBusMessage *message = dbus_pending_call_steal_reply(call);
463
464    if (dbus_set_error_from_message(&err, message))
465    {
466       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msg_pending_func - Access denied") );
467    }
468    else
469    {
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);
472    }
473
474    gDbusPendingRvalue = replyArg;   // set the return value
475    dbus_message_unref(message);
476
477    // unlock the mutex because we have received the reply to the dbus message
478    pthread_mutex_unlock(&gDbusPendingRegMtx);
479 }
480
481
482
483