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_data_access.c
13 * @ingroup Persistence client library
14 * @author Ingo Huerner
15 * @brief Implementation of persistence database access
16 * Library provides an API to access persistent data
20 #include "persistence_client_library_db_access.h"
21 #include "persistence_client_library_custom_loader.h"
22 #include "persistence_client_library_dbus_service.h"
23 #include "persistence_client_library_prct_access.h"
25 #include <persComErrors.h>
26 #include <persComDataOrg.h>
27 #include <persComDbAccess.h>
29 #include <dbus/dbus.h>
38 static int gHandlesDB[DbTableSize][PersistencePolicy_LastEntry];
39 static int gHandlesDBCreated[DbTableSize][PersistencePolicy_LastEntry] = { {0} };
43 int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, unsigned int reason);
46 char* pers_get_raw_key(char *key)
51 temp = strrchr(key, (int)'/');
62 int pers_db_open_default(const char* dbPath, PersDefaultType_e DefaultType)
65 char path[DbPathMaxLen] = {0};
67 if (PersDefaultType_Configurable == DefaultType)
69 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gLocalConfigurableDefault);
71 else if (PersDefaultType_Factory== DefaultType)
73 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gLocalFactoryDefault);
77 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open_default ==> unknown DefaultType"));
81 if (EPERS_COMMON != ret)
83 ret = persComDbOpen(path, 0);
87 DLT_LOG(gPclDLTContext, DLT_LOG_WARN,
88 DLT_STRING("pers_db_open_default() -> persComDbOpen() -> problem open db: "),
90 DLT_STRING(" Code: "),
99 int pers_get_defaults(char* dbPath, char* key, unsigned char* buffer, unsigned int buffer_size, PersGetDefault_e job)
101 PersDefaultType_e i = PersDefaultType_Configurable;
102 int handleDefaultDB = -1;
103 int read_size = EPERS_NOKEY;
104 char dltMessage[DbPathMaxLen] = {0};
106 key = pers_get_raw_key(key); /* We need only the raw key without a prefixed '/node/' or '/user/1/seat/0' etc... */
108 for(i=0; i<PersDefaultType_LastEntry; i++)
110 handleDefaultDB = pers_db_open_default(dbPath, i);
111 if(handleDefaultDB >= 0)
113 if (PersGetDefault_Data == job)
115 read_size = persComDbReadKey(handleDefaultDB, key, (char*)buffer, buffer_size);
117 else if (PersGetDefault_Size == job)
119 read_size = persComDbGetKeySize(handleDefaultDB, key);
123 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_get_defaults ==> unknown job"));
127 if (0 > persComDbClose(handleDefaultDB))
129 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_get_defaults ==> persComDbClose returned with error"));
132 if(read_size < 0) // check read_size
134 if(PERS_COM_ERR_NOT_FOUND == read_size)
136 read_size = EPERS_NOKEY;
139 else /* read_size >= 0 --> default value found */
141 if (PersDefaultType_Configurable == i)
143 snprintf(dltMessage, DbPathMaxLen, "%s%s", dbPath, gLocalConfigurableDefault);
145 if (PersDefaultType_Factory == i)
147 snprintf(dltMessage, DbPathMaxLen, "%s%s", dbPath, gLocalFactoryDefault);
149 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Default data will be used for Key"),
152 DLT_STRING(dltMessage));
160 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Default data not available for Key"),
170 int database_get(PersistenceInfo_s* info, const char* dbPath)
175 // create array index: index is a combination of resource config table type and group
176 arrayIdx = info->configKey.storage + info->context.ldbid ;
178 //if(arrayIdx <= DbTableSize)
179 if(arrayIdx < DbTableSize)
181 if(gHandlesDBCreated[arrayIdx][info->configKey.policy] == 0)
184 char path[DbPathMaxLen] = {0};
186 if(PersistencePolicy_wt == info->configKey.policy)
188 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gLocalWt);
190 else if(PersistencePolicy_wc == info->configKey.policy)
192 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gLocalCached);
201 handleDB = persComDbOpen(path, 0x01);
204 gHandlesDB[arrayIdx][info->configKey.policy] = handleDB ;
205 gHandlesDBCreated[arrayIdx][info->configKey.policy] = 1;
209 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_get ==> persComDbOpen() failed"));
214 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_get ==> wrong policy! Cannot extend dbPath wit database."));
219 handleDB = gHandlesDB[arrayIdx][info->configKey.policy];
224 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_get ==> invalid storage type"), DLT_STRING(dbPath));
233 void database_close(PersistenceInfo_s* info)
235 int arrayIdx = info->configKey.storage + info->context.ldbid;
237 if(info->configKey.storage <= PersistenceStorage_shared )
239 int iErrorCode = persComDbClose(gHandlesDB[arrayIdx][info->configKey.policy]) ;
242 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_close ==> persComDbClose() failed"));
246 gHandlesDBCreated[arrayIdx][info->configKey.policy] = 0;
251 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_close ==> invalid storage type"), DLT_INT(info->context.ldbid ));
255 void database_close_all()
259 for(i=0; i<DbTableSize; i++)
261 // close write cached database
262 if(gHandlesDBCreated[i][PersistencePolicy_wc] == 1)
264 int iErrorCode = persComDbClose(gHandlesDB[i][PersistencePolicy_wc]);
267 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_close_all => failed to close db => persComDbClose"));
271 gHandlesDBCreated[i][PersistencePolicy_wc] = 0;
275 // close write through database
276 if(gHandlesDBCreated[i][PersistencePolicy_wt] == 1)
278 int iErrorCode = persComDbClose(gHandlesDB[i][PersistencePolicy_wt]);
281 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_close_all => failed to close db => persComDbClose"));
285 gHandlesDBCreated[i][PersistencePolicy_wt] = 0;
293 int persistence_get_data(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
296 int ret_defaults = -1;
298 if( PersistenceStorage_shared == info->configKey.storage
299 || PersistenceStorage_local == info->configKey.storage)
301 int handleDB = database_get(info, dbPath);
304 read_size = persComDbReadKey(handleDB, key, (char*)buffer, buffer_size) ;
307 read_size = pers_get_defaults(dbPath, key, buffer, buffer_size, PersGetDefault_Data); /* 0 ==> Get data */
311 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
313 int idx = custom_client_name_to_id(dbPath, 1);
314 char workaroundPath[128]; // workaround, because /sys/ can not be accessed on host!!!!
315 snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath );
317 if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_data != NULL) )
319 char pathKeyString[128] = {0};
320 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
322 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
326 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
328 read_size = gPersCustomFuncs[idx].custom_plugin_get_data(pathKeyString, (char*)buffer, buffer_size);
332 read_size = EPERS_NOPLUGINFUNCT;
335 if (1 > read_size) /* Try to get default values */
337 info->configKey.policy = PersistencePolicy_wc; /* Set the policy */
338 info->configKey.type = PersistenceResourceType_key; /* Set the type */
339 (void)get_db_path_and_key(info, key, NULL, dbPath);
340 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Plugin data not available. Try to get default data of key:"),
342 ret_defaults = pers_get_defaults(dbPath, key, buffer, buffer_size, PersGetDefault_Data);
343 if (0 < ret_defaults)
345 read_size = ret_defaults;
354 int persistence_set_data(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
358 if( PersistenceStorage_local == info->configKey.storage
359 || PersistenceStorage_shared == info->configKey.storage )
364 handleDB = database_get(info, dbPath);
367 write_size = persComDbWriteKey(handleDB, key, (char*)buffer, buffer_size) ;
370 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_set_data ==> persComDbWriteKey() failure"));
374 if(PersistenceStorage_shared == info->configKey.storage)
376 int rval = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
379 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_set_data ==> failed to send notification signal"));
388 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_set_data ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
389 write_size = EPERS_NOPRCTABLE;
392 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
394 int idx = custom_client_name_to_id(dbPath, 1);
395 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_set_data != NULL) )
397 char pathKeyString[128] = {0};
398 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
400 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
404 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
406 write_size = gPersCustomFuncs[idx].custom_plugin_set_data(pathKeyString, (char*)buffer, buffer_size);
408 if ((0 < write_size) && ((unsigned int)write_size == buffer_size)) /* Check return value and send notification if OK */
410 int rval = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
413 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_set_data ==> failed to send notification signal"));
420 write_size = EPERS_NOPLUGINFUNCT;
428 int persistence_get_data_size(char* dbPath, char* key, PersistenceInfo_s* info)
431 int ret_defaults = -1;
433 if( PersistenceStorage_shared == info->configKey.storage
434 || PersistenceStorage_local == info->configKey.storage)
436 int handleDB = database_get(info, dbPath);
439 read_size = persComDbGetKeySize(handleDB, key);
442 read_size = pers_get_defaults(dbPath, key, NULL, 0, PersGetDefault_Size);
446 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
448 int idx = custom_client_name_to_id(dbPath, 1);
449 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_size != NULL) )
451 char pathKeyString[128] = {0};
452 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
454 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
458 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
460 read_size = gPersCustomFuncs[idx].custom_plugin_get_size(pathKeyString);
464 read_size = EPERS_NOPLUGINFUNCT;
469 info->configKey.policy = PersistencePolicy_wc; /* Set the policy */
470 info->configKey.type = PersistenceResourceType_key; /* Set the type */
471 (void)get_db_path_and_key(info, key, NULL, dbPath);
472 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Plugin data not available. Try to get size of default data for key:"),
474 ret_defaults = pers_get_defaults(dbPath, key, NULL, 0, PersGetDefault_Size);
475 if (0 < ret_defaults)
477 read_size = ret_defaults;
486 int persistence_delete_data(char* dbPath, char* key, PersistenceInfo_s* info)
489 if(PersistenceStorage_custom != info->configKey.storage)
491 int handleDB = database_get(info, dbPath);
494 ret = persComDbDeleteKey(handleDB, key) ;
497 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_delete_data => persComDbDeleteKey failed: "), DLT_STRING(key));
498 if(PERS_COM_ERR_NOT_FOUND == ret)
504 ret = EPERS_DB_ERROR_INTERNAL ;
508 if(PersistenceStorage_shared == info->configKey.storage)
510 pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
515 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_delete_data ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
516 ret = EPERS_NOPRCTABLE;
519 else // custom storage implementation via custom library
521 int idx = custom_client_name_to_id(dbPath, 1);
522 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_delete_data != NULL) )
524 char pathKeyString[128] = {0};
525 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
527 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
531 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
533 ret = gPersCustomFuncs[idx].custom_plugin_delete_data(pathKeyString);
535 if(0 <= ret) /* Check return value and send notification if OK */
537 pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
542 ret = EPERS_NOPLUGINFUNCT;
549 int persistence_notify_on_change(const char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no,
550 pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
554 if(regPolicy < Notify_lastEntry)
556 snprintf(gNotifykey, DbKeyMaxLen, "%s", key);
557 gNotifyLdbid = ldbid; // to do: pass correct ==> JUST TESTING!!!!
558 gNotifyUserNo = user_no;
559 gNotifySeatNo = seat_no;
560 gNotifyReason = regPolicy;
562 if(regPolicy == Notify_register)
565 gChangeNotifyCallback = callback;
567 else if(regPolicy == Notify_unregister)
570 gChangeNotifyCallback = NULL;
573 if(-1 == deliverToMainloop(CMD_REG_NOTIFY_SIGNAL, 0, 0))
575 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_notify_on_change => failed to write to pipe"), DLT_INT(errno));
592 int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, pclNotifyStatus_e reason)
595 if(reason < pclNotifyStatus_lastEntry)
597 snprintf(gNotifykey, DbKeyMaxLen, "%s", key);
599 gNotifyLdbid = context->ldbid; // to do: pass correct ==> JUST TESTING!!!!
600 gNotifyUserNo = context->user_no;
601 gNotifySeatNo = context->seat_no;
602 gNotifyReason = reason;
604 if(-1 == deliverToMainloop(CMD_SEND_NOTIFY_SIGNAL, 0,0) )
606 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_send_Notification_Signal => failed to write to pipe"), DLT_INT(errno));
607 rval = EPERS_NOTIFY_SIG;
612 rval = EPERS_NOTIFY_SIG;
619 void pers_rct_close_all()
623 // close all open persistence resource configuration tables
624 for(i=0; i< PrctDbTableSize; i++)
626 if(gResource_table[i] != -1)
628 if(persComRctClose(gResource_table[i]) != 0)
630 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_prepare_shutdown => failed to close db => index:"), DLT_INT(i));
633 gResource_table[i] = -1;