Allow make from the exec directory.
[openais.git] / exec / evs.c
blobfc6106523191b6bfe4676be33aa95acaae96fb97
1 /*
2 * Copyright (c) 2004-2006 MontaVista Software, Inc.
3 * Copyright (c) 2006-2007 Red Hat, Inc.
4 * Copyright (c) 2006 Sun Microsystems, Inc.
6 * All rights reserved.
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>
38 #include <sys/un.h>
39 #include <sys/ioctl.h>
40 #include <netinet/in.h>
41 #include <sys/uio.h>
42 #include <unistd.h>
43 #include <fcntl.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <errno.h>
47 #include <signal.h>
48 #include <time.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
52 #include "swab.h"
53 #include "totem.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"
60 #include "totempg.h"
61 #include "main.h"
62 #include "tlist.h"
63 #include "flow.h"
64 #include "ipc.h"
65 #include "mempool.h"
66 #include "objdb.h"
67 #include "service.h"
68 #include "logsys.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);
100 struct evs_pd {
101 struct evs_group *groups;
102 int group_entries;
103 struct list_head list;
104 void *conn;
107 static struct openais_lib_handler evs_lib_service[] =
109 { /* 0 */
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
115 { /* 1 */
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
121 { /* 2 */
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
127 { /* 3 */
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
133 { /* 4 */
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",
151 .id = EVS_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,
162 .exec_dump_fn = NULL
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",
180 .version = 0,
181 .versions_replace = 0,
182 .versions_replace_count = 0,
183 .dependencies = 0,
184 .dependency_count = 0,
185 .constructor = NULL,
186 .destructor = NULL,
187 .interfaces = NULL,
191 static struct lcr_comp evs_comp_ver0 = {
192 .iface_count = 1,
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)
209 (void) objdb;
211 return 0;
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;
264 evs_pd->conn = conn;
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));
271 return (0);
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);
279 return (0);
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;
287 void *addr;
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;
292 goto exit_error;
295 addr = realloc (evs_pd->groups, sizeof (struct evs_group) *
296 (evs_pd->group_entries + req_lib_evs_join->group_entries));
297 if (addr == NULL) {
298 error = SA_AIS_ERR_NO_MEMORY;
299 goto exit_error;
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;
309 exit_error:
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;
323 int error_index;
324 int i, j;
325 int found;
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++) {
329 found = 0;
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) {
336 * Delete entry
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;
343 found = 1;
344 break;
345 } else {
346 j++;
349 if (found == 0) {
350 error = EVS_ERR_NOT_EXIST;
351 error_index = i;
352 break;
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;
371 int send_ok = 0;
372 int res;
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);
394 // TODO
395 if (res == 0) {
396 error = EVS_OK;
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;
414 char *msg_addr;
415 int send_ok = 0;
416 int res;
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);
441 if (res == 0) {
442 error = EVS_OK;
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 (
482 void *msg,
483 unsigned int nodeid)
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;
487 char *msg_addr;
488 struct list_head *list;
489 int found = 0;
490 int i, j;
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) {
503 found = 0;
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) {
512 found = 1;
513 break;
516 if (found) {
517 break;
521 if (found) {
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);