Patch to remove segfault on the exiting of a service.
[openais.git] / lib / lck.c
blob0b822b794abe2b031be2e841773d3ddb7c91d65b
1 /*
2 * Copyright (c) 2005 MontaVista Software, Inc.
4 * All rights reserved.
6 * Author: Steven Dake (sdake@mvista.com)
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the MontaVista Software, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
35 #include <stdio.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <assert.h>
39 #include <unistd.h>
40 #include <errno.h>
41 #include <pthread.h>
42 #include <sys/types.h>
43 #include <sys/uio.h>
44 #include <sys/socket.h>
45 #include <sys/select.h>
46 #include <sys/un.h>
48 #include <saAis.h>
49 #include <list.h>
50 #include <saLck.h>
51 #include <ipc_gen.h>
52 #include <ipc_lck.h>
54 #include <ais_util.h>
56 struct message_overlay {
57 mar_res_header_t header __attribute__((aligned(8)));
58 char data[4096];
62 * Data structure for instance data
64 struct lckInstance {
65 int response_fd;
66 int dispatch_fd;
67 SaLckCallbacksT callbacks;
68 int finalize;
69 SaLckHandleT lckHandle;
70 struct list_head resource_list;
71 pthread_mutex_t response_mutex;
72 pthread_mutex_t dispatch_mutex;
75 struct lckResourceInstance {
76 int response_fd;
77 SaLckHandleT lckHandle;
78 SaLckResourceHandleT lckResourceHandle;
79 SaLckResourceOpenFlagsT resourceOpenFlags;
80 SaNameT lockResourceName;
81 struct list_head list;
82 mar_message_source_t source;
83 pthread_mutex_t *response_mutex;
86 struct lckLockIdInstance {
87 int response_fd;
88 SaLckResourceHandleT lckResourceHandle;
89 struct list_head list;
90 void *resource_lock;
91 pthread_mutex_t *response_mutex;
94 void lckHandleInstanceDestructor (void *instance);
95 void lckResourceHandleInstanceDestructor (void *instance);
96 void lckResourceHandleLockIdInstanceDestructor (void *instance);
99 * All LCK instances in this database
101 static struct saHandleDatabase lckHandleDatabase = {
102 .handleCount = 0,
103 .handles = 0,
104 .mutex = PTHREAD_MUTEX_INITIALIZER,
105 .handleInstanceDestructor = lckHandleInstanceDestructor
109 * All Resource instances in this database
111 static struct saHandleDatabase lckResourceHandleDatabase = {
112 .handleCount = 0,
113 .handles = 0,
114 .mutex = PTHREAD_MUTEX_INITIALIZER,
115 .handleInstanceDestructor = lckResourceHandleInstanceDestructor
119 * All Resource Lock Identifier instances in this database
121 static struct saHandleDatabase lckLockIdHandleDatabase = {
122 .handleCount = 0,
123 .handles = 0,
124 .mutex = PTHREAD_MUTEX_INITIALIZER,
125 .handleInstanceDestructor = lckResourceHandleLockIdInstanceDestructor
129 * Versions supported
131 static SaVersionT lckVersionsSupported[] = {
132 { 'B', 1, 1 }
135 static struct saVersionDatabase lckVersionDatabase = {
136 sizeof (lckVersionsSupported) / sizeof (SaVersionT),
137 lckVersionsSupported
142 * Implementation
144 void lckHandleInstanceDestructor (void *instance)
146 struct lckInstance *lckInstance = instance;
148 pthread_mutex_destroy (&lckInstance->response_mutex);
149 pthread_mutex_destroy (&lckInstance->dispatch_mutex);
152 void lckResourceHandleInstanceDestructor (void *instance)
156 void lckResourceHandleLockIdInstanceDestructor (void *instance)
160 #ifdef NOT_DONE
161 static void lckSectionIterationInstanceFinalize (struct lckSectionIterationInstance *lckSectionIterationInstance)
163 struct iteratorSectionIdListEntry *iteratorSectionIdListEntry;
164 struct list_head *sectionIdIterationList;
165 struct list_head *sectionIdIterationListNext;
167 * iterate list of section ids for this iterator to free the allocated memory
168 * be careful to cache next pointer because free removes memory from use
170 for (sectionIdIterationList = lckSectionIterationInstance->sectionIdListHead.next,
171 sectionIdIterationListNext = sectionIdIterationList->next;
172 sectionIdIterationList != &lckSectionIterationInstance->sectionIdListHead;
173 sectionIdIterationList = sectionIdIterationListNext,
174 sectionIdIterationListNext = sectionIdIterationList->next) {
176 iteratorSectionIdListEntry = list_entry (sectionIdIterationList,
177 struct iteratorSectionIdListEntry, list);
179 free (iteratorSectionIdListEntry);
182 list_del (&lckSectionIterationInstance->list);
184 saHandleDestroy (&lckSectionIterationHandleDatabase,
185 lckSectionIterationInstance->sectionIterationHandle);
188 static void lckResourceInstanceFinalize (struct lckResourceInstance *lckResourceInstance)
190 struct lckSectionIterationInstance *sectionIterationInstance;
191 struct list_head *sectionIterationList;
192 struct list_head *sectionIterationListNext;
194 for (sectionIterationList = lckResourceInstance->section_iteration_list_head.next,
195 sectionIterationListNext = sectionIterationList->next;
196 sectionIterationList != &lckResourceInstance->section_iteration_list_head;
197 sectionIterationList = sectionIterationListNext,
198 sectionIterationListNext = sectionIterationList->next) {
200 sectionIterationInstance = list_entry (sectionIterationList,
201 struct lckSectionIterationInstance, list);
203 lckSectionIterationInstanceFinalize (sectionIterationInstance);
206 list_del (&lckResourceInstance->list);
208 saHandleDestroy (&lckResourceHandleDatabase, lckResourceInstance->lckResourceHandle);
211 static void lckInstanceFinalize (struct lckInstance *lckInstance)
213 struct lckResourceInstance *lckResourceInstance;
214 struct list_head *resourceInstanceList;
215 struct list_head *resourceInstanceListNext;
217 for (resourceInstanceList = lckInstance->resource_list.next,
218 resourceInstanceListNext = resourceInstanceList->next;
219 resourceInstanceList != &lckInstance->resource_list;
220 resourceInstanceList = resourceInstanceListNext,
221 resourceInstanceListNext = resourceInstanceList->next) {
223 lckResourceInstance = list_entry (resourceInstanceList,
224 struct lckResourceInstance, list);
226 lckResourceInstanceFinalize (lckResourceInstance);
229 saHandleDestroy (&lckHandleDatabase, lckInstance->lckHandle);
232 #endif
234 SaAisErrorT
235 saLckInitialize (
236 SaLckHandleT *lckHandle,
237 const SaLckCallbacksT *callbacks,
238 SaVersionT *version)
240 struct lckInstance *lckInstance;
241 SaAisErrorT error = SA_AIS_OK;
243 if (lckHandle == NULL) {
244 return (SA_AIS_ERR_INVALID_PARAM);
247 error = saVersionVerify (&lckVersionDatabase, version);
248 if (error != SA_AIS_OK) {
249 goto error_no_destroy;
252 error = saHandleCreate (&lckHandleDatabase, sizeof (struct lckInstance),
253 lckHandle);
254 if (error != SA_AIS_OK) {
255 goto error_no_destroy;
258 error = saHandleInstanceGet (&lckHandleDatabase, *lckHandle,
259 (void *)&lckInstance);
260 if (error != SA_AIS_OK) {
261 goto error_destroy;
264 lckInstance->response_fd = -1;
266 error = saServiceConnect (&lckInstance->response_fd,
267 &lckInstance->dispatch_fd, LCK_SERVICE);
268 if (error != SA_AIS_OK) {
269 goto error_put_destroy;
272 if (callbacks) {
273 memcpy (&lckInstance->callbacks, callbacks, sizeof (SaLckCallbacksT));
274 } else {
275 memset (&lckInstance->callbacks, 0, sizeof (SaLckCallbacksT));
278 list_init (&lckInstance->resource_list);
280 lckInstance->lckHandle = *lckHandle;
282 pthread_mutex_init (&lckInstance->response_mutex, NULL);
285 saHandleInstancePut (&lckHandleDatabase, *lckHandle);
287 return (SA_AIS_OK);
289 error_put_destroy:
290 saHandleInstancePut (&lckHandleDatabase, *lckHandle);
291 error_destroy:
292 saHandleDestroy (&lckHandleDatabase, *lckHandle);
293 error_no_destroy:
294 return (error);
297 SaAisErrorT
298 saLckSelectionObjectGet (
299 const SaLckHandleT lckHandle,
300 SaSelectionObjectT *selectionObject)
302 struct lckInstance *lckInstance;
303 SaAisErrorT error;
305 if (selectionObject == NULL) {
306 return (SA_AIS_ERR_INVALID_PARAM);
308 error = saHandleInstanceGet (&lckHandleDatabase, lckHandle, (void *)&lckInstance);
309 if (error != SA_AIS_OK) {
310 return (error);
313 *selectionObject = lckInstance->dispatch_fd;
315 saHandleInstancePut (&lckHandleDatabase, lckHandle);
317 return (SA_AIS_OK);
320 SaAisErrorT
321 saLckOptionCheck (
322 SaLckHandleT lckHandle,
323 SaLckOptionsT *lckOptions)
325 return (SA_AIS_OK);
328 SaAisErrorT
329 saLckDispatch (
330 const SaLckHandleT lckHandle,
331 SaDispatchFlagsT dispatchFlags)
333 struct pollfd ufds;
334 int poll_fd;
335 int timeout = 1;
336 SaLckCallbacksT callbacks;
337 SaAisErrorT error;
338 int dispatch_avail;
339 struct lckInstance *lckInstance;
340 struct lckResourceInstance *lckResourceInstance;
341 struct lckLockIdInstance *lckLockIdInstance;
342 int cont = 1; /* always continue do loop except when set to 0 */
343 struct message_overlay dispatch_data;
344 struct res_lib_lck_lockwaitercallback *res_lib_lck_lockwaitercallback;
345 struct res_lib_lck_resourceopenasync *res_lib_lck_resourceopenasync = NULL;
346 struct res_lib_lck_resourcelockasync *res_lib_lck_resourcelockasync = NULL;
347 struct res_lib_lck_resourceunlockasync *res_lib_lck_resourceunlockasync;
350 if (dispatchFlags != SA_DISPATCH_ONE &&
351 dispatchFlags != SA_DISPATCH_ALL &&
352 dispatchFlags != SA_DISPATCH_BLOCKING) {
354 return (SA_AIS_ERR_INVALID_PARAM);
357 error = saHandleInstanceGet (&lckHandleDatabase, lckHandle,
358 (void *)&lckInstance);
359 if (error != SA_AIS_OK) {
360 goto error_exit;
364 * Timeout instantly for SA_DISPATCH_ALL
366 if (dispatchFlags == SA_DISPATCH_ALL) {
367 timeout = 0;
370 do {
372 * Read data directly from socket
374 poll_fd = lckInstance->dispatch_fd;
375 ufds.fd = poll_fd;
376 ufds.events = POLLIN;
377 ufds.revents = 0;
379 error = saPollRetry(&ufds, 1, timeout);
380 if (error != SA_AIS_OK) {
381 goto error_put;
383 pthread_mutex_lock(&lckInstance->dispatch_mutex);
385 if (lckInstance->finalize == 1) {
386 error = SA_AIS_OK;
387 goto error_unlock;
390 if ((ufds.revents & (POLLERR|POLLHUP|POLLNVAL)) != 0) {
391 error = SA_AIS_ERR_BAD_HANDLE;
392 goto error_unlock;
395 dispatch_avail = (ufds.revents & POLLIN);
397 if (dispatch_avail == 0 && dispatchFlags == SA_DISPATCH_ALL) {
398 pthread_mutex_unlock(&lckInstance->dispatch_mutex);
399 break; /* exit do while cont is 1 loop */
400 } else
401 if (dispatch_avail == 0) {
402 pthread_mutex_unlock(&lckInstance->dispatch_mutex);
403 continue;
406 memset(&dispatch_data,0, sizeof(struct message_overlay));
407 error = saRecvRetry (lckInstance->dispatch_fd, &dispatch_data.header, sizeof (mar_res_header_t));
408 if (error != SA_AIS_OK) {
409 goto error_unlock;
411 if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
412 error = saRecvRetry (lckInstance->dispatch_fd, &dispatch_data.data,
413 dispatch_data.header.size - sizeof (mar_res_header_t));
414 if (error != SA_AIS_OK) {
415 goto error_unlock;
420 * Make copy of callbacks, message data, unlock instance,
421 * and call callback. A risk of this dispatch method is that
422 * the callback routines may operate at the same time that
423 * LckFinalize has been called in another thread.
425 memcpy(&callbacks,&lckInstance->callbacks, sizeof(lckInstance->callbacks));
426 pthread_mutex_unlock(&lckInstance->dispatch_mutex);
428 * Dispatch incoming response
430 switch (dispatch_data.header.id) {
431 case MESSAGE_RES_LCK_LOCKWAITERCALLBACK:
432 if (callbacks.saLckResourceOpenCallback == NULL) {
433 continue;
435 res_lib_lck_lockwaitercallback = (struct res_lib_lck_lockwaitercallback *)&dispatch_data;
436 callbacks.saLckLockWaiterCallback (
437 res_lib_lck_lockwaitercallback->waiter_signal,
438 res_lib_lck_lockwaitercallback->lock_id,
439 res_lib_lck_lockwaitercallback->mode_held,
440 res_lib_lck_lockwaitercallback->mode_requested);
441 break;
443 case MESSAGE_RES_LCK_RESOURCEOPENASYNC:
444 if (callbacks.saLckLockWaiterCallback == NULL) {
445 continue;
447 res_lib_lck_resourceopenasync = (struct res_lib_lck_resourceopenasync *)&dispatch_data;
449 * This instance get/listadd/put required so that close
450 * later has the proper list of resources
452 if (res_lib_lck_resourceopenasync->header.error == SA_AIS_OK) {
453 error = saHandleInstanceGet (&lckResourceHandleDatabase,
454 res_lib_lck_resourceopenasync->resourceHandle,
455 (void *)&lckResourceInstance);
457 assert (error == SA_AIS_OK); /* should only be valid handles here */
459 * open succeeded without error
462 callbacks.saLckResourceOpenCallback(
463 res_lib_lck_resourceopenasync->invocation,
464 res_lib_lck_resourceopenasync->resourceHandle,
465 res_lib_lck_resourceopenasync->header.error);
466 saHandleInstancePut (&lckResourceHandleDatabase,
467 res_lib_lck_resourceopenasync->resourceHandle);
468 } else {
470 * open failed with error
472 callbacks.saLckResourceOpenCallback(
473 res_lib_lck_resourceopenasync->invocation,
475 res_lib_lck_resourceopenasync->header.error);
477 break;
478 case MESSAGE_RES_LCK_RESOURCELOCKASYNC:
479 DPRINT (("grant\n"));
480 if (callbacks.saLckLockGrantCallback == NULL) {
481 continue;
483 res_lib_lck_resourcelockasync = (struct res_lib_lck_resourcelockasync *)&dispatch_data;
485 * This instance get/listadd/put required so that close
486 * later has the proper list of resources
488 if (res_lib_lck_resourcelockasync->header.error == SA_AIS_OK) {
489 error = saHandleInstanceGet (&lckLockIdHandleDatabase,
490 res_lib_lck_resourcelockasync->lockId,
491 (void *)&lckLockIdInstance);
493 assert (error == SA_AIS_OK); /* should only be valid handles here */
495 * open succeeded without error
497 lckLockIdInstance->resource_lock = res_lib_lck_resourcelockasync->resource_lock;
499 callbacks.saLckLockGrantCallback(
500 res_lib_lck_resourcelockasync->invocation,
501 res_lib_lck_resourcelockasync->lockStatus,
502 res_lib_lck_resourcelockasync->header.error);
503 saHandleInstancePut (&lckLockIdHandleDatabase,
504 res_lib_lck_resourcelockasync->lockId);
505 } else {
507 * open failed with error
509 callbacks.saLckLockGrantCallback (
510 res_lib_lck_resourceopenasync->invocation,
512 res_lib_lck_resourceopenasync->header.error);
514 break;
517 case MESSAGE_RES_LCK_RESOURCEUNLOCKASYNC:
518 if (callbacks.saLckResourceUnlockCallback == NULL) {
519 continue;
521 res_lib_lck_resourceunlockasync = (struct res_lib_lck_resourceunlockasync *)&dispatch_data;
522 callbacks.saLckResourceUnlockCallback (
523 res_lib_lck_resourceunlockasync->invocation,
524 res_lib_lck_resourceunlockasync->header.error);
526 if (res_lib_lck_resourcelockasync->header.error == SA_AIS_OK) {
527 error = saHandleInstanceGet (&lckLockIdHandleDatabase,
528 res_lib_lck_resourceunlockasync->lockId,
529 (void *)&lckLockIdInstance);
530 if (error == SA_AIS_OK) {
531 saHandleInstancePut (&lckLockIdHandleDatabase, res_lib_lck_resourceunlockasync->lockId);
533 saHandleDestroy (&lckLockIdHandleDatabase, res_lib_lck_resourceunlockasync->lockId);
536 break;
537 #ifdef NOT_DONE_YET
539 case MESSAGE_RES_LCK_RESOURCESYNCHRONIZEASYNC:
540 if (callbacks.saLckResourceSynchronizeCallback == NULL) {
541 continue;
544 res_lib_lck_resourcesynchronizeasync = (struct res_lib_lck_resourcesynchronizeasync *) &dispatch_data;
546 callbacks.saLckResourceSynchronizeCallback(
547 res_lib_lck_resourcesynchronizeasync->invocation,
548 res_lib_lck_resourcesynchronizeasync->header.error);
549 break;
550 #endif
552 default:
553 /* TODO */
554 break;
557 * Determine if more messages should be processed
559 switch (dispatchFlags) {
560 case SA_DISPATCH_ONE:
561 cont = 0;
562 break;
563 case SA_DISPATCH_ALL:
564 break;
565 case SA_DISPATCH_BLOCKING:
566 break;
568 } while (cont);
569 error_unlock:
570 pthread_mutex_unlock(&lckInstance->dispatch_mutex);
571 error_put:
572 saHandleInstancePut(&lckHandleDatabase, lckHandle);
573 error_exit:
574 return (error);
577 SaAisErrorT
578 saLckFinalize (
579 const SaLckHandleT lckHandle)
581 struct lckInstance *lckInstance;
582 SaAisErrorT error;
584 error = saHandleInstanceGet (&lckHandleDatabase, lckHandle,
585 (void *)&lckInstance);
586 if (error != SA_AIS_OK) {
587 return (error);
590 pthread_mutex_lock (&lckInstance->response_mutex);
593 * Another thread has already started finalizing
595 if (lckInstance->finalize) {
596 pthread_mutex_unlock (&lckInstance->response_mutex);
597 saHandleInstancePut (&lckHandleDatabase, lckHandle);
598 return (SA_AIS_ERR_BAD_HANDLE);
601 lckInstance->finalize = 1;
603 pthread_mutex_unlock (&lckInstance->response_mutex);
605 // TODO lckInstanceFinalize (lckInstance);
607 if (lckInstance->response_fd != -1) {
608 shutdown (lckInstance->response_fd, 0);
609 close (lckInstance->response_fd);
612 if (lckInstance->dispatch_fd != -1) {
613 shutdown (lckInstance->dispatch_fd, 0);
614 close (lckInstance->dispatch_fd);
617 saHandleInstancePut (&lckHandleDatabase, lckHandle);
619 return (SA_AIS_OK);
622 SaAisErrorT
623 saLckResourceOpen (
624 SaLckHandleT lckHandle,
625 const SaNameT *lockResourceName,
626 SaLckResourceOpenFlagsT resourceOpenFlags,
627 SaTimeT timeout,
628 SaLckResourceHandleT *lckResourceHandle)
630 SaAisErrorT error;
631 struct lckResourceInstance *lckResourceInstance;
632 struct lckInstance *lckInstance;
633 struct req_lib_lck_resourceopen req_lib_lck_resourceopen;
634 struct res_lib_lck_resourceopen res_lib_lck_resourceopen;
636 if (lckResourceHandle == NULL) {
637 return (SA_AIS_ERR_INVALID_PARAM);
640 if (lockResourceName == NULL) {
641 return (SA_AIS_ERR_INVALID_PARAM);
644 error = saHandleInstanceGet (&lckHandleDatabase, lckHandle,
645 (void *)&lckInstance);
646 if (error != SA_AIS_OK) {
647 goto error_exit;
650 error = saHandleCreate (&lckResourceHandleDatabase,
651 sizeof (struct lckResourceInstance), lckResourceHandle);
652 if (error != SA_AIS_OK) {
653 goto error_put_lck;
656 error = saHandleInstanceGet (&lckResourceHandleDatabase,
657 *lckResourceHandle, (void *)&lckResourceInstance);
658 if (error != SA_AIS_OK) {
659 goto error_destroy;
662 lckResourceInstance->response_fd = lckInstance->response_fd;
664 lckResourceInstance->lckHandle = lckHandle;
665 lckResourceInstance->lckResourceHandle = *lckResourceHandle;
666 lckResourceInstance->response_mutex = &lckInstance->response_mutex;
668 req_lib_lck_resourceopen.header.size = sizeof (struct req_lib_lck_resourceopen);
669 req_lib_lck_resourceopen.header.id = MESSAGE_REQ_LCK_RESOURCEOPEN;
671 marshall_to_mar_name_t (&req_lib_lck_resourceopen.lockResourceName, (SaNameT *)lockResourceName);
673 memcpy (&lckResourceInstance->lockResourceName, lockResourceName, sizeof(SaNameT));
674 req_lib_lck_resourceopen.resourceOpenFlags = resourceOpenFlags;
675 req_lib_lck_resourceopen.resourceHandle = *lckResourceHandle;
676 req_lib_lck_resourceopen.async_call = 0;
678 pthread_mutex_lock (&lckInstance->response_mutex);
680 error = saSendReceiveReply (lckResourceInstance->response_fd,
681 &req_lib_lck_resourceopen,
682 sizeof (struct req_lib_lck_resourceopen),
683 &res_lib_lck_resourceopen,
684 sizeof (struct res_lib_lck_resourceopen));
686 pthread_mutex_unlock (&lckInstance->response_mutex);
688 if (res_lib_lck_resourceopen.header.error != SA_AIS_OK) {
689 error = res_lib_lck_resourceopen.header.error;
690 goto error_put_destroy;
693 memcpy (&lckResourceInstance->source,
694 &res_lib_lck_resourceopen.source,
695 sizeof (mar_message_source_t));
697 saHandleInstancePut (&lckResourceHandleDatabase, *lckResourceHandle);
699 saHandleInstancePut (&lckHandleDatabase, lckHandle);
701 list_init (&lckResourceInstance->list);
703 list_add (&lckResourceInstance->list, &lckInstance->resource_list);
704 return (error);
706 error_put_destroy:
707 saHandleInstancePut (&lckResourceHandleDatabase, *lckResourceHandle);
708 error_destroy:
709 saHandleDestroy (&lckResourceHandleDatabase, *lckResourceHandle);
710 error_put_lck:
711 saHandleInstancePut (&lckHandleDatabase, lckHandle);
712 error_exit:
713 return (error);
716 SaAisErrorT
717 saLckResourceOpenAsync (
718 SaLckHandleT lckHandle,
719 SaInvocationT invocation,
720 const SaNameT *lockResourceName,
721 SaLckResourceOpenFlagsT resourceOpenFlags)
723 struct lckResourceInstance *lckResourceInstance;
724 struct lckInstance *lckInstance;
725 SaLckResourceHandleT lckResourceHandle;
726 SaAisErrorT error;
727 struct req_lib_lck_resourceopen req_lib_lck_resourceopen;
728 struct res_lib_lck_resourceopenasync res_lib_lck_resourceopenasync;
730 error = saHandleInstanceGet (&lckHandleDatabase, lckHandle,
731 (void *)&lckInstance);
732 if (error != SA_AIS_OK) {
733 goto error_exit;
736 if (lckInstance->callbacks.saLckResourceOpenCallback == NULL) {
737 error = SA_AIS_ERR_INIT;
738 goto error_put_lck;
741 error = saHandleCreate (&lckResourceHandleDatabase,
742 sizeof (struct lckResourceInstance), &lckResourceHandle);
743 if (error != SA_AIS_OK) {
744 goto error_put_lck;
747 error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
748 (void *)&lckResourceInstance);
749 if (error != SA_AIS_OK) {
750 goto error_destroy;
753 lckResourceInstance->response_fd = lckInstance->response_fd;
754 lckResourceInstance->response_mutex = &lckInstance->response_mutex;
755 lckResourceInstance->lckHandle = lckHandle;
756 lckResourceInstance->lckResourceHandle = lckResourceHandle;
757 lckResourceInstance->resourceOpenFlags = resourceOpenFlags;
759 memcpy (&lckResourceInstance->lockResourceName, lockResourceName, sizeof (SaNameT));
760 req_lib_lck_resourceopen.header.size = sizeof (struct req_lib_lck_resourceopen);
761 req_lib_lck_resourceopen.header.id = MESSAGE_REQ_LCK_RESOURCEOPENASYNC;
762 req_lib_lck_resourceopen.invocation = invocation;
763 req_lib_lck_resourceopen.resourceOpenFlags = resourceOpenFlags;
764 req_lib_lck_resourceopen.resourceHandle = lckResourceHandle;
765 req_lib_lck_resourceopen.async_call = 1;
767 pthread_mutex_lock (&lckInstance->response_mutex);
769 error = saSendReceiveReply (lckResourceInstance->response_fd,
770 &req_lib_lck_resourceopen,
771 sizeof (struct req_lib_lck_resourceopen),
772 &res_lib_lck_resourceopenasync,
773 sizeof (struct res_lib_lck_resourceopenasync));
775 pthread_mutex_unlock (&lckInstance->response_mutex);
777 if (error == SA_AIS_OK) {
778 saHandleInstancePut (&lckResourceHandleDatabase,
779 lckResourceHandle);
780 saHandleInstancePut (&lckHandleDatabase, lckHandle);
781 return (res_lib_lck_resourceopenasync.header.error);
784 saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
785 error_destroy:
786 saHandleDestroy (&lckResourceHandleDatabase, lckResourceHandle);
787 error_put_lck:
788 saHandleInstancePut (&lckHandleDatabase, lckHandle);
789 error_exit:
790 return (error);
793 SaAisErrorT
794 saLckResourceClose (
795 SaLckResourceHandleT lckResourceHandle)
797 struct req_lib_lck_resourceclose req_lib_lck_resourceclose;
798 struct res_lib_lck_resourceclose res_lib_lck_resourceclose;
799 SaAisErrorT error;
800 struct lckResourceInstance *lckResourceInstance;
802 error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
803 (void *)&lckResourceInstance);
804 if (error != SA_AIS_OK) {
805 return (error);
808 req_lib_lck_resourceclose.header.size = sizeof (struct req_lib_lck_resourceclose);
809 req_lib_lck_resourceclose.header.id = MESSAGE_REQ_LCK_RESOURCECLOSE;
810 marshall_to_mar_name_t (&req_lib_lck_resourceclose.lockResourceName,
811 &lckResourceInstance->lockResourceName);
812 req_lib_lck_resourceclose.resourceHandle = lckResourceHandle;
814 pthread_mutex_lock (lckResourceInstance->response_mutex);
816 error = saSendReceiveReply (lckResourceInstance->response_fd,
817 &req_lib_lck_resourceclose,
818 sizeof (struct req_lib_lck_resourceclose),
819 &res_lib_lck_resourceclose,
820 sizeof (struct res_lib_lck_resourceclose));
822 pthread_mutex_unlock (lckResourceInstance->response_mutex);
824 saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
826 saHandleDestroy (&lckResourceHandleDatabase, lckResourceHandle);
828 return (error == SA_AIS_OK ? res_lib_lck_resourceclose.header.error : error);
831 SaAisErrorT
832 saLckResourceLock (
833 SaLckResourceHandleT lckResourceHandle,
834 SaLckLockIdT *lockId,
835 SaLckLockModeT lockMode,
836 SaLckLockFlagsT lockFlags,
837 SaLckWaiterSignalT waiterSignal,
838 SaTimeT timeout,
839 SaLckLockStatusT *lockStatus)
841 struct req_lib_lck_resourcelock req_lib_lck_resourcelock;
842 struct res_lib_lck_resourcelock res_lib_lck_resourcelock;
843 SaAisErrorT error;
844 struct lckResourceInstance *lckResourceInstance;
845 struct lckLockIdInstance *lckLockIdInstance;
846 int lock_fd;
847 int dummy_fd;
849 error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
850 (void *)&lckResourceInstance);
851 if (error != SA_AIS_OK) {
852 return (error);
855 error = saHandleCreate (&lckLockIdHandleDatabase,
856 sizeof (struct lckLockIdInstance), lockId);
857 if (error != SA_AIS_OK) {
858 goto error_put_lck;
861 error = saHandleInstanceGet (&lckLockIdHandleDatabase, *lockId,
862 (void *)&lckLockIdInstance);
863 if (error != SA_AIS_OK) {
864 goto error_destroy;
867 error = saServiceConnect (&lock_fd, &dummy_fd, LCK_SERVICE);
868 if (error != SA_AIS_OK) { // TODO error handling
869 goto error_destroy;
872 lckLockIdInstance->response_mutex = lckResourceInstance->response_mutex;
873 lckLockIdInstance->response_fd = lckResourceInstance->response_fd;
874 lckLockIdInstance->lckResourceHandle = lckResourceHandle;
876 req_lib_lck_resourcelock.header.size = sizeof (struct req_lib_lck_resourcelock);
877 req_lib_lck_resourcelock.header.id = MESSAGE_REQ_LCK_RESOURCELOCK;
878 marshall_to_mar_name_t (&req_lib_lck_resourcelock.lockResourceName,
879 &lckResourceInstance->lockResourceName);
880 req_lib_lck_resourcelock.lockMode = lockMode;
881 req_lib_lck_resourcelock.lockFlags = lockFlags;
882 req_lib_lck_resourcelock.waiterSignal = waiterSignal;
883 req_lib_lck_resourcelock.lockId = *lockId;
884 req_lib_lck_resourcelock.async_call = 0;
885 req_lib_lck_resourcelock.invocation = 0;
886 req_lib_lck_resourcelock.resourceHandle = lckResourceHandle;
888 memcpy (&req_lib_lck_resourcelock.source,
889 &lckResourceInstance->source,
890 sizeof (mar_message_source_t));
893 * no mutex needed here since its a new connection
895 error = saSendReceiveReply (lock_fd,
896 &req_lib_lck_resourcelock,
897 sizeof (struct req_lib_lck_resourcelock),
898 &res_lib_lck_resourcelock,
899 sizeof (struct res_lib_lck_resourcelock));
901 close (lock_fd);
902 close (dummy_fd);
904 if (error == SA_AIS_OK) {
905 lckLockIdInstance->resource_lock = res_lib_lck_resourcelock.resource_lock;
906 *lockStatus = res_lib_lck_resourcelock.lockStatus;
908 return (res_lib_lck_resourcelock.header.error);
912 * Error
914 saHandleInstancePut (&lckLockIdHandleDatabase, *lockId);
916 error_destroy:
917 saHandleDestroy (&lckLockIdHandleDatabase, *lockId);
919 error_put_lck:
920 saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
921 return (error);
925 SaAisErrorT
926 saLckResourceLockAsync (
927 SaLckResourceHandleT lckResourceHandle,
928 SaInvocationT invocation,
929 SaLckLockIdT *lockId,
930 SaLckLockModeT lockMode,
931 SaLckLockFlagsT lockFlags,
932 SaLckWaiterSignalT waiterSignal)
934 struct req_lib_lck_resourcelock req_lib_lck_resourcelock;
935 struct res_lib_lck_resourcelockasync res_lib_lck_resourcelockasync;
936 SaAisErrorT error;
937 struct lckResourceInstance *lckResourceInstance;
938 struct lckLockIdInstance *lckLockIdInstance;
939 int lock_fd;
940 int dummy_fd;
942 error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
943 (void *)&lckResourceInstance);
944 if (error != SA_AIS_OK) {
945 return (error);
948 error = saHandleCreate (&lckLockIdHandleDatabase,
949 sizeof (struct lckLockIdInstance), lockId);
950 if (error != SA_AIS_OK) {
951 goto error_put_lck;
954 error = saHandleInstanceGet (&lckLockIdHandleDatabase, *lockId,
955 (void *)&lckLockIdInstance);
956 if (error != SA_AIS_OK) {
957 goto error_destroy;
960 error = saServiceConnect (&lock_fd, &dummy_fd, LCK_SERVICE);
961 if (error != SA_AIS_OK) { // TODO error handling
962 goto error_destroy;
965 lckLockIdInstance->response_mutex = lckResourceInstance->response_mutex;
966 lckLockIdInstance->response_fd = lckResourceInstance->response_fd;
967 lckLockIdInstance->lckResourceHandle = lckResourceHandle;
969 req_lib_lck_resourcelock.header.size = sizeof (struct req_lib_lck_resourcelock);
970 req_lib_lck_resourcelock.header.id = MESSAGE_REQ_LCK_RESOURCELOCKASYNC;
971 marshall_to_mar_name_t (&req_lib_lck_resourcelock.lockResourceName,
972 &lckResourceInstance->lockResourceName);
973 req_lib_lck_resourcelock.lockMode = lockMode;
974 req_lib_lck_resourcelock.lockFlags = lockFlags;
975 req_lib_lck_resourcelock.waiterSignal = waiterSignal;
976 req_lib_lck_resourcelock.lockId = *lockId;
977 req_lib_lck_resourcelock.async_call = 1;
978 req_lib_lck_resourcelock.invocation = invocation;
979 req_lib_lck_resourcelock.resourceHandle = lckResourceHandle;
981 memcpy (&req_lib_lck_resourcelock.source,
982 &lckResourceInstance->source,
983 sizeof (mar_message_source_t));
986 * no mutex needed here since its a new connection
988 error = saSendReceiveReply (lock_fd,
989 &req_lib_lck_resourcelock,
990 sizeof (struct req_lib_lck_resourcelock),
991 &res_lib_lck_resourcelockasync,
992 sizeof (struct res_lib_lck_resourcelock));
994 close (lock_fd);
995 close (dummy_fd);
997 if (error == SA_AIS_OK) {
998 return (res_lib_lck_resourcelockasync.header.error);
1002 * Error
1004 saHandleInstancePut (&lckLockIdHandleDatabase, *lockId);
1006 error_destroy:
1007 saHandleDestroy (&lckLockIdHandleDatabase, *lockId);
1009 error_put_lck:
1010 saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
1011 return (error);
1014 SaAisErrorT
1015 saLckResourceUnlock (
1016 SaLckLockIdT lockId,
1017 SaTimeT timeout)
1019 struct req_lib_lck_resourceunlock req_lib_lck_resourceunlock;
1020 struct res_lib_lck_resourceunlock res_lib_lck_resourceunlock;
1021 SaAisErrorT error;
1022 struct lckLockIdInstance *lckLockIdInstance;
1023 struct lckResourceInstance *lckResourceInstance;
1025 error = saHandleInstanceGet (&lckLockIdHandleDatabase, lockId,
1026 (void *)&lckLockIdInstance);
1027 if (error != SA_AIS_OK) {
1028 return (error);
1032 * Retrieve resource name
1034 error = saHandleInstanceGet (&lckResourceHandleDatabase,
1035 lckLockIdInstance->lckResourceHandle, (void *)&lckResourceInstance);
1036 if (error != SA_AIS_OK) {
1037 saHandleInstancePut (&lckLockIdHandleDatabase, lockId);
1038 return (error);
1041 marshall_to_mar_name_t (&req_lib_lck_resourceunlock.lockResourceName,
1042 &lckResourceInstance->lockResourceName);
1044 saHandleInstancePut (&lckResourceHandleDatabase,
1045 lckLockIdInstance->lckResourceHandle);
1047 req_lib_lck_resourceunlock.header.size = sizeof (struct req_lib_lck_resourceunlock);
1048 req_lib_lck_resourceunlock.header.id = MESSAGE_REQ_LCK_RESOURCEUNLOCK;
1049 req_lib_lck_resourceunlock.lockId = lockId;
1050 req_lib_lck_resourceunlock.timeout = timeout;
1051 req_lib_lck_resourceunlock.invocation = -1;
1052 req_lib_lck_resourceunlock.async_call = 0;
1053 req_lib_lck_resourceunlock.resource_lock = lckLockIdInstance->resource_lock;
1055 pthread_mutex_lock (lckLockIdInstance->response_mutex);
1057 error = saSendReceiveReply (lckLockIdInstance->response_fd,
1058 &req_lib_lck_resourceunlock,
1059 sizeof (struct req_lib_lck_resourceunlock),
1060 &res_lib_lck_resourceunlock,
1061 sizeof (struct res_lib_lck_resourceunlock));
1063 pthread_mutex_unlock (lckLockIdInstance->response_mutex);
1065 saHandleInstancePut (&lckLockIdHandleDatabase, lockId);
1067 saHandleDestroy (&lckLockIdHandleDatabase, lockId);
1069 return (error == SA_AIS_OK ? res_lib_lck_resourceunlock.header.error : error);
1072 SaAisErrorT
1073 saLckResourceUnlockAsync (
1074 SaInvocationT invocation,
1075 SaLckLockIdT lockId)
1077 struct req_lib_lck_resourceunlock req_lib_lck_resourceunlock;
1078 struct res_lib_lck_resourceunlockasync res_lib_lck_resourceunlockasync;
1079 SaAisErrorT error;
1080 struct lckLockIdInstance *lckLockIdInstance;
1081 struct lckResourceInstance *lckResourceInstance;
1083 error = saHandleInstanceGet (&lckLockIdHandleDatabase, lockId,
1084 (void *)&lckLockIdInstance);
1085 if (error != SA_AIS_OK) {
1086 return (error);
1090 * Retrieve resource name
1092 error = saHandleInstanceGet (&lckResourceHandleDatabase,
1093 lckLockIdInstance->lckResourceHandle, (void *)&lckResourceInstance);
1094 if (error != SA_AIS_OK) {
1095 saHandleInstancePut (&lckLockIdHandleDatabase, lockId);
1096 return (error);
1099 marshall_to_mar_name_t (&req_lib_lck_resourceunlock.lockResourceName,
1100 &lckResourceInstance->lockResourceName);
1102 saHandleInstancePut (&lckResourceHandleDatabase,
1103 lckLockIdInstance->lckResourceHandle);
1107 * Build and send request
1109 req_lib_lck_resourceunlock.header.size = sizeof (struct req_lib_lck_resourceunlock);
1110 req_lib_lck_resourceunlock.header.id = MESSAGE_REQ_LCK_RESOURCEUNLOCKASYNC;
1111 req_lib_lck_resourceunlock.invocation = invocation;
1112 req_lib_lck_resourceunlock.lockId = lockId;
1113 req_lib_lck_resourceunlock.async_call = 1;
1115 pthread_mutex_lock (lckLockIdInstance->response_mutex);
1117 error = saSendReceiveReply (lckLockIdInstance->response_fd,
1118 &req_lib_lck_resourceunlock,
1119 sizeof (struct req_lib_lck_resourceunlock),
1120 &res_lib_lck_resourceunlockasync,
1121 sizeof (struct res_lib_lck_resourceunlockasync));
1123 pthread_mutex_unlock (lckLockIdInstance->response_mutex);
1125 saHandleInstancePut (&lckLockIdHandleDatabase, lockId);
1127 return (error == SA_AIS_OK ? res_lib_lck_resourceunlockasync.header.error : error);
1130 SaAisErrorT
1131 saLckLockPurge (
1132 SaLckResourceHandleT lckResourceHandle)
1134 struct req_lib_lck_lockpurge req_lib_lck_lockpurge;
1135 struct res_lib_lck_lockpurge res_lib_lck_lockpurge;
1136 SaAisErrorT error;
1137 struct lckResourceInstance *lckResourceInstance;
1139 error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
1140 (void *)&lckResourceInstance);
1141 if (error != SA_AIS_OK) {
1142 return (error);
1145 req_lib_lck_lockpurge.header.size = sizeof (struct req_lib_lck_lockpurge);
1146 req_lib_lck_lockpurge.header.id = MESSAGE_REQ_LCK_LOCKPURGE;
1147 marshall_to_mar_name_t (&req_lib_lck_lockpurge.lockResourceName,
1148 &lckResourceInstance->lockResourceName);
1150 pthread_mutex_lock (lckResourceInstance->response_mutex);
1152 error = saSendReceiveReply (lckResourceInstance->response_fd,
1153 &req_lib_lck_lockpurge,
1154 sizeof (struct req_lib_lck_lockpurge),
1155 &res_lib_lck_lockpurge,
1156 sizeof (struct res_lib_lck_lockpurge));
1158 pthread_mutex_unlock (lckResourceInstance->response_mutex);
1160 saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
1162 return (error == SA_AIS_OK ? res_lib_lck_lockpurge.header.error : error);