root/daemons/based/based_notify.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cib_notify_send_one
  2. cib_notify_send
  3. cib_diff_notify

   1 /*
   2  * Copyright 2004-2025 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <sys/param.h>
  13 #include <stdio.h>
  14 #include <sys/types.h>
  15 #include <unistd.h>
  16 #include <inttypes.h>           // PRIx64
  17 
  18 #include <stdlib.h>
  19 #include <errno.h>
  20 #include <fcntl.h>
  21 
  22 #include <time.h>
  23 
  24 #include <glib.h>
  25 #include <libxml/tree.h>
  26 
  27 #include <crm/crm.h>
  28 #include <crm/cib/internal.h>
  29 
  30 #include <crm/common/xml.h>
  31 #include <crm/common/remote_internal.h>
  32 #include <pacemaker-based.h>
  33 
  34 struct cib_notification_s {
  35     const xmlNode *msg;
  36     struct iovec *iov;
  37     int32_t iov_size;
  38 };
  39 
  40 static void
  41 cib_notify_send_one(gpointer key, gpointer value, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  42 {
  43     const char *type = NULL;
  44     gboolean do_send = FALSE;
  45     int rc = pcmk_rc_ok;
  46 
  47     pcmk__client_t *client = value;
  48     struct cib_notification_s *update = user_data;
  49 
  50     if (client->ipcs == NULL && client->remote == NULL) {
  51         crm_warn("Skipping client with NULL channel");
  52         return;
  53     }
  54 
  55     type = crm_element_value(update->msg, PCMK__XA_SUBT);
  56     CRM_LOG_ASSERT(type != NULL);
  57 
  58     if (pcmk_is_set(client->flags, cib_notify_diff)
  59         && pcmk__str_eq(type, PCMK__VALUE_CIB_DIFF_NOTIFY, pcmk__str_none)) {
  60 
  61         do_send = TRUE;
  62 
  63     } else if (pcmk_is_set(client->flags, cib_notify_confirm)
  64                && pcmk__str_eq(type, PCMK__VALUE_CIB_UPDATE_CONFIRMATION,
  65                                pcmk__str_none)) {
  66         do_send = TRUE;
  67 
  68     } else if (pcmk_is_set(client->flags, cib_notify_pre)
  69                && pcmk__str_eq(type, PCMK__VALUE_CIB_PRE_NOTIFY,
  70                                pcmk__str_none)) {
  71         do_send = TRUE;
  72 
  73     } else if (pcmk_is_set(client->flags, cib_notify_post)
  74                && pcmk__str_eq(type, PCMK__VALUE_CIB_POST_NOTIFY,
  75                                pcmk__str_none)) {
  76         do_send = TRUE;
  77     }
  78 
  79     if (do_send) {
  80         switch (PCMK__CLIENT_TYPE(client)) {
  81             case pcmk__client_ipc:
  82                 rc = pcmk__ipc_send_iov(client, update->iov,
  83                                         crm_ipc_server_event);
  84 
  85                 /* EAGAIN isn't an error for server events.  Sending did fail
  86                  * with EAGAIN, but the iov was added to the send queue and we
  87                  * will attempt to send it again the next time pcmk__ipc_send_iov
  88                  * is called, or when crm_ipcs_flush_events_cb happens.
  89                  */
  90                 if ((rc != EAGAIN) && (rc != pcmk_rc_ok)) {
  91                     crm_warn("Could not notify client %s: %s " QB_XS " id=%s",
  92                              pcmk__client_name(client), pcmk_rc_str(rc),
  93                              client->id);
  94                 }
  95                 break;
  96             case pcmk__client_tls:
  97             case pcmk__client_tcp:
  98                 crm_debug("Sent %s notification to client %s (id %s)",
  99                           type, pcmk__client_name(client), client->id);
 100                 pcmk__remote_send_xml(client->remote, update->msg);
 101                 break;
 102             default:
 103                 crm_err("Unknown transport for client %s "
 104                         QB_XS " flags=%#016" PRIx64,
 105                         pcmk__client_name(client), client->flags);
 106         }
 107     }
 108 }
 109 
 110 static void
 111 cib_notify_send(const xmlNode *xml)
     /* [previous][next][first][last][top][bottom][index][help] */
 112 {
 113     struct iovec *iov;
 114     struct cib_notification_s update;
 115     GString *iov_buffer = NULL;
 116     ssize_t bytes = 0;
 117     int rc = pcmk_rc_ok;
 118     uint16_t index = 0;
 119 
 120     iov_buffer = g_string_sized_new(1024);
 121     pcmk__xml_string(xml, 0, iov_buffer, 0);
 122 
 123     do {
 124         rc = pcmk__ipc_prepare_iov(0, iov_buffer, index, &iov, &bytes);
 125 
 126         if ((rc != pcmk_rc_ok) && (rc != pcmk_rc_ipc_more)) {
 127             crm_notice("Could not notify clients: %s " QB_XS " rc=%d",
 128                        pcmk_rc_str(rc), rc);
 129             break;
 130         }
 131 
 132         update.msg = xml;
 133         update.iov = iov;
 134         update.iov_size = bytes;
 135         pcmk__foreach_ipc_client(cib_notify_send_one, &update);
 136         pcmk_free_ipc_event(iov);
 137 
 138         if (rc == pcmk_rc_ok) {
 139             break;
 140         }
 141 
 142         index++;
 143     } while (true);
 144 
 145     g_string_free(iov_buffer, TRUE);
 146 }
 147 
 148 void
 149 cib_diff_notify(const char *op, int result, const char *call_id,
     /* [previous][next][first][last][top][bottom][index][help] */
 150                 const char *client_id, const char *client_name,
 151                 const char *origin, xmlNode *update, xmlNode *diff)
 152 {
 153     int add_updates = 0;
 154     int add_epoch = 0;
 155     int add_admin_epoch = 0;
 156 
 157     int del_updates = 0;
 158     int del_epoch = 0;
 159     int del_admin_epoch = 0;
 160 
 161     uint8_t log_level = LOG_TRACE;
 162 
 163     xmlNode *update_msg = NULL;
 164     xmlNode *wrapper = NULL;
 165 
 166     if (diff == NULL) {
 167         return;
 168     }
 169 
 170     if (result != pcmk_ok) {
 171         log_level = LOG_WARNING;
 172     }
 173 
 174     cib_diff_version_details(diff, &add_admin_epoch, &add_epoch, &add_updates,
 175                              &del_admin_epoch, &del_epoch, &del_updates);
 176 
 177     if ((add_admin_epoch != del_admin_epoch)
 178         || (add_epoch != del_epoch)
 179         || (add_updates != del_updates)) {
 180 
 181         do_crm_log(log_level,
 182                    "Updated CIB generation %d.%d.%d to %d.%d.%d from client "
 183                    "%s%s%s (%s) (%s)",
 184                    del_admin_epoch, del_epoch, del_updates,
 185                    add_admin_epoch, add_epoch, add_updates,
 186                    client_name,
 187                    ((call_id != NULL)? " call " : ""), pcmk__s(call_id, ""),
 188                    pcmk__s(origin, "unspecified peer"), pcmk_strerror(result));
 189 
 190     } else if ((add_admin_epoch != 0)
 191                || (add_epoch != 0)
 192                || (add_updates != 0)) {
 193 
 194         do_crm_log(log_level,
 195                    "Local-only change to CIB generation %d.%d.%d from client "
 196                    "%s%s%s (%s) (%s)",
 197                    add_admin_epoch, add_epoch, add_updates,
 198                    client_name,
 199                    ((call_id != NULL)? " call " : ""), pcmk__s(call_id, ""),
 200                    pcmk__s(origin, "unspecified peer"), pcmk_strerror(result));
 201     }
 202 
 203     update_msg = pcmk__xe_create(NULL, PCMK__XE_NOTIFY);
 204 
 205     crm_xml_add(update_msg, PCMK__XA_T, PCMK__VALUE_CIB_NOTIFY);
 206     crm_xml_add(update_msg, PCMK__XA_SUBT, PCMK__VALUE_CIB_DIFF_NOTIFY);
 207     crm_xml_add(update_msg, PCMK__XA_CIB_OP, op);
 208     crm_xml_add(update_msg, PCMK__XA_CIB_CLIENTID, client_id);
 209     crm_xml_add(update_msg, PCMK__XA_CIB_CLIENTNAME, client_name);
 210     crm_xml_add(update_msg, PCMK__XA_CIB_CALLID, call_id);
 211     crm_xml_add(update_msg, PCMK__XA_SRC, origin);
 212     crm_xml_add_int(update_msg, PCMK__XA_CIB_RC, result);
 213 
 214     wrapper = pcmk__xe_create(update_msg, PCMK__XE_CIB_UPDATE_RESULT);
 215     pcmk__xml_copy(wrapper, diff);
 216 
 217     crm_log_xml_trace(update_msg, "diff-notify");
 218     cib_notify_send(update_msg);
 219     pcmk__xml_free(update_msg);
 220 }

/* [previous][next][first][last][top][bottom][index][help] */