~ubuntu-branches/ubuntu/utopic/pacemaker/utopic-proposed

« back to all changes in this revision

Viewing changes to tools/attrd.c

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2013-07-16 16:40:24 UTC
  • mfrom: (1.1.11) (2.2.3 experimental)
  • Revision ID: package-import@ubuntu.com-20130716164024-lvwrf4xivk1wdr3c
Tags: 1.1.9+git20130321-1ubuntu1
* Resync from debian expiremental.
* debian/control:
  - Use lower version for Build-Depends on libcorosync-dev
    and libqb-dev.
  - Build-Depends on libcfg-dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#include <fcntl.h>
30
30
 
31
31
#include <crm/crm.h>
32
 
#include <crm/cib.h>
 
32
#include <crm/cib/internal.h>
33
33
#include <crm/msg_xml.h>
34
34
#include <crm/common/ipc.h>
35
 
#include <crm/common/cluster.h>
 
35
#include <crm/common/ipcs.h>
 
36
#include <crm/cluster/internal.h>
 
37
#include <crm/common/mainloop.h>
36
38
 
37
39
#include <crm/common/xml.h>
38
 
#include <crm/common/msg.h>
39
 
#include <attrd.h>
 
40
 
 
41
#include <crm/attrd.h>
40
42
 
41
43
#define OPTARGS "hV"
42
44
#if SUPPORT_HEARTBEAT
68
70
 
69
71
} attr_hash_entry_t;
70
72
 
71
 
static void
72
 
free_hash_entry(gpointer data)
73
 
{
74
 
    attr_hash_entry_t *entry = data;
75
 
 
76
 
    if (entry == NULL) {
77
 
        return;
78
 
    }
79
 
    crm_free(entry->id);
80
 
    crm_free(entry->set);
81
 
    crm_free(entry->dampen);
82
 
    crm_free(entry->section);
83
 
    crm_free(entry->uuid);
84
 
    crm_free(entry->value);
85
 
    crm_free(entry->stored_value);
86
 
    crm_free(entry->user);
87
 
    crm_free(entry);
88
 
}
89
 
 
90
73
void attrd_local_callback(xmlNode * msg);
91
74
gboolean attrd_timer_callback(void *user_data);
92
75
gboolean attrd_trigger_update(attr_hash_entry_t * hash_entry);
93
76
void attrd_perform_update(attr_hash_entry_t * hash_entry);
94
77
 
95
78
static void
 
79
free_hash_entry(gpointer data)
 
80
{
 
81
    attr_hash_entry_t *entry = data;
 
82
 
 
83
    if (entry == NULL) {
 
84
        return;
 
85
    }
 
86
    free(entry->id);
 
87
    free(entry->set);
 
88
    free(entry->dampen);
 
89
    free(entry->section);
 
90
    free(entry->uuid);
 
91
    free(entry->value);
 
92
    free(entry->stored_value);
 
93
    free(entry->user);
 
94
    free(entry);
 
95
}
 
96
 
 
97
static int32_t
 
98
attrd_ipc_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
 
99
{
 
100
    crm_trace("Connection %p", c);
 
101
    if (need_shutdown) {
 
102
        crm_info("Ignoring new client [%d] during shutdown", crm_ipcs_client_pid(c));
 
103
        return -EPERM;
 
104
    }
 
105
 
 
106
    if (crm_client_new(c, uid, gid) == NULL) {
 
107
        return -EIO;
 
108
    }
 
109
    return 0;
 
110
}
 
111
 
 
112
static void
 
113
attrd_ipc_created(qb_ipcs_connection_t * c)
 
114
{
 
115
    crm_trace("Connection %p", c);
 
116
}
 
117
 
 
118
/* Exit code means? */
 
119
static int32_t
 
120
attrd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
 
121
{
 
122
    uint32_t id = 0;
 
123
    uint32_t flags = 0;
 
124
    crm_client_t *client = crm_client_get(c);
 
125
    xmlNode *msg = crm_ipcs_recv(client, data, size, &id, &flags);
 
126
 
 
127
    if (flags & crm_ipc_client_response) {
 
128
        crm_trace("Ack'ing msg from %d (%p)", crm_ipcs_client_pid(c), c);
 
129
        crm_ipcs_send_ack(client, id, "ack", __FUNCTION__, __LINE__);
 
130
    }
 
131
 
 
132
    if (msg == NULL) {
 
133
        crm_debug("No msg from %d (%p)", crm_ipcs_client_pid(c), c);
 
134
        return 0;
 
135
    }
 
136
#if ENABLE_ACL
 
137
    determine_request_user(client->user, msg, F_ATTRD_USER);
 
138
#endif
 
139
 
 
140
    crm_trace("Processing msg from %d (%p)", crm_ipcs_client_pid(c), c);
 
141
    crm_log_xml_trace(msg, __PRETTY_FUNCTION__);
 
142
 
 
143
    attrd_local_callback(msg);
 
144
 
 
145
    free_xml(msg);
 
146
    return 0;
 
147
}
 
148
 
 
149
/* Error code means? */
 
150
static int32_t
 
151
attrd_ipc_closed(qb_ipcs_connection_t * c)
 
152
{
 
153
    crm_client_t *client = crm_client_get(c);
 
154
 
 
155
    crm_trace("Connection %p", c);
 
156
    crm_client_destroy(client);
 
157
    return 0;
 
158
}
 
159
 
 
160
static void
 
161
attrd_ipc_destroy(qb_ipcs_connection_t * c)
 
162
{
 
163
    crm_trace("Connection %p", c);
 
164
}
 
165
 
 
166
struct qb_ipcs_service_handlers ipc_callbacks = {
 
167
    .connection_accept = attrd_ipc_accept,
 
168
    .connection_created = attrd_ipc_created,
 
169
    .msg_process = attrd_ipc_dispatch,
 
170
    .connection_closed = attrd_ipc_closed,
 
171
    .connection_destroyed = attrd_ipc_destroy
 
172
};
 
173
 
 
174
static void
96
175
attrd_shutdown(int nsig)
97
176
{
98
177
    need_shutdown = TRUE;
100
179
    if (mainloop != NULL && g_main_is_running(mainloop)) {
101
180
        g_main_quit(mainloop);
102
181
    } else {
103
 
        exit(0);
 
182
        crm_exit(0);
104
183
    }
105
184
}
106
185
 
119
198
/*      fprintf(stream, "\t-h\thelp message\n"); */
120
199
    fflush(stream);
121
200
 
122
 
    exit(exit_status);
 
201
    crm_exit(exit_status);
123
202
}
124
203
 
125
 
typedef struct attrd_client_s {
126
 
    char *id;
127
 
    char *name;
128
 
    char *user;
129
 
 
130
 
    IPC_Channel *channel;
131
 
    GCHSource *source;
132
 
} attrd_client_t;
133
 
 
134
204
static void
135
205
stop_attrd_timer(attr_hash_entry_t * hash_entry)
136
206
{
141
211
    }
142
212
}
143
213
 
144
 
static gboolean
145
 
attrd_ipc_callback(IPC_Channel * client, gpointer user_data)
146
 
{
147
 
    int lpc = 0;
148
 
    xmlNode *msg = NULL;
149
 
    attrd_client_t *curr_client = (attrd_client_t *) user_data;
150
 
    gboolean stay_connected = TRUE;
151
 
 
152
 
    crm_trace("Invoked: %s", curr_client->id);
153
 
 
154
 
    while (IPC_ISRCONN(client)) {
155
 
        if (client->ops->is_message_pending(client) == 0) {
156
 
            break;
157
 
        }
158
 
 
159
 
        msg = xmlfromIPC(client, MAX_IPC_DELAY);
160
 
        if (msg == NULL) {
161
 
            break;
162
 
        }
163
 
 
164
 
        lpc++;
165
 
 
166
 
#if ENABLE_ACL
167
 
        determine_request_user(&curr_client->user, client, msg, F_ATTRD_USER);
168
 
#endif
169
 
 
170
 
        crm_trace("Processing msg from %s", curr_client->id);
171
 
        crm_log_xml_trace(msg, __PRETTY_FUNCTION__);
172
 
 
173
 
        attrd_local_callback(msg);
174
 
 
175
 
        free_xml(msg);
176
 
        msg = NULL;
177
 
 
178
 
        if (client->ch_status != IPC_CONNECT) {
179
 
            break;
180
 
        }
181
 
    }
182
 
 
183
 
    crm_trace("Processed %d messages", lpc);
184
 
    if (client->ch_status != IPC_CONNECT) {
185
 
        stay_connected = FALSE;
186
 
    }
187
 
 
188
 
    return stay_connected;
189
 
}
190
 
 
191
 
static void
192
 
attrd_connection_destroy(gpointer user_data)
193
 
{
194
 
    attrd_client_t *client = user_data;
195
 
 
196
 
    /* cib_process_disconnect */
197
 
 
198
 
    if (client == NULL) {
199
 
        return;
200
 
    }
201
 
 
202
 
    if (client->source != NULL) {
203
 
        crm_trace("Deleting %s (%p) from mainloop", client->name, client->source);
204
 
        G_main_del_IPC_Channel(client->source);
205
 
        client->source = NULL;
206
 
    }
207
 
 
208
 
    crm_trace("Destroying %s (%p)", client->name, client);
209
 
    crm_free(client->name);
210
 
    crm_free(client->id);
211
 
    crm_free(client->user);
212
 
    crm_free(client);
213
 
    crm_trace("Freed the cib client");
214
 
 
215
 
    return;
216
 
}
217
 
 
218
 
static gboolean
219
 
attrd_connect(IPC_Channel * channel, gpointer user_data)
220
 
{
221
 
    attrd_client_t *new_client = NULL;
222
 
 
223
 
    crm_trace("Connecting channel");
224
 
 
225
 
    if (channel == NULL) {
226
 
        crm_err("Channel was NULL");
227
 
        return FALSE;
228
 
 
229
 
    } else if (channel->ch_status != IPC_CONNECT) {
230
 
        crm_err("Channel was disconnected");
231
 
        return FALSE;
232
 
    } else if (need_shutdown) {
233
 
        crm_info("Ignoring connection request during shutdown");
234
 
        return FALSE;
235
 
    }
236
 
 
237
 
    crm_malloc0(new_client, sizeof(attrd_client_t));
238
 
    new_client->channel = channel;
239
 
 
240
 
    crm_trace("Created channel %p for channel %s", new_client, new_client->id);
241
 
 
242
 
/*              channel->ops->set_recv_qlen(channel, 100); */
243
 
/*              channel->ops->set_send_qlen(channel, 400); */
244
 
 
245
 
    new_client->source =
246
 
        G_main_add_IPC_Channel(G_PRIORITY_DEFAULT, channel, FALSE, attrd_ipc_callback, new_client,
247
 
                               attrd_connection_destroy);
248
 
 
249
 
    crm_trace("Client %s connected", new_client->id);
250
 
 
251
 
    return TRUE;
252
 
}
253
 
 
254
214
static void
255
215
log_hash_entry(int level, attr_hash_entry_t * entry, const char *text)
256
216
{
257
 
    do_crm_log(level, "%s", text);
258
 
    do_crm_log(level, "Set:     %s", entry->section);
259
 
    do_crm_log(level, "Name:    %s", entry->id);
260
 
    do_crm_log(level, "Value:   %s", entry->value);
261
 
    do_crm_log(level, "Timeout: %s", entry->dampen);
 
217
    do_crm_log(level, "%s: Set: %s, Name: %s, Value: %s, Timeout: %s",
 
218
               text, entry->section, entry->id, entry->value, entry->dampen);
262
219
}
263
220
 
264
221
static attr_hash_entry_t *
278
235
    if (hash_entry == NULL) {
279
236
        /* create one and add it */
280
237
        crm_info("Creating hash entry for %s", attr);
281
 
        crm_malloc0(hash_entry, sizeof(attr_hash_entry_t));
282
 
        hash_entry->id = crm_strdup(attr);
 
238
        hash_entry = calloc(1, sizeof(attr_hash_entry_t));
 
239
        hash_entry->id = strdup(attr);
283
240
 
284
241
        g_hash_table_insert(attr_hash, hash_entry->id, hash_entry);
285
242
        hash_entry = g_hash_table_lookup(attr_hash, attr);
288
245
 
289
246
    value = crm_element_value(msg, F_ATTRD_SET);
290
247
    if (value != NULL) {
291
 
        crm_free(hash_entry->set);
292
 
        hash_entry->set = crm_strdup(value);
 
248
        free(hash_entry->set);
 
249
        hash_entry->set = strdup(value);
293
250
        crm_debug("\t%s->set: %s", attr, value);
294
251
    }
295
252
 
297
254
    if (value == NULL) {
298
255
        value = XML_CIB_TAG_STATUS;
299
256
    }
300
 
    crm_free(hash_entry->section);
301
 
    hash_entry->section = crm_strdup(value);
 
257
    free(hash_entry->section);
 
258
    hash_entry->section = strdup(value);
302
259
    crm_trace("\t%s->section: %s", attr, value);
303
260
 
304
261
    value = crm_element_value(msg, F_ATTRD_DAMPEN);
305
262
    if (value != NULL) {
306
 
        crm_free(hash_entry->dampen);
307
 
        hash_entry->dampen = crm_strdup(value);
 
263
        free(hash_entry->dampen);
 
264
        hash_entry->dampen = strdup(value);
308
265
 
309
266
        hash_entry->timeout = crm_get_msec(value);
310
267
        crm_trace("\t%s->timeout: %s", attr, value);
311
268
    }
312
269
#if ENABLE_ACL
313
 
    crm_free(hash_entry->user);
 
270
    free(hash_entry->user);
314
271
 
315
272
    value = crm_element_value(msg, F_ATTRD_USER);
316
273
    if (value != NULL) {
317
 
        hash_entry->user = crm_strdup(value);
 
274
        hash_entry->user = strdup(value);
318
275
        crm_trace("\t%s->user: %s", attr, value);
319
276
    }
320
277
#endif
339
296
        g_main_quit(mainloop);
340
297
        return;
341
298
    }
342
 
    exit(LSB_EXIT_OK);
 
299
    crm_exit(EX_OK);
343
300
}
344
301
 
345
302
static void
369
326
 
370
327
#if SUPPORT_COROSYNC
371
328
static gboolean
372
 
attrd_ais_dispatch(AIS_Message * wrapper, char *data, int sender)
 
329
attrd_ais_dispatch(int kind, const char *from, const char *data)
373
330
{
374
331
    xmlNode *xml = NULL;
375
332
 
376
 
    if (wrapper->header.id == crm_class_cluster) {
 
333
    if (kind == crm_class_cluster) {
377
334
        xml = string2xml(data);
378
335
        if (xml == NULL) {
379
 
            crm_err("Bad message received: %d:'%.120s'", wrapper->id, data);
 
336
            crm_err("Bad message received: '%.120s'", data);
380
337
        }
381
338
    }
382
339
 
386
343
        const char *host = crm_element_value(xml, F_ATTRD_HOST);
387
344
        const char *ignore = crm_element_value(xml, F_ATTRD_IGNORE_LOCALLY);
388
345
 
389
 
        crm_xml_add_int(xml, F_SEQ, wrapper->id);
390
 
        crm_xml_add(xml, F_ORIG, wrapper->sender.uname);
 
346
        /* crm_xml_add_int(xml, F_SEQ, wrapper->id); */
 
347
        crm_xml_add(xml, F_ORIG, from);
391
348
 
392
349
        if (host != NULL && safe_str_eq(host, attrd_uname)) {
393
 
            crm_notice("Update relayed from %s", wrapper->sender.uname);
 
350
            crm_notice("Update relayed from %s", from);
394
351
            attrd_local_callback(xml);
395
352
 
396
 
        } else if (ignore == NULL || safe_str_neq(wrapper->sender.uname, attrd_uname)) {
397
 
            crm_trace("%s message from %s", op, wrapper->sender.uname);
 
353
        } else if (ignore == NULL || safe_str_neq(from, attrd_uname)) {
 
354
            crm_trace("%s message from %s", op, from);
398
355
            hash_entry = find_hash_entry(xml);
399
356
            stop_attrd_timer(hash_entry);
400
357
            attrd_perform_update(hash_entry);
409
366
static void
410
367
attrd_ais_destroy(gpointer unused)
411
368
{
412
 
    ais_fd_sync = -1;
413
369
    if (need_shutdown) {
414
370
        /* we signed out, so this is expected */
415
 
        crm_info("OpenAIS disconnection complete");
 
371
        crm_info("Corosync disconnection complete");
416
372
        return;
417
373
    }
418
374
 
419
 
    crm_crit("Lost connection to OpenAIS service!");
 
375
    crm_crit("Lost connection to Corosync service!");
420
376
    if (mainloop != NULL && g_main_is_running(mainloop)) {
421
377
        g_main_quit(mainloop);
422
378
        return;
423
379
    }
424
 
    exit(LSB_EXIT_GENERIC);
 
380
    crm_exit(EX_USAGE);
425
381
}
426
382
#endif
427
383
 
428
384
static void
429
385
attrd_cib_connection_destroy(gpointer user_data)
430
386
{
 
387
    cib_t *conn = user_data;
 
388
 
 
389
    conn->cmds->signoff(conn);  /* Ensure IPC is cleaned up */
 
390
 
431
391
    if (need_shutdown) {
432
392
        crm_info("Connection to the CIB terminated...");
433
393
 
434
394
    } else {
435
395
        /* eventually this will trigger a reconnect, not a shutdown */
436
396
        crm_err("Connection to the CIB terminated...");
437
 
        exit(1);
 
397
        crm_exit(1);
438
398
    }
439
399
 
440
400
    return;
451
411
}
452
412
 
453
413
static void
 
414
local_update_for_hash_entry(gpointer key, gpointer value, gpointer user_data)
 
415
{
 
416
    attr_hash_entry_t *entry = value;
 
417
 
 
418
    if (entry->timer_id == 0) {
 
419
        crm_trace("Performing local-only update after replace for %s", entry->id);
 
420
        attrd_perform_update(entry);
 
421
        /* } else {
 
422
         *     just let the timer expire and attrd_timer_callback() will do the right thing
 
423
         */
 
424
    }
 
425
}
 
426
 
 
427
static void
454
428
do_cib_replaced(const char *event, xmlNode * msg)
455
429
{
456
 
    crm_info("Sending full refresh");
457
 
    g_hash_table_foreach(attr_hash, update_for_hash_entry, NULL);
 
430
    crm_info("Updating all attributes after %s event", event);
 
431
    g_hash_table_foreach(attr_hash, local_update_for_hash_entry, NULL);
458
432
}
459
433
 
460
434
static gboolean
470
444
    }
471
445
 
472
446
    if (was_err == FALSE) {
473
 
        enum cib_errors rc = cib_not_connected;
 
447
        int rc = -ENOTCONN;
474
448
 
475
449
        if (attempts < max_retry) {
476
450
            crm_debug("CIB signon attempt %d", attempts);
477
451
            rc = local_conn->cmds->signon(local_conn, T_ATTRD, cib_command);
478
452
        }
479
453
 
480
 
        if (rc != cib_ok && attempts > max_retry) {
481
 
            crm_err("Signon to CIB failed: %s", cib_error2string(rc));
 
454
        if (rc != pcmk_ok && attempts > max_retry) {
 
455
            crm_err("Signon to CIB failed: %s", pcmk_strerror(rc));
482
456
            was_err = TRUE;
483
457
 
484
 
        } else if (rc != cib_ok) {
 
458
        } else if (rc != pcmk_ok) {
485
459
            attempts++;
486
460
            return TRUE;
487
461
        }
490
464
    crm_info("Connected to the CIB after %d signon attempts", attempts);
491
465
 
492
466
    if (was_err == FALSE) {
493
 
        enum cib_errors rc =
494
 
            local_conn->cmds->set_connection_dnotify(local_conn, attrd_cib_connection_destroy);
495
 
        if (rc != cib_ok) {
 
467
        int rc = local_conn->cmds->set_connection_dnotify(local_conn, attrd_cib_connection_destroy);
 
468
 
 
469
        if (rc != pcmk_ok) {
496
470
            crm_err("Could not set dnotify callback");
497
471
            was_err = TRUE;
498
472
        }
499
473
    }
500
474
 
501
475
    if (was_err == FALSE) {
502
 
        if (cib_ok !=
 
476
        if (pcmk_ok !=
503
477
            local_conn->cmds->add_notify_callback(local_conn, T_CIB_REPLACE_NOTIFY,
504
478
                                                  do_cib_replaced)) {
505
479
            crm_err("Could not set CIB notification callback");
509
483
 
510
484
    if (was_err) {
511
485
        crm_err("Aborting startup");
512
 
        exit(100);
 
486
        crm_exit(100);
513
487
    }
514
488
 
515
489
    cib_conn = local_conn;
516
490
 
517
 
    crm_info("Sending full refresh");
518
 
    g_hash_table_foreach(attr_hash, update_for_hash_entry, NULL);
 
491
    crm_info("Sending full refresh now that we're connected to the cib");
 
492
    g_hash_table_foreach(attr_hash, local_update_for_hash_entry, NULL);
519
493
 
520
494
    return FALSE;
521
495
}
525
499
{
526
500
    int flag = 0;
527
501
    int argerr = 0;
 
502
    crm_cluster_t cluster;
528
503
    gboolean was_err = FALSE;
529
 
    char *channel_name = crm_strdup(T_ATTRD);
 
504
    qb_ipcs_connection_t *c = NULL;
 
505
    qb_ipcs_service_t *ipcs = NULL;
530
506
 
531
 
    crm_log_init(T_ATTRD, LOG_NOTICE, TRUE, FALSE, argc, argv);
 
507
    crm_log_init(T_ATTRD, LOG_NOTICE, TRUE, FALSE, argc, argv, FALSE);
532
508
    mainloop_add_signal(SIGTERM, attrd_shutdown);
533
509
 
534
510
    while ((flag = getopt(argc, argv, OPTARGS)) != EOF) {
535
511
        switch (flag) {
536
512
            case 'V':
537
 
                crm_bump_log_level();
 
513
                crm_bump_log_level(argc, argv);
538
514
                break;
539
515
            case 'h':          /* Help message */
540
 
                usage(T_ATTRD, LSB_EXIT_OK);
 
516
                usage(T_ATTRD, EX_OK);
541
517
                break;
542
518
            default:
543
519
                ++argerr;
550
526
    }
551
527
 
552
528
    if (argerr) {
553
 
        usage(T_ATTRD, LSB_EXIT_GENERIC);
 
529
        usage(T_ATTRD, EX_USAGE);
554
530
    }
555
531
 
556
532
    attr_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, free_hash_entry);
558
534
    crm_info("Starting up");
559
535
 
560
536
    if (was_err == FALSE) {
561
 
        void *destroy = NULL;
562
 
        void *dispatch = NULL;
563
 
        void *data = NULL;
564
537
 
565
538
#if SUPPORT_COROSYNC
566
539
        if (is_openais_cluster()) {
567
 
            destroy = attrd_ais_destroy;
568
 
            dispatch = attrd_ais_dispatch;
 
540
            cluster.destroy = attrd_ais_destroy;
 
541
            cluster.cs_dispatch = attrd_ais_dispatch;
569
542
        }
570
543
#endif
571
544
 
572
545
#if SUPPORT_HEARTBEAT
573
546
        if (is_heartbeat_cluster()) {
574
 
            data = &attrd_cluster_conn;
575
 
            dispatch = attrd_ha_callback;
576
 
            destroy = attrd_ha_connection_destroy;
 
547
            cluster.hb_conn = NULL;
 
548
            cluster.hb_dispatch = attrd_ha_callback;
 
549
            cluster.destroy = attrd_ha_connection_destroy;
577
550
        }
578
551
#endif
579
552
 
580
 
        if (FALSE == crm_cluster_connect(&attrd_uname, &attrd_uuid, dispatch, destroy, data)) {
 
553
        if (FALSE == crm_cluster_connect(&cluster)) {
581
554
            crm_err("HA Signon failed");
582
555
            was_err = TRUE;
583
556
        }
 
557
 
 
558
        attrd_uname = cluster.uname;
 
559
        attrd_uuid = cluster.uuid;
 
560
#if SUPPORT_HEARTBEAT
 
561
        attrd_cluster_conn = cluster.hb_conn;
 
562
#endif
584
563
    }
585
564
 
586
565
    crm_info("Cluster connection active");
587
566
 
588
567
    if (was_err == FALSE) {
589
 
        int rc = init_server_ipc_comms(channel_name, attrd_connect,
590
 
                                       default_ipc_connection_destroy);
591
 
 
592
 
        if (rc != 0) {
593
 
            crm_err("Could not start IPC server");
594
 
            was_err = TRUE;
595
 
        }
 
568
        attrd_ipc_server_init(&ipcs, &ipc_callbacks);
596
569
    }
597
570
 
598
571
    crm_info("Accepting attribute updates");
620
593
    }
621
594
#endif
622
595
 
 
596
    c = qb_ipcs_connection_first_get(ipcs);
 
597
    while (c != NULL) {
 
598
        qb_ipcs_connection_t *last = c;
 
599
 
 
600
        c = qb_ipcs_connection_next_get(ipcs, last);
 
601
 
 
602
        /* There really shouldn't be anyone connected at this point */
 
603
        crm_notice("Disconnecting client %p, pid=%d...", last, crm_ipcs_client_pid(last));
 
604
        qb_ipcs_disconnect(last);
 
605
        qb_ipcs_connection_unref(last);
 
606
    }
 
607
 
 
608
    qb_ipcs_destroy(ipcs);
 
609
 
623
610
    if (cib_conn) {
624
611
        cib_conn->cmds->signoff(cib_conn);
625
612
        cib_delete(cib_conn);
626
613
    }
627
614
 
628
615
    g_hash_table_destroy(attr_hash);
629
 
    crm_free(channel_name);
630
 
    crm_free(attrd_uuid);
 
616
    free(attrd_uuid);
631
617
    empty_uuid_cache();
632
618
 
633
 
    return 0;
 
619
    return crm_exit(0);
634
620
}
635
621
 
636
622
struct attrd_callback_s {
644
630
    attr_hash_entry_t *hash_entry = NULL;
645
631
    struct attrd_callback_s *data = user_data;
646
632
 
647
 
    if (data->value == NULL && rc == cib_NOTEXISTS) {
648
 
        rc = cib_ok;
 
633
    if (data->value == NULL && rc == -ENXIO) {
 
634
        rc = pcmk_ok;
 
635
 
 
636
    } else if (call_id < 0) {
 
637
        crm_warn("Update %s=%s failed: %s", data->attr, data->value, pcmk_strerror(call_id));
 
638
        goto cleanup;
649
639
    }
650
640
 
651
641
    switch (rc) {
652
 
        case cib_ok:
 
642
        case pcmk_ok:
653
643
            crm_debug("Update %d for %s=%s passed", call_id, data->attr, data->value);
654
644
            hash_entry = g_hash_table_lookup(attr_hash, data->attr);
655
645
 
656
646
            if (hash_entry) {
657
 
                crm_free(hash_entry->stored_value);
 
647
                free(hash_entry->stored_value);
658
648
                hash_entry->stored_value = NULL;
659
649
                if (data->value != NULL) {
660
 
                    hash_entry->stored_value = crm_strdup(data->value);
 
650
                    hash_entry->stored_value = strdup(data->value);
661
651
                }
662
652
            }
663
653
            break;
664
 
        case cib_diff_failed:  /* When an attr changes while the CIB is syncing */
665
 
        case cib_remote_timeout:       /* When an attr changes while there is a DC election */
666
 
        case cib_NOTEXISTS:    /* When an attr changes while the CIB is syncing a
 
654
        case -pcmk_err_diff_failed:    /* When an attr changes while the CIB is syncing */
 
655
        case -ETIME:           /* When an attr changes while there is a DC election */
 
656
        case -ENXIO:           /* When an attr changes while the CIB is syncing a
667
657
                                 *   newer config from a node that just came up
668
658
                                 */
669
659
            crm_warn("Update %d for %s=%s failed: %s",
670
 
                     call_id, data->attr, data->value, cib_error2string(rc));
 
660
                     call_id, data->attr, data->value, pcmk_strerror(rc));
671
661
            break;
672
662
        default:
673
663
            crm_err("Update %d for %s=%s failed: %s",
674
 
                    call_id, data->attr, data->value, cib_error2string(rc));
 
664
                    call_id, data->attr, data->value, pcmk_strerror(rc));
675
665
    }
676
 
 
677
 
    crm_free(data->value);
678
 
    crm_free(data->attr);
679
 
    crm_free(data);
 
666
  cleanup:
 
667
    free(data->value);
 
668
    free(data->attr);
 
669
    free(data);
680
670
}
681
671
 
682
672
void
683
673
attrd_perform_update(attr_hash_entry_t * hash_entry)
684
674
{
685
 
    int rc = cib_ok;
 
675
    int rc = pcmk_ok;
686
676
    struct attrd_callback_s *data = NULL;
687
677
    const char *user_name = NULL;
688
678
 
708
698
                                  hash_entry->set, hash_entry->uuid, hash_entry->id, NULL, FALSE,
709
699
                                  user_name);
710
700
 
711
 
        if (hash_entry->stored_value) {
 
701
        if (rc >= 0 && hash_entry->stored_value) {
712
702
            crm_notice("Sent delete %d: node=%s, attr=%s, id=%s, set=%s, section=%s",
713
703
                       rc, attrd_uuid, hash_entry->id,
714
704
                       hash_entry->uuid ? hash_entry->uuid : "<n/a>", hash_entry->set,
715
705
                       hash_entry->section);
716
706
 
717
 
        } else if (rc < 0 && rc != cib_NOTEXISTS) {
 
707
        } else if (rc < 0 && rc != -ENXIO) {
718
708
            crm_notice
719
709
                ("Delete operation failed: node=%s, attr=%s, id=%s, set=%s, section=%s: %s (%d)",
720
710
                 attrd_uuid, hash_entry->id, hash_entry->uuid ? hash_entry->uuid : "<n/a>",
721
 
                 hash_entry->set, hash_entry->section, cib_error2string(rc), rc);
 
711
                 hash_entry->set, hash_entry->section, pcmk_strerror(rc), rc);
722
712
 
723
713
        } else {
724
714
            crm_trace("Sent delete %d: node=%s, attr=%s, id=%s, set=%s, section=%s",
725
 
                        rc, attrd_uuid, hash_entry->id,
726
 
                        hash_entry->uuid ? hash_entry->uuid : "<n/a>", hash_entry->set,
727
 
                        hash_entry->section);
 
715
                      rc, attrd_uuid, hash_entry->id,
 
716
                      hash_entry->uuid ? hash_entry->uuid : "<n/a>", hash_entry->set,
 
717
                      hash_entry->section);
728
718
        }
729
719
 
730
720
    } else {
732
722
        rc = update_attr_delegate(cib_conn, cib_none, hash_entry->section,
733
723
                                  attrd_uuid, NULL, hash_entry->set, hash_entry->uuid,
734
724
                                  hash_entry->id, hash_entry->value, FALSE, user_name);
 
725
        if (rc < 0) {
 
726
            crm_notice("Sent update %s=%s failed: %s", hash_entry->id, hash_entry->value,
 
727
                       pcmk_strerror(rc));
 
728
        }
735
729
        if (safe_str_neq(hash_entry->value, hash_entry->stored_value) || rc < 0) {
736
730
            crm_notice("Sent update %d: %s=%s", rc, hash_entry->id, hash_entry->value);
737
731
        } else {
739
733
        }
740
734
    }
741
735
 
742
 
    crm_malloc0(data, sizeof(struct attrd_callback_s));
743
 
    data->attr = crm_strdup(hash_entry->id);
 
736
    data = calloc(1, sizeof(struct attrd_callback_s));
 
737
    data->attr = strdup(hash_entry->id);
744
738
    if (hash_entry->value != NULL) {
745
 
        data->value = crm_strdup(hash_entry->value);
 
739
        data->value = strdup(hash_entry->value);
746
740
    }
747
 
    add_cib_op_callback(cib_conn, rc, FALSE, data, attrd_cib_callback);
748
 
 
 
741
    cib_conn->cmds->register_callback(cib_conn, rc, 120, FALSE, data, "attrd_cib_callback",
 
742
                                      attrd_cib_callback);
749
743
    return;
750
744
}
751
745
 
767
761
    }
768
762
 
769
763
    if (host != NULL && safe_str_neq(host, attrd_uname)) {
770
 
        send_cluster_message(host, crm_msg_attrd, msg, FALSE);
 
764
        send_cluster_message(crm_get_peer(0, host), crm_msg_attrd, msg, FALSE);
771
765
        return;
772
766
    }
773
767
 
781
775
        const char *key = crm_element_value(msg, F_ATTRD_KEY);
782
776
 
783
777
        if (key) {
784
 
            hash_entry->uuid = crm_strdup(key);
 
778
            hash_entry->uuid = strdup(key);
785
779
        }
786
780
    }
787
781
 
827
821
        return;
828
822
    }
829
823
 
830
 
    crm_free(hash_entry->value);
 
824
    free(hash_entry->value);
831
825
    hash_entry->value = NULL;
832
826
    if (value != NULL) {
833
 
        hash_entry->value = crm_strdup(value);
 
827
        hash_entry->value = strdup(value);
834
828
        crm_debug("New value of %s is %s", attr, value);
835
829
    }
836
830