xref: /illumos-gate/usr/src/lib/fm/libfmevent/common/libfmevent.h (revision fb2a9bae0030340ad72b9c26ba1ffee2ee3cafec)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _LIBFMEVENT_H
28 #define	_LIBFMEVENT_H
29 
30 /*
31  * FMA event library.
32  *
33  * A. Protocol event subscription interfaces (Committed).
34  */
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 #include <sys/types.h>
41 #include <libnvpair.h>
42 #include <stdlib.h>
43 #include <door.h>
44 #include <sys/time.h>
45 #include <sys/fm/protocol.h>
46 
47 /*
48  * Library ABI interface version.  Quote the version you are using
49  * to fmev_shdl_init.  Only interfaces introduced in or prior to the
50  * quoted version will be available.  Once introduced an interface
51  * only ever changes compatibly.
52  */
53 #define	LIBFMEVENT_VERSION_1	1
54 
55 #define	LIBFMEVENT_VERSION_LATEST	LIBFMEVENT_VERSION_1
56 
57 /*
58  * Success and error return values.  The descriptive comment for each
59  * FMEVERR_* becomes the string that is returned by fmev_strerror for that
60  * error type.
61  */
62 typedef enum {
63     FMEV_SUCCESS = 0,
64     FMEV_OK = FMEV_SUCCESS, /* alias for FMEV_SUCCESS */
65     FMEVERR_UNKNOWN = 0xe000, /* Error details unknown */
66     FMEVERR_VERSION_MISMATCH, /* Library ABI version incompatible with caller */
67     FMEVERR_API, /* Library API usage violation */
68     FMEVERR_ALLOC, /* Failed to allocate additional resources */
69     FMEVERR_MALFORMED_EVENT, /* Event contents are inconsistent or corrupt */
70     FMEVERR_OVERFLOW, /* Operation would overflow result type */
71     FMEVERR_INTERNAL, /* Internal library error */
72     FMEVERR_NOPRIV, /* Insufficient permissions or privilege */
73     FMEVERR_BUSY, /* Resource is busy */
74     FMEVERR_DUPLICATE, /* Duplicate request */
75     FMEVERR_BADCLASS, /* Bad event class or class pattern */
76     FMEVERR_NOMATCH, /* No match to criteria provided */
77     FMEVERR_MAX_SUBSCRIBERS, /* Exceeds maximum subscribers per handle */
78     FMEVERR_INVALIDARG /* Argument is invalid */
79 } fmev_err_t;
80 
81 /*
82  * Some interfaces return an fmev_err_t - FMEV_SUCCESS on success, otherwise
83  * failure of the indicated type.  You can use fmev_strerror to render an
84  * fmev_err_t into a string.
85  *
86  * Other interfaces do not return an fmev_err_t directly.  For example
87  * where we return a pointer an error is indicated by a NULL return.
88  * In these cases you can retrieve the fmev_err_t describing the reason
89  * for the failure using fmev_errno or get a string with
90  * fmev_strerr(fmev_errno).  Note that fmev_errno is per-thread and holds
91  * the error value for any error that occured during the last libfmevent
92  * API call made by the current thread.  Use fmev_errno as you would
93  * regular errno, but you should not assign to fmev_errno.
94  */
95 extern const fmev_err_t *__fmev_errno(void);	/* do not use this directly */
96 #define	fmev_errno (*(__fmev_errno()))
97 extern const char *fmev_strerror(fmev_err_t);
98 
99 /*
100  * Part A - Protocol Event Subscription
101  * ======
102  *
103  * Subscribe to FMA protocol events published by the fault management
104  * daemon, receiving a callback for each matching event.
105  *
106  * This is a Committed interface (see attributes(5) for a definition).
107  */
108 
109 /*
110  * Opaque subscription handle and event types.
111  */
112 typedef struct fmev_shdl *fmev_shdl_t;
113 typedef struct fmev *fmev_t;
114 
115 /*
116  * Subscription callback function type for fmev_shdl_subscribe.
117  */
118 typedef void fmev_cbfunc_t(fmev_t, const char *, nvlist_t *, void *);
119 
120 /*
121  * Initialize a new handle using fmev_shdl_init and quoting interface
122  * version number along with alloc, zalloc and free function pointers (all
123  * NULL to use the defaults.
124  *
125  * Close the handle and release resources with fmev_shdl_fini.
126  */
127 
128 extern fmev_shdl_t fmev_shdl_init(uint32_t,
129     void *(*)(size_t),		/* alloc */
130     void *(*)(size_t),		/* zalloc */
131     void (*)(void *, size_t));	/* free */
132 
133 extern fmev_err_t fmev_shdl_fini(fmev_shdl_t);
134 
135 /*
136  * Having created a handle you may optionally configure various properties
137  * for this handle using fmev_shdlctl_*.  In most cases accepting the defaults
138  * (that are obtained through fmev_shdl_init alone) will provide adequate
139  * semantics - the controls below are provided for applications
140  * that require fine-grained control over event delivery semantics and, in
141  * particular, the service threads used to perform delivery callbacks.
142  *
143  * These controls may only be applied to a subscription handle
144  * that has no current subscriptions in place.  You therefore cannot
145  * change the properties once subscriptions are established, and the
146  * handle properties apply uniformly to all subscriptions on that handle.
147  * If you require different properties per subscription then use multiple
148  * handles.
149  *
150  * fmev_shdlctl_serialize() will serialize all callbacks arising from all
151  * subscriptions on a handle.  Event deliveries are normally single-threaded
152  * on a per-subscribtion bases, that is a call to fmev_shdl_subscribe
153  * will have deliveries arising from that subscription delivered
154  * in a serialized fashion on a single thread dedicated to the subscription.
155  * If multiple subscriptions are established then each has a dedicated
156  * delivery thread - fmev_shdlctl_serialize arranges that only one of these
157  * threads services a callback at any one time.
158  *
159  * fmev_shdlctl_thrattr() allows you to provide thread attributes for use
160  * in pthread_create() when server threads are created.  The attributes
161  * are not copied - the pthread_attr_t object passed must exist for
162  * the duration of all subscriptions on the handle.  These attributes only
163  * apply if fmev_shdlctl_thrcreate() is not in use on this handle.
164  *
165  * fmev_shdlctl_sigmask() allows you to provide a sigset_t signal mask
166  * of signals to block in server threads.  The pthread_sigmask is set
167  * to this immediately before pthread_create, and restored immediately
168  * after pthread_create.  This mask only applies if fmev_shdlctl_thrcreate()
169  * is not in use on this handle.
170  *
171  * fmev_shdlctl_thrsetup() allows you to install a custom door server thread
172  * setup function - see door_xcreate(3C).  This will be used with the
173  * default thread creation semantics or with any custom thread creation
174  * function appointed with fmev_shdlctl_thrcreate().
175  *
176  * fmev_shdlctl_thrcreate() allows you to install a custom door server thread
177  * creation function - see door_xcreate(3C).  This option excludes
178  * fmev_shdlctl_{thrattr,sigmask} but the remaining options
179  * of fmev_shdlctl_{serialize,thrsetup} are still available.
180  */
181 
182 extern fmev_err_t fmev_shdlctl_serialize(fmev_shdl_t);
183 extern fmev_err_t fmev_shdlctl_thrattr(fmev_shdl_t, pthread_attr_t *);
184 extern fmev_err_t fmev_shdlctl_sigmask(fmev_shdl_t, sigset_t *);
185 extern fmev_err_t fmev_shdlctl_thrsetup(fmev_shdl_t,
186     door_xcreate_thrsetup_func_t *, void *);
187 extern fmev_err_t fmev_shdlctl_thrcreate(fmev_shdl_t,
188     door_xcreate_server_func_t *, void *);
189 
190 /*
191  * Specify subscription choices on a handle using fmev_shdl_subscribe as
192  * many times as needed to describe the full event set.  The event class
193  * pattern can be wildcarded using simple '*' wildcarding.  When an event
194  * matching a subscription is received a callback is performed to the
195  * nominated function passing a fmev_t handle on the event and the
196  * requested cookie argument.
197  *
198  * See the fault management event protocol specification for a description
199  * of event classes.
200  *
201  * Drop a subscription using fmev_shdl_unsubscribe (which must match an
202  * earlier subscription).
203  */
204 
205 #define	FMEV_MAX_CLASS	64	/* Longest class string for subscription */
206 
207 extern fmev_err_t fmev_shdl_subscribe(fmev_shdl_t, const char *, fmev_cbfunc_t,
208     void *);
209 extern fmev_err_t fmev_shdl_unsubscribe(fmev_shdl_t, const char *);
210 
211 /*
212  * Event access.  In the common case that the event is processed to
213  * completion in the context of the event callback you need only
214  * use fmev_attr_list to access the nvlist of event attributes,
215  * with no responsibility for freeing the event or the nvlist; for
216  * convenience, fmev_class and fmev_timestamp can both be used to
217  * look inside an event without having to work with the attribute list (and
218  * the callback receives the class as an argument).
219  *
220  * See libnvpair(3LIB) for interfaces to access an nvlist_t.
221  *
222  * The remaining interfaces apply in the case that event handling will
223  * continue beyond the context of the event callback in which it is received.
224  *
225  * The fmev_t handle received in a callback is reference-counted;
226  * the initial reference count on entry to the callback is 1, and the
227  * count is always decremented when the callback completes.  To continue
228  * to operate on a received event outside of the context of the callback
229  * in which it is first received, take an fmev_hold during the callback
230  * and later fmev_rele to release your hold (and free the event if the count
231  * drops to 0).
232  *
233  * To access attributes of an event use fmev_attr_list to receive
234  * an nvlist_t pointer valid for the same lifetime as the event itself (i.e.,
235  * until its reference count drops to zero).
236  *
237  * If changes are made to a received fmev_t (discouraged) then all who
238  * have a hold on the event share the change.  To obtain an independent
239  * copy of an fmev_t, with a reference count of 1, use fmev_dup.  When
240  * finished with the copy decrement the reference count
241  * using fmev_rele - the event will be freed if the count reaches 0.
242  *
243  * For convenience you can retrieve the class of an event using fmev_class
244  * (it's also available as an argument to a callback, and within the
245  * event attribute list).  The string returned by fmev_class is valid for
246  * the same lifetime as the event itself.
247  *
248  * The time at which a protocol event was generated is available via
249  * fmev_timespec; tv_sec has seconds since the epoch, and tv_nsec nanoseconds
250  * past that second.  This can fail with FMEVERR_OVERFLOW if the seconds
251  * value does not fit within a time_t;  you can retrieve the 64-bit second
252  * and nanosecond values with fmev_time_sec and fmev_time_nsec.
253  */
254 
255 extern nvlist_t *fmev_attr_list(fmev_t);
256 extern const char *fmev_class(fmev_t);
257 
258 extern fmev_err_t fmev_timespec(fmev_t, struct timespec *);
259 extern uint64_t fmev_time_sec(fmev_t);
260 extern uint64_t fmev_time_nsec(fmev_t);
261 extern struct tm *fmev_localtime(fmev_t, struct tm *);
262 
263 extern void fmev_hold(fmev_t);
264 extern void fmev_rele(fmev_t);
265 extern fmev_t fmev_dup(fmev_t);
266 
267 /*
268  * The following will allocate and free memory based on the choices made
269  * at fmev_shdl_init.
270  */
271 void *fmev_shdl_alloc(fmev_shdl_t, size_t);
272 void *fmev_shdl_zalloc(fmev_shdl_t, size_t);
273 void fmev_shdl_free(fmev_shdl_t, void *, size_t);
274 
275 #ifdef __cplusplus
276 }
277 #endif
278 
279 #endif /* _LIBFMEVENT_H */
280