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);
76 itzam_btree* pers_db_open(PersistenceInfo_s* info, const char* dbPath)
79 itzam_btree* btree = NULL;
81 // create array index: index is a combination of resource config table type and group
82 arrayIdx = info->configKey.storage + info->context.ldbid ;
84 //if(arrayIdx <= DbTableSize)
85 if(arrayIdx < DbTableSize)
87 if(gBtreeCreated[arrayIdx][info->configKey.policy] == 0)
89 itzam_state state = ITZAM_FAILED;
90 state = itzam_btree_open(&gBtree[arrayIdx][info->configKey.policy], dbPath,
91 itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
92 if (state != ITZAM_OKAY)
94 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open ==> itzam_btree_open => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
96 gBtreeCreated[arrayIdx][info->configKey.policy] = 1;
99 btree = &gBtree[arrayIdx][info->configKey.policy];
103 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open ==> invalid storage type"), DLT_STRING(dbPath));
110 void pers_db_close(PersistenceInfo_s* info)
112 int arrayIdx = info->configKey.storage + info->context.ldbid;
114 if(info->configKey.storage <= PersistenceStorage_shared )
116 itzam_state state = ITZAM_FAILED;
117 state = itzam_btree_close(&gBtree[arrayIdx][info->configKey.policy]);
118 if (state != ITZAM_OKAY)
120 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close ==> itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
122 gBtreeCreated[arrayIdx][info->configKey.policy] = 0;
126 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close ==> invalid storage type"), DLT_INT(info->context.ldbid ));
132 void pers_db_close_all()
136 for(i=0; i<DbTableSize; i++)
138 // close write cached database
139 if(gBtreeCreated[i][PersistencePolicy_wc] == 1)
141 itzam_state state = ITZAM_FAILED;
142 state = itzam_btree_close(&gBtree[i][PersistencePolicy_wc]);
143 if (state != ITZAM_OKAY)
145 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close_all ==> itzam_btree_close => Itzam problem:"), DLT_STRING(STATE_MESSAGES[state]) );
147 gBtreeCreated[i][PersistencePolicy_wc] = 0;
150 // close write through database
151 if(gBtreeCreated[i][PersistencePolicy_wt] == 1)
153 itzam_state state = ITZAM_FAILED;
154 state = itzam_btree_close(&gBtree[i][PersistencePolicy_wt]);
155 if (state != ITZAM_OKAY)
157 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close_all ==>itzam_btree_close => Itzam problem:"), DLT_STRING(STATE_MESSAGES[state]));
159 gBtreeCreated[i][PersistencePolicy_wt] = 0;
166 int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
170 if( PersistenceStorage_shared == info->configKey.storage
171 || PersistenceStorage_local == info->configKey.storage)
173 itzam_btree* btree = NULL;
174 KeyValuePair_s search;
176 btree = pers_db_open(info, dbPath);
179 if(itzam_true == itzam_btree_find(btree, key, &search))
181 read_size = search.m_data_size;
182 if(read_size > buffer_size)
184 read_size = buffer_size; // truncate data size to buffer size
186 memcpy(buffer, search.m_data, read_size);
190 read_size = EPERS_NOKEY;
195 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==>no resource config table"), DLT_STRING(dbPath), DLT_STRING(key) );
196 read_size = EPERS_NOPRCTABLE;
199 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
201 int idx = custom_client_name_to_id(dbPath, 1);
202 char workaroundPath[128]; // workaround, because /sys/ can not be accessed on host!!!!
203 snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath );
205 if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_get_data != NULL) )
207 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
209 char pathKeyString[128];
210 snprintf(pathKeyString, 128, "%s/%s", dbPath, key);
211 read_size = gPersCustomFuncs[idx].custom_plugin_get_data(pathKeyString, (char*)buffer, buffer_size);
215 read_size = gPersCustomFuncs[idx].custom_plugin_get_data(info->configKey.customID, (char*)buffer, buffer_size);
220 read_size = EPERS_NOPLUGINFUNCT;
228 int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
232 if( PersistenceStorage_local == info->configKey.storage
233 || PersistenceStorage_shared == info->configKey.storage )
235 write_size = buffer_size;
236 itzam_btree* btree = NULL;
237 itzam_state state = ITZAM_FAILED;
238 KeyValuePair_s insert;
240 btree = pers_db_open(info, dbPath);
244 keySize = (int)strlen((const char*)key);
245 if(keySize < DbKeySize)
248 dataSize = (int)strlen( (const char*)buffer);
249 if(dataSize < DbValueSize)
251 // -----------------------------------------------------------------------------
253 itzam_btree_transaction_start(btree);
256 memset(insert.m_key, 0, DbKeySize);
257 memcpy(insert.m_key, key, keySize);
258 if(itzam_true == itzam_btree_find(btree, key, &insert))
260 // key already available, so delete "old" key
261 state = itzam_btree_remove(btree, (const void *)&insert);
265 memset(insert.m_data, 0, DbValueSize);
266 memcpy(insert.m_data, buffer, dataSize);
269 insert.m_data_size = buffer_size;
271 state = itzam_btree_insert(btree,(const void *)&insert);
272 if (state != ITZAM_OKAY)
274 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> itzam_btree_insert => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]) );
275 write_size = EPERS_DB_ERROR_INTERNAL;
279 itzam_btree_transaction_commit(btree);
281 // -----------------------------------------------------------------------------
283 if(PersistenceStorage_shared == info->configKey.storage)
285 pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
290 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> data to long » size:"), DLT_INT(dataSize), DLT_INT(DbValueSize) );
291 write_size = EPERS_DB_VALUE_SIZE;
296 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> key to long » size"), DLT_INT(keySize), DLT_INT(DbKeySize) );
297 write_size = EPERS_DB_KEY_SIZE;
302 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
303 write_size = EPERS_NOPRCTABLE;
306 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
308 int idx = custom_client_name_to_id(dbPath, 1);
309 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data != NULL) )
311 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
313 char pathKeyString[128];
314 snprintf(pathKeyString, 128, "%s/%s", dbPath, key);
315 write_size = gPersCustomFuncs[idx].custom_plugin_set_data(pathKeyString, (char*)buffer, buffer_size);
318 write_size = gPersCustomFuncs[idx].custom_plugin_set_data(info->configKey.customID, (char*)buffer, buffer_size);
322 write_size = EPERS_NOPLUGINFUNCT;
330 int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
334 if( PersistenceStorage_shared == info->configKey.storage
335 || PersistenceStorage_local == info->configKey.storage)
338 itzam_btree* btree = NULL;
339 KeyValuePair_s search;
341 btree = pers_db_open(info, dbPath);
344 keySize = (int)strlen((const char*)key);
345 if(keySize < DbKeySize)
347 memset(search.m_key,0, DbKeySize);
348 memcpy(search.m_key, key, keySize);
349 if(itzam_true == itzam_btree_find(btree, key, &search))
351 read_size = search.m_data_size;
355 read_size = EPERS_NOKEY;
360 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
361 read_size = EPERS_DB_KEY_SIZE;
366 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> no config table"), DLT_STRING(dbPath), DLT_STRING(key));
367 read_size = EPERS_NOPRCTABLE;
370 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
372 int idx = custom_client_name_to_id(dbPath, 1);
373 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data != NULL) )
375 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
377 char pathKeyString[128];
378 snprintf(pathKeyString, 128, "%s/%s", dbPath, key);
379 read_size = gPersCustomFuncs[idx].custom_plugin_get_size(pathKeyString);
382 read_size = gPersCustomFuncs[idx].custom_plugin_get_size(info->configKey.customID);
386 read_size = EPERS_NOPLUGINFUNCT;
394 int pers_db_delete_key(char* dbPath, char* key, PersistenceInfo_s* info)
397 if(PersistenceStorage_custom != info->configKey.storage)
399 itzam_btree* btree = NULL;
400 KeyValuePair_s delete;
402 btree = pers_db_open(info, dbPath);
406 keySize = (int)strlen((const char*)key);
407 if(keySize < DbKeySize)
409 // -----------------------------------------------------------------------------
411 itzam_btree_transaction_start(btree);
415 memset(delete.m_key,0, DbKeySize);
416 memcpy(delete.m_key, key, keySize);
417 state = itzam_btree_remove(btree, (const void *)&delete);
418 if (state != ITZAM_OKAY)
420 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> itzam_btree_remove => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
421 ret = EPERS_DB_ERROR_INTERNAL;
423 itzam_btree_transaction_commit(btree);
425 // -----------------------------------------------------------------------------
427 if(PersistenceStorage_shared == info->configKey.storage)
429 pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
434 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
435 ret = EPERS_DB_KEY_SIZE;
440 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
441 ret = EPERS_NOPRCTABLE;
444 else // custom storage implementation via custom library
446 int idx = custom_client_name_to_id(dbPath, 1);
447 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data != NULL) )
449 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
451 char pathKeyString[128];
452 snprintf(pathKeyString, 128, "%s/%s", dbPath, key);
453 ret = gPersCustomFuncs[idx].custom_plugin_delete_data(pathKeyString);
456 ret = gPersCustomFuncs[idx].custom_plugin_delete_data(info->configKey.customID);
460 ret = EPERS_NOPLUGINFUNCT;
467 int persistence_reg_notify_on_change(char* dbPath, char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no,
468 pclChangeNotifyCallback_t callback)
472 dbus_error_init (&error);
473 char ruleChanged[DbusMatchRuleSize];
474 char ruleDeleted[DbusMatchRuleSize];
477 gChangeNotifyCallback = callback;
479 // add match for c h a n g e
480 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'",
481 key, ldbid, user_no, seat_no);
482 dbus_bus_add_match(get_dbus_connection(), ruleChanged, &error);
485 // add match for d e l e t e
486 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'",
487 key, ldbid, user_no, seat_no);
488 dbus_bus_add_match(get_dbus_connection(), ruleDeleted, &error);
491 // add match for c r e a t e
492 snprintf(ruleDeleted, DbusMatchRuleSize, "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceResCreate',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%u',arg2='%u',arg3='%u'",
493 key, ldbid, user_no, seat_no);
494 dbus_bus_add_match(get_dbus_connection(), ruleDeleted, &error);
500 int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, pclNotifyStatus_e reason)
502 DBusMessage* message;
505 char ldbid_array[DbusSubMatchSize];
506 char user_array[DbusSubMatchSize];
507 char seat_array[DbusSubMatchSize];
508 const char* ldbid_ptr = ldbid_array;
509 const char* user_ptr = user_array;
510 const char* seat_ptr = seat_array;
512 char* changeSignal = "PersistenceResChange";
513 char* deleteSignal = "PersistenceResDelete";
514 char* createSignal = "PersistenceResCreate";
515 char* theReason = NULL;
517 DBusConnection* conn = get_dbus_connection();
519 memset(ldbid_array, 0, DbusSubMatchSize);
520 memset(user_array, 0, DbusSubMatchSize);
521 memset(seat_array, 0, DbusSubMatchSize);
524 // dbus_bus_add_match is used for the notification mechanism,
525 // and this works only for type DBUS_TYPE_STRING as message arguments
526 // this is the reason to use string instead of integer types directly
527 snprintf(ldbid_array, DbusSubMatchSize, "%d", context->ldbid);
528 snprintf(user_array, DbusSubMatchSize, "%d", context->user_no);
529 snprintf(seat_array, DbusSubMatchSize, "%d", context->seat_no);
533 case pclNotifyStatus_deleted:
534 theReason = deleteSignal;
536 case pclNotifyStatus_created:
537 theReason = createSignal;
539 case pclNotifyStatus_changed:
540 theReason = changeSignal;
543 theReason = changeSignal;
547 if(theReason != NULL)
549 message = dbus_message_new_signal("/org/genivi/persistence/adminconsumer", // const char *path,
550 "org.genivi.persistence.adminconsumer", // const char *interface,
551 theReason); // const char *name
553 ret = dbus_message_append_args(message,
554 DBUS_TYPE_STRING, &key,
555 DBUS_TYPE_STRING, &ldbid_ptr,
556 DBUS_TYPE_STRING, &user_ptr,
557 DBUS_TYPE_STRING, &seat_ptr,
564 if(dbus_connection_send(conn, message, 0) == TRUE)
566 // Free the signal now we have finished with it
567 dbus_message_unref(message);
571 rval = EPERS_NOTIFY_SIG;
576 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!!"));
581 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_send_Notification_Signal ==> ERROR dbus_message_append_args"));
582 rval = EPERS_NOTIFY_SIG;
587 rval = EPERS_NOTIFY_SIG;
594 //---------------------------------------------------------------------------------------------------------
595 // C U R S O R F U N C T I O N S
596 //---------------------------------------------------------------------------------------------------------
598 int get_cursor_handle()
602 if(pthread_mutex_lock(&gMtx) == 0)
604 if(gFreeCursorHandleIdxHead > 0) // check if we have a free spot in the array before the current max
606 handle = gFreeCursorHandleArray[--gFreeCursorHandleIdxHead];
610 if(gHandleIdx < MaxPersHandle-1)
612 handle = gHandleIdx++; // no free spot before current max, increment handle index
616 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("get_cursor_handle ==> Reached maximum of open handles:"), DLT_INT(MaxPersHandle));
620 pthread_mutex_unlock(&gMtx);
626 void close_cursor_handle(int handlerDB)
628 if(pthread_mutex_lock(&gMtx) == 0)
630 if(gFreeCursorHandleIdxHead < MaxPersHandle)
632 gFreeCursorHandleArray[gFreeCursorHandleIdxHead++] = handlerDB;
634 pthread_mutex_unlock(&gMtx);
640 int pers_db_cursor_create(char* dbPath)
643 itzam_state state = ITZAM_FAILED;
645 handle = get_cursor_handle();
647 if(handle < MaxPersHandle && handle >= 0)
650 state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 1/*recover*/, 0/*read_only*/);
651 if (state != ITZAM_OKAY)
653 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_create ==> itzam_btree_open"), DLT_STRING(STATE_MESSAGES[state]));
659 state = itzam_btree_cursor_create(&gCursorArray[handle].m_cursor, &gCursorArray[handle].m_btree);
660 if(state == ITZAM_OKAY)
662 gCursorArray[handle].m_empty = 0;
666 gCursorArray[handle].m_empty = 1;
675 int pers_db_cursor_next(unsigned int handlerDB)
678 //if(handlerDB < MaxPersHandle && handlerDB >= 0)
679 if(handlerDB < MaxPersHandle )
681 if(gCursorArray[handlerDB].m_empty != 1)
684 success = itzam_btree_cursor_next(&gCursorArray[handlerDB].m_cursor);
686 if(success == itzam_true)
692 rval = EPERS_LAST_ENTRY_IN_DB;
697 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> invalid handle: "), DLT_INT(handlerDB));
702 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
709 int pers_db_cursor_get_key(unsigned int handlerDB, char * bufKeyName_out, int bufSize)
712 KeyValuePair_s search;
714 if(handlerDB < MaxPersHandle)
716 if(gCursorArray[handlerDB].m_empty != 1)
719 itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
720 length = strlen(search.m_key);
723 memcpy(bufKeyName_out, search.m_key, length);
728 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_key ==> buffer to small » keySize: "), DLT_INT(bufSize));
733 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key ==> invalid handle:"), DLT_INT(handlerDB));
738 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
745 int pers_db_cursor_get_data(unsigned int handlerDB, char * bufData_out, int bufSize)
748 KeyValuePair_s search;
750 if(handlerDB < MaxPersHandle)
752 if(gCursorArray[handlerDB].m_empty != 1)
755 itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
757 length = strlen(search.m_data);
760 memcpy(bufData_out, search.m_data, length);
765 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data ==> buffer to small » keySize: "), DLT_INT(bufSize));
770 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> invalid handle:"), DLT_INT(handlerDB));
775 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
782 int pers_db_cursor_get_data_size(unsigned int handlerDB)
785 KeyValuePair_s search;
787 if(handlerDB < MaxPersHandle)
789 if(gCursorArray[handlerDB].m_empty != 1)
791 itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
792 size = strlen(search.m_data);
796 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data_size ==> invalid handle:"), DLT_INT(handlerDB));
801 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
808 int pers_db_cursor_destroy(unsigned int handlerDB)
811 if(handlerDB < MaxPersHandle)
813 itzam_btree_cursor_free(&gCursorArray[handlerDB].m_cursor);
814 gCursorArray[handlerDB].m_empty = 1;
816 itzam_state state = ITZAM_FAILED;
817 state = itzam_btree_close(&gCursorArray[handlerDB].m_btree);
818 if (state != ITZAM_OKAY)
820 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_destroy ==> itzam_btree_close: Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
823 close_cursor_handle(handlerDB);
833 //-----------------------------------------------------------------------------
834 // code to print database content (for debugging)
835 //-----------------------------------------------------------------------------
839 itzam_btree_cursor cursor;
840 state = itzam_btree_cursor_create(&cursor, &btree);
841 if(state == ITZAM_OKAY)
843 printf("==> Database content ==> db size: %d\n", (int)itzam_btree_count(&btree));
846 // get the key pointed to by the cursor
847 state = itzam_btree_cursor_read(&cursor,(void *)&rec);
848 if (state == ITZAM_OKAY)
850 printf(" Key: %s \n ==> data: %s\n", rec.m_key, rec.m_data);
853 fprintf(stderr, "\nItzam problem: %s\n", STATE_MESSAGES[state]);
855 while (itzam_btree_cursor_next(&cursor));
857 state = itzam_btree_cursor_free(&cursor);
860 //-----------------------------------------------------------------------------