This source file includes following definitions.
- cib_notify_send_one
- cib_notify_send
- cib_diff_notify
1
2
3
4
5
6
7
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>
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)
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
86
87
88
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)
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,
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 }