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_db_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);
47 char* pers_get_raw_key(char *key)
52 temp = strrchr(key, (int)'/');
63 int pers_db_open_default(const char* dbPath, PersDefaultType_e DefaultType)
66 char path[DbPathMaxLen] = {0};
68 if (PersDefaultType_Configurable == DefaultType)
70 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gLocalConfigurableDefault);
72 else if (PersDefaultType_Factory== DefaultType)
74 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gLocalFactoryDefault);
78 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open_default ==> unknown DefaultType"));
82 if (EPERS_COMMON != ret)
84 ret = persComDbOpen(path, 0);
88 DLT_LOG(gPclDLTContext, DLT_LOG_WARN,
89 DLT_STRING("pers_db_open_default() -> persComDbOpen() -> problem open db: "), DLT_STRING(path),
90 DLT_STRING(" Code: "), DLT_INT(ret));
98 int pers_get_defaults(char* dbPath, char* key, unsigned char* buffer, unsigned int buffer_size, PersGetDefault_e job)
100 PersDefaultType_e i = PersDefaultType_Configurable;
101 int handleDefaultDB = -1;
102 int read_size = EPERS_NOKEY;
103 char dltMessage[DbPathMaxLen] = {0};
105 for(i=0; i<PersDefaultType_LastEntry; i++)
107 handleDefaultDB = pers_db_open_default(dbPath, i);
108 if(handleDefaultDB >= 0)
110 if (PersGetDefault_Data == job)
112 read_size = persComDbReadKey(handleDefaultDB, key, (char*)buffer, buffer_size);
114 else if (PersGetDefault_Size == job)
116 read_size = persComDbGetKeySize(handleDefaultDB, key);
120 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_get_defaults ==> unknown job"));
124 if (0 > persComDbClose(handleDefaultDB))
126 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_get_defaults ==> persComDbClose returned with error"));
129 if(read_size < 0) // check read_size
131 if(PERS_COM_ERR_NOT_FOUND == read_size)
133 read_size = EPERS_NOKEY;
136 else /* read_size >= 0 --> default value found */
138 if (PersDefaultType_Configurable == i)
140 snprintf(dltMessage, DbPathMaxLen, "%s%s", dbPath, gLocalConfigurableDefault);
142 if (PersDefaultType_Factory == i)
144 snprintf(dltMessage, DbPathMaxLen, "%s%s", dbPath, gLocalFactoryDefault);
146 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Default data will be used for Key"), DLT_STRING(key),
147 DLT_STRING("from"), DLT_STRING(dltMessage));
155 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Default data not available for Key"), DLT_STRING(key),
156 DLT_STRING("Path:"), DLT_STRING(dbPath));
163 static int database_get(PersistenceInfo_s* info, const char* dbPath)
168 // create array index: index is a combination of resource config table type and group
169 arrayIdx = info->configKey.storage + info->context.ldbid ;
171 if(arrayIdx < DbTableSize)
173 if(gHandlesDBCreated[arrayIdx][info->configKey.policy] == 0)
175 char path[DbPathMaxLen] = {0};
177 if(PersistencePolicy_wt == info->configKey.policy)
179 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gLocalWt);
181 else if(PersistencePolicy_wc == info->configKey.policy)
183 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gLocalCached);
192 handleDB = persComDbOpen(path, 0x01);
195 gHandlesDB[arrayIdx][info->configKey.policy] = handleDB ;
196 gHandlesDBCreated[arrayIdx][info->configKey.policy] = 1;
200 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_get ==> persComDbOpen() failed"));
205 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_get ==> wrong policy! Cannot extend dbPath wit database."));
210 handleDB = gHandlesDB[arrayIdx][info->configKey.policy];
215 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_get ==> invalid storage type"), DLT_STRING(dbPath));
224 void database_close(PersistenceInfo_s* info)
226 int arrayIdx = info->configKey.storage + info->context.ldbid;
228 if(info->configKey.storage <= PersistenceStorage_shared )
230 int iErrorCode = persComDbClose(gHandlesDB[arrayIdx][info->configKey.policy]) ;
233 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_close ==> persComDbClose() failed"));
237 gHandlesDBCreated[arrayIdx][info->configKey.policy] = 0;
242 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_close ==> invalid storage type"), DLT_INT(info->context.ldbid ));
246 void database_close_all()
250 for(i=0; i<DbTableSize; i++)
252 for(j=0; j < PersistencePolicy_na; j++)
254 if(gHandlesDBCreated[i][j] == 1)
256 int iErrorCode = persComDbClose(gHandlesDB[i][j]);
259 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("database_close_all => failed to close db => persComDbClose"));
263 gHandlesDBCreated[i][j] = 0;
272 int persistence_get_data(char* dbPath, char* key, const char* resourceID, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
275 int ret_defaults = -1;
277 if( PersistenceStorage_shared == info->configKey.storage
278 || PersistenceStorage_local == info->configKey.storage)
280 int handleDB = database_get(info, dbPath);
283 read_size = persComDbReadKey(handleDB, key, (char*)buffer, buffer_size);
286 read_size = pers_get_defaults(dbPath, (char*)resourceID, buffer, buffer_size, PersGetDefault_Data); /* 0 ==> Get data */
290 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
292 int idx = custom_client_name_to_id(dbPath, 1);
293 char workaroundPath[128]; // workaround, because /sys/ can not be accessed on host!!!!
294 snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath );
296 if(idx < PersCustomLib_LastEntry)
299 if(gPersCustomFuncs[idx].custom_plugin_get_size == NULL )
301 if(getCustomLoadingType(idx) == LoadType_OnDemand)
303 // plugin not loaded, try to load the requested plugin
304 if(load_custom_library(idx, &gPersCustomFuncs[idx]) == 1)
306 // check again if the plugin function is now available
307 if(gPersCustomFuncs[idx].custom_plugin_get_data != NULL)
313 else if(getCustomLoadingType(idx) == LoadType_PclInit)
315 if(gPersCustomFuncs[idx].custom_plugin_get_data != NULL)
322 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Plugin not available (getData), unknown loading type: "),
323 DLT_INT(getCustomLoadingType(idx)));
324 read_size = EPERS_COMMON;
329 available = 1; // already loaded
334 char pathKeyString[128] = {0};
335 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
337 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
341 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
343 read_size = gPersCustomFuncs[idx].custom_plugin_get_data(pathKeyString, (char*)buffer, buffer_size);
347 read_size = EPERS_NOPLUGINFUNCT;
352 read_size = EPERS_NOPLUGINFUNCT;
355 if (1 > read_size) /* Try to get default values */
357 info->configKey.policy = PersistencePolicy_wc; /* Set the policy */
358 info->configKey.type = PersistenceResourceType_key; /* Set the type */
360 (void)get_db_path_and_key(info, key, NULL, dbPath);
362 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Plugin data not available. Try to get default data of key:"), DLT_STRING(key));
363 ret_defaults = pers_get_defaults(dbPath, (char*)resourceID, buffer, buffer_size, PersGetDefault_Data);
364 if (0 < ret_defaults)
366 read_size = ret_defaults;
375 int persistence_set_data(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
379 if( PersistenceStorage_local == info->configKey.storage
380 || PersistenceStorage_shared == info->configKey.storage )
385 handleDB = database_get(info, dbPath);
388 write_size = persComDbWriteKey(handleDB, key, (char*)buffer, buffer_size) ;
391 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_set_data ==> persComDbWriteKey() failure"));
395 if(PersistenceStorage_shared == info->configKey.storage)
397 int rval = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
400 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_set_data ==> failed to send notification signal"));
409 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_set_data ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
410 write_size = EPERS_NOPRCTABLE;
413 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
416 int idx = custom_client_name_to_id(dbPath, 1);
417 if(idx < PersCustomLib_LastEntry )
419 if(gPersCustomFuncs[idx].custom_plugin_set_data != NULL)
422 if (getCustomLoadingType(idx) == LoadType_OnDemand)
424 // plugin not loaded, try to load the requested plugin
425 if(load_custom_library(idx, &gPersCustomFuncs[idx]) == 1)
427 // check again if the plugin function is now available
428 if(gPersCustomFuncs[idx].custom_plugin_set_data != NULL)
434 else if(getCustomLoadingType(idx) == LoadType_PclInit)
436 if(gPersCustomFuncs[idx].custom_plugin_set_data != NULL)
443 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Plugin not available (setData), unknown loading type: "),
444 DLT_INT(getCustomLoadingType(idx)));
445 write_size = EPERS_COMMON;
450 available = 1; // already loaded
455 char pathKeyString[128] = {0};
456 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
458 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
462 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
464 write_size = gPersCustomFuncs[idx].custom_plugin_set_data(pathKeyString, (char*)buffer, buffer_size);
465 //write_size = persComDbWriteKey(handleDB, key, (char*)buffer, buffer_size) ;
467 if ((0 < write_size) && ((unsigned int)write_size == buffer_size)) /* Check return value and send notification if OK */
469 int rval = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
472 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_set_data ==> failed to send notification signal"));
479 write_size = EPERS_NOPLUGINFUNCT;
484 write_size = EPERS_NOPLUGINFUNCT;
492 int persistence_get_data_size(char* dbPath, char* key, const char* resourceID, PersistenceInfo_s* info)
495 int ret_defaults = -1;
497 if( PersistenceStorage_shared == info->configKey.storage
498 || PersistenceStorage_local == info->configKey.storage)
500 int handleDB = database_get(info, dbPath);
504 read_size = persComDbGetKeySize(handleDB, key);
507 read_size = pers_get_defaults( dbPath, (char*)resourceID, NULL, 0, PersGetDefault_Size);
511 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
514 int idx = custom_client_name_to_id(dbPath, 1);
515 if(idx < PersCustomLib_LastEntry )
517 if(gPersCustomFuncs[idx].custom_plugin_get_size == NULL )
519 if (getCustomLoadingType(idx) == LoadType_OnDemand)
521 // plugin not loaded, try to load the requested plugin
522 if(load_custom_library(idx, &gPersCustomFuncs[idx]) == 1)
524 // check again if the plugin function is now available
525 if(gPersCustomFuncs[idx].custom_plugin_get_size != NULL)
531 else if(getCustomLoadingType(idx) == LoadType_PclInit)
533 if(gPersCustomFuncs[idx].custom_plugin_get_size != NULL)
540 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Plugin not available (getDataSize), unknown loading type: "),
541 DLT_INT(getCustomLoadingType(idx)));
542 read_size = EPERS_COMMON;
547 available = 1; // already loaded
552 char pathKeyString[128] = {0};
553 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
555 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
559 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
561 read_size = gPersCustomFuncs[idx].custom_plugin_get_size(pathKeyString);
565 read_size = EPERS_NOPLUGINFUNCT;
570 read_size = EPERS_NOPLUGINFUNCT;
575 info->configKey.policy = PersistencePolicy_wc; /* Set the policy */
576 info->configKey.type = PersistenceResourceType_key; /* Set the type */
577 (void)get_db_path_and_key(info, key, NULL, dbPath);
578 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Plugin data not available. Try to get size of default data for key:"),
580 ret_defaults = pers_get_defaults(dbPath, (char*)resourceID, NULL, 0, PersGetDefault_Size);
581 if (0 < ret_defaults)
583 read_size = ret_defaults;
592 int persistence_delete_data(char* dbPath, char* key, PersistenceInfo_s* info)
595 if(PersistenceStorage_custom != info->configKey.storage)
597 int handleDB = database_get(info, dbPath);
600 ret = persComDbDeleteKey(handleDB, key) ;
603 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_delete_data => persComDbDeleteKey failed: "), DLT_STRING(key));
604 if(PERS_COM_ERR_NOT_FOUND == ret)
610 ret = EPERS_DB_ERROR_INTERNAL ;
614 if(PersistenceStorage_shared == info->configKey.storage)
616 pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
621 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_delete_data ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
622 ret = EPERS_NOPRCTABLE;
625 else // custom storage implementation via custom library
628 int idx = custom_client_name_to_id(dbPath, 1);
629 if(idx < PersCustomLib_LastEntry)
631 if(gPersCustomFuncs[idx].custom_plugin_get_size == NULL )
633 if (getCustomLoadingType(idx) == LoadType_OnDemand)
635 // plugin not loaded, try to load the requested plugin
636 if(load_custom_library(idx, &gPersCustomFuncs[idx]) == 1)
638 // check again if the plugin function is now available
639 if(gPersCustomFuncs[idx].custom_plugin_delete_data != NULL)
645 else if(getCustomLoadingType(idx) == LoadType_PclInit)
647 if(gPersCustomFuncs[idx].custom_plugin_delete_data != NULL)
654 DLT_LOG(gPclDLTContext, DLT_LOG_INFO, DLT_STRING("Plugin not available (deleteData), unknown loading type: "),
655 DLT_INT(getCustomLoadingType(idx)));
661 available = 1; // already loaded
666 char pathKeyString[128] = {0};
667 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
669 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
673 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
675 ret = gPersCustomFuncs[idx].custom_plugin_delete_data(pathKeyString);
677 if(0 <= ret) /* Check return value and send notification if OK */
679 pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
684 ret = EPERS_NOPLUGINFUNCT;
689 ret = EPERS_NOPLUGINFUNCT;
696 int persistence_notify_on_change(const char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no,
697 pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
701 if(regPolicy < Notify_lastEntry)
705 data.message.cmd = (uint32_t)CMD_REG_NOTIFY_SIGNAL;
706 data.message.params[0] = ldbid;
707 data.message.params[1] = user_no;
708 data.message.params[2] = seat_no;
709 data.message.params[3] = regPolicy;
711 snprintf(data.message.string, DbKeyMaxLen, "%s", key);
713 if(regPolicy == Notify_register)
716 gChangeNotifyCallback = callback;
718 else if(regPolicy == Notify_unregister)
721 gChangeNotifyCallback = NULL;
724 if(-1 == deliverToMainloop(&data))
726 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_notify_on_change => failed to write to pipe"), DLT_INT(errno));
743 int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, pclNotifyStatus_e reason)
746 if(reason < pclNotifyStatus_lastEntry)
750 data.message.cmd = (uint32_t)CMD_SEND_NOTIFY_SIGNAL;
751 data.message.params[0] = context->ldbid;
752 data.message.params[1] = context->user_no;
753 data.message.params[2] = context->seat_no;
754 data.message.params[3] = reason;
756 snprintf(data.message.string, DbKeyMaxLen, "%s", key);
758 if(-1 == deliverToMainloop(&data) )
760 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_send_Notification_Signal => failed to write to pipe"), DLT_INT(errno));
761 rval = EPERS_NOTIFY_SIG;
766 rval = EPERS_NOTIFY_SIG;
773 void pers_rct_close_all()
777 // close all open persistence resource configuration tables
778 for(i=0; i< PrctDbTableSize; i++)
780 if(get_resource_cfg_table_by_idx(i) != -1)
782 if(persComRctClose(get_resource_cfg_table_by_idx(i)) != 0)
784 DLT_LOG(gPclDLTContext, DLT_LOG_ERROR, DLT_STRING("process_prepare_shutdown => failed to close db => index:"), DLT_INT(i));
787 invalidate_resource_cfg_table(i);