Removed compiler warnings
[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 #include "persistence_client_library_prct_access.h"
25
26 #include "persistence_client_library_dbus_service.h"
27
28 #include <dbus/dbus.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
33
34
35 /// definition of a key-value pair stored in the database
36 typedef struct _KeyValuePair_s
37 {
38     char m_key[DbKeySize];    /// the key
39     char m_data[DbValueSize];    /// the data
40     unsigned int m_data_size;   /// the size of the data
41 }
42 KeyValuePair_s;
43
44
45 // definition of a cursor entry
46 typedef struct _CursorEntry_s
47 {
48    itzam_btree_cursor m_cursor;
49    itzam_btree        m_btree;
50    int                m_empty;
51 }
52 CursorEntry_s;
53
54 // cursor array handle
55 CursorEntry_s gCursorArray[MaxPersHandle];
56
57 /// handle index
58 static int gHandleIdx = 1;
59
60 /// free handle array
61 int gFreeCursorHandleArray[MaxPersHandle];
62 // free head index
63 int gFreeCursorHandleIdxHead = 0;
64
65 // mutex to controll access to the cursor array
66 pthread_mutex_t gMtx = PTHREAD_MUTEX_INITIALIZER;
67
68
69 /// btree array
70 static itzam_btree gBtree[DbTableSize][PersistencePolicy_LastEntry];
71 static int gBtreeCreated[DbTableSize][PersistencePolicy_LastEntry] = { {0} };
72
73
74 // function prototype
75 int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, unsigned int reason);
76 int pers_get_default_data(char* dbPath, char* key, unsigned char* buffer, unsigned int buffer_size);
77
78
79
80
81 int pers_db_open_default(itzam_btree* btree, const char* dbPath, int configDefault)
82 {
83    itzam_state  state = ITZAM_FAILED;
84    char path[DbPathMaxLen] = {0};
85
86    if(1 == configDefault)
87    {
88       snprintf(path, DbPathMaxLen, "%s%s", dbPath, gConfigDefault);
89    }
90    else if(0 == configDefault)
91    {
92       snprintf(path, DbPathMaxLen, "%s%s", dbPath, gDefault);
93    }
94    else
95    {
96       return -1;  // invalid
97    }
98
99    state = itzam_btree_open(btree, path, itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
100    if (state != ITZAM_OKAY)
101    {
102       DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open_default ==> itzam_btree_open => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
103    }
104
105    return 1;
106 }
107
108
109 itzam_btree* pers_db_open(PersistenceInfo_s* info, const char* dbPath)
110 {
111    int arrayIdx = 0;
112    itzam_btree* btree = NULL;
113
114    // create array index: index is a combination of resource config table type and group
115    arrayIdx = info->configKey.storage + info->context.ldbid;
116
117    //if(arrayIdx <= DbTableSize)
118    if(arrayIdx < DbTableSize)
119    {
120       if(gBtreeCreated[arrayIdx][info->configKey.policy] == 0)
121       {
122          itzam_state  state = ITZAM_FAILED;
123          char path[DbPathMaxLen] = {0};
124
125          if(PersistencePolicy_wt == info->configKey.policy)
126          {
127             snprintf(path, DbPathMaxLen, "%s%s", dbPath, gWt);
128          }
129          else if(PersistencePolicy_wc == info->configKey.policy)
130          {
131             snprintf(path, DbPathMaxLen, "%s%s", dbPath, gCached);
132          }
133          else
134          {
135             return btree;
136          }
137
138          state = itzam_btree_open(&gBtree[arrayIdx][info->configKey.policy], path,
139                                   itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
140          if (state != ITZAM_OKAY)
141          {
142             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open ==> itzam_btree_open => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
143          }
144          gBtreeCreated[arrayIdx][info->configKey.policy] = 1;
145       }
146       // assign database
147       btree = &gBtree[arrayIdx][info->configKey.policy];
148    }
149    else
150    {
151       DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open ==> invalid storage type"), DLT_STRING(dbPath));
152    }
153    return btree;
154 }
155
156
157
158 void pers_db_close(PersistenceInfo_s* info)
159 {
160    int arrayIdx = info->configKey.storage + info->context.ldbid;
161
162    if(info->configKey.storage <= PersistenceStorage_shared )
163    {
164       itzam_state  state = ITZAM_FAILED;
165       state = itzam_btree_close(&gBtree[arrayIdx][info->configKey.policy]);
166       if (state != ITZAM_OKAY)
167       {
168          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close ==> itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
169       }
170       gBtreeCreated[arrayIdx][info->configKey.policy] = 0;
171    }
172    else
173    {
174       DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close ==> invalid storage type"), DLT_INT(info->context.ldbid ));
175    }
176 }
177
178
179
180 void pers_db_close_all()
181 {
182    int i = 0;
183
184    for(i=0; i<DbTableSize; i++)
185    {
186       // close write cached database
187       if(gBtreeCreated[i][PersistencePolicy_wc] == 1)
188       {
189          itzam_state  state = ITZAM_FAILED;
190          state = itzam_btree_close(&gBtree[i][PersistencePolicy_wc]);
191          if (state != ITZAM_OKAY)
192          {
193             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close_all ==> itzam_btree_close => Itzam problem:"), DLT_STRING(STATE_MESSAGES[state]) );
194          }
195          gBtreeCreated[i][PersistencePolicy_wc] = 0;
196       }
197
198       // close write through database
199       if(gBtreeCreated[i][PersistencePolicy_wt] == 1)
200       {
201          itzam_state  state = ITZAM_FAILED;
202          state = itzam_btree_close(&gBtree[i][PersistencePolicy_wt]);
203          if (state != ITZAM_OKAY)
204          {
205             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close_all ==>itzam_btree_close => Itzam problem:"), DLT_STRING(STATE_MESSAGES[state]));
206          }
207          gBtreeCreated[i][PersistencePolicy_wt] = 0;
208       }
209    }
210 }
211
212
213 void pers_rct_close_all()
214 {
215    int i = 0;
216    itzam_btree* resourceTable = NULL;
217    itzam_state  state = ITZAM_FAILED;
218
219    // close open persistence resource configuration table
220    for(i=0; i< PrctDbTableSize; i++)
221    {
222       resourceTable = (itzam_btree*)get_resource_cfg_table_by_idx(i);
223       // dereference opend database
224       if(resourceTable != NULL &&  get_resource_cfg_table_status(i) == 1)
225       {
226          state = itzam_btree_close(resourceTable);
227          invalidate_resource_cfg_table(i);
228          if (state != ITZAM_OKAY)
229          {
230             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("process_prepare_shutdown => itzam_btree_close: Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
231          }
232       }
233    }
234 }
235
236 int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
237 {
238    int read_size = -1;
239
240    if(   PersistenceStorage_shared == info->configKey.storage
241       || PersistenceStorage_local == info->configKey.storage)
242    {
243       itzam_btree* btree = NULL;
244       int keyFound = 0;
245
246       btree = pers_db_open(info, dbPath);
247       if(btree != NULL)
248       {
249          KeyValuePair_s search;
250
251          if(itzam_true == itzam_btree_find(btree, key, &search))
252          {
253             read_size = search.m_data_size;
254             if(read_size > buffer_size)
255             {
256                read_size = buffer_size;   // truncate data size to buffer size
257             }
258             memcpy(buffer, search.m_data, read_size);
259             keyFound = 1;
260          }
261       }
262       if(keyFound == 0) // check for default values.
263       {
264          read_size = pers_get_default_data(dbPath, key, buffer, buffer_size);
265       }
266    }
267    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
268    {
269       int idx =  custom_client_name_to_id(dbPath, 1);
270       char workaroundPath[128];  // workaround, because /sys/ can not be accessed on host!!!!
271       snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath  );
272
273       if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_data != NULL) )
274       {
275          char pathKeyString[128] = {0};
276          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
277          {
278             snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
279          }
280          else
281          {
282             snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
283          }
284          read_size = gPersCustomFuncs[idx].custom_plugin_get_data(pathKeyString, (char*)buffer, buffer_size);
285
286          if(read_size < 0) // check if for custom storage default values are available
287          {
288             read_size = pers_get_default_data(dbPath, key, buffer, buffer_size);
289          }
290       }
291       else
292       {
293          read_size = EPERS_NOPLUGINFUNCT;
294       }
295    }
296    return read_size;
297 }
298
299
300
301 int pers_get_default_data(char* dbPath, char* key, unsigned char* buffer, unsigned int buffer_size)
302 {
303    int keyFound = 0;
304    int read_size = 0;
305    KeyValuePair_s search;
306
307    itzam_state  state = ITZAM_FAILED;
308    itzam_btree btreeConfDefault;
309    itzam_btree btreeDefault;
310
311    // 1. check if _configurable_ default data is available
312    // --------------------------------
313    if(pers_db_open_default(&btreeConfDefault, dbPath, 1) != -1)
314    {
315       if(itzam_true == itzam_btree_find(&btreeConfDefault, key, &search)) // read db
316       {
317          read_size = search.m_data_size;
318          if(read_size > buffer_size)
319          {
320             read_size = buffer_size;   // truncate data size to buffer size
321          }
322          memcpy(buffer, search.m_data, read_size);
323
324          keyFound = 1;
325       }
326       else
327       {
328          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));
329       }
330
331       state = itzam_btree_close(&btreeConfDefault);
332       if (state != ITZAM_OKAY)
333       {
334          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> default: itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
335       }
336    }
337
338    // 2. check if default data is available
339    // --------------------------------
340    if(keyFound == 0)
341    {
342       if(pers_db_open_default(&btreeDefault, dbPath, 0) != -1)
343       {
344          if(itzam_true == itzam_btree_find(&btreeDefault, key, &search)) // read db
345          {
346             read_size = search.m_data_size;
347             if(read_size > buffer_size)
348             {
349                read_size = buffer_size;   // truncate data size to buffer size
350             }
351             memcpy(buffer, search.m_data, read_size);
352          }
353          else
354          {
355             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> 3. reasoure not found in both default db's"), DLT_STRING(key) );
356             read_size = EPERS_NOKEY;   // the key is not available neither in regular db nor in the default db's
357          }
358
359          state = itzam_btree_close(&btreeDefault);
360          if (state != ITZAM_OKAY)
361          {
362             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> default: itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
363          }
364       }
365       else
366       {
367          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==>no resource config table"), DLT_STRING(dbPath), DLT_STRING(key) );
368          read_size = EPERS_NOPRCTABLE;
369       }
370    }
371    return read_size;
372 }
373
374
375
376 int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
377 {
378    int write_size = -1;
379
380    if(   PersistenceStorage_local == info->configKey.storage
381       || PersistenceStorage_shared == info->configKey.storage )
382    {
383       write_size = buffer_size;
384       itzam_btree* btree = NULL;
385       itzam_state  state = ITZAM_FAILED;
386       KeyValuePair_s insert;
387
388       btree = pers_db_open(info, dbPath);
389       if(btree != NULL)
390       {
391          int keySize = 0;
392          keySize = (int)strlen((const char*)key);
393          if(keySize < DbKeySize)
394          {
395             int dataSize = 0;
396             dataSize = (int)strlen( (const char*)buffer);
397             if(dataSize < DbValueSize)
398             {
399                // -----------------------------------------------------------------------------
400                // transaction start
401                // itzam_btree_transaction_start(btree);
402
403                // key
404                memset(insert.m_key, 0, DbKeySize);
405                memcpy(insert.m_key, key, keySize);
406                if(itzam_true == itzam_btree_find(btree, key, &insert))
407                {
408                   // key already available, so delete "old" key
409                   state = itzam_btree_remove(btree, (const void *)&insert);
410                }
411
412                // data
413                memset(insert.m_data, 0, DbValueSize);
414                memcpy(insert.m_data, buffer, dataSize);
415
416                // data size
417                insert.m_data_size = buffer_size;
418
419                state = itzam_btree_insert(btree,(const void *)&insert);
420                if (state != ITZAM_OKAY)
421                {
422                   DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> itzam_btree_insert => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]) );
423                   write_size = EPERS_DB_ERROR_INTERNAL;
424                }
425
426                // itzam_btree_transaction_commit(btree);
427                // transaction end
428                // -----------------------------------------------------------------------------
429
430                if(PersistenceStorage_shared == info->configKey.storage)
431                {
432                   int rval = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
433                   if(rval <= 0)
434                   {
435                      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> failed to send notification signal"));
436                      write_size = rval;
437                   }
438                }
439             }
440             else
441             {
442                DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> data to long » size:"), DLT_INT(dataSize), DLT_INT(DbValueSize) );
443                write_size = EPERS_DB_VALUE_SIZE;
444             }
445          }
446          else
447          {
448             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> key to long » size"), DLT_INT(keySize), DLT_INT(DbKeySize) );
449             write_size = EPERS_DB_KEY_SIZE;
450          }
451       }
452       else
453       {
454          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
455          write_size = EPERS_NOPRCTABLE;
456       }
457    }
458    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
459    {
460       int idx = custom_client_name_to_id(dbPath, 1);
461       if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_set_data != NULL) )
462       {
463          char pathKeyString[128] = {0};
464          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
465          {
466             snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
467          }
468          else
469          {
470             snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
471          }
472          write_size = gPersCustomFuncs[idx].custom_plugin_set_data(pathKeyString, (char*)buffer, buffer_size);
473
474          if(write_size >= 0)  // success ==> send deleted notification
475          {
476             int rval = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
477             if(rval <= 0)
478             {
479                DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> failed to send notification signal"));
480                write_size = rval;
481             }
482          }
483       }
484       else
485       {
486          write_size = EPERS_NOPLUGINFUNCT;
487       }
488    }
489    return write_size;
490 }
491
492
493
494 int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
495 {
496    int read_size = -1;
497
498    if(   PersistenceStorage_shared == info->configKey.storage
499       || PersistenceStorage_local == info->configKey.storage)
500    {
501       int keySize = 0;
502       itzam_btree*  btree = NULL;
503       KeyValuePair_s search;
504
505       btree = pers_db_open(info, dbPath);
506       if(btree != NULL)
507       {
508          keySize = (int)strlen((const char*)key);
509          if(keySize < DbKeySize)
510          {
511             memset(search.m_key,0, DbKeySize);
512             memcpy(search.m_key, key, keySize);
513             if(itzam_true == itzam_btree_find(btree, key, &search))
514             {
515                read_size = search.m_data_size;
516             }
517             else
518             {
519                read_size = EPERS_NOKEY;
520             }
521          }
522          else
523          {
524             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
525             read_size = EPERS_DB_KEY_SIZE;
526          }
527       }
528       else
529       {
530          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> no config table"), DLT_STRING(dbPath), DLT_STRING(key));
531          read_size = EPERS_NOPRCTABLE;
532       }
533    }
534    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
535    {
536       int idx = custom_client_name_to_id(dbPath, 1);
537       if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_size != NULL) )
538       {
539          char pathKeyString[128] = {0};
540          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
541          {
542             snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
543          }
544          else
545          {
546             snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
547          }
548          read_size = gPersCustomFuncs[idx].custom_plugin_get_size(pathKeyString);
549       }
550       else
551       {
552          read_size = EPERS_NOPLUGINFUNCT;
553       }
554    }
555    return read_size;
556 }
557
558
559
560 int pers_db_delete_key(char* dbPath, char* key, PersistenceInfo_s* info)
561 {
562    int ret = 0;
563    if(PersistenceStorage_custom != info->configKey.storage)
564    {
565       itzam_btree*  btree = NULL;
566       KeyValuePair_s delete;
567
568       btree = pers_db_open(info, dbPath);
569       if(btree != NULL)
570       {
571          int keySize = 0;
572          keySize = (int)strlen((const char*)key);
573          if(keySize < DbKeySize)
574          {
575             // -----------------------------------------------------------------------------
576             // transaction start
577             itzam_btree_transaction_start(btree);
578
579             itzam_state  state;
580
581             memset(delete.m_key,0, DbKeySize);
582             memcpy(delete.m_key, key, keySize);
583             state = itzam_btree_remove(btree, (const void *)&delete);
584             if (state != ITZAM_OKAY)
585             {
586                DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> itzam_btree_remove => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
587                ret = EPERS_DB_ERROR_INTERNAL;
588             }
589             itzam_btree_transaction_commit(btree);
590             // transaction end
591             // -----------------------------------------------------------------------------
592
593             if(PersistenceStorage_shared == info->configKey.storage)
594             {
595                ret = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
596             }
597          }
598          else
599          {
600             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
601             ret = EPERS_DB_KEY_SIZE;
602          }
603       }
604       else
605       {
606          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
607          ret = EPERS_NOPRCTABLE;
608       }
609    }
610    else   // custom storage implementation via custom library
611    {
612       int idx = custom_client_name_to_id(dbPath, 1);
613       if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_delete_data != NULL) )
614       {
615          char pathKeyString[128] = {0};
616          if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
617          {
618             snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
619          }
620          else
621          {
622             snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
623          }
624          ret = gPersCustomFuncs[idx].custom_plugin_delete_data(pathKeyString);
625          if(ret >= 0)   // success ==> send deleted notification
626          {
627             ret = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
628          }
629       }
630       else
631       {
632          ret = EPERS_NOPLUGINFUNCT;
633       }
634    }
635    return ret;
636 }
637
638
639 int persistence_notify_on_change(char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no,
640                                  pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
641 {
642    int rval = 0;
643
644    if(regPolicy < Notify_lastEntry)
645    {
646       snprintf(gNotifykey, DbKeyMaxLen, "%s", key);
647       gNotifyLdbid  = ldbid;     // to do: pass correct ==> JUST TESTING!!!!
648       gNotifyUserNo = user_no;
649       gNotifySeatNo = seat_no;
650       gNotifyReason = regPolicy;
651
652       if(regPolicy == Notify_register)
653       {
654          // assign callback
655          gChangeNotifyCallback = callback;
656       }
657       else if(regPolicy == Notify_unregister)
658       {
659          // remove callback
660          gChangeNotifyCallback = NULL;
661       }
662
663       if(-1 == deliverToMainloop(CMD_REG_NOTIFY_SIGNAL, 0, 0))
664       {
665          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_notify_on_change => failed to write to pipe"), DLT_INT(errno));
666          rval = -1;
667       }
668    }
669    else
670    {
671       rval = -1;
672    }
673
674    return rval;
675 }
676
677
678
679
680
681
682 int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, pclNotifyStatus_e reason)
683 {
684    int rval = 1;
685    if(reason < pclNotifyStatus_lastEntry)
686    {
687       snprintf(gNotifykey,  DbKeyMaxLen,       "%s", key);
688
689       gNotifyLdbid  = context->ldbid;     // to do: pass correct ==> JUST TESTING!!!!
690       gNotifyUserNo = context->user_no;
691       gNotifySeatNo = context->seat_no;
692       gNotifyReason = reason;
693
694       if(-1 == deliverToMainloop(CMD_SEND_NOTIFY_SIGNAL, 0,0) )
695       {
696          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_send_Notification_Signal => failed to write to pipe"), DLT_INT(errno));
697          rval = EPERS_NOTIFY_SIG;
698       }
699    }
700    else
701    {
702       rval = EPERS_NOTIFY_SIG;
703    }
704
705    return rval;
706 }
707
708
709 //---------------------------------------------------------------------------------------------------------
710 // C U R S O R    F U N C T I O N S
711 //---------------------------------------------------------------------------------------------------------
712
713 int get_cursor_handle()
714 {
715    int handle = 0;
716
717    if(pthread_mutex_lock(&gMtx) == 0)
718    {
719       if(gFreeCursorHandleIdxHead > 0)   // check if we have a free spot in the array before the current max
720       {
721          handle = gFreeCursorHandleArray[--gFreeCursorHandleIdxHead];
722       }
723       else
724       {
725          if(gHandleIdx < MaxPersHandle-1)
726          {
727             handle = gHandleIdx++;  // no free spot before current max, increment handle index
728          }
729          else
730          {
731             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("get_cursor_handle ==> Reached maximum of open handles:"), DLT_INT(MaxPersHandle));
732             handle = -1;
733          }
734       }
735       pthread_mutex_unlock(&gMtx);
736    }
737    return handle;
738 }
739
740
741 void close_cursor_handle(int handlerDB)
742 {
743    if(pthread_mutex_lock(&gMtx) == 0)
744    {
745       if(gFreeCursorHandleIdxHead < MaxPersHandle)
746       {
747          gFreeCursorHandleArray[gFreeCursorHandleIdxHead++] = handlerDB;
748       }
749       pthread_mutex_unlock(&gMtx);
750    }
751 }
752
753
754
755 int pers_db_cursor_create(char* dbPath)
756 {
757    int handle = -1;
758    itzam_state  state = ITZAM_FAILED;
759
760    handle = get_cursor_handle();
761
762    if(handle < MaxPersHandle && handle >= 0)
763    {
764       // open database
765       state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 1/*recover*/, 0/*read_only*/);
766       if (state != ITZAM_OKAY)
767       {
768          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_create ==> itzam_btree_open"), DLT_STRING(STATE_MESSAGES[state]));
769       }
770       else
771       {
772          itzam_state  state;
773
774          state = itzam_btree_cursor_create(&gCursorArray[handle].m_cursor, &gCursorArray[handle].m_btree);
775          if(state == ITZAM_OKAY)
776          {
777             gCursorArray[handle].m_empty = 0;
778          }
779          else
780          {
781             gCursorArray[handle].m_empty = 1;
782          }
783       }
784    }
785    return handle;
786 }
787
788
789
790 int pers_db_cursor_next(unsigned int handlerDB)
791 {
792    int rval = -99;
793
794    //if(handlerDB < MaxPersHandle && handlerDB >= 0)
795    if(handlerDB < MaxPersHandle )
796    {
797       if(gCursorArray[handlerDB].m_empty != 1)
798       {
799          itzam_bool success;
800          success = itzam_btree_cursor_next(&gCursorArray[handlerDB].m_cursor);
801
802          if(success == itzam_true)
803          {
804             rval = 0;
805          }
806          else
807          {
808             rval = EPERS_LAST_ENTRY_IN_DB;
809          }
810       }
811       else
812       {
813          printf("Invalid handle\n");
814          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> invalid handle: "), DLT_INT(handlerDB));
815       }
816    }
817    else
818    {
819       printf("Handle bigger than max\n");
820       DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
821    }
822    return rval;
823 }
824
825
826
827 int pers_db_cursor_get_key(unsigned int handlerDB, char * bufKeyName_out, int bufSize)
828 {
829    int rval = -1;
830    KeyValuePair_s search;
831
832    if(handlerDB < MaxPersHandle)
833    {
834       if(gCursorArray[handlerDB].m_empty != 1)
835       {
836          int length = 0;
837          itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
838          length = strlen(search.m_key);
839          if(length < bufSize)
840          {
841             memcpy(bufKeyName_out, search.m_key, length);
842             rval = 0;
843          }
844          else
845          {
846             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_key  ==> buffer to small » keySize: "), DLT_INT(bufSize));
847          }
848       }
849       else
850       {
851          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key  ==>  invalid handle:"), DLT_INT(handlerDB));
852       }
853    }
854    else
855    {
856       DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
857    }
858    return rval;
859 }
860
861
862
863 int pers_db_cursor_get_data(unsigned int handlerDB, char * bufData_out, int bufSize)
864 {
865    int rval = -1;
866    KeyValuePair_s search;
867
868    if(handlerDB < MaxPersHandle)
869    {
870       if(gCursorArray[handlerDB].m_empty != 1)
871       {
872          int length = 0;
873          itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
874
875          length = strlen(search.m_data);
876          if(length < bufSize)
877          {
878             memcpy(bufData_out, search.m_data, length);
879             rval = 0;
880          }
881          else
882          {
883             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data  ==> buffer to small » keySize: "), DLT_INT(bufSize));
884          }
885       }
886       else
887       {
888          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data  ==>  invalid handle:"), DLT_INT(handlerDB));
889       }
890    }
891    else
892    {
893       DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
894    }
895    return rval;
896 }
897
898
899
900 int pers_db_cursor_get_data_size(unsigned int handlerDB)
901 {
902    int size = -1;
903    KeyValuePair_s search;
904
905    if(handlerDB < MaxPersHandle)
906    {
907       if(gCursorArray[handlerDB].m_empty != 1)
908       {
909          itzam_btree_cursor_read(&gCursorArray[handlerDB].m_cursor ,(void *)&search);
910          size = strlen(search.m_data);
911       }
912       else
913       {
914          DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data_size  ==>  invalid handle:"), DLT_INT(handlerDB));
915       }
916    }
917    else
918    {
919       DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data  ==>  handle bigger than max:"), DLT_INT(MaxPersHandle));
920    }
921    return size;
922 }
923
924
925
926 int pers_db_cursor_destroy(unsigned int handlerDB)
927 {
928    int rval = -1;
929    if(handlerDB < MaxPersHandle)
930    {
931       itzam_btree_cursor_free(&gCursorArray[handlerDB].m_cursor);
932       gCursorArray[handlerDB].m_empty = 1;
933
934       itzam_state state = ITZAM_FAILED;
935       state = itzam_btree_close(&gCursorArray[handlerDB].m_btree);
936       if (state != ITZAM_OKAY)
937       {
938             DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_destroy  ==>  itzam_btree_close: Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
939       }
940
941       close_cursor_handle(handlerDB);
942
943       rval = 0;
944    }
945    return rval;
946 }
947
948
949
950
951 //-----------------------------------------------------------------------------
952 // code to print database content (for debugging)
953 //-----------------------------------------------------------------------------
954 // walk the database
955 /*
956 KeyValuePair_s  rec;
957 itzam_btree_cursor cursor;
958 state = itzam_btree_cursor_create(&cursor, &btree);
959 if(state == ITZAM_OKAY)
960 {
961   printf("==> Database content ==> db size: %d\n", (int)itzam_btree_count(&btree));
962   do
963   {
964      // get the key pointed to by the cursor
965      state = itzam_btree_cursor_read(&cursor,(void *)&rec);
966      if (state == ITZAM_OKAY)
967      {
968        printf("   Key: %s \n     ==> data: %s\n", rec.m_key, rec.m_data);
969      }
970      else
971         fprintf(stderr, "\nItzam problem: %s\n", STATE_MESSAGES[state]);
972   }
973   while (itzam_btree_cursor_next(&cursor));
974
975   state = itzam_btree_cursor_free(&cursor);
976 }
977 */
978 //-----------------------------------------------------------------------------
979
980
981
982
983