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

« back to all changes in this revision

Viewing changes to cib/main.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:
1
 
/* 
 
1
/*
2
2
 * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
3
 
 * 
 
3
 *
4
4
 * This program is free software; you can redistribute it and/or
5
5
 * modify it under the terms of the GNU General Public
6
6
 * License as published by the Free Software Foundation; either
7
7
 * version 2 of the License, or (at your option) any later version.
8
 
 * 
 
8
 *
9
9
 * This software is distributed in the hope that it will be useful,
10
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
12
 * General Public License for more details.
13
 
 * 
 
13
 *
14
14
 * You should have received a copy of the GNU General Public
15
15
 * License along with this library; if not, write to the Free Software
16
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
30
30
#include <fcntl.h>
31
31
 
32
32
#include <crm/crm.h>
33
 
#include <crm/cib.h>
 
33
#include <crm/cib/internal.h>
34
34
#include <crm/msg_xml.h>
35
 
#include <crm/common/ipc.h>
36
 
#include <crm/common/cluster.h>
 
35
#include <crm/cluster/internal.h>
37
36
 
38
37
#include <crm/common/xml.h>
39
 
#include <crm/common/msg.h>
 
38
 
 
39
#include <crm/common/mainloop.h>
40
40
 
41
41
#include <cibio.h>
42
42
#include <callbacks.h>
58
58
extern gboolean stand_alone;
59
59
 
60
60
gboolean cib_shutdown_flag = FALSE;
61
 
enum cib_errors cib_status = cib_ok;
 
61
int cib_status = pcmk_ok;
 
62
 
 
63
crm_cluster_t crm_cluster;
62
64
 
63
65
#if SUPPORT_HEARTBEAT
64
66
oc_ev_t *cib_ev_token;
65
67
ll_cluster_t *hb_conn = NULL;
66
68
extern void oc_ev_special(const oc_ev_t *, oc_ev_class_t, int);
67
69
gboolean cib_register_ha(ll_cluster_t * hb_cluster, const char *client_name);
 
70
#else
 
71
void *hb_conn = NULL;
68
72
#endif
69
73
 
70
74
extern void terminate_cib(const char *caller, gboolean fast);
71
75
 
72
76
GMainLoop *mainloop = NULL;
73
 
const char *cib_root = CRM_CONFIG_DIR;
 
77
const char *cib_root = NULL;
74
78
char *cib_our_uname = NULL;
75
79
gboolean preserve_status = FALSE;
76
80
gboolean cib_writes_enabled = TRUE;
77
81
int remote_fd = 0;
78
82
int remote_tls_fd = 0;
79
83
 
80
 
void usage(const char *cmd, int exit_status);
81
84
int cib_init(void);
82
85
void cib_shutdown(int nsig);
83
 
void cib_ha_connection_destroy(gpointer user_data);
84
86
gboolean startCib(const char *filename);
85
87
extern int write_cib_contents(gpointer p);
86
88
 
87
 
GTRIGSource *cib_writer = NULL;
88
 
GHashTable *client_list = NULL;
89
89
GHashTable *config_hash = NULL;
 
90
GHashTable *local_notify_queue = NULL;
90
91
 
91
92
char *channel1 = NULL;
92
93
char *channel2 = NULL;
105
106
}
106
107
 
107
108
static void
108
 
cib_diskwrite_complete(gpointer userdata, int status, int signo, int exitcode)
109
 
{
110
 
    if (exitcode != LSB_EXIT_OK || signo != 0 || status != 0) {
111
 
        crm_err("Disk write failed: status=%d, signo=%d, exitcode=%d", status, signo, exitcode);
112
 
 
113
 
        if (cib_writes_enabled) {
114
 
            crm_err("Disabling disk writes after write failure");
115
 
            cib_writes_enabled = FALSE;
116
 
        }
117
 
 
118
 
    } else {
119
 
        crm_trace("Disk write passed");
120
 
    }
121
 
}
122
 
 
123
 
static void
124
109
log_cib_client(gpointer key, gpointer value, gpointer user_data)
125
110
{
126
 
    cib_client_t *a_client = value;
127
 
 
128
 
    crm_info("Client %s/%s", crm_str(a_client->name),
129
 
    crm_str(a_client->channel_name));
 
111
    crm_info("Client %s", crm_client_name(value));
130
112
}
131
113
 
 
114
/* *INDENT-OFF* */
 
115
static struct crm_option long_options[] = {
 
116
    /* Top-level Options */
 
117
    {"help",    0, 0, '?', "\tThis text"},
 
118
    {"verbose", 0, 0, 'V', "\tIncrease debug output"},
 
119
 
 
120
    {"per-action-cib", 0, 0, 'a', "\tAdvanced use only"},
 
121
    {"stand-alone",    0, 0, 's', "\tAdvanced use only"},
 
122
    {"disk-writes",    0, 0, 'w', "\tAdvanced use only"},
 
123
    {"cib-root",       1, 0, 'r', "\tAdvanced use only"},
 
124
 
 
125
    {0, 0, 0, 0}
 
126
};
 
127
/* *INDENT-ON* */
 
128
 
132
129
int
133
130
main(int argc, char **argv)
134
131
{
135
132
    int flag;
136
133
    int rc = 0;
 
134
    int index = 0;
137
135
    int argerr = 0;
138
 
 
139
 
#ifdef HAVE_GETOPT_H
140
 
    int option_index = 0;
141
 
/* *INDENT-OFF* */
142
 
        static struct option long_options[] = {
143
 
                {"per-action-cib", 0, 0, 'a'},
144
 
                {"stand-alone",    0, 0, 's'},
145
 
                {"disk-writes",    0, 0, 'w'},
146
 
 
147
 
                {"cib-root",    1, 0, 'r'},
148
 
 
149
 
                {"verbose",     0, 0, 'V'},
150
 
                {"help",        0, 0, '?'},
151
 
                {"metadata",    0, 0, 'm'},
152
 
 
153
 
                {0, 0, 0, 0}
154
 
        };
155
 
/* *INDENT-ON* */
156
 
#endif
157
 
 
158
136
    struct passwd *pwentry = NULL;
159
137
 
160
 
    crm_log_init("cib", LOG_INFO, TRUE, FALSE, 0, NULL);
 
138
    crm_log_init(NULL, LOG_INFO, TRUE, FALSE, argc, argv, FALSE);
 
139
    crm_set_options(NULL, "[options]",
 
140
                    long_options, "Daemon for storing and replicating the cluster configuration");
 
141
 
161
142
    mainloop_add_signal(SIGTERM, cib_shutdown);
162
143
    mainloop_add_signal(SIGPIPE, cib_enable_writes);
163
144
 
164
 
    cib_writer =
165
 
        G_main_add_tempproc_trigger(G_PRIORITY_LOW, write_cib_contents, "write_cib_contents", NULL,
166
 
                                    NULL, NULL, cib_diskwrite_complete);
167
 
 
168
 
    /* EnableProcLogging(); */
169
 
    set_sigchld_proctrack(G_PRIORITY_HIGH, DEFAULT_MAXDISPATCHTIME);
 
145
    cib_writer = mainloop_add_trigger(G_PRIORITY_LOW, write_cib_contents, NULL);
170
146
 
171
147
    crm_peer_init();
172
 
    client_list = g_hash_table_new(crm_str_hash, g_str_equal);
173
148
 
174
149
    while (1) {
175
 
#ifdef HAVE_GETOPT_H
176
 
        flag = getopt_long(argc, argv, OPTARGS, long_options, &option_index);
177
 
#else
178
 
        flag = getopt(argc, argv, OPTARGS);
179
 
#endif
 
150
        flag = crm_get_option(argc, argv, &index);
180
151
        if (flag == -1)
181
152
            break;
182
153
 
183
154
        switch (flag) {
184
155
            case 'V':
185
 
                crm_bump_log_level();
 
156
                crm_bump_log_level(argc, argv);
186
157
                break;
187
158
            case 's':
188
159
                stand_alone = TRUE;
207
178
                }
208
179
                break;
209
180
            case '?':          /* Help message */
210
 
                usage(crm_system_name, LSB_EXIT_OK);
 
181
                crm_help(flag, EX_OK);
211
182
                break;
212
183
            case 'w':
213
184
                cib_writes_enabled = TRUE;
233
204
    }
234
205
 
235
206
    if (argerr) {
236
 
        usage(crm_system_name, LSB_EXIT_GENERIC);
 
207
        crm_help('?', EX_USAGE);
 
208
    }
 
209
 
 
210
    if (cib_root == NULL) {
 
211
        char *path = g_strdup_printf("%s/cib.xml", CRM_CONFIG_DIR);
 
212
        char *legacy = g_strdup_printf("%s/cib.xml", CRM_LEGACY_CONFIG_DIR);
 
213
 
 
214
        if (g_file_test(path, G_FILE_TEST_EXISTS)) {
 
215
            cib_root = CRM_CONFIG_DIR;
 
216
 
 
217
        } else if (g_file_test(legacy, G_FILE_TEST_EXISTS)) {
 
218
            cib_root = CRM_LEGACY_CONFIG_DIR;
 
219
            crm_notice("Using legacy config location: %s", cib_root);
 
220
 
 
221
        } else {
 
222
            cib_root = CRM_CONFIG_DIR;
 
223
            crm_notice("Using new config location: %s", cib_root);
 
224
        }
 
225
 
 
226
        g_free(legacy);
 
227
        g_free(path);
 
228
 
 
229
    } else {
 
230
        crm_notice("Using custom config location: %s", cib_root);
237
231
    }
238
232
 
239
233
    if (crm_is_writable(cib_root, NULL, CRM_DAEMON_USER, CRM_DAEMON_GROUP, FALSE) == FALSE) {
246
240
    /* read local config file */
247
241
    rc = cib_init();
248
242
 
249
 
    CRM_CHECK(g_hash_table_size(client_list) == 0, crm_warn("Not all clients gone at exit"));
250
 
    g_hash_table_foreach(client_list, log_cib_client, NULL);
 
243
    CRM_CHECK(crm_hash_table_size(client_connections) == 0,
 
244
              crm_warn("Not all clients gone at exit"));
 
245
    g_hash_table_foreach(client_connections, log_cib_client, NULL);
251
246
    cib_cleanup();
252
247
 
253
248
#if SUPPORT_HEARTBEAT
264
259
cib_cleanup(void)
265
260
{
266
261
    crm_peer_destroy();
 
262
    if (local_notify_queue) {
 
263
        g_hash_table_destroy(local_notify_queue);
 
264
    }
 
265
    crm_client_cleanup();
267
266
    g_hash_table_destroy(config_hash);
268
 
    g_hash_table_destroy(client_list);
269
 
    crm_free(cib_our_uname);
270
 
#if HAVE_LIBXML2
271
 
    crm_xml_cleanup();
272
 
#endif
273
 
    crm_free(channel1);
274
 
    crm_free(channel2);
275
 
    crm_free(channel3);
276
 
    crm_free(channel4);
277
 
    crm_free(channel5);
 
267
    free(cib_our_uname);
 
268
    free(channel1);
 
269
    free(channel2);
 
270
    free(channel3);
 
271
    free(channel4);
 
272
    free(channel5);
278
273
}
279
274
 
280
275
unsigned long cib_num_ops = 0;
281
276
const char *cib_stat_interval = "10min";
282
277
unsigned long cib_num_local = 0, cib_num_updates = 0, cib_num_fail = 0;
283
278
unsigned long cib_bad_connects = 0, cib_num_timeouts = 0;
284
 
longclock_t cib_call_time = 0;
285
 
 
286
 
gboolean cib_stats(gpointer data);
287
 
 
288
 
gboolean
289
 
cib_stats(gpointer data)
290
 
{
291
 
    int local_log_level = LOG_DEBUG;
292
 
    static unsigned long last_stat = 0;
293
 
    unsigned int cib_calls_ms = 0;
294
 
    static unsigned long cib_stat_interval_ms = 0;
295
 
 
296
 
    if (cib_stat_interval_ms == 0) {
297
 
        cib_stat_interval_ms = crm_get_msec(cib_stat_interval);
298
 
    }
299
 
 
300
 
    cib_calls_ms = longclockto_ms(cib_call_time);
301
 
 
302
 
    if ((cib_num_ops - last_stat) > 0) {
303
 
        unsigned long calls_diff = cib_num_ops - last_stat;
304
 
        double stat_1 = (1000 * cib_calls_ms) / calls_diff;
305
 
 
306
 
        local_log_level = LOG_INFO;
307
 
        do_crm_log(local_log_level,
308
 
                   "Processed %lu operations"
309
 
                   " (%.2fus average, %lu%% utilization) in the last %s",
310
 
                   calls_diff, stat_1,
311
 
                   (100 * cib_calls_ms) / cib_stat_interval_ms, cib_stat_interval);
312
 
    }
313
 
 
314
 
    crm_trace(
315
 
                        "\tDetail: %lu operations (%ums total)"
316
 
                        " (%lu local, %lu updates, %lu failures,"
317
 
                        " %lu timeouts, %lu bad connects)",
318
 
                        cib_num_ops, cib_calls_ms, cib_num_local, cib_num_updates,
319
 
                        cib_num_fail, cib_bad_connects, cib_num_timeouts);
320
 
 
321
 
    last_stat = cib_num_ops;
322
 
    cib_call_time = 0;
323
 
    return TRUE;
324
 
}
325
279
 
326
280
#if SUPPORT_HEARTBEAT
327
281
gboolean ccm_connect(void);
346
300
    int cib_ev_fd;
347
301
 
348
302
    int (*ccm_api_register) (oc_ev_t ** token) =
349
 
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_register");
 
303
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_register", 1);
350
304
 
351
305
    int (*ccm_api_set_callback) (const oc_ev_t * token,
352
306
                                 oc_ev_class_t class,
353
307
                                 oc_ev_callback_t * fn,
354
308
                                 oc_ev_callback_t ** prev_fn) =
355
 
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_set_callback");
 
309
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_set_callback", 1);
356
310
 
357
311
    void (*ccm_api_special) (const oc_ev_t *, oc_ev_class_t, int) =
358
 
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_special");
 
312
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_special", 1);
359
313
    int (*ccm_api_activate) (const oc_ev_t * token, int *fd) =
360
 
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_activate");
 
314
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_activate", 1);
361
315
    int (*ccm_api_unregister) (oc_ev_t * token) =
362
 
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_unregister");
 
316
        find_library_function(&ccm_library, CCM_LIBRARY, "oc_ev_unregister", 1);
 
317
 
 
318
    static struct mainloop_fd_callbacks ccm_fd_callbacks = {
 
319
        .dispatch = cib_ccm_dispatch,
 
320
        .destroy = ccm_connection_destroy,
 
321
    };
363
322
 
364
323
    while (did_fail) {
365
324
        did_fail = FALSE;
405
364
    }
406
365
 
407
366
    crm_debug("CCM Activation passed... all set to go!");
408
 
    G_main_add_fd(G_PRIORITY_HIGH, cib_ev_fd, FALSE,
409
 
                  cib_ccm_dispatch, cib_ev_token, ccm_connection_destroy);
 
367
    mainloop_add_fd("heartbeat-ccm", G_PRIORITY_MEDIUM, cib_ev_fd, cib_ev_token, &ccm_fd_callbacks);
410
368
 
411
369
    return TRUE;
412
370
}
414
372
 
415
373
#if SUPPORT_COROSYNC
416
374
static gboolean
417
 
cib_ais_dispatch(AIS_Message * wrapper, char *data, int sender)
 
375
cib_ais_dispatch(int kind, const char *from, const char *data)
418
376
{
419
377
    xmlNode *xml = NULL;
420
378
 
421
 
    if (wrapper->header.id == crm_class_cluster) {
 
379
    if (kind == crm_class_cluster) {
422
380
        xml = string2xml(data);
423
381
        if (xml == NULL) {
424
382
            goto bail;
425
383
        }
426
 
        crm_xml_add(xml, F_ORIG, wrapper->sender.uname);
427
 
        crm_xml_add_int(xml, F_SEQ, wrapper->id);
 
384
        crm_xml_add(xml, F_ORIG, from);
 
385
        /* crm_xml_add_int(xml, F_SEQ, wrapper->id); */
428
386
        cib_peer_callback(xml, NULL);
429
387
    }
430
388
 
440
398
static void
441
399
cib_ais_destroy(gpointer user_data)
442
400
{
443
 
    ais_fd_sync = -1;
444
401
    if (cib_shutdown_flag) {
445
402
        crm_info("Corosync disconnection complete");
446
403
    } else {
451
408
#endif
452
409
 
453
410
static void
454
 
cib_ais_status_callback(enum crm_status_type type, crm_node_t * node, const void *data)
 
411
cib_peer_update_callback(enum crm_status_type type, crm_node_t * node, const void *data)
455
412
{
456
 
    if(cib_shutdown_flag && crm_active_peers(crm_proc_cib) < 2 && g_hash_table_size(client_list) == 0) {
 
413
#if 0
 
414
    /* crm_active_peers(crm_proc_cib) appears to give the wrong answer
 
415
     * sometimes, this might help figure out why
 
416
     */
 
417
    if (type == crm_status_nstate) {
 
418
        crm_info("status: %s is now %s (was %s)", node->uname, node->state, (const char *)data);
 
419
        if (safe_str_eq(CRMD_JOINSTATE_MEMBER, node->state)) {
 
420
            return;
 
421
        }
 
422
 
 
423
    } else if (type == crm_status_processes) {
 
424
        uint32_t old = 0;
 
425
 
 
426
        if (data) {
 
427
            old = *(const uint32_t *)data;
 
428
        }
 
429
 
 
430
        if ((node->processes ^ old) & crm_proc_cib) {
 
431
            crm_info("status: cib process on %s is now %sactive",
 
432
                     node->uname, is_set(node->processes, crm_proc_cib) ? "" : "in");
 
433
        } else {
 
434
            return;
 
435
        }
 
436
 
 
437
    } else {
 
438
        return;
 
439
    }
 
440
#endif
 
441
    if (cib_shutdown_flag && crm_active_peers() < 2 && crm_hash_table_size(client_connections) == 0) {
457
442
        crm_info("No more peers");
458
443
        terminate_cib(__FUNCTION__, FALSE);
459
444
    }
460
445
}
461
446
 
 
447
#if SUPPORT_HEARTBEAT
 
448
static void
 
449
cib_ha_connection_destroy(gpointer user_data)
 
450
{
 
451
    if (cib_shutdown_flag) {
 
452
        crm_info("Heartbeat disconnection complete... exiting");
 
453
        terminate_cib(__FUNCTION__, FALSE);
 
454
    } else {
 
455
        crm_err("Heartbeat connection lost!  Exiting.");
 
456
        terminate_cib(__FUNCTION__, TRUE);
 
457
    }
 
458
}
 
459
#endif
 
460
 
462
461
int
463
462
cib_init(void)
464
463
{
465
 
    gboolean was_error = FALSE;
 
464
    if (is_openais_cluster()) {
 
465
#if SUPPORT_COROSYNC
 
466
        crm_cluster.destroy = cib_ais_destroy;
 
467
        crm_cluster.cs_dispatch = cib_ais_dispatch;
 
468
#endif
 
469
    } else if (is_heartbeat_cluster()) {
 
470
#if SUPPORT_HEARTBEAT
 
471
        crm_cluster.hb_dispatch = cib_ha_peer_callback;
 
472
        crm_cluster.destroy = cib_ha_connection_destroy;
 
473
#endif
 
474
    }
466
475
 
467
476
    config_hash =
468
477
        g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
469
478
 
470
479
    if (startCib("cib.xml") == FALSE) {
471
480
        crm_crit("Cannot start CIB... terminating");
472
 
        exit(1);
 
481
        crm_exit(1);
473
482
    }
474
483
 
475
484
    if (stand_alone == FALSE) {
476
 
        void *dispatch = cib_ha_peer_callback;
477
 
        void *destroy = cib_ha_connection_destroy;
478
 
 
479
 
        if (is_openais_cluster()) {
480
 
#if SUPPORT_COROSYNC
481
 
            destroy = cib_ais_destroy;
482
 
            dispatch = cib_ais_dispatch;
483
 
#endif
484
 
        }
485
 
 
486
 
        if (crm_cluster_connect(&cib_our_uname, NULL, dispatch, destroy,
487
 
#if SUPPORT_HEARTBEAT
488
 
                                &hb_conn
489
 
#else
490
 
                                NULL
491
 
#endif
492
 
            ) == FALSE) {
 
485
        if (crm_cluster_connect(&crm_cluster) == FALSE) {
493
486
            crm_crit("Cannot sign in to the cluster... terminating");
494
 
            exit(100);
 
487
            crm_exit(100);
495
488
        }
 
489
        cib_our_uname = crm_cluster.uname;
496
490
        if (is_openais_cluster()) {
497
 
            crm_set_status_callback(&cib_ais_status_callback);
 
491
            crm_set_status_callback(&cib_peer_update_callback);
498
492
        }
499
493
#if SUPPORT_HEARTBEAT
500
494
        if (is_heartbeat_cluster()) {
501
495
 
 
496
            gboolean was_error = FALSE;
 
497
 
 
498
            hb_conn = crm_cluster.hb_conn;
502
499
            if (was_error == FALSE) {
503
500
                if (HA_OK !=
504
501
                    hb_conn->llc_ops->set_cstatus_callback(hb_conn, cib_client_status_callback,
522
519
#endif
523
520
 
524
521
    } else {
525
 
        cib_our_uname = crm_strdup("localhost");
 
522
        cib_our_uname = strdup("localhost");
526
523
    }
527
524
 
528
 
    channel1 = crm_strdup(cib_channel_callback);
529
 
    was_error = init_server_ipc_comms(channel1, cib_client_connect, default_ipc_connection_destroy);
530
 
 
531
 
    channel2 = crm_strdup(cib_channel_ro);
532
 
    was_error = was_error || init_server_ipc_comms(channel2, cib_client_connect,
533
 
                                                   default_ipc_connection_destroy);
534
 
 
535
 
    channel3 = crm_strdup(cib_channel_rw);
536
 
    was_error = was_error || init_server_ipc_comms(channel3, cib_client_connect,
537
 
                                                   default_ipc_connection_destroy);
 
525
    cib_ipc_servers_init(&ipcs_ro,
 
526
                         &ipcs_rw,
 
527
                         &ipcs_shm,
 
528
                         &ipc_ro_callbacks,
 
529
                         &ipc_rw_callbacks);
538
530
 
539
531
    if (stand_alone) {
540
 
        if (was_error) {
541
 
            crm_err("Couldnt start");
542
 
            return 1;
543
 
        }
544
532
        cib_is_master = TRUE;
545
 
 
546
 
        /* Create the mainloop and run it... */
547
 
        mainloop = g_main_new(FALSE);
548
 
        crm_info("Starting %s mainloop", crm_system_name);
549
 
 
550
 
        g_main_run(mainloop);
551
 
        return 0;
552
 
    }
553
 
 
554
 
    if (was_error == FALSE) {
555
 
        /* Create the mainloop and run it... */
556
 
        mainloop = g_main_new(FALSE);
557
 
        crm_info("Starting %s mainloop", crm_system_name);
558
 
 
559
 
        g_timeout_add(crm_get_msec(cib_stat_interval), cib_stats, NULL);
560
 
 
561
 
        g_main_run(mainloop);
562
 
 
563
 
    } else {
564
 
        crm_err("Couldnt start all communication channels, exiting.");
565
 
    }
566
 
 
567
 
    return 0;
568
 
}
569
 
 
570
 
void
571
 
usage(const char *cmd, int exit_status)
572
 
{
573
 
    FILE *stream;
574
 
 
575
 
    stream = exit_status ? stderr : stdout;
576
 
 
577
 
    fprintf(stream, "usage: %s [-%s]\n", cmd, OPTARGS);
578
 
    fprintf(stream, "\t--%s (-%c)\t\tTurn on debug info."
579
 
            "  Additional instances increase verbosity\n", "verbose", 'V');
580
 
    fprintf(stream, "\t--%s (-%c)\t\tThis help message\n", "help", '?');
581
 
    fprintf(stream, "\t--%s (-%c)\t\tShow configurable cib options\n", "metadata", 'm');
582
 
    fprintf(stream, "\t--%s (-%c)\tAdvanced use only\n", "per-action-cib", 'a');
583
 
    fprintf(stream, "\t--%s (-%c)\tAdvanced use only\n", "stand-alone", 's');
584
 
    fprintf(stream, "\t--%s (-%c)\tAdvanced use only\n", "disk-writes", 'w');
585
 
    fprintf(stream, "\t--%s (-%c)\t\tAdvanced use only\n", "cib-root", 'r');
586
 
    fflush(stream);
587
 
 
588
 
    exit(exit_status);
589
 
}
590
 
 
591
 
void
592
 
cib_ha_connection_destroy(gpointer user_data)
593
 
{
594
 
    if (cib_shutdown_flag) {
595
 
        crm_info("Heartbeat disconnection complete... exiting");
596
 
        terminate_cib(__FUNCTION__, FALSE);
597
 
    } else {
598
 
        crm_err("Heartbeat connection lost!  Exiting.");
599
 
        terminate_cib(__FUNCTION__, TRUE);
600
 
    }
601
 
}
602
 
 
603
 
static void
604
 
disconnect_cib_client(gpointer key, gpointer value, gpointer user_data)
605
 
{
606
 
    cib_client_t *a_client = value;
607
 
 
608
 
    crm_trace("Processing client %s/%s... send=%d, recv=%d",
609
 
                crm_str(a_client->name), crm_str(a_client->channel_name),
610
 
                (int)a_client->channel->send_queue->current_qlen,
611
 
                (int)a_client->channel->recv_queue->current_qlen);
612
 
 
613
 
    if (a_client->channel->ch_status == IPC_CONNECT) {
614
 
        a_client->channel->ops->resume_io(a_client->channel);
615
 
        if (a_client->channel->send_queue->current_qlen != 0
616
 
            || a_client->channel->recv_queue->current_qlen != 0) {
617
 
            crm_info("Flushed messages to/from %s/%s... send=%d, recv=%d",
618
 
                     crm_str(a_client->name),
619
 
                     crm_str(a_client->channel_name),
620
 
                     (int)a_client->channel->send_queue->current_qlen,
621
 
                     (int)a_client->channel->recv_queue->current_qlen);
622
 
        }
623
 
    }
624
 
 
625
 
    if (a_client->channel->ch_status == IPC_CONNECT) {
626
 
        crm_warn("Disconnecting %s/%s...",
627
 
                 crm_str(a_client->name), crm_str(a_client->channel_name));
628
 
        a_client->channel->ops->disconnect(a_client->channel);
629
 
    }
630
 
}
631
 
 
632
 
extern gboolean cib_process_disconnect(IPC_Channel * channel, cib_client_t * cib_client);
633
 
 
634
 
void
635
 
cib_shutdown(int nsig)
636
 
{
637
 
    if (cib_shutdown_flag == FALSE) {
638
 
        cib_shutdown_flag = TRUE;
639
 
        crm_debug("Disconnecting %d clients", g_hash_table_size(client_list));
640
 
        g_hash_table_foreach(client_list, disconnect_cib_client, NULL);
641
 
        crm_info("Disconnected %d clients", g_hash_table_size(client_list));
642
 
        cib_process_disconnect(NULL, NULL);
643
 
 
644
 
    } else {
645
 
        crm_info("Waiting for %d clients to disconnect...", g_hash_table_size(client_list));
646
 
    }
 
533
    }
 
534
 
 
535
    /* Create the mainloop and run it... */
 
536
    mainloop = g_main_new(FALSE);
 
537
    crm_info("Starting %s mainloop", crm_system_name);
 
538
 
 
539
    g_main_run(mainloop);
 
540
    cib_ipc_servers_destroy(ipcs_ro, ipcs_rw, ipcs_shm);
 
541
 
 
542
    return crm_exit(0);
647
543
}
648
544
 
649
545
gboolean