Added use of default data for files; added test data that can be used by PAS installa...
[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 "persistence_client_library_dbus_cmd.h"
20
21 #include "persistence_client_library_handle.h"
22 #include "persistence_client_library_custom_loader.h"
23 #include "persistence_client_library_pas_interface.h"
24
25 #include "persistence_client_library_data_organization.h"
26 #include "persistence_client_library_db_access.h"
27
28 #include <dlfcn.h>
29 #include <errno.h>
30
31
32 // function prototype
33 void msg_pending_func(DBusPendingCall *call, void *data);
34
35
36
37 void process_reg_notification_signal(DBusConnection* conn)
38 {
39    char ruleChanged[DbusMatchRuleSize] = {0};
40    char ruleDeleted[DbusMatchRuleSize] = {0};
41    char ruleCreated[DbusMatchRuleSize] = {0};
42
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             gNotifykey, gNotifyLdbid, gNotifyUserNo, gNotifySeatNo);
47
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             gNotifykey, gNotifyLdbid, gNotifyUserNo, gNotifySeatNo);
52
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             gNotifykey, gNotifyLdbid, gNotifyUserNo, gNotifySeatNo);
57
58    if(gNotifyPolicy == Notify_register)
59    {
60       dbus_bus_add_match(conn, ruleChanged, NULL);
61       dbus_bus_add_match(conn, ruleDeleted, NULL);
62       dbus_bus_add_match(conn, ruleCreated, NULL);
63    }
64    else if(gNotifyPolicy == Notify_unregister)
65    {
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    }
70
71    dbus_connection_flush(conn);  // flush the connection to add the match
72 }
73
74
75
76 void process_send_notification_signal(DBusConnection* conn)
77 {
78    dbus_bool_t ret;
79    DBusMessage* message;
80    const char* notifyReason = NULL;
81
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 = gNotifykey;
89
90    switch(gNotifyReason)
91    {
92       case pclNotifyStatus_deleted:
93          notifyReason = gDeleteSignal;
94          break;
95       case  pclNotifyStatus_created:
96          notifyReason = gCreateSignal;
97          break;
98       case pclNotifyStatus_changed:
99          notifyReason = gChangeSignal;
100          break;
101       default:
102          notifyReason = NULL;
103          break;
104    }
105
106    if(notifyReason != NULL)
107    {
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, "%u", gNotifyLdbid);
112       snprintf(userArray,  DbusSubMatchSize, "%u", gNotifyUserNo);
113       snprintf(seatArray,  DbusSubMatchSize, "%u", gNotifySeatNo);
114
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
119
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,
124                                               DBUS_TYPE_INVALID);
125       if(ret == TRUE)
126       {
127          // Send the signal
128          if(conn != NULL)
129          {
130             if(dbus_connection_send(conn, message, 0) == TRUE)
131             {
132                // Free the signal now we have finished with it
133                dbus_message_unref(message);
134             }
135             else
136             {
137                DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> failed to send dbus message!!"));
138             }
139          }
140          else
141          {
142             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!!"));
143          }
144       }
145       else
146       {
147          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> ERROR dbus_message_append_args"));
148       }
149    }
150    else
151    {
152       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_Notification_Signal ==> ERROR invalid notification reason"));
153    }
154 }
155
156
157
158 void process_block_and_write_data_back(unsigned int requestID, unsigned int status)
159 {
160    (void)requestID;
161    (void)status;
162    // lock persistence data access
163    pers_lock_access();
164    // sync data back to memory device
165    pers_data_sync();
166    // send complete notification
167    //pers_admin_service_data_sync_complete(requestID, status);
168 }
169
170
171
172 void process_prepare_shutdown(int complete)
173 {
174    int i = 0, rval = 0;
175
176    // block write
177    pers_lock_access();
178
179    // flush open files to disk
180    for(i=0; i<MaxPersHandle; i++)
181    {
182       if(gOpenFdArray[i] == FileOpen)
183       {
184          fsync(i);
185
186 #if USE_FILECACHE
187          if(complete == Shutdown_Full)
188          {
189                 rval = pfcCloseFile(i);
190          }
191          else if(complete == Shutdown_Partial)
192          {
193                 pfcWriteBackAndSync(i);
194          }
195 #else
196          if(complete == Shutdown_Full)
197          {
198                 rval = close(i);
199          }
200          else if(complete == Shutdown_Partial)
201          {
202                 fsync(i);
203          }
204 #endif
205          if(rval == -1)
206          {
207                 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_prepare_shutdown => failed to close file: "), DLT_STRING(strerror(errno)) );
208          }
209
210       }
211    }
212
213    // close all opend rct
214    pers_rct_close_all();
215
216    // close opend database
217    database_close_all();
218
219    if(complete > 0)
220    {
221         close_all_persistence_handle();
222    }
223
224
225    if(complete > 0)
226    {
227                 // unload custom client libraries
228                 for(i=0; i<PersCustomLib_LastEntry; i++)
229                 {
230                         if(gPersCustomFuncs[i].custom_plugin_deinit != NULL)
231                         {
232                                 // deinitialize plugin
233                                 gPersCustomFuncs[i].custom_plugin_deinit();
234                                 // close library handle
235                                 dlclose(gPersCustomFuncs[i].handle);
236
237                                 invalidate_custom_plugin(i);
238                         }
239                 }
240    }
241 }
242
243
244
245 void process_send_pas_request(DBusConnection* conn, unsigned int requestID, int status)
246 {
247    DBusError error;
248    dbus_error_init (&error);
249
250    DBusMessage* message = dbus_message_new_method_call("org.genivi.persistence.admin",       // destination
251                                                       "/org/genivi/persistence/admin",       // path
252                                                        "org.genivi.persistence.admin",       // interface
253                                                        "PersistenceAdminRequestCompleted");  // method
254    if(conn != NULL)
255    {
256       if(message != NULL)
257       {
258          dbus_message_append_args(message, DBUS_TYPE_UINT32, &requestID,
259                                            DBUS_TYPE_INT32,  &status,
260                                            DBUS_TYPE_INVALID);
261
262          if(!dbus_connection_send(conn, message, 0))
263          {
264             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => Access denied"), DLT_STRING(error.message) );
265          }
266
267          dbus_connection_flush(conn);
268          dbus_message_unref(message);
269       }
270       else
271       {
272          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request => ERROR: Invalid message") );
273       }
274    }
275    else
276    {
277       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_request => ERROR: Invalid connection") );
278    }
279 }
280
281
282 void process_send_pas_register(DBusConnection* conn, int regType, int notificationFlag)
283 {
284    DBusError error;
285    dbus_error_init (&error);
286    DBusPendingCall* pending = NULL;
287
288    char* method = NULL;
289
290    if(regType == 0)
291       method = "UnRegisterPersAdminNotification";
292    else if(regType == 1)
293       method = "RegisterPersAdminNotification";
294
295    if(conn != NULL)
296    {
297       const char* objName = "/org/genivi/persistence/adminconsumer";
298       const char* busName = dbus_bus_get_unique_name(conn);
299
300       if(busName != NULL)
301       {
302          DBusMessage* message = dbus_message_new_method_call("org.genivi.persistence.admin",    // destination
303                                                             "/org/genivi/persistence/admin",    // path
304                                                              "org.genivi.persistence.admin",    // interface
305                                                              method);                           // method
306
307          if(message != NULL)
308          {
309             dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,  // bus name
310                                               DBUS_TYPE_STRING, &objName,
311                                               DBUS_TYPE_INT32,  &notificationFlag,
312                                               DBUS_TYPE_UINT32, &gTimeoutMs,
313                                               DBUS_TYPE_INVALID);
314
315             dbus_connection_send_with_reply(conn,           //    the connection
316                                             message,        // the message to write
317                                             &pending,       // pending
318                                             gTimeoutMs);    // timeout in milliseconds or -1 for default
319
320             dbus_connection_flush(conn);
321
322             if(!dbus_pending_call_set_notify(pending, msg_pending_func, method, NULL))
323             {
324                DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_send_pas_register => dbus_pending_call_set_notify: FAILED\n") );
325             }
326             dbus_pending_call_unref(pending);
327          }
328          else
329          {
330             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register =>  ERROR: Invalid message") );
331          }
332          dbus_message_unref(message);
333       }
334       else
335       {
336          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register =>  ERROR: Invalid busname") );
337       }
338    }
339    else
340    {
341       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_pas_register =>  ERROR: Invalid connection") );
342    }
343 }
344
345
346 void process_send_lifecycle_register(DBusConnection* conn, int regType, int shutdownMode)
347 {
348    DBusError error;
349    dbus_error_init (&error);
350
351    char* method = NULL;
352
353    if(regType == 1)
354       method = "RegisterShutdownClient";
355    else if(regType == 0)
356       method = "UnRegisterShutdownClient";
357
358    if(conn != NULL)
359    {
360       const char* objName = "/org/genivi/NodeStateManager/LifeCycleConsumer";
361       const char* busName = dbus_bus_get_unique_name(conn);
362
363       DBusMessage* message = dbus_message_new_method_call("org.genivi.NodeStateManager",           // destination
364                                                           "/org/genivi/NodeStateManager/Consumer", // path
365                                                           "org.genivi.NodeStateManager.Consumer",  // interface
366                                                           method);                                 // method
367       if(message != NULL)
368       {
369          if(regType == 1)   // register
370          {
371             dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,
372                                               DBUS_TYPE_STRING, &objName,
373                                               DBUS_TYPE_UINT32, &shutdownMode,
374                                               DBUS_TYPE_UINT32, &gTimeoutMs, DBUS_TYPE_INVALID);
375          }
376          else           // unregister
377          {
378             dbus_message_append_args(message, DBUS_TYPE_STRING, &busName,
379                                               DBUS_TYPE_STRING, &objName,
380                                               DBUS_TYPE_UINT32, &shutdownMode, DBUS_TYPE_INVALID);
381          }
382
383                    if(!dbus_connection_send(conn, message, 0))
384                    {
385                       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => Access denied"), DLT_STRING(error.message) );
386                    }
387                    dbus_connection_flush(conn);
388          dbus_message_unref(message);
389       }
390       else
391       {
392          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => ERROR: Invalid message"));
393       }
394    }
395    else
396    {
397       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_register => ERROR: connection isn NULL"));
398    }
399 }
400
401
402
403 void process_send_lifecycle_request(DBusConnection* conn, int requestId, int status)
404 {
405    DBusError error;
406    dbus_error_init (&error);
407
408    if(conn != NULL)
409    {
410       DBusMessage* message = dbus_message_new_method_call("org.genivi.NodeStateManager",           // destination
411                                                          "/org/genivi/NodeStateManager/Consumer",  // path
412                                                           "org.genivi.NodeStateManager.Consumer",  // interface
413                                                           "LifecycleRequestComplete");             // method
414       if(message != NULL)
415       {
416          dbus_message_append_args(message, DBUS_TYPE_INT32, &requestId,
417                                            DBUS_TYPE_INT32, &status,
418                                            DBUS_TYPE_INVALID);
419
420
421          if(!dbus_connection_send(conn, message, 0))
422          {
423             DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => Access denied"), DLT_STRING(error.message) );
424           }
425
426           dbus_connection_flush(conn);
427           dbus_message_unref(message);
428       }
429       else
430       {
431          DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => ERROR: Invalid message"));
432       }
433    }
434    else
435    {
436       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("send_lifecycle_request => ERROR: connection isn NULL"));
437    }
438 }
439
440
441
442 void msg_pending_func(DBusPendingCall *call, void *data)
443 {
444    int replyArg = -1;
445    DBusError err;
446    dbus_error_init(&err);
447
448    (void)data;
449
450    DBusMessage *message = dbus_pending_call_steal_reply(call);
451
452    if (dbus_set_error_from_message(&err, message))
453    {
454       DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("msg_pending_func ==> Access denied") );
455    }
456    else
457    {
458       //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("msg_pending_func ==> UNlock mutex") );
459       dbus_message_get_args(message, &err, DBUS_TYPE_INT32, &replyArg, DBUS_TYPE_INVALID);
460    }
461
462    gDbusPendingRvalue = replyArg;   // set the return value
463    dbus_message_unref(message);
464
465    // unlock the mutex because we have received the reply to the dbus message
466    pthread_mutex_unlock(&gDbusPendingRegMtx);
467 }
468
469
470
471