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_key.c
13 * @ingroup Persistence client library
14 * @author Ingo Huerner
15 * @brief Implementation of the persistence client library.
16 * Library provides an API to access persistent data
20 #include "persistence_client_library_key.h"
22 #include "../include_protected/persistence_client_library_db_access.h"
23 #include "../include_protected/persistence_client_library_rc_table.h"
24 #include "../include_protected/crc32.h"
26 #include "persistence_client_library_handle.h"
27 #include "persistence_client_library_pas_interface.h"
28 #include "persistence_client_library_prct_access.h"
29 #include "persistence_client_library_custom_loader.h"
32 // ----------------------------------------------------------------------------
33 // ----------------------------------------------------------------------------
34 // function with handle
35 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
38 int pclKeyHandleOpen(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no)
40 int handle = EPERS_NOT_INITIALIZED;
42 if(gPclInitialized >= PCLinitialized)
44 PersistenceInfo_s dbContext;
46 char dbKey[DbKeyMaxLen] = {0}; // database key
47 char dbPath[DbPathMaxLen] = {0}; // database location
49 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleOpen: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
50 dbContext.context.ldbid = ldbid;
51 dbContext.context.seat_no = seat_no;
52 dbContext.context.user_no = user_no;
54 // get database context: database path and database key
55 handle = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
57 && (dbContext.configKey.type == PersistenceResourceType_key) ) // check if type matches
59 if(dbContext.configKey.storage < PersistenceStorage_LastEntry) // check if store policy is valid
61 if(PersistenceStorage_custom == dbContext.configKey.storage)
63 int idx = custom_client_name_to_id(dbPath, 1);
64 char workaroundPath[128]; // workaround, because /sys/ can not be accessed on host!!!!
65 snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath );
67 if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_open != NULL) )
69 int flag = 0, mode = 0;
70 handle = gPersCustomFuncs[idx].custom_plugin_handle_open(workaroundPath, flag, mode);
74 handle = EPERS_NOPLUGINFUNCT;
79 handle = get_persistence_handle_idx();
82 if((handle < MaxPersHandle) && (0 <= handle))
84 // remember data in handle array
85 strncpy(gKeyHandleArray[handle].dbPath, dbPath, DbPathMaxLen);
86 strncpy(gKeyHandleArray[handle].dbKey, dbKey, DbKeyMaxLen);
87 strncpy(gKeyHandleArray[handle].resourceID, resource_id, DbResIDMaxLen);
88 gKeyHandleArray[handle].dbPath[DbPathMaxLen-1] = '\0'; // Ensures 0-Termination
89 gKeyHandleArray[handle].dbKey[ DbPathMaxLen-1] = '\0'; // Ensures 0-Termination
90 gKeyHandleArray[handle].info = dbContext;
94 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyHandleOpen: error - handleId out of bounds:"), DLT_INT(handle));
100 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyHandleOpen: error - no database context or resource is not a key "));
110 int pclKeyHandleClose(int key_handle)
112 int rval = EPERS_NOT_INITIALIZED;
114 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleClose: "),
115 // DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
117 if(gPclInitialized >= PCLinitialized)
119 if(key_handle < MaxPersHandle)
121 if(PersistenceStorage_custom == gKeyHandleArray[key_handle].info.configKey.storage )
123 int idx = custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1);
125 if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_close != NULL) )
127 rval = gPersCustomFuncs[idx].custom_plugin_handle_close(key_handle);
131 rval = EPERS_NOPLUGINFUNCT;
136 set_persistence_handle_close_idx(key_handle);
140 // invalidate entries
141 memset(gKeyHandleArray[key_handle].dbPath, 0, DbPathMaxLen);
142 memset(gKeyHandleArray[key_handle].dbKey ,0, DbKeyMaxLen);
143 gKeyHandleArray[key_handle].info.configKey.storage = -1;
147 rval = EPERS_MAXHANDLE;
156 int pclKeyHandleGetSize(int key_handle)
158 int size = EPERS_NOT_INITIALIZED;
160 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleGetSize: "),
161 // DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
163 if(gPclInitialized >= PCLinitialized)
165 if(key_handle < MaxPersHandle)
167 if(PersistenceStorage_custom == gKeyHandleArray[key_handle].info.configKey.storage)
169 int idx = custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1);
171 if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_size != NULL) )
173 size = gPersCustomFuncs[idx].custom_plugin_get_size(gKeyHandleArray[key_handle].dbPath);
177 size = EPERS_NOPLUGINFUNCT;
182 size = pers_db_get_key_size(gKeyHandleArray[key_handle].dbPath, gKeyHandleArray[key_handle].dbKey,
183 &gKeyHandleArray[key_handle].info);
188 size = EPERS_MAXHANDLE;
197 int pclKeyHandleReadData(int key_handle, unsigned char* buffer, int buffer_size)
199 int size = EPERS_NOT_INITIALIZED;
201 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleReadData: "),
202 // DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
204 if(gPclInitialized >= PCLinitialized)
206 if(key_handle < MaxPersHandle)
208 if(PersistenceStorage_custom == gKeyHandleArray[key_handle].info.configKey.storage)
210 int idx = custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1);
212 if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_get_data != NULL) )
214 size = gPersCustomFuncs[idx].custom_plugin_handle_get_data(key_handle, (char*)buffer, buffer_size-1);
218 size = EPERS_NOPLUGINFUNCT;
223 size = pers_db_read_key(gKeyHandleArray[key_handle].dbPath, gKeyHandleArray[key_handle].dbKey,
224 &gKeyHandleArray[key_handle].info, buffer, buffer_size);
229 size = EPERS_MAXHANDLE;
238 int pclKeyHandleRegisterNotifyOnChange(int key_handle, pclChangeNotifyCallback_t callback)
240 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleRegisterNotifyOnChange: "),
241 // DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
243 return handleRegNotifyOnChange(key_handle, callback, Notify_register);
246 int pclKeyHandleUnRegisterNotifyOnChange(int key_handle, pclChangeNotifyCallback_t callback)
248 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleUnRegisterNotifyOnChange: "),
249 // DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
251 return handleRegNotifyOnChange(key_handle, callback, Notify_unregister);
256 int handleRegNotifyOnChange(int key_handle, pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
258 int rval = EPERS_NOT_INITIALIZED;
260 if(gPclInitialized >= PCLinitialized)
262 if(key_handle < MaxPersHandle)
264 rval = regNotifyOnChange(gKeyHandleArray[key_handle].info.context.ldbid,
265 gKeyHandleArray[key_handle].resourceID,
266 gKeyHandleArray[key_handle].info.context.user_no,
267 gKeyHandleArray[key_handle].info.context.seat_no,
273 rval = EPERS_MAXHANDLE;
281 int pclKeyHandleWriteData(int key_handle, unsigned char* buffer, int buffer_size)
283 int size = EPERS_NOT_INITIALIZED;
285 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyHandleWriteData: "),
286 // DLT_INT(gKeyHandleArray[key_handle].info.context.ldbid), DLT_STRING(gKeyHandleArray[key_handle].resourceID) );
288 if(gPclInitialized >= PCLinitialized)
290 if(AccessNoLock != isAccessLocked() ) // check if access to persistent data is locked
292 if(buffer_size <= gMaxKeyValDataSize) // check data size
294 if(key_handle < MaxPersHandle)
296 if(gKeyHandleArray[key_handle].info.configKey.permission != PersistencePermission_ReadOnly) // don't write to a read only resource
298 if(PersistenceStorage_custom == gKeyHandleArray[key_handle].info.configKey.storage)
300 int idx = custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1);
302 if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data != NULL) )
304 size = gPersCustomFuncs[idx].custom_plugin_handle_set_data(key_handle, (char*)buffer, buffer_size-1);
306 if(size >= 0) // success ==> send change notification
308 int rval = pers_send_Notification_Signal(gKeyHandleArray[key_handle].dbKey,
309 &(gKeyHandleArray[key_handle].info.context), pclNotifyStatus_changed);
313 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyHandleWriteData: error - failed to send notification"));
320 size = EPERS_NOPLUGINFUNCT;
325 size = pers_db_write_key(gKeyHandleArray[key_handle].dbPath, gKeyHandleArray[key_handle].dbKey,
326 &gKeyHandleArray[key_handle].info, buffer, buffer_size);
331 size = EPERS_RESOURCE_READ_ONLY;
337 size = EPERS_MAXHANDLE;
342 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyHandleWriteData: error - buffer_size to big, limit is [bytes]:"), DLT_INT(gMaxKeyValDataSize));
343 size = EPERS_MAX_BUFF_SIZE;
359 // ----------------------------------------------------------------------------
360 // ----------------------------------------------------------------------------
361 // functions to be used directly without a handle
362 // ----------------------------------------------------------------------------
363 // ----------------------------------------------------------------------------
365 int pclKeyDelete(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no)
367 int rval = EPERS_NOT_INITIALIZED;
369 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyDelete: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
371 if(gPclInitialized >= PCLinitialized)
373 if(AccessNoLock != isAccessLocked() ) // check if access to persistent data is locked
375 PersistenceInfo_s dbContext;
377 char dbKey[DbKeyMaxLen] = {0}; // database key
378 char dbPath[DbPathMaxLen] = {0}; // database location
380 dbContext.context.ldbid = ldbid;
381 dbContext.context.seat_no = seat_no;
382 dbContext.context.user_no = user_no;
384 // get database context: database path and database key
385 rval = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
387 && (dbContext.configKey.type == PersistenceResourceType_key) ) // check if type is matching
389 if( dbContext.configKey.storage < PersistenceStorage_LastEntry
390 && dbContext.configKey.storage >= PersistenceStorage_local) // check if store policy is valid
392 rval = pers_db_delete_key(dbPath, dbKey, &dbContext);
412 int pclKeyGetSize(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no)
414 int data_size = EPERS_NOT_INITIALIZED;
416 if(gPclInitialized >= PCLinitialized)
418 PersistenceInfo_s dbContext;
420 char dbKey[DbKeyMaxLen] = {0}; // database key
421 char dbPath[DbPathMaxLen] = {0}; // database location
423 dbContext.context.ldbid = ldbid;
424 dbContext.context.seat_no = seat_no;
425 dbContext.context.user_no = user_no;
427 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyGetSize: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
429 // get database context: database path and database key
430 data_size = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
432 && (dbContext.configKey.type == PersistenceResourceType_key) ) // check if type matches
434 if( dbContext.configKey.storage < PersistenceStorage_LastEntry
435 && dbContext.configKey.storage >= PersistenceStorage_local) // check if store policy is valid
437 data_size = pers_db_get_key_size(dbPath, dbKey, &dbContext);
441 data_size = EPERS_BADPOL;
446 data_size = EPERS_BADPOL;
456 int pclKeyReadData(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no,
457 unsigned char* buffer, int buffer_size)
459 int data_size = EPERS_NOT_INITIALIZED;
461 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyReadData: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
463 if(gPclInitialized >= PCLinitialized)
465 if(AccessNoLock != isAccessLocked() ) // check if access to persistent data is locked
467 PersistenceInfo_s dbContext;
469 char dbKey[DbKeyMaxLen] = {0}; // database key
470 char dbPath[DbPathMaxLen] = {0}; // database location
472 dbContext.context.ldbid = ldbid;
473 dbContext.context.seat_no = seat_no;
474 dbContext.context.user_no = user_no;
476 // get database context: database path and database key
477 data_size = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
479 && (dbContext.configKey.type == PersistenceResourceType_key) )
482 if( dbContext.configKey.storage < PersistenceStorage_LastEntry
483 && dbContext.configKey.storage >= PersistenceStorage_local) // check if store policy is valid
485 data_size = pers_db_read_key(dbPath, dbKey, &dbContext, buffer, buffer_size);
489 data_size = EPERS_BADPOL;
494 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyReadData - error - no database context or resource is not a key"));
499 data_size = EPERS_LOCKFS;
508 int pclKeyWriteData(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no,
509 unsigned char* buffer, int buffer_size)
511 int data_size = EPERS_NOT_INITIALIZED;
513 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyWriteData: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
515 if(gPclInitialized >= PCLinitialized)
517 if(AccessNoLock != isAccessLocked() ) // check if access to persistent data is locked
519 if(buffer_size <= gMaxKeyValDataSize) // check data size
521 PersistenceInfo_s dbContext;
523 unsigned int hash_val_data = 0;
525 char dbKey[DbKeyMaxLen] = {0}; // database key
526 char dbPath[DbPathMaxLen] = {0}; // database location
528 dbContext.context.ldbid = ldbid;
529 dbContext.context.seat_no = seat_no;
530 dbContext.context.user_no = user_no;
532 // get database context: database path and database key
533 data_size = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
535 && (dbContext.configKey.type == PersistenceResourceType_key))
537 if(dbContext.configKey.permission != PersistencePermission_ReadOnly) // don't write to a read only resource
539 // get hash value of data to verify storing
540 hash_val_data = pclCrc32(hash_val_data, buffer, buffer_size);
543 if( dbContext.configKey.storage < PersistenceStorage_LastEntry
544 && dbContext.configKey.storage >= PersistenceStorage_local) // check if store policy is valid
546 data_size = pers_db_write_key(dbPath, dbKey, &dbContext, buffer, buffer_size);
550 data_size = EPERS_BADPOL;
555 data_size = EPERS_RESOURCE_READ_ONLY;
560 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyWriteData - error - no database context or resource is not a key"));
565 data_size = EPERS_BUFLIMIT;
566 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyWriteData: error - buffer_size to big, limit is [bytes]:"), DLT_INT(gMaxKeyValDataSize));
571 data_size = EPERS_LOCKFS;
580 int pclKeyUnRegisterNotifyOnChange( unsigned int ldbid, const char * resource_id, unsigned int user_no, unsigned int seat_no, pclChangeNotifyCallback_t callback)
582 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyUnRegisterNotifyOnChange: "),
583 // DLT_INT(ldbid), DLT_STRING(resource_id) );
585 return regNotifyOnChange(ldbid, resource_id, user_no, seat_no, callback, Notify_unregister);
589 int pclKeyRegisterNotifyOnChange(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no, pclChangeNotifyCallback_t callback)
591 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyRegisterNotifyOnChange: "),
592 // DLT_INT(ldbid), DLT_STRING(resource_id) );
594 return regNotifyOnChange(ldbid, resource_id, user_no, seat_no, callback, Notify_register);
600 int regNotifyOnChange(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no, pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
602 int rval = EPERS_NOT_INITIALIZED;
604 if(gPclInitialized >= PCLinitialized)
606 PersistenceInfo_s dbContext;
608 // unsigned int hash_val_data = 0;
609 char dbKey[DbKeyMaxLen] = {0}; // database key
610 char dbPath[DbPathMaxLen] = {0}; // database location
612 //DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclKeyRegisterNotifyOnChange: "), DLT_INT(ldbid), DLT_STRING(resource_id) );
614 dbContext.context.ldbid = ldbid;
615 dbContext.context.seat_no = seat_no;
616 dbContext.context.user_no = user_no;
618 // get database context: database path and database key
619 rval = get_db_context(&dbContext, resource_id, ResIsNoFile, dbKey, dbPath);
621 // registration is only on shared and custom keys possible
622 if( (dbContext.configKey.storage != PersistenceStorage_local)
623 && (dbContext.configKey.type == PersistenceResourceType_key) )
625 rval = persistence_notify_on_change(dbKey, ldbid, user_no, seat_no, callback, regPolicy);
629 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclKeyRegisterNotifyOnChange: error - resource is not a shared resource or resource is not a key"));
630 rval = EPERS_NOTIFY_NOT_ALLOWED;