Corrected error codes in doxygen function doc; corrected problem with return value...
[profile/ivi/persistence-client-library.git] / src / persistence_client_library_db_access.c
index 778cd03..976fbdd 100644 (file)
 #include "persistence_client_library_custom_loader.h"
 #include "persistence_client_library_itzam_errors.h"
 
+#include "persistence_client_library_dbus_service.h"
+
+#include <dbus/dbus.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <errno.h>
 
 
 /// definition of a key-value pair stored in the database
 typedef struct _KeyValuePair_s
 {
-    char m_key[DbKeySize];       /// the key
+    char m_key[DbKeySize];    /// the key
     char m_data[DbValueSize];    /// the data
     unsigned int m_data_size;   /// the size of the data
 }
@@ -66,13 +70,48 @@ static itzam_btree gBtree[DbTableSize][PersistencePolicy_LastEntry];
 static int gBtreeCreated[DbTableSize][PersistencePolicy_LastEntry] = { {0} };
 
 
+// function prototype
+int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, unsigned int reason);
+int pers_get_default_data(char* dbPath, char* key, char* buffer, unsigned int buffer_size);
+
+
+
+
+int pers_db_open_default(itzam_btree* btree, const char* dbPath, int configDefault)
+{
+   itzam_state  state = ITZAM_FAILED;
+   char path[DbPathMaxLen] = {0};
+
+   if(1 == configDefault)
+   {
+      snprintf(path, DbPathMaxLen, "%s%s", dbPath, gConfigDefault);
+   }
+   else if(0 == configDefault)
+   {
+      snprintf(path, DbPathMaxLen, "%s%s", dbPath, gDefault);
+   }
+   else
+   {
+      return -1;  // invalid
+   }
+
+   state = itzam_btree_open(btree, path, itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
+   if (state != ITZAM_OKAY)
+   {
+      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open_default ==> itzam_btree_open => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
+   }
+
+   return 1;
+}
+
+
 itzam_btree* pers_db_open(PersistenceInfo_s* info, const char* dbPath)
 {
    int arrayIdx = 0;
    itzam_btree* btree = NULL;
 
    // create array index: index is a combination of resource config table type and group
-   arrayIdx = info->configKey.storage + info->context.ldbid ;
+   arrayIdx = info->configKey.storage + info->context.ldbid;
 
    //if(arrayIdx <= DbTableSize)
    if(arrayIdx < DbTableSize)
@@ -80,11 +119,26 @@ itzam_btree* pers_db_open(PersistenceInfo_s* info, const char* dbPath)
       if(gBtreeCreated[arrayIdx][info->configKey.policy] == 0)
       {
          itzam_state  state = ITZAM_FAILED;
-         state = itzam_btree_open(&gBtree[arrayIdx][info->configKey.policy], dbPath,
+         char path[DbPathMaxLen] = {0};
+
+         if(PersistencePolicy_wt == info->configKey.policy)
+         {
+            snprintf(path, DbPathMaxLen, "%s%s", dbPath, gWt);
+         }
+         else if(PersistencePolicy_wc == info->configKey.policy)
+         {
+            snprintf(path, DbPathMaxLen, "%s%s", dbPath, gCached);
+         }
+         else
+         {
+            return btree;
+         }
+
+         state = itzam_btree_open(&gBtree[arrayIdx][info->configKey.policy], path,
                                   itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
          if (state != ITZAM_OKAY)
          {
-            fprintf(stderr, "pers_db_open ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open ==> itzam_btree_open => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
          }
          gBtreeCreated[arrayIdx][info->configKey.policy] = 1;
       }
@@ -93,7 +147,7 @@ itzam_btree* pers_db_open(PersistenceInfo_s* info, const char* dbPath)
    }
    else
    {
-      printf("btree_get ==> invalid storage type\n");
+      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_open ==> invalid storage type"), DLT_STRING(dbPath));
    }
    return btree;
 }
@@ -110,13 +164,13 @@ void pers_db_close(PersistenceInfo_s* info)
       state = itzam_btree_close(&gBtree[arrayIdx][info->configKey.policy]);
       if (state != ITZAM_OKAY)
       {
-         fprintf(stderr, "pers_db_close ==> Close Itzam problem: %s\n", STATE_MESSAGES[state]);
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close ==> itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
       }
       gBtreeCreated[arrayIdx][info->configKey.policy] = 0;
    }
    else
    {
-      printf("pers_db_close ==> invalid storage type\n");
+      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close ==> invalid storage type"), DLT_INT(info->context.ldbid ));
    }
 }
 
@@ -135,7 +189,7 @@ void pers_db_close_all()
          state = itzam_btree_close(&gBtree[i][PersistencePolicy_wc]);
          if (state != ITZAM_OKAY)
          {
-            fprintf(stderr, "pers_db_close_all ==> Close WC: Itzam problem: %s\n", STATE_MESSAGES[state]);
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close_all ==> itzam_btree_close => Itzam problem:"), DLT_STRING(STATE_MESSAGES[state]) );
          }
          gBtreeCreated[i][PersistencePolicy_wc] = 0;
       }
@@ -147,7 +201,7 @@ void pers_db_close_all()
          state = itzam_btree_close(&gBtree[i][PersistencePolicy_wt]);
          if (state != ITZAM_OKAY)
          {
-            fprintf(stderr, "pers_db_close_all ==> Close WT: Itzam problem: %s\n", STATE_MESSAGES[state]);
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_close_all ==>itzam_btree_close => Itzam problem:"), DLT_STRING(STATE_MESSAGES[state]));
          }
          gBtreeCreated[i][PersistencePolicy_wt] = 0;
       }
@@ -155,7 +209,6 @@ void pers_db_close_all()
 }
 
 
-
 int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
 {
    int read_size = -1;
@@ -164,12 +217,14 @@ int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned
       || PersistenceStorage_local == info->configKey.storage)
    {
       itzam_btree* btree = NULL;
+      int keyFound = 0;
       itzam_state  state = ITZAM_FAILED;
-      KeyValuePair_s search;
 
       btree = pers_db_open(info, dbPath);
       if(btree != NULL)
       {
+         KeyValuePair_s search;
+
          if(itzam_true == itzam_btree_find(btree, key, &search))
          {
             read_size = search.m_data_size;
@@ -178,21 +233,12 @@ int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned
                read_size = buffer_size;   // truncate data size to buffer size
             }
             memcpy(buffer, search.m_data, read_size);
+            keyFound = 1;
          }
-         else
-         {
-            read_size = EPERS_NOKEY;
-         }
-
-         //
-         // workaround till lifecycle is working correctly
-         //
-         pers_db_close(info);
       }
-      else
+      if(keyFound == 0) // check for default values.
       {
-         read_size = EPERS_NOPRCTABLE;
-         fprintf(stderr, "\npersistence_get_data ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
+         read_size = pers_get_default_data(dbPath, key, buffer, buffer_size);
       }
    }
    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
@@ -201,9 +247,23 @@ int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned
       char workaroundPath[128];  // workaround, because /sys/ can not be accessed on host!!!!
       snprintf(workaroundPath, 128, "%s%s", "/Data", dbPath  );
 
-      if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_get_data != NULL) )
+      if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_data != NULL) )
       {
-         gPersCustomFuncs[idx].custom_plugin_get_data(key, (char*)buffer, buffer_size);
+         char pathKeyString[128] = {0};
+         if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
+         {
+            snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
+         }
+         else
+         {
+            snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
+         }
+         read_size = gPersCustomFuncs[idx].custom_plugin_get_data(pathKeyString, (char*)buffer, buffer_size);
+
+         if(read_size < 0) // check if for custom storage default values are available
+         {
+            read_size = pers_get_default_data(dbPath, key, buffer, buffer_size);
+         }
       }
       else
       {
@@ -215,12 +275,87 @@ int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned
 
 
 
+int pers_get_default_data(char* dbPath, char* key, char* buffer, unsigned int buffer_size)
+{
+   int keyFound = 0;
+   int read_size = 0;
+   KeyValuePair_s search;
+
+   itzam_state  state = ITZAM_FAILED;
+   itzam_btree btreeConfDefault;
+   itzam_btree btreeDefault;
+
+   // 1. check if _configurable_ default data is available
+   // --------------------------------
+   if(pers_db_open_default(&btreeConfDefault, dbPath, 1) != -1)
+   {
+      if(itzam_true == itzam_btree_find(&btreeConfDefault, key, &search)) // read db
+      {
+         read_size = search.m_data_size;
+         if(read_size > buffer_size)
+         {
+            read_size = buffer_size;   // truncate data size to buffer size
+         }
+         memcpy(buffer, search.m_data, read_size);
+
+         keyFound = 1;
+      }
+      else
+      {
+         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));
+      }
+
+      state = itzam_btree_close(&btreeConfDefault);
+      if (state != ITZAM_OKAY)
+      {
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> default: itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
+      }
+   }
+
+   // 2. check if default data is available
+   // --------------------------------
+   if(keyFound == 0)
+   {
+      if(pers_db_open_default(&btreeDefault, dbPath, 0) != -1)
+      {
+         if(itzam_true == itzam_btree_find(&btreeDefault, key, &search)) // read db
+         {
+            read_size = search.m_data_size;
+            if(read_size > buffer_size)
+            {
+               read_size = buffer_size;   // truncate data size to buffer size
+            }
+            memcpy(buffer, search.m_data, read_size);
+         }
+         else
+         {
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> 3. reasoure not found in both default db's"), DLT_STRING(key) );
+            read_size = EPERS_NOKEY;   // the key is not available neither in regular db nor in the default db's
+         }
+
+         state = itzam_btree_close(&btreeDefault);
+         if (state != ITZAM_OKAY)
+         {
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==> default: itzam_btree_close => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
+         }
+      }
+      else
+      {
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_read_key ==>no resource config table"), DLT_STRING(dbPath), DLT_STRING(key) );
+         read_size = EPERS_NOPRCTABLE;
+      }
+   }
+   return read_size;
+}
+
+
+
 int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned char* buffer, unsigned int buffer_size)
 {
    int write_size = -1;
 
-   if(   PersistenceStorage_shared == info->configKey.storage
-      || PersistenceStorage_local == info->configKey.storage)
+   if(   PersistenceStorage_local == info->configKey.storage
+      || PersistenceStorage_shared == info->configKey.storage )
    {
       write_size = buffer_size;
       itzam_btree* btree = NULL;
@@ -238,6 +373,10 @@ int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned
             dataSize = (int)strlen( (const char*)buffer);
             if(dataSize < DbValueSize)
             {
+               // -----------------------------------------------------------------------------
+               // transaction start
+               itzam_btree_transaction_start(btree);
+
                // key
                memset(insert.m_key, 0, DbKeySize);
                memcpy(insert.m_key, key, keySize);
@@ -257,39 +396,67 @@ int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned
                state = itzam_btree_insert(btree,(const void *)&insert);
                if (state != ITZAM_OKAY)
                {
-                  fprintf(stderr, "\npersistence_set_data ==> Insert Itzam problem: %s\n", STATE_MESSAGES[state]);
+                  DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> itzam_btree_insert => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]) );
                   write_size = EPERS_DB_ERROR_INTERNAL;
                }
+
+               itzam_btree_transaction_commit(btree);
+               // transaction end
+               // -----------------------------------------------------------------------------
+
+               if(PersistenceStorage_shared == info->configKey.storage)
+               {
+                  int rval = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
+                  if(rval <= 0)
+                  {
+                     DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> failed to send notification signal"));
+                     write_size = rval;
+                  }
+               }
             }
             else
             {
-               fprintf(stderr, "\npersistence_set_data ==> set_value_to_table_itzam => data to long » size %d | maxSize: %d\n", dataSize, DbKeySize);
+               DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> data to long » size:"), DLT_INT(dataSize), DLT_INT(DbValueSize) );
                write_size = EPERS_DB_VALUE_SIZE;
             }
-
-            //
-            // workaround till lifecycle is working correctly
-            //
-            pers_db_close(info);
          }
          else
          {
-            fprintf(stderr, "\nset_value_to_table_itzam => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize);
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> key to long » size"), DLT_INT(keySize), DLT_INT(DbKeySize) );
             write_size = EPERS_DB_KEY_SIZE;
          }
       }
       else
       {
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
          write_size = EPERS_NOPRCTABLE;
-         fprintf(stderr, "\npersistence_set_data ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
       }
    }
    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
    {
       int idx = custom_client_name_to_id(dbPath, 1);
-      if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data) )
+      if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_set_data != NULL) )
       {
-         gPersCustomFuncs[idx].custom_plugin_set_data(key, (char*)buffer, buffer_size);
+         char pathKeyString[128] = {0};
+         if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
+         {
+            snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
+         }
+         else
+         {
+            snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
+         }
+         write_size = gPersCustomFuncs[idx].custom_plugin_set_data(pathKeyString, (char*)buffer, buffer_size);
+
+         if(write_size >= 0)  // success ==> send deleted notification
+         {
+            int rval = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_changed);
+            if(rval <= 0)
+            {
+               DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_write_key ==> failed to send notification signal"));
+               write_size = rval;
+            }
+         }
       }
       else
       {
@@ -310,7 +477,6 @@ int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
    {
       int keySize = 0;
       itzam_btree*  btree = NULL;
-      itzam_state  state = ITZAM_FAILED;
       KeyValuePair_s search;
 
       btree = pers_db_open(info, dbPath);
@@ -323,7 +489,7 @@ int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
             memcpy(search.m_key, key, keySize);
             if(itzam_true == itzam_btree_find(btree, key, &search))
             {
-               read_size = strlen(search.m_data);
+               read_size = search.m_data_size;
             }
             else
             {
@@ -332,26 +498,31 @@ int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
          }
          else
          {
-            fprintf(stderr, "persistence_get_data_size => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize);
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
             read_size = EPERS_DB_KEY_SIZE;
          }
-         //
-         // workaround till lifecycle is working correctly
-         //
-         pers_db_close(info);
       }
       else
       {
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_get_key_size ==> no config table"), DLT_STRING(dbPath), DLT_STRING(key));
          read_size = EPERS_NOPRCTABLE;
-         fprintf(stderr, "\npersistence_get_data_size ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
       }
    }
    else if(PersistenceStorage_custom == info->configKey.storage)   // custom storage implementation via custom library
    {
       int idx = custom_client_name_to_id(dbPath, 1);
-      if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data) )
+      if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_get_size != NULL) )
       {
-         gPersCustomFuncs[idx].custom_plugin_get_size(key);
+         char pathKeyString[128] = {0};
+         if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
+         {
+            snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
+         }
+         else
+         {
+            snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
+         }
+         read_size = gPersCustomFuncs[idx].custom_plugin_get_size(pathKeyString);
       }
       else
       {
@@ -363,7 +534,7 @@ int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info)
 
 
 
-int pers_db_delete_key(char* dbPath, char* dbKey, PersistenceInfo_s* info)
+int pers_db_delete_key(char* dbPath, char* key, PersistenceInfo_s* info)
 {
    int ret = 0;
    if(PersistenceStorage_custom != info->configKey.storage)
@@ -371,47 +542,67 @@ int pers_db_delete_key(char* dbPath, char* dbKey, PersistenceInfo_s* info)
       itzam_btree*  btree = NULL;
       KeyValuePair_s delete;
 
-      //printf("delete_key_from_table_itzam => Path: \"%s\" | key: \"%s\" \n", dbPath, key);
       btree = pers_db_open(info, dbPath);
       if(btree != NULL)
       {
          int keySize = 0;
-         keySize = (int)strlen((const char*)dbKey);
+         keySize = (int)strlen((const char*)key);
          if(keySize < DbKeySize)
          {
+            // -----------------------------------------------------------------------------
+            // transaction start
+            itzam_btree_transaction_start(btree);
+
             itzam_state  state;
 
             memset(delete.m_key,0, DbKeySize);
-            memcpy(delete.m_key, dbKey, keySize);
+            memcpy(delete.m_key, key, keySize);
             state = itzam_btree_remove(btree, (const void *)&delete);
             if (state != ITZAM_OKAY)
             {
-               fprintf(stderr, "persistence_delete_data ==> Remove Itzam problem: %s\n", STATE_MESSAGES[state]);
+               DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> itzam_btree_remove => Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
                ret = EPERS_DB_ERROR_INTERNAL;
             }
+            itzam_btree_transaction_commit(btree);
+            // transaction end
+            // -----------------------------------------------------------------------------
+
+            if(PersistenceStorage_shared == info->configKey.storage)
+            {
+               ret = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
+            }
          }
          else
          {
-            fprintf(stderr, "persistence_delete_data => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize);
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> key to long"), DLT_INT(keySize), DLT_INT(DbKeySize));
             ret = EPERS_DB_KEY_SIZE;
          }
-         //
-         // workaround till lifecycle is working correctly
-         //
-         pers_db_close(info);
       }
       else
       {
-         fprintf(stderr, "persistence_delete_data => no prct table\n");
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_delete_key ==> no resource config table"), DLT_STRING(dbPath), DLT_STRING(key));
          ret = EPERS_NOPRCTABLE;
       }
    }
    else   // custom storage implementation via custom library
    {
       int idx = custom_client_name_to_id(dbPath, 1);
-      if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_set_data) )
+      if((idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_delete_data != NULL) )
       {
-         gPersCustomFuncs[idx].custom_plugin_delete_data(dbKey);
+         char pathKeyString[128] = {0};
+         if(info->configKey.customID[0] == '\0')   // if we have not a customID we use the key
+         {
+            snprintf(pathKeyString, 128, "0x%08X/%s/%s", info->context.ldbid, info->configKey.custom_name, key);
+         }
+         else
+         {
+            snprintf(pathKeyString, 128, "0x%08X/%s", info->context.ldbid, info->configKey.customID);
+         }
+         ret = gPersCustomFuncs[idx].custom_plugin_delete_data(pathKeyString);
+         if(ret >= 0)   // success ==> send deleted notification
+         {
+            ret = pers_send_Notification_Signal(key, &info->context, pclNotifyStatus_deleted);
+         }
       }
       else
       {
@@ -422,15 +613,76 @@ int pers_db_delete_key(char* dbPath, char* dbKey, PersistenceInfo_s* info)
 }
 
 
-int persistence_reg_notify_on_change(char* dbPath, char* key)
+int persistence_notify_on_change(char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no,
+                                 pclChangeNotifyCallback_t callback, PersNotifyRegPolicy_e regPolicy)
 {
-   int rval = -1;
+   int rval = 0;
+
+   if(regPolicy < Notify_lastEntry)
+   {
+      snprintf(gNotifykey, DbKeyMaxLen, "%s", key);
+      gNotifyLdbid  = ldbid;     // to do: pass correct ==> JUST TESTING!!!!
+      gNotifyUserNo = user_no;
+      gNotifySeatNo = seat_no;
+      gNotifyReason = regPolicy;
+
+      if(regPolicy == Notify_register)
+      {
+         // assign callback
+         gChangeNotifyCallback = callback;
+      }
+      else if(regPolicy == Notify_unregister)
+      {
+         // remove callback
+         gChangeNotifyCallback = NULL;
+      }
+
+      if(-1 == deliverToMainloop(CMD_REG_NOTIFY_SIGNAL, 0, 0))
+      {
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_notify_on_change => failed to write to pipe"), DLT_INT(errno));
+         rval = -1;
+      }
+   }
+   else
+   {
+      rval = -1;
+   }
 
    return rval;
 }
 
 
 
+
+
+
+int pers_send_Notification_Signal(const char* key, PersistenceDbContext_s* context, pclNotifyStatus_e reason)
+{
+   int rval = 1;
+   if(reason < pclNotifyStatus_lastEntry)
+   {
+      snprintf(gNotifykey,  DbKeyMaxLen,       "%s", key);
+
+      gNotifyLdbid  = context->ldbid;     // to do: pass correct ==> JUST TESTING!!!!
+      gNotifyUserNo = context->user_no;
+      gNotifySeatNo = context->seat_no;
+      gNotifyReason = reason;
+
+      if(-1 == deliverToMainloop(CMD_SEND_NOTIFY_SIGNAL, 0,0) )
+      {
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_send_Notification_Signal => failed to write to pipe"), DLT_INT(errno));
+         rval = EPERS_NOTIFY_SIG;
+      }
+   }
+   else
+   {
+      rval = EPERS_NOTIFY_SIG;
+   }
+
+   return rval;
+}
+
+
 //---------------------------------------------------------------------------------------------------------
 // C U R S O R    F U N C T I O N S
 //---------------------------------------------------------------------------------------------------------
@@ -453,8 +705,8 @@ int get_cursor_handle()
          }
          else
          {
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("get_cursor_handle ==> Reached maximum of open handles:"), DLT_INT(MaxPersHandle));
             handle = -1;
-            printf("get_persistence_handle_idx => Reached maximum of open handles: %d \n", MaxPersHandle);
          }
       }
       pthread_mutex_unlock(&gMtx);
@@ -487,10 +739,10 @@ int pers_db_cursor_create(char* dbPath)
    if(handle < MaxPersHandle && handle >= 0)
    {
       // open database
-      state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/);
+      state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 1/*recover*/, 0/*read_only*/);
       if (state != ITZAM_OKAY)
       {
-         fprintf(stderr, "pers_db_open ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]);
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_create ==> itzam_btree_open"), DLT_STRING(STATE_MESSAGES[state]));
       }
       else
       {
@@ -534,12 +786,12 @@ int pers_db_cursor_next(unsigned int handlerDB)
       }
       else
       {
-         printf("persistence_db_cursor_get_key ==> invalid handle: %u \n", handlerDB);
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> invalid handle: "), DLT_INT(handlerDB));
       }
    }
    else
    {
-      printf("persistence_db_cursor_get_key ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
+      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_next ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
    }
    return rval;
 }
@@ -565,17 +817,17 @@ int pers_db_cursor_get_key(unsigned int handlerDB, char * bufKeyName_out, int bu
          }
          else
          {
-            printf("persistence_db_cursor_get_key ==> buffer to small » keySize: %d | bufSize: %d \n", length, bufSize);
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_key  ==> buffer to small » keySize: "), DLT_INT(bufSize));
          }
       }
       else
       {
-         printf("persistence_db_cursor_get_key ==> invalid handle: %u \n", handlerDB);
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key  ==>  invalid handle:"), DLT_INT(handlerDB));
       }
    }
    else
    {
-      printf("persistence_db_cursor_get_key ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
+      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_key ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
    }
    return rval;
 }
@@ -602,17 +854,17 @@ int pers_db_cursor_get_data(unsigned int handlerDB, char * bufData_out, int bufS
          }
          else
          {
-            printf("persistence_db_cursor_get_data ==> buffer to small » keySize: %d | bufSize: %d \n", length, bufSize);
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data  ==> buffer to small » keySize: "), DLT_INT(bufSize));
          }
       }
       else
       {
-         printf("persistence_db_cursor_get_data ==> invalid handle: %u \n", handlerDB);
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data  ==>  invalid handle:"), DLT_INT(handlerDB));
       }
    }
    else
    {
-      printf("persistence_db_cursor_get_data ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
+      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data ==> handle bigger than max:"), DLT_INT(MaxPersHandle));
    }
    return rval;
 }
@@ -633,12 +885,12 @@ int pers_db_cursor_get_data_size(unsigned int handlerDB)
       }
       else
       {
-         printf("persistence_db_cursor_get_data ==> invalid handle: %u \n", handlerDB);
+         DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_get_data_size  ==>  invalid handle:"), DLT_INT(handlerDB));
       }
    }
    else
    {
-      printf("persistence_db_cursor_get_data ==> handle bigger than max » handleDB: %u | max: : %d \n", handlerDB, MaxPersHandle);
+      DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("persistence_db_cursor_get_data  ==>  handle bigger than max:"), DLT_INT(MaxPersHandle));
    }
    return size;
 }
@@ -657,7 +909,7 @@ int pers_db_cursor_destroy(unsigned int handlerDB)
       state = itzam_btree_close(&gCursorArray[handlerDB].m_btree);
       if (state != ITZAM_OKAY)
       {
-            fprintf(stderr, "pers_db_cursor_destroy ==> Close: Itzam problem: %s\n", STATE_MESSAGES[state]);
+            DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pers_db_cursor_destroy  ==>  itzam_btree_close: Itzam problem"), DLT_STRING(STATE_MESSAGES[state]));
       }
 
       close_cursor_handle(handlerDB);