LCOV - code coverage report
Current view: top level - src/libs/notification - notification.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 69 114 60.5 %
Date: 2019-09-12 12:28:41 Functions: 7 27 25.9 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Implementation of notification functions as defined in
       5             :  * kdbnotification.h
       6             :  *
       7             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       8             :  *
       9             :  */
      10             : 
      11             : #include <kdbassert.h>
      12             : #include <kdbease.h>
      13             : #include <kdbhelper.h>
      14             : #include <kdbinvoke.h>
      15             : #include <kdbioprivate.h>
      16             : #include <kdblogger.h>
      17             : #include <kdbnotification.h>
      18             : #include <kdbnotificationinternal.h>
      19             : #include <kdbplugin.h>
      20             : #include <kdbprivate.h> // for elektraGetPluginFunction, elektraPluginFindGlobal, kdb->globalPlugins and plugin->config
      21             : 
      22             : #include <stdio.h>
      23             : 
      24           8 : static void pluginsOpenNotification (KDB * kdb, ElektraNotificationCallback callback, ElektraNotificationCallbackContext * context)
      25             : {
      26           8 :         ELEKTRA_NOT_NULL (kdb);
      27           8 :         ELEKTRA_NOT_NULL (callback);
      28             : 
      29           8 :         KeySet * parameters = ksNew (2, keyNew ("/callback", KEY_FUNC, callback, KEY_END),
      30             :                                      keyNew ("/context", KEY_BINARY, KEY_SIZE, sizeof (context), KEY_VALUE, &context, KEY_END), KS_END);
      31             : 
      32             :         // iterate over global plugins
      33         152 :         for (int positionIndex = 0; positionIndex < NR_GLOBAL_POSITIONS; positionIndex++)
      34             :         {
      35         576 :                 for (int subPositionIndex = 0; subPositionIndex < NR_GLOBAL_SUBPOSITIONS; subPositionIndex++)
      36             :                 {
      37         576 :                         Plugin * plugin = kdb->globalPlugins[positionIndex][subPositionIndex];
      38         576 :                         if (!plugin)
      39             :                         {
      40         496 :                                 continue;
      41             :                         }
      42             : 
      43             : 
      44          80 :                         elektraDeferredCall (plugin, "openNotification", parameters);
      45             :                 }
      46             :         }
      47             : 
      48           8 :         ksDel (parameters);
      49           8 : }
      50             : 
      51           8 : static void pluginsCloseNotification (KDB * kdb)
      52             : {
      53           8 :         ELEKTRA_NOT_NULL (kdb);
      54             : 
      55             :         // iterate over global plugins
      56         144 :         for (int positionIndex = 0; positionIndex < NR_GLOBAL_POSITIONS; positionIndex++)
      57             :         {
      58         576 :                 for (int subPositionIndex = 0; subPositionIndex < NR_GLOBAL_SUBPOSITIONS; subPositionIndex++)
      59             :                 {
      60         576 :                         Plugin * plugin = kdb->globalPlugins[positionIndex][subPositionIndex];
      61         576 :                         if (!plugin)
      62             :                         {
      63         496 :                                 continue;
      64             :                         }
      65             : 
      66          80 :                         elektraDeferredCall (plugin, "closeNotification", NULL);
      67             :                 }
      68             :         }
      69           8 : }
      70             : 
      71             : /**
      72             :  * @see kdbnotificationinternal.h ::ElektraNotificationKdbUpdate
      73             :  */
      74           0 : static void elektraNotificationKdbUpdate (KDB * kdb, Key * changedKey)
      75             : {
      76           0 :         KeySet * ks = ksNew (0, KS_END);
      77           0 :         kdbGet (kdb, ks, changedKey);
      78           0 :         ksDel (ks);
      79           0 : }
      80             : 
      81          10 : int elektraNotificationOpen (KDB * kdb)
      82             : {
      83             :         // Make sure kdb is not null
      84          10 :         if (!kdb)
      85             :         {
      86             :                 ELEKTRA_LOG_WARNING ("kdb was not set");
      87             :                 return 0;
      88             :         }
      89             : 
      90          10 :         Plugin * notificationPlugin = elektraPluginFindGlobal (kdb, "internalnotification");
      91             :         // Allow open only once
      92          10 :         if (notificationPlugin)
      93             :         {
      94             :                 ELEKTRA_LOG_WARNING ("elektraNotificationOpen already called for kdb");
      95             :                 return 0;
      96             :         }
      97             : 
      98             :         // Create context for notification callback
      99           8 :         ElektraNotificationCallbackContext * context = elektraMalloc (sizeof (*context));
     100           8 :         if (context == NULL)
     101             :         {
     102             :                 return 0;
     103             :         }
     104           8 :         context->kdb = kdb;
     105           8 :         context->kdbUpdate = &elektraNotificationKdbUpdate;
     106             : 
     107           8 :         Key * parent = keyNew ("", KEY_END);
     108           8 :         KeySet * contract = ksNew (2, keyNew ("system/elektra/ensure/plugins/global/internalnotification", KEY_VALUE, "mounted", KEY_END),
     109             :                                    keyNew ("system/elektra/ensure/plugins/global/internalnotification/config/context", KEY_BINARY, KEY_SIZE,
     110             :                                            sizeof (context), KEY_VALUE, &context, KEY_END),
     111             :                                    KS_END);
     112           8 :         if (kdbEnsure (kdb, contract, parent) != 0)
     113             :         {
     114           0 :                 keyDel (parent);
     115             :                 ELEKTRA_LOG_WARNING ("kdbEnsure failed");
     116           0 :                 return 0;
     117             :         }
     118             : 
     119           8 :         notificationPlugin = elektraPluginFindGlobal (kdb, "internalnotification");
     120           8 :         if (notificationPlugin == NULL)
     121             :         {
     122             :                 ELEKTRA_LOG_WARNING ("kdbEnsure failed");
     123             :                 return 0;
     124             :         }
     125             : 
     126           8 :         context->notificationPlugin = notificationPlugin;
     127             : 
     128             :         // Get notification callback from notification plugin
     129           8 :         size_t func = elektraPluginGetFunction (notificationPlugin, "notificationCallback");
     130           8 :         if (!func)
     131             :         {
     132             :                 // remove notification plugin again
     133           0 :                 contract = ksNew (1, keyNew ("system/elektra/ensure/plugins/global/internalnotification", KEY_VALUE, "unmounted", KEY_END),
     134             :                                   KS_END);
     135           0 :                 if (kdbEnsure (kdb, contract, parent) != 0)
     136             :                 {
     137             :                         ELEKTRA_LOG_WARNING ("kdbEnsure failed");
     138             :                 }
     139           0 :                 keyDel (parent);
     140           0 :                 return 0;
     141             :         }
     142           8 :         ElektraNotificationCallback notificationCallback = (ElektraNotificationCallback) func;
     143             : 
     144           8 :         keyDel (parent);
     145             : 
     146             :         // Open notification for plugins
     147           8 :         pluginsOpenNotification (kdb, notificationCallback, context);
     148             : 
     149           8 :         return 1;
     150             : }
     151             : 
     152          10 : int elektraNotificationClose (KDB * kdb)
     153             : {
     154             :         // Make sure kdb is not null
     155          10 :         if (!kdb)
     156             :         {
     157             :                 ELEKTRA_LOG_WARNING ("kdb was not set");
     158             :                 return 0;
     159             :         }
     160             : 
     161          10 :         Plugin * notificationPlugin = elektraPluginFindGlobal (kdb, "internalnotification");
     162             :         // Make sure open was called
     163          10 :         if (notificationPlugin == NULL)
     164             :         {
     165             :                 ELEKTRA_LOG_WARNING ("elektraNotificationOpen not called before elektraPluginClose");
     166             :                 return 0;
     167             :         }
     168             : 
     169           8 :         Key * contextKey = ksLookupByName (notificationPlugin->config, "user/context", 0);
     170           8 :         ElektraNotificationCallbackContext * context = *(ElektraNotificationCallbackContext **) keyValue (contextKey);
     171           8 :         elektraFree (context);
     172             : 
     173             :         // Unmount the plugin
     174           8 :         Key * parent = keyNew ("", KEY_END);
     175           8 :         KeySet * contract =
     176           8 :                 ksNew (1, keyNew ("system/elektra/ensure/plugins/global/internalnotification", KEY_VALUE, "unmounted", KEY_END), KS_END);
     177           8 :         if (kdbEnsure (kdb, contract, parent) != 0)
     178             :         {
     179             :                 ELEKTRA_LOG_WARNING ("kdbEnsure failed");
     180             :         }
     181           8 :         keyDel (parent);
     182             : 
     183             :         // Close notification for plugins
     184           8 :         pluginsCloseNotification (kdb);
     185             : 
     186           8 :         return 1;
     187             : }
     188             : 
     189             : /**
     190             :  * @internal
     191             :  * Get notification plugin from kdb.
     192             :  *
     193             :  * @param  kdb KDB handle
     194             :  * @return     Notification plugin handle or NULL if not present
     195             :  */
     196           8 : static Plugin * getNotificationPlugin (KDB * kdb)
     197             : {
     198           8 :         ELEKTRA_NOT_NULL (kdb);
     199             : 
     200           8 :         Plugin * notificationPlugin = elektraPluginFindGlobal (kdb, "internalnotification");
     201           8 :         if (notificationPlugin)
     202             :         {
     203             :                 return notificationPlugin;
     204             :         }
     205             :         else
     206             :         {
     207             :                 ELEKTRA_LOG_WARNING (
     208             :                         "notificationPlugin not set. use "
     209             :                         "elektraNotificationOpen before calling other "
     210             :                         "elektraNotification-functions");
     211           4 :                 return NULL;
     212             :         }
     213             : }
     214             : 
     215           4 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (int, Int)
     216           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (unsigned int, UnsignedInt)
     217           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (long, Long)
     218           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (unsigned long, UnsignedLong)
     219           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (float, Float)
     220           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (double, Double)
     221             : 
     222           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_boolean_t, KdbBoolean)
     223           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_char_t, KdbChar)
     224           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_octet_t, KdbOctet)
     225           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_short_t, KdbShort)
     226           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_unsigned_short_t, KdbUnsignedShort)
     227           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_long_t, KdbLong)
     228           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_unsigned_long_t, KdbUnsignedLong)
     229           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_long_long_t, KdbLongLong)
     230           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_unsigned_long_long_t, KdbUnsignedLongLong)
     231           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_float_t, KdbFloat)
     232           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_double_t, KdbDouble)
     233           0 : ELEKTRA_NOTIFICATION_TYPE_DEFINITION (kdb_long_double_t, KdbLongDouble)
     234             : 
     235           4 : int elektraNotificationRegisterCallback (KDB * kdb, Key * key, ElektraNotificationChangeCallback callback, void * context)
     236             : {
     237           4 :         if (!kdb || !key || !callback)
     238             :         {
     239             :                 ELEKTRA_LOG_WARNING ("null pointer passed");
     240             :                 return 0;
     241             :         }
     242             : 
     243             :         // Find notification plugin
     244           4 :         Plugin * notificationPlugin = getNotificationPlugin (kdb);
     245           4 :         if (!notificationPlugin)
     246             :         {
     247             :                 return 0;
     248             :         }
     249             : 
     250             :         // Get register function from plugin
     251           2 :         size_t func = elektraPluginGetFunction (notificationPlugin, "registerCallback");
     252           2 :         if (!func)
     253             :         {
     254             :                 return 0;
     255             :         }
     256             : 
     257             :         // Call register function
     258           2 :         ElektraNotificationPluginRegisterCallback registerFunc = (ElektraNotificationPluginRegisterCallback) func;
     259           2 :         return registerFunc (notificationPlugin, key, callback, context);
     260             : }
     261             : 
     262           0 : int elektraNotificationRegisterCallbackSameOrBelow (KDB * kdb, Key * key, ElektraNotificationChangeCallback callback, void * context)
     263             : {
     264           0 :         if (!kdb || !key || !callback)
     265             :         {
     266             :                 ELEKTRA_LOG_WARNING ("null pointer passed");
     267             :                 return 0;
     268             :         }
     269             : 
     270             :         // Find notification plugin
     271           0 :         Plugin * notificationPlugin = getNotificationPlugin (kdb);
     272           0 :         if (!notificationPlugin)
     273             :         {
     274             :                 return 0;
     275             :         }
     276             : 
     277             :         // Get register function from plugin
     278           0 :         size_t func = elektraPluginGetFunction (notificationPlugin, "registerCallbackSameOrBelow");
     279           0 :         if (!func)
     280             :         {
     281             :                 return 0;
     282             :         }
     283             : 
     284             :         // Call register function
     285           0 :         ElektraNotificationPluginRegisterCallbackSameOrBelow registerFunc = (ElektraNotificationPluginRegisterCallbackSameOrBelow) func;
     286           0 :         return registerFunc (notificationPlugin, key, callback, context);
     287             : }
     288             : 
     289           0 : int elektraNotificationSetConversionErrorCallback (KDB * kdb, ElektraNotificationConversionErrorCallback callback, void * context)
     290             : {
     291           0 :         if (!kdb || !callback)
     292             :         {
     293             :                 ELEKTRA_LOG_WARNING ("null pointer passed");
     294             :                 return 0;
     295             :         }
     296             : 
     297             :         // Find notification plugin
     298           0 :         Plugin * notificationPlugin = getNotificationPlugin (kdb);
     299           0 :         if (!notificationPlugin)
     300             :         {
     301             :                 return 0;
     302             :         }
     303             : 
     304             :         // Get register function from plugin
     305           0 :         size_t func = elektraPluginGetFunction (notificationPlugin, "setConversionErrorCallback");
     306           0 :         if (!func)
     307             :         {
     308             :                 return 0;
     309             :         }
     310             : 
     311             :         // Call register function
     312           0 :         ElektraNotificationSetConversionErrorCallback setCallbackFunc = (ElektraNotificationSetConversionErrorCallback) func;
     313           0 :         setCallbackFunc (notificationPlugin, callback, context);
     314           0 :         return 1;
     315             : }

Generated by: LCOV version 1.13