If a customID is available for a customer plugin, used this ID instead the key
[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          //
191          // workaround till lifecycle is working correctly
192          //
193          pers_db_close(info);
194       }
195       else
196       {
197          read_size = EPERS_NOPRCTABLE;
198          fprintf(stderr, "\npersistence_get_data ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
199       }
200    }
201    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
202    {
203       int idx =  custom_client_name_to_id(dbPath, 1);
204       char workaroundPath[128];  // workaround, because /sys/ can not be accessed on host!!!!
205       snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath  );
206
207       if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_get_data != NULL) )
208       {
209          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
210             gPersCustomFuncs[idx].custom_plugin_get_data(key, (char*)buffer, buffer_size);
211          else
212             gPersCustomFuncs[idx].custom_plugin_get_data(info->configKey.customID, (char*)buffer, buffer_size);
213       }
214       else
215       {
216          read_size = EPERS_NOPLUGINFUNCT;
217       }
218    }
219    return read_size;
220 }
221
222
223
224 int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
225 {
226    int write_size = -1;
227
228    if(   PersistenceStorage_local == info->configKey.storage
229       || PersistenceStorage_shared == info->configKey.storage )
230    {
231       write_size = buffer_size;
232       itzam_btree* btree = NULL;
233       itzam_state  state = ITZAM_FAILED;
234       KeyValuePair_s insert;
235
236       btree = pers_db_open(info, dbPath);
237       if(btree != NULL)
238       {
239          int keySize = 0;
240          keySize = (int)strlen((const char*)key);
241          if(keySize < DbKeySize)
242          {
243             int dataSize = 0;
244             dataSize = (int)strlen( (const char*)buffer);
245             if(dataSize < DbValueSize)
246             {
247                // key
248                memset(insert.m_key, 0, DbKeySize);
249                memcpy(insert.m_key, key, keySize);
250                if(itzam_true == itzam_btree_find(btree, key, &insert))
251                {
252                   // key already available, so delete "old" key
253                   state = itzam_btree_remove(btree, (const void *)&insert);
254                }
255
256                // data
257                memset(insert.m_data, 0, DbValueSize);
258                memcpy(insert.m_data, buffer, dataSize);
259
260                // data size
261                insert.m_data_size = buffer_size;
262
263                state = itzam_btree_insert(btree,(const void *)&insert);
264                if (state != ITZAM_OKAY)
265                {
266                   fprintf(stderr, "\npersistence_set_data ==> Insert Itzam problem: %s\n", STATE_MESSAGES[state]);
267                   write_size = EPERS_DB_ERROR_INTERNAL;
268                }
269
270                if(PersistenceStorage_shared == info->configKey.storage)
271                {
272                   // send changed notification
273                   DBusMessage* message;
274                   char ldbid_array[12];
275                   char user_array[12];
276                   char seat_array[12];
277                   const char* ldbid_ptr = ldbid_array;
278                   const char* user_ptr = user_array;
279                   const char* seat_ptr = seat_array;
280
281                   memset(ldbid_array, 0, 12);
282                   memset(user_array, 0, 12);
283                   memset(seat_array, 0, 12);
284
285                   // dbus_bus_add_match is used for the notification mechanism,
286                   // and this works only for type DBUS_TYPE_STRING as message arguments
287                   // this is the reason to use string instead of integer types directly
288                   snprintf(ldbid_array, 12, "%d", info->context.ldbid);
289                   snprintf(user_array,  12, "%d", info->context.user_no);
290                   snprintf(seat_array,  12, "%d", info->context.seat_no);
291
292                   message = dbus_message_new_signal("/org/genivi/persistence/adminconsumer",     // const char *path,
293                                                     "org.genivi.persistence.adminconsumer",      // const char *interface,
294                                                     "PersistenceValueChanged" );                 // const char *name
295
296                   dbus_message_append_args(message,
297                                            DBUS_TYPE_STRING, &key,
298                                            DBUS_TYPE_STRING, &ldbid_ptr,
299                                            DBUS_TYPE_STRING, &user_ptr,
300                                            DBUS_TYPE_STRING, &seat_ptr,
301                                            DBUS_TYPE_INVALID);
302
303                    // Send the signal
304                    dbus_connection_send(get_dbus_connection(), message, NULL);
305
306                    // Free the signal now we have finished with it
307                    dbus_message_unref(message);
308                }
309             }
310             else
311             {
312                fprintf(stderr, "\npersistence_set_data ==> set_value_to_table_itzam => data to long » size %d | maxSize: %d\n", dataSize, DbKeySize);
313                write_size = EPERS_DB_VALUE_SIZE;
314             }
315
316             //
317             // workaround till lifecycle is working correctly
318             //
319             pers_db_close(info);
320          }
321          else
322          {
323             fprintf(stderr, "\nset_value_to_table_itzam => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize);
324             write_size = EPERS_DB_KEY_SIZE;
325          }
326       }
327       else
328       {
329          write_size = EPERS_NOPRCTABLE;
330          fprintf(stderr, "\npersistence_set_data ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
331       }
332    }
333    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
334    {
335       int idx = custom_client_name_to_id(dbPath, 1);
336       if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data) )
337       {
338          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
339             gPersCustomFuncs[idx].custom_plugin_set_data(key, (char*)buffer, buffer_size);
340          else
341             gPersCustomFuncs[idx].custom_plugin_set_data(info->configKey.customID, (char*)buffer, buffer_size);
342       }
343       else
344       {
345          write_size = EPERS_NOPLUGINFUNCT;
346       }
347    }
348    return write_size;
349 }
350
351
352
353 int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
354 {
355    int read_size = -1;
356
357    if(   PersistenceStorage_shared == info->configKey.storage
358       || PersistenceStorage_local == info->configKey.storage)
359    {
360       int keySize = 0;
361       itzam_btree*  btree = NULL;
362       itzam_state  state = ITZAM_FAILED;
363       KeyValuePair_s search;
364
365       btree = pers_db_open(info, dbPath);
366       if(btree != NULL)
367       {
368          keySize = (int)strlen((const char*)key);
369          if(keySize < DbKeySize)
370          {
371             memset(search.m_key,0, DbKeySize);
372             memcpy(search.m_key, key, keySize);
373             if(itzam_true == itzam_btree_find(btree, key, &search))
374             {
375                read_size = strlen(search.m_data);
376             }
377             else
378             {
379                read_size = EPERS_NOKEY;
380             }
381          }
382          else
383          {
384             fprintf(stderr, "persistence_get_data_size => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize);
385             read_size = EPERS_DB_KEY_SIZE;
386          }
387          //
388          // workaround till lifecycle is working correctly
389          //
390          pers_db_close(info);
391       }
392       else
393       {
394          read_size = EPERS_NOPRCTABLE;
395          fprintf(stderr, "\npersistence_get_data_size ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
396       }
397    }
398    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
399    {
400       int idx = custom_client_name_to_id(dbPath, 1);
401       if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data) )
402       {
403          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
404             gPersCustomFuncs[idx].custom_plugin_get_size(key);
405          else
406             gPersCustomFuncs[idx].custom_plugin_get_size(info->configKey.customID);
407       }
408       else
409       {
410          read_size = EPERS_NOPLUGINFUNCT;
411       }
412    }
413    return read_size;
414 }
415
416
417
418 int pers_db_delete_key(char* dbPath, char* dbKey, PersistenceInfo_s* info)
419 {
420    int ret = 0;
421    if(PersistenceStorage_custom != info->configKey.storage)
422    {
423       itzam_btree*  btree = NULL;
424       KeyValuePair_s delete;
425
426       //printf("delete_key_from_table_itzam => Path: \"%s\" | key: \"%s\" \n", dbPath, key);
427       btree = pers_db_open(info, dbPath);
428       if(btree != NULL)
429       {
430          int keySize = 0;
431          keySize = (int)strlen((const char*)dbKey);
432          if(keySize < DbKeySize)
433          {
434             itzam_state  state;
435
436             memset(delete.m_key,0, DbKeySize);
437             memcpy(delete.m_key, dbKey, keySize);
438             state = itzam_btree_remove(btree, (const void *)&delete);
439             if (state != ITZAM_OKAY)
440             {
441                fprintf(stderr, "persistence_delete_data ==> Remove Itzam problem: %s\n", STATE_MESSAGES[state]);
442                ret = EPERS_DB_ERROR_INTERNAL;
443             }
444          }
445          else
446          {
447             fprintf(stderr, "persistence_delete_data => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize);
448             ret = EPERS_DB_KEY_SIZE;
449          }
450          //
451          // workaround till lifecycle is working correctly
452          //
453          pers_db_close(info);
454       }
455       else
456       {
457          fprintf(stderr, "persistence_delete_data => no prct table\n");
458          ret = EPERS_NOPRCTABLE;
459       }
460    }
461    else   // custom storage implementation via custom library
462    {
463       int idx = custom_client_name_to_id(dbPath, 1);
464       if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data) )
465       {
466          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
467             gPersCustomFuncs[idx].custom_plugin_delete_data(dbKey);
468          else
469             gPersCustomFuncs[idx].custom_plugin_delete_data(info->configKey.customID);
470       }
471       else
472       {
473          ret = EPERS_NOPLUGINFUNCT;
474       }
475    }
476    return ret;
477 }
478
479
480 int persistence_reg_notify_on_change(char* dbPath, char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no,
481                                      changeNotifyCallback_t callback)
482 {
483    int rval = -1;
484    DBusError error;
485    dbus_error_init (&error);
486    char rule[300];
487    char ldbid_array[12];
488    char user_array[12];
489    char seat_array[12];
490
491    memset(ldbid_array, 0, 12);
492    memset(user_array, 0, 12);
493    memset(seat_array, 0, 12);
494
495    // assign callback
496    gChangeNotifyCallback = callback;
497
498    // dbus_bus_add_match works only for type DBUS_TYPE_STRING as message arguments
499    // this is the reason to use string instead of integer types directly
500    snprintf(ldbid_array, 12, "%d", ldbid);
501    snprintf(user_array,  12, "%d", user_no);
502    snprintf(seat_array,  12, "%d", seat_no);
503
504    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'",
505             key, ldbid_array, user_array, seat_array);
506
507    dbus_bus_add_match(get_dbus_connection(), rule, &error);
508
509    return rval;
510 }
511
512
513
514 //---------------------------------------------------------------------------------------------------------
515 // C U R S O R    F U N C T I O N S
516 //---------------------------------------------------------------------------------------------------------
517
518 int get_cursor_handle()
519 {
520    int handle = 0;
521
522    if(pthread_mutex_lock(&gMtx) == 0)
523    {
524       if(gFreeCursorHandleIdxHead > 0)   // check if we have a free spot in the array before the current max
525       {
526          handle = gFreeCursorHandleArray[--gFreeCursorHandleIdxHead];
527       }
528       else
529       {
530          if(gHandleIdx < MaxPersHandle-1)
531          {
532             handle = gHandleIdx++;  // no free spot before current max, increment handle index
533          }
534          else
535          {
536             handle = -1;
537             printf("get_persistence_handle_idx => Reached maximum of open handles: %d \n", MaxPersHandle);
538          }
539       }
540       pthread_mutex_unlock(&gMtx);
541    }
542    return handle;
543 }
544
545
546 void close_cursor_handle(int handlerDB)
547 {
548    if(pthread_mutex_lock(&gMtx) == 0)
549    {
550       if(gFreeCursorHandleIdxHead < MaxPersHandle)
551       {
552          gFreeCursorHandleArray[gFreeCursorHandleIdxHead++] = handlerDB;
553       }
554       pthread_mutex_unlock(&gMtx);
555    }
556 }
557
558
559
560 int pers_db_cursor_create(char* dbPath)
561 {
562    int handle = -1;
563    itzam_state  state = ITZAM_FAILED;
564
565    handle = get_cursor_handle();
566
567    if(handle < MaxPersHandle && handle >= 0)
568    {
569       // open database
570       state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
571       if (state != ITZAM_OKAY)
572       {
573          fprintf(stderr, "pers_db_open ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
574       }
575       else
576       {
577          itzam_state  state;
578
579          state = itzam_btree_cursor_create(&gCursorArray[handle].m_cursor, &gCursorArray[handle].m_btree);
580          if(state == ITZAM_OKAY)
581          {
582             gCursorArray[handle].m_empty = 0;
583          }
584          else
585          {
586             gCursorArray[handle].m_empty = 1;
587          }
588       }
589    }
590    return handle;
591 }
592
593
594
595 int pers_db_cursor_next(unsigned int handlerDB)
596 {
597    int rval = -1;
598    //if(handlerDB < MaxPersHandle && handlerDB >= 0)
599    if(handlerDB < MaxPersHandle )
600    {
601       if(gCursorArray[handlerDB].m_empty != 1)
602       {
603          itzam_bool success;
604          success = itzam_btree_cursor_next(&gCursorArray[handlerDB].m_cursor);
605
606          if(success == itzam_true)
607          {
608             rval = 0;
609          }
610          else
611          {
612             rval = EPERS_LAST_ENTRY_IN_DB;
613          }
614       }
615       else
616       {
617          printf("persistence_db_cursor_get_key ==> invalid handle: %u \n", handlerDB);
618       }
619    }
620    else
621    {
622       printf("persistence_db_cursor_get_key ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
623    }
624    return rval;
625 }
626
627
628
629 int pers_db_cursor_get_key(unsigned int handlerDB, char * bufKeyName_out, int bufSize)
630 {
631    int rval = -1;
632    KeyValuePair_s search;
633
634    if(handlerDB < MaxPersHandle)
635    {
636       if(gCursorArray[handlerDB].m_empty != 1)
637       {
638          int length = 0;
639          itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
640          length = strlen(search.m_key);
641          if(length < bufSize)
642          {
643             memcpy(bufKeyName_out, search.m_key, length);
644             rval = 0;
645          }
646          else
647          {
648             printf("persistence_db_cursor_get_key ==> buffer to small » keySize: %d | bufSize: %d \n", length, bufSize);
649          }
650       }
651       else
652       {
653          printf("persistence_db_cursor_get_key ==> invalid handle: %u \n", handlerDB);
654       }
655    }
656    else
657    {
658       printf("persistence_db_cursor_get_key ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
659    }
660    return rval;
661 }
662
663
664
665 int pers_db_cursor_get_data(unsigned int handlerDB, char * bufData_out, int bufSize)
666 {
667    int rval = -1;
668    KeyValuePair_s search;
669
670    if(handlerDB < MaxPersHandle)
671    {
672       if(gCursorArray[handlerDB].m_empty != 1)
673       {
674          int length = 0;
675          itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
676
677          length = strlen(search.m_data);
678          if(length < bufSize)
679          {
680             memcpy(bufData_out, search.m_data, length);
681             rval = 0;
682          }
683          else
684          {
685             printf("persistence_db_cursor_get_data ==> buffer to small » keySize: %d | bufSize: %d \n", length, bufSize);
686          }
687       }
688       else
689       {
690          printf("persistence_db_cursor_get_data ==> invalid handle: %u \n", handlerDB);
691       }
692    }
693    else
694    {
695       printf("persistence_db_cursor_get_data ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
696    }
697    return rval;
698 }
699
700
701
702 int pers_db_cursor_get_data_size(unsigned int handlerDB)
703 {
704    int size = -1;
705    KeyValuePair_s search;
706
707    if(handlerDB < MaxPersHandle)
708    {
709       if(gCursorArray[handlerDB].m_empty != 1)
710       {
711          itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
712          size = strlen(search.m_data);
713       }
714       else
715       {
716          printf("persistence_db_cursor_get_data ==> invalid handle: %u \n", handlerDB);
717       }
718    }
719    else
720    {
721       printf("persistence_db_cursor_get_data ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
722    }
723    return size;
724 }
725
726
727
728 int pers_db_cursor_destroy(unsigned int handlerDB)
729 {
730    int rval = -1;
731    if(handlerDB < MaxPersHandle)
732    {
733       itzam_btree_cursor_free(&gCursorArray[handlerDB].m_cursor);
734       gCursorArray[handlerDB].m_empty = 1;
735
736       itzam_state state = ITZAM_FAILED;
737       state = itzam_btree_close(&gCursorArray[handlerDB].m_btree);
738       if (state != ITZAM_OKAY)
739       {
740             fprintf(stderr, "pers_db_cursor_destroy ==> Close: Itzam problem: %s\n", STATE_MESSAGES[state]);
741       }
742
743       close_cursor_handle(handlerDB);
744
745       rval = 0;
746    }
747    return rval;
748 }
749
750
751
752
753 //-----------------------------------------------------------------------------
754 // code to print database content (for debugging)
755 //-----------------------------------------------------------------------------
756 // walk the database
757 /*
758 KeyValuePair_s  rec;
759 itzam_btree_cursor cursor;
760 state = itzam_btree_cursor_create(&cursor, &btree);
761 if(state == ITZAM_OKAY)
762 {
763   printf("==> Database content ==> db size: %d\n", (int)itzam_btree_count(&btree));
764   do
765   {
766      // get the key pointed to by the cursor
767      state = itzam_btree_cursor_read(&cursor,(void *)&rec);
768      if (state == ITZAM_OKAY)
769      {
770        printf("   Key: %s \n     ==> data: %s\n", rec.m_key, rec.m_data);
771      }
772      else
773         fprintf(stderr, "\nItzam problem: %s\n", STATE_MESSAGES[state]);
774   }
775   while (itzam_btree_cursor_next(&cursor));
776
777   state = itzam_btree_cursor_free(&cursor);
778 }
779 */
780 //-----------------------------------------------------------------------------
781
782
783
784
785