2 * Copyright (c) 2004-2005 Mark Haverkamp
3 * Copyright (c) 2004-2005 Open Source Development Lab
7 * This software licensed under BSD license, the text of which follows:
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * - Neither the name of the Open Source Developement Lab nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/types.h>
41 #include <sys/socket.h>
44 #include "../exec/totem.h"
47 static void evtHandleInstanceDestructor(void *instance
);
48 static void chanHandleInstanceDestructor(void *instance
);
49 static void eventHandleInstanceDestructor(void *instance
);
52 * Versions of the SAF AIS specification supported by this library
54 static SaVersionT supported_versions
[] = {
58 static struct saVersionDatabase evt_version_database
= {
59 sizeof(supported_versions
) / sizeof(SaVersionT
),
66 struct saHandleDatabase evt_instance_handle_db
= {
69 .mutex
= PTHREAD_MUTEX_INITIALIZER
,
70 .handleInstanceDestructor
= evtHandleInstanceDestructor
74 * Channel instance data
76 struct saHandleDatabase channel_handle_db
= {
79 .mutex
= PTHREAD_MUTEX_INITIALIZER
,
80 .handleInstanceDestructor
= chanHandleInstanceDestructor
86 struct saHandleDatabase event_handle_db
= {
89 .mutex
= PTHREAD_MUTEX_INITIALIZER
,
90 .handleInstanceDestructor
= eventHandleInstanceDestructor
94 mar_res_header_t header
__attribute__((aligned(8)));
95 char data
[MESSAGE_SIZE_MAX
];
100 struct list_head hl_entry
;
104 * data required to support events for a given initialization
106 * ei_dispatch_fd: fd used for getting callback data e.g. async event data
107 * ei_response_fd: fd used for everything else (i.e. evt sync api commands).
108 * ei_callback: callback function.
109 * ei_version: version sent to the evtInitialize call.
110 * ei_node_id: our node id.
111 * ei_node_name: our node name.
112 * ei_dispatch_mutex: mutex for dispatch fd. This lock also ensures that
113 * only one thread is using ei_dispatch_data.
114 * ei_response_mutex: mutex for response fd
115 * ei_channel_list: list of associated channels (struct handle_list)
116 * ei_dispatch_data: event buffer for evtDispatch
117 * ei_finalize: instance in finalize flag
118 * ei_data_available: Indicates that there is a pending event message though
119 * there may not be a poll event. This can happen
120 * when we get a SA_AIS_ERR_TRY_AGAIN when asking for an
124 struct event_instance
{
127 SaEvtCallbacksT ei_callback
;
128 SaVersionT ei_version
;
129 SaClmNodeIdT ei_node_id
;
130 SaNameT ei_node_name
;
131 pthread_mutex_t ei_dispatch_mutex
;
132 pthread_mutex_t ei_response_mutex
;
133 struct list_head ei_channel_list
;
134 struct res_overlay ei_dispatch_data
;
135 unsigned int ei_finalize
:1;
136 unsigned int ei_data_available
:1;
141 * Data associated with an opened channel
143 * eci_channel_name: name of channel
144 * eci_open_flags: channel open flags
145 * eci_svr_channel_handle: channel handle returned from server
146 * eci_closing: channel in process of being closed
147 * eci_mutex: channel mutex
148 * eci_event_list: events associated with this
149 * channel (struct handle_list)
150 * eci_hl: pointer to event instance handle struct
153 struct event_channel_instance
{
155 SaNameT eci_channel_name
;
156 SaEvtChannelOpenFlagsT eci_open_flags
;
157 uint32_t eci_svr_channel_handle
;
158 SaEvtHandleT eci_instance_handle
;
160 pthread_mutex_t eci_mutex
;
161 struct list_head eci_event_list
;
162 struct handle_list
*eci_hl
;
169 * Store event data from saEvtEventAllocate function.
170 * Store event data from received events.
172 * edi_channel_handle: handle (local) of assocated channel
173 * edi_patterns: event patterns
174 * edi_priority: event priority
175 * edi_retention_time: event's retention time
176 * edi_pub_name: event's publisher name
177 * edi_pub_node: event's publisher node
178 * edi_pub_time: event's publish time
179 * edi_event_id: event's Id
180 * edi_event_data: event's data
181 * edi_event_data_size: size of edi_event_data
182 * edi_freeing: event is being freed
183 * edi_mutex: event data mutex
184 * edi_hl: pointer to channel's handle
185 * struct for this event.
186 * edi_ro: read only flag
188 struct event_data_instance
{
189 SaEvtChannelHandleT edi_channel_handle
;
190 SaEvtEventPatternArrayT edi_patterns
;
191 SaUint8T edi_priority
;
192 SaTimeT edi_retention_time
;
193 SaNameT edi_pub_name
;
194 SaClmNodeIdT edi_pub_node
;
195 SaTimeT edi_pub_time
;
196 SaEvtEventIdT edi_event_id
;
197 void *edi_event_data
;
198 SaSizeT edi_event_data_size
;
200 pthread_mutex_t edi_mutex
;
201 struct handle_list
*edi_hl
;
206 #define min(a,b) ((a) < (b) ? (a) : (b))
208 static inline int is_valid_event_id(SaEvtEventIdT evt_id
)
218 * Clean up function for an evt instance (saEvtInitialize) handle
219 * Not to be confused with event data.
221 static void evtHandleInstanceDestructor(void *instance
)
223 struct event_instance
*evti
= instance
;
224 struct event_channel_instance
*eci
;
225 struct handle_list
*hl
;
226 struct list_head
*l
, *nxt
;
231 * Free up any channel data
233 for (l
= evti
->ei_channel_list
.next
;
234 l
!= &evti
->ei_channel_list
; l
= nxt
) {
237 hl
= list_entry(l
, struct handle_list
, hl_entry
);
238 handle
= hl
->hl_handle
;
239 error
= saHandleInstanceGet(&channel_handle_db
, hl
->hl_handle
,
241 if (error
!= SA_AIS_OK
) {
247 saHandleDestroy(&channel_handle_db
, handle
);
248 saHandleInstancePut(&channel_handle_db
, handle
);
251 pthread_mutex_destroy(&evti
->ei_dispatch_mutex
);
252 pthread_mutex_destroy(&evti
->ei_response_mutex
);
256 * Clean up function for an open channel handle
258 static void chanHandleInstanceDestructor(void *instance
)
260 struct event_channel_instance
*eci
= instance
;
261 struct list_head
*l
, *nxt
;
262 struct handle_list
*hl
;
266 list_del(&eci
->eci_hl
->hl_entry
);
271 * Free up any channel associated events
273 for (l
= eci
->eci_event_list
.next
; l
!= &eci
->eci_event_list
; l
= nxt
) {
275 hl
= list_entry(l
, struct handle_list
, hl_entry
);
276 handle
= hl
->hl_handle
;
277 saEvtEventFree(handle
);
280 pthread_mutex_destroy(&eci
->eci_mutex
);
284 * Clean up function for an event handle
286 static void eventHandleInstanceDestructor(void *instance
)
288 struct event_data_instance
*edi
= instance
;
292 list_del(&edi
->edi_hl
->hl_entry
);
296 if (edi
->edi_patterns
.patterns
) {
297 for (i
= 0; i
< edi
->edi_patterns
.patternsNumber
; i
++) {
298 free(edi
->edi_patterns
.patterns
[i
].pattern
);
300 free(edi
->edi_patterns
.patterns
);
302 if (edi
->edi_event_data
) {
303 free(edi
->edi_event_data
);
306 pthread_mutex_destroy(&edi
->edi_mutex
);
309 static SaAisErrorT
evt_recv_event(int fd
, struct lib_event_data
**msg
)
312 mar_res_header_t hdr
;
315 error
= saRecvRetry(fd
, &hdr
, sizeof(hdr
));
316 if (error
!= SA_AIS_OK
) {
319 *msg
= malloc(hdr
.size
);
321 error
= SA_AIS_ERR_LIBRARY
;
324 data
= (void *)((unsigned long)*msg
) + sizeof(hdr
);
325 memcpy(*msg
, &hdr
, sizeof(hdr
));
326 if (hdr
.size
> sizeof(hdr
)) {
327 error
= saRecvRetry(fd
, data
, hdr
.size
- sizeof(hdr
));
328 if (error
!= SA_AIS_OK
) {
337 * The saEvtInitialize() function initializes the Event Service for the
338 * invoking process. A user of the Event Service must invoke this function
339 * before it invokes any other function of the Event Service API. Each
340 * initialization returns a different callback handle that the process
341 * can use to communicate with that library instance.
346 SaEvtHandleT
*evtHandle
,
347 const SaEvtCallbacksT
*callbacks
,
350 SaAisErrorT error
= SA_AIS_OK
;
351 struct event_instance
*evti
;
353 if (!version
|| !evtHandle
) {
354 error
= SA_AIS_ERR_INVALID_PARAM
;
358 * validate the requested version with what we support
360 error
= saVersionVerify(&evt_version_database
, version
);
361 if (error
!= SA_AIS_OK
) {
366 * Allocate instance data, allocate unique handle for instance,
367 * assign instance data to unique handle
369 error
= saHandleCreate(&evt_instance_handle_db
, sizeof(*evti
),
371 if (error
!= SA_AIS_OK
) {
374 error
= saHandleInstanceGet(&evt_instance_handle_db
, *evtHandle
,
376 if (error
!= SA_AIS_OK
) {
377 if (error
== SA_AIS_ERR_BAD_HANDLE
) {
378 error
= SA_AIS_ERR_LIBRARY
;
380 goto error_handle_free
;
382 memset(evti
, 0, sizeof(*evti
));
384 list_init(&evti
->ei_channel_list
);
387 * Save the version so we can check with the event server
388 * and see if it supports this version.
390 evti
->ei_version
= *version
;
393 * Set up communication with the event server
395 error
= saServiceConnect(&evti
->ei_response_fd
,
396 &evti
->ei_dispatch_fd
, EVT_SERVICE
);
397 if (error
!= SA_AIS_OK
) {
398 goto error_handle_put
;
402 * The callback function is saved in the event instance for
403 * saEvtDispatch() to use.
406 memcpy(&evti
->ei_callback
, callbacks
,
407 sizeof(evti
->ei_callback
));
410 pthread_mutex_init(&evti
->ei_dispatch_mutex
, NULL
);
411 pthread_mutex_init(&evti
->ei_response_mutex
, NULL
);
412 saHandleInstancePut(&evt_instance_handle_db
, *evtHandle
);
417 saHandleInstancePut(&evt_instance_handle_db
, *evtHandle
);
419 (void)saHandleDestroy(&evt_instance_handle_db
, *evtHandle
);
425 * The saEvtSelectionObjectGet() function returns the operating system
426 * handle selectionObject, associated with the handle evtHandle, allowing
427 * the invoking process to ascertain when callbacks are pending. This
428 * function allows a process to avoid repeated invoking saEvtDispatch() to
429 * see if there is a new event, thus, needlessly consuming CPU time. In a
430 * POSIX environment the system handle could be a file descriptor that is
431 * used with the poll() or select() system calls to detect incoming callbacks.
434 saEvtSelectionObjectGet(
435 SaEvtHandleT evtHandle
,
436 SaSelectionObjectT
*selectionObject
)
438 struct event_instance
*evti
;
441 if (!selectionObject
) {
442 return SA_AIS_ERR_INVALID_PARAM
;
445 error
= saHandleInstanceGet(&evt_instance_handle_db
, evtHandle
,
448 if (error
!= SA_AIS_OK
) {
452 *selectionObject
= evti
->ei_dispatch_fd
;
454 saHandleInstancePut(&evt_instance_handle_db
, evtHandle
);
461 * Alocate an event data structure and associated handle to be
462 * used to supply event data to a call back function.
464 static SaAisErrorT
make_event(SaEvtEventHandleT
*event_handle
,
465 struct lib_event_data
*evt
)
467 struct event_data_instance
*edi
;
468 struct event_channel_instance
*eci
;
469 mar_evt_event_pattern_t
*pat
;
472 struct handle_list
*hl
;
475 error
= saHandleCreate(&event_handle_db
, sizeof(*edi
),
477 if (error
!= SA_AIS_OK
) {
478 if (error
== SA_AIS_ERR_NO_MEMORY
) {
479 error
= SA_AIS_ERR_LIBRARY
;
484 error
= saHandleInstanceGet(&event_handle_db
, *event_handle
,
486 if (error
!= SA_AIS_OK
) {
487 saHandleDestroy(&event_handle_db
, *event_handle
);
491 error
= saHandleInstanceGet(&channel_handle_db
,
492 evt
->led_lib_channel_handle
,
494 if (error
!= SA_AIS_OK
) {
495 saHandleDestroy(&event_handle_db
, *event_handle
);
496 goto make_evt_done_put
;
499 pthread_mutex_init(&edi
->edi_mutex
, NULL
);
501 edi
->edi_freeing
= 0;
502 edi
->edi_channel_handle
= evt
->led_lib_channel_handle
;
503 edi
->edi_priority
= evt
->led_priority
;
504 edi
->edi_retention_time
= evt
->led_retention_time
;
505 edi
->edi_pub_node
= evt
->led_publisher_node_id
;
506 edi
->edi_pub_time
= evt
->led_publish_time
;
507 edi
->edi_event_data_size
= evt
->led_user_data_size
;
508 edi
->edi_event_id
= evt
->led_event_id
;
509 marshall_from_mar_name_t (&edi
->edi_pub_name
, &evt
->led_publisher_name
);
511 if (edi
->edi_event_data_size
) {
512 edi
->edi_event_data
= malloc(edi
->edi_event_data_size
);
513 if (!edi
->edi_event_data
) {
514 saHandleDestroy(&event_handle_db
, *event_handle
);
517 * saEvtDispatch doesn't return SA_AIS_ERR_NO_MEMORY
519 error
= SA_AIS_ERR_LIBRARY
;
520 goto make_evt_done_put2
;
522 memcpy(edi
->edi_event_data
,
523 evt
->led_body
+ evt
->led_user_data_offset
,
524 edi
->edi_event_data_size
);
528 * Move the pattern bits into the SaEvtEventPatternArrayT
530 edi
->edi_patterns
.patternsNumber
= evt
->led_patterns_number
;
531 edi
->edi_patterns
.allocatedNumber
= evt
->led_patterns_number
;
532 edi
->edi_patterns
.patterns
= malloc(sizeof(SaEvtEventPatternT
) *
533 edi
->edi_patterns
.patternsNumber
);
534 if (!edi
->edi_patterns
.patterns
) {
536 * The destructor will take care of freeing event data already
539 edi
->edi_patterns
.patternsNumber
= 0;
540 saHandleDestroy(&event_handle_db
, *event_handle
);
543 * saEvtDispatch doesn't return SA_AIS_ERR_NO_MEMORY
545 error
= SA_AIS_ERR_LIBRARY
;
546 goto make_evt_done_put2
;
548 memset(edi
->edi_patterns
.patterns
, 0, sizeof(SaEvtEventPatternT
) *
549 edi
->edi_patterns
.patternsNumber
);
550 pat
= (mar_evt_event_pattern_t
*)evt
->led_body
;
551 str
= evt
->led_body
+ sizeof(mar_evt_event_pattern_t
) *
552 edi
->edi_patterns
.patternsNumber
;
553 for (i
= 0; i
< evt
->led_patterns_number
; i
++) {
554 edi
->edi_patterns
.patterns
[i
].patternSize
= pat
->pattern_size
;
555 edi
->edi_patterns
.patterns
[i
].allocatedSize
= pat
->pattern_size
;
556 edi
->edi_patterns
.patterns
[i
].pattern
= malloc(pat
->pattern_size
);
557 if (!edi
->edi_patterns
.patterns
[i
].pattern
) {
558 DPRINT (("make_event: couldn't alloc %llu bytes\n",
559 (unsigned long long)pat
->pattern_size
));
560 saHandleDestroy(&event_handle_db
, *event_handle
);
561 error
= SA_AIS_ERR_LIBRARY
;
562 goto make_evt_done_put2
;
564 memcpy(edi
->edi_patterns
.patterns
[i
].pattern
,
565 str
, pat
->pattern_size
);
566 str
+= pat
->pattern_size
;
570 hl
= malloc(sizeof(*hl
));
572 saHandleDestroy(&event_handle_db
, *event_handle
);
573 error
= SA_AIS_ERR_LIBRARY
;
576 hl
->hl_handle
= *event_handle
;
577 list_init(&hl
->hl_entry
);
578 list_add(&hl
->hl_entry
, &eci
->eci_event_list
);
582 saHandleInstancePut (&channel_handle_db
, evt
->led_lib_channel_handle
);
585 saHandleInstancePut (&event_handle_db
, *event_handle
);
592 * The saEvtDispatch() function invokes, in the context of the calling
593 * thread, one or all of the pending callbacks for the handle evtHandle.
597 SaEvtHandleT evtHandle
,
598 SaDispatchFlagsT dispatchFlags
)
604 struct event_instance
*evti
;
605 SaEvtEventHandleT event_handle
;
606 SaEvtCallbacksT callbacks
;
607 int ignore_dispatch
= 0;
608 int cont
= 1; /* always continue do loop except when set to 0 */
610 struct lib_event_data
*evt
= 0;
611 struct res_evt_event_data res
;
613 if (dispatchFlags
< SA_DISPATCH_ONE
||
614 dispatchFlags
> SA_DISPATCH_BLOCKING
) {
615 return SA_AIS_ERR_INVALID_PARAM
;
618 error
= saHandleInstanceGet(&evt_instance_handle_db
, evtHandle
,
620 if (error
!= SA_AIS_OK
) {
625 * Timeout instantly for SA_DISPATCH_ALL
627 if (dispatchFlags
== SA_DISPATCH_ALL
|| dispatchFlags
== SA_DISPATCH_ONE
) {
632 poll_fd
= evti
->ei_dispatch_fd
;
635 ufds
.events
= POLLIN
;
638 error
= saPollRetry(&ufds
, 1, timeout
);
639 if (error
!= SA_AIS_OK
) {
643 pthread_mutex_lock(&evti
->ei_dispatch_mutex
);
646 * Handle has been finalized in another thread
648 if (evti
->ei_finalize
== 1) {
650 goto dispatch_unlock
;
654 * If we know that we have an event waiting, we can skip the
655 * polling and just ask for it.
657 if (!evti
->ei_data_available
) {
659 * Check the poll data in case the fd status has changed
660 * since taking the lock
662 error
= saPollRetry(&ufds
, 1, 0);
663 if (error
!= SA_AIS_OK
) {
664 goto dispatch_unlock
;
667 if ((ufds
.revents
& (POLLERR
|POLLHUP
|POLLNVAL
)) != 0) {
668 error
= SA_AIS_ERR_BAD_HANDLE
;
669 goto dispatch_unlock
;
672 dispatch_avail
= ufds
.revents
& POLLIN
;
673 if (dispatch_avail
== 0 &&
674 (dispatchFlags
== SA_DISPATCH_ALL
||
675 dispatchFlags
== SA_DISPATCH_ONE
)) {
676 pthread_mutex_unlock(&evti
->ei_dispatch_mutex
);
677 break; /* exit do while cont is 1 loop */
678 } else if (dispatch_avail
== 0) {
679 pthread_mutex_unlock(&evti
->ei_dispatch_mutex
);
680 continue; /* next poll */
683 if (ufds
.revents
& POLLIN
) {
684 error
= saRecvRetry (evti
->ei_dispatch_fd
, &evti
->ei_dispatch_data
.header
,
685 sizeof (mar_res_header_t
));
687 if (error
!= SA_AIS_OK
) {
688 goto dispatch_unlock
;
690 if (evti
->ei_dispatch_data
.header
.size
> sizeof (mar_res_header_t
)) {
691 error
= saRecvRetry (evti
->ei_dispatch_fd
, &evti
->ei_dispatch_data
.data
,
692 evti
->ei_dispatch_data
.header
.size
- sizeof (mar_res_header_t
));
693 if (error
!= SA_AIS_OK
) {
694 goto dispatch_unlock
;
698 pthread_mutex_unlock(&evti
->ei_dispatch_mutex
);
703 * We know that we have an event available from before.
704 * Fake up a header message and the switch statement will
705 * take care of the rest.
707 evti
->ei_dispatch_data
.header
.id
= MESSAGE_RES_EVT_AVAILABLE
;
711 * Make copy of callbacks, message data, unlock instance,
712 * and call callback. A risk of this dispatch method is that
713 * the callback routines may operate at the same time that
714 * EvtFinalize has been called in another thread.
716 memcpy(&callbacks
, &evti
->ei_callback
, sizeof(evti
->ei_callback
));
719 * Dispatch incoming response
721 switch (evti
->ei_dispatch_data
.header
.id
) {
723 case MESSAGE_RES_EVT_AVAILABLE
:
724 evti
->ei_data_available
= 0;
726 * There are events available. Send a request for one and then
729 res
.evd_head
.id
= MESSAGE_REQ_EVT_EVENT_DATA
;
730 res
.evd_head
.size
= sizeof(res
);
732 pthread_mutex_lock(&evti
->ei_response_mutex
);
733 error
= saSendRetry(evti
->ei_response_fd
, &res
, sizeof(res
));
735 if (error
!= SA_AIS_OK
) {
736 DPRINT (("MESSAGE_RES_EVT_AVAILABLE: send failed: %d\n", error
));
737 pthread_mutex_unlock(&evti
->ei_response_mutex
);
740 error
= evt_recv_event(evti
->ei_response_fd
, &evt
);
741 pthread_mutex_unlock(&evti
->ei_response_mutex
);
743 if (error
!= SA_AIS_OK
) {
744 DPRINT (("MESSAGE_RES_EVT_AVAILABLE: receive failed: %d\n", error
));
748 * No data available. This is OK, another thread may have
751 if (evt
->led_head
.error
== SA_AIS_ERR_NOT_EXIST
) {
756 if (evt
->led_head
.error
!= SA_AIS_OK
) {
757 error
= evt
->led_head
.error
;
760 * If we get a try again response, we've lost the poll event
761 * so we have a data available flag so that we know that there
762 * really is an event waiting the next time dispatch gets
765 if (error
== SA_AIS_ERR_TRY_AGAIN
) {
766 evti
->ei_data_available
= 1;
768 DPRINT (("MESSAGE_RES_EVT_AVAILABLE: Error returned: %d\n", error
));
773 error
= make_event(&event_handle
, evt
);
774 if (error
!= SA_AIS_OK
) {
779 * Only call if there was a function registered
781 if (callbacks
.saEvtEventDeliverCallback
) {
782 callbacks
.saEvtEventDeliverCallback(evt
->led_sub_id
,
783 event_handle
, evt
->led_user_data_size
);
787 case MESSAGE_RES_EVT_CHAN_OPEN_CALLBACK
:
789 struct res_evt_open_chan_async
*resa
=
790 (struct res_evt_open_chan_async
*)&evti
->ei_dispatch_data
;
791 struct event_channel_instance
*eci
;
794 * Check for errors. If there are none, then
795 * look up the local channel via the handle that we
796 * got from the callback request. All we need to do
797 * is place in the handle from the server side and then
798 * we can call the callback.
800 error
= resa
->ica_head
.error
;
801 if (error
== SA_AIS_OK
) {
802 error
= saHandleInstanceGet(&channel_handle_db
,
803 resa
->ica_c_handle
, (void*)&eci
);
804 if (error
== SA_AIS_OK
) {
805 eci
->eci_svr_channel_handle
= resa
->ica_channel_handle
;
806 saHandleInstancePut (&channel_handle_db
,
812 * Only call if there was a function registered
814 if (callbacks
.saEvtChannelOpenCallback
) {
815 callbacks
.saEvtChannelOpenCallback(resa
->ica_invocation
,
816 resa
->ica_c_handle
, error
);
823 DPRINT (("Dispatch: Bad message type 0x%x\n", evti
->ei_dispatch_data
.header
.id
));
824 error
= SA_AIS_ERR_LIBRARY
;
825 goto dispatch_unlock
;
828 pthread_mutex_unlock(&evti
->ei_dispatch_mutex
);
831 * If empty is zero it means the we got the
832 * message from the queue and we are responsible
841 * Determine if more messages should be processed
843 switch (dispatchFlags
) {
844 case SA_DISPATCH_ONE
:
845 if (ignore_dispatch
) {
851 case SA_DISPATCH_ALL
:
852 if (ignore_dispatch
) {
856 case SA_DISPATCH_BLOCKING
:
864 pthread_mutex_unlock(&evti
->ei_dispatch_mutex
);
866 saHandleInstancePut(&evt_instance_handle_db
, evtHandle
);
871 * The saEvtFinalize() function closes the association, represented by the
872 * evtHandle parameter, between the process and the Event Service. It may
874 * This function cannot be invoked before the process has invoked the
875 * corresponding saEvtInitialize() function for the Event Service. After
876 * this function is invoked, the selection object is no longer valid.
877 * Moreover, the Event Service is unavailable for further use unless it is
878 * reinitialized using the saEvtInitialize() function.
881 saEvtFinalize(SaEvtHandleT evtHandle
)
883 struct event_instance
*evti
;
886 error
= saHandleInstanceGet(&evt_instance_handle_db
, evtHandle
,
888 if (error
!= SA_AIS_OK
) {
892 pthread_mutex_lock(&evti
->ei_response_mutex
);
895 * Another thread has already started finalizing
897 if (evti
->ei_finalize
) {
898 pthread_mutex_unlock(&evti
->ei_response_mutex
);
899 saHandleInstancePut(&evt_instance_handle_db
, evtHandle
);
900 return SA_AIS_ERR_BAD_HANDLE
;
903 evti
->ei_finalize
= 1;
905 pthread_mutex_unlock(&evti
->ei_response_mutex
);
907 saHandleDestroy(&evt_instance_handle_db
, evtHandle
);
909 * Disconnect from the server
911 if (evti
->ei_response_fd
!= -1) {
912 shutdown(evti
->ei_response_fd
, 0);
913 close(evti
->ei_response_fd
);
916 if (evti
->ei_dispatch_fd
!= -1) {
917 shutdown(evti
->ei_dispatch_fd
, 0);
918 close(evti
->ei_dispatch_fd
);
920 saHandleInstancePut(&evt_instance_handle_db
, evtHandle
);
926 * The saEvtChannelOpen() function creates a new event channel or open an
927 * existing channel. The saEvtChannelOpen() function is a blocking operation
928 * and returns a new event channel handle. An event channel may be opened
929 * multiple times by the same or different processes for publishing, and
930 * subscribing to, events. If a process opens an event channel multiple
931 * times, it is possible to receive the same event multiple times. However,
932 * a process shall never receive an event more than once on a particular
933 * event channel handle. If a process opens a channel twice and an event is
934 * matched on both open channels, the Event Service performs two
935 * callbacks -- one for each opened channel.
939 SaEvtHandleT evtHandle
,
940 const SaNameT
*channelName
,
941 SaEvtChannelOpenFlagsT channelOpenFlags
,
943 SaEvtChannelHandleT
*channelHandle
)
945 struct event_instance
*evti
;
946 struct req_evt_channel_open req
;
947 struct res_evt_channel_open res
;
948 struct event_channel_instance
*eci
;
949 struct handle_list
*hl
;
953 if (!channelHandle
|| !channelName
) {
954 return SA_AIS_ERR_INVALID_PARAM
;
957 if ((channelOpenFlags
& ~(SA_EVT_CHANNEL_CREATE
|SA_EVT_CHANNEL_PUBLISHER
|
958 SA_EVT_CHANNEL_SUBSCRIBER
)) != 0) {
959 return SA_AIS_ERR_BAD_FLAGS
;
963 return (SA_AIS_ERR_TIMEOUT
);
965 error
= saHandleInstanceGet(&evt_instance_handle_db
, evtHandle
,
968 if (error
!= SA_AIS_OK
) {
973 * create a handle for this open channel
975 error
= saHandleCreate(&channel_handle_db
, sizeof(*eci
),
977 if (error
!= SA_AIS_OK
) {
982 error
= saHandleInstanceGet(&channel_handle_db
, *channelHandle
,
984 if (error
!= SA_AIS_OK
) {
985 saHandleDestroy(&channel_handle_db
, *channelHandle
);
989 list_init(&eci
->eci_event_list
);
992 * Send the request to the server and wait for a response
994 req
.ico_head
.size
= sizeof(req
);
995 req
.ico_head
.id
= MESSAGE_REQ_EVT_OPEN_CHANNEL
;
996 req
.ico_c_handle
= *channelHandle
;
997 req
.ico_timeout
= timeout
;
998 req
.ico_open_flag
= channelOpenFlags
;
999 marshall_to_mar_name_t (&req
.ico_channel_name
, (SaNameT
*)channelName
);
1001 iov
.iov_base
= (char *)&req
;
1002 iov
.iov_len
= sizeof(req
);
1004 pthread_mutex_lock(&evti
->ei_response_mutex
);
1006 error
= saSendMsgReceiveReply(evti
->ei_response_fd
, &iov
, 1,
1009 pthread_mutex_unlock (&evti
->ei_response_mutex
);
1011 if (error
!= SA_AIS_OK
) {
1012 goto chan_open_free
;
1015 if (res
.ico_head
.id
!= MESSAGE_RES_EVT_OPEN_CHANNEL
) {
1016 error
= SA_AIS_ERR_LIBRARY
;
1017 goto chan_open_free
;
1020 error
= res
.ico_head
.error
;
1021 if (error
!= SA_AIS_OK
) {
1022 goto chan_open_free
;
1025 eci
->eci_svr_channel_handle
= res
.ico_channel_handle
;
1026 eci
->eci_channel_name
= *channelName
;
1027 eci
->eci_open_flags
= channelOpenFlags
;
1028 eci
->eci_instance_handle
= evtHandle
;
1029 eci
->eci_closing
= 0;
1030 hl
= malloc(sizeof(*hl
));
1032 error
= SA_AIS_ERR_NO_MEMORY
;
1033 goto chan_open_free
;
1036 hl
->hl_handle
= *channelHandle
;
1037 list_init(&hl
->hl_entry
);
1038 list_add(&hl
->hl_entry
, &evti
->ei_channel_list
);
1040 pthread_mutex_init(&eci
->eci_mutex
, NULL
);
1041 saHandleInstancePut (&evt_instance_handle_db
, evtHandle
);
1042 saHandleInstancePut (&channel_handle_db
, *channelHandle
);
1047 saHandleDestroy(&channel_handle_db
, *channelHandle
);
1048 saHandleInstancePut (&channel_handle_db
, *channelHandle
);
1050 saHandleInstancePut (&evt_instance_handle_db
, evtHandle
);
1056 * The saEvtChannelClose() function closes an event channel and frees
1057 * resources allocated for that event channel in the invoking process.
1061 saEvtChannelClose(SaEvtChannelHandleT channelHandle
)
1064 struct event_instance
*evti
;
1065 struct event_channel_instance
*eci
;
1066 struct req_evt_channel_close req
;
1067 struct res_evt_channel_close res
;
1070 error
= saHandleInstanceGet(&channel_handle_db
, channelHandle
,
1072 if (error
!= SA_AIS_OK
) {
1073 goto chan_close_done
;
1077 * get the evt handle for the fd
1079 error
= saHandleInstanceGet(&evt_instance_handle_db
,
1080 eci
->eci_instance_handle
, (void*)&evti
);
1081 if (error
!= SA_AIS_OK
) {
1082 goto chan_close_put1
;
1086 * Make sure that the channel isn't being closed elsewhere
1088 pthread_mutex_lock(&eci
->eci_mutex
);
1089 if (eci
->eci_closing
) {
1090 pthread_mutex_unlock(&eci
->eci_mutex
);
1091 saHandleInstancePut(&channel_handle_db
, channelHandle
);
1092 return SA_AIS_ERR_BAD_HANDLE
;
1094 eci
->eci_closing
= 1;
1095 pthread_mutex_unlock(&eci
->eci_mutex
);
1099 * Send the request to the server and wait for a response
1101 req
.icc_head
.size
= sizeof(req
);
1102 req
.icc_head
.id
= MESSAGE_REQ_EVT_CLOSE_CHANNEL
;
1103 req
.icc_channel_handle
= eci
->eci_svr_channel_handle
;
1105 iov
.iov_base
= (char *)&req
;
1106 iov
.iov_len
= sizeof (req
);
1108 pthread_mutex_lock(&evti
->ei_response_mutex
);
1110 error
= saSendMsgReceiveReply (evti
->ei_response_fd
, &iov
, 1,
1111 &res
, sizeof (res
));
1113 pthread_mutex_unlock(&evti
->ei_response_mutex
);
1115 if (error
!= SA_AIS_OK
) {
1116 eci
->eci_closing
= 0;
1117 goto chan_close_put2
;
1119 if (res
.icc_head
.id
!= MESSAGE_RES_EVT_CLOSE_CHANNEL
) {
1120 error
= SA_AIS_ERR_LIBRARY
;
1121 eci
->eci_closing
= 0;
1122 goto chan_close_put2
;
1125 error
= res
.icc_head
.error
;
1126 if (error
== SA_AIS_ERR_TRY_AGAIN
) {
1127 pthread_mutex_lock(&eci
->eci_mutex
);
1128 eci
->eci_closing
= 0;
1129 pthread_mutex_unlock(&eci
->eci_mutex
);
1130 goto chan_close_put2
;
1133 saHandleInstancePut(&evt_instance_handle_db
,
1134 eci
->eci_instance_handle
);
1135 saHandleDestroy(&channel_handle_db
, channelHandle
);
1136 saHandleInstancePut(&channel_handle_db
, channelHandle
);
1141 saHandleInstancePut(&evt_instance_handle_db
,
1142 eci
->eci_instance_handle
);
1144 saHandleInstancePut(&channel_handle_db
, channelHandle
);
1150 * The saEvtChannelOpenAsync() function creates a new event channel or open an
1151 * existing channel. The saEvtChannelOpenAsync() function is a non-blocking
1152 * operation. A new event channel handle is returned in the channel open
1153 * callback function (SaEvtChannelOpenCallbackT).
1156 saEvtChannelOpenAsync(SaEvtHandleT evtHandle
,
1157 SaInvocationT invocation
,
1158 const SaNameT
*channelName
,
1159 SaEvtChannelOpenFlagsT channelOpenFlags
)
1161 struct event_instance
*evti
;
1162 struct req_evt_channel_open req
;
1163 struct res_evt_channel_open res
;
1164 struct event_channel_instance
*eci
;
1165 SaEvtChannelHandleT channel_handle
;
1167 struct handle_list
*hl
;
1171 return SA_AIS_ERR_INVALID_PARAM
;
1174 if ((channelOpenFlags
& ~(SA_EVT_CHANNEL_CREATE
|SA_EVT_CHANNEL_PUBLISHER
|
1175 SA_EVT_CHANNEL_SUBSCRIBER
)) != 0) {
1176 return SA_AIS_ERR_BAD_FLAGS
;
1179 error
= saHandleInstanceGet(&evt_instance_handle_db
, evtHandle
,
1182 if (error
!= SA_AIS_OK
) {
1183 goto chan_open_done
;
1187 * Make sure that an open channel callback has been
1188 * registered before allowing the open to continue.
1190 if (!evti
->ei_callback
.saEvtChannelOpenCallback
) {
1191 error
= SA_AIS_ERR_INIT
;
1196 * create a handle for this open channel
1198 error
= saHandleCreate(&channel_handle_db
, sizeof(*eci
),
1200 if (error
!= SA_AIS_OK
) {
1205 error
= saHandleInstanceGet(&channel_handle_db
, channel_handle
,
1207 if (error
!= SA_AIS_OK
) {
1208 saHandleDestroy(&channel_handle_db
, channel_handle
);
1212 list_init(&eci
->eci_event_list
);
1215 * Send the request to the server. The response isn't the open channel,
1216 * just an ack. The open channel will be returned when the channel open
1217 * callback is called.
1219 req
.ico_head
.size
= sizeof(req
);
1220 req
.ico_head
.id
= MESSAGE_REQ_EVT_OPEN_CHANNEL_ASYNC
;
1221 req
.ico_c_handle
= channel_handle
;
1222 req
.ico_timeout
= 0;
1223 req
.ico_invocation
= invocation
;
1224 req
.ico_open_flag
= channelOpenFlags
;
1225 marshall_to_mar_name_t (&req
.ico_channel_name
, (SaNameT
*)channelName
);
1226 iov
.iov_base
= (char *)&req
;
1227 iov
.iov_len
= sizeof(req
);
1230 pthread_mutex_lock(&evti
->ei_response_mutex
);
1232 error
= saSendMsgReceiveReply (evti
->ei_response_fd
, &iov
, 1,
1233 &res
, sizeof (res
));
1235 pthread_mutex_unlock(&evti
->ei_response_mutex
);
1237 if (error
!= SA_AIS_OK
) {
1238 goto chan_open_free
;
1241 if (res
.ico_head
.id
!= MESSAGE_RES_EVT_OPEN_CHANNEL
) {
1242 error
= SA_AIS_ERR_LIBRARY
;
1243 goto chan_open_free
;
1246 error
= res
.ico_head
.error
;
1247 if (error
!= SA_AIS_OK
) {
1248 goto chan_open_free
;
1251 eci
->eci_svr_channel_handle
= 0; /* filled in by callback */
1252 eci
->eci_channel_name
= *channelName
;
1253 eci
->eci_open_flags
= channelOpenFlags
;
1254 eci
->eci_instance_handle
= evtHandle
;
1255 eci
->eci_closing
= 0;
1256 list_init(&eci
->eci_event_list
);
1257 hl
= malloc(sizeof(*hl
));
1259 error
= SA_AIS_ERR_NO_MEMORY
;
1260 goto chan_open_free
;
1263 hl
->hl_handle
= channel_handle
;
1264 list_init(&hl
->hl_entry
);
1265 list_add(&hl
->hl_entry
, &evti
->ei_channel_list
);
1267 pthread_mutex_init(&eci
->eci_mutex
, NULL
);
1268 saHandleInstancePut (&evt_instance_handle_db
, evtHandle
);
1269 saHandleInstancePut (&channel_handle_db
, channel_handle
);
1274 saHandleDestroy(&channel_handle_db
, channel_handle
);
1275 saHandleInstancePut (&channel_handle_db
, channel_handle
);
1277 saHandleInstancePut (&evt_instance_handle_db
, evtHandle
);
1282 * The SaEvtChannelUnlink function deletes an existing event channel
1285 * After completion of the invocation:
1286 * - An open of the channel name without a create will fail.
1287 * - The channel remains available to any already opened instances.
1288 * - If an open/create is performed on this channel name a new instance
1290 * - The ulinked channel's resources will be deleted when the last open
1291 * instance is closed.
1293 * Note that an event channel is only deleted from the cluster
1294 * namespace when saEvtChannelUnlink() is invoked on it. The deletion
1295 * of an event channel frees all resources allocated by the Event
1296 * Service for it, such as published events with non-zero retention
1301 SaEvtHandleT evtHandle
,
1302 const SaNameT
*channelName
)
1304 struct event_instance
*evti
;
1305 struct req_evt_channel_unlink req
;
1306 struct res_evt_channel_unlink res
;
1311 return SA_AIS_ERR_INVALID_PARAM
;
1314 error
= saHandleInstanceGet(&evt_instance_handle_db
, evtHandle
,
1317 if (error
!= SA_AIS_OK
) {
1318 goto chan_unlink_done
;
1322 * Send the request to the server and wait for a response
1324 req
.iuc_head
.size
= sizeof(req
);
1325 req
.iuc_head
.id
= MESSAGE_REQ_EVT_UNLINK_CHANNEL
;
1326 marshall_to_mar_name_t (&req
.iuc_channel_name
, (SaNameT
*)channelName
);
1327 iov
.iov_base
= (char *)&req
;
1328 iov
.iov_len
= sizeof(req
);
1331 pthread_mutex_lock(&evti
->ei_response_mutex
);
1333 error
= saSendMsgReceiveReply (evti
->ei_response_fd
, &iov
, 1,
1334 &res
, sizeof (res
));
1336 pthread_mutex_unlock(&evti
->ei_response_mutex
);
1338 if (error
!= SA_AIS_OK
) {
1339 goto chan_unlink_put
;
1342 if (res
.iuc_head
.id
!= MESSAGE_RES_EVT_UNLINK_CHANNEL
) {
1343 error
= SA_AIS_ERR_LIBRARY
;
1344 goto chan_unlink_put
;
1347 error
= res
.iuc_head
.error
;
1350 saHandleInstancePut (&evt_instance_handle_db
, evtHandle
);
1356 * The saEvtEventAllocate() function allocates memory for the event, but not
1357 * for the eventHandle, and initializes all event attributes to default values.
1358 * The event allocated by saEvtEventAllocate() is freed by invoking
1360 * The memory associated with the eventHandle is not deallocated by the
1361 * saEvtEventAllocate() function or the saEvtEventFree() function. It is the
1362 * responsibility of the invoking process to deallocate the memory for the
1363 * eventHandle when the process has published the event and has freed the
1364 * event by invoking saEvtEventFree().
1368 const SaEvtChannelHandleT channelHandle
,
1369 SaEvtEventHandleT
*eventHandle
)
1372 struct event_data_instance
*edi
;
1373 struct event_instance
*evti
;
1374 struct event_channel_instance
*eci
;
1375 struct handle_list
*hl
;
1378 return SA_AIS_ERR_INVALID_PARAM
;
1381 error
= saHandleInstanceGet(&channel_handle_db
, channelHandle
,
1383 if (error
!= SA_AIS_OK
) {
1387 error
= saHandleInstanceGet(&evt_instance_handle_db
,
1388 eci
->eci_instance_handle
, (void*)&evti
);
1389 if (error
!= SA_AIS_OK
) {
1393 error
= saHandleCreate(&event_handle_db
, sizeof(*edi
),
1395 if (error
!= SA_AIS_OK
) {
1398 error
= saHandleInstanceGet(&event_handle_db
, *eventHandle
,
1400 if (error
!= SA_AIS_OK
) {
1401 saHandleDestroy(&event_handle_db
, *eventHandle
);
1405 pthread_mutex_init(&edi
->edi_mutex
, NULL
);
1407 edi
->edi_freeing
= 0;
1408 edi
->edi_channel_handle
= channelHandle
;
1409 edi
->edi_pub_node
= evti
->ei_node_id
;
1410 edi
->edi_priority
= SA_EVT_LOWEST_PRIORITY
;
1411 edi
->edi_event_id
= SA_EVT_EVENTID_NONE
;
1412 edi
->edi_pub_time
= SA_TIME_UNKNOWN
;
1413 edi
->edi_retention_time
= 0;
1414 hl
= malloc(sizeof(*hl
));
1416 saHandleDestroy(&event_handle_db
, *eventHandle
);
1417 error
= SA_AIS_ERR_NO_MEMORY
;
1421 hl
->hl_handle
= *eventHandle
;
1422 list_init(&hl
->hl_entry
);
1423 list_add(&hl
->hl_entry
, &eci
->eci_event_list
);
1426 saHandleInstancePut (&event_handle_db
, *eventHandle
);
1429 saHandleInstancePut (&evt_instance_handle_db
, eci
->eci_instance_handle
);
1431 saHandleInstancePut (&channel_handle_db
, channelHandle
);
1437 * The saEvtEventFree() function gives the Event Service premission to
1438 * deallocate the memory that contains the attributes of the event that is
1439 * associated with eventHandle. The function is used to free events allocated
1440 * by saEvtEventAllocate() and by saEvtEventDeliverCallback().
1443 saEvtEventFree(SaEvtEventHandleT eventHandle
)
1446 struct event_data_instance
*edi
;
1448 error
= saHandleInstanceGet(&event_handle_db
, eventHandle
,
1450 if (error
!= SA_AIS_OK
) {
1455 * Make sure that the event isn't being freed elsewhere
1457 pthread_mutex_lock(&edi
->edi_mutex
);
1458 if (edi
->edi_freeing
) {
1459 pthread_mutex_unlock(&edi
->edi_mutex
);
1460 saHandleInstancePut(&event_handle_db
, eventHandle
);
1461 return SA_AIS_ERR_BAD_HANDLE
;
1463 edi
->edi_freeing
= 1;
1465 pthread_mutex_unlock(&edi
->edi_mutex
);
1466 saHandleDestroy(&event_handle_db
, eventHandle
);
1467 saHandleInstancePut(&event_handle_db
, eventHandle
);
1474 * This function may be used to assign writeable event attributes. It takes
1475 * as arguments an event handle eventHandle and the attribute to be set in
1476 * the event structure of the event with that handle. Note: The only
1477 * attributes that a process can set are the patternArray, priority,
1478 * retentionTime and publisherName attributes.
1481 saEvtEventAttributesSet(
1482 const SaEvtEventHandleT eventHandle
,
1483 const SaEvtEventPatternArrayT
*patternArray
,
1484 SaEvtEventPriorityT priority
,
1485 SaTimeT retentionTime
,
1486 const SaNameT
*publisherName
)
1488 SaEvtEventPatternT
*oldpatterns
;
1491 struct event_data_instance
*edi
;
1494 if (priority
> SA_EVT_LOWEST_PRIORITY
) {
1495 return SA_AIS_ERR_INVALID_PARAM
;
1498 error
= saHandleInstanceGet(&event_handle_db
, eventHandle
,
1500 if (error
!= SA_AIS_OK
) {
1503 pthread_mutex_lock(&edi
->edi_mutex
);
1506 * Cannot modify an event returned via callback.
1509 error
= SA_AIS_ERR_ACCESS
;
1510 goto attr_set_unlock
;
1513 edi
->edi_priority
= priority
;
1514 edi
->edi_retention_time
= retentionTime
;
1516 if (publisherName
) {
1517 edi
->edi_pub_name
= *publisherName
;
1520 if (!patternArray
) {
1521 goto attr_set_unlock
;
1524 oldpatterns
= edi
->edi_patterns
.patterns
;
1525 oldnumber
= edi
->edi_patterns
.patternsNumber
;
1526 edi
->edi_patterns
.patterns
= 0;
1527 edi
->edi_patterns
.patterns
= malloc(sizeof(SaEvtEventPatternT
) *
1528 patternArray
->patternsNumber
);
1529 if (!edi
->edi_patterns
.patterns
) {
1530 error
= SA_AIS_ERR_NO_MEMORY
;
1531 goto attr_set_done_reset
;
1533 edi
->edi_patterns
.patternsNumber
= patternArray
->patternsNumber
;
1534 edi
->edi_patterns
.allocatedNumber
= patternArray
->patternsNumber
;
1537 * copy the patterns from the caller. allocating memory for
1538 * of all the strings.
1540 for (i
= 0; i
< patternArray
->patternsNumber
; i
++) {
1541 edi
->edi_patterns
.patterns
[i
].pattern
=
1542 malloc(patternArray
->patterns
[i
].patternSize
);
1543 if (!edi
->edi_patterns
.patterns
[i
].pattern
) {
1545 for (j
= 0; j
< i
; j
++) {
1546 free(edi
->edi_patterns
.patterns
[j
].pattern
);
1548 free(edi
->edi_patterns
.patterns
);
1549 error
= SA_AIS_ERR_NO_MEMORY
;
1550 goto attr_set_done_reset
;
1552 memcpy(edi
->edi_patterns
.patterns
[i
].pattern
,
1553 patternArray
->patterns
[i
].pattern
,
1554 patternArray
->patterns
[i
].patternSize
);
1555 edi
->edi_patterns
.patterns
[i
].patternSize
=
1556 patternArray
->patterns
[i
].patternSize
;
1557 edi
->edi_patterns
.patterns
[i
].allocatedSize
=
1558 patternArray
->patterns
[i
].patternSize
;
1562 * free up the old pattern memory
1565 for (i
= 0; i
< oldnumber
; i
++) {
1566 if (oldpatterns
[i
].pattern
) {
1567 free(oldpatterns
[i
].pattern
);
1572 goto attr_set_unlock
;
1574 attr_set_done_reset
:
1575 edi
->edi_patterns
.patterns
= oldpatterns
;
1576 edi
->edi_patterns
.patternsNumber
= oldnumber
;
1578 pthread_mutex_unlock(&edi
->edi_mutex
);
1579 saHandleInstancePut(&event_handle_db
, eventHandle
);
1585 * This function takes as parameters an event handle eventHandle and the
1586 * attributes of the event with that handle. The function retrieves the
1587 * value of the attributes for the event and stores them at the address
1588 * provided for the out parameters.
1589 * It is the responsibility of the invoking process to allocate memory for
1590 * the out parameters before it invokes this function. The Event Service
1591 * assigns the out values into that memory. For each of the out, or in/out,
1592 * parameters, if the invoking process provides a NULL reference, the
1593 * Availability Management Framework does not return the out value.
1594 * Similarly, it is the responsibility of the invoking process to allocate
1595 * memory for the patternArray.
1598 saEvtEventAttributesGet(
1599 SaEvtEventHandleT eventHandle
,
1600 SaEvtEventPatternArrayT
*patternArray
,
1601 SaEvtEventPriorityT
*priority
,
1602 SaTimeT
*retentionTime
,
1603 SaNameT
*publisherName
,
1604 SaTimeT
*publishTime
,
1605 SaEvtEventIdT
*eventId
)
1608 struct event_data_instance
*edi
;
1612 error
= saHandleInstanceGet(&event_handle_db
, eventHandle
,
1614 if (error
!= SA_AIS_OK
) {
1617 pthread_mutex_lock(&edi
->edi_mutex
);
1620 * Go through the args and send back information if the pointer
1624 *eventId
= edi
->edi_event_id
;
1628 *publishTime
= edi
->edi_pub_time
;
1631 if (publisherName
) {
1632 *publisherName
= edi
->edi_pub_name
;
1635 if (retentionTime
) {
1636 *retentionTime
= edi
->edi_retention_time
;
1640 *priority
= edi
->edi_priority
;
1643 if (!patternArray
) {
1644 goto attr_get_unlock
;
1648 * The spec says that if the called passes in a NULL patterns array,
1649 * then we allocate the required data and the caller is responsible
1650 * for dealocating later. Otherwise, we copy to pre-allocated space.
1651 * If there are more patterns than allcated space, we set the return
1652 * code to SA_AIS_ERR_NO_SPACE and copy as much as will fit. We will
1653 * return the total number of patterns available in the patternsNumber
1654 * regardless of how much was allocated.
1657 if (patternArray
->patterns
== NULL
) {
1658 npats
= edi
->edi_patterns
.patternsNumber
;
1659 patternArray
->allocatedNumber
= edi
->edi_patterns
.patternsNumber
;
1660 patternArray
->patternsNumber
= edi
->edi_patterns
.patternsNumber
;
1661 patternArray
->patterns
= malloc(sizeof(*patternArray
->patterns
) *
1662 edi
->edi_patterns
.patternsNumber
);
1663 if (!patternArray
->patterns
) {
1664 error
= SA_AIS_ERR_LIBRARY
;
1665 goto attr_get_unlock
;
1667 for (i
= 0; i
< edi
->edi_patterns
.patternsNumber
; i
++) {
1668 patternArray
->patterns
[i
].allocatedSize
=
1669 edi
->edi_patterns
.patterns
[i
].allocatedSize
;
1670 patternArray
->patterns
[i
].patternSize
=
1671 edi
->edi_patterns
.patterns
[i
].patternSize
;
1672 patternArray
->patterns
[i
].pattern
=
1673 malloc(edi
->edi_patterns
.patterns
[i
].patternSize
);
1674 if (!patternArray
->patterns
[i
].pattern
) {
1677 * back out previous mallocs
1679 for (j
= 0; j
< i
; j
++) {
1680 free(patternArray
->patterns
[j
].pattern
);
1682 free(patternArray
->patterns
);
1685 * saEvtEventAttributesGet doesn't return
1686 * SA_AIS_ERR_NO_MEMORY
1688 error
= SA_AIS_ERR_LIBRARY
;
1689 goto attr_get_unlock
;
1693 if (patternArray
->allocatedNumber
< edi
->edi_patterns
.allocatedNumber
) {
1694 error
= SA_AIS_ERR_NO_SPACE
;
1695 npats
= patternArray
->allocatedNumber
;
1697 npats
= edi
->edi_patterns
.patternsNumber
;
1700 patternArray
->patternsNumber
= edi
->edi_patterns
.patternsNumber
;
1703 * copy the patterns to the callers structure. If we have pre-allocated
1704 * data, the patterns may not fit in the supplied space. In that case we
1707 for (i
= 0; i
< npats
; i
++) {
1709 memcpy(patternArray
->patterns
[i
].pattern
,
1710 edi
->edi_patterns
.patterns
[i
].pattern
,
1711 min(patternArray
->patterns
[i
].allocatedSize
,
1712 edi
->edi_patterns
.patterns
[i
].patternSize
));
1714 if (patternArray
->patterns
[i
].allocatedSize
<
1715 edi
->edi_patterns
.patterns
[i
].patternSize
) {
1716 error
= SA_AIS_ERR_NO_SPACE
;
1719 patternArray
->patterns
[i
].patternSize
=
1720 edi
->edi_patterns
.patterns
[i
].patternSize
;
1724 pthread_mutex_unlock(&edi
->edi_mutex
);
1725 saHandleInstancePut(&event_handle_db
, eventHandle
);
1731 * The saEvtEventDataGet() function allows a process to retrieve the data
1732 * associated with an event previously delivered by
1733 * saEvtEventDeliverCallback().
1737 const SaEvtEventHandleT eventHandle
,
1739 SaSizeT
*eventDataSize
)
1741 SaAisErrorT error
= SA_AIS_ERR_INVALID_PARAM
;
1742 struct event_data_instance
*edi
;
1745 if (!eventDataSize
) {
1749 error
= saHandleInstanceGet(&event_handle_db
, eventHandle
,
1751 if (error
!= SA_AIS_OK
) {
1754 pthread_mutex_lock(&edi
->edi_mutex
);
1757 * If no buffer was supplied, then just tell the caller
1758 * how large a buffer is needed.
1761 error
= SA_AIS_ERR_NO_SPACE
;
1762 *eventDataSize
= edi
->edi_event_data_size
;
1767 * Can't get data from an event that wasn't
1768 * a delivered event.
1771 error
= SA_AIS_ERR_BAD_HANDLE
;
1775 if (edi
->edi_event_data
&& edi
->edi_event_data_size
) {
1776 xfsize
= min(*eventDataSize
, edi
->edi_event_data_size
);
1777 if (*eventDataSize
< edi
->edi_event_data_size
) {
1778 error
= SA_AIS_ERR_NO_SPACE
;
1780 *eventDataSize
= edi
->edi_event_data_size
;
1781 memcpy(eventData
, edi
->edi_event_data
, xfsize
);
1787 pthread_mutex_unlock(&edi
->edi_mutex
);
1788 saHandleInstancePut(&event_handle_db
, eventHandle
);
1794 * Calculate the size in bytes for patterns
1796 static size_t patt_size(const SaEvtEventPatternArrayT
*patterns
)
1799 size_t size
= sizeof(mar_evt_event_pattern_array_t
);
1800 for (i
= 0; i
< patterns
->patternsNumber
; i
++) {
1801 size
+= sizeof(mar_evt_event_pattern_t
);
1802 size
+= patterns
->patterns
[i
].patternSize
;
1808 * copy patterns to a form for sending to the server
1810 static uint32_t aispatt_to_evt_patt(
1811 const SaEvtEventPatternArrayT
*patterns
,
1815 mar_evt_event_pattern_t
*pats
= data
;
1816 SaUint8T
*str
= (SaUint8T
*)pats
+
1817 (patterns
->patternsNumber
* sizeof(*pats
));
1820 * Pointers are replaced with offsets into the data array. These
1821 * will be later converted back into pointers when received as events.
1823 for (i
= 0; i
< patterns
->patternsNumber
; i
++) {
1824 memcpy(str
, patterns
->patterns
[i
].pattern
,
1825 patterns
->patterns
[i
].patternSize
);
1826 pats
->pattern_size
= patterns
->patterns
[i
].patternSize
;
1827 pats
->pattern
= (SaUint8T
*)((void *)str
- data
);
1828 str
+= patterns
->patterns
[i
].patternSize
;
1831 return patterns
->patternsNumber
;
1835 * Calculate the size in bytes for filters
1837 static size_t filt_size(const SaEvtEventFilterArrayT
*filters
)
1840 size_t size
= sizeof(mar_evt_event_filter_array_t
);
1842 for (i
= 0; i
< filters
->filtersNumber
; i
++) {
1843 size
+= sizeof(mar_evt_event_filter_t
);
1844 size
+= filters
->filters
[i
].filter
.patternSize
;
1850 * Convert the Sa filters to a form that can be sent over the network
1851 * i.e. replace pointers with offsets. The pointers will be reconstituted
1854 static uint32_t aisfilt_to_evt_filt(
1855 const SaEvtEventFilterArrayT
*filters
,
1859 mar_evt_event_filter_array_t
*filtd
= data
;
1860 mar_evt_event_filter_t
*filts
= data
+ sizeof(mar_evt_event_filter_array_t
);
1861 SaUint8T
*str
= (SaUint8T
*)filts
+
1862 (filters
->filtersNumber
* sizeof(*filts
));
1865 * Pointers are replaced with offsets into the data array. These
1866 * will be later converted back into pointers by the evt server.
1868 filtd
->filters
= (mar_evt_event_filter_t
*)((void *)filts
- data
);
1869 filtd
->filters_number
= filters
->filtersNumber
;
1871 for (i
= 0; i
< filters
->filtersNumber
; i
++) {
1872 filts
->filter_type
= filters
->filters
[i
].filterType
;
1873 filts
->filter
.pattern_size
=
1874 filters
->filters
[i
].filter
.patternSize
;
1876 filters
->filters
[i
].filter
.pattern
,
1877 filters
->filters
[i
].filter
.patternSize
);
1878 filts
->filter
.pattern
= (SaUint8T
*)((void *)str
- data
);
1879 str
+= filters
->filters
[i
].filter
.patternSize
;
1882 return filters
->filtersNumber
;
1886 * The saEvtEventPublish() function publishes an event on the associated
1887 * channel. The event to be published consists of a
1888 * standard set of attributes (the event header) and an optional data part.
1889 * Before an event can be published, the publisher process must invoke the
1890 * saEvtEventPatternArraySet() function to set the event patterns. The event
1891 * is delivered to subscribers whose subscription filter matches the event
1893 * When the Event Service publishes an event, it automatically sets
1894 * the following readonly event attributes:
1895 * - Event attribute time
1896 * - Event publisher identifier
1897 * - Event publisher node identifier
1898 * - Event identifier
1899 * In addition to the event attributes, a process can supply values for the
1900 * eventData and eventDataSize parameters for publication as part of the
1901 * event. The data portion of the event may be at most SA_EVT_DATA_MAX_LEN
1903 * The process may assume that the invocation of saEvtEventPublish() copies
1904 * all pertinent parameters, including the memory associated with the
1905 * eventHandle and eventData parameters, to its own local memory. However,
1906 * the invocation does not automatically deallocate memory associated with
1907 * the eventHandle and eventData parameters. It is the responsibility of the
1908 * invoking process to deallocate the memory for those parameters after
1909 * saEvtEventPublish() returns.
1913 const SaEvtEventHandleT eventHandle
,
1914 const void *eventData
,
1915 SaSizeT eventDataSize
,
1916 SaEvtEventIdT
*eventId
)
1919 struct event_data_instance
*edi
;
1920 struct event_instance
*evti
;
1921 struct event_channel_instance
*eci
;
1922 struct lib_event_data
*req
;
1923 struct res_evt_event_publish res
;
1924 size_t pattern_size
;
1925 struct event_pattern
*patterns
;
1930 return SA_AIS_ERR_INVALID_PARAM
;
1933 if (eventDataSize
> SA_EVT_DATA_MAX_LEN
) {
1934 error
= SA_AIS_ERR_TOO_BIG
;
1938 error
= saHandleInstanceGet(&event_handle_db
, eventHandle
,
1940 if (error
!= SA_AIS_OK
) {
1943 pthread_mutex_lock(&edi
->edi_mutex
);
1945 error
= saHandleInstanceGet(&channel_handle_db
, edi
->edi_channel_handle
,
1947 if (error
!= SA_AIS_OK
) {
1952 * See if we can publish to this channel
1954 if (!(eci
->eci_open_flags
& SA_EVT_CHANNEL_PUBLISHER
)) {
1955 error
= SA_AIS_ERR_ACCESS
;
1959 error
= saHandleInstanceGet(&evt_instance_handle_db
,
1960 eci
->eci_instance_handle
, (void*)&evti
);
1961 if (error
!= SA_AIS_OK
) {
1966 * Figure out how much memory we need for the patterns and data
1968 pattern_size
= patt_size(&edi
->edi_patterns
);
1970 req
= malloc(sizeof(*req
) + eventDataSize
+ pattern_size
);
1973 error
= SA_AIS_ERR_NO_MEMORY
;
1977 patterns
= (struct event_pattern
*)req
->led_body
;
1978 data_start
= (void *)req
->led_body
+ pattern_size
;
1981 * copy everything to the request structure
1983 aispatt_to_evt_patt(&edi
->edi_patterns
, patterns
);
1985 req
->led_patterns_number
= edi
->edi_patterns
.patternsNumber
;
1987 req
->led_user_data_offset
= pattern_size
;
1988 if (eventData
&& eventDataSize
) {
1989 memcpy(data_start
, eventData
, eventDataSize
);
1990 req
->led_user_data_size
= eventDataSize
;
1992 req
->led_user_data_size
= 0;
1995 req
->led_head
.id
= MESSAGE_REQ_EVT_PUBLISH
;
1996 req
->led_head
.size
= sizeof(*req
) + pattern_size
+ eventDataSize
;
1997 req
->led_svr_channel_handle
= eci
->eci_svr_channel_handle
;
1998 req
->led_retention_time
= edi
->edi_retention_time
;
1999 req
->led_publish_time
= clustTimeNow();
2000 req
->led_priority
= edi
->edi_priority
;
2001 marshall_to_mar_name_t (&req
->led_publisher_name
, &edi
->edi_pub_name
);
2003 iov
.iov_base
= (char *)req
;
2004 iov
.iov_len
= req
->led_head
.size
;
2006 pthread_mutex_lock(&evti
->ei_response_mutex
);
2008 error
= saSendMsgReceiveReply(evti
->ei_response_fd
, &iov
, 1, &res
,
2011 pthread_mutex_unlock (&evti
->ei_response_mutex
);
2013 if (error
!= SA_AIS_OK
) {
2014 pthread_mutex_unlock (&evti
->ei_response_mutex
);
2018 error
= res
.iep_head
.error
;
2019 if (error
== SA_AIS_OK
) {
2020 *eventId
= res
.iep_event_id
;
2024 saHandleInstancePut (&evt_instance_handle_db
, eci
->eci_instance_handle
);
2026 saHandleInstancePut (&channel_handle_db
, edi
->edi_channel_handle
);
2028 pthread_mutex_unlock(&edi
->edi_mutex
);
2029 saHandleInstancePut(&event_handle_db
, eventHandle
);
2035 * The saEvtEventSubscribe() function enables a process to subscribe for
2036 * events on an event channel by registering one or more filters on that
2037 * event channel. The process must have opened the event channel, designated
2038 * by channelHandle, with the SA_EVT_CHANNEL_SUBSCRIBER flag set for an
2039 * invocation of this function to be successful.
2040 * The memory associated with the filters is not deallocated by the
2041 * saEvtEventSubscribe() function. It is the responsibility of the invoking
2042 * process to deallocate the memory when the saEvtEventSubscribe() function
2044 * For a given subscription, the filters parameter cannot be modified. To
2045 * change the filters parameter without losing events, a process must
2046 * establish a new subscription with the new filters parameter. After the new
2047 * subscription is established, the old subscription can be removed by
2048 * invoking the saEvtEventUnsubscribe() function.
2051 saEvtEventSubscribe(
2052 const SaEvtChannelHandleT channelHandle
,
2053 const SaEvtEventFilterArrayT
*filters
,
2054 SaEvtSubscriptionIdT subscriptionId
)
2057 struct event_instance
*evti
;
2058 struct event_channel_instance
*eci
;
2059 struct req_evt_event_subscribe
*req
;
2060 struct res_evt_event_subscribe res
;
2065 return SA_AIS_ERR_INVALID_PARAM
;
2067 error
= saHandleInstanceGet(&channel_handle_db
, channelHandle
,
2069 if (error
!= SA_AIS_OK
) {
2070 goto subscribe_done
;
2074 * get the evt handle for the fd
2076 error
= saHandleInstanceGet(&evt_instance_handle_db
,
2077 eci
->eci_instance_handle
, (void*)&evti
);
2078 if (error
!= SA_AIS_OK
) {
2079 goto subscribe_put1
;
2083 * Make sure that a deliver callback has been
2084 * registered before allowing the subscribe to continue.
2086 if (!evti
->ei_callback
.saEvtEventDeliverCallback
) {
2087 error
= SA_AIS_ERR_INIT
;
2088 goto subscribe_put2
;
2092 * See if we can subscribe to this channel
2094 if (!(eci
->eci_open_flags
& SA_EVT_CHANNEL_SUBSCRIBER
)) {
2095 error
= SA_AIS_ERR_ACCESS
;
2096 goto subscribe_put2
;
2100 * calculate size needed to store the filters
2102 sz
= filt_size(filters
);
2104 req
= malloc(sizeof(*req
) + sz
);
2107 error
= SA_AIS_ERR_NO_MEMORY
;
2108 goto subscribe_put2
;
2112 * Copy the supplied filters to the request
2114 req
->ics_filter_count
= aisfilt_to_evt_filt(filters
,
2115 req
->ics_filter_data
);
2116 req
->ics_head
.id
= MESSAGE_REQ_EVT_SUBSCRIBE
;
2117 req
->ics_head
.size
= sizeof(*req
) + sz
;
2118 req
->ics_channel_handle
= eci
->eci_svr_channel_handle
;
2119 req
->ics_sub_id
= subscriptionId
;
2120 req
->ics_filter_size
= sz
;
2121 iov
.iov_base
= (char *)req
;
2122 iov
.iov_len
= req
->ics_head
.size
;
2124 pthread_mutex_lock(&evti
->ei_response_mutex
);
2125 error
= saSendMsgReceiveReply(evti
->ei_response_fd
, &iov
, 1,
2127 pthread_mutex_unlock (&evti
->ei_response_mutex
);
2130 if (res
.ics_head
.id
!= MESSAGE_RES_EVT_SUBSCRIBE
) {
2131 goto subscribe_put2
;
2134 error
= res
.ics_head
.error
;
2137 saHandleInstancePut(&evt_instance_handle_db
,
2138 eci
->eci_instance_handle
);
2140 saHandleInstancePut(&channel_handle_db
, channelHandle
);
2146 * The saEvtEventUnsubscribe() function allows a process to stop receiving
2147 * events for a particular subscription on an event channel by removing the
2148 * subscription. The saEvtEventUnsubscribe() operation is successful if the
2149 * subscriptionId parameter matches a previously registered subscription.
2150 * Pending events that no longer match any subscription, because the
2151 * saEvtEventUnsubscribe() operation had been invoked, are purged. a process
2152 * that wishes to modify a subscription without losing any events must
2153 * establish the new subscription before removing the existing subscription.
2156 saEvtEventUnsubscribe(
2157 const SaEvtChannelHandleT channelHandle
,
2158 SaEvtSubscriptionIdT subscriptionId
)
2161 struct event_instance
*evti
;
2162 struct event_channel_instance
*eci
;
2163 struct req_evt_event_unsubscribe req
;
2164 struct res_evt_event_unsubscribe res
;
2167 error
= saHandleInstanceGet(&channel_handle_db
, channelHandle
,
2169 if (error
!= SA_AIS_OK
) {
2170 goto unsubscribe_done
;
2173 error
= saHandleInstanceGet(&evt_instance_handle_db
,
2174 eci
->eci_instance_handle
, (void*)&evti
);
2175 if (error
!= SA_AIS_OK
) {
2176 goto unsubscribe_put1
;
2179 req
.icu_head
.id
= MESSAGE_REQ_EVT_UNSUBSCRIBE
;
2180 req
.icu_head
.size
= sizeof(req
);
2182 req
.icu_channel_handle
= eci
->eci_svr_channel_handle
;
2183 req
.icu_sub_id
= subscriptionId
;
2184 iov
.iov_base
= (char *)&req
;
2185 iov
.iov_len
= sizeof(req
);
2187 pthread_mutex_lock(&evti
->ei_response_mutex
);
2188 error
= saSendMsgReceiveReply(evti
->ei_response_fd
, &iov
, 1,
2190 pthread_mutex_unlock (&evti
->ei_response_mutex
);
2192 if (error
!= SA_AIS_OK
) {
2193 goto unsubscribe_put2
;
2196 if (res
.icu_head
.id
!= MESSAGE_RES_EVT_UNSUBSCRIBE
) {
2197 error
= SA_AIS_ERR_LIBRARY
;
2198 goto unsubscribe_put2
;
2201 error
= res
.icu_head
.error
;
2204 saHandleInstancePut(&evt_instance_handle_db
,
2205 eci
->eci_instance_handle
);
2207 saHandleInstancePut(&channel_handle_db
, channelHandle
);
2214 * The saEvtEventRetentionTimeClear() function is used to clear the retention
2215 * time of a published event. It indicates to the Event Service that it does
2216 * not need to keep the event any longer for potential new subscribers. Once
2217 * the value of the retention time is reset to 0, the event is no longer
2218 * available for new subscribers. The event is held until all old subscribers
2219 * in the system process the event and free the event using saEvtEventFree().
2222 saEvtEventRetentionTimeClear(
2223 const SaEvtChannelHandleT channelHandle
,
2224 const SaEvtEventIdT eventId
)
2227 struct event_instance
*evti
;
2228 struct event_channel_instance
*eci
;
2229 struct req_evt_event_clear_retentiontime req
;
2230 struct res_evt_event_clear_retentiontime res
;
2233 if (!is_valid_event_id(eventId
)) {
2234 return SA_AIS_ERR_INVALID_PARAM
;
2237 error
= saHandleInstanceGet(&channel_handle_db
, channelHandle
,
2239 if (error
!= SA_AIS_OK
) {
2243 error
= saHandleInstanceGet(&evt_instance_handle_db
,
2244 eci
->eci_instance_handle
, (void*)&evti
);
2245 if (error
!= SA_AIS_OK
) {
2249 req
.iec_head
.id
= MESSAGE_REQ_EVT_CLEAR_RETENTIONTIME
;
2250 req
.iec_head
.size
= sizeof(req
);
2252 req
.iec_channel_handle
= eci
->eci_svr_channel_handle
;
2253 req
.iec_event_id
= eventId
;
2255 iov
.iov_base
= (char *)&req
;
2256 iov
.iov_len
= sizeof(req
);
2258 pthread_mutex_lock(&evti
->ei_response_mutex
);
2259 error
= saSendMsgReceiveReply(evti
->ei_response_fd
, &iov
, 1,
2261 pthread_mutex_unlock (&evti
->ei_response_mutex
);
2263 if (error
!= SA_AIS_OK
) {
2266 if (res
.iec_head
.id
!= MESSAGE_RES_EVT_CLEAR_RETENTIONTIME
) {
2267 error
= SA_AIS_ERR_LIBRARY
;
2271 error
= res
.iec_head
.error
;
2274 saHandleInstancePut(&evt_instance_handle_db
,
2275 eci
->eci_instance_handle
);
2277 saHandleInstancePut(&channel_handle_db
, channelHandle
);
2283 * vi: set autoindent tabstop=4 shiftwidth=4 :