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