LCOV - code coverage report
Current view: top level - src/plugins/zeromqrecv - subscribe.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 44 59 74.6 %
Date: 2019-09-12 12:28:41 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include "zeromqrecv.h"
      10             : 
      11             : #include <kdbhelper.h>
      12             : #include <kdblogger.h>
      13             : 
      14             : /**
      15             :  * @internal
      16             :  * Called whenever the socket becomes readable.
      17             :  * ZeroMq since sends multipart messages atomically (all or nothing)
      18             :  * both message parts are instantly available.
      19             :  *
      20             :  * @param socket  ZeroMq socket
      21             :  * @param context context passed to elektraIoAdapterZeroMqAttach()
      22             :  */
      23           2 : static void zeroMqRecvSocketReadable (void * socket, void * context)
      24             : {
      25           2 :         ElektraZeroMqRecvPluginData * data = context;
      26             : 
      27             :         char * changeType;
      28             :         char * changedKeyName;
      29             : 
      30             :         zmq_msg_t message;
      31           2 :         zmq_msg_init (&message);
      32             : 
      33           2 :         int result = zmq_msg_recv (&message, socket, ZMQ_DONTWAIT);
      34           2 :         if (result == -1)
      35             :         {
      36             :                 ELEKTRA_LOG_WARNING ("receiving change type failed: %s; aborting", zmq_strerror (zmq_errno ()));
      37           0 :                 zmq_msg_close (&message);
      38           0 :                 return;
      39             :         }
      40           2 :         if (!zmq_msg_more (&message))
      41             :         {
      42             :                 ELEKTRA_LOG_WARNING ("message has only one part; aborting");
      43           0 :                 zmq_msg_close (&message);
      44           0 :                 return;
      45             :         }
      46           2 :         int length = zmq_msg_size (&message);
      47           2 :         changeType = elektraStrNDup (zmq_msg_data (&message), length + 1);
      48           2 :         changeType[length] = '\0';
      49             :         ELEKTRA_LOG_DEBUG ("received change type %s", changeType);
      50             : 
      51           2 :         result = zmq_msg_recv (&message, socket, ZMQ_DONTWAIT);
      52           2 :         if (result == -1)
      53             :         {
      54             :                 ELEKTRA_LOG_WARNING ("receiving key name failed: %s; aborting", zmq_strerror (zmq_errno ()));
      55           0 :                 elektraFree (changeType);
      56           0 :                 zmq_msg_close (&message);
      57           0 :                 return;
      58             :         }
      59           2 :         length = zmq_msg_size (&message);
      60           2 :         changedKeyName = elektraStrNDup (zmq_msg_data (&message), length + 1);
      61           2 :         changedKeyName[length] = '\0';
      62             :         ELEKTRA_LOG_DEBUG ("received key name %s", changedKeyName);
      63             : 
      64             :         // notify about changes
      65           2 :         Key * changedKey = keyNew (changedKeyName, KEY_END);
      66           2 :         data->notificationCallback (changedKey, data->notificationContext);
      67             : 
      68           2 :         zmq_msg_close (&message);
      69           2 :         elektraFree (changeType);
      70           2 :         elektraFree (changedKeyName);
      71             : }
      72             : 
      73             : /**
      74             :  * @internal
      75             :  * Setup ZeroMq for receiving notifications.
      76             :  *
      77             :  * @param data plugin data containing context, socket, etc.
      78             :  */
      79           4 : void elektraZeroMqRecvSetup (ElektraZeroMqRecvPluginData * data)
      80             : {
      81             :         // create zmq context
      82           4 :         if (!data->zmqContext)
      83             :         {
      84           4 :                 data->zmqContext = zmq_ctx_new ();
      85           4 :                 if (data->zmqContext == NULL)
      86             :                 {
      87             :                         ELEKTRA_LOG_WARNING ("zmq_ctx_new failed %s", zmq_strerror (zmq_errno ()));
      88             :                         return;
      89             :                 }
      90             :         }
      91             : 
      92             :         // create publish socket
      93           4 :         if (!data->zmqSubscriber)
      94             :         {
      95           4 :                 data->zmqSubscriber = zmq_socket (data->zmqContext, ZMQ_SUB);
      96           4 :                 if (data->zmqSubscriber == NULL)
      97             :                 {
      98             :                         ELEKTRA_LOG_WARNING ("zmq_socket failed %s", zmq_strerror (zmq_errno ()));
      99           0 :                         zmq_close (data->zmqSubscriber);
     100           0 :                         return;
     101             :                 }
     102             : 
     103             :                 // subscribe to notifications
     104           4 :                 char * keyCommitType = "Commit";
     105           4 :                 if (zmq_setsockopt (data->zmqSubscriber, ZMQ_SUBSCRIBE, keyCommitType, elektraStrLen (keyCommitType)) != 0)
     106             :                 {
     107             :                         ELEKTRA_LOG_WARNING ("failed to subscribe to %s messages", keyCommitType);
     108             :                 }
     109             : 
     110             :                 // connect to endpoint
     111           4 :                 int result = zmq_connect (data->zmqSubscriber, data->endpoint);
     112           4 :                 if (result != 0)
     113             :                 {
     114             :                         ELEKTRA_LOG_WARNING ("zmq_connect error: %s\n", zmq_strerror (zmq_errno ()));
     115           0 :                         zmq_close (data->zmqSubscriber);
     116           0 :                         data->zmqSubscriber = NULL;
     117           0 :                         return;
     118             :                 }
     119             :         }
     120             : 
     121           4 :         if (!data->zmqAdapter)
     122             :         {
     123             :                 // attach ZeroMq adater and wait for socket to be writable
     124           4 :                 data->zmqAdapter = elektraIoAdapterZeroMqAttach (data->zmqSubscriber, data->ioBinding, ELEKTRA_IO_ADAPTER_ZEROMQCB_READ,
     125             :                                                                  zeroMqRecvSocketReadable, data);
     126           4 :                 if (!data->zmqAdapter)
     127             :                 {
     128             :                         ELEKTRA_LOG_WARNING ("could not attach zmq adapter");
     129           0 :                         zmq_close (data->zmqSubscriber);
     130           0 :                         data->zmqSubscriber = NULL;
     131           0 :                         return;
     132             :                 }
     133             :         }
     134             : }
     135             : 
     136             : /**
     137             :  * @internal
     138             :  * Cleanup ZeroMq.
     139             :  *
     140             :  * @param data plugin data
     141             :  */
     142           4 : void elektraZeroMqRecvTeardown (ElektraZeroMqRecvPluginData * data)
     143             : {
     144           4 :         if (data->zmqAdapter)
     145             :         {
     146           4 :                 elektraIoAdapterZeroMqDetach (data->zmqAdapter);
     147           4 :                 data->zmqAdapter = NULL;
     148             :         }
     149             : 
     150           4 :         if (data->zmqSubscriber)
     151             :         {
     152           4 :                 zmq_close (data->zmqSubscriber);
     153           4 :                 data->zmqSubscriber = NULL;
     154             :         }
     155             : 
     156           4 :         if (data->zmqContext)
     157             :         {
     158           4 :                 zmq_ctx_destroy (data->zmqContext);
     159           4 :                 data->zmqContext = NULL;
     160             :         }
     161           4 : }

Generated by: LCOV version 1.13