2 * Copyright (c) 2004-2006 MontaVista Software, Inc.
3 * Copyright (c) 2006-2007 Red Hat, Inc.
4 * Copyright (c) 2006 Sun Microsystems, Inc.
8 * Author: Steven Dake (sdake@redhat.com)
10 * This software licensed under BSD license, the text of which follows:
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
15 * - Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 * - Neither the name of the MontaVista Software, Inc. nor the names of its
21 * contributors may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/types.h>
37 #include <sys/socket.h>
39 #include <sys/ioctl.h>
40 #include <netinet/in.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
54 #include "../include/saAis.h"
55 #include "../include/ipc_gen.h"
56 #include "../include/ipc_evs.h"
57 #include "../include/list.h"
58 #include "../include/queue.h"
59 #include "../lcr/lcr_comp.h"
70 LOGSYS_DECLARE_SUBSYS ("EVS", LOG_INFO
);
72 enum evs_exec_message_req_types
{
73 MESSAGE_REQ_EXEC_EVS_MCAST
= 0
77 * Service Interfaces required by service_message_handler struct
79 static int evs_exec_init_fn(struct objdb_iface_ver0
*objdb
);
80 static void evs_confchg_fn (
81 enum totem_configuration_type configuration_type
,
82 unsigned int *member_list
, int member_list_entries
,
83 unsigned int *left_list
, int left_list_entries
,
84 unsigned int *joined_list
, int joined_list_entries
,
85 struct memb_ring_id
*ring_id
);
87 static void message_handler_req_exec_mcast (void *msg
, unsigned int nodeid
);
89 static void req_exec_mcast_endian_convert (void *msg
);
91 static void message_handler_req_evs_join (void *conn
, void *msg
);
92 static void message_handler_req_evs_leave (void *conn
, void *msg
);
93 static void message_handler_req_evs_mcast_joined (void *conn
, void *msg
);
94 static void message_handler_req_evs_mcast_groups (void *conn
, void *msg
);
95 static void message_handler_req_evs_membership_get (void *conn
, void *msg
);
97 static int evs_lib_init_fn (void *conn
);
98 static int evs_lib_exit_fn (void *conn
);
101 struct evs_group
*groups
;
103 struct list_head list
;
107 static struct openais_lib_handler evs_lib_service
[] =
110 .lib_handler_fn
= message_handler_req_evs_join
,
111 .response_size
= sizeof (struct res_lib_evs_join
),
112 .response_id
= MESSAGE_RES_EVS_JOIN
,
113 .flow_control
= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
116 .lib_handler_fn
= message_handler_req_evs_leave
,
117 .response_size
= sizeof (struct res_lib_evs_leave
),
118 .response_id
= MESSAGE_RES_EVS_LEAVE
,
119 .flow_control
= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
122 .lib_handler_fn
= message_handler_req_evs_mcast_joined
,
123 .response_size
= sizeof (struct res_lib_evs_mcast_joined
),
124 .response_id
= MESSAGE_RES_EVS_MCAST_JOINED
,
125 .flow_control
= OPENAIS_FLOW_CONTROL_REQUIRED
128 .lib_handler_fn
= message_handler_req_evs_mcast_groups
,
129 .response_size
= sizeof (struct res_lib_evs_mcast_groups
),
130 .response_id
= MESSAGE_RES_EVS_MCAST_GROUPS
,
131 .flow_control
= OPENAIS_FLOW_CONTROL_REQUIRED
134 .lib_handler_fn
= message_handler_req_evs_membership_get
,
135 .response_size
= sizeof (struct res_lib_evs_membership_get
),
136 .response_id
= MESSAGE_RES_EVS_MEMBERSHIP_GET
,
137 .flow_control
= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
141 static struct openais_exec_handler evs_exec_service
[] =
144 .exec_handler_fn
= message_handler_req_exec_mcast
,
145 .exec_endian_convert_fn
= req_exec_mcast_endian_convert
149 struct openais_service_handler evs_service_handler
= {
150 .name
= "openais extended virtual synchrony service",
152 .private_data_size
= sizeof (struct evs_pd
),
153 .flow_control
= OPENAIS_FLOW_CONTROL_REQUIRED
,
154 .lib_init_fn
= evs_lib_init_fn
,
155 .lib_exit_fn
= evs_lib_exit_fn
,
156 .lib_service
= evs_lib_service
,
157 .lib_service_count
= sizeof (evs_lib_service
) / sizeof (struct openais_lib_handler
),
158 .exec_service
= evs_exec_service
,
159 .exec_service_count
= sizeof (evs_exec_service
) / sizeof (struct openais_exec_handler
),
160 .confchg_fn
= evs_confchg_fn
,
161 .exec_init_fn
= evs_exec_init_fn
,
165 static DECLARE_LIST_INIT (confchg_notify
);
168 * Dynamic loading descriptor
171 static struct openais_service_handler
*evs_get_service_handler_ver0 (void);
173 static struct openais_service_handler_iface_ver0 evs_service_handler_iface
= {
174 .openais_get_service_handler_ver0
= evs_get_service_handler_ver0
177 static struct lcr_iface openais_evs_ver0
[1] = {
179 .name
= "openais_evs",
181 .versions_replace
= 0,
182 .versions_replace_count
= 0,
184 .dependency_count
= 0,
191 static struct lcr_comp evs_comp_ver0
= {
193 .ifaces
= openais_evs_ver0
196 static struct openais_service_handler
*evs_get_service_handler_ver0 (void)
198 return (&evs_service_handler
);
201 __attribute__ ((constructor
)) static void evs_comp_register (void) {
202 lcr_interfaces_set (&openais_evs_ver0
[0], &evs_service_handler_iface
);
204 lcr_component_register (&evs_comp_ver0
);
207 static int evs_exec_init_fn(struct objdb_iface_ver0
*objdb
)
214 struct res_evs_confchg_callback res_evs_confchg_callback
;
216 static void evs_confchg_fn (
217 enum totem_configuration_type configuration_type
,
218 unsigned int *member_list
, int member_list_entries
,
219 unsigned int *left_list
, int left_list_entries
,
220 unsigned int *joined_list
, int joined_list_entries
,
221 struct memb_ring_id
*ring_id
)
223 struct list_head
*list
;
224 struct evs_pd
*evs_pd
;
227 * Build configuration change message
229 res_evs_confchg_callback
.header
.size
= sizeof (struct res_evs_confchg_callback
);
230 res_evs_confchg_callback
.header
.id
= MESSAGE_RES_EVS_CONFCHG_CALLBACK
;
231 res_evs_confchg_callback
.header
.error
= SA_AIS_OK
;
233 memcpy (res_evs_confchg_callback
.member_list
,
234 member_list
, member_list_entries
* sizeof(*member_list
));
235 res_evs_confchg_callback
.member_list_entries
= member_list_entries
;
237 memcpy (res_evs_confchg_callback
.left_list
,
238 left_list
, left_list_entries
* sizeof(*left_list
));
239 res_evs_confchg_callback
.left_list_entries
= left_list_entries
;
241 memcpy (res_evs_confchg_callback
.joined_list
,
242 joined_list
, joined_list_entries
* sizeof(*joined_list
));
243 res_evs_confchg_callback
.joined_list_entries
= joined_list_entries
;
246 * Send configuration change message to every EVS library user
248 for (list
= confchg_notify
.next
; list
!= &confchg_notify
; list
= list
->next
) {
249 evs_pd
= list_entry (list
, struct evs_pd
, list
);
250 openais_conn_send_response (evs_pd
->conn
,
251 &res_evs_confchg_callback
,
252 sizeof (res_evs_confchg_callback
));
256 static int evs_lib_init_fn (void *conn
)
258 struct evs_pd
*evs_pd
= (struct evs_pd
*)openais_conn_private_data_get (conn
);
260 log_printf (LOG_LEVEL_DEBUG
, "Got request to initalize evs service.\n");
262 evs_pd
->groups
= NULL
;
263 evs_pd
->group_entries
= 0;
265 list_init (&evs_pd
->list
);
266 list_add (&evs_pd
->list
, &confchg_notify
);
268 openais_conn_send_response (conn
, &res_evs_confchg_callback
,
269 sizeof (res_evs_confchg_callback
));
274 static int evs_lib_exit_fn (void *conn
)
276 struct evs_pd
*evs_pd
= (struct evs_pd
*)openais_conn_private_data_get (conn
);
278 list_del (&evs_pd
->list
);
282 static void message_handler_req_evs_join (void *conn
, void *msg
)
284 evs_error_t error
= EVS_OK
;
285 struct req_lib_evs_join
*req_lib_evs_join
= (struct req_lib_evs_join
*)msg
;
286 struct res_lib_evs_join res_lib_evs_join
;
288 struct evs_pd
*evs_pd
= (struct evs_pd
*)openais_conn_private_data_get (conn
);
290 if (req_lib_evs_join
->group_entries
> 50) {
291 error
= EVS_ERR_TOO_MANY_GROUPS
;
295 addr
= realloc (evs_pd
->groups
, sizeof (struct evs_group
) *
296 (evs_pd
->group_entries
+ req_lib_evs_join
->group_entries
));
298 error
= SA_AIS_ERR_NO_MEMORY
;
301 evs_pd
->groups
= addr
;
303 memcpy (&evs_pd
->groups
[evs_pd
->group_entries
],
304 req_lib_evs_join
->groups
,
305 sizeof (struct evs_group
) * req_lib_evs_join
->group_entries
);
307 evs_pd
->group_entries
+= req_lib_evs_join
->group_entries
;
310 res_lib_evs_join
.header
.size
= sizeof (struct res_lib_evs_join
);
311 res_lib_evs_join
.header
.id
= MESSAGE_RES_EVS_JOIN
;
312 res_lib_evs_join
.header
.error
= error
;
314 openais_conn_send_response (conn
, &res_lib_evs_join
,
315 sizeof (struct res_lib_evs_join
));
318 static void message_handler_req_evs_leave (void *conn
, void *msg
)
320 struct req_lib_evs_leave
*req_lib_evs_leave
= (struct req_lib_evs_leave
*)msg
;
321 struct res_lib_evs_leave res_lib_evs_leave
;
322 evs_error_t error
= EVS_OK
;
326 struct evs_pd
*evs_pd
= (struct evs_pd
*)openais_conn_private_data_get (conn
);
328 for (i
= 0; i
< req_lib_evs_leave
->group_entries
; i
++) {
330 for (j
= 0; j
< evs_pd
->group_entries
;) {
332 if (memcmp (&req_lib_evs_leave
->groups
[i
],
333 &evs_pd
->groups
[j
], sizeof (struct evs_group
)) == 0) {
338 memmove (&evs_pd
->groups
[j
], &evs_pd
->groups
[j
+ 1],
339 (evs_pd
->group_entries
- j
- 1) * sizeof (struct evs_group
));
341 evs_pd
->group_entries
-= 1;
350 error
= EVS_ERR_NOT_EXIST
;
356 res_lib_evs_leave
.header
.size
= sizeof (struct res_lib_evs_leave
);
357 res_lib_evs_leave
.header
.id
= MESSAGE_RES_EVS_LEAVE
;
358 res_lib_evs_leave
.header
.error
= error
;
360 openais_conn_send_response (conn
, &res_lib_evs_leave
,
361 sizeof (struct res_lib_evs_leave
));
364 static void message_handler_req_evs_mcast_joined (void *conn
, void *msg
)
366 evs_error_t error
= EVS_ERR_TRY_AGAIN
;
367 struct req_lib_evs_mcast_joined
*req_lib_evs_mcast_joined
= (struct req_lib_evs_mcast_joined
*)msg
;
368 struct res_lib_evs_mcast_joined res_lib_evs_mcast_joined
;
369 struct iovec req_exec_evs_mcast_iovec
[3];
370 struct req_exec_evs_mcast req_exec_evs_mcast
;
373 struct evs_pd
*evs_pd
= (struct evs_pd
*)openais_conn_private_data_get (conn
);
375 req_exec_evs_mcast
.header
.size
= sizeof (struct req_exec_evs_mcast
) +
376 evs_pd
->group_entries
* sizeof (struct evs_group
) +
377 req_lib_evs_mcast_joined
->msg_len
;
379 req_exec_evs_mcast
.header
.id
=
380 SERVICE_ID_MAKE (EVS_SERVICE
, MESSAGE_REQ_EXEC_EVS_MCAST
);
381 req_exec_evs_mcast
.msg_len
= req_lib_evs_mcast_joined
->msg_len
;
382 req_exec_evs_mcast
.group_entries
= evs_pd
->group_entries
;
384 req_exec_evs_mcast_iovec
[0].iov_base
= (char *)&req_exec_evs_mcast
;
385 req_exec_evs_mcast_iovec
[0].iov_len
= sizeof (req_exec_evs_mcast
);
386 req_exec_evs_mcast_iovec
[1].iov_base
= (char *)evs_pd
->groups
;
387 req_exec_evs_mcast_iovec
[1].iov_len
= evs_pd
->group_entries
* sizeof (struct evs_group
);
388 req_exec_evs_mcast_iovec
[2].iov_base
= (char *)&req_lib_evs_mcast_joined
->msg
;
389 req_exec_evs_mcast_iovec
[2].iov_len
= req_lib_evs_mcast_joined
->msg_len
;
390 // TODO this doesn't seem to work for some reason
391 send_ok
= totempg_groups_send_ok_joined (openais_group_handle
, req_exec_evs_mcast_iovec
, 3);
393 res
= totempg_groups_mcast_joined (openais_group_handle
, req_exec_evs_mcast_iovec
, 3, TOTEMPG_AGREED
);
399 res_lib_evs_mcast_joined
.header
.size
= sizeof (struct res_lib_evs_mcast_joined
);
400 res_lib_evs_mcast_joined
.header
.id
= MESSAGE_RES_EVS_MCAST_JOINED
;
401 res_lib_evs_mcast_joined
.header
.error
= error
;
403 openais_conn_send_response (conn
, &res_lib_evs_mcast_joined
,
404 sizeof (struct res_lib_evs_mcast_joined
));
407 static void message_handler_req_evs_mcast_groups (void *conn
, void *msg
)
409 evs_error_t error
= EVS_ERR_TRY_AGAIN
;
410 struct req_lib_evs_mcast_groups
*req_lib_evs_mcast_groups
= (struct req_lib_evs_mcast_groups
*)msg
;
411 struct res_lib_evs_mcast_groups res_lib_evs_mcast_groups
;
412 struct iovec req_exec_evs_mcast_iovec
[3];
413 struct req_exec_evs_mcast req_exec_evs_mcast
;
418 req_exec_evs_mcast
.header
.size
= sizeof (struct req_exec_evs_mcast
) +
419 sizeof (struct evs_group
) * req_lib_evs_mcast_groups
->group_entries
+
420 req_lib_evs_mcast_groups
->msg_len
;
422 req_exec_evs_mcast
.header
.id
=
423 SERVICE_ID_MAKE (EVS_SERVICE
, MESSAGE_REQ_EXEC_EVS_MCAST
);
424 req_exec_evs_mcast
.msg_len
= req_lib_evs_mcast_groups
->msg_len
;
425 req_exec_evs_mcast
.group_entries
= req_lib_evs_mcast_groups
->group_entries
;
427 msg_addr
= (char *)req_lib_evs_mcast_groups
+
428 sizeof (struct req_lib_evs_mcast_groups
) +
429 (sizeof (struct evs_group
) * req_lib_evs_mcast_groups
->group_entries
);
431 req_exec_evs_mcast_iovec
[0].iov_base
= (char *)&req_exec_evs_mcast
;
432 req_exec_evs_mcast_iovec
[0].iov_len
= sizeof (req_exec_evs_mcast
);
433 req_exec_evs_mcast_iovec
[1].iov_base
= (char *)&req_lib_evs_mcast_groups
->groups
;
434 req_exec_evs_mcast_iovec
[1].iov_len
= sizeof (struct evs_group
) * req_lib_evs_mcast_groups
->group_entries
;
435 req_exec_evs_mcast_iovec
[2].iov_base
= msg_addr
;
436 req_exec_evs_mcast_iovec
[2].iov_len
= req_lib_evs_mcast_groups
->msg_len
;
438 // TODO this is wacky
439 send_ok
= totempg_groups_send_ok_joined (openais_group_handle
, req_exec_evs_mcast_iovec
, 3);
440 res
= totempg_groups_mcast_joined (openais_group_handle
, req_exec_evs_mcast_iovec
, 3, TOTEMPG_AGREED
);
445 res_lib_evs_mcast_groups
.header
.size
= sizeof (struct res_lib_evs_mcast_groups
);
446 res_lib_evs_mcast_groups
.header
.id
= MESSAGE_RES_EVS_MCAST_GROUPS
;
447 res_lib_evs_mcast_groups
.header
.error
= error
;
449 openais_conn_send_response (conn
, &res_lib_evs_mcast_groups
,
450 sizeof (struct res_lib_evs_mcast_groups
));
453 static void message_handler_req_evs_membership_get (void *conn
, void *msg
)
455 struct res_lib_evs_membership_get res_lib_evs_membership_get
;
457 res_lib_evs_membership_get
.header
.size
= sizeof (struct res_lib_evs_membership_get
);
458 res_lib_evs_membership_get
.header
.id
= MESSAGE_RES_EVS_MEMBERSHIP_GET
;
459 res_lib_evs_membership_get
.header
.error
= EVS_OK
;
460 res_lib_evs_membership_get
.local_nodeid
= totempg_my_nodeid_get ();
461 memcpy (&res_lib_evs_membership_get
.member_list
,
462 &res_evs_confchg_callback
.member_list
,
463 sizeof (res_lib_evs_membership_get
.member_list
));
465 res_lib_evs_membership_get
.member_list_entries
=
466 res_evs_confchg_callback
.member_list_entries
;
468 openais_conn_send_response (conn
, &res_lib_evs_membership_get
,
469 sizeof (struct res_lib_evs_membership_get
));
472 static void req_exec_mcast_endian_convert (void *msg
)
474 struct req_exec_evs_mcast
*req_exec_evs_mcast
=
475 (struct req_exec_evs_mcast
*)msg
;
476 req_exec_evs_mcast
->group_entries
=
477 swab32 (req_exec_evs_mcast
->group_entries
);
478 req_exec_evs_mcast
->msg_len
= swab32 (req_exec_evs_mcast
->msg_len
);
481 static void message_handler_req_exec_mcast (
485 struct req_exec_evs_mcast
*req_exec_evs_mcast
= (struct req_exec_evs_mcast
*)msg
;
486 struct res_evs_deliver_callback res_evs_deliver_callback
;
488 struct list_head
*list
;
491 struct evs_pd
*evs_pd
;
493 res_evs_deliver_callback
.header
.size
= sizeof (struct res_evs_deliver_callback
) +
494 req_exec_evs_mcast
->msg_len
;
495 res_evs_deliver_callback
.header
.id
= MESSAGE_RES_EVS_DELIVER_CALLBACK
;
496 res_evs_deliver_callback
.header
.error
= SA_AIS_OK
;
497 res_evs_deliver_callback
.msglen
= req_exec_evs_mcast
->msg_len
;
499 msg_addr
= (char *)req_exec_evs_mcast
+ sizeof (struct req_exec_evs_mcast
) +
500 (sizeof (struct evs_group
) * req_exec_evs_mcast
->group_entries
);
502 for (list
= confchg_notify
.next
; list
!= &confchg_notify
; list
= list
->next
) {
504 evs_pd
= list_entry (list
, struct evs_pd
, list
);
506 for (i
= 0; i
< evs_pd
->group_entries
; i
++) {
507 for (j
= 0; j
< req_exec_evs_mcast
->group_entries
; j
++) {
509 if (memcmp (&evs_pd
->groups
[i
], &req_exec_evs_mcast
->groups
[j
],
510 sizeof (struct evs_group
)) == 0) {
522 res_evs_deliver_callback
.local_nodeid
= nodeid
;
523 openais_conn_send_response (evs_pd
->conn
, &res_evs_deliver_callback
,
524 sizeof (struct res_evs_deliver_callback
));
525 openais_conn_send_response (evs_pd
->conn
, msg_addr
,
526 req_exec_evs_mcast
->msg_len
);