2
2
* Copyright (c) 2004-2006 MontaVista Software, Inc.
3
* Copyright (c) 2006-2008 Red Hat, Inc.
3
* Copyright (c) 2006-2009 Red Hat, Inc.
5
5
* All rights reserved.
7
7
* Author: Steven Dake (sdake@redhat.com)
9
9
* This software licensed under BSD license, the text of which follows:
11
11
* Redistribution and use in source and binary forms, with or without
12
12
* modification, are permitted provided that the following conditions are met:
43
46
#include <stdlib.h>
48
50
#include <netinet/in.h>
49
51
#include <arpa/inet.h>
51
53
#include <corosync/swab.h>
52
#include <corosync/saAis.h>
53
#include <corosync/ipc_gen.h>
54
#include <corosync/corotypes.h>
55
#include <corosync/coroipc_types.h>
56
#include <corosync/corodefs.h>
57
#include <corosync/mar_gen.h>
54
58
#include <corosync/lcr/lcr_comp.h>
55
59
#include <corosync/engine/coroapi.h>
60
#include <corosync/engine/logsys.h>
61
#include <corosync/list.h>
63
#include <corosync/evs.h>
56
64
#include <corosync/ipc_evs.h>
57
#include <corosync/list.h>
58
#include <corosync/engine/logsys.h>
60
LOGSYS_DECLARE_SUBSYS ("EVS", LOG_INFO);
66
LOGSYS_DECLARE_SUBSYS ("EVS");
62
68
enum evs_exec_message_req_types {
63
69
MESSAGE_REQ_EXEC_EVS_MCAST = 0
72
78
static void evs_confchg_fn (
73
79
enum totem_configuration_type configuration_type,
74
unsigned int *member_list, int member_list_entries,
75
unsigned int *left_list, int left_list_entries,
76
unsigned int *joined_list, int joined_list_entries,
77
struct memb_ring_id *ring_id);
80
const unsigned int *member_list, size_t member_list_entries,
81
const unsigned int *left_list, size_t left_list_entries,
82
const unsigned int *joined_list, size_t joined_list_entries,
83
const struct memb_ring_id *ring_id);
79
static void message_handler_req_exec_mcast (void *msg, unsigned int nodeid);
85
static void message_handler_req_exec_mcast (const void *msg, unsigned int nodeid);
81
87
static void req_exec_mcast_endian_convert (void *msg);
83
static void message_handler_req_evs_join (void *conn, void *msg);
84
static void message_handler_req_evs_leave (void *conn, void *msg);
85
static void message_handler_req_evs_mcast_joined (void *conn, void *msg);
86
static void message_handler_req_evs_mcast_groups (void *conn, void *msg);
87
static void message_handler_req_evs_membership_get (void *conn, void *msg);
89
static void message_handler_req_evs_join (void *conn, const void *msg);
90
static void message_handler_req_evs_leave (void *conn, const void *msg);
91
static void message_handler_req_evs_mcast_joined (void *conn, const void *msg);
92
static void message_handler_req_evs_mcast_groups (void *conn, const void *msg);
93
static void message_handler_req_evs_membership_get (void *conn, const void *msg);
89
95
static int evs_lib_init_fn (void *conn);
90
96
static int evs_lib_exit_fn (void *conn);
95
101
struct list_head list;
99
105
static struct corosync_api_v1 *api;
101
107
static struct corosync_lib_handler evs_lib_engine[] =
104
110
.lib_handler_fn = message_handler_req_evs_join,
105
.response_size = sizeof (struct res_lib_evs_join),
106
.response_id = MESSAGE_RES_EVS_JOIN,
107
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
111
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
110
114
.lib_handler_fn = message_handler_req_evs_leave,
111
.response_size = sizeof (struct res_lib_evs_leave),
112
.response_id = MESSAGE_RES_EVS_LEAVE,
113
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
115
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
116
118
.lib_handler_fn = message_handler_req_evs_mcast_joined,
117
.response_size = sizeof (struct res_lib_evs_mcast_joined),
118
.response_id = MESSAGE_RES_EVS_MCAST_JOINED,
119
.flow_control = COROSYNC_LIB_FLOW_CONTROL_REQUIRED
119
.flow_control = CS_LIB_FLOW_CONTROL_REQUIRED
122
122
.lib_handler_fn = message_handler_req_evs_mcast_groups,
123
.response_size = sizeof (struct res_lib_evs_mcast_groups),
124
.response_id = MESSAGE_RES_EVS_MCAST_GROUPS,
125
.flow_control = COROSYNC_LIB_FLOW_CONTROL_REQUIRED
123
.flow_control = CS_LIB_FLOW_CONTROL_REQUIRED
128
126
.lib_handler_fn = message_handler_req_evs_membership_get,
129
.response_size = sizeof (struct res_lib_evs_membership_get),
130
.response_id = MESSAGE_RES_EVS_MEMBERSHIP_GET,
131
.flow_control = COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
127
.flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
143
139
struct corosync_service_engine evs_service_engine = {
144
140
.name = "corosync extended virtual synchrony service",
145
141
.id = EVS_SERVICE,
146
143
.private_data_size = sizeof (struct evs_pd),
147
.flow_control = COROSYNC_LIB_FLOW_CONTROL_REQUIRED,
144
.flow_control = CS_LIB_FLOW_CONTROL_REQUIRED,
148
145
.lib_init_fn = evs_lib_init_fn,
149
146
.lib_exit_fn = evs_lib_exit_fn,
150
147
.lib_engine = evs_lib_engine,
153
150
.exec_engine_count = sizeof (evs_exec_engine) / sizeof (struct corosync_exec_handler),
154
151
.confchg_fn = evs_confchg_fn,
155
152
.exec_init_fn = evs_exec_init_fn,
153
.exec_dump_fn = NULL,
154
.sync_mode = CS_SYNC_V1
159
157
static DECLARE_LIST_INIT (confchg_notify);
192
190
return (&evs_service_engine);
195
__attribute__ ((constructor)) static void evs_comp_register (void) {
193
#ifdef COROSYNC_SOLARIS
194
void corosync_lcr_component_register (void);
196
void corosync_lcr_component_register (void) {
198
__attribute__ ((constructor)) static void corosync_lcr_component_register (void) {
196
200
lcr_interfaces_set (&corosync_evs_ver0[0], &evs_service_engine_iface);
198
202
lcr_component_register (&evs_comp_ver0);
211
219
static void evs_confchg_fn (
212
220
enum totem_configuration_type configuration_type,
213
unsigned int *member_list, int member_list_entries,
214
unsigned int *left_list, int left_list_entries,
215
unsigned int *joined_list, int joined_list_entries,
216
struct memb_ring_id *ring_id)
221
const unsigned int *member_list, size_t member_list_entries,
222
const unsigned int *left_list, size_t left_list_entries,
223
const unsigned int *joined_list, size_t joined_list_entries,
224
const struct memb_ring_id *ring_id)
218
226
struct list_head *list;
219
227
struct evs_pd *evs_pd;
224
232
res_evs_confchg_callback.header.size = sizeof (struct res_evs_confchg_callback);
225
233
res_evs_confchg_callback.header.id = MESSAGE_RES_EVS_CONFCHG_CALLBACK;
226
res_evs_confchg_callback.header.error = SA_AIS_OK;
234
res_evs_confchg_callback.header.error = CS_OK;
228
236
memcpy (res_evs_confchg_callback.member_list,
229
237
member_list, member_list_entries * sizeof(*member_list));
243
251
for (list = confchg_notify.next; list != &confchg_notify; list = list->next) {
244
252
evs_pd = list_entry (list, struct evs_pd, list);
245
api->ipc_conn_send_response (evs_pd->conn,
253
api->ipc_response_send (evs_pd->conn,
246
254
&res_evs_confchg_callback,
247
255
sizeof (res_evs_confchg_callback));
253
261
struct evs_pd *evs_pd = (struct evs_pd *)api->ipc_private_data_get (conn);
255
log_printf (LOG_LEVEL_DEBUG, "Got request to initalize evs service.\n");
263
log_printf (LOGSYS_LEVEL_DEBUG, "Got request to initalize evs service.\n");
257
265
evs_pd->groups = NULL;
258
266
evs_pd->group_entries = 0;
260
268
list_init (&evs_pd->list);
261
269
list_add (&evs_pd->list, &confchg_notify);
263
api->ipc_conn_send_response (conn, &res_evs_confchg_callback,
271
api->ipc_dispatch_send (conn, &res_evs_confchg_callback,
264
272
sizeof (res_evs_confchg_callback));
277
static void message_handler_req_evs_join (void *conn, void *msg)
285
static void message_handler_req_evs_join (void *conn, const void *msg)
279
evs_error_t error = EVS_OK;
280
struct req_lib_evs_join *req_lib_evs_join = (struct req_lib_evs_join *)msg;
287
cs_error_t error = CS_OK;
288
const struct req_lib_evs_join *req_lib_evs_join = msg;
281
289
struct res_lib_evs_join res_lib_evs_join;
283
291
struct evs_pd *evs_pd = (struct evs_pd *)api->ipc_private_data_get (conn);
285
293
if (req_lib_evs_join->group_entries > 50) {
286
error = EVS_ERR_TOO_MANY_GROUPS;
294
error = CS_ERR_TOO_MANY_GROUPS;
290
addr = realloc (evs_pd->groups, sizeof (struct evs_group) *
298
addr = realloc (evs_pd->groups, sizeof (struct evs_group) *
291
299
(evs_pd->group_entries + req_lib_evs_join->group_entries));
292
300
if (addr == NULL) {
293
error = SA_AIS_ERR_NO_MEMORY;
301
error = CS_ERR_NO_MEMORY;
296
304
evs_pd->groups = addr;
306
314
res_lib_evs_join.header.id = MESSAGE_RES_EVS_JOIN;
307
315
res_lib_evs_join.header.error = error;
309
api->ipc_conn_send_response (conn, &res_lib_evs_join,
317
api->ipc_response_send (conn, &res_lib_evs_join,
310
318
sizeof (struct res_lib_evs_join));
313
static void message_handler_req_evs_leave (void *conn, void *msg)
321
static void message_handler_req_evs_leave (void *conn, const void *msg)
315
struct req_lib_evs_leave *req_lib_evs_leave = (struct req_lib_evs_leave *)msg;
323
const struct req_lib_evs_leave *req_lib_evs_leave = msg;
316
324
struct res_lib_evs_leave res_lib_evs_leave;
317
evs_error_t error = EVS_OK;
325
cs_error_t error = CS_OK;
352
360
res_lib_evs_leave.header.id = MESSAGE_RES_EVS_LEAVE;
353
361
res_lib_evs_leave.header.error = error;
355
api->ipc_conn_send_response (conn, &res_lib_evs_leave,
363
api->ipc_response_send (conn, &res_lib_evs_leave,
356
364
sizeof (struct res_lib_evs_leave));
359
static void message_handler_req_evs_mcast_joined (void *conn, void *msg)
367
static void message_handler_req_evs_mcast_joined (void *conn, const void *msg)
361
evs_error_t error = EVS_ERR_TRY_AGAIN;
362
struct req_lib_evs_mcast_joined *req_lib_evs_mcast_joined = (struct req_lib_evs_mcast_joined *)msg;
369
cs_error_t error = CS_ERR_TRY_AGAIN;
370
const struct req_lib_evs_mcast_joined *req_lib_evs_mcast_joined = msg;
363
371
struct res_lib_evs_mcast_joined res_lib_evs_mcast_joined;
364
372
struct iovec req_exec_evs_mcast_iovec[3];
365
373
struct req_exec_evs_mcast req_exec_evs_mcast;
368
375
struct evs_pd *evs_pd = (struct evs_pd *)api->ipc_private_data_get (conn);
382
389
req_exec_evs_mcast_iovec[1].iov_len = evs_pd->group_entries * sizeof (struct evs_group);
383
390
req_exec_evs_mcast_iovec[2].iov_base = (char *)&req_lib_evs_mcast_joined->msg;
384
391
req_exec_evs_mcast_iovec[2].iov_len = req_lib_evs_mcast_joined->msg_len;
385
// TODO this doesn't seem to work for some reason
386
send_ok = api->totem_send_ok (req_exec_evs_mcast_iovec, 3);
388
393
res = api->totem_mcast (req_exec_evs_mcast_iovec, 3, TOTEM_AGREED);
394
399
res_lib_evs_mcast_joined.header.size = sizeof (struct res_lib_evs_mcast_joined);
395
400
res_lib_evs_mcast_joined.header.id = MESSAGE_RES_EVS_MCAST_JOINED;
396
401
res_lib_evs_mcast_joined.header.error = error;
398
api->ipc_conn_send_response (conn, &res_lib_evs_mcast_joined,
403
api->ipc_response_send (conn, &res_lib_evs_mcast_joined,
399
404
sizeof (struct res_lib_evs_mcast_joined));
402
static void message_handler_req_evs_mcast_groups (void *conn, void *msg)
407
static void message_handler_req_evs_mcast_groups (void *conn, const void *msg)
404
evs_error_t error = EVS_ERR_TRY_AGAIN;
405
struct req_lib_evs_mcast_groups *req_lib_evs_mcast_groups = (struct req_lib_evs_mcast_groups *)msg;
409
cs_error_t error = CS_ERR_TRY_AGAIN;
410
const struct req_lib_evs_mcast_groups *req_lib_evs_mcast_groups = msg;
406
411
struct res_lib_evs_mcast_groups res_lib_evs_mcast_groups;
407
412
struct iovec req_exec_evs_mcast_iovec[3];
408
413
struct req_exec_evs_mcast req_exec_evs_mcast;
414
const char *msg_addr;
413
417
req_exec_evs_mcast.header.size = sizeof (struct req_exec_evs_mcast) +
419
423
req_exec_evs_mcast.msg_len = req_lib_evs_mcast_groups->msg_len;
420
424
req_exec_evs_mcast.group_entries = req_lib_evs_mcast_groups->group_entries;
422
msg_addr = (char *)req_lib_evs_mcast_groups +
423
sizeof (struct req_lib_evs_mcast_groups) +
426
msg_addr = (const char *)req_lib_evs_mcast_groups +
427
sizeof (struct req_lib_evs_mcast_groups) +
424
428
(sizeof (struct evs_group) * req_lib_evs_mcast_groups->group_entries);
426
430
req_exec_evs_mcast_iovec[0].iov_base = (char *)&req_exec_evs_mcast;
427
431
req_exec_evs_mcast_iovec[0].iov_len = sizeof (req_exec_evs_mcast);
428
432
req_exec_evs_mcast_iovec[1].iov_base = (char *)&req_lib_evs_mcast_groups->groups;
429
433
req_exec_evs_mcast_iovec[1].iov_len = sizeof (struct evs_group) * req_lib_evs_mcast_groups->group_entries;
430
req_exec_evs_mcast_iovec[2].iov_base = msg_addr;
434
req_exec_evs_mcast_iovec[2].iov_base = (void *) msg_addr; /* discard const */
431
435
req_exec_evs_mcast_iovec[2].iov_len = req_lib_evs_mcast_groups->msg_len;
433
// TODO this is wacky
434
send_ok = api->totem_send_ok (req_exec_evs_mcast_iovec, 3);
435
437
res = api->totem_mcast (req_exec_evs_mcast_iovec, 3, TOTEM_AGREED);
440
442
res_lib_evs_mcast_groups.header.size = sizeof (struct res_lib_evs_mcast_groups);
441
443
res_lib_evs_mcast_groups.header.id = MESSAGE_RES_EVS_MCAST_GROUPS;
442
444
res_lib_evs_mcast_groups.header.error = error;
444
api->ipc_conn_send_response (conn, &res_lib_evs_mcast_groups,
446
api->ipc_response_send (conn, &res_lib_evs_mcast_groups,
445
447
sizeof (struct res_lib_evs_mcast_groups));
448
static void message_handler_req_evs_membership_get (void *conn, void *msg)
450
static void message_handler_req_evs_membership_get (void *conn, const void *msg)
450
452
struct res_lib_evs_membership_get res_lib_evs_membership_get;
452
454
res_lib_evs_membership_get.header.size = sizeof (struct res_lib_evs_membership_get);
453
455
res_lib_evs_membership_get.header.id = MESSAGE_RES_EVS_MEMBERSHIP_GET;
454
res_lib_evs_membership_get.header.error = EVS_OK;
456
res_lib_evs_membership_get.header.error = CS_OK;
455
457
res_lib_evs_membership_get.local_nodeid = api->totem_nodeid_get ();
456
458
memcpy (&res_lib_evs_membership_get.member_list,
457
459
&res_evs_confchg_callback.member_list,
460
462
res_lib_evs_membership_get.member_list_entries =
461
463
res_evs_confchg_callback.member_list_entries;
463
api->ipc_conn_send_response (conn, &res_lib_evs_membership_get,
465
api->ipc_response_send (conn, &res_lib_evs_membership_get,
464
466
sizeof (struct res_lib_evs_membership_get));
476
478
static void message_handler_req_exec_mcast (
478
480
unsigned int nodeid)
480
struct req_exec_evs_mcast *req_exec_evs_mcast = (struct req_exec_evs_mcast *)msg;
482
const struct req_exec_evs_mcast *req_exec_evs_mcast = msg;
481
483
struct res_evs_deliver_callback res_evs_deliver_callback;
484
const char *msg_addr;
483
485
struct list_head *list;
486
488
struct evs_pd *evs_pd;
488
491
res_evs_deliver_callback.header.size = sizeof (struct res_evs_deliver_callback) +
489
492
req_exec_evs_mcast->msg_len;
490
493
res_evs_deliver_callback.header.id = MESSAGE_RES_EVS_DELIVER_CALLBACK;
491
res_evs_deliver_callback.header.error = SA_AIS_OK;
494
res_evs_deliver_callback.header.error = CS_OK;
492
495
res_evs_deliver_callback.msglen = req_exec_evs_mcast->msg_len;
494
msg_addr = (char *)req_exec_evs_mcast + sizeof (struct req_exec_evs_mcast) +
497
msg_addr = (const char *)req_exec_evs_mcast + sizeof (struct req_exec_evs_mcast) +
495
498
(sizeof (struct evs_group) * req_exec_evs_mcast->group_entries);
497
500
for (list = confchg_notify.next; list != &confchg_notify; list = list->next) {
517
520
res_evs_deliver_callback.local_nodeid = nodeid;
518
api->ipc_conn_send_response (evs_pd->conn, &res_evs_deliver_callback,
519
sizeof (struct res_evs_deliver_callback));
520
api->ipc_conn_send_response (evs_pd->conn, msg_addr,
521
req_exec_evs_mcast->msg_len);
521
iov[0].iov_base = (void *)&res_evs_deliver_callback;
522
iov[0].iov_len = sizeof (struct res_evs_deliver_callback);
523
iov[1].iov_base = (void *) msg_addr; /* discard const */
524
iov[1].iov_len = req_exec_evs_mcast->msg_len;
526
api->ipc_dispatch_iov_send (