2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#ifndef _LIBFMEVENT_H
2N/A#define _LIBFMEVENT_H
2N/A
2N/A/*
2N/A * FMA event library.
2N/A *
2N/A * A. Protocol event subscription interfaces (Committed).
2N/A * B. Raw event publication interfaces (Consolidation Private).
2N/A */
2N/A
2N/A#ifdef __cplusplus
2N/Aextern "C" {
2N/A#endif
2N/A
2N/A#include <sys/types.h>
2N/A#include <libnvpair.h>
2N/A#include <stdlib.h>
2N/A#include <door.h>
2N/A#include <sys/time.h>
2N/A#include <sys/fm/protocol.h>
2N/A
2N/A/*
2N/A * Library ABI interface version. Quote the version you are using
2N/A * to fmev_shdl_init. Only interfaces introduced in or prior to the
2N/A * quoted version will be available. Once introduced an interface
2N/A * only ever changes compatibly.
2N/A *
2N/A * Introduced in
2N/A * API Function LIBFMEVENT_VERSION_*
2N/A * ----------------------- --------------------
2N/A * fmev_attr_list; 1
2N/A * fmev_class; 1
2N/A * fmev_dup; 1
2N/A * fmev_ev2shdl 2
2N/A * fmev_hold; 1
2N/A * fmev_hrtime; 3
2N/A * fmev_localtime; 1
2N/A * fmev_rele; 1
2N/A * fmev_shdl_alloc; 1
2N/A * fmev_shdl_init; 1
2N/A * fmev_shdl_fini; 1
2N/A * fmev_shdl_free; 1
2N/A * fmev_shdl_getauthority 2
2N/A * fmev_shdl_nvl2str 2
2N/A * fmev_shdl_strdup 2
2N/A * fmev_shdl_strfree 2
2N/A * fmev_shdl_subscribe; 1
2N/A * fmev_shdl_unsubscribe; 1
2N/A * fmev_shdl_zalloc; 1
2N/A * fmev_shdlctl_serialize; 1
2N/A * fmev_shdlctl_sigmask; 1
2N/A * fmev_shdlctl_thrattr; 1
2N/A * fmev_shdlctl_thrcreate; 1
2N/A * fmev_shdlctl_thrsetup; 1
2N/A * fmev_strerror; 1
2N/A * fmev_timespec; 1
2N/A * fmev_time_nsec; 1
2N/A * fmev_time_sec; 1
2N/A */
2N/A
2N/A#define LIBFMEVENT_VERSION_1 1
2N/A#define LIBFMEVENT_VERSION_2 2
2N/A#define LIBFMEVENT_VERSION_3 3
2N/A
2N/A#define LIBFMEVENT_VERSION_LATEST LIBFMEVENT_VERSION_3
2N/A
2N/A/*
2N/A * Success and error return values. The descriptive comment for each
2N/A * FMEVERR_* becomes the string that is returned by fmev_strerror for that
2N/A * error type.
2N/A */
2N/Atypedef enum {
2N/A FMEV_SUCCESS = 0,
2N/A FMEV_OK = FMEV_SUCCESS, /* alias for FMEV_SUCCESS */
2N/A FMEVERR_UNKNOWN = 0xe000, /* Error details unknown */
2N/A FMEVERR_VERSION_MISMATCH, /* Library ABI version incompatible with caller */
2N/A FMEVERR_API, /* Library API usage violation */
2N/A FMEVERR_ALLOC, /* Failed to allocate additional resources */
2N/A FMEVERR_MALFORMED_EVENT, /* Event contents are inconsistent or corrupt */
2N/A FMEVERR_OVERFLOW, /* Operation would overflow result type */
2N/A FMEVERR_INTERNAL, /* Internal library error */
2N/A FMEVERR_NOPRIV, /* Insufficient permissions or privilege */
2N/A FMEVERR_BUSY, /* Resource is busy */
2N/A FMEVERR_DUPLICATE, /* Duplicate request */
2N/A FMEVERR_BADCLASS, /* Bad event class or class pattern */
2N/A FMEVERR_NOMATCH, /* No match to criteria provided */
2N/A FMEVERR_MAX_SUBSCRIBERS, /* Exceeds maximum subscribers per handle */
2N/A FMEVERR_INVALIDARG, /* Argument is invalid */
2N/A FMEVERR_STRING2BIG, /* String argument exceeds maximum length */
2N/A FMEVERR_VARARGS_MALFORMED, /* Varargs list bad or incorrectly terminated */
2N/A FMEVERR_VARARGS_TOOLONG, /* Varargs list exceeds maximum length */
2N/A FMEVERR_BADRULESET, /* Ruleset selected for publication is bad */
2N/A FMEVERR_BADPRI, /* Priority selected for publication is bad */
2N/A FMEVERR_TRANSPORT, /* Error in underlying event transport implementation */
2N/A FMEVERR_NVLIST /* nvlist argument is not of type NV_UNIQUE_NAME */
2N/A} fmev_err_t;
2N/A
2N/A/*
2N/A * Some interfaces return an fmev_err_t - FMEV_SUCCESS on success, otherwise
2N/A * failure of the indicated type. You can use fmev_strerror to render an
2N/A * fmev_err_t into a string.
2N/A *
2N/A * Other interfaces do not return an fmev_err_t directly. For example
2N/A * where we return a pointer an error is indicated by a NULL return.
2N/A * In these cases you can retrieve the fmev_err_t describing the reason
2N/A * for the failure using fmev_errno or get a string with
2N/A * fmev_strerr(fmev_errno). Note that fmev_errno is per-thread and holds
2N/A * the error value for any error that occured during the last libfmevent
2N/A * API call made by the current thread. Use fmev_errno as you would
2N/A * regular errno, but you should not assign to fmev_errno.
2N/A */
2N/Aextern const fmev_err_t *__fmev_errno(void); /* do not use this directly */
2N/A#define fmev_errno (*(__fmev_errno()))
2N/Aextern const char *fmev_strerror(fmev_err_t);
2N/A
2N/A/*
2N/A * Part A - Protocol Event Subscription
2N/A * ======
2N/A *
2N/A * Subscribe to FMA protocol events published by the fault management
2N/A * daemon, receiving a callback for each matching event.
2N/A *
2N/A * This is a Committed interface (see attributes(5) for a definition).
2N/A */
2N/A
2N/A/*
2N/A * Opaque subscription handle and event types.
2N/A */
2N/Atypedef struct fmev_shdl *fmev_shdl_t;
2N/Atypedef struct fmev *fmev_t;
2N/A
2N/A/*
2N/A * Subscription callback function type for fmev_shdl_subscribe.
2N/A */
2N/Atypedef void fmev_cbfunc_t(fmev_t, const char *, nvlist_t *, void *);
2N/A
2N/A/*
2N/A * Initialize a new handle using fmev_shdl_init and quoting interface
2N/A * version number along with alloc, zalloc and free function pointers (all
2N/A * NULL to use the defaults.
2N/A *
2N/A * Close the handle and release resources with fmev_shdl_fini.
2N/A */
2N/A
2N/Aextern fmev_shdl_t fmev_shdl_init(uint32_t,
2N/A void *(*)(size_t), /* alloc */
2N/A void *(*)(size_t), /* zalloc */
2N/A void (*)(void *, size_t)); /* free */
2N/A
2N/Aextern fmev_err_t fmev_shdl_fini(fmev_shdl_t);
2N/A
2N/A/*
2N/A * Having created a handle you may optionally configure various properties
2N/A * for this handle using fmev_shdlctl_*. In most cases accepting the defaults
2N/A * (that are obtained through fmev_shdl_init alone) will provide adequate
2N/A * semantics - the controls below are provided for applications
2N/A * that require fine-grained control over event delivery semantics and, in
2N/A * particular, the service threads used to perform delivery callbacks.
2N/A *
2N/A * These controls may only be applied to a subscription handle
2N/A * that has no current subscriptions in place. You therefore cannot
2N/A * change the properties once subscriptions are established, and the
2N/A * handle properties apply uniformly to all subscriptions on that handle.
2N/A * If you require different properties per subscription then use multiple
2N/A * handles.
2N/A *
2N/A * fmev_shdlctl_serialize() will serialize all callbacks arising from all
2N/A * subscriptions on a handle. Event deliveries are normally single-threaded
2N/A * on a per-subscribtion bases, that is a call to fmev_shdl_subscribe
2N/A * will have deliveries arising from that subscription delivered
2N/A * in a serialized fashion on a single thread dedicated to the subscription.
2N/A * If multiple subscriptions are established then each has a dedicated
2N/A * delivery thread - fmev_shdlctl_serialize arranges that only one of these
2N/A * threads services a callback at any one time.
2N/A *
2N/A * fmev_shdlctl_thrattr() allows you to provide thread attributes for use
2N/A * in pthread_create() when server threads are created. The attributes
2N/A * are not copied - the pthread_attr_t object passed must exist for
2N/A * the duration of all subscriptions on the handle. These attributes only
2N/A * apply if fmev_shdlctl_thrcreate() is not in use on this handle.
2N/A *
2N/A * fmev_shdlctl_sigmask() allows you to provide a sigset_t signal mask
2N/A * of signals to block in server threads. The pthread_sigmask is set
2N/A * to this immediately before pthread_create, and restored immediately
2N/A * after pthread_create. This mask only applies if fmev_shdlctl_thrcreate()
2N/A * is not in use on this handle.
2N/A *
2N/A * fmev_shdlctl_thrsetup() allows you to install a custom door server thread
2N/A * setup function - see door_xcreate(3C). This will be used with the
2N/A * default thread creation semantics or with any custom thread creation
2N/A * function appointed with fmev_shdlctl_thrcreate().
2N/A *
2N/A * fmev_shdlctl_thrcreate() allows you to install a custom door server thread
2N/A * creation function - see door_xcreate(3C). This option excludes
2N/A * fmev_shdlctl_{thrattr,sigmask} but the remaining options
2N/A * of fmev_shdlctl_{serialize,thrsetup} are still available.
2N/A */
2N/A
2N/Aextern fmev_err_t fmev_shdlctl_serialize(fmev_shdl_t);
2N/Aextern fmev_err_t fmev_shdlctl_thrattr(fmev_shdl_t, pthread_attr_t *);
2N/Aextern fmev_err_t fmev_shdlctl_sigmask(fmev_shdl_t, sigset_t *);
2N/Aextern fmev_err_t fmev_shdlctl_thrsetup(fmev_shdl_t,
2N/A door_xcreate_thrsetup_func_t *, void *);
2N/Aextern fmev_err_t fmev_shdlctl_thrcreate(fmev_shdl_t,
2N/A door_xcreate_server_func_t *, void *);
2N/A
2N/A/*
2N/A * Specify subscription choices on a handle using fmev_shdl_subscribe as
2N/A * many times as needed to describe the full event set. The event class
2N/A * pattern can be wildcarded using simple '*' wildcarding. When an event
2N/A * matching a subscription is received a callback is performed to the
2N/A * nominated function passing a fmev_t handle on the event and the
2N/A * requested cookie argument.
2N/A *
2N/A * See the fault management event protocol specification for a description
2N/A * of event classes.
2N/A *
2N/A * Drop a subscription using fmev_shdl_unsubscribe (which must match an
2N/A * earlier subscription).
2N/A */
2N/A
2N/A#define FMEV_MAX_CLASS 64 /* Longest class string for subscription */
2N/A
2N/Aextern fmev_err_t fmev_shdl_subscribe(fmev_shdl_t, const char *, fmev_cbfunc_t,
2N/A void *);
2N/Aextern fmev_err_t fmev_shdl_unsubscribe(fmev_shdl_t, const char *);
2N/A
2N/A/*
2N/A * Retrieve an authority nvlist for the fault manager that is forwarding
2N/A * events to us. This may be NULL if the fault manager has not yet
2N/A * started up and made the information available. The caller is
2N/A * responsible for freeing the nvlist returned.
2N/A */
2N/Aextern fmev_err_t fmev_shdl_getauthority(fmev_shdl_t, nvlist_t **);
2N/A
2N/A/*
2N/A * Event access. In the common case that the event is processed to
2N/A * completion in the context of the event callback you need only
2N/A * use fmev_attr_list to access the nvlist of event attributes,
2N/A * with no responsibility for freeing the event or the nvlist; for
2N/A * convenience, fmev_class and fmev_timestamp can both be used to
2N/A * look inside an event without having to work with the attribute list (and
2N/A * the callback receives the class as an argument).
2N/A *
2N/A * See libnvpair(3LIB) for interfaces to access an nvlist_t.
2N/A *
2N/A * The remaining interfaces apply in the case that event handling will
2N/A * continue beyond the context of the event callback in which it is received.
2N/A *
2N/A * The fmev_t handle received in a callback is reference-counted;
2N/A * the initial reference count on entry to the callback is 1, and the
2N/A * count is always decremented when the callback completes. To continue
2N/A * to operate on a received event outside of the context of the callback
2N/A * in which it is first received, take an fmev_hold during the callback
2N/A * and later fmev_rele to release your hold (and free the event if the count
2N/A * drops to 0).
2N/A *
2N/A * To access attributes of an event use fmev_attr_list to receive
2N/A * an nvlist_t pointer valid for the same lifetime as the event itself (i.e.,
2N/A * until its reference count drops to zero).
2N/A *
2N/A * If changes are made to a received fmev_t (discouraged) then all who
2N/A * have a hold on the event share the change. To obtain an independent
2N/A * copy of an fmev_t, with a reference count of 1, use fmev_dup. When
2N/A * finished with the copy decrement the reference count
2N/A * using fmev_rele - the event will be freed if the count reaches 0.
2N/A *
2N/A * For convenience you can retrieve the class of an event using fmev_class
2N/A * (it's also available as an argument to a callback, and within the
2N/A * event attribute list). The string returned by fmev_class is valid for
2N/A * the same lifetime as the event itself.
2N/A *
2N/A * The time at which a protocol event was generated is available via
2N/A * fmev_timespec; tv_sec has seconds since the epoch, and tv_nsec nanoseconds
2N/A * past that second. This can fail with FMEVERR_OVERFLOW if the seconds
2N/A * value does not fit within a time_t; you can retrieve the 64-bit second
2N/A * and nanosecond values with fmev_time_sec and fmev_time_nsec.
2N/A *
2N/A * An FMRI in an event payload is typically in nvlist form, i.e
2N/A * DATA_TYPE_NVLIST. That form is useful for extracting individual
2N/A * component fields, but that requires knowledge of the FMRI scheme and
2N/A * Public commitment thereof. FMRIs are typically Private, but in some
2N/A * cases they can be descriptive such as in listing the ASRU(s) affected
2N/A * by a fault; so we offer an API member which will blindly render any
2N/A * FMRI in its string form. Use fmev_shdl_nvl2str to format an nvlist_t
2N/A * as a string (if it is recognized as an FMRI); the caller is responsible
2N/A * for freeing the returned string using fmev_shdl_strfree. If
2N/A * fmev_shdl_nvl2str fails it will return NULL with fmev_errno set -
2N/A * FMEVERR_INVALIDARG if the nvlist_t does not appear to be a valid/known FMRI,
2N/A * FMEVERR_ALLOC if an allocation for memory for the string failed.
2N/A *
2N/A * fmev_ev2shdl will return the fmev_shdl_t with which a received fmev_t
2N/A * is associated. It should only be used in an event delivery callback
2N/A * context and for the event received in that callback.
2N/A */
2N/A
2N/Aextern nvlist_t *fmev_attr_list(fmev_t);
2N/Aextern const char *fmev_class(fmev_t);
2N/A
2N/Aextern fmev_err_t fmev_timespec(fmev_t, struct timespec *);
2N/Aextern uint64_t fmev_time_sec(fmev_t);
2N/Aextern uint64_t fmev_time_nsec(fmev_t);
2N/Aextern struct tm *fmev_localtime(fmev_t, struct tm *);
2N/Aextern hrtime_t fmev_hrtime(fmev_t);
2N/A
2N/Aextern void fmev_hold(fmev_t);
2N/Aextern void fmev_rele(fmev_t);
2N/Aextern fmev_t fmev_dup(fmev_t);
2N/A
2N/Aextern char *fmev_shdl_nvl2str(fmev_shdl_t, nvlist_t *);
2N/A
2N/Aextern fmev_shdl_t fmev_ev2shdl(fmev_t);
2N/A
2N/A/*
2N/A * The following will allocate and free memory based on the choices made
2N/A * at fmev_shdl_init.
2N/A */
2N/Avoid *fmev_shdl_alloc(fmev_shdl_t, size_t);
2N/Avoid *fmev_shdl_zalloc(fmev_shdl_t, size_t);
2N/Avoid fmev_shdl_free(fmev_shdl_t, void *, size_t);
2N/Aextern char *fmev_shdl_strdup(fmev_shdl_t, char *);
2N/Aextern void fmev_shdl_strfree(fmev_shdl_t, char *);
2N/A
2N/A/*
2N/A * Part B - Raw Event Publication
2N/A * ======
2N/A *
2N/A * The following interfaces are private to the Solaris system and are
2N/A * subject to change at any time without notice. Applications using
2N/A * these interfaces will fail to run on future releases. The interfaces
2N/A * should not be used for any purpose until they are publicly documented
2N/A * for use outside of Sun. These interface are *certain* to change
2N/A * incompatibly, as the current interface is very much purpose-built for
2N/A * a limited application.
2N/A *
2N/A * The interfaces below allow a process to publish a "raw" event
2N/A * which will be transmitted to the fault manager and post-processed
2N/A * into a full FMA protocol event. The post-processing to be applied
2N/A * is selected by a "ruleset" specified either implicitly or explicitly
2N/A * at publication. A ruleset will take the raw event (comprising
2N/A * class, subclass, priority, raw payload) and mark it up into a full
2N/A * protocol event; it may also augment the payload through looking up
2N/A * details that would have been costly to compute at publication time.
2N/A *
2N/A * In this first implementation event dispatch is synchronous and blocking,
2N/A * and not guaranteed to be re-entrant. This limits the call sites
2N/A * at which publication calls can be placed, and also means that careful
2N/A * thought is required before sprinkling event publication code throughout
2N/A * common system libraries. The dispatch mechanism amounts to some
2N/A * nvlist chicanery followed by a sysevent_evc_publish. A future revision
2N/A * will relax the context from which one may publish, and add more-powerful
2N/A * publication interfaces.
2N/A *
2N/A * Some publication interfaces (those ending in _nvl) accept a preconstructed
2N/A * nvlist as raw event payload. We require that such an nvlist be of type
2N/A * NV_UNIQUE_NAME. The publication interfaces all call nvlist_free on any
2N/A * nvlist that is passed for publication.
2N/A *
2N/A * Other publication interfaces allow you to build up the raw event payload
2N/A * by specifying the members in a varargs list terminated by FMEV_ARG_TERM.
2N/A * Again we require that payload member names are unique (that is, you cannot
2N/A * have two members with the same name but different datatype). See
2N/A * <sys/nvpair.h> for the data_type_t enumeration of types supported - but
2N/A * note that DATA_TYPE_BOOLEAN is excluded (DATA_TYPE_BOOLEAN_VALUE is
2N/A * supported). A single-valued (non-array type) member is specified with 3
2N/A * consecutive varargs as:
2N/A *
2N/A * (char *)name, DATA_TYPE_foo, (type)value
2N/A *
2N/A * An array-valued member is specified with 4 consecutive varargs as:
2N/A *
2N/A * (char *)name, DATA_TYPE_foo_ARRAY, (int)nelem, (type *)arrayptr
2N/A *
2N/A * The varargs list that specifies the nvlist must begin with an
2N/A * integer that specifies the number of members that follow. For example:
2N/A *
2N/A * uint32_t mode;
2N/A * char *clientname;
2N/A * uint32_t ins[NARGS];
2N/A *
2N/A * fmev_publish("class", "subclass", FMEV_LOPRI,
2N/A * 3,
2N/A * "mode", DATA_TYPE_UINT32, mode,
2N/A * "client", DATA_TYPE_STRING, clientname,
2N/A * "ins", DATA_TYPE_UINT32_ARRAY, sizeof (ins) / sizeof (ins[0]), ins,
2N/A * FMEV_ARG_TERM);
2N/A *
2N/A * The following tables summarize the capabilities of the various
2N/A * publication interfaces.
2N/A *
2N/A * Detector
2N/A * Interface Ruleset? File/Line Func
2N/A * ---------------------------- -------- --------- ----
2N/A * fmev_publish_nvl default Yes No
2N/A * fmev_publish_nvl (C99) default Yes Yes
2N/A * fmev_rspublish_nvl chosen Yes No
2N/A * fmev_rspublish_nvl (C99) chosen Yes Yes
2N/A * fmev_publish default No No
2N/A * fmev_publish (C99) default Yes Yes
2N/A * fmev_rspublish chosen No No
2N/A * fmev_rspublish (C99) chosen Yes Yes
2N/A *
2N/A * Summary: if not using C99 then try to use the _nvl variants as the
2N/A * varargs variants will not include file, line or function in the
2N/A * detector.
2N/A */
2N/A
2N/A/*
2N/A * In publishing an event you must select a "ruleset" (or accept the
2N/A * defaults). Rulesets are listed in the following header.
2N/A */
2N/A#include <fm/libfmevent_ruleset.h>
2N/A
2N/A/*
2N/A * In publishing an event we can specify a class and subclass (which
2N/A * in post-processing combine in some way selected by the ruleset to
2N/A * form a full event protocol class). The maximum class and subclass
2N/A * string lengths are as follows.
2N/A */
2N/A#define FMEV_PUB_MAXCLASSLEN 32
2N/A#define FMEV_PUB_MAXSUBCLASSLEN 32
2N/A
2N/A/*
2N/A * Events are either high-priority (try really hard not to lose) or
2N/A * low-priority (can drop, throttle etc). Convert a fmev_pri_t to
2N/A * a string with fmev_pri_string().
2N/A */
2N/Atypedef enum fmev_pri {
2N/A FMEV_LOPRI = 0x1000,
2N/A FMEV_HIPRI
2N/A} fmev_pri_t;
2N/A
2N/Aextern const char *fmev_pri_string(fmev_pri_t);
2N/A
2N/A/*
2N/A * The varargs event publication interfaces must terminate the list
2N/A * of nvpair specifications with FMEV_ARG_TERM. This is to guard
2N/A * against very easily-made mistakes in those arg lists.
2N/A */
2N/A#define FMEV_ARG_TERM (void *)0xa4a3a2a1
2N/A
2N/A/*
2N/A * The following are NOT for direct use.
2N/A */
2N/Aextern fmev_err_t _i_fmev_publish_nvl(
2N/A const char *, const char *, int64_t,
2N/A const char *, const char *, const char *,
2N/A fmev_pri_t, nvlist_t *);
2N/A
2N/Aextern fmev_err_t _i_fmev_publish(
2N/A const char *, const char *, int64_t,
2N/A const char *, const char *, const char *,
2N/A fmev_pri_t,
2N/A uint_t, ...);
2N/A
2N/A/*
2N/A * Post-processing will always generate a "detector" payload member. In
2N/A * the case of the _nvl publishing variants the detector information
2N/A * includes file and line number, and - if your application is compiled
2N/A * with C99 enabled - function name.
2N/A */
2N/A#if __STDC_VERSION__ - 0 >= 199901L
2N/A#define _FMEVFUNC __func__
2N/A#else
2N/A#define _FMEVFUNC NULL
2N/A#endif
2N/A
2N/A/*
2N/A * All these definitions "return" an fmev_err_t.
2N/A *
2N/A * In the _nvl variants you pass a preconstructed event payload; otherwise
2N/A * you include an integer indicating the number of payload
2N/A * (name, type, value) tuples that follow, then all those tuples, finally
2N/A * terminated by FMEV_ARG_TERM.
2N/A *
2N/A * In the rspublish variants you select a ruleset from
2N/A * libfmevent_ruleset.h - just use the final suffix (as in
2N/A * DEFAULT, EREPORT, ISV).
2N/A *
2N/A * The primary classification must not be NULL or the empty string.
2N/A *
2N/A * arg type Description
2N/A * ------- --------------- -------------------------------------------
2N/A * ruleset const char * Ruleset; can be NULL (implies default ruleset)
2N/A * cl1 const char * Primary classification string
2N/A * cl2 const char * Secondary classification string
2N/A * pri fmev_pri_t Priority
2N/A * nvl nvlist_t * Preconstructed attributes; caller must free
2N/A * ntuples int Number of tuples before FMEV_ARG_TERM
2N/A * suffix - See above.
2N/A */
2N/A
2N/A/*
2N/A * fmev_publish_nvl - Default ruleset implied; class/subclass, pri and an nvl
2N/A */
2N/A#define fmev_publish_nvl(cl1, cl2, pri, nvl) \
2N/A _i_fmev_publish_nvl( \
2N/A __FILE__, _FMEVFUNC, __LINE__, \
2N/A FMEV_RULESET_DEFAULT, cl1, cl2, \
2N/A pri, nvl)
2N/A
2N/A/*
2N/A * fmev_rspublish_nvl - As fmev_publish_nvl, but with a chosen ruleset.
2N/A */
2N/A#define fmev_rspublish_nvl(ruleset, cl1, cl2, pri, nvl) \
2N/A _i_fmev_publish_nvl( \
2N/A __FILE__, _FMEVFUNC, __LINE__, \
2N/A ruleset, cl1, cl2, \
2N/A pri, nvl)
2N/A
2N/A#if __STDC_VERSION__ - 0 >= 199901L && !defined(__lint)
2N/A
2N/A/*
2N/A * fmev_publish (C99 version) - Default ruleset; class/subclass, pri, nvpairs
2N/A */
2N/A#define fmev_publish(cl1, cl2, pri, ntuples, ...) \
2N/A _i_fmev_publish( \
2N/A __FILE__, __func__, __LINE__, \
2N/A FMEV_RULESET_DEFAULT, cl1, cl2, \
2N/A pri, \
2N/A ntuples, __VA_ARGS__)
2N/A
2N/A
2N/A/*
2N/A * fmev_rspublish (C99 version) - As fmev_publish, but with a chosen ruleset.
2N/A */
2N/A#define fmev_rspublish(ruleset, cl1, cl2, pri, ntuples, ...) \
2N/A _i_fmev_publish( \
2N/A __FILE__, __func__, __LINE__, \
2N/A ruleset, cl1, cl2, \
2N/A pri, \
2N/A ntuples, __VA_ARGS__)
2N/A
2N/A#else
2N/A
2N/A/*
2N/A * fmev_publish (pre C99)
2N/A */
2N/Aextern fmev_err_t fmev_publish(const char *, const char *,
2N/A fmev_pri_t, uint_t, ...);
2N/A
2N/A/*
2N/A * fmev_rspublish (pre C99)
2N/A */
2N/Aextern fmev_err_t fmev_rspublish(const char *, const char *, const char *,
2N/A fmev_pri_t, uint_t, ...);
2N/A
2N/A#endif /* __STDC_VERSION__ */
2N/A
2N/A#ifdef __cplusplus
2N/A}
2N/A#endif
2N/A
2N/A#endif /* _LIBFMEVENT_H */