This source file includes following definitions.
- attrd_set_requesting_shutdown
- attrd_clear_requesting_shutdown
- attrd_requesting_shutdown
- attrd_shutting_down
- attrd_shutdown
- attrd_init_mainloop
- attrd_run_mainloop
- attrd_ipc_accept
- attrd_ipc_closed
- attrd_ipc_destroy
- attrd_init_ipc
- attrd_cib_disconnect
- attrd_cib_replaced_cb
- attrd_value_needs_expansion
- attrd_expand_value
- attrd_failure_regex
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdio.h>
13 #include <stdbool.h>
14 #include <errno.h>
15 #include <glib.h>
16 #include <regex.h>
17 #include <sys/types.h>
18
19 #include <crm/crm.h>
20 #include <crm/common/ipc_internal.h>
21 #include <crm/common/mainloop.h>
22
23 #include "pacemaker-attrd.h"
24
25 cib_t *the_cib = NULL;
26
27 static bool requesting_shutdown = FALSE;
28 static bool shutting_down = FALSE;
29 static GMainLoop *mloop = NULL;
30
31
32
33
34
35 void
36 attrd_set_requesting_shutdown()
37 {
38 requesting_shutdown = TRUE;
39 }
40
41
42
43
44
45 void
46 attrd_clear_requesting_shutdown()
47 {
48 requesting_shutdown = FALSE;
49 }
50
51
52
53
54
55
56
57 gboolean
58 attrd_requesting_shutdown()
59 {
60 return requesting_shutdown;
61 }
62
63
64
65
66
67
68
69 gboolean
70 attrd_shutting_down()
71 {
72 return shutting_down;
73 }
74
75
76
77
78
79
80
81 void
82 attrd_shutdown(int nsig)
83 {
84
85 shutting_down = TRUE;
86
87
88 mainloop_destroy_signal(SIGTERM);
89 mainloop_destroy_signal(SIGCHLD);
90 mainloop_destroy_signal(SIGPIPE);
91 mainloop_destroy_signal(SIGUSR1);
92 mainloop_destroy_signal(SIGUSR2);
93 mainloop_destroy_signal(SIGTRAP);
94
95 if ((mloop == NULL) || !g_main_loop_is_running(mloop)) {
96
97
98
99 crm_exit(CRM_EX_OK);
100 } else {
101 g_main_loop_quit(mloop);
102 g_main_loop_unref(mloop);
103 }
104 }
105
106
107
108
109
110 void
111 attrd_init_mainloop()
112 {
113 mloop = g_main_loop_new(NULL, FALSE);
114 }
115
116
117
118
119
120 void
121 attrd_run_mainloop()
122 {
123 g_main_loop_run(mloop);
124 }
125
126
127
128
129
130
131
132
133
134
135
136 static int32_t
137 attrd_ipc_accept(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
138 {
139 crm_trace("New client connection %p", c);
140 if (shutting_down) {
141 crm_info("Ignoring new connection from pid %d during shutdown",
142 pcmk__client_pid(c));
143 return -EPERM;
144 }
145
146 if (pcmk__new_client(c, uid, gid) == NULL) {
147 return -EIO;
148 }
149 return pcmk_ok;
150 }
151
152
153
154
155
156
157
158
159
160 static int32_t
161 attrd_ipc_closed(qb_ipcs_connection_t *c)
162 {
163 pcmk__client_t *client = pcmk__find_client(c);
164
165 if (client == NULL) {
166 crm_trace("Ignoring request to clean up unknown connection %p", c);
167 } else {
168 crm_trace("Cleaning up closed client connection %p", c);
169 pcmk__free_client(client);
170 }
171 return FALSE;
172 }
173
174
175
176
177
178
179
180
181
182
183 static void
184 attrd_ipc_destroy(qb_ipcs_connection_t *c)
185 {
186 crm_trace("Destroying client connection %p", c);
187 attrd_ipc_closed(c);
188 }
189
190
191
192
193
194
195
196
197 void
198 attrd_init_ipc(qb_ipcs_service_t **ipcs, qb_ipcs_msg_process_fn dispatch_fn)
199 {
200
201 static struct qb_ipcs_service_handlers ipc_callbacks = {
202 .connection_accept = attrd_ipc_accept,
203 .connection_created = NULL,
204 .msg_process = NULL,
205 .connection_closed = attrd_ipc_closed,
206 .connection_destroyed = attrd_ipc_destroy
207 };
208
209 ipc_callbacks.msg_process = dispatch_fn;
210 pcmk__serve_attrd_ipc(ipcs, &ipc_callbacks);
211 }
212
213 void
214 attrd_cib_disconnect()
215 {
216 CRM_CHECK(the_cib != NULL, return);
217 the_cib->cmds->del_notify_callback(the_cib, T_CIB_REPLACE_NOTIFY, attrd_cib_replaced_cb);
218 the_cib->cmds->del_notify_callback(the_cib, T_CIB_DIFF_NOTIFY, attrd_cib_updated_cb);
219 cib__clean_up_connection(&the_cib);
220 }
221
222 void
223 attrd_cib_replaced_cb(const char *event, xmlNode * msg)
224 {
225 int change_section = cib_change_section_nodes | cib_change_section_status | cib_change_section_alerts;
226
227 if (attrd_requesting_shutdown() || attrd_shutting_down()) {
228 return;
229 }
230
231 crm_element_value_int(msg, F_CIB_CHANGE_SECTION, &change_section);
232
233 if (attrd_election_won()) {
234 if (change_section & (cib_change_section_nodes | cib_change_section_status)) {
235 crm_notice("Updating all attributes after %s event", event);
236 write_attributes(TRUE, FALSE);
237 }
238 }
239
240 if (change_section & cib_change_section_alerts) {
241
242 mainloop_set_trigger(attrd_config_read);
243 }
244 }
245
246
247 #define plus_plus_len (5)
248
249
250
251
252
253
254
255
256
257 gboolean
258 attrd_value_needs_expansion(const char *value)
259 {
260 return ((strlen(value) >= (plus_plus_len + 2))
261 && (value[plus_plus_len] == '+')
262 && ((value[plus_plus_len + 1] == '+')
263 || (value[plus_plus_len + 1] == '=')));
264 }
265
266
267
268
269
270
271
272
273
274
275 int
276 attrd_expand_value(const char *value, const char *old_value)
277 {
278 int offset = 1;
279 int int_value = char2score(old_value);
280
281 if (value[plus_plus_len + 1] != '+') {
282 const char *offset_s = value + (plus_plus_len + 2);
283
284 offset = char2score(offset_s);
285 }
286 int_value += offset;
287
288 if (int_value > INFINITY) {
289 int_value = INFINITY;
290 }
291 return int_value;
292 }
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307 int
308 attrd_failure_regex(regex_t *regex, const char *rsc, const char *op,
309 guint interval_ms)
310 {
311 char *pattern = NULL;
312 int rc;
313
314
315
316 if (rsc == NULL) {
317 pattern = strdup(ATTRD_RE_CLEAR_ALL);
318 } else if (op == NULL) {
319 pattern = crm_strdup_printf(ATTRD_RE_CLEAR_ONE, rsc);
320 } else {
321 pattern = crm_strdup_printf(ATTRD_RE_CLEAR_OP, rsc, op, interval_ms);
322 }
323
324
325 crm_trace("Clearing attributes matching %s", pattern);
326 rc = regcomp(regex, pattern, REG_EXTENDED|REG_NOSUB);
327 free(pattern);
328
329 return (rc == 0)? pcmk_ok : -EINVAL;
330 }