clm.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. /*
  2. * Copyright (c) 2002-2005 MontaVista Software, Inc.
  3. * Copyright (c) 2006 Red Hat, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. * Author: Steven Dake (sdake@mvista.com)
  8. *
  9. * This software licensed under BSD license, the text of which follows:
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions are met:
  13. *
  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.
  22. *
  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.
  34. */
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <stdlib.h>
  38. #include <unistd.h>
  39. #include <assert.h>
  40. #include <errno.h>
  41. #include <pthread.h>
  42. #include <sys/types.h>
  43. #include <sys/socket.h>
  44. #include <sys/select.h>
  45. #include <sys/un.h>
  46. #include "../include/swab.h"
  47. #include "../exec/totem.h"
  48. #include "../include/saAis.h"
  49. #include "../include/saClm.h"
  50. #include "../include/ipc_gen.h"
  51. #include "../include/ipc_clm.h"
  52. #include "../include/mar_gen.h"
  53. #include "../include/mar_clm.h"
  54. #include "util.h"
  55. struct res_overlay {
  56. mar_res_header_t header;
  57. char data[512000];
  58. };
  59. struct clmInstance {
  60. int response_fd;
  61. int dispatch_fd;
  62. SaClmCallbacksT callbacks;
  63. int finalize;
  64. pthread_mutex_t response_mutex;
  65. pthread_mutex_t dispatch_mutex;
  66. };
  67. static void clmHandleInstanceDestructor (void *);
  68. static struct saHandleDatabase clmHandleDatabase = {
  69. .handleCount = 0,
  70. .handles = 0,
  71. .mutex = PTHREAD_MUTEX_INITIALIZER,
  72. .handleInstanceDestructor = clmHandleInstanceDestructor
  73. };
  74. /*
  75. * Versions supported
  76. */
  77. static SaVersionT clmVersionsSupported[] = {
  78. { 'B', 1, 1 }
  79. };
  80. static struct saVersionDatabase clmVersionDatabase = {
  81. sizeof (clmVersionsSupported) / sizeof (SaVersionT),
  82. clmVersionsSupported
  83. };
  84. void clmHandleInstanceDestructor (void *instance)
  85. {
  86. }
  87. /**
  88. * @defgroup saClm SAF AIS Cluster Membership API
  89. * @ingroup saf
  90. *
  91. * @{
  92. */
  93. /**
  94. * This function initializes the Cluster Membership Service for the invoking
  95. * process and registers the various callback functions. This function must
  96. * be invoked prior to the invocation of any other Cluster Membership Service
  97. * functionality. The handle clmHandle is returned as the reference to this
  98. * association between the process and the Cluster Membership Service. The
  99. * process uses this handle in subsequent communication with the Cluster
  100. * Membership Service.
  101. *
  102. * @param clmHandle A pointer to the handle designating this particular
  103. * initialization of the Cluster Membership Service that is to be
  104. * returned by the Cluster Membership Service.
  105. * @param clmCallbacks If clmCallbacks is set to NULL, no callback is
  106. * registered; otherise, it is a pointer to an SaClmCallbacksT structure,
  107. * containing the callback functions of the process that the Cluster
  108. * Membership Service may invoke. Only non-NULL callback functions
  109. * in this structure will be registered.
  110. * @param version The version requested from the application is passed into
  111. * this parameter and the version supported is returned.
  112. *
  113. * @returns SA_AIS_OK if the function completed successfully.
  114. * @returns SA_AIS_ERR_LIBRARY if an unexpected problem occurred in
  115. * the library.
  116. * @returns SA_AIS_ERR_TRY_AGAIN if the service cannot be provided at this
  117. * time.
  118. * @returns SA_AIS_ERR_INVALID_PARAM if a parameter is not set correctly.
  119. * @returns SA_AIS_ERR_NO_MEMORY if the Cluster Membership Service is out
  120. * of memory and cannot provide the service.
  121. * @returns SA_AIS_ERR_VERSION if the version parameter is not compatible with
  122. * the version of the Cluster Membership Service implementation.
  123. */
  124. SaAisErrorT
  125. saClmInitialize (
  126. SaClmHandleT *clmHandle,
  127. const SaClmCallbacksT *clmCallbacks,
  128. SaVersionT *version)
  129. {
  130. struct clmInstance *clmInstance;
  131. SaAisErrorT error = SA_AIS_OK;
  132. if (clmHandle == NULL) {
  133. return (SA_AIS_ERR_INVALID_PARAM);
  134. }
  135. if (version == NULL) {
  136. return (SA_AIS_ERR_INVALID_PARAM);
  137. }
  138. error = saVersionVerify (&clmVersionDatabase, version);
  139. if (error != SA_AIS_OK) {
  140. goto error_no_destroy;
  141. }
  142. error = saHandleCreate (&clmHandleDatabase, sizeof (struct clmInstance),
  143. clmHandle);
  144. if (error != SA_AIS_OK) {
  145. goto error_no_destroy;
  146. }
  147. error = saHandleInstanceGet (&clmHandleDatabase, *clmHandle,
  148. (void *)&clmInstance);
  149. if (error != SA_AIS_OK) {
  150. goto error_destroy;
  151. }
  152. clmInstance->response_fd = -1;
  153. clmInstance->dispatch_fd = -1;
  154. error = saServiceConnect (&clmInstance->response_fd,
  155. &clmInstance->dispatch_fd, CLM_SERVICE);
  156. if (error != SA_AIS_OK) {
  157. goto error_put_destroy;
  158. }
  159. if (clmCallbacks) {
  160. memcpy (&clmInstance->callbacks, clmCallbacks, sizeof (SaClmCallbacksT));
  161. } else {
  162. memset (&clmInstance->callbacks, 0, sizeof (SaClmCallbacksT));
  163. }
  164. pthread_mutex_init (&clmInstance->response_mutex, NULL);
  165. pthread_mutex_init (&clmInstance->dispatch_mutex, NULL);
  166. saHandleInstancePut (&clmHandleDatabase, *clmHandle);
  167. return (SA_AIS_OK);
  168. error_put_destroy:
  169. saHandleInstancePut (&clmHandleDatabase, *clmHandle);
  170. error_destroy:
  171. saHandleDestroy (&clmHandleDatabase, *clmHandle);
  172. error_no_destroy:
  173. return (error);
  174. }
  175. /**
  176. * This function returns the operating system handle, selectionObject,
  177. * assocated with the handle clmHandle. The invoking process can use this
  178. * handle to detect pending callbacks, instead of repeatedly invoking
  179. * saClmDispatch() for this purpose.
  180. *
  181. * In a POSIX environment, the operating system handle is a file descriptor
  182. * that is used with the poll() or select() system calls to detect pending
  183. * callbacks.
  184. *
  185. * The selectionObject returned by saClmSelectionObjectGet() is valid until
  186. * saClmFinalize() is invoked on the same handle clmHandle.
  187. *
  188. * @param clmHandle The handle, obtained through the saClmInitialize function,
  189. * designating this particular initialization of the Cluster Membership
  190. * @param selectionObject A pointer to the operating system handle that the
  191. * invoking process can use to detect pending callbacks.
  192. *
  193. * @returns SA_AIS_OK if the function completed successfully.
  194. * @returns SA_AIS_ERR_BAD_HANDLE if the handle clmHandle is invalid, since it is
  195. * corrupted, uninitialized, or has already been finalized.
  196. */
  197. SaAisErrorT
  198. saClmSelectionObjectGet (
  199. SaClmHandleT clmHandle,
  200. SaSelectionObjectT *selectionObject)
  201. {
  202. struct clmInstance *clmInstance;
  203. SaAisErrorT error;
  204. if (selectionObject == NULL) {
  205. return (SA_AIS_ERR_INVALID_PARAM);
  206. }
  207. error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
  208. (void *)&clmInstance);
  209. if (error != SA_AIS_OK) {
  210. return (error);
  211. }
  212. *selectionObject = clmInstance->dispatch_fd;
  213. saHandleInstancePut (&clmHandleDatabase, clmHandle);
  214. return (SA_AIS_OK);
  215. }
  216. /**
  217. * This function invokes, in the context of the calling thread, pending callbacks for
  218. * the handle clmhandle in a way that is specified by the dispatchFlags parameter.
  219. *
  220. * @param clmHandle The handle, obtained through the saClmInitialize() function,
  221. * designating the particular initialization of the Cluster Membership Service.
  222. * @param dispatchFlags Flags that specify the callback exection behavior of
  223. * saClmDispatch, which have the values SA_DISPATCH_ONE, SA_DISPATCH_ALL, or
  224. * SA_DISPATCH_BLOCKING.
  225. * @returns SA_AIS_OK if the function completed successfully.
  226. * @returns SA_AIS_ERR_TRY_AGAIN if the service cannot be provided at this time. The
  227. * process may retry later.
  228. * @returns SA_AIS_ERR_BAD_HANDLE if the handle clmHandle is invalid, since it is
  229. * corrupted, uninitialized, or has already been finalized.
  230. * @returns SA_AIS_ERR_INVALID_PARAM if the dispatchFlags parameter is valid.
  231. */
  232. SaAisErrorT
  233. saClmDispatch (
  234. SaClmHandleT clmHandle,
  235. SaDispatchFlagsT dispatchFlags)
  236. {
  237. struct pollfd ufds;
  238. int timeout = -1;
  239. SaAisErrorT error;
  240. int cont = 1; /* always continue do loop except when set to 0 */
  241. int dispatch_avail;
  242. struct clmInstance *clmInstance;
  243. struct res_lib_clm_clustertrack *res_lib_clm_clustertrack;
  244. struct res_clm_nodegetcallback *res_clm_nodegetcallback;
  245. SaClmCallbacksT callbacks;
  246. struct res_overlay dispatch_data;
  247. SaClmClusterNotificationBufferT notificationBuffer;
  248. SaClmClusterNotificationT notification[PROCESSOR_COUNT_MAX];
  249. SaClmClusterNodeT clusterNode;
  250. int items_to_copy;
  251. unsigned int i;
  252. if (dispatchFlags != SA_DISPATCH_ONE &&
  253. dispatchFlags != SA_DISPATCH_ALL &&
  254. dispatchFlags != SA_DISPATCH_BLOCKING) {
  255. return (SA_AIS_ERR_INVALID_PARAM);
  256. }
  257. error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
  258. (void *)&clmInstance);
  259. if (error != SA_AIS_OK) {
  260. return (error);
  261. }
  262. /*
  263. * Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and
  264. * wait indefinately for SA_DISPATCH_BLOCKING
  265. */
  266. if (dispatchFlags == SA_DISPATCH_ALL) {
  267. timeout = 0;
  268. }
  269. do {
  270. ufds.fd = clmInstance->dispatch_fd;
  271. ufds.events = POLLIN;
  272. ufds.revents = 0;
  273. pthread_mutex_lock (&clmInstance->dispatch_mutex);
  274. error = saPollRetry (&ufds, 1, timeout);
  275. if (error != SA_AIS_OK) {
  276. goto error_unlock;
  277. }
  278. /*
  279. * Handle has been finalized in another thread
  280. */
  281. if (clmInstance->finalize == 1) {
  282. error = SA_AIS_OK;
  283. goto error_unlock;
  284. }
  285. if ((ufds.revents & (POLLERR|POLLHUP|POLLNVAL)) != 0) {
  286. error = SA_AIS_ERR_BAD_HANDLE;
  287. goto error_unlock;
  288. }
  289. dispatch_avail = ufds.revents & POLLIN;
  290. if (dispatch_avail == 0 && dispatchFlags == SA_DISPATCH_ALL) {
  291. pthread_mutex_unlock (&clmInstance->dispatch_mutex);
  292. break; /* exit do while cont is 1 loop */
  293. } else
  294. if (dispatch_avail == 0) {
  295. pthread_mutex_unlock (&clmInstance->dispatch_mutex);
  296. continue; /* next poll */
  297. }
  298. if (ufds.revents & POLLIN) {
  299. error = saRecvRetry (clmInstance->dispatch_fd, &dispatch_data.header,
  300. sizeof (mar_res_header_t));
  301. if (error != SA_AIS_OK) {
  302. goto error_unlock;
  303. }
  304. if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
  305. error = saRecvRetry (clmInstance->dispatch_fd, &dispatch_data.data,
  306. dispatch_data.header.size - sizeof (mar_res_header_t));
  307. if (error != SA_AIS_OK) {
  308. goto error_unlock;
  309. }
  310. }
  311. } else {
  312. pthread_mutex_unlock (&clmInstance->dispatch_mutex);
  313. continue;
  314. }
  315. /*
  316. * Make copy of callbacks, message data, unlock instance, and call callback
  317. * A risk of this dispatch method is that the callback routines may
  318. * operate at the same time that clmFinalize has been called in another thread.
  319. */
  320. memcpy (&callbacks, &clmInstance->callbacks, sizeof (SaClmCallbacksT));
  321. pthread_mutex_unlock (&clmInstance->dispatch_mutex);
  322. /*
  323. * Dispatch incoming message
  324. */
  325. switch (dispatch_data.header.id) {
  326. case MESSAGE_RES_CLM_TRACKCALLBACK:
  327. if (callbacks.saClmClusterTrackCallback == NULL) {
  328. continue;
  329. }
  330. res_lib_clm_clustertrack = (struct res_lib_clm_clustertrack *)&dispatch_data;
  331. error = SA_AIS_OK;
  332. notificationBuffer.notification = notification;
  333. notificationBuffer.viewNumber = res_lib_clm_clustertrack->view;
  334. notificationBuffer.notification = notification;
  335. notificationBuffer.numberOfItems =
  336. res_lib_clm_clustertrack->number_of_items;
  337. items_to_copy = notificationBuffer.numberOfItems
  338. < res_lib_clm_clustertrack->number_of_items ?
  339. notificationBuffer.numberOfItems :
  340. res_lib_clm_clustertrack->number_of_items;
  341. for (i = 0; i < items_to_copy; i++) {
  342. marshall_from_mar_clm_cluster_notification_t (
  343. &notificationBuffer.notification[i],
  344. &res_lib_clm_clustertrack->notification[i]);
  345. }
  346. callbacks.saClmClusterTrackCallback (
  347. (const SaClmClusterNotificationBufferT *)&notificationBuffer,
  348. res_lib_clm_clustertrack->number_of_items, error);
  349. break;
  350. case MESSAGE_RES_CLM_NODEGETCALLBACK:
  351. if (callbacks.saClmClusterNodeGetCallback == NULL) {
  352. continue;
  353. }
  354. res_clm_nodegetcallback = (struct res_clm_nodegetcallback *)&dispatch_data;
  355. marshall_from_mar_clm_cluster_node_t (
  356. &clusterNode,
  357. &res_clm_nodegetcallback->cluster_node);
  358. callbacks.saClmClusterNodeGetCallback (
  359. res_clm_nodegetcallback->invocation,
  360. &clusterNode,
  361. res_clm_nodegetcallback->header.error);
  362. break;
  363. default:
  364. error = SA_AIS_ERR_LIBRARY;
  365. goto error_put;
  366. break;
  367. }
  368. /*
  369. * Determine if more messages should be processed
  370. * */
  371. switch (dispatchFlags) {
  372. case SA_DISPATCH_ONE:
  373. cont = 0;
  374. break;
  375. case SA_DISPATCH_ALL:
  376. break;
  377. case SA_DISPATCH_BLOCKING:
  378. break;
  379. }
  380. } while (cont);
  381. goto error_put;
  382. error_unlock:
  383. pthread_mutex_unlock (&clmInstance->dispatch_mutex);
  384. error_put:
  385. saHandleInstancePut (&clmHandleDatabase, clmHandle);
  386. return (error);
  387. }
  388. /**
  389. * The saClmFinalize function closes the assocation, represented by the clmHandle
  390. * parameter, between the invoking process and the Cluster Membership Service. The
  391. * process must have invoked saClmInitialize before it invokes this function. A
  392. * process must invoke this function once for each handle it acquired by invoking
  393. * saClmInitialize().
  394. *
  395. * If the saClmFinalize() function returns successfully, the saClmFinalize() function
  396. * releases all resources acquired when saClmInitialize(0 was called. Moreover, it
  397. * stops any tracking associated with the particular handle. Furthermore, it cancels
  398. * all pending callbacks related to the particular handle. Note that because the
  399. * callback invocation is asynchronous, it is still possible that some callback calls
  400. * are processed after this call returns successfully.
  401. *
  402. * After saClmFinalize() is invoked, the selection object is no longer valid.
  403. *
  404. * @param clmHandle The handle, obtained through the saClmInitialize() function,
  405. * designating this particular initialization of the Cluster Membership Service.
  406. *
  407. * @returns SA_AIS_OK if the function completed successfully.
  408. * @returns SA_AIS_ERR_BAD_HANDLE if the handle clmHandle is invalid, since it is
  409. * corrupted, uninitialized, or has already been finalized.
  410. */
  411. SaAisErrorT
  412. saClmFinalize (
  413. SaClmHandleT clmHandle)
  414. {
  415. struct clmInstance *clmInstance;
  416. SaAisErrorT error;
  417. error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
  418. (void *)&clmInstance);
  419. if (error != SA_AIS_OK) {
  420. return (error);
  421. }
  422. pthread_mutex_lock (&clmInstance->response_mutex);
  423. /*
  424. * Another thread has already started finalizing
  425. */
  426. if (clmInstance->finalize) {
  427. pthread_mutex_unlock (&clmInstance->response_mutex);
  428. saHandleInstancePut (&clmHandleDatabase, clmHandle);
  429. return (SA_AIS_ERR_BAD_HANDLE);
  430. }
  431. clmInstance->finalize = 1;
  432. pthread_mutex_unlock (&clmInstance->response_mutex);
  433. saHandleDestroy (&clmHandleDatabase, clmHandle);
  434. if (clmInstance->response_fd != -1) {
  435. shutdown (clmInstance->response_fd, 0);
  436. close (clmInstance->response_fd);
  437. }
  438. if (clmInstance->dispatch_fd != -1) {
  439. shutdown (clmInstance->dispatch_fd, 0);
  440. close (clmInstance->dispatch_fd);
  441. }
  442. saHandleInstancePut (&clmHandleDatabase, clmHandle);
  443. return (error);
  444. }
  445. SaAisErrorT
  446. saClmClusterTrack (
  447. SaClmHandleT clmHandle,
  448. SaUint8T trackFlags,
  449. SaClmClusterNotificationBufferT *notificationBuffer)
  450. {
  451. struct req_lib_clm_clustertrack req_lib_clm_clustertrack;
  452. struct res_lib_clm_clustertrack res_lib_clm_clustertrack;
  453. struct clmInstance *clmInstance;
  454. SaAisErrorT error = SA_AIS_OK;
  455. int items_to_copy;
  456. unsigned int i;
  457. error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
  458. (void *)&clmInstance);
  459. if (error != SA_AIS_OK) {
  460. return (error);
  461. }
  462. if ((trackFlags & SA_TRACK_CHANGES) && (trackFlags & SA_TRACK_CHANGES_ONLY)) {
  463. error = SA_AIS_ERR_BAD_FLAGS;
  464. goto error_nounlock;
  465. }
  466. if (trackFlags & ~(SA_TRACK_CURRENT | SA_TRACK_CHANGES | SA_TRACK_CHANGES_ONLY)) {
  467. error = SA_AIS_ERR_BAD_FLAGS;
  468. goto error_nounlock;
  469. }
  470. if ((notificationBuffer != NULL) &&
  471. (notificationBuffer->notification != NULL) &&
  472. (notificationBuffer->numberOfItems == 0)) {
  473. error = SA_AIS_ERR_INVALID_PARAM;
  474. goto error_nounlock;
  475. }
  476. req_lib_clm_clustertrack.header.size = sizeof (struct req_lib_clm_clustertrack);
  477. req_lib_clm_clustertrack.header.id = MESSAGE_REQ_CLM_TRACKSTART;
  478. req_lib_clm_clustertrack.track_flags = trackFlags;
  479. req_lib_clm_clustertrack.return_in_callback = 0;
  480. if ((trackFlags & SA_TRACK_CURRENT) && (notificationBuffer == NULL)) {
  481. req_lib_clm_clustertrack.return_in_callback = 1;
  482. }
  483. pthread_mutex_lock (&clmInstance->response_mutex);
  484. if ((clmInstance->callbacks.saClmClusterTrackCallback == 0) &&
  485. ((notificationBuffer == NULL) ||
  486. (trackFlags & (SA_TRACK_CHANGES | SA_TRACK_CHANGES_ONLY)))) {
  487. error = SA_AIS_ERR_INIT;
  488. goto error_exit;
  489. }
  490. error = saSendReceiveReply (clmInstance->response_fd,
  491. &req_lib_clm_clustertrack,
  492. sizeof (struct req_lib_clm_clustertrack),
  493. &res_lib_clm_clustertrack,
  494. sizeof (struct res_lib_clm_clustertrack));
  495. if ((trackFlags & SA_TRACK_CURRENT) && (notificationBuffer != NULL)) {
  496. if (notificationBuffer->notification == 0) {
  497. notificationBuffer->viewNumber = res_lib_clm_clustertrack.view;
  498. notificationBuffer->notification =
  499. malloc (res_lib_clm_clustertrack.number_of_items *
  500. sizeof (SaClmClusterNotificationT));
  501. notificationBuffer->numberOfItems =
  502. res_lib_clm_clustertrack.number_of_items;
  503. }
  504. items_to_copy = notificationBuffer->numberOfItems <
  505. res_lib_clm_clustertrack.number_of_items ?
  506. notificationBuffer->numberOfItems :
  507. res_lib_clm_clustertrack.number_of_items;
  508. for (i = 0; i < items_to_copy; i++) {
  509. marshall_from_mar_clm_cluster_notification_t (
  510. &notificationBuffer->notification[i],
  511. &res_lib_clm_clustertrack.notification[i]);
  512. }
  513. notificationBuffer->viewNumber = res_lib_clm_clustertrack.view;
  514. notificationBuffer->numberOfItems = items_to_copy;
  515. }
  516. error_exit:
  517. pthread_mutex_unlock (&clmInstance->response_mutex);
  518. error_nounlock:
  519. saHandleInstancePut (&clmHandleDatabase, clmHandle);
  520. return (error == SA_AIS_OK ? res_lib_clm_clustertrack.header.error : error);
  521. }
  522. SaAisErrorT
  523. saClmClusterTrackStop (
  524. SaClmHandleT clmHandle)
  525. {
  526. struct clmInstance *clmInstance;
  527. struct req_lib_clm_trackstop req_lib_clm_trackstop;
  528. struct res_lib_clm_trackstop res_lib_clm_trackstop;
  529. SaAisErrorT error = SA_AIS_OK;
  530. req_lib_clm_trackstop.header.size = sizeof (struct req_lib_clm_trackstop);
  531. req_lib_clm_trackstop.header.id = MESSAGE_REQ_CLM_TRACKSTOP;
  532. error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
  533. (void *)&clmInstance);
  534. if (error != SA_AIS_OK) {
  535. return (error);
  536. }
  537. pthread_mutex_lock (&clmInstance->response_mutex);
  538. error = saSendReceiveReply (clmInstance->response_fd,
  539. &req_lib_clm_trackstop,
  540. sizeof (struct req_lib_clm_trackstop),
  541. &res_lib_clm_trackstop,
  542. sizeof (struct res_lib_clm_trackstop));
  543. pthread_mutex_unlock (&clmInstance->response_mutex);
  544. saHandleInstancePut (&clmHandleDatabase, clmHandle);
  545. return (error == SA_AIS_OK ? res_lib_clm_trackstop.header.error : error);
  546. }
  547. SaAisErrorT
  548. saClmClusterNodeGet (
  549. SaClmHandleT clmHandle,
  550. SaClmNodeIdT nodeId,
  551. SaTimeT timeout,
  552. SaClmClusterNodeT *clusterNode)
  553. {
  554. struct clmInstance *clmInstance;
  555. struct req_lib_clm_nodeget req_lib_clm_nodeget;
  556. struct res_clm_nodeget res_clm_nodeget;
  557. SaAisErrorT error = SA_AIS_OK;
  558. if (clusterNode == NULL) {
  559. return (SA_AIS_ERR_INVALID_PARAM);
  560. }
  561. if (timeout == 0) {
  562. return (SA_AIS_ERR_TIMEOUT);
  563. }
  564. error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
  565. (void *)&clmInstance);
  566. if (error != SA_AIS_OK) {
  567. return (error);
  568. }
  569. pthread_mutex_lock (&clmInstance->response_mutex);
  570. /*
  571. * Send request message
  572. */
  573. req_lib_clm_nodeget.header.size = sizeof (struct req_lib_clm_nodeget);
  574. req_lib_clm_nodeget.header.id = MESSAGE_REQ_CLM_NODEGET;
  575. req_lib_clm_nodeget.node_id = nodeId;
  576. error = saSendReceiveReply (clmInstance->response_fd, &req_lib_clm_nodeget,
  577. sizeof (struct req_lib_clm_nodeget), &res_clm_nodeget, sizeof (res_clm_nodeget));
  578. if (error != SA_AIS_OK) {
  579. goto error_exit;
  580. }
  581. error = res_clm_nodeget.header.error;
  582. marshall_from_mar_clm_cluster_node_t (clusterNode,
  583. &res_clm_nodeget.cluster_node);
  584. error_exit:
  585. pthread_mutex_unlock (&clmInstance->response_mutex);
  586. saHandleInstancePut (&clmHandleDatabase, clmHandle);
  587. return (error);
  588. }
  589. SaAisErrorT
  590. saClmClusterNodeGetAsync (
  591. SaClmHandleT clmHandle,
  592. SaInvocationT invocation,
  593. SaClmNodeIdT nodeId)
  594. {
  595. struct clmInstance *clmInstance;
  596. struct req_lib_clm_nodegetasync req_lib_clm_nodegetasync;
  597. struct res_clm_nodegetasync res_clm_nodegetasync;
  598. SaAisErrorT error = SA_AIS_OK;
  599. req_lib_clm_nodegetasync.header.size = sizeof (struct req_lib_clm_nodegetasync);
  600. req_lib_clm_nodegetasync.header.id = MESSAGE_REQ_CLM_NODEGETASYNC;
  601. req_lib_clm_nodegetasync.invocation = invocation;
  602. req_lib_clm_nodegetasync.node_id = nodeId;
  603. error = saHandleInstanceGet (&clmHandleDatabase, clmHandle,
  604. (void *)&clmInstance);
  605. if (error != SA_AIS_OK) {
  606. return (error);
  607. }
  608. pthread_mutex_lock (&clmInstance->response_mutex);
  609. if (clmInstance->callbacks.saClmClusterNodeGetCallback == NULL) {
  610. error = SA_AIS_ERR_INIT;
  611. goto error_exit;
  612. }
  613. error = saSendReceiveReply (clmInstance->response_fd, &req_lib_clm_nodegetasync,
  614. sizeof (struct req_lib_clm_nodegetasync),
  615. &res_clm_nodegetasync, sizeof (struct res_clm_nodegetasync));
  616. if (error != SA_AIS_OK) {
  617. goto error_exit;
  618. }
  619. error = res_clm_nodegetasync.header.error;
  620. error_exit:
  621. pthread_mutex_unlock (&clmInstance->response_mutex);
  622. saHandleInstancePut (&clmHandleDatabase, clmHandle);
  623. return (error);
  624. }
  625. /** @} */