Fix build error.
[openais.git] / lib / clm.c
blob70c697199efc3afaeac6ba022d22d128223934dc
1 /*
2 * Copyright (c) 2002-2005 MontaVista Software, Inc.
3 * Copyright (c) 2006 Red Hat, Inc.
5 * All rights reserved.
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.
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <assert.h>
41 #include <errno.h>
42 #include <pthread.h>
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <sys/select.h>
46 #include <sys/un.h>
48 #include <swab.h>
49 #include "../exec/totem.h"
50 #include <saAis.h>
51 #include <saClm.h>
52 #include <ipc_gen.h>
53 #include <ipc_clm.h>
54 #include <mar_gen.h>
55 #include <mar_clm.h>
57 #include <ais_util.h>
59 struct res_overlay {
60 mar_res_header_t header;
61 char data[512000];
64 struct clmInstance {
65 int response_fd;
66 int dispatch_fd;
67 SaClmCallbacksT callbacks;
68 int finalize;
69 pthread_mutex_t response_mutex;
70 pthread_mutex_t dispatch_mutex;
73 static void clmHandleInstanceDestructor (void *);
75 static struct saHandleDatabase clmHandleDatabase = {
76 .handleCount = 0,
77 .handles = 0,
78 .mutex = PTHREAD_MUTEX_INITIALIZER,
79 .handleInstanceDestructor = clmHandleInstanceDestructor
83 * Versions supported
85 static SaVersionT clmVersionsSupported[] = {
86 { 'B', 1, 1 }
89 static struct saVersionDatabase clmVersionDatabase = {
90 sizeof (clmVersionsSupported) / sizeof (SaVersionT),
91 clmVersionsSupported
94 void clmHandleInstanceDestructor (void *instance)
96 struct clmInstance *clmInstance = instance;
98 pthread_mutex_destroy (&clmInstance->response_mutex);
99 pthread_mutex_destroy (&clmInstance->dispatch_mutex);
104 * @defgroup saClm SAF AIS Cluster Membership API
105 * @ingroup saf
107 * @{
110 * This function initializes the Cluster Membership Service for the invoking
111 * process and registers the various callback functions. This function must
112 * be invoked prior to the invocation of any other Cluster Membership Service
113 * functionality. The handle clmHandle is returned as the reference to this
114 * association between the process and the Cluster Membership Service. The
115 * process uses this handle in subsequent communication with the Cluster
116 * Membership Service.
118 * @param clmHandle A pointer to the handle designating this particular
119 * initialization of the Cluster Membership Service that is to be
120 * returned by the Cluster Membership Service.
121 * @param clmCallbacks If clmCallbacks is set to NULL, no callback is
122 * registered; otherise, it is a pointer to an SaClmCallbacksT structure,
123 * containing the callback functions of the process that the Cluster
124 * Membership Service may invoke. Only non-NULL callback functions
125 * in this structure will be registered.
126 * @param version The version requested from the application is passed into
127 * this parameter and the version supported is returned.
129 * @returns SA_AIS_OK if the function completed successfully.
130 * @returns SA_AIS_ERR_LIBRARY if an unexpected problem occurred in
131 * the library.
132 * @returns SA_AIS_ERR_TRY_AGAIN if the service cannot be provided at this
133 * time.
134 * @returns SA_AIS_ERR_INVALID_PARAM if a parameter is not set correctly.
135 * @returns SA_AIS_ERR_NO_MEMORY if the Cluster Membership Service is out
136 * of memory and cannot provide the service.
137 * @returns SA_AIS_ERR_VERSION if the version parameter is not compatible with
138 * the version of the Cluster Membership Service implementation.
140 SaAisErrorT
141 saClmInitialize (
142 SaClmHandleT *clmHandle,
143 const SaClmCallbacksT *clmCallbacks,
144 SaVersionT *version)
146 struct clmInstance *clmInstance;
147 SaAisErrorT error = SA_AIS_OK;
150 if (clmHandle == NULL) {
151 return (SA_AIS_ERR_INVALID_PARAM);
153 if (version == NULL) {
154 return (SA_AIS_ERR_INVALID_PARAM);
157 error = saVersionVerify (&clmVersionDatabase, version);
158 if (error != SA_AIS_OK) {
159 goto error_no_destroy;
162 error = saHandleCreate (&clmHandleDatabase, sizeof (struct clmInstance),
163 clmHandle);
164 if (error != SA_AIS_OK) {
165 goto error_no_destroy;
168 error = saHandleInstanceGet (&clmHandleDatabase, *clmHandle,
169 (void *)&clmInstance);
170 if (error != SA_AIS_OK) {
171 goto error_destroy;
174 clmInstance->response_fd = -1;
176 clmInstance->dispatch_fd = -1;
178 error = saServiceConnect (&clmInstance->response_fd,
179 &clmInstance->dispatch_fd, CLM_SERVICE);
180 if (error != SA_AIS_OK) {
181 goto error_put_destroy;
184 if (clmCallbacks) {
185 memcpy (&clmInstance->callbacks, clmCallbacks, sizeof (SaClmCallbacksT));
186 } else {
187 memset (&clmInstance->callbacks, 0, sizeof (SaClmCallbacksT));
190 pthread_mutex_init (&clmInstance->response_mutex, NULL);
192 pthread_mutex_init (&clmInstance->dispatch_mutex, NULL);
194 saHandleInstancePut (&clmHandleDatabase, *clmHandle);
196 return (SA_AIS_OK);
198 error_put_destroy:
199 saHandleInstancePut (&clmHandleDatabase, *clmHandle);
200 error_destroy:
201 saHandleDestroy (&clmHandleDatabase, *clmHandle);
202 error_no_destroy:
203 return (error);
207 * This function returns the operating system handle, selectionObject,
208 * assocated with the handle clmHandle. The invoking process can use this
209 * handle to detect pending callbacks, instead of repeatedly invoking
210 * saClmDispatch() for this purpose.
212 * In a POSIX environment, the operating system handle is a file descriptor
213 * that is used with the poll() or select() system calls to detect pending
214 * callbacks.
216 * The selectionObject returned by saClmSelectionObjectGet() is valid until
217 * saClmFinalize() is invoked on the same handle clmHandle.
219 * @param clmHandle The handle, obtained through the saClmInitialize function,
220 * designating this particular initialization of the Cluster Membership
221 * @param selectionObject A pointer to the operating system handle that the
222 * invoking process can use to detect pending callbacks.
224 * @returns SA_AIS_OK if the function completed successfully.
225 * @returns SA_AIS_ERR_BAD_HANDLE if the handle clmHandle is invalid, since it is
226 * corrupted, uninitialized, or has already been finalized.
228 SaAisErrorT
229 saClmSelectionObjectGet (
230 SaClmHandleT clmHandle,
231 SaSelectionObjectT *selectionObject)
233 struct clmInstance *clmInstance;
234 SaAisErrorT error;
236 if (selectionObject == NULL) {
237 return (SA_AIS_ERR_INVALID_PARAM);
239 error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
240 (void *)&clmInstance);
241 if (error != SA_AIS_OK) {
242 return (error);
245 *selectionObject = clmInstance->dispatch_fd;
247 saHandleInstancePut (&clmHandleDatabase, clmHandle);
248 return (SA_AIS_OK);
252 * This function invokes, in the context of the calling thread, pending callbacks for
253 * the handle clmhandle in a way that is specified by the dispatchFlags parameter.
255 * @param clmHandle The handle, obtained through the saClmInitialize() function,
256 * designating the particular initialization of the Cluster Membership Service.
257 * @param dispatchFlags Flags that specify the callback exection behavior of
258 * saClmDispatch, which have the values SA_DISPATCH_ONE, SA_DISPATCH_ALL, or
259 * SA_DISPATCH_BLOCKING.
260 * @returns SA_AIS_OK if the function completed successfully.
261 * @returns SA_AIS_ERR_TRY_AGAIN if the service cannot be provided at this time. The
262 * process may retry later.
263 * @returns SA_AIS_ERR_BAD_HANDLE if the handle clmHandle is invalid, since it is
264 * corrupted, uninitialized, or has already been finalized.
265 * @returns SA_AIS_ERR_INVALID_PARAM if the dispatchFlags parameter is valid.
267 SaAisErrorT
268 saClmDispatch (
269 SaClmHandleT clmHandle,
270 SaDispatchFlagsT dispatchFlags)
272 struct pollfd ufds;
273 int timeout = -1;
274 SaAisErrorT error;
275 int cont = 1; /* always continue do loop except when set to 0 */
276 int dispatch_avail;
277 struct clmInstance *clmInstance;
278 struct res_lib_clm_clustertrack *res_lib_clm_clustertrack;
279 struct res_clm_nodegetcallback *res_clm_nodegetcallback;
280 SaClmCallbacksT callbacks;
281 struct res_overlay dispatch_data;
282 SaClmClusterNotificationBufferT notificationBuffer;
283 SaClmClusterNotificationT notification[PROCESSOR_COUNT_MAX];
284 SaClmClusterNodeT clusterNode;
285 int items_to_copy;
286 unsigned int i;
288 if (dispatchFlags != SA_DISPATCH_ONE &&
289 dispatchFlags != SA_DISPATCH_ALL &&
290 dispatchFlags != SA_DISPATCH_BLOCKING) {
292 return (SA_AIS_ERR_INVALID_PARAM);
295 error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
296 (void *)&clmInstance);
297 if (error != SA_AIS_OK) {
298 return (error);
302 * Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and
303 * wait indefinately for SA_DISPATCH_BLOCKING
305 if (dispatchFlags == SA_DISPATCH_ALL) {
306 timeout = 0;
309 do {
310 ufds.fd = clmInstance->dispatch_fd;
311 ufds.events = POLLIN;
312 ufds.revents = 0;
314 pthread_mutex_lock (&clmInstance->dispatch_mutex);
316 error = saPollRetry (&ufds, 1, timeout);
317 if (error != SA_AIS_OK) {
318 goto error_unlock;
322 * Handle has been finalized in another thread
324 if (clmInstance->finalize == 1) {
325 error = SA_AIS_OK;
326 goto error_unlock;
329 if ((ufds.revents & (POLLERR|POLLHUP|POLLNVAL)) != 0) {
330 error = SA_AIS_ERR_BAD_HANDLE;
331 goto error_unlock;
334 dispatch_avail = ufds.revents & POLLIN;
335 if (dispatch_avail == 0 && dispatchFlags == SA_DISPATCH_ALL) {
336 pthread_mutex_unlock (&clmInstance->dispatch_mutex);
337 break; /* exit do while cont is 1 loop */
338 } else
339 if (dispatch_avail == 0) {
340 pthread_mutex_unlock (&clmInstance->dispatch_mutex);
341 continue; /* next poll */
344 if (ufds.revents & POLLIN) {
345 error = saRecvRetry (clmInstance->dispatch_fd, &dispatch_data.header,
346 sizeof (mar_res_header_t));
347 if (error != SA_AIS_OK) {
348 goto error_unlock;
350 if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
351 error = saRecvRetry (clmInstance->dispatch_fd, &dispatch_data.data,
352 dispatch_data.header.size - sizeof (mar_res_header_t));
353 if (error != SA_AIS_OK) {
354 goto error_unlock;
357 } else {
358 pthread_mutex_unlock (&clmInstance->dispatch_mutex);
359 continue;
363 * Make copy of callbacks, message data, unlock instance, and call callback
364 * A risk of this dispatch method is that the callback routines may
365 * operate at the same time that clmFinalize has been called in another thread.
367 memcpy (&callbacks, &clmInstance->callbacks, sizeof (SaClmCallbacksT));
368 pthread_mutex_unlock (&clmInstance->dispatch_mutex);
371 * Dispatch incoming message
373 switch (dispatch_data.header.id) {
375 case MESSAGE_RES_CLM_TRACKCALLBACK:
376 if (callbacks.saClmClusterTrackCallback == NULL) {
377 continue;
379 res_lib_clm_clustertrack = (struct res_lib_clm_clustertrack *)&dispatch_data;
380 error = SA_AIS_OK;
382 notificationBuffer.notification = notification;
384 notificationBuffer.viewNumber = res_lib_clm_clustertrack->view;
385 notificationBuffer.notification = notification;
386 notificationBuffer.numberOfItems =
387 res_lib_clm_clustertrack->number_of_items;
389 items_to_copy = notificationBuffer.numberOfItems
390 < res_lib_clm_clustertrack->number_of_items ?
391 notificationBuffer.numberOfItems :
392 res_lib_clm_clustertrack->number_of_items;
394 for (i = 0; i < items_to_copy; i++) {
395 marshall_from_mar_clm_cluster_notification_t (
396 &notificationBuffer.notification[i],
397 &res_lib_clm_clustertrack->notification[i]);
400 callbacks.saClmClusterTrackCallback (
401 (const SaClmClusterNotificationBufferT *)&notificationBuffer,
402 res_lib_clm_clustertrack->number_of_items, error);
404 break;
406 case MESSAGE_RES_CLM_NODEGETCALLBACK:
407 if (callbacks.saClmClusterNodeGetCallback == NULL) {
408 continue;
410 res_clm_nodegetcallback = (struct res_clm_nodegetcallback *)&dispatch_data;
411 marshall_from_mar_clm_cluster_node_t (
412 &clusterNode,
413 &res_clm_nodegetcallback->cluster_node);
415 callbacks.saClmClusterNodeGetCallback (
416 res_clm_nodegetcallback->invocation,
417 &clusterNode,
418 res_clm_nodegetcallback->header.error);
419 break;
421 default:
422 error = SA_AIS_ERR_LIBRARY;
423 goto error_put;
424 break;
428 * Determine if more messages should be processed
429 * */
430 switch (dispatchFlags) {
431 case SA_DISPATCH_ONE:
432 cont = 0;
433 break;
434 case SA_DISPATCH_ALL:
435 break;
436 case SA_DISPATCH_BLOCKING:
437 break;
439 } while (cont);
441 goto error_put;
443 error_unlock:
444 pthread_mutex_unlock (&clmInstance->dispatch_mutex);
446 error_put:
447 saHandleInstancePut (&clmHandleDatabase, clmHandle);
448 return (error);
453 * The saClmFinalize function closes the assocation, represented by the clmHandle
454 * parameter, between the invoking process and the Cluster Membership Service. The
455 * process must have invoked saClmInitialize before it invokes this function. A
456 * process must invoke this function once for each handle it acquired by invoking
457 * saClmInitialize().
459 * If the saClmFinalize() function returns successfully, the saClmFinalize() function
460 * releases all resources acquired when saClmInitialize(0 was called. Moreover, it
461 * stops any tracking associated with the particular handle. Furthermore, it cancels
462 * all pending callbacks related to the particular handle. Note that because the
463 * callback invocation is asynchronous, it is still possible that some callback calls
464 * are processed after this call returns successfully.
466 * After saClmFinalize() is invoked, the selection object is no longer valid.
468 * @param clmHandle The handle, obtained through the saClmInitialize() function,
469 * designating this particular initialization of the Cluster Membership Service.
471 * @returns SA_AIS_OK if the function completed successfully.
472 * @returns SA_AIS_ERR_BAD_HANDLE if the handle clmHandle is invalid, since it is
473 * corrupted, uninitialized, or has already been finalized.
475 SaAisErrorT
476 saClmFinalize (
477 SaClmHandleT clmHandle)
479 struct clmInstance *clmInstance;
480 SaAisErrorT error;
482 error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
483 (void *)&clmInstance);
484 if (error != SA_AIS_OK) {
485 return (error);
488 pthread_mutex_lock (&clmInstance->response_mutex);
491 * Another thread has already started finalizing
493 if (clmInstance->finalize) {
494 pthread_mutex_unlock (&clmInstance->response_mutex);
495 saHandleInstancePut (&clmHandleDatabase, clmHandle);
496 return (SA_AIS_ERR_BAD_HANDLE);
499 clmInstance->finalize = 1;
501 pthread_mutex_unlock (&clmInstance->response_mutex);
503 saHandleDestroy (&clmHandleDatabase, clmHandle);
505 if (clmInstance->response_fd != -1) {
506 shutdown (clmInstance->response_fd, 0);
507 close (clmInstance->response_fd);
509 if (clmInstance->dispatch_fd != -1) {
510 shutdown (clmInstance->dispatch_fd, 0);
511 close (clmInstance->dispatch_fd);
514 saHandleInstancePut (&clmHandleDatabase, clmHandle);
516 return (error);
519 SaAisErrorT
520 saClmClusterTrack (
521 SaClmHandleT clmHandle,
522 SaUint8T trackFlags,
523 SaClmClusterNotificationBufferT *notificationBuffer)
525 struct req_lib_clm_clustertrack req_lib_clm_clustertrack;
526 struct res_lib_clm_clustertrack res_lib_clm_clustertrack;
527 struct clmInstance *clmInstance;
528 SaAisErrorT error = SA_AIS_OK;
529 int items_to_copy;
530 unsigned int i;
532 error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
533 (void *)&clmInstance);
534 if (error != SA_AIS_OK) {
535 return (error);
538 if ((trackFlags & SA_TRACK_CHANGES) && (trackFlags & SA_TRACK_CHANGES_ONLY)) {
539 error = SA_AIS_ERR_BAD_FLAGS;
540 goto error_nounlock;
543 if (trackFlags & ~(SA_TRACK_CURRENT | SA_TRACK_CHANGES | SA_TRACK_CHANGES_ONLY)) {
544 error = SA_AIS_ERR_BAD_FLAGS;
545 goto error_nounlock;
548 if ((notificationBuffer != NULL) &&
549 (notificationBuffer->notification != NULL) &&
550 (notificationBuffer->numberOfItems == 0)) {
552 error = SA_AIS_ERR_INVALID_PARAM;
553 goto error_nounlock;
556 req_lib_clm_clustertrack.header.size = sizeof (struct req_lib_clm_clustertrack);
557 req_lib_clm_clustertrack.header.id = MESSAGE_REQ_CLM_TRACKSTART;
558 req_lib_clm_clustertrack.track_flags = trackFlags;
559 req_lib_clm_clustertrack.return_in_callback = 0;
560 if ((trackFlags & SA_TRACK_CURRENT) && (notificationBuffer == NULL)) {
561 req_lib_clm_clustertrack.return_in_callback = 1;
564 pthread_mutex_lock (&clmInstance->response_mutex);
566 if ((clmInstance->callbacks.saClmClusterTrackCallback == 0) &&
567 ((notificationBuffer == NULL) ||
568 (trackFlags & (SA_TRACK_CHANGES | SA_TRACK_CHANGES_ONLY)))) {
570 error = SA_AIS_ERR_INIT;
571 goto error_exit;
574 error = saSendReceiveReply (clmInstance->response_fd,
575 &req_lib_clm_clustertrack,
576 sizeof (struct req_lib_clm_clustertrack),
577 &res_lib_clm_clustertrack,
578 sizeof (struct res_lib_clm_clustertrack));
580 if ((trackFlags & SA_TRACK_CURRENT) && (notificationBuffer != NULL)) {
581 if (notificationBuffer->notification == 0) {
582 notificationBuffer->viewNumber = res_lib_clm_clustertrack.view;
584 notificationBuffer->notification =
585 malloc (res_lib_clm_clustertrack.number_of_items *
586 sizeof (SaClmClusterNotificationT));
588 notificationBuffer->numberOfItems =
589 res_lib_clm_clustertrack.number_of_items;
592 items_to_copy = notificationBuffer->numberOfItems <
593 res_lib_clm_clustertrack.number_of_items ?
594 notificationBuffer->numberOfItems :
595 res_lib_clm_clustertrack.number_of_items;
597 for (i = 0; i < items_to_copy; i++) {
598 marshall_from_mar_clm_cluster_notification_t (
599 &notificationBuffer->notification[i],
600 &res_lib_clm_clustertrack.notification[i]);
603 notificationBuffer->viewNumber = res_lib_clm_clustertrack.view;
604 notificationBuffer->numberOfItems = items_to_copy;
607 error_exit:
608 pthread_mutex_unlock (&clmInstance->response_mutex);
610 error_nounlock:
611 saHandleInstancePut (&clmHandleDatabase, clmHandle);
613 return (error == SA_AIS_OK ? res_lib_clm_clustertrack.header.error : error);
616 SaAisErrorT
617 saClmClusterTrackStop (
618 SaClmHandleT clmHandle)
620 struct clmInstance *clmInstance;
621 struct req_lib_clm_trackstop req_lib_clm_trackstop;
622 struct res_lib_clm_trackstop res_lib_clm_trackstop;
623 SaAisErrorT error = SA_AIS_OK;
625 req_lib_clm_trackstop.header.size = sizeof (struct req_lib_clm_trackstop);
626 req_lib_clm_trackstop.header.id = MESSAGE_REQ_CLM_TRACKSTOP;
627 error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
628 (void *)&clmInstance);
629 if (error != SA_AIS_OK) {
630 return (error);
633 pthread_mutex_lock (&clmInstance->response_mutex);
635 error = saSendReceiveReply (clmInstance->response_fd,
636 &req_lib_clm_trackstop,
637 sizeof (struct req_lib_clm_trackstop),
638 &res_lib_clm_trackstop,
639 sizeof (struct res_lib_clm_trackstop));
641 pthread_mutex_unlock (&clmInstance->response_mutex);
643 saHandleInstancePut (&clmHandleDatabase, clmHandle);
645 return (error == SA_AIS_OK ? res_lib_clm_trackstop.header.error : error);
648 SaAisErrorT
649 saClmClusterNodeGet (
650 SaClmHandleT clmHandle,
651 SaClmNodeIdT nodeId,
652 SaTimeT timeout,
653 SaClmClusterNodeT *clusterNode)
655 struct clmInstance *clmInstance;
656 struct req_lib_clm_nodeget req_lib_clm_nodeget;
657 struct res_clm_nodeget res_clm_nodeget;
658 SaAisErrorT error = SA_AIS_OK;
660 if (clusterNode == NULL) {
661 return (SA_AIS_ERR_INVALID_PARAM);
664 if (timeout == 0) {
665 return (SA_AIS_ERR_TIMEOUT);
668 error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
669 (void *)&clmInstance);
670 if (error != SA_AIS_OK) {
671 return (error);
674 pthread_mutex_lock (&clmInstance->response_mutex);
677 * Send request message
679 req_lib_clm_nodeget.header.size = sizeof (struct req_lib_clm_nodeget);
680 req_lib_clm_nodeget.header.id = MESSAGE_REQ_CLM_NODEGET;
681 req_lib_clm_nodeget.node_id = nodeId;
683 error = saSendReceiveReply (clmInstance->response_fd, &req_lib_clm_nodeget,
684 sizeof (struct req_lib_clm_nodeget), &res_clm_nodeget, sizeof (res_clm_nodeget));
685 if (error != SA_AIS_OK) {
686 goto error_exit;
689 error = res_clm_nodeget.header.error;
691 marshall_from_mar_clm_cluster_node_t (clusterNode,
692 &res_clm_nodeget.cluster_node);
694 error_exit:
695 pthread_mutex_unlock (&clmInstance->response_mutex);
697 saHandleInstancePut (&clmHandleDatabase, clmHandle);
699 return (error);
702 SaAisErrorT
703 saClmClusterNodeGetAsync (
704 SaClmHandleT clmHandle,
705 SaInvocationT invocation,
706 SaClmNodeIdT nodeId)
708 struct clmInstance *clmInstance;
709 struct req_lib_clm_nodegetasync req_lib_clm_nodegetasync;
710 struct res_clm_nodegetasync res_clm_nodegetasync;
711 SaAisErrorT error = SA_AIS_OK;
713 req_lib_clm_nodegetasync.header.size = sizeof (struct req_lib_clm_nodegetasync);
714 req_lib_clm_nodegetasync.header.id = MESSAGE_REQ_CLM_NODEGETASYNC;
715 req_lib_clm_nodegetasync.invocation = invocation;
716 req_lib_clm_nodegetasync.node_id = nodeId;
718 error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
719 (void *)&clmInstance);
720 if (error != SA_AIS_OK) {
721 return (error);
724 pthread_mutex_lock (&clmInstance->response_mutex);
726 if (clmInstance->callbacks.saClmClusterNodeGetCallback == NULL) {
727 error = SA_AIS_ERR_INIT;
728 goto error_exit;
731 error = saSendReceiveReply (clmInstance->response_fd, &req_lib_clm_nodegetasync,
732 sizeof (struct req_lib_clm_nodegetasync),
733 &res_clm_nodegetasync, sizeof (struct res_clm_nodegetasync));
734 if (error != SA_AIS_OK) {
735 goto error_exit;
738 error = res_clm_nodegetasync.header.error;
740 error_exit:
741 pthread_mutex_unlock (&clmInstance->response_mutex);
743 saHandleInstancePut (&clmHandleDatabase, clmHandle);
745 return (error);
748 /** @} */