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;
387 itzam_btree_transaction_commit(btree);
389 // -----------------------------------------------------------------------------
391 if(PersistenceStorage_shared == info->configKey.storage)
393 write_size = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
398 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> data to long » size:"), DLT_INT(dataSize), DLT_INT(DbValueSize) );
399 write_size = EPERS_DB_VALUE_SIZE;
404 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> key to long » size"), DLT_INT(keySize), DLT_INT(DbKeySize) );
405 write_size = EPERS_DB_KEY_SIZE;
410 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
411 write_size = EPERS_NOPRCTABLE;
414 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) && (gPersCustomFuncs[idx].custom_plugin_set_data != NULL) )
419 char pathKeyString[128] = {0};
420 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
422 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
426 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
428 write_size = gPersCustomFuncs[idx].custom_plugin_set_data(pathKeyString, (char*)buffer, buffer_size);
430 if(write_size >= 0) // success ==> send deleted notification
432 write_size = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
437 write_size = EPERS_NOPLUGINFUNCT;
445 int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
449 if( PersistenceStorage_shared == info->configKey.storage
450 || PersistenceStorage_local == info->configKey.storage)
453 itzam_btree* btree = NULL;
454 KeyValuePair_s search;
456 btree = pers_db_open(info, dbPath);
459 keySize = (int)strlen((const char*)key);
460 if(keySize < DbKeySize)
462 memset(search.m_key,0, DbKeySize);
463 memcpy(search.m_key, key, keySize);
464 if(itzam_true == itzam_btree_find(btree, key, &search))
466 read_size = search.m_data_size;
470 read_size = EPERS_NOKEY;
475 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
476 read_size = EPERS_DB_KEY_SIZE;
481 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> no config table"), DLT_STRING(dbPath), DLT_STRING(key));
482 read_size = EPERS_NOPRCTABLE;
485 else if(PersistenceStorage_custom == info->configKey.storage) // custom storage implementation via custom library
487 int idx = custom_client_name_to_id(dbPath, 1);
488 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_size != NULL) )
490 char pathKeyString[128] = {0};
491 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
493 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
497 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
499 read_size = gPersCustomFuncs[idx].custom_plugin_get_size(pathKeyString);
503 read_size = EPERS_NOPLUGINFUNCT;
511 int pers_db_delete_key(char* dbPath, char* key, PersistenceInfo_s* info)
514 if(PersistenceStorage_custom != info->configKey.storage)
516 itzam_btree* btree = NULL;
517 KeyValuePair_s delete;
519 btree = pers_db_open(info, dbPath);
523 keySize = (int)strlen((const char*)key);
524 if(keySize < DbKeySize)
526 // -----------------------------------------------------------------------------
528 itzam_btree_transaction_start(btree);
532 memset(delete.m_key,0, DbKeySize);
533 memcpy(delete.m_key, key, keySize);
534 state = itzam_btree_remove(btree, (const void *)&delete);
535 if (state != ITZAM_OKAY)
537 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> itzam_btree_remove => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
538 ret = EPERS_DB_ERROR_INTERNAL;
540 itzam_btree_transaction_commit(btree);
542 // -----------------------------------------------------------------------------
544 if(PersistenceStorage_shared == info->configKey.storage)
546 ret = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
551 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
552 ret = EPERS_DB_KEY_SIZE;
557 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
558 ret = EPERS_NOPRCTABLE;
561 else // custom storage implementation via custom library
563 int idx = custom_client_name_to_id(dbPath, 1);
564 if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_delete_data != NULL) )
566 char pathKeyString[128] = {0};
567 if(info->configKey.customID[0] == '\0') // if we have not a customID we use the key
569 snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
573 snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
575 ret = gPersCustomFuncs[idx].custom_plugin_delete_data(pathKeyString);
576 if(ret >= 0) // success ==> send deleted notification
578 ret = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
583 ret = EPERS_NOPLUGINFUNCT;
590 int persistence_notify_on_change(char* dbPath, char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no,
591 pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
594 char ruleChanged[DbusMatchRuleSize];
595 char ruleDeleted[DbusMatchRuleSize];
596 char ruleCreated[DbusMatchRuleSize];
597 DBusConnection* conn = get_dbus_connection();
599 // add match for c h a n g e
600 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'",
601 key, ldbid, user_no, seat_no);
602 // add match for d e l e t e
603 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'",
604 key, ldbid, user_no, seat_no);
605 // add match for c r e a t e
606 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'",
607 key, ldbid, user_no, seat_no);
609 if(regPolicy == Notify_register)
612 gChangeNotifyCallback = callback;
614 dbus_bus_add_match(conn, ruleChanged, NULL);
615 dbus_bus_add_match(conn, ruleDeleted, NULL);
616 dbus_bus_add_match(conn, ruleCreated, NULL);
618 else if(regPolicy == Notify_unregister)
621 gChangeNotifyCallback = NULL;
623 dbus_bus_remove_match(conn, ruleChanged, NULL);
624 dbus_bus_remove_match(conn, ruleDeleted, NULL);
625 dbus_bus_remove_match(conn, ruleCreated, NULL);
628 dbus_connection_flush(conn); // flush the connection to add the match
634 int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, pclNotifyStatus_e reason)
636 DBusMessage* message;
639 char ldbid_array[DbusSubMatchSize] = {0};
640 char user_array[DbusSubMatchSize] = {0};
641 char seat_array[DbusSubMatchSize] = {0};
642 const char* ldbid_ptr = ldbid_array;
643 const char* user_ptr = user_array;
644 const char* seat_ptr = seat_array;
646 char* changeSignal = "PersistenceResChange";
647 char* deleteSignal = "PersistenceResDelete";
648 char* createSignal = "PersistenceResCreate";
649 char* theReason = NULL;
651 DBusConnection* conn = get_dbus_connection();
654 // dbus_bus_add_match is used for the notification mechanism,
655 // and this works only for type DBUS_TYPE_STRING as message arguments
656 // this is the reason to use string instead of integer types directly
657 snprintf(ldbid_array, DbusSubMatchSize, "%d", context->ldbid);
658 snprintf(user_array, DbusSubMatchSize, "%d", context->user_no);
659 snprintf(seat_array, DbusSubMatchSize, "%d", context->seat_no);
663 case pclNotifyStatus_deleted:
664 theReason = deleteSignal;
666 case pclNotifyStatus_created:
667 theReason = createSignal;
669 case pclNotifyStatus_changed:
670 theReason = changeSignal;
673 theReason = changeSignal;
677 if(theReason != NULL)
679 message = dbus_message_new_signal("/org/genivi/persistence/adminconsumer", // const char *path,
680 "org.genivi.persistence.adminconsumer", // const char *interface,
681 theReason); // const char *name
683 ret = dbus_message_append_args(message,
684 DBUS_TYPE_STRING, &key,
685 DBUS_TYPE_STRING, &ldbid_ptr,
686 DBUS_TYPE_STRING, &user_ptr,
687 DBUS_TYPE_STRING, &seat_ptr,
694 if(dbus_connection_send(conn, message, 0) == TRUE)
696 // Free the signal now we have finished with it
697 dbus_message_unref(message);
701 rval = EPERS_NOTIFY_SIG;
706 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!!"));
711 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_send_Notification_Signal ==> ERROR dbus_message_append_args"));
712 rval = EPERS_NOTIFY_SIG;
717 rval = EPERS_NOTIFY_SIG;
724 //---------------------------------------------------------------------------------------------------------
725 // C U R S O R F U N C T I O N S
726 //---------------------------------------------------------------------------------------------------------
728 int get_cursor_handle()
732 if(pthread_mutex_lock(&gMtx) == 0)
734 if(gFreeCursorHandleIdxHead > 0) // check if we have a free spot in the array before the current max
736 handle = gFreeCursorHandleArray[--gFreeCursorHandleIdxHead];
740 if(gHandleIdx < MaxPersHandle-1)
742 handle = gHandleIdx++; // no free spot before current max, increment handle index
746 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("get_cursor_handle ==> Reached maximum of open handles:"), DLT_INT(MaxPersHandle));
750 pthread_mutex_unlock(&gMtx);
756 void close_cursor_handle(int handlerDB)
758 if(pthread_mutex_lock(&gMtx) == 0)
760 if(gFreeCursorHandleIdxHead < MaxPersHandle)
762 gFreeCursorHandleArray[gFreeCursorHandleIdxHead++] = handlerDB;
764 pthread_mutex_unlock(&gMtx);
770 int pers_db_cursor_create(char* dbPath)
773 itzam_state state = ITZAM_FAILED;
775 handle = get_cursor_handle();
777 if(handle < MaxPersHandle && handle >= 0)
780 state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 1/*recover*/, 0/*read_only*/);
781 if (state != ITZAM_OKAY)
783 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_create ==> itzam_btree_open"), DLT_STRING(STATE_MESSAGES[state]));
789 state = itzam_btree_cursor_create(&gCursorArray[handle].m_cursor, &gCursorArray[handle].m_btree);
790 if(state == ITZAM_OKAY)
792 gCursorArray[handle].m_empty = 0;
796 gCursorArray[handle].m_empty = 1;
805 int pers_db_cursor_next(unsigned int handlerDB)
808 //if(handlerDB < MaxPersHandle && handlerDB >= 0)
809 if(handlerDB < MaxPersHandle )
811 if(gCursorArray[handlerDB].m_empty != 1)
814 success = itzam_btree_cursor_next(&gCursorArray[handlerDB].m_cursor);
816 if(success == itzam_true)
822 rval = EPERS_LAST_ENTRY_IN_DB;
827 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> invalid handle: "), DLT_INT(handlerDB));
832 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
839 int pers_db_cursor_get_key(unsigned int handlerDB, char * bufKeyName_out, int bufSize)
842 KeyValuePair_s search;
844 if(handlerDB < MaxPersHandle)
846 if(gCursorArray[handlerDB].m_empty != 1)
849 itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
850 length = strlen(search.m_key);
853 memcpy(bufKeyName_out, search.m_key, length);
858 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_key ==> buffer to small » keySize: "), DLT_INT(bufSize));
863 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key ==> invalid handle:"), DLT_INT(handlerDB));
868 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
875 int pers_db_cursor_get_data(unsigned int handlerDB, char * bufData_out, int bufSize)
878 KeyValuePair_s search;
880 if(handlerDB < MaxPersHandle)
882 if(gCursorArray[handlerDB].m_empty != 1)
885 itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
887 length = strlen(search.m_data);
890 memcpy(bufData_out, search.m_data, length);
895 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data ==> buffer to small » keySize: "), DLT_INT(bufSize));
900 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> invalid handle:"), DLT_INT(handlerDB));
905 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
912 int pers_db_cursor_get_data_size(unsigned int handlerDB)
915 KeyValuePair_s search;
917 if(handlerDB < MaxPersHandle)
919 if(gCursorArray[handlerDB].m_empty != 1)
921 itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
922 size = strlen(search.m_data);
926 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data_size ==> invalid handle:"), DLT_INT(handlerDB));
931 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
938 int pers_db_cursor_destroy(unsigned int handlerDB)
941 if(handlerDB < MaxPersHandle)
943 itzam_btree_cursor_free(&gCursorArray[handlerDB].m_cursor);
944 gCursorArray[handlerDB].m_empty = 1;
946 itzam_state state = ITZAM_FAILED;
947 state = itzam_btree_close(&gCursorArray[handlerDB].m_btree);
948 if (state != ITZAM_OKAY)
950 DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_destroy ==> itzam_btree_close: Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
953 close_cursor_handle(handlerDB);
963 //-----------------------------------------------------------------------------
964 // code to print database content (for debugging)
965 //-----------------------------------------------------------------------------
969 itzam_btree_cursor cursor;
970 state = itzam_btree_cursor_create(&cursor, &btree);
971 if(state == ITZAM_OKAY)
973 printf("==> Database content ==> db size: %d\n", (int)itzam_btree_count(&btree));
976 // get the key pointed to by the cursor
977 state = itzam_btree_cursor_read(&cursor,(void *)&rec);
978 if (state == ITZAM_OKAY)
980 printf(" Key: %s \n ==> data: %s\n", rec.m_key, rec.m_data);
983 fprintf(stderr, "\nItzam problem: %s\n", STATE_MESSAGES[state]);
985 while (itzam_btree_cursor_next(&cursor));
987 state = itzam_btree_cursor_free(&cursor);
990 //-----------------------------------------------------------------------------