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.
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.
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]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Subscription event access interfaces.
30 #include <sys/types.h>
33 #include <libsysevent.h>
35 #include <fm/libfmevent.h>
36 #include <sys/fm/protocol.h>
38 #include "fmev_impl.h"
40 #define FMEV_API_ENTER(iep, v) \
41 fmev_api_enter(fmev_shdl_cmn(((iep)->ei_hdl)), LIBFMEVENT_VERSION_##v)
44 uint32_t ei_magic
; /* _FMEVMAGIC */
45 volatile uint32_t ei_refcnt
; /* reference count */
46 fmev_shdl_t ei_hdl
; /* handle received on */
47 nvlist_t
*ei_nvl
; /* (duped) sysevent attribute list */
48 uint64_t ei_fmtime
[2]; /* embedded protocol event time */
51 #define FMEV2IMPL(ev) ((fmev_impl_t *)(ev))
52 #define IMPL2FMEV(iep) ((fmev_t)(iep))
54 #define _FMEVMAGIC 0x466d4576 /* "FmEv" */
56 #define EVENT_VALID(iep) ((iep)->ei_magic == _FMEVMAGIC && \
57 (iep)->ei_refcnt > 0 && fmev_shdl_valid((iep)->ei_hdl))
60 #define FM_TIME_NSEC 1
63 * Transform a received sysevent_t into an fmev_t.
66 uint64_t fmev_bad_attr
, fmev_bad_tod
, fmev_bad_class
;
69 fmev_sysev2fmev(fmev_shdl_t hdl
, sysevent_t
*sep
, char **clsp
, nvlist_t
**nvlp
)
75 if ((iep
= fmev_shdl_alloc(hdl
, sizeof (*iep
))) == NULL
)
79 * sysevent_get_attr_list duplicates the nvlist - we free it
80 * in fmev_free when the reference count hits zero.
82 if (sysevent_get_attr_list(sep
, &iep
->ei_nvl
) != 0) {
83 fmev_shdl_free(hdl
, iep
, sizeof (*iep
));
90 if (nvlist_lookup_string(iep
->ei_nvl
, FM_CLASS
, clsp
) != 0) {
91 nvlist_free(iep
->ei_nvl
);
92 fmev_shdl_free(hdl
, iep
, sizeof (*iep
));
97 if (nvlist_lookup_uint64_array(iep
->ei_nvl
, "__tod", &tod
,
98 &nelem
) != 0 || nelem
!= 2) {
99 nvlist_free(iep
->ei_nvl
);
100 fmev_shdl_free(hdl
, iep
, sizeof (*iep
));
105 iep
->ei_fmtime
[FM_TIME_SEC
] = tod
[0];
106 iep
->ei_fmtime
[FM_TIME_NSEC
] = tod
[1];
109 * Now remove the fmd-private __tod and __ttl members.
111 (void) nvlist_remove_all(iep
->ei_nvl
, "__tod");
112 (void) nvlist_remove_all(iep
->ei_nvl
, "__ttl");
114 iep
->ei_magic
= _FMEVMAGIC
;
117 ASSERT(EVENT_VALID(iep
));
119 return (IMPL2FMEV(iep
));
123 fmev_free(fmev_impl_t
*iep
)
125 ASSERT(iep
->ei_refcnt
== 0);
127 nvlist_free(iep
->ei_nvl
);
128 fmev_shdl_free(iep
->ei_hdl
, iep
, sizeof (*iep
));
134 fmev_impl_t
*iep
= FMEV2IMPL(ev
);
136 ASSERT(EVENT_VALID(iep
));
138 (void) FMEV_API_ENTER(iep
, 1);
140 atomic_inc_32(&iep
->ei_refcnt
);
146 fmev_impl_t
*iep
= FMEV2IMPL(ev
);
148 ASSERT(EVENT_VALID(iep
));
150 (void) FMEV_API_ENTER(iep
, 1);
152 if (atomic_dec_32_nv(&iep
->ei_refcnt
) == 0)
159 fmev_impl_t
*iep
= FMEV2IMPL(ev
);
162 ASSERT(EVENT_VALID(iep
));
164 if (!FMEV_API_ENTER(iep
, 1))
165 return (NULL
); /* fmev_errno set */
168 (void) fmev_seterr(FMEVERR_API
);
172 if ((cp
= fmev_shdl_alloc(iep
->ei_hdl
, sizeof (*iep
))) == NULL
) {
173 (void) fmev_seterr(FMEVERR_ALLOC
);
177 if (nvlist_dup(iep
->ei_nvl
, &cp
->ei_nvl
, 0) != 0) {
178 fmev_shdl_free(iep
->ei_hdl
, cp
, sizeof (*cp
));
179 (void) fmev_seterr(FMEVERR_ALLOC
);
183 cp
->ei_magic
= _FMEVMAGIC
;
184 cp
->ei_hdl
= iep
->ei_hdl
;
186 return (IMPL2FMEV(cp
));
190 fmev_attr_list(fmev_t ev
)
192 fmev_impl_t
*iep
= FMEV2IMPL(ev
);
194 ASSERT(EVENT_VALID(iep
));
196 if (!FMEV_API_ENTER(iep
, 1))
197 return (NULL
); /* fmev_errno set */
200 (void) fmev_seterr(FMEVERR_API
);
202 } else if (iep
->ei_nvl
== NULL
) {
203 (void) fmev_seterr(FMEVERR_MALFORMED_EVENT
);
207 return (iep
->ei_nvl
);
211 fmev_class(fmev_t ev
)
213 fmev_impl_t
*iep
= FMEV2IMPL(ev
);
216 ASSERT(EVENT_VALID(iep
));
218 if (!FMEV_API_ENTER(iep
, 1))
219 return (NULL
); /* fmev_errno set */
222 (void) fmev_seterr(FMEVERR_API
);
226 if (nvlist_lookup_string(iep
->ei_nvl
, FM_CLASS
, (char **)&class) != 0 ||
228 (void) fmev_seterr(FMEVERR_MALFORMED_EVENT
);
236 fmev_timespec(fmev_t ev
, struct timespec
*tp
)
238 fmev_impl_t
*iep
= FMEV2IMPL(ev
);
241 ASSERT(EVENT_VALID(iep
));
242 if (!FMEV_API_ENTER(iep
, 1))
246 timetlimit
= INT64_MAX
;
248 timetlimit
= INT32_MAX
;
251 if (iep
->ei_fmtime
[FM_TIME_SEC
] > timetlimit
)
252 return (FMEVERR_OVERFLOW
);
254 tp
->tv_sec
= (time_t)iep
->ei_fmtime
[FM_TIME_SEC
];
255 tp
->tv_nsec
= (long)iep
->ei_fmtime
[FM_TIME_NSEC
];
257 return (FMEV_SUCCESS
);
261 fmev_time_sec(fmev_t ev
)
263 return (FMEV2IMPL(ev
)->ei_fmtime
[FM_TIME_SEC
]);
267 fmev_time_nsec(fmev_t ev
)
269 return (FMEV2IMPL(ev
)->ei_fmtime
[FM_TIME_NSEC
]);
273 fmev_localtime(fmev_t ev
, struct tm
*tm
)
277 seconds
= (time_t)fmev_time_sec(ev
);
278 return (localtime_r(&seconds
, tm
));
282 fmev_ev2shdl(fmev_t ev
)
284 fmev_impl_t
*iep
= FMEV2IMPL(ev
);
286 if (!FMEV_API_ENTER(iep
, 2))
289 return (iep
->ei_hdl
);