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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * stats.c -- simple stats tracking table module
27  *
28  * this version of stats.c links with eft and implements the
29  * stats using the fmd's stats API.
30  */
31 
32 #pragma ident	"%Z%%M%	%I%	%E% SMI"
33 
34 #include <sys/types.h>
35 #include <strings.h>
36 #include "stats.h"
37 #include "alloc.h"
38 #include "out.h"
39 #include <fm/fmd_api.h>
40 
41 extern fmd_hdl_t *Hdl;		/* handle from eft.c */
42 
43 struct stats {
44 	fmd_stat_t fmd_stats;
45 	enum stats_type {
46 		STATS_COUNTER = 3000,
47 		STATS_ELAPSE,
48 		STATS_STRING
49 	} t;
50 
51 	/* used for STATS_ELAPSE */
52 	hrtime_t start;
53 	hrtime_t stop;
54 };
55 
56 static int Ext;			/* true if extended stats are enabled */
57 
58 /*
59  * stats_init -- initialize the stats module
60  *
61  */
62 
63 void
64 stats_init(int ext)
65 {
66 	Ext = ext;
67 }
68 
69 void
70 stats_fini(void)
71 {
72 }
73 
74 static struct stats *
75 stats_new(const char *name, const char *desc, enum stats_type t)
76 {
77 	struct stats *ret = MALLOC(sizeof (*ret));
78 
79 	bzero(ret, sizeof (*ret));
80 	ret->t = t;
81 
82 	(void) strlcpy(ret->fmd_stats.fmds_desc, desc,
83 	    sizeof (ret->fmd_stats.fmds_desc));
84 
85 	/* NULL name means generate a unique name */
86 	if (name == NULL) {
87 		static int uniqstat;
88 
89 		(void) snprintf(ret->fmd_stats.fmds_name,
90 		    sizeof (ret->fmd_stats.fmds_name),
91 		    "stat.rules%d", uniqstat++);
92 	} else {
93 		(void) strlcpy(ret->fmd_stats.fmds_name, name,
94 		    sizeof (ret->fmd_stats.fmds_name));
95 	}
96 
97 	switch (t) {
98 	case STATS_COUNTER:
99 		ret->fmd_stats.fmds_type = FMD_TYPE_INT32;
100 		break;
101 
102 	case STATS_ELAPSE:
103 		ret->fmd_stats.fmds_type = FMD_TYPE_TIME;
104 		break;
105 
106 	case STATS_STRING:
107 		ret->fmd_stats.fmds_type = FMD_TYPE_STRING;
108 		break;
109 
110 	default:
111 		out(O_DIE, "stats_new: unknown type %d", t);
112 	}
113 
114 	(void) fmd_stat_create(Hdl, FMD_STAT_NOALLOC, 1, &(ret->fmd_stats));
115 
116 	return (ret);
117 }
118 
119 void
120 stats_delete(struct stats *sp)
121 {
122 	if (sp == NULL)
123 		return;
124 
125 	fmd_stat_destroy(Hdl, 1, &(sp->fmd_stats));
126 	FREE(sp);
127 }
128 
129 struct stats *
130 stats_new_counter(const char *name, const char *desc, int ext)
131 {
132 	if (ext && !Ext)
133 		return (NULL);		/* extended stats not enabled */
134 
135 	return (stats_new(name, desc, STATS_COUNTER));
136 }
137 
138 void
139 stats_counter_bump(struct stats *sp)
140 {
141 	if (sp == NULL)
142 		return;
143 
144 	ASSERT(sp->t == STATS_COUNTER);
145 
146 	sp->fmd_stats.fmds_value.i32++;
147 }
148 
149 void
150 stats_counter_add(struct stats *sp, int n)
151 {
152 	if (sp == NULL)
153 		return;
154 
155 	ASSERT(sp->t == STATS_COUNTER);
156 
157 	sp->fmd_stats.fmds_value.i32 += n;
158 }
159 
160 void
161 stats_counter_reset(struct stats *sp)
162 {
163 	if (sp == NULL)
164 		return;
165 
166 	ASSERT(sp->t == STATS_COUNTER);
167 
168 	sp->fmd_stats.fmds_value.i32 = 0;
169 }
170 
171 int
172 stats_counter_value(struct stats *sp)
173 {
174 	if (sp == NULL)
175 		return (0);
176 
177 	ASSERT(sp->t == STATS_COUNTER);
178 
179 	return (sp->fmd_stats.fmds_value.i32);
180 }
181 
182 struct stats *
183 stats_new_elapse(const char *name, const char *desc, int ext)
184 {
185 	if (ext && !Ext)
186 		return (NULL);		/* extended stats not enabled */
187 
188 	return (stats_new(name, desc, STATS_ELAPSE));
189 }
190 
191 void
192 stats_elapse_start(struct stats *sp)
193 {
194 	if (sp == NULL)
195 		return;
196 
197 	ASSERT(sp->t == STATS_ELAPSE);
198 
199 	sp->start = gethrtime();
200 }
201 
202 void
203 stats_elapse_stop(struct stats *sp)
204 {
205 	if (sp == NULL)
206 		return;
207 
208 	ASSERT(sp->t == STATS_ELAPSE);
209 
210 	sp->stop = gethrtime();
211 	sp->fmd_stats.fmds_value.ui64 = sp->stop - sp->start;
212 }
213 
214 struct stats *
215 stats_new_string(const char *name, const char *desc, int ext)
216 {
217 	struct stats *r;
218 
219 	if (ext && !Ext)
220 		return (NULL);		/* extended stats not enabled */
221 
222 	r = stats_new(name, desc, STATS_STRING);
223 	return (r);
224 }
225 
226 void
227 stats_string_set(struct stats *sp, const char *s)
228 {
229 	if (sp == NULL)
230 		return;
231 
232 	ASSERT(sp->t == STATS_STRING);
233 
234 	if (sp->fmd_stats.fmds_value.str)
235 		fmd_hdl_strfree(Hdl, sp->fmd_stats.fmds_value.str);
236 	sp->fmd_stats.fmds_value.str = fmd_hdl_strdup(Hdl, s, FMD_SLEEP);
237 }
238 
239 /*
240  * stats_publish -- spew all stats
241  *
242  */
243 
244 void
245 stats_publish(void)
246 {
247 	/* nothing to do for eft */
248 }
249