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 "../include_protected/persistence_client_library_db_access.h"
21 #include "../include_protected/persistence_client_library_rc_table.h"
22 #include "persistence_client_library_custom_loader.h"
23 #include "persistence_client_library_itzam_errors.h"
25 #include "persistence_client_library_dbus_service.h"
27 #include <dbus/dbus.h>
33 /// definition of a key-value pair stored in the database
34 typedef struct _KeyValuePair_s
36 char m_key[DbKeySize]; /// the key
37 char m_data[DbValueSize]; /// the data
38 unsigned int m_data_size; /// the size of the data
43 // definition of a cursor entry
44 typedef struct _CursorEntry_s
46 itzam_btree_cursor m_cursor;
52 // cursor array handle
53 CursorEntry_s gCursorArray[MaxPersHandle];
56 static int gHandleIdx = 1;
59 int gFreeCursorHandleArray[MaxPersHandle];
61 int gFreeCursorHandleIdxHead = 0;
63 // mutex to controll access to the cursor array
64 pthread_mutex_t gMtx = PTHREAD_MUTEX_INITIALIZER;
68 static itzam_btree gBtree[DbTableSize][PersistencePolicy_LastEntry];
69 static int gBtreeCreated[DbTableSize][PersistencePolicy_LastEntry] = { {0} };
73 int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, unsigned int reason);
80 int pers_db_open_default(itzam_btree* btree, const char* dbPath, int configDefault)
82 itzam_state state = ITZAM_FAILED;
83 char path[DbPathMaxLen] = {0};
85 if(1 == configDefault)
87 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gConfigDefault);
89 else if(0 == configDefault)
91 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gDefault);
98 state = itzam_btree_open(btree, path, itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
99 if (state != ITZAM_OKAY)
101 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open_default ==> itzam_btree_open => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
108 itzam_btree* pers_db_open(PersistenceInfo_s* info, const char* dbPath)
111 itzam_btree* btree = NULL;
113 // create array index: index is a combination of resource config table type and group
114 arrayIdx = info->configKey.storage + info->context.ldbid ;
116 //if(arrayIdx <= DbTableSize)
117 if(arrayIdx < DbTableSize)
119 if(gBtreeCreated[arrayIdx][info->configKey.policy] == 0)
121 itzam_state state = ITZAM_FAILED;
122 char path[DbPathMaxLen] = {0};
124 if(PersistencePolicy_wt == info->configKey.policy)
126 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gWt);
128 else if(PersistencePolicy_wc == info->configKey.policy)
130 snprintf(path, DbPathMaxLen, "%s%s", dbPath, gCached);
137 state = itzam_btree_open(&gBtree[arrayIdx][info->configKey.policy], path,
138 itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
139 if (state != ITZAM_OKAY)
141 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open ==> itzam_btree_open => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
143 gBtreeCreated[arrayIdx][info->configKey.policy] = 1;
146 btree = &gBtree[arrayIdx][info->configKey.policy];
150 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open ==> invalid storage type"), DLT_STRING(dbPath));
157 void pers_db_close(PersistenceInfo_s* info)
159 int arrayIdx = info->configKey.storage + info->context.ldbid;
161 if(info->configKey.storage <= PersistenceStorage_shared )
163 itzam_state state = ITZAM_FAILED;
164 state = itzam_btree_close(&gBtree[arrayIdx][info->configKey.policy]);
165 if (state != ITZAM_OKAY)
167 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close ==> itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
169 gBtreeCreated[arrayIdx][info->configKey.policy] = 0;
173 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close ==> invalid storage type"), DLT_INT(info->context.ldbid ));
179 void pers_db_close_all()
183 for(i=0; i<DbTableSize; i++)
185 // close write cached database
186 if(gBtreeCreated[i][PersistencePolicy_wc] == 1)
188 itzam_state state = ITZAM_FAILED;
189 state = itzam_btree_close(&gBtree[i][PersistencePolicy_wc]);
190 if (state != ITZAM_OKAY)
192 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close_all ==> itzam_btree_close => Itzam problem:"), DLT_STRING(STATE_MESSAGES[state]) );
194 gBtreeCreated[i][PersistencePolicy_wc] = 0;
197 // close write through database
198 if(gBtreeCreated[i][PersistencePolicy_wt] == 1)
200 itzam_state state = ITZAM_FAILED;
201 state = itzam_btree_close(&gBtree[i][PersistencePolicy_wt]);
202 if (state != ITZAM_OKAY)
204 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close_all ==>itzam_btree_close => Itzam problem:"), DLT_STRING(STATE_MESSAGES[state]));
206 gBtreeCreated[i][PersistencePolicy_wt] = 0;
212 int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
216 if( PersistenceStorage_shared == info->configKey.storage
217 || PersistenceStorage_local == info->configKey.storage)
219 itzam_btree* btree = NULL;
220 itzam_btree btreeDefault;
221 itzam_btree btreeConfDefault;
222 KeyValuePair_s search;
224 itzam_state state = ITZAM_FAILED;
226 btree = pers_db_open(info, dbPath);
229 if(itzam_true == itzam_btree_find(btree, key, &search))
231 read_size = search.m_data_size;
232 if(read_size > buffer_size)
234 read_size = buffer_size; // truncate data size to buffer size
236 memcpy(buffer, search.m_data, read_size);
242 // 1. check if _configurable_ default data is available
243 // --------------------------------
246 if(pers_db_open_default(&btreeConfDefault, dbPath, 1) != -1)
248 if(itzam_true == itzam_btree_find(&btreeConfDefault, key, &search)) // read db
250 read_size = search.m_data_size;
251 if(read_size > buffer_size)
253 read_size = buffer_size; // truncate data size to buffer size
255 memcpy(buffer, search.m_data, read_size);
261 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> 2. resource not found in default config => search in default db"), DLT_STRING(key));
264 state = itzam_btree_close(&btreeConfDefault);
265 if (state != ITZAM_OKAY)
267 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> default: itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
272 // 2. check if default data is available
273 // --------------------------------
276 if(pers_db_open_default(&btreeDefault, dbPath, 0) != -1)
278 if(itzam_true == itzam_btree_find(&btreeDefault, key, &search)) // read db
280 read_size = search.m_data_size;
281 if(read_size > buffer_size)
283 read_size = buffer_size; // truncate data size to buffer size
285 memcpy(buffer, search.m_data, read_size);
289 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> 3. reasoure not found in both default db's"), DLT_STRING(key) );
290 read_size = EPERS_NOKEY; // the key is not available neither in regular db nor in the default db's
293 state = itzam_btree_close(&btreeDefault);
294 if (state != ITZAM_OKAY)
296 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> default: itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
301 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==>no resource config table"), DLT_STRING(dbPath), DLT_STRING(key) );
302 read_size = EPERS_NOPRCTABLE;
308 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
310 int idx = custom_client_name_to_id(dbPath, 1);
311 char workaroundPath[128]; // workaround, because /sys/ can not be accessed on host!!!!
312 snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath );
314 if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_data != NULL) )
316 char pathKeyString[128] = {0};
317 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
319 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
323 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
325 read_size = gPersCustomFuncs[idx].custom_plugin_get_data(pathKeyString, (char*)buffer, buffer_size);
329 read_size = EPERS_NOPLUGINFUNCT;
337 int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
341 if( PersistenceStorage_local == info->configKey.storage
342 || PersistenceStorage_shared == info->configKey.storage )
344 write_size = buffer_size;
345 itzam_btree* btree = NULL;
346 itzam_state state = ITZAM_FAILED;
347 KeyValuePair_s insert;
349 btree = pers_db_open(info, dbPath);
353 keySize = (int)strlen((const char*)key);
354 if(keySize < DbKeySize)
357 dataSize = (int)strlen( (const char*)buffer);
358 if(dataSize < DbValueSize)
360 // -----------------------------------------------------------------------------
362 itzam_btree_transaction_start(btree);
365 memset(insert.m_key, 0, DbKeySize);
366 memcpy(insert.m_key, key, keySize);
367 if(itzam_true == itzam_btree_find(btree, key, &insert))
369 // key already available, so delete "old" key
370 state = itzam_btree_remove(btree, (const void *)&insert);
374 memset(insert.m_data, 0, DbValueSize);
375 memcpy(insert.m_data, buffer, dataSize);
378 insert.m_data_size = buffer_size;
380 state = itzam_btree_insert(btree,(const void *)&insert);
381 if (state != ITZAM_OKAY)
383 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> itzam_btree_insert => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]) );
384 write_size = EPERS_DB_ERROR_INTERNAL;
388 itzam_btree_transaction_commit(btree);
390 // -----------------------------------------------------------------------------
392 if(PersistenceStorage_shared == info->configKey.storage)
394 pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
399 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> data to long » size:"), DLT_INT(dataSize), DLT_INT(DbValueSize) );
400 write_size = EPERS_DB_VALUE_SIZE;
405 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> key to long » size"), DLT_INT(keySize), DLT_INT(DbKeySize) );
406 write_size = EPERS_DB_KEY_SIZE;
411 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
412 write_size = EPERS_NOPRCTABLE;
415 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
417 int idx = custom_client_name_to_id(dbPath, 1);
418 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_set_data != NULL) )
420 char pathKeyString[128] = {0};
421 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
423 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
427 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
429 write_size = gPersCustomFuncs[idx].custom_plugin_set_data(pathKeyString, (char*)buffer, buffer_size);
433 write_size = EPERS_NOPLUGINFUNCT;
441 int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
445 if( PersistenceStorage_shared == info->configKey.storage
446 || PersistenceStorage_local == info->configKey.storage)
449 itzam_btree* btree = NULL;
450 KeyValuePair_s search;
452 btree = pers_db_open(info, dbPath);
455 keySize = (int)strlen((const char*)key);
456 if(keySize < DbKeySize)
458 memset(search.m_key,0, DbKeySize);
459 memcpy(search.m_key, key, keySize);
460 if(itzam_true == itzam_btree_find(btree, key, &search))
462 read_size = search.m_data_size;
466 read_size = EPERS_NOKEY;
471 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
472 read_size = EPERS_DB_KEY_SIZE;
477 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> no config table"), DLT_STRING(dbPath), DLT_STRING(key));
478 read_size = EPERS_NOPRCTABLE;
481 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
483 int idx = custom_client_name_to_id(dbPath, 1);
484 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_size != NULL) )
486 char pathKeyString[128] = {0};
487 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
489 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
493 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
495 read_size = gPersCustomFuncs[idx].custom_plugin_get_size(pathKeyString);
499 read_size = EPERS_NOPLUGINFUNCT;
507 int pers_db_delete_key(char* dbPath, char* key, PersistenceInfo_s* info)
510 if(PersistenceStorage_custom != info->configKey.storage)
512 itzam_btree* btree = NULL;
513 KeyValuePair_s delete;
515 btree = pers_db_open(info, dbPath);
519 keySize = (int)strlen((const char*)key);
520 if(keySize < DbKeySize)
522 // -----------------------------------------------------------------------------
524 itzam_btree_transaction_start(btree);
528 memset(delete.m_key,0, DbKeySize);
529 memcpy(delete.m_key, key, keySize);
530 state = itzam_btree_remove(btree, (const void *)&delete);
531 if (state != ITZAM_OKAY)
533 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> itzam_btree_remove => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
534 ret = EPERS_DB_ERROR_INTERNAL;
536 itzam_btree_transaction_commit(btree);
538 // -----------------------------------------------------------------------------
540 if(PersistenceStorage_shared == info->configKey.storage)
542 pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
547 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
548 ret = EPERS_DB_KEY_SIZE;
553 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
554 ret = EPERS_NOPRCTABLE;
557 else // custom storage implementation via custom library
559 int idx = custom_client_name_to_id(dbPath, 1);
560 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_delete_data != NULL) )
562 char pathKeyString[128] = {0};
563 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
565 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
569 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
571 ret = gPersCustomFuncs[idx].custom_plugin_delete_data(pathKeyString);
575 ret = EPERS_NOPLUGINFUNCT;
582 int persistence_notify_on_change(char* dbPath, char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no,
583 pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
586 char ruleChanged[DbusMatchRuleSize];
587 char ruleDeleted[DbusMatchRuleSize];
588 char ruleCreated[DbusMatchRuleSize];
589 DBusConnection* conn = get_dbus_connection();
591 // add match for c h a n g e
592 snprintf(ruleChanged, DbusMatchRuleSize, "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResChange',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
593 key, ldbid, user_no, seat_no);
594 // add match for d e l e t e
595 snprintf(ruleDeleted, DbusMatchRuleSize, "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResDelete',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
596 key, ldbid, user_no, seat_no);
597 // add match for c r e a t e
598 snprintf(ruleCreated, DbusMatchRuleSize, "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResCreate',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
599 key, ldbid, user_no, seat_no);
601 if(regPolicy == Notify_register)
604 gChangeNotifyCallback = callback;
606 dbus_bus_add_match(conn, ruleChanged, NULL);
607 dbus_bus_add_match(conn, ruleDeleted, NULL);
608 dbus_bus_add_match(conn, ruleCreated, NULL);
610 else if(regPolicy == Notify_unregister)
613 gChangeNotifyCallback = NULL;
615 dbus_bus_remove_match(conn, ruleChanged, NULL);
616 dbus_bus_remove_match(conn, ruleDeleted, NULL);
617 dbus_bus_remove_match(conn, ruleCreated, NULL);
620 dbus_connection_flush(conn); // flush the connection to add the match
626 int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, pclNotifyStatus_e reason)
628 DBusMessage* message;
631 char ldbid_array[DbusSubMatchSize] = {0};
632 char user_array[DbusSubMatchSize] = {0};
633 char seat_array[DbusSubMatchSize] = {0};
634 const char* ldbid_ptr = ldbid_array;
635 const char* user_ptr = user_array;
636 const char* seat_ptr = seat_array;
638 char* changeSignal = "PersistenceResChange";
639 char* deleteSignal = "PersistenceResDelete";
640 char* createSignal = "PersistenceResCreate";
641 char* theReason = NULL;
643 DBusConnection* conn = get_dbus_connection();
646 // dbus_bus_add_match is used for the notification mechanism,
647 // and this works only for type DBUS_TYPE_STRING as message arguments
648 // this is the reason to use string instead of integer types directly
649 snprintf(ldbid_array, DbusSubMatchSize, "%d", context->ldbid);
650 snprintf(user_array, DbusSubMatchSize, "%d", context->user_no);
651 snprintf(seat_array, DbusSubMatchSize, "%d", context->seat_no);
655 case pclNotifyStatus_deleted:
656 theReason = deleteSignal;
658 case pclNotifyStatus_created:
659 theReason = createSignal;
661 case pclNotifyStatus_changed:
662 theReason = changeSignal;
665 theReason = changeSignal;
669 if(theReason != NULL)
671 message = dbus_message_new_signal("/org/genivi/persistence/adminconsumer", // const char *path,
672 "org.genivi.persistence.adminconsumer", // const char *interface,
673 theReason); // const char *name
675 ret = dbus_message_append_args(message,
676 DBUS_TYPE_STRING, &key,
677 DBUS_TYPE_STRING, &ldbid_ptr,
678 DBUS_TYPE_STRING, &user_ptr,
679 DBUS_TYPE_STRING, &seat_ptr,
686 if(dbus_connection_send(conn, message, 0) == TRUE)
688 // Free the signal now we have finished with it
689 dbus_message_unref(message);
693 rval = EPERS_NOTIFY_SIG;
698 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_send_Notification_Signal ==> E R R O R C O N E C T I O N NULL!!"));
703 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_send_Notification_Signal ==> ERROR dbus_message_append_args"));
704 rval = EPERS_NOTIFY_SIG;
709 rval = EPERS_NOTIFY_SIG;
716 //---------------------------------------------------------------------------------------------------------
717 // C U R S O R F U N C T I O N S
718 //---------------------------------------------------------------------------------------------------------
720 int get_cursor_handle()
724 if(pthread_mutex_lock(&gMtx) == 0)
726 if(gFreeCursorHandleIdxHead > 0) // check if we have a free spot in the array before the current max
728 handle = gFreeCursorHandleArray[--gFreeCursorHandleIdxHead];
732 if(gHandleIdx < MaxPersHandle-1)
734 handle = gHandleIdx++; // no free spot before current max, increment handle index
738 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("get_cursor_handle ==> Reached maximum of open handles:"), DLT_INT(MaxPersHandle));
742 pthread_mutex_unlock(&gMtx);
748 void close_cursor_handle(int handlerDB)
750 if(pthread_mutex_lock(&gMtx) == 0)
752 if(gFreeCursorHandleIdxHead < MaxPersHandle)
754 gFreeCursorHandleArray[gFreeCursorHandleIdxHead++] = handlerDB;
756 pthread_mutex_unlock(&gMtx);
762 int pers_db_cursor_create(char* dbPath)
765 itzam_state state = ITZAM_FAILED;
767 handle = get_cursor_handle();
769 if(handle < MaxPersHandle && handle >= 0)
772 state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 1/*recover*/, 0/*read_only*/);
773 if (state != ITZAM_OKAY)
775 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_create ==> itzam_btree_open"), DLT_STRING(STATE_MESSAGES[state]));
781 state = itzam_btree_cursor_create(&gCursorArray[handle].m_cursor, &gCursorArray[handle].m_btree);
782 if(state == ITZAM_OKAY)
784 gCursorArray[handle].m_empty = 0;
788 gCursorArray[handle].m_empty = 1;
797 int pers_db_cursor_next(unsigned int handlerDB)
800 //if(handlerDB < MaxPersHandle && handlerDB >= 0)
801 if(handlerDB < MaxPersHandle )
803 if(gCursorArray[handlerDB].m_empty != 1)
806 success = itzam_btree_cursor_next(&gCursorArray[handlerDB].m_cursor);
808 if(success == itzam_true)
814 rval = EPERS_LAST_ENTRY_IN_DB;
819 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> invalid handle: "), DLT_INT(handlerDB));
824 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
831 int pers_db_cursor_get_key(unsigned int handlerDB, char * bufKeyName_out, int bufSize)
834 KeyValuePair_s search;
836 if(handlerDB < MaxPersHandle)
838 if(gCursorArray[handlerDB].m_empty != 1)
841 itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
842 length = strlen(search.m_key);
845 memcpy(bufKeyName_out, search.m_key, length);
850 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_key ==> buffer to small » keySize: "), DLT_INT(bufSize));
855 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key ==> invalid handle:"), DLT_INT(handlerDB));
860 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
867 int pers_db_cursor_get_data(unsigned int handlerDB, char * bufData_out, int bufSize)
870 KeyValuePair_s search;
872 if(handlerDB < MaxPersHandle)
874 if(gCursorArray[handlerDB].m_empty != 1)
877 itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
879 length = strlen(search.m_data);
882 memcpy(bufData_out, search.m_data, length);
887 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data ==> buffer to small » keySize: "), DLT_INT(bufSize));
892 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> invalid handle:"), DLT_INT(handlerDB));
897 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
904 int pers_db_cursor_get_data_size(unsigned int handlerDB)
907 KeyValuePair_s search;
909 if(handlerDB < MaxPersHandle)
911 if(gCursorArray[handlerDB].m_empty != 1)
913 itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
914 size = strlen(search.m_data);
918 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data_size ==> invalid handle:"), DLT_INT(handlerDB));
923 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
930 int pers_db_cursor_destroy(unsigned int handlerDB)
933 if(handlerDB < MaxPersHandle)
935 itzam_btree_cursor_free(&gCursorArray[handlerDB].m_cursor);
936 gCursorArray[handlerDB].m_empty = 1;
938 itzam_state state = ITZAM_FAILED;
939 state = itzam_btree_close(&gCursorArray[handlerDB].m_btree);
940 if (state != ITZAM_OKAY)
942 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_destroy ==> itzam_btree_close: Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
945 close_cursor_handle(handlerDB);
955 //-----------------------------------------------------------------------------
956 // code to print database content (for debugging)
957 //-----------------------------------------------------------------------------
961 itzam_btree_cursor cursor;
962 state = itzam_btree_cursor_create(&cursor, &btree);
963 if(state == ITZAM_OKAY)
965 printf("==> Database content ==> db size: %d\n", (int)itzam_btree_count(&btree));
968 // get the key pointed to by the cursor
969 state = itzam_btree_cursor_read(&cursor,(void *)&rec);
970 if (state == ITZAM_OKAY)
972 printf(" Key: %s \n ==> data: %s\n", rec.m_key, rec.m_data);
975 fprintf(stderr, "\nItzam problem: %s\n", STATE_MESSAGES[state]);
977 while (itzam_btree_cursor_next(&cursor));
979 state = itzam_btree_cursor_free(&cursor);
982 //-----------------------------------------------------------------------------