lck.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160
  1. /*
  2. * Copyright (c) 2005 MontaVista Software, Inc.
  3. *
  4. * All rights reserved.
  5. *
  6. * Author: Steven Dake (sdake@mvista.com)
  7. *
  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:
  12. *
  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.
  21. *
  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.
  33. */
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <stdlib.h>
  37. #include <assert.h>
  38. #include <unistd.h>
  39. #include <errno.h>
  40. #include <pthread.h>
  41. #include <sys/types.h>
  42. #include <sys/uio.h>
  43. #include <sys/socket.h>
  44. #include <sys/select.h>
  45. #include <sys/un.h>
  46. #include "../include/saAis.h"
  47. #include "../include/list.h"
  48. #include "../include/saLck.h"
  49. #include "../include/ipc_gen.h"
  50. #include "../include/ipc_lck.h"
  51. #include "util.h"
  52. struct message_overlay {
  53. mar_res_header_t header __attribute__((aligned(8)));
  54. char data[4096];
  55. };
  56. /*
  57. * Data structure for instance data
  58. */
  59. struct lckInstance {
  60. int response_fd;
  61. int dispatch_fd;
  62. SaLckCallbacksT callbacks;
  63. int finalize;
  64. SaLckHandleT lckHandle;
  65. struct list_head resource_list;
  66. pthread_mutex_t response_mutex;
  67. pthread_mutex_t dispatch_mutex;
  68. };
  69. struct lckResourceInstance {
  70. int response_fd;
  71. SaLckHandleT lckHandle;
  72. SaLckResourceHandleT lckResourceHandle;
  73. SaLckResourceOpenFlagsT resourceOpenFlags;
  74. SaNameT lockResourceName;
  75. struct list_head list;
  76. mar_message_source_t source;
  77. pthread_mutex_t *response_mutex;
  78. };
  79. struct lckLockIdInstance {
  80. int response_fd;
  81. SaLckResourceHandleT lckResourceHandle;
  82. struct list_head list;
  83. void *resource_lock;
  84. pthread_mutex_t *response_mutex;
  85. };
  86. void lckHandleInstanceDestructor (void *instance);
  87. void lckResourceHandleInstanceDestructor (void *instance);
  88. void lckResourceHandleLockIdInstanceDestructor (void *instance);
  89. /*
  90. * All LCK instances in this database
  91. */
  92. static struct saHandleDatabase lckHandleDatabase = {
  93. .handleCount = 0,
  94. .handles = 0,
  95. .mutex = PTHREAD_MUTEX_INITIALIZER,
  96. .handleInstanceDestructor = lckHandleInstanceDestructor
  97. };
  98. /*
  99. * All Resource instances in this database
  100. */
  101. static struct saHandleDatabase lckResourceHandleDatabase = {
  102. .handleCount = 0,
  103. .handles = 0,
  104. .mutex = PTHREAD_MUTEX_INITIALIZER,
  105. .handleInstanceDestructor = lckResourceHandleInstanceDestructor
  106. };
  107. /*
  108. * All Resource Lock Identifier instances in this database
  109. */
  110. static struct saHandleDatabase lckLockIdHandleDatabase = {
  111. .handleCount = 0,
  112. .handles = 0,
  113. .mutex = PTHREAD_MUTEX_INITIALIZER,
  114. .handleInstanceDestructor = lckResourceHandleLockIdInstanceDestructor
  115. };
  116. /*
  117. * Versions supported
  118. */
  119. static SaVersionT lckVersionsSupported[] = {
  120. { 'B', 1, 1 }
  121. };
  122. static struct saVersionDatabase lckVersionDatabase = {
  123. sizeof (lckVersionsSupported) / sizeof (SaVersionT),
  124. lckVersionsSupported
  125. };
  126. /*
  127. * Implementation
  128. */
  129. void lckHandleInstanceDestructor (void *instance)
  130. {
  131. }
  132. void lckResourceHandleInstanceDestructor (void *instance)
  133. {
  134. return;
  135. }
  136. void lckResourceHandleLockIdInstanceDestructor (void *instance)
  137. {
  138. }
  139. #ifdef NOT_DONE
  140. static void lckSectionIterationInstanceFinalize (struct lckSectionIterationInstance *lckSectionIterationInstance)
  141. {
  142. struct iteratorSectionIdListEntry *iteratorSectionIdListEntry;
  143. struct list_head *sectionIdIterationList;
  144. struct list_head *sectionIdIterationListNext;
  145. /*
  146. * iterate list of section ids for this iterator to free the allocated memory
  147. * be careful to cache next pointer because free removes memory from use
  148. */
  149. for (sectionIdIterationList = lckSectionIterationInstance->sectionIdListHead.next,
  150. sectionIdIterationListNext = sectionIdIterationList->next;
  151. sectionIdIterationList != &lckSectionIterationInstance->sectionIdListHead;
  152. sectionIdIterationList = sectionIdIterationListNext,
  153. sectionIdIterationListNext = sectionIdIterationList->next) {
  154. iteratorSectionIdListEntry = list_entry (sectionIdIterationList,
  155. struct iteratorSectionIdListEntry, list);
  156. free (iteratorSectionIdListEntry);
  157. }
  158. list_del (&lckSectionIterationInstance->list);
  159. saHandleDestroy (&lckSectionIterationHandleDatabase,
  160. lckSectionIterationInstance->sectionIterationHandle);
  161. }
  162. static void lckResourceInstanceFinalize (struct lckResourceInstance *lckResourceInstance)
  163. {
  164. struct lckSectionIterationInstance *sectionIterationInstance;
  165. struct list_head *sectionIterationList;
  166. struct list_head *sectionIterationListNext;
  167. for (sectionIterationList = lckResourceInstance->section_iteration_list_head.next,
  168. sectionIterationListNext = sectionIterationList->next;
  169. sectionIterationList != &lckResourceInstance->section_iteration_list_head;
  170. sectionIterationList = sectionIterationListNext,
  171. sectionIterationListNext = sectionIterationList->next) {
  172. sectionIterationInstance = list_entry (sectionIterationList,
  173. struct lckSectionIterationInstance, list);
  174. lckSectionIterationInstanceFinalize (sectionIterationInstance);
  175. }
  176. list_del (&lckResourceInstance->list);
  177. saHandleDestroy (&lckResourceHandleDatabase, lckResourceInstance->lckResourceHandle);
  178. }
  179. static void lckInstanceFinalize (struct lckInstance *lckInstance)
  180. {
  181. struct lckResourceInstance *lckResourceInstance;
  182. struct list_head *resourceInstanceList;
  183. struct list_head *resourceInstanceListNext;
  184. for (resourceInstanceList = lckInstance->resource_list.next,
  185. resourceInstanceListNext = resourceInstanceList->next;
  186. resourceInstanceList != &lckInstance->resource_list;
  187. resourceInstanceList = resourceInstanceListNext,
  188. resourceInstanceListNext = resourceInstanceList->next) {
  189. lckResourceInstance = list_entry (resourceInstanceList,
  190. struct lckResourceInstance, list);
  191. lckResourceInstanceFinalize (lckResourceInstance);
  192. }
  193. saHandleDestroy (&lckHandleDatabase, lckInstance->lckHandle);
  194. }
  195. #endif
  196. SaAisErrorT
  197. saLckInitialize (
  198. SaLckHandleT *lckHandle,
  199. const SaLckCallbacksT *callbacks,
  200. SaVersionT *version)
  201. {
  202. struct lckInstance *lckInstance;
  203. SaAisErrorT error = SA_AIS_OK;
  204. if (lckHandle == NULL) {
  205. return (SA_AIS_ERR_INVALID_PARAM);
  206. }
  207. error = saVersionVerify (&lckVersionDatabase, version);
  208. if (error != SA_AIS_OK) {
  209. goto error_no_destroy;
  210. }
  211. error = saHandleCreate (&lckHandleDatabase, sizeof (struct lckInstance),
  212. lckHandle);
  213. if (error != SA_AIS_OK) {
  214. goto error_no_destroy;
  215. }
  216. error = saHandleInstanceGet (&lckHandleDatabase, *lckHandle,
  217. (void *)&lckInstance);
  218. if (error != SA_AIS_OK) {
  219. goto error_destroy;
  220. }
  221. lckInstance->response_fd = -1;
  222. error = saServiceConnect (&lckInstance->response_fd,
  223. &lckInstance->dispatch_fd, LCK_SERVICE);
  224. if (error != SA_AIS_OK) {
  225. goto error_put_destroy;
  226. }
  227. if (callbacks) {
  228. memcpy (&lckInstance->callbacks, callbacks, sizeof (SaLckCallbacksT));
  229. } else {
  230. memset (&lckInstance->callbacks, 0, sizeof (SaLckCallbacksT));
  231. }
  232. list_init (&lckInstance->resource_list);
  233. lckInstance->lckHandle = *lckHandle;
  234. pthread_mutex_init (&lckInstance->response_mutex, NULL);
  235. saHandleInstancePut (&lckHandleDatabase, *lckHandle);
  236. return (SA_AIS_OK);
  237. error_put_destroy:
  238. saHandleInstancePut (&lckHandleDatabase, *lckHandle);
  239. error_destroy:
  240. saHandleDestroy (&lckHandleDatabase, *lckHandle);
  241. error_no_destroy:
  242. return (error);
  243. }
  244. SaAisErrorT
  245. saLckSelectionObjectGet (
  246. const SaLckHandleT lckHandle,
  247. SaSelectionObjectT *selectionObject)
  248. {
  249. struct lckInstance *lckInstance;
  250. SaAisErrorT error;
  251. if (selectionObject == NULL) {
  252. return (SA_AIS_ERR_INVALID_PARAM);
  253. }
  254. error = saHandleInstanceGet (&lckHandleDatabase, lckHandle, (void *)&lckInstance);
  255. if (error != SA_AIS_OK) {
  256. return (error);
  257. }
  258. *selectionObject = lckInstance->dispatch_fd;
  259. saHandleInstancePut (&lckHandleDatabase, lckHandle);
  260. return (SA_AIS_OK);
  261. }
  262. SaAisErrorT
  263. saLckOptionCheck (
  264. SaLckHandleT lckHandle,
  265. SaLckOptionsT *lckOptions)
  266. {
  267. return (SA_AIS_OK);
  268. }
  269. SaAisErrorT
  270. saLckDispatch (
  271. const SaLckHandleT lckHandle,
  272. SaDispatchFlagsT dispatchFlags)
  273. {
  274. struct pollfd ufds;
  275. int poll_fd;
  276. int timeout = 1;
  277. SaLckCallbacksT callbacks;
  278. SaAisErrorT error;
  279. int dispatch_avail;
  280. struct lckInstance *lckInstance;
  281. struct lckResourceInstance *lckResourceInstance;
  282. struct lckLockIdInstance *lckLockIdInstance;
  283. int cont = 1; /* always continue do loop except when set to 0 */
  284. struct message_overlay dispatch_data;
  285. struct res_lib_lck_lockwaitercallback *res_lib_lck_lockwaitercallback;
  286. struct res_lib_lck_resourceopenasync *res_lib_lck_resourceopenasync = NULL;
  287. struct res_lib_lck_resourcelockasync *res_lib_lck_resourcelockasync = NULL;
  288. struct res_lib_lck_resourceunlockasync *res_lib_lck_resourceunlockasync;
  289. if (dispatchFlags != SA_DISPATCH_ONE &&
  290. dispatchFlags != SA_DISPATCH_ALL &&
  291. dispatchFlags != SA_DISPATCH_BLOCKING) {
  292. return (SA_AIS_ERR_INVALID_PARAM);
  293. }
  294. error = saHandleInstanceGet (&lckHandleDatabase, lckHandle,
  295. (void *)&lckInstance);
  296. if (error != SA_AIS_OK) {
  297. goto error_exit;
  298. }
  299. /*
  300. * Timeout instantly for SA_DISPATCH_ALL
  301. */
  302. if (dispatchFlags == SA_DISPATCH_ALL) {
  303. timeout = 0;
  304. }
  305. do {
  306. /*
  307. * Read data directly from socket
  308. */
  309. poll_fd = lckInstance->dispatch_fd;
  310. ufds.fd = poll_fd;
  311. ufds.events = POLLIN;
  312. ufds.revents = 0;
  313. error = saPollRetry(&ufds, 1, timeout);
  314. if (error != SA_AIS_OK) {
  315. goto error_put;
  316. }
  317. pthread_mutex_lock(&lckInstance->dispatch_mutex);
  318. if (lckInstance->finalize == 1) {
  319. error = SA_AIS_OK;
  320. goto error_unlock;
  321. }
  322. if ((ufds.revents & (POLLERR|POLLHUP|POLLNVAL)) != 0) {
  323. error = SA_AIS_ERR_BAD_HANDLE;
  324. goto error_unlock;
  325. }
  326. dispatch_avail = (ufds.revents & POLLIN);
  327. if (dispatch_avail == 0 && dispatchFlags == SA_DISPATCH_ALL) {
  328. pthread_mutex_unlock(&lckInstance->dispatch_mutex);
  329. break; /* exit do while cont is 1 loop */
  330. } else
  331. if (dispatch_avail == 0) {
  332. pthread_mutex_unlock(&lckInstance->dispatch_mutex);
  333. continue;
  334. }
  335. memset(&dispatch_data,0, sizeof(struct message_overlay));
  336. error = saRecvRetry (lckInstance->dispatch_fd, &dispatch_data.header, sizeof (mar_res_header_t));
  337. if (error != SA_AIS_OK) {
  338. goto error_unlock;
  339. }
  340. if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
  341. error = saRecvRetry (lckInstance->dispatch_fd, &dispatch_data.data,
  342. dispatch_data.header.size - sizeof (mar_res_header_t));
  343. if (error != SA_AIS_OK) {
  344. goto error_unlock;
  345. }
  346. }
  347. /*
  348. * Make copy of callbacks, message data, unlock instance,
  349. * and call callback. A risk of this dispatch method is that
  350. * the callback routines may operate at the same time that
  351. * LckFinalize has been called in another thread.
  352. */
  353. memcpy(&callbacks,&lckInstance->callbacks, sizeof(lckInstance->callbacks));
  354. pthread_mutex_unlock(&lckInstance->dispatch_mutex);
  355. /*
  356. * Dispatch incoming response
  357. */
  358. switch (dispatch_data.header.id) {
  359. case MESSAGE_RES_LCK_LOCKWAITERCALLBACK:
  360. if (callbacks.saLckResourceOpenCallback == NULL) {
  361. continue;
  362. }
  363. res_lib_lck_lockwaitercallback = (struct res_lib_lck_lockwaitercallback *)&dispatch_data;
  364. callbacks.saLckLockWaiterCallback (
  365. res_lib_lck_lockwaitercallback->waiter_signal,
  366. res_lib_lck_lockwaitercallback->lock_id,
  367. res_lib_lck_lockwaitercallback->mode_held,
  368. res_lib_lck_lockwaitercallback->mode_requested);
  369. break;
  370. case MESSAGE_RES_LCK_RESOURCEOPENASYNC:
  371. if (callbacks.saLckLockWaiterCallback == NULL) {
  372. continue;
  373. }
  374. res_lib_lck_resourceopenasync = (struct res_lib_lck_resourceopenasync *)&dispatch_data;
  375. /*
  376. * This instance get/listadd/put required so that close
  377. * later has the proper list of resources
  378. */
  379. if (res_lib_lck_resourceopenasync->header.error == SA_AIS_OK) {
  380. error = saHandleInstanceGet (&lckResourceHandleDatabase,
  381. res_lib_lck_resourceopenasync->resourceHandle,
  382. (void *)&lckResourceInstance);
  383. assert (error == SA_AIS_OK); /* should only be valid handles here */
  384. /*
  385. * open succeeded without error
  386. */
  387. callbacks.saLckResourceOpenCallback(
  388. res_lib_lck_resourceopenasync->invocation,
  389. res_lib_lck_resourceopenasync->resourceHandle,
  390. res_lib_lck_resourceopenasync->header.error);
  391. saHandleInstancePut (&lckResourceHandleDatabase,
  392. res_lib_lck_resourceopenasync->resourceHandle);
  393. } else {
  394. /*
  395. * open failed with error
  396. */
  397. callbacks.saLckResourceOpenCallback(
  398. res_lib_lck_resourceopenasync->invocation,
  399. -1,
  400. res_lib_lck_resourceopenasync->header.error);
  401. }
  402. break;
  403. case MESSAGE_RES_LCK_RESOURCELOCKASYNC:
  404. DPRINT (("grant\n"));
  405. if (callbacks.saLckLockGrantCallback == NULL) {
  406. continue;
  407. }
  408. res_lib_lck_resourcelockasync = (struct res_lib_lck_resourcelockasync *)&dispatch_data;
  409. /*
  410. * This instance get/listadd/put required so that close
  411. * later has the proper list of resources
  412. */
  413. if (res_lib_lck_resourcelockasync->header.error == SA_AIS_OK) {
  414. error = saHandleInstanceGet (&lckLockIdHandleDatabase,
  415. res_lib_lck_resourcelockasync->lockId,
  416. (void *)&lckLockIdInstance);
  417. assert (error == SA_AIS_OK); /* should only be valid handles here */
  418. /*
  419. * open succeeded without error
  420. */
  421. lckLockIdInstance->resource_lock = res_lib_lck_resourcelockasync->resource_lock;
  422. callbacks.saLckLockGrantCallback(
  423. res_lib_lck_resourcelockasync->invocation,
  424. res_lib_lck_resourcelockasync->lockStatus,
  425. res_lib_lck_resourcelockasync->header.error);
  426. saHandleInstancePut (&lckLockIdHandleDatabase,
  427. res_lib_lck_resourcelockasync->lockId);
  428. } else {
  429. /*
  430. * open failed with error
  431. */
  432. callbacks.saLckLockGrantCallback (
  433. res_lib_lck_resourceopenasync->invocation,
  434. -1,
  435. res_lib_lck_resourceopenasync->header.error);
  436. }
  437. break;
  438. case MESSAGE_RES_LCK_RESOURCEUNLOCKASYNC:
  439. if (callbacks.saLckResourceUnlockCallback == NULL) {
  440. continue;
  441. }
  442. res_lib_lck_resourceunlockasync = (struct res_lib_lck_resourceunlockasync *)&dispatch_data;
  443. callbacks.saLckResourceUnlockCallback (
  444. res_lib_lck_resourceunlockasync->invocation,
  445. res_lib_lck_resourceunlockasync->header.error);
  446. if (res_lib_lck_resourcelockasync->header.error == SA_AIS_OK) {
  447. error = saHandleInstanceGet (&lckLockIdHandleDatabase,
  448. res_lib_lck_resourceunlockasync->lockId,
  449. (void *)&lckLockIdInstance);
  450. if (error == SA_AIS_OK) {
  451. saHandleInstancePut (&lckLockIdHandleDatabase, res_lib_lck_resourceunlockasync->lockId);
  452. saHandleDestroy (&lckLockIdHandleDatabase, res_lib_lck_resourceunlockasync->lockId);
  453. }
  454. }
  455. break;
  456. #ifdef NOT_DONE_YET
  457. case MESSAGE_RES_LCK_RESOURCESYNCHRONIZEASYNC:
  458. if (callbacks.saLckResourceSynchronizeCallback == NULL) {
  459. continue;
  460. }
  461. res_lib_lck_resourcesynchronizeasync = (struct res_lib_lck_resourcesynchronizeasync *) &dispatch_data;
  462. callbacks.saLckResourceSynchronizeCallback(
  463. res_lib_lck_resourcesynchronizeasync->invocation,
  464. res_lib_lck_resourcesynchronizeasync->header.error);
  465. break;
  466. #endif
  467. default:
  468. /* TODO */
  469. break;
  470. }
  471. /*
  472. * Determine if more messages should be processed
  473. */
  474. switch (dispatchFlags) {
  475. case SA_DISPATCH_ONE:
  476. cont = 0;
  477. break;
  478. case SA_DISPATCH_ALL:
  479. break;
  480. case SA_DISPATCH_BLOCKING:
  481. break;
  482. }
  483. } while (cont);
  484. error_unlock:
  485. pthread_mutex_unlock(&lckInstance->dispatch_mutex);
  486. error_put:
  487. saHandleInstancePut(&lckHandleDatabase, lckHandle);
  488. error_exit:
  489. return (error);
  490. }
  491. SaAisErrorT
  492. saLckFinalize (
  493. const SaLckHandleT lckHandle)
  494. {
  495. struct lckInstance *lckInstance;
  496. SaAisErrorT error;
  497. error = saHandleInstanceGet (&lckHandleDatabase, lckHandle,
  498. (void *)&lckInstance);
  499. if (error != SA_AIS_OK) {
  500. return (error);
  501. }
  502. pthread_mutex_lock (&lckInstance->response_mutex);
  503. /*
  504. * Another thread has already started finalizing
  505. */
  506. if (lckInstance->finalize) {
  507. pthread_mutex_unlock (&lckInstance->response_mutex);
  508. saHandleInstancePut (&lckHandleDatabase, lckHandle);
  509. return (SA_AIS_ERR_BAD_HANDLE);
  510. }
  511. lckInstance->finalize = 1;
  512. pthread_mutex_unlock (&lckInstance->response_mutex);
  513. // TODO lckInstanceFinalize (lckInstance);
  514. if (lckInstance->response_fd != -1) {
  515. shutdown (lckInstance->response_fd, 0);
  516. close (lckInstance->response_fd);
  517. }
  518. if (lckInstance->dispatch_fd != -1) {
  519. shutdown (lckInstance->dispatch_fd, 0);
  520. close (lckInstance->dispatch_fd);
  521. }
  522. saHandleInstancePut (&lckHandleDatabase, lckHandle);
  523. return (SA_AIS_OK);
  524. }
  525. SaAisErrorT
  526. saLckResourceOpen (
  527. SaLckHandleT lckHandle,
  528. const SaNameT *lockResourceName,
  529. SaLckResourceOpenFlagsT resourceOpenFlags,
  530. SaTimeT timeout,
  531. SaLckResourceHandleT *lckResourceHandle)
  532. {
  533. SaAisErrorT error;
  534. struct lckResourceInstance *lckResourceInstance;
  535. struct lckInstance *lckInstance;
  536. struct req_lib_lck_resourceopen req_lib_lck_resourceopen;
  537. struct res_lib_lck_resourceopen res_lib_lck_resourceopen;
  538. if (lckResourceHandle == NULL) {
  539. return (SA_AIS_ERR_INVALID_PARAM);
  540. }
  541. if (lockResourceName == NULL) {
  542. return (SA_AIS_ERR_INVALID_PARAM);
  543. }
  544. error = saHandleInstanceGet (&lckHandleDatabase, lckHandle,
  545. (void *)&lckInstance);
  546. if (error != SA_AIS_OK) {
  547. goto error_exit;
  548. }
  549. error = saHandleCreate (&lckResourceHandleDatabase,
  550. sizeof (struct lckResourceInstance), lckResourceHandle);
  551. if (error != SA_AIS_OK) {
  552. goto error_put_lck;
  553. }
  554. error = saHandleInstanceGet (&lckResourceHandleDatabase,
  555. *lckResourceHandle, (void *)&lckResourceInstance);
  556. if (error != SA_AIS_OK) {
  557. goto error_destroy;
  558. }
  559. lckResourceInstance->response_fd = lckInstance->response_fd;
  560. lckResourceInstance->lckHandle = lckHandle;
  561. lckResourceInstance->lckResourceHandle = *lckResourceHandle;
  562. lckResourceInstance->response_mutex = &lckInstance->response_mutex;
  563. req_lib_lck_resourceopen.header.size = sizeof (struct req_lib_lck_resourceopen);
  564. req_lib_lck_resourceopen.header.id = MESSAGE_REQ_LCK_RESOURCEOPEN;
  565. marshall_to_mar_name_t (&req_lib_lck_resourceopen.lockResourceName, (SaNameT *)lockResourceName);
  566. memcpy (&lckResourceInstance->lockResourceName, lockResourceName, sizeof(SaNameT));
  567. req_lib_lck_resourceopen.resourceOpenFlags = resourceOpenFlags;
  568. req_lib_lck_resourceopen.resourceHandle = *lckResourceHandle;
  569. req_lib_lck_resourceopen.async_call = 0;
  570. pthread_mutex_lock (&lckInstance->response_mutex);
  571. error = saSendReceiveReply (lckResourceInstance->response_fd,
  572. &req_lib_lck_resourceopen,
  573. sizeof (struct req_lib_lck_resourceopen),
  574. &res_lib_lck_resourceopen,
  575. sizeof (struct res_lib_lck_resourceopen));
  576. pthread_mutex_unlock (&lckInstance->response_mutex);
  577. if (res_lib_lck_resourceopen.header.error != SA_AIS_OK) {
  578. error = res_lib_lck_resourceopen.header.error;
  579. goto error_put_destroy;
  580. }
  581. memcpy (&lckResourceInstance->source,
  582. &res_lib_lck_resourceopen.source,
  583. sizeof (mar_message_source_t));
  584. saHandleInstancePut (&lckResourceHandleDatabase, *lckResourceHandle);
  585. saHandleInstancePut (&lckHandleDatabase, lckHandle);
  586. list_init (&lckResourceInstance->list);
  587. list_add (&lckResourceInstance->list, &lckInstance->resource_list);
  588. return (error);
  589. error_put_destroy:
  590. saHandleInstancePut (&lckResourceHandleDatabase, *lckResourceHandle);
  591. error_destroy:
  592. saHandleDestroy (&lckResourceHandleDatabase, *lckResourceHandle);
  593. error_put_lck:
  594. saHandleInstancePut (&lckHandleDatabase, lckHandle);
  595. error_exit:
  596. return (error);
  597. }
  598. SaAisErrorT
  599. saLckResourceOpenAsync (
  600. SaLckHandleT lckHandle,
  601. SaInvocationT invocation,
  602. const SaNameT *lockResourceName,
  603. SaLckResourceOpenFlagsT resourceOpenFlags)
  604. {
  605. struct lckResourceInstance *lckResourceInstance;
  606. struct lckInstance *lckInstance;
  607. SaLckResourceHandleT lckResourceHandle;
  608. SaAisErrorT error;
  609. struct req_lib_lck_resourceopen req_lib_lck_resourceopen;
  610. struct res_lib_lck_resourceopenasync res_lib_lck_resourceopenasync;
  611. error = saHandleInstanceGet (&lckHandleDatabase, lckHandle,
  612. (void *)&lckInstance);
  613. if (error != SA_AIS_OK) {
  614. goto error_exit;
  615. }
  616. if (lckInstance->callbacks.saLckResourceOpenCallback == NULL) {
  617. error = SA_AIS_ERR_INIT;
  618. goto error_put_lck;
  619. }
  620. error = saHandleCreate (&lckResourceHandleDatabase,
  621. sizeof (struct lckResourceInstance), &lckResourceHandle);
  622. if (error != SA_AIS_OK) {
  623. goto error_put_lck;
  624. }
  625. error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
  626. (void *)&lckResourceInstance);
  627. if (error != SA_AIS_OK) {
  628. goto error_destroy;
  629. }
  630. lckResourceInstance->response_fd = lckInstance->response_fd;
  631. lckResourceInstance->response_mutex = &lckInstance->response_mutex;
  632. lckResourceInstance->lckHandle = lckHandle;
  633. lckResourceInstance->lckResourceHandle = lckResourceHandle;
  634. lckResourceInstance->resourceOpenFlags = resourceOpenFlags;
  635. memcpy (&lckResourceInstance->lockResourceName, lockResourceName, sizeof (SaNameT));
  636. req_lib_lck_resourceopen.header.size = sizeof (struct req_lib_lck_resourceopen);
  637. req_lib_lck_resourceopen.header.id = MESSAGE_REQ_LCK_RESOURCEOPENASYNC;
  638. req_lib_lck_resourceopen.invocation = invocation;
  639. req_lib_lck_resourceopen.resourceOpenFlags = resourceOpenFlags;
  640. req_lib_lck_resourceopen.resourceHandle = lckResourceHandle;
  641. req_lib_lck_resourceopen.async_call = 1;
  642. pthread_mutex_lock (&lckInstance->response_mutex);
  643. error = saSendReceiveReply (lckResourceInstance->response_fd,
  644. &req_lib_lck_resourceopen,
  645. sizeof (struct req_lib_lck_resourceopen),
  646. &res_lib_lck_resourceopenasync,
  647. sizeof (struct res_lib_lck_resourceopenasync));
  648. pthread_mutex_unlock (&lckInstance->response_mutex);
  649. if (error == SA_AIS_OK) {
  650. saHandleInstancePut (&lckResourceHandleDatabase,
  651. lckResourceHandle);
  652. saHandleInstancePut (&lckHandleDatabase, lckHandle);
  653. return (res_lib_lck_resourceopenasync.header.error);
  654. }
  655. saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
  656. error_destroy:
  657. saHandleDestroy (&lckResourceHandleDatabase, lckResourceHandle);
  658. error_put_lck:
  659. saHandleInstancePut (&lckHandleDatabase, lckHandle);
  660. error_exit:
  661. return (error);
  662. }
  663. SaAisErrorT
  664. saLckResourceClose (
  665. SaLckResourceHandleT lckResourceHandle)
  666. {
  667. struct req_lib_lck_resourceclose req_lib_lck_resourceclose;
  668. struct res_lib_lck_resourceclose res_lib_lck_resourceclose;
  669. SaAisErrorT error;
  670. struct lckResourceInstance *lckResourceInstance;
  671. error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
  672. (void *)&lckResourceInstance);
  673. if (error != SA_AIS_OK) {
  674. return (error);
  675. }
  676. req_lib_lck_resourceclose.header.size = sizeof (struct req_lib_lck_resourceclose);
  677. req_lib_lck_resourceclose.header.id = MESSAGE_REQ_LCK_RESOURCECLOSE;
  678. marshall_to_mar_name_t (&req_lib_lck_resourceclose.lockResourceName,
  679. &lckResourceInstance->lockResourceName);
  680. req_lib_lck_resourceclose.resourceHandle = lckResourceHandle;
  681. pthread_mutex_lock (lckResourceInstance->response_mutex);
  682. error = saSendReceiveReply (lckResourceInstance->response_fd,
  683. &req_lib_lck_resourceclose,
  684. sizeof (struct req_lib_lck_resourceclose),
  685. &res_lib_lck_resourceclose,
  686. sizeof (struct res_lib_lck_resourceclose));
  687. pthread_mutex_unlock (lckResourceInstance->response_mutex);
  688. saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
  689. saHandleDestroy (&lckResourceHandleDatabase, lckResourceHandle);
  690. return (error == SA_AIS_OK ? res_lib_lck_resourceclose.header.error : error);
  691. }
  692. SaAisErrorT
  693. saLckResourceLock (
  694. SaLckResourceHandleT lckResourceHandle,
  695. SaLckLockIdT *lockId,
  696. SaLckLockModeT lockMode,
  697. SaLckLockFlagsT lockFlags,
  698. SaLckWaiterSignalT waiterSignal,
  699. SaTimeT timeout,
  700. SaLckLockStatusT *lockStatus)
  701. {
  702. struct req_lib_lck_resourcelock req_lib_lck_resourcelock;
  703. struct res_lib_lck_resourcelock res_lib_lck_resourcelock;
  704. SaAisErrorT error;
  705. struct lckResourceInstance *lckResourceInstance;
  706. struct lckLockIdInstance *lckLockIdInstance;
  707. int lock_fd;
  708. int dummy_fd;
  709. error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
  710. (void *)&lckResourceInstance);
  711. if (error != SA_AIS_OK) {
  712. return (error);
  713. }
  714. error = saHandleCreate (&lckLockIdHandleDatabase,
  715. sizeof (struct lckLockIdInstance), lockId);
  716. if (error != SA_AIS_OK) {
  717. goto error_put_lck;
  718. }
  719. error = saHandleInstanceGet (&lckLockIdHandleDatabase, *lockId,
  720. (void *)&lckLockIdInstance);
  721. if (error != SA_AIS_OK) {
  722. goto error_destroy;
  723. }
  724. error = saServiceConnect (&lock_fd, &dummy_fd, LCK_SERVICE);
  725. if (error != SA_AIS_OK) { // TODO error handling
  726. goto error_destroy;
  727. }
  728. lckLockIdInstance->response_mutex = lckResourceInstance->response_mutex;
  729. lckLockIdInstance->response_fd = lckResourceInstance->response_fd;
  730. lckLockIdInstance->lckResourceHandle = lckResourceHandle;
  731. req_lib_lck_resourcelock.header.size = sizeof (struct req_lib_lck_resourcelock);
  732. req_lib_lck_resourcelock.header.id = MESSAGE_REQ_LCK_RESOURCELOCK;
  733. marshall_to_mar_name_t (&req_lib_lck_resourcelock.lockResourceName,
  734. &lckResourceInstance->lockResourceName);
  735. req_lib_lck_resourcelock.lockMode = lockMode;
  736. req_lib_lck_resourcelock.lockFlags = lockFlags;
  737. req_lib_lck_resourcelock.waiterSignal = waiterSignal;
  738. req_lib_lck_resourcelock.lockId = *lockId;
  739. req_lib_lck_resourcelock.async_call = 0;
  740. req_lib_lck_resourcelock.invocation = 0;
  741. req_lib_lck_resourcelock.resourceHandle = lckResourceHandle;
  742. memcpy (&req_lib_lck_resourcelock.source,
  743. &lckResourceInstance->source,
  744. sizeof (mar_message_source_t));
  745. /*
  746. * no mutex needed here since its a new connection
  747. */
  748. error = saSendReceiveReply (lock_fd,
  749. &req_lib_lck_resourcelock,
  750. sizeof (struct req_lib_lck_resourcelock),
  751. &res_lib_lck_resourcelock,
  752. sizeof (struct res_lib_lck_resourcelock));
  753. close (lock_fd);
  754. close (dummy_fd);
  755. if (error == SA_AIS_OK) {
  756. lckLockIdInstance->resource_lock = res_lib_lck_resourcelock.resource_lock;
  757. *lockStatus = res_lib_lck_resourcelock.lockStatus;
  758. return (res_lib_lck_resourcelock.header.error);
  759. }
  760. /*
  761. * Error
  762. */
  763. saHandleInstancePut (&lckLockIdHandleDatabase, *lockId);
  764. error_destroy:
  765. saHandleDestroy (&lckLockIdHandleDatabase, *lockId);
  766. error_put_lck:
  767. saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
  768. return (error);
  769. }
  770. SaAisErrorT
  771. saLckResourceLockAsync (
  772. SaLckResourceHandleT lckResourceHandle,
  773. SaInvocationT invocation,
  774. SaLckLockIdT *lockId,
  775. SaLckLockModeT lockMode,
  776. SaLckLockFlagsT lockFlags,
  777. SaLckWaiterSignalT waiterSignal)
  778. {
  779. struct req_lib_lck_resourcelock req_lib_lck_resourcelock;
  780. struct res_lib_lck_resourcelockasync res_lib_lck_resourcelockasync;
  781. SaAisErrorT error;
  782. struct lckResourceInstance *lckResourceInstance;
  783. struct lckLockIdInstance *lckLockIdInstance;
  784. int lock_fd;
  785. int dummy_fd;
  786. error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
  787. (void *)&lckResourceInstance);
  788. if (error != SA_AIS_OK) {
  789. return (error);
  790. }
  791. error = saHandleCreate (&lckLockIdHandleDatabase,
  792. sizeof (struct lckLockIdInstance), lockId);
  793. if (error != SA_AIS_OK) {
  794. goto error_put_lck;
  795. }
  796. error = saHandleInstanceGet (&lckLockIdHandleDatabase, *lockId,
  797. (void *)&lckLockIdInstance);
  798. if (error != SA_AIS_OK) {
  799. goto error_destroy;
  800. }
  801. error = saServiceConnect (&lock_fd, &dummy_fd, LCK_SERVICE);
  802. if (error != SA_AIS_OK) { // TODO error handling
  803. goto error_destroy;
  804. }
  805. lckLockIdInstance->response_mutex = lckResourceInstance->response_mutex;
  806. lckLockIdInstance->response_fd = lckResourceInstance->response_fd;
  807. lckLockIdInstance->lckResourceHandle = lckResourceHandle;
  808. req_lib_lck_resourcelock.header.size = sizeof (struct req_lib_lck_resourcelock);
  809. req_lib_lck_resourcelock.header.id = MESSAGE_REQ_LCK_RESOURCELOCKASYNC;
  810. marshall_to_mar_name_t (&req_lib_lck_resourcelock.lockResourceName,
  811. &lckResourceInstance->lockResourceName);
  812. req_lib_lck_resourcelock.lockMode = lockMode;
  813. req_lib_lck_resourcelock.lockFlags = lockFlags;
  814. req_lib_lck_resourcelock.waiterSignal = waiterSignal;
  815. req_lib_lck_resourcelock.lockId = *lockId;
  816. req_lib_lck_resourcelock.async_call = 1;
  817. req_lib_lck_resourcelock.invocation = invocation;
  818. req_lib_lck_resourcelock.resourceHandle = lckResourceHandle;
  819. memcpy (&req_lib_lck_resourcelock.source,
  820. &lckResourceInstance->source,
  821. sizeof (mar_message_source_t));
  822. /*
  823. * no mutex needed here since its a new connection
  824. */
  825. error = saSendReceiveReply (lock_fd,
  826. &req_lib_lck_resourcelock,
  827. sizeof (struct req_lib_lck_resourcelock),
  828. &res_lib_lck_resourcelockasync,
  829. sizeof (struct res_lib_lck_resourcelock));
  830. close (lock_fd);
  831. close (dummy_fd);
  832. if (error == SA_AIS_OK) {
  833. return (res_lib_lck_resourcelockasync.header.error);
  834. }
  835. /*
  836. * Error
  837. */
  838. saHandleInstancePut (&lckLockIdHandleDatabase, *lockId);
  839. error_destroy:
  840. saHandleDestroy (&lckLockIdHandleDatabase, *lockId);
  841. error_put_lck:
  842. saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
  843. return (error);
  844. }
  845. SaAisErrorT
  846. saLckResourceUnlock (
  847. SaLckLockIdT lockId,
  848. SaTimeT timeout)
  849. {
  850. struct req_lib_lck_resourceunlock req_lib_lck_resourceunlock;
  851. struct res_lib_lck_resourceunlock res_lib_lck_resourceunlock;
  852. SaAisErrorT error;
  853. struct lckLockIdInstance *lckLockIdInstance;
  854. struct lckResourceInstance *lckResourceInstance;
  855. error = saHandleInstanceGet (&lckLockIdHandleDatabase, lockId,
  856. (void *)&lckLockIdInstance);
  857. if (error != SA_AIS_OK) {
  858. return (error);
  859. }
  860. /*
  861. * Retrieve resource name
  862. */
  863. error = saHandleInstanceGet (&lckResourceHandleDatabase,
  864. lckLockIdInstance->lckResourceHandle, (void *)&lckResourceInstance);
  865. if (error != SA_AIS_OK) {
  866. saHandleInstancePut (&lckLockIdHandleDatabase, lockId);
  867. return (error);
  868. }
  869. marshall_to_mar_name_t (&req_lib_lck_resourceunlock.lockResourceName,
  870. &lckResourceInstance->lockResourceName);
  871. saHandleInstancePut (&lckResourceHandleDatabase,
  872. lckLockIdInstance->lckResourceHandle);
  873. req_lib_lck_resourceunlock.header.size = sizeof (struct req_lib_lck_resourceunlock);
  874. req_lib_lck_resourceunlock.header.id = MESSAGE_REQ_LCK_RESOURCEUNLOCK;
  875. req_lib_lck_resourceunlock.lockId = lockId;
  876. req_lib_lck_resourceunlock.timeout = timeout;
  877. req_lib_lck_resourceunlock.invocation = -1;
  878. req_lib_lck_resourceunlock.async_call = 0;
  879. req_lib_lck_resourceunlock.resource_lock = lckLockIdInstance->resource_lock;
  880. pthread_mutex_lock (lckLockIdInstance->response_mutex);
  881. error = saSendReceiveReply (lckLockIdInstance->response_fd,
  882. &req_lib_lck_resourceunlock,
  883. sizeof (struct req_lib_lck_resourceunlock),
  884. &res_lib_lck_resourceunlock,
  885. sizeof (struct res_lib_lck_resourceunlock));
  886. pthread_mutex_unlock (lckLockIdInstance->response_mutex);
  887. saHandleInstancePut (&lckLockIdHandleDatabase, lockId);
  888. saHandleDestroy (&lckLockIdHandleDatabase, lockId);
  889. return (error == SA_AIS_OK ? res_lib_lck_resourceunlock.header.error : error);
  890. }
  891. SaAisErrorT
  892. saLckResourceUnlockAsync (
  893. SaInvocationT invocation,
  894. SaLckLockIdT lockId)
  895. {
  896. struct req_lib_lck_resourceunlock req_lib_lck_resourceunlock;
  897. struct res_lib_lck_resourceunlockasync res_lib_lck_resourceunlockasync;
  898. SaAisErrorT error;
  899. struct lckLockIdInstance *lckLockIdInstance;
  900. struct lckResourceInstance *lckResourceInstance;
  901. error = saHandleInstanceGet (&lckLockIdHandleDatabase, lockId,
  902. (void *)&lckLockIdInstance);
  903. if (error != SA_AIS_OK) {
  904. return (error);
  905. }
  906. /*
  907. * Retrieve resource name
  908. */
  909. error = saHandleInstanceGet (&lckResourceHandleDatabase,
  910. lckLockIdInstance->lckResourceHandle, (void *)&lckResourceInstance);
  911. if (error != SA_AIS_OK) {
  912. saHandleInstancePut (&lckLockIdHandleDatabase, lockId);
  913. return (error);
  914. }
  915. marshall_to_mar_name_t (&req_lib_lck_resourceunlock.lockResourceName,
  916. &lckResourceInstance->lockResourceName);
  917. saHandleInstancePut (&lckResourceHandleDatabase,
  918. lckLockIdInstance->lckResourceHandle);
  919. /*
  920. * Build and send request
  921. */
  922. req_lib_lck_resourceunlock.header.size = sizeof (struct req_lib_lck_resourceunlock);
  923. req_lib_lck_resourceunlock.header.id = MESSAGE_REQ_LCK_RESOURCEUNLOCKASYNC;
  924. req_lib_lck_resourceunlock.invocation = invocation;
  925. req_lib_lck_resourceunlock.lockId = lockId;
  926. req_lib_lck_resourceunlock.async_call = 1;
  927. pthread_mutex_lock (lckLockIdInstance->response_mutex);
  928. error = saSendReceiveReply (lckLockIdInstance->response_fd,
  929. &req_lib_lck_resourceunlock,
  930. sizeof (struct req_lib_lck_resourceunlock),
  931. &res_lib_lck_resourceunlockasync,
  932. sizeof (struct res_lib_lck_resourceunlockasync));
  933. pthread_mutex_unlock (lckLockIdInstance->response_mutex);
  934. saHandleInstancePut (&lckLockIdHandleDatabase, lockId);
  935. return (error == SA_AIS_OK ? res_lib_lck_resourceunlockasync.header.error : error);
  936. }
  937. SaAisErrorT
  938. saLckLockPurge (
  939. SaLckResourceHandleT lckResourceHandle)
  940. {
  941. struct req_lib_lck_lockpurge req_lib_lck_lockpurge;
  942. struct res_lib_lck_lockpurge res_lib_lck_lockpurge;
  943. SaAisErrorT error;
  944. struct lckResourceInstance *lckResourceInstance;
  945. error = saHandleInstanceGet (&lckResourceHandleDatabase, lckResourceHandle,
  946. (void *)&lckResourceInstance);
  947. if (error != SA_AIS_OK) {
  948. return (error);
  949. }
  950. req_lib_lck_lockpurge.header.size = sizeof (struct req_lib_lck_lockpurge);
  951. req_lib_lck_lockpurge.header.id = MESSAGE_REQ_LCK_LOCKPURGE;
  952. marshall_to_mar_name_t (&req_lib_lck_lockpurge.lockResourceName,
  953. &lckResourceInstance->lockResourceName);
  954. pthread_mutex_lock (lckResourceInstance->response_mutex);
  955. error = saSendReceiveReply (lckResourceInstance->response_fd,
  956. &req_lib_lck_lockpurge,
  957. sizeof (struct req_lib_lck_lockpurge),
  958. &res_lib_lck_lockpurge,
  959. sizeof (struct res_lib_lck_lockpurge));
  960. pthread_mutex_unlock (lckResourceInstance->response_mutex);
  961. saHandleInstancePut (&lckResourceHandleDatabase, lckResourceHandle);
  962. return (error == SA_AIS_OK ? res_lib_lck_lockpurge.header.error : error);
  963. }