3 * Copyright (c) 2002-2005 MontaVista Software, Inc.
4 * Copyright (c) 2006 Red Hat, Inc.
8 * Author: Steven Dake (sdake@mvista.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.
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <sys/select.h>
57 mar_res_header_t header
;
62 * Data structure for instance data
67 OpenaisCfgCallbacksT callbacks
;
71 pthread_mutex_t response_mutex
;
72 pthread_mutex_t dispatch_mutex
;
75 static void cfg_handleInstanceDestructor (void *);
78 * All instances in one database
80 static struct saHandleDatabase cfg_hdb
= {
83 .mutex
= PTHREAD_MUTEX_INITIALIZER
,
84 .handleInstanceDestructor
= cfg_handleInstanceDestructor
90 void cfg_handleInstanceDestructor (void *instance
)
92 struct cfg_instance
*cfg_instance
= instance
;
94 pthread_mutex_destroy (&cfg_instance
->response_mutex
);
95 pthread_mutex_destroy (&cfg_instance
->dispatch_mutex
);
99 openais_cfg_initialize (
100 openais_cfg_handle_t
*cfg_handle
,
101 const OpenaisCfgCallbacksT
*cfgCallbacks
)
103 struct cfg_instance
*cfg_instance
;
104 SaAisErrorT error
= SA_AIS_OK
;
106 error
= saHandleCreate (&cfg_hdb
, sizeof (struct cfg_instance
), cfg_handle
);
107 if (error
!= SA_AIS_OK
) {
108 goto error_no_destroy
;
111 error
= saHandleInstanceGet (&cfg_hdb
, *cfg_handle
, (void *)&cfg_instance
);
112 if (error
!= SA_AIS_OK
) {
116 cfg_instance
->response_fd
= -1;
118 cfg_instance
->dispatch_fd
= -1;
120 error
= saServiceConnect (&cfg_instance
->response_fd
,
121 &cfg_instance
->dispatch_fd
, CFG_SERVICE
);
122 if (error
!= SA_AIS_OK
) {
123 goto error_put_destroy
;
127 memcpy (&cfg_instance
->callbacks
, cfgCallbacks
, sizeof (OpenaisCfgCallbacksT
));
130 pthread_mutex_init (&cfg_instance
->response_mutex
, NULL
);
132 pthread_mutex_init (&cfg_instance
->dispatch_mutex
, NULL
);
134 saHandleInstancePut (&cfg_hdb
, *cfg_handle
);
139 saHandleInstancePut (&cfg_hdb
, *cfg_handle
);
141 saHandleDestroy (&cfg_hdb
, *cfg_handle
);
148 openais_cfg_handle_t cfg_handle
,
149 SaSelectionObjectT
*selectionObject
)
151 struct cfg_instance
*cfg_instance
;
154 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
155 if (error
!= SA_AIS_OK
) {
159 *selectionObject
= cfg_instance
->dispatch_fd
;
161 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
166 openais_cfg_dispatch (
167 openais_cfg_handle_t cfg_handle
,
168 SaDispatchFlagsT dispatchFlags
)
173 int cont
= 1; /* always continue do loop except when set to 0 */
175 struct cfg_instance
*cfg_instance
;
177 struct res_lib_openais_healthcheckcallback
*res_lib_openais_healthcheckcallback
;
178 struct res_lib_openais_readinessstatesetcallback
*res_lib_openais_readinessstatesetcallback
;
179 struct res_lib_openais_csisetcallback
*res_lib_openais_csisetcallback
;
180 struct res_lib_openais_csiremovecallback
*res_lib_openais_csiremovecallback
;
181 struct res_lib_cfg_statetrackcallback
*res_lib_cfg_statetrackcallback
;
183 OpenaisCfgCallbacksT callbacks
;
184 struct res_overlay dispatch_data
;
186 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
187 (void *)&cfg_instance
);
188 if (error
!= SA_AIS_OK
) {
193 * Timeout instantly for SA_DISPATCH_ALL
195 if (dispatchFlags
== SA_DISPATCH_ALL
) {
201 * Read data directly from socket
203 ufds
.fd
= cfg_instance
->dispatch_fd
;
204 ufds
.events
= POLLIN
;
207 error
= saPollRetry (&ufds
, 1, timeout
);
208 if (error
!= SA_AIS_OK
) {
212 pthread_mutex_lock (&cfg_instance
->dispatch_mutex
);
214 error
= saPollRetry (&ufds
, 1, 0);
215 if (error
!= SA_AIS_OK
) {
220 * Handle has been finalized in another thread
222 if (cfg_instance
->finalize
== 1) {
224 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
228 dispatch_avail
= ufds
.revents
& POLLIN
;
229 if (dispatch_avail
== 0 && dispatchFlags
== SA_DISPATCH_ALL
) {
230 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
231 break; /* exit do while cont is 1 loop */
233 if (dispatch_avail
== 0) {
234 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
235 continue; /* next poll */
238 if (ufds
.revents
& POLLIN
) {
240 * Queue empty, read response from socket
242 error
= saRecvRetry (cfg_instance
->dispatch_fd
, &dispatch_data
.header
,
243 sizeof (mar_res_header_t
));
244 if (error
!= SA_AIS_OK
) {
247 if (dispatch_data
.header
.size
> sizeof (mar_res_header_t
)) {
248 error
= saRecvRetry (cfg_instance
->dispatch_fd
, &dispatch_data
.data
,
249 dispatch_data
.header
.size
- sizeof (mar_res_header_t
));
250 if (error
!= SA_AIS_OK
) {
255 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
260 * Make copy of callbacks, message data, unlock instance, and call callback
261 * A risk of this dispatch method is that the callback routines may
262 * operate at the same time that cfgFinalize has been called in another thread.
264 memcpy (&callbacks
, &cfg_instance
->callbacks
, sizeof (OpenaisCfgCallbacksT
));
265 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
268 * Dispatch incoming response
270 switch (dispatch_data
.header
.id
) {
273 error
= SA_AIS_ERR_LIBRARY
;
279 * Determine if more messages should be processed
281 switch (dispatchFlags
) {
282 case SA_DISPATCH_ONE
:
285 case SA_DISPATCH_ALL
:
287 case SA_DISPATCH_BLOCKING
:
293 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
299 openais_cfg_finalize (
300 openais_cfg_handle_t cfg_handle
)
302 struct cfg_instance
*cfg_instance
;
305 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
306 if (error
!= SA_AIS_OK
) {
310 pthread_mutex_lock (&cfg_instance
->dispatch_mutex
);
312 pthread_mutex_lock (&cfg_instance
->response_mutex
);
315 * Another thread has already started finalizing
317 if (cfg_instance
->finalize
) {
318 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
319 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
320 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
321 return (SA_AIS_ERR_BAD_HANDLE
);
324 cfg_instance
->finalize
= 1;
326 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
328 pthread_mutex_unlock (&cfg_instance
->dispatch_mutex
);
330 pthread_mutex_destroy (&cfg_instance
->response_mutex
);
332 pthread_mutex_destroy (&cfg_instance
->dispatch_mutex
);
334 saHandleDestroy (&cfg_hdb
, cfg_handle
);
336 if (cfg_instance
->response_fd
!= -1) {
337 shutdown (cfg_instance
->response_fd
, 0);
338 close (cfg_instance
->response_fd
);
340 if (cfg_instance
->dispatch_fd
!= -1) {
341 shutdown (cfg_instance
->dispatch_fd
, 0);
342 close (cfg_instance
->dispatch_fd
);
345 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
351 openais_cfg_ring_status_get (
352 openais_cfg_handle_t cfg_handle
,
353 char ***interface_names
,
355 unsigned int *interface_count
)
357 struct cfg_instance
*cfg_instance
;
358 struct req_lib_cfg_ringstatusget req_lib_cfg_ringstatusget
;
359 struct res_lib_cfg_ringstatusget res_lib_cfg_ringstatusget
;
363 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
364 if (error
!= SA_AIS_OK
) {
368 req_lib_cfg_ringstatusget
.header
.size
= sizeof (struct req_lib_cfg_ringstatusget
);
369 req_lib_cfg_ringstatusget
.header
.id
= MESSAGE_REQ_CFG_RINGSTATUSGET
;
371 pthread_mutex_lock (&cfg_instance
->response_mutex
);
373 error
= saSendReceiveReply (cfg_instance
->response_fd
,
374 &req_lib_cfg_ringstatusget
,
375 sizeof (struct req_lib_cfg_ringstatusget
),
376 &res_lib_cfg_ringstatusget
,
377 sizeof (struct res_lib_cfg_ringstatusget
));
379 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
381 *interface_count
= res_lib_cfg_ringstatusget
.interface_count
;
382 *interface_names
= malloc (sizeof (char *) * *interface_count
);
383 if (*interface_names
== NULL
) {
384 return (SA_AIS_ERR_NO_MEMORY
);
386 memset (*interface_names
, 0, sizeof (char *) * *interface_count
);
388 *status
= malloc (sizeof (char *) * *interface_count
);
389 if (*status
== NULL
) {
390 error
= SA_AIS_ERR_NO_MEMORY
;
391 goto error_free_interface_names
;
393 memset (*status
, 0, sizeof (char *) * *interface_count
);
395 for (i
= 0; i
< res_lib_cfg_ringstatusget
.interface_count
; i
++) {
396 (*(interface_names
))[i
] = strdup (res_lib_cfg_ringstatusget
.interface_name
[i
]);
397 if ((*(interface_names
))[i
] == NULL
) {
398 error
= SA_AIS_ERR_NO_MEMORY
;
399 goto error_free_contents
;
401 (*(status
))[i
] = strdup (res_lib_cfg_ringstatusget
.interface_status
[i
]);
402 if ((*(status
))[i
] == NULL
) {
403 error
= SA_AIS_ERR_NO_MEMORY
;
404 goto error_free_contents
;
410 for (i
= 0; i
< res_lib_cfg_ringstatusget
.interface_count
; i
++) {
411 if ((*(interface_names
))[i
]) {
412 free ((*(interface_names
))[i
]);
414 if ((*(status
))[i
]) {
415 free ((*(status
))[i
]);
421 error_free_interface_names
:
422 free (*interface_names
);
425 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
431 openais_cfg_ring_reenable (
432 openais_cfg_handle_t cfg_handle
)
434 struct cfg_instance
*cfg_instance
;
435 struct req_lib_cfg_ringreenable req_lib_cfg_ringreenable
;
436 struct res_lib_cfg_ringreenable res_lib_cfg_ringreenable
;
439 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
, (void *)&cfg_instance
);
440 if (error
!= SA_AIS_OK
) {
444 req_lib_cfg_ringreenable
.header
.size
= sizeof (struct req_lib_cfg_ringreenable
);
445 req_lib_cfg_ringreenable
.header
.id
= MESSAGE_REQ_CFG_RINGREENABLE
;
447 pthread_mutex_lock (&cfg_instance
->response_mutex
);
449 error
= saSendReceiveReply (cfg_instance
->response_fd
,
450 &req_lib_cfg_ringreenable
,
451 sizeof (struct req_lib_cfg_ringreenable
),
452 &res_lib_cfg_ringreenable
,
453 sizeof (struct res_lib_cfg_ringreenable
));
455 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
456 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
462 openais_cfg_state_track (
463 openais_cfg_handle_t cfg_handle
,
465 const OpenaisCfgStateNotificationT
*notificationBuffer
)
467 struct cfg_instance
*cfg_instance
;
468 struct req_lib_cfg_statetrack req_lib_cfg_statetrack
;
469 struct res_lib_cfg_statetrack res_lib_cfg_statetrack
;
472 req_lib_cfg_statetrack
.header
.size
= sizeof (struct req_lib_cfg_statetrack
);
473 req_lib_cfg_statetrack
.header
.id
= MESSAGE_REQ_CFG_STATETRACKSTART
;
474 req_lib_cfg_statetrack
.trackFlags
= trackFlags
;
475 req_lib_cfg_statetrack
.notificationBufferAddress
= (OpenaisCfgStateNotificationT
*)notificationBuffer
;
477 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
478 (void *)&cfg_instance
);
479 if (error
!= SA_AIS_OK
) {
483 pthread_mutex_lock (&cfg_instance
->response_mutex
);
485 error
= saSendReceiveReply (cfg_instance
->response_fd
,
486 &req_lib_cfg_statetrack
,
487 sizeof (struct req_lib_cfg_statetrack
),
488 &res_lib_cfg_statetrack
,
489 sizeof (struct res_lib_cfg_statetrack
));
491 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
493 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
495 return (error
== SA_AIS_OK
? res_lib_cfg_statetrack
.header
.error
: error
);
499 openais_cfg_state_track_stop (
500 openais_cfg_handle_t cfg_handle
)
502 struct cfg_instance
*cfg_instance
;
503 struct req_lib_cfg_statetrackstop req_lib_cfg_statetrackstop
;
504 struct res_lib_cfg_statetrackstop res_lib_cfg_statetrackstop
;
507 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
508 (void *)&cfg_instance
);
509 if (error
!= SA_AIS_OK
) {
513 req_lib_cfg_statetrackstop
.header
.size
= sizeof (struct req_lib_cfg_statetrackstop
);
514 req_lib_cfg_statetrackstop
.header
.id
= MESSAGE_REQ_CFG_STATETRACKSTOP
;
516 pthread_mutex_lock (&cfg_instance
->response_mutex
);
518 error
= saSendReceiveReply (cfg_instance
->response_fd
,
519 &req_lib_cfg_statetrackstop
,
520 sizeof (struct req_lib_cfg_statetrackstop
),
521 &res_lib_cfg_statetrackstop
,
522 sizeof (struct res_lib_cfg_statetrackstop
));
524 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
526 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
528 return (error
== SA_AIS_OK
? res_lib_cfg_statetrackstop
.header
.error
: error
);
532 openais_cfg_admin_state_get (
533 openais_cfg_handle_t cfg_handle
,
534 OpenaisCfgAdministrativeTargetT administrativeTarget
,
535 OpenaisCfgAdministrativeStateT
*administrativeState
)
537 struct cfg_instance
*cfg_instance
;
538 struct req_lib_cfg_administrativestateget req_lib_cfg_administrativestateget
;
539 struct res_lib_cfg_administrativestateget res_lib_cfg_administrativestateget
;
542 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
543 (void *)&cfg_instance
);
544 if (error
!= SA_AIS_OK
) {
548 req_lib_cfg_administrativestateget
.header
.id
= MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET
;
549 req_lib_cfg_administrativestateget
.header
.size
= sizeof (struct req_lib_cfg_administrativestateget
);
550 req_lib_cfg_administrativestateget
.administrativeTarget
= administrativeTarget
;
552 error
= saSendReceiveReply (cfg_instance
->response_fd
,
553 &req_lib_cfg_administrativestateget
,
554 sizeof (struct req_lib_cfg_administrativestateget
),
555 &res_lib_cfg_administrativestateget
,
556 sizeof (struct res_lib_cfg_administrativestateget
));
558 error
= res_lib_cfg_administrativestateget
.header
.error
;
560 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
562 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
564 return (error
== SA_AIS_OK
? res_lib_cfg_administrativestateget
.header
.error
: error
);
568 openais_cfg_admin_state_set (
569 openais_cfg_handle_t cfg_handle
,
570 OpenaisCfgAdministrativeTargetT administrativeTarget
,
571 OpenaisCfgAdministrativeStateT administrativeState
)
573 struct cfg_instance
*cfg_instance
;
574 struct req_lib_cfg_administrativestateset req_lib_cfg_administrativestateset
;
575 struct res_lib_cfg_administrativestateset res_lib_cfg_administrativestateset
;
578 error
= saHandleInstanceGet (&cfg_hdb
, cfg_handle
,
579 (void *)&cfg_instance
);
580 if (error
!= SA_AIS_OK
) {
584 req_lib_cfg_administrativestateset
.header
.id
= MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET
;
585 req_lib_cfg_administrativestateset
.header
.size
= sizeof (struct req_lib_cfg_administrativestateset
);
586 req_lib_cfg_administrativestateset
.administrativeTarget
= administrativeTarget
;
587 req_lib_cfg_administrativestateset
.administrativeState
= administrativeState
;
589 error
= saSendReceiveReply (cfg_instance
->response_fd
,
590 &req_lib_cfg_administrativestateset
,
591 sizeof (struct req_lib_cfg_administrativestateset
),
592 &res_lib_cfg_administrativestateset
,
593 sizeof (struct res_lib_cfg_administrativestateset
));
595 error
= res_lib_cfg_administrativestateset
.header
.error
;
597 pthread_mutex_unlock (&cfg_instance
->response_mutex
);
599 saHandleInstancePut (&cfg_hdb
, cfg_handle
);
601 return (error
== SA_AIS_OK
? res_lib_cfg_administrativestateset
.header
.error
: error
);