2 * Copyright (c) 2002-2005 MontaVista Software, Inc.
3 * Copyright (c) 2006-2007 Red Hat, Inc.
7 * Author: Steven Dake (sdake@mvista.com)
9 * This software licensed under BSD license, the text of which follows:
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
14 * - Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * - Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * - Neither the name of the MontaVista Software, Inc. nor the names of its
20 * contributors may be used to endorse or promote products derived from this
21 * software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGE.
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <sys/select.h>
56 mar_res_header_t header
;
61 * Data structure for instance data
66 OpenaisCfgCallbacksT callbacks
;
70 pthread_mutex_t response_mutex
;
71 pthread_mutex_t dispatch_mutex
;
74 static void cfg_handleInstanceDestructor (void *);
77 * All instances in one database
79 static struct saHandleDatabase cfg_hdb
= {
82 .mutex
= PTHREAD_MUTEX_INITIALIZER
,
83 .handleInstanceDestructor
= cfg_handleInstanceDestructor
89 void cfg_handleInstanceDestructor (void *instance
)
91 struct cfg_instance
*cfg_instance
= instance
;
93 pthread_mutex_destroy (&cfg_instance
->response_mutex
);
94 pthread_mutex_destroy (&cfg_instance
->dispatch_mutex
);
98 openais_cfg_initialize (
99 openais_cfg_handle_t
*cfg_handle
,
100 const OpenaisCfgCallbacksT
*cfgCallbacks
)
102 struct cfg_instance
*cfg_instance
;
103 SaAisErrorT error
= SA_AIS_OK
;
105 error
= saHandleCreate (&cfg_hdb
, sizeof (struct cfg_instance
), cfg_handle
);
106 if (error
!= SA_AIS_OK
) {
107 goto error_no_destroy
;
110 error
= saHandleInstanceGet (&cfg_hdb
, *cfg_handle
, (void *)&cfg_instance
);
111 if (error
!= SA_AIS_OK
) {
115 cfg_instance
->response_fd
= -1;
117 cfg_instance
->dispatch_fd
= -1;
119 error
= saServiceConnect (&cfg_instance
->response_fd
,
120 &cfg_instance
->dispatch_fd
, CFG_SERVICE
);
121 if (error
!= SA_AIS_OK
) {
122 goto error_put_destroy
;
126 memcpy (&cfg_instance
->callbacks
, cfgCallbacks
, sizeof (OpenaisCfgCallbacksT
));
129 pthread_mutex_init (&cfg_instance
->response_mutex
, NULL
);
131 pthread_mutex_init (&cfg_instance
->dispatch_mutex
, NULL
);
133 saHandleInstancePut (&cfg_hdb
, *cfg_handle
);
138 saHandleInstancePut (&cfg_hdb
, *cfg_handle
);
140 saHandleDestroy (&cfg_hdb
, *cfg_handle
);
147 openais_cfg_handle_t cfg_handle
,
148 SaSelectionObjectT
*selectionObject
)
150 struct cfg_instance
*cfg_instance
;
153 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
154 if (error
!= SA_AIS_OK
) {
158 *selectionObject
= cfg_instance
->dispatch_fd
;
160 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
165 openais_cfg_dispatch (
166 openais_cfg_handle_t cfg_handle
,
167 SaDispatchFlagsT dispatchFlags
)
172 int cont
= 1; /* always continue do loop except when set to 0 */
174 struct cfg_instance
*cfg_instance
;
176 struct res_lib_openais_healthcheckcallback
*res_lib_openais_healthcheckcallback
;
177 struct res_lib_openais_readinessstatesetcallback
*res_lib_openais_readinessstatesetcallback
;
178 struct res_lib_openais_csisetcallback
*res_lib_openais_csisetcallback
;
179 struct res_lib_openais_csiremovecallback
*res_lib_openais_csiremovecallback
;
180 struct res_lib_cfg_statetrackcallback
*res_lib_cfg_statetrackcallback
;
182 OpenaisCfgCallbacksT callbacks
;
183 struct res_overlay dispatch_data
;
185 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
186 (void *)&cfg_instance
);
187 if (error
!= SA_AIS_OK
) {
192 * Timeout instantly for SA_DISPATCH_ALL
194 if (dispatchFlags
== SA_DISPATCH_ALL
) {
200 * Read data directly from socket
202 ufds
.fd
= cfg_instance
->dispatch_fd
;
203 ufds
.events
= POLLIN
;
206 error
= saPollRetry (&ufds
, 1, timeout
);
207 if (error
!= SA_AIS_OK
) {
211 pthread_mutex_lock (&cfg_instance
->dispatch_mutex
);
213 error
= saPollRetry (&ufds
, 1, 0);
214 if (error
!= SA_AIS_OK
) {
219 * Handle has been finalized in another thread
221 if (cfg_instance
->finalize
== 1) {
223 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
227 dispatch_avail
= ufds
.revents
& POLLIN
;
228 if (dispatch_avail
== 0 && dispatchFlags
== SA_DISPATCH_ALL
) {
229 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
230 break; /* exit do while cont is 1 loop */
232 if (dispatch_avail
== 0) {
233 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
234 continue; /* next poll */
237 if (ufds
.revents
& POLLIN
) {
239 * Queue empty, read response from socket
241 error
= saRecvRetry (cfg_instance
->dispatch_fd
, &dispatch_data
.header
,
242 sizeof (mar_res_header_t
));
243 if (error
!= SA_AIS_OK
) {
246 if (dispatch_data
.header
.size
> sizeof (mar_res_header_t
)) {
247 error
= saRecvRetry (cfg_instance
->dispatch_fd
, &dispatch_data
.data
,
248 dispatch_data
.header
.size
- sizeof (mar_res_header_t
));
249 if (error
!= SA_AIS_OK
) {
254 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
259 * Make copy of callbacks, message data, unlock instance, and call callback
260 * A risk of this dispatch method is that the callback routines may
261 * operate at the same time that cfgFinalize has been called in another thread.
263 memcpy (&callbacks
, &cfg_instance
->callbacks
, sizeof (OpenaisCfgCallbacksT
));
264 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
267 * Dispatch incoming response
269 switch (dispatch_data
.header
.id
) {
272 error
= SA_AIS_ERR_LIBRARY
;
278 * Determine if more messages should be processed
280 switch (dispatchFlags
) {
281 case SA_DISPATCH_ONE
:
284 case SA_DISPATCH_ALL
:
286 case SA_DISPATCH_BLOCKING
:
292 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
298 openais_cfg_finalize (
299 openais_cfg_handle_t cfg_handle
)
301 struct cfg_instance
*cfg_instance
;
304 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
305 if (error
!= SA_AIS_OK
) {
309 pthread_mutex_lock (&cfg_instance
->dispatch_mutex
);
311 pthread_mutex_lock (&cfg_instance
->response_mutex
);
314 * Another thread has already started finalizing
316 if (cfg_instance
->finalize
) {
317 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
318 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
319 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
320 return (SA_AIS_ERR_BAD_HANDLE
);
323 cfg_instance
->finalize
= 1;
325 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
327 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
329 pthread_mutex_destroy (&cfg_instance
->response_mutex
);
331 pthread_mutex_destroy (&cfg_instance
->dispatch_mutex
);
333 saHandleDestroy (&cfg_hdb
, cfg_handle
);
335 if (cfg_instance
->response_fd
!= -1) {
336 shutdown (cfg_instance
->response_fd
, 0);
337 close (cfg_instance
->response_fd
);
339 if (cfg_instance
->dispatch_fd
!= -1) {
340 shutdown (cfg_instance
->dispatch_fd
, 0);
341 close (cfg_instance
->dispatch_fd
);
344 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
350 openais_cfg_ring_status_get (
351 openais_cfg_handle_t cfg_handle
,
352 char ***interface_names
,
354 unsigned int *interface_count
)
356 struct cfg_instance
*cfg_instance
;
357 struct req_lib_cfg_ringstatusget req_lib_cfg_ringstatusget
;
358 struct res_lib_cfg_ringstatusget res_lib_cfg_ringstatusget
;
362 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
363 if (error
!= SA_AIS_OK
) {
367 req_lib_cfg_ringstatusget
.header
.size
= sizeof (struct req_lib_cfg_ringstatusget
);
368 req_lib_cfg_ringstatusget
.header
.id
= MESSAGE_REQ_CFG_RINGSTATUSGET
;
370 pthread_mutex_lock (&cfg_instance
->response_mutex
);
372 error
= saSendReceiveReply (cfg_instance
->response_fd
,
373 &req_lib_cfg_ringstatusget
,
374 sizeof (struct req_lib_cfg_ringstatusget
),
375 &res_lib_cfg_ringstatusget
,
376 sizeof (struct res_lib_cfg_ringstatusget
));
378 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
380 *interface_count
= res_lib_cfg_ringstatusget
.interface_count
;
381 *interface_names
= malloc (sizeof (char *) * *interface_count
);
382 if (*interface_names
== NULL
) {
383 return (SA_AIS_ERR_NO_MEMORY
);
385 memset (*interface_names
, 0, sizeof (char *) * *interface_count
);
387 *status
= malloc (sizeof (char *) * *interface_count
);
388 if (*status
== NULL
) {
389 error
= SA_AIS_ERR_NO_MEMORY
;
390 goto error_free_interface_names
;
392 memset (*status
, 0, sizeof (char *) * *interface_count
);
394 for (i
= 0; i
< res_lib_cfg_ringstatusget
.interface_count
; i
++) {
395 (*(interface_names
))[i
] = strdup (res_lib_cfg_ringstatusget
.interface_name
[i
]);
396 if ((*(interface_names
))[i
] == NULL
) {
397 error
= SA_AIS_ERR_NO_MEMORY
;
398 goto error_free_contents
;
400 (*(status
))[i
] = strdup (res_lib_cfg_ringstatusget
.interface_status
[i
]);
401 if ((*(status
))[i
] == NULL
) {
402 error
= SA_AIS_ERR_NO_MEMORY
;
403 goto error_free_contents
;
409 for (i
= 0; i
< res_lib_cfg_ringstatusget
.interface_count
; i
++) {
410 if ((*(interface_names
))[i
]) {
411 free ((*(interface_names
))[i
]);
413 if ((*(status
))[i
]) {
414 free ((*(status
))[i
]);
420 error_free_interface_names
:
421 free (*interface_names
);
424 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
430 openais_cfg_ring_reenable (
431 openais_cfg_handle_t cfg_handle
)
433 struct cfg_instance
*cfg_instance
;
434 struct req_lib_cfg_ringreenable req_lib_cfg_ringreenable
;
435 struct res_lib_cfg_ringreenable res_lib_cfg_ringreenable
;
438 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
439 if (error
!= SA_AIS_OK
) {
443 req_lib_cfg_ringreenable
.header
.size
= sizeof (struct req_lib_cfg_ringreenable
);
444 req_lib_cfg_ringreenable
.header
.id
= MESSAGE_REQ_CFG_RINGREENABLE
;
446 pthread_mutex_lock (&cfg_instance
->response_mutex
);
448 error
= saSendReceiveReply (cfg_instance
->response_fd
,
449 &req_lib_cfg_ringreenable
,
450 sizeof (struct req_lib_cfg_ringreenable
),
451 &res_lib_cfg_ringreenable
,
452 sizeof (struct res_lib_cfg_ringreenable
));
454 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
455 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
461 openais_cfg_service_load (
462 openais_cfg_handle_t cfg_handle
,
464 unsigned int service_ver
)
466 struct cfg_instance
*cfg_instance
;
467 struct req_lib_cfg_serviceload req_lib_cfg_serviceload
;
468 struct res_lib_cfg_serviceload res_lib_cfg_serviceload
;
471 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
472 if (error
!= SA_AIS_OK
) {
476 req_lib_cfg_serviceload
.header
.size
= sizeof (struct req_lib_cfg_serviceload
);
477 req_lib_cfg_serviceload
.header
.id
= MESSAGE_REQ_CFG_SERVICELOAD
;
478 memset (&req_lib_cfg_serviceload
.service_name
, 0,
479 sizeof (req_lib_cfg_serviceload
.service_name
));
480 strncpy ((char *)req_lib_cfg_serviceload
.service_name
, service_name
,
481 sizeof (req_lib_cfg_serviceload
.service_name
) - 1);
482 req_lib_cfg_serviceload
.service_ver
= service_ver
;
484 pthread_mutex_lock (&cfg_instance
->response_mutex
);
486 error
= saSendReceiveReply (cfg_instance
->response_fd
,
487 &req_lib_cfg_serviceload
,
488 sizeof (struct req_lib_cfg_serviceload
),
489 &res_lib_cfg_serviceload
,
490 sizeof (struct res_lib_cfg_serviceload
));
492 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
493 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
499 openais_cfg_service_unload (
500 openais_cfg_handle_t cfg_handle
,
502 unsigned int service_ver
)
504 struct cfg_instance
*cfg_instance
;
505 struct req_lib_cfg_serviceunload req_lib_cfg_serviceunload
;
506 struct res_lib_cfg_serviceunload res_lib_cfg_serviceunload
;
509 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
510 if (error
!= SA_AIS_OK
) {
514 req_lib_cfg_serviceunload
.header
.size
= sizeof (struct req_lib_cfg_serviceunload
);
515 req_lib_cfg_serviceunload
.header
.id
= MESSAGE_REQ_CFG_SERVICEUNLOAD
;
516 memset (&req_lib_cfg_serviceunload
.service_name
, 0,
517 sizeof (req_lib_cfg_serviceunload
.service_name
));
518 strncpy ((char *)req_lib_cfg_serviceunload
.service_name
, service_name
,
519 sizeof (req_lib_cfg_serviceunload
.service_name
) - 1);
520 req_lib_cfg_serviceunload
.service_ver
= service_ver
;
522 pthread_mutex_lock (&cfg_instance
->response_mutex
);
524 error
= saSendReceiveReply (cfg_instance
->response_fd
,
525 &req_lib_cfg_serviceunload
,
526 sizeof (struct req_lib_cfg_serviceunload
),
527 &res_lib_cfg_serviceunload
,
528 sizeof (struct res_lib_cfg_serviceunload
));
530 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
531 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
536 openais_cfg_state_track (
537 openais_cfg_handle_t cfg_handle
,
539 const OpenaisCfgStateNotificationT
*notificationBuffer
)
541 struct cfg_instance
*cfg_instance
;
542 struct req_lib_cfg_statetrack req_lib_cfg_statetrack
;
543 struct res_lib_cfg_statetrack res_lib_cfg_statetrack
;
546 req_lib_cfg_statetrack
.header
.size
= sizeof (struct req_lib_cfg_statetrack
);
547 req_lib_cfg_statetrack
.header
.id
= MESSAGE_REQ_CFG_STATETRACKSTART
;
548 req_lib_cfg_statetrack
.trackFlags
= trackFlags
;
549 req_lib_cfg_statetrack
.notificationBufferAddress
= (OpenaisCfgStateNotificationT
*)notificationBuffer
;
551 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
552 (void *)&cfg_instance
);
553 if (error
!= SA_AIS_OK
) {
557 pthread_mutex_lock (&cfg_instance
->response_mutex
);
559 error
= saSendReceiveReply (cfg_instance
->response_fd
,
560 &req_lib_cfg_statetrack
,
561 sizeof (struct req_lib_cfg_statetrack
),
562 &res_lib_cfg_statetrack
,
563 sizeof (struct res_lib_cfg_statetrack
));
565 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
567 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
569 return (error
== SA_AIS_OK
? res_lib_cfg_statetrack
.header
.error
: error
);
573 openais_cfg_state_track_stop (
574 openais_cfg_handle_t cfg_handle
)
576 struct cfg_instance
*cfg_instance
;
577 struct req_lib_cfg_statetrackstop req_lib_cfg_statetrackstop
;
578 struct res_lib_cfg_statetrackstop res_lib_cfg_statetrackstop
;
581 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
582 (void *)&cfg_instance
);
583 if (error
!= SA_AIS_OK
) {
587 req_lib_cfg_statetrackstop
.header
.size
= sizeof (struct req_lib_cfg_statetrackstop
);
588 req_lib_cfg_statetrackstop
.header
.id
= MESSAGE_REQ_CFG_STATETRACKSTOP
;
590 pthread_mutex_lock (&cfg_instance
->response_mutex
);
592 error
= saSendReceiveReply (cfg_instance
->response_fd
,
593 &req_lib_cfg_statetrackstop
,
594 sizeof (struct req_lib_cfg_statetrackstop
),
595 &res_lib_cfg_statetrackstop
,
596 sizeof (struct res_lib_cfg_statetrackstop
));
598 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
600 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
602 return (error
== SA_AIS_OK
? res_lib_cfg_statetrackstop
.header
.error
: error
);
606 openais_cfg_admin_state_get (
607 openais_cfg_handle_t cfg_handle
,
608 OpenaisCfgAdministrativeTargetT administrativeTarget
,
609 OpenaisCfgAdministrativeStateT
*administrativeState
)
611 struct cfg_instance
*cfg_instance
;
612 struct req_lib_cfg_administrativestateget req_lib_cfg_administrativestateget
;
613 struct res_lib_cfg_administrativestateget res_lib_cfg_administrativestateget
;
616 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
617 (void *)&cfg_instance
);
618 if (error
!= SA_AIS_OK
) {
622 req_lib_cfg_administrativestateget
.header
.id
= MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET
;
623 req_lib_cfg_administrativestateget
.header
.size
= sizeof (struct req_lib_cfg_administrativestateget
);
624 req_lib_cfg_administrativestateget
.administrativeTarget
= administrativeTarget
;
626 error
= saSendReceiveReply (cfg_instance
->response_fd
,
627 &req_lib_cfg_administrativestateget
,
628 sizeof (struct req_lib_cfg_administrativestateget
),
629 &res_lib_cfg_administrativestateget
,
630 sizeof (struct res_lib_cfg_administrativestateget
));
632 error
= res_lib_cfg_administrativestateget
.header
.error
;
634 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
636 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
638 return (error
== SA_AIS_OK
? res_lib_cfg_administrativestateget
.header
.error
: error
);
642 openais_cfg_admin_state_set (
643 openais_cfg_handle_t cfg_handle
,
644 OpenaisCfgAdministrativeTargetT administrativeTarget
,
645 OpenaisCfgAdministrativeStateT administrativeState
)
647 struct cfg_instance
*cfg_instance
;
648 struct req_lib_cfg_administrativestateset req_lib_cfg_administrativestateset
;
649 struct res_lib_cfg_administrativestateset res_lib_cfg_administrativestateset
;
652 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
653 (void *)&cfg_instance
);
654 if (error
!= SA_AIS_OK
) {
658 req_lib_cfg_administrativestateset
.header
.id
= MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET
;
659 req_lib_cfg_administrativestateset
.header
.size
= sizeof (struct req_lib_cfg_administrativestateset
);
660 req_lib_cfg_administrativestateset
.administrativeTarget
= administrativeTarget
;
661 req_lib_cfg_administrativestateset
.administrativeState
= administrativeState
;
663 error
= saSendReceiveReply (cfg_instance
->response_fd
,
664 &req_lib_cfg_administrativestateset
,
665 sizeof (struct req_lib_cfg_administrativestateset
),
666 &res_lib_cfg_administrativestateset
,
667 sizeof (struct res_lib_cfg_administrativestateset
));
669 error
= res_lib_cfg_administrativestateset
.header
.error
;
671 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
673 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
675 return (error
== SA_AIS_OK
? res_lib_cfg_administrativestateset
.header
.error
: error
);