Added backup file and checksum creation for files
[profile/ivi/persistence-client-library.git] / src / persistence_client_library_db_access.c
1 /******************************************************************************
2  * Project         Persistency
3  * (c) copyright   2012
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 ******************************************************************************/
11  /**
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
17  * @see            
18  */
19
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"
24
25 #include "persistence_client_library_dbus_service.h"
26
27 #include <dbus/dbus.h>
28 #include <string.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31
32
33 /// definition of a key-value pair stored in the database
34 typedef struct _KeyValuePair_s
35 {
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
39 }
40 KeyValuePair_s;
41
42
43 // definition of a cursor entry
44 typedef struct _CursorEntry_s
45 {
46    itzam_btree_cursor m_cursor;
47    itzam_btree        m_btree;
48    int                m_empty;
49 }
50 CursorEntry_s;
51
52 // cursor array handle
53 CursorEntry_s gCursorArray[MaxPersHandle];
54
55 /// handle index
56 static int gHandleIdx = 1;
57
58 /// free handle array
59 int gFreeCursorHandleArray[MaxPersHandle];
60 // free head index
61 int gFreeCursorHandleIdxHead = 0;
62
63 // mutex to controll access to the cursor array
64 pthread_mutex_t gMtx = PTHREAD_MUTEX_INITIALIZER;
65
66
67 /// btree array
68 static itzam_btree gBtree[DbTableSize][PersistencePolicy_LastEntry];
69 static int gBtreeCreated[DbTableSize][PersistencePolicy_LastEntry] = { {0} };
70
71
72 itzam_btree* pers_db_open(PersistenceInfo_s* info, const char* dbPath)
73 {
74    int arrayIdx = 0;
75    itzam_btree* btree = NULL;
76
77    // create array index: index is a combination of resource config table type and group
78    arrayIdx = info->configKey.storage + info->context.ldbid ;
79
80    //if(arrayIdx <= DbTableSize)
81    if(arrayIdx < DbTableSize)
82    {
83       if(gBtreeCreated[arrayIdx][info->configKey.policy] == 0)
84       {
85          itzam_state  state = ITZAM_FAILED;
86          state = itzam_btree_open(&gBtree[arrayIdx][info->configKey.policy], dbPath,
87                                   itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
88          if (state != ITZAM_OKAY)
89          {
90             fprintf(stderr, "pers_db_open ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
91          }
92          gBtreeCreated[arrayIdx][info->configKey.policy] = 1;
93       }
94       // assign database
95       btree = &gBtree[arrayIdx][info->configKey.policy];
96    }
97    else
98    {
99       printf("btree_get ==> invalid storage type\n");
100    }
101    return btree;
102 }
103
104
105
106 void pers_db_close(PersistenceInfo_s* info)
107 {
108    int arrayIdx = info->configKey.storage + info->context.ldbid;
109
110    if(info->configKey.storage <= PersistenceStorage_shared )
111    {
112       itzam_state  state = ITZAM_FAILED;
113       state = itzam_btree_close(&gBtree[arrayIdx][info->configKey.policy]);
114       if (state != ITZAM_OKAY)
115       {
116          fprintf(stderr, "pers_db_close ==> Close Itzam problem: %s\n", STATE_MESSAGES[state]);
117       }
118       gBtreeCreated[arrayIdx][info->configKey.policy] = 0;
119    }
120    else
121    {
122       printf("pers_db_close ==> invalid storage type\n");
123    }
124 }
125
126
127
128 void pers_db_close_all()
129 {
130    int i = 0;
131
132    for(i=0; i<DbTableSize; i++)
133    {
134       // close write cached database
135       if(gBtreeCreated[i][PersistencePolicy_wc] == 1)
136       {
137          itzam_state  state = ITZAM_FAILED;
138          state = itzam_btree_close(&gBtree[i][PersistencePolicy_wc]);
139          if (state != ITZAM_OKAY)
140          {
141             fprintf(stderr, "pers_db_close_all ==> Close WC: Itzam problem: %s\n", STATE_MESSAGES[state]);
142          }
143          gBtreeCreated[i][PersistencePolicy_wc] = 0;
144       }
145
146       // close write through database
147       if(gBtreeCreated[i][PersistencePolicy_wt] == 1)
148       {
149          itzam_state  state = ITZAM_FAILED;
150          state = itzam_btree_close(&gBtree[i][PersistencePolicy_wt]);
151          if (state != ITZAM_OKAY)
152          {
153             fprintf(stderr, "pers_db_close_all ==> Close WT: Itzam problem: %s\n", STATE_MESSAGES[state]);
154          }
155          gBtreeCreated[i][PersistencePolicy_wt] = 0;
156       }
157    }
158 }
159
160
161
162 int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
163 {
164    int read_size = -1;
165
166    if(   PersistenceStorage_shared == info->configKey.storage
167       || PersistenceStorage_local == info->configKey.storage)
168    {
169       itzam_btree* btree = NULL;
170       itzam_state  state = ITZAM_FAILED;
171       KeyValuePair_s search;
172
173       btree = pers_db_open(info, dbPath);
174       if(btree != NULL)
175       {
176          if(itzam_true == itzam_btree_find(btree, key, &search))
177          {
178             read_size = search.m_data_size;
179             if(read_size > buffer_size)
180             {
181                read_size = buffer_size;   // truncate data size to buffer size
182             }
183             memcpy(buffer, search.m_data, read_size);
184          }
185          else
186          {
187             read_size = EPERS_NOKEY;
188          }
189       }
190       else
191       {
192          read_size = EPERS_NOPRCTABLE;
193          fprintf(stderr, "\npersistence_get_data ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
194       }
195    }
196    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
197    {
198       int idx =  custom_client_name_to_id(dbPath, 1);
199       char workaroundPath[128];  // workaround, because /sys/ can not be accessed on host!!!!
200       snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath  );
201
202       if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_get_data != NULL) )
203       {
204          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
205             gPersCustomFuncs[idx].custom_plugin_get_data(key, (char*)buffer, buffer_size);
206          else
207             gPersCustomFuncs[idx].custom_plugin_get_data(info->configKey.customID, (char*)buffer, buffer_size);
208       }
209       else
210       {
211          read_size = EPERS_NOPLUGINFUNCT;
212       }
213    }
214    return read_size;
215 }
216
217
218
219 int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
220 {
221    int write_size = -1;
222
223    if(   PersistenceStorage_local == info->configKey.storage
224       || PersistenceStorage_shared == info->configKey.storage )
225    {
226       write_size = buffer_size;
227       itzam_btree* btree = NULL;
228       itzam_state  state = ITZAM_FAILED;
229       KeyValuePair_s insert;
230
231       btree = pers_db_open(info, dbPath);
232       if(btree != NULL)
233       {
234          int keySize = 0;
235          keySize = (int)strlen((const char*)key);
236          if(keySize < DbKeySize)
237          {
238             int dataSize = 0;
239             dataSize = (int)strlen( (const char*)buffer);
240             if(dataSize < DbValueSize)
241             {
242                // -----------------------------------------------------------------------------
243                // transaction start
244                itzam_btree_transaction_start(btree);
245
246                // key
247                memset(insert.m_key, 0, DbKeySize);
248                memcpy(insert.m_key, key, keySize);
249                if(itzam_true == itzam_btree_find(btree, key, &insert))
250                {
251                   // key already available, so delete "old" key
252                   state = itzam_btree_remove(btree, (const void *)&insert);
253                }
254
255                // data
256                memset(insert.m_data, 0, DbValueSize);
257                memcpy(insert.m_data, buffer, dataSize);
258
259                // data size
260                insert.m_data_size = buffer_size;
261
262                state = itzam_btree_insert(btree,(const void *)&insert);
263                if (state != ITZAM_OKAY)
264                {
265                   fprintf(stderr, "\npersistence_set_data ==> Insert Itzam problem: %s\n", STATE_MESSAGES[state]);
266                   write_size = EPERS_DB_ERROR_INTERNAL;
267                }
268
269
270                itzam_btree_transaction_commit(btree);
271                // transaction end
272                // -----------------------------------------------------------------------------
273
274                if(PersistenceStorage_shared == info->configKey.storage)
275                {
276                   // send changed notification
277                   DBusMessage* message;
278                   char ldbid_array[12];
279                   char user_array[12];
280                   char seat_array[12];
281                   const char* ldbid_ptr = ldbid_array;
282                   const char* user_ptr = user_array;
283                   const char* seat_ptr = seat_array;
284
285                   memset(ldbid_array, 0, 12);
286                   memset(user_array, 0, 12);
287                   memset(seat_array, 0, 12);
288
289                   // dbus_bus_add_match is used for the notification mechanism,
290                   // and this works only for type DBUS_TYPE_STRING as message arguments
291                   // this is the reason to use string instead of integer types directly
292                   snprintf(ldbid_array, 12, "%d", info->context.ldbid);
293                   snprintf(user_array,  12, "%d", info->context.user_no);
294                   snprintf(seat_array,  12, "%d", info->context.seat_no);
295
296                   message = dbus_message_new_signal("/org/genivi/persistence/adminconsumer",     // const char *path,
297                                                     "org.genivi.persistence.adminconsumer",      // const char *interface,
298                                                     "PersistenceValueChanged" );                 // const char *name
299
300                   dbus_message_append_args(message,
301                                            DBUS_TYPE_STRING, &key,
302                                            DBUS_TYPE_STRING, &ldbid_ptr,
303                                            DBUS_TYPE_STRING, &user_ptr,
304                                            DBUS_TYPE_STRING, &seat_ptr,
305                                            DBUS_TYPE_INVALID);
306
307                    // Send the signal
308                    dbus_connection_send(get_dbus_connection(), message, NULL);
309
310                    // Free the signal now we have finished with it
311                    dbus_message_unref(message);
312                }
313             }
314             else
315             {
316                fprintf(stderr, "\npersistence_set_data ==> set_value_to_table_itzam => data to long » size %d | maxSize: %d\n", dataSize, DbKeySize);
317                write_size = EPERS_DB_VALUE_SIZE;
318             }
319          }
320          else
321          {
322             fprintf(stderr, "\nset_value_to_table_itzam => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize);
323             write_size = EPERS_DB_KEY_SIZE;
324          }
325       }
326       else
327       {
328          write_size = EPERS_NOPRCTABLE;
329          fprintf(stderr, "\npersistence_set_data ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
330       }
331    }
332    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
333    {
334       int idx = custom_client_name_to_id(dbPath, 1);
335       if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data) )
336       {
337          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
338             gPersCustomFuncs[idx].custom_plugin_set_data(key, (char*)buffer, buffer_size);
339          else
340             gPersCustomFuncs[idx].custom_plugin_set_data(info->configKey.customID, (char*)buffer, buffer_size);
341       }
342       else
343       {
344          write_size = EPERS_NOPLUGINFUNCT;
345       }
346    }
347    return write_size;
348 }
349
350
351
352 int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
353 {
354    int read_size = -1;
355
356    if(   PersistenceStorage_shared == info->configKey.storage
357       || PersistenceStorage_local == info->configKey.storage)
358    {
359       int keySize = 0;
360       itzam_btree*  btree = NULL;
361       itzam_state  state = ITZAM_FAILED;
362       KeyValuePair_s search;
363
364       btree = pers_db_open(info, dbPath);
365       if(btree != NULL)
366       {
367          keySize = (int)strlen((const char*)key);
368          if(keySize < DbKeySize)
369          {
370             memset(search.m_key,0, DbKeySize);
371             memcpy(search.m_key, key, keySize);
372             if(itzam_true == itzam_btree_find(btree, key, &search))
373             {
374                read_size = search.m_data_size;
375             }
376             else
377             {
378                read_size = EPERS_NOKEY;
379             }
380          }
381          else
382          {
383             fprintf(stderr, "persistence_get_data_size => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize);
384             read_size = EPERS_DB_KEY_SIZE;
385          }
386       }
387       else
388       {
389          read_size = EPERS_NOPRCTABLE;
390          fprintf(stderr, "\npersistence_get_data_size ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
391       }
392    }
393    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
394    {
395       int idx = custom_client_name_to_id(dbPath, 1);
396       if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data) )
397       {
398          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
399             gPersCustomFuncs[idx].custom_plugin_get_size(key);
400          else
401             gPersCustomFuncs[idx].custom_plugin_get_size(info->configKey.customID);
402       }
403       else
404       {
405          read_size = EPERS_NOPLUGINFUNCT;
406       }
407    }
408    return read_size;
409 }
410
411
412
413 int pers_db_delete_key(char* dbPath, char* dbKey, PersistenceInfo_s* info)
414 {
415    int ret = 0;
416    if(PersistenceStorage_custom != info->configKey.storage)
417    {
418       itzam_btree*  btree = NULL;
419       KeyValuePair_s delete;
420
421       //printf("delete_key_from_table_itzam => Path: \"%s\" | key: \"%s\" \n", dbPath, key);
422       btree = pers_db_open(info, dbPath);
423       if(btree != NULL)
424       {
425          int keySize = 0;
426          keySize = (int)strlen((const char*)dbKey);
427          if(keySize < DbKeySize)
428          {
429             // -----------------------------------------------------------------------------
430             // transaction start
431             itzam_btree_transaction_start(btree);
432
433             itzam_state  state;
434
435             memset(delete.m_key,0, DbKeySize);
436             memcpy(delete.m_key, dbKey, keySize);
437             state = itzam_btree_remove(btree, (const void *)&delete);
438             if (state != ITZAM_OKAY)
439             {
440                fprintf(stderr, "persistence_delete_data ==> Remove Itzam problem: %s\n", STATE_MESSAGES[state]);
441                ret = EPERS_DB_ERROR_INTERNAL;
442             }
443             itzam_btree_transaction_commit(btree);
444             // transaction end
445             // -----------------------------------------------------------------------------
446          }
447          else
448          {
449             fprintf(stderr, "persistence_delete_data => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize);
450             ret = EPERS_DB_KEY_SIZE;
451          }
452       }
453       else
454       {
455          fprintf(stderr, "persistence_delete_data => no prct table\n");
456          ret = EPERS_NOPRCTABLE;
457       }
458    }
459    else   // custom storage implementation via custom library
460    {
461       int idx = custom_client_name_to_id(dbPath, 1);
462       if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data) )
463       {
464          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
465             gPersCustomFuncs[idx].custom_plugin_delete_data(dbKey);
466          else
467             gPersCustomFuncs[idx].custom_plugin_delete_data(info->configKey.customID);
468       }
469       else
470       {
471          ret = EPERS_NOPLUGINFUNCT;
472       }
473    }
474    return ret;
475 }
476
477
478 int persistence_reg_notify_on_change(char* dbPath, char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no,
479                                      pclChangeNotifyCallback_t callback)
480 {
481    int rval = -1;
482    DBusError error;
483    dbus_error_init (&error);
484    char rule[300];
485    char ldbid_array[12];
486    char user_array[12];
487    char seat_array[12];
488
489    memset(ldbid_array, 0, 12);
490    memset(user_array, 0, 12);
491    memset(seat_array, 0, 12);
492
493    // assign callback
494    gChangeNotifyCallback = callback;
495
496    // dbus_bus_add_match works only for type DBUS_TYPE_STRING as message arguments
497    // this is the reason to use string instead of integer types directly
498    snprintf(ldbid_array, 12, "%u", ldbid);
499    snprintf(user_array,  12, "%u", user_no);
500    snprintf(seat_array,  12, "%u", seat_no);
501
502    snprintf(rule, 256, "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceValueChanged',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%s',arg2='%s',arg3='%s'",
503             key, ldbid_array, user_array, seat_array);
504
505    dbus_bus_add_match(get_dbus_connection(), rule, &error);
506
507    return rval;
508 }
509
510
511
512 //---------------------------------------------------------------------------------------------------------
513 // C U R S O R    F U N C T I O N S
514 //---------------------------------------------------------------------------------------------------------
515
516 int get_cursor_handle()
517 {
518    int handle = 0;
519
520    if(pthread_mutex_lock(&gMtx) == 0)
521    {
522       if(gFreeCursorHandleIdxHead > 0)   // check if we have a free spot in the array before the current max
523       {
524          handle = gFreeCursorHandleArray[--gFreeCursorHandleIdxHead];
525       }
526       else
527       {
528          if(gHandleIdx < MaxPersHandle-1)
529          {
530             handle = gHandleIdx++;  // no free spot before current max, increment handle index
531          }
532          else
533          {
534             handle = -1;
535             printf("get_persistence_handle_idx => Reached maximum of open handles: %d \n", MaxPersHandle);
536          }
537       }
538       pthread_mutex_unlock(&gMtx);
539    }
540    return handle;
541 }
542
543
544 void close_cursor_handle(int handlerDB)
545 {
546    if(pthread_mutex_lock(&gMtx) == 0)
547    {
548       if(gFreeCursorHandleIdxHead < MaxPersHandle)
549       {
550          gFreeCursorHandleArray[gFreeCursorHandleIdxHead++] = handlerDB;
551       }
552       pthread_mutex_unlock(&gMtx);
553    }
554 }
555
556
557
558 int pers_db_cursor_create(char* dbPath)
559 {
560    int handle = -1;
561    itzam_state  state = ITZAM_FAILED;
562
563    handle = get_cursor_handle();
564
565    if(handle < MaxPersHandle && handle >= 0)
566    {
567       // open database
568       state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 1/*recover*/, 0/*read_only*/);
569       if (state != ITZAM_OKAY)
570       {
571          fprintf(stderr, "pers_db_open ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
572       }
573       else
574       {
575          itzam_state  state;
576
577          state = itzam_btree_cursor_create(&gCursorArray[handle].m_cursor, &gCursorArray[handle].m_btree);
578          if(state == ITZAM_OKAY)
579          {
580             gCursorArray[handle].m_empty = 0;
581          }
582          else
583          {
584             gCursorArray[handle].m_empty = 1;
585          }
586       }
587    }
588    return handle;
589 }
590
591
592
593 int pers_db_cursor_next(unsigned int handlerDB)
594 {
595    int rval = -1;
596    //if(handlerDB < MaxPersHandle && handlerDB >= 0)
597    if(handlerDB < MaxPersHandle )
598    {
599       if(gCursorArray[handlerDB].m_empty != 1)
600       {
601          itzam_bool success;
602          success = itzam_btree_cursor_next(&gCursorArray[handlerDB].m_cursor);
603
604          if(success == itzam_true)
605          {
606             rval = 0;
607          }
608          else
609          {
610             rval = EPERS_LAST_ENTRY_IN_DB;
611          }
612       }
613       else
614       {
615          printf("persistence_db_cursor_get_key ==> invalid handle: %u \n", handlerDB);
616       }
617    }
618    else
619    {
620       printf("persistence_db_cursor_get_key ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
621    }
622    return rval;
623 }
624
625
626
627 int pers_db_cursor_get_key(unsigned int handlerDB, char * bufKeyName_out, int bufSize)
628 {
629    int rval = -1;
630    KeyValuePair_s search;
631
632    if(handlerDB < MaxPersHandle)
633    {
634       if(gCursorArray[handlerDB].m_empty != 1)
635       {
636          int length = 0;
637          itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
638          length = strlen(search.m_key);
639          if(length < bufSize)
640          {
641             memcpy(bufKeyName_out, search.m_key, length);
642             rval = 0;
643          }
644          else
645          {
646             printf("persistence_db_cursor_get_key ==> buffer to small » keySize: %d | bufSize: %d \n", length, bufSize);
647          }
648       }
649       else
650       {
651          printf("persistence_db_cursor_get_key ==> invalid handle: %u \n", handlerDB);
652       }
653    }
654    else
655    {
656       printf("persistence_db_cursor_get_key ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
657    }
658    return rval;
659 }
660
661
662
663 int pers_db_cursor_get_data(unsigned int handlerDB, char * bufData_out, int bufSize)
664 {
665    int rval = -1;
666    KeyValuePair_s search;
667
668    if(handlerDB < MaxPersHandle)
669    {
670       if(gCursorArray[handlerDB].m_empty != 1)
671       {
672          int length = 0;
673          itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
674
675          length = strlen(search.m_data);
676          if(length < bufSize)
677          {
678             memcpy(bufData_out, search.m_data, length);
679             rval = 0;
680          }
681          else
682          {
683             printf("persistence_db_cursor_get_data ==> buffer to small » keySize: %d | bufSize: %d \n", length, bufSize);
684          }
685       }
686       else
687       {
688          printf("persistence_db_cursor_get_data ==> invalid handle: %u \n", handlerDB);
689       }
690    }
691    else
692    {
693       printf("persistence_db_cursor_get_data ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
694    }
695    return rval;
696 }
697
698
699
700 int pers_db_cursor_get_data_size(unsigned int handlerDB)
701 {
702    int size = -1;
703    KeyValuePair_s search;
704
705    if(handlerDB < MaxPersHandle)
706    {
707       if(gCursorArray[handlerDB].m_empty != 1)
708       {
709          itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
710          size = strlen(search.m_data);
711       }
712       else
713       {
714          printf("persistence_db_cursor_get_data ==> invalid handle: %u \n", handlerDB);
715       }
716    }
717    else
718    {
719       printf("persistence_db_cursor_get_data ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
720    }
721    return size;
722 }
723
724
725
726 int pers_db_cursor_destroy(unsigned int handlerDB)
727 {
728    int rval = -1;
729    if(handlerDB < MaxPersHandle)
730    {
731       itzam_btree_cursor_free(&gCursorArray[handlerDB].m_cursor);
732       gCursorArray[handlerDB].m_empty = 1;
733
734       itzam_state state = ITZAM_FAILED;
735       state = itzam_btree_close(&gCursorArray[handlerDB].m_btree);
736       if (state != ITZAM_OKAY)
737       {
738             fprintf(stderr, "pers_db_cursor_destroy ==> Close: Itzam problem: %s\n", STATE_MESSAGES[state]);
739       }
740
741       close_cursor_handle(handlerDB);
742
743       rval = 0;
744    }
745    return rval;
746 }
747
748
749
750
751 //-----------------------------------------------------------------------------
752 // code to print database content (for debugging)
753 //-----------------------------------------------------------------------------
754 // walk the database
755 /*
756 KeyValuePair_s  rec;
757 itzam_btree_cursor cursor;
758 state = itzam_btree_cursor_create(&cursor, &btree);
759 if(state == ITZAM_OKAY)
760 {
761   printf("==> Database content ==> db size: %d\n", (int)itzam_btree_count(&btree));
762   do
763   {
764      // get the key pointed to by the cursor
765      state = itzam_btree_cursor_read(&cursor,(void *)&rec);
766      if (state == ITZAM_OKAY)
767      {
768        printf("   Key: %s \n     ==> data: %s\n", rec.m_key, rec.m_data);
769      }
770      else
771         fprintf(stderr, "\nItzam problem: %s\n", STATE_MESSAGES[state]);
772   }
773   while (itzam_btree_cursor_next(&cursor));
774
775   state = itzam_btree_cursor_free(&cursor);
776 }
777 */
778 //-----------------------------------------------------------------------------
779
780
781
782
783