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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * stats.c -- simple stats tracking table module
26  *
27  * this version of stats.c links with eft and implements the
28  * stats using the fmd's stats API.
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include <sys/types.h>
34 #include <strings.h>
35 #include "stats.h"
36 #include "alloc.h"
37 #include "out.h"
38 #include "stats_impl.h"
39 #include <fm/fmd_api.h>
40 
41 extern fmd_hdl_t *Hdl;		/* handle from eft.c */
42 
43 static int Ext;			/* true if extended stats are enabled */
44 
45 /*
46  * stats_init -- initialize the stats module
47  *
48  */
49 
50 void
stats_init(int ext)51 stats_init(int ext)
52 {
53 	Ext = ext;
54 }
55 
56 void
stats_fini(void)57 stats_fini(void)
58 {
59 }
60 
61 static struct stats *
stats_new(const char * name,const char * desc,enum stats_type t)62 stats_new(const char *name, const char *desc, enum stats_type t)
63 {
64 	struct stats *ret = MALLOC(sizeof (*ret));
65 
66 	bzero(ret, sizeof (*ret));
67 	ret->t = t;
68 
69 	(void) strlcpy(ret->fmd_stats.fmds_desc, desc,
70 	    sizeof (ret->fmd_stats.fmds_desc));
71 
72 	/* NULL name means generate a unique name */
73 	if (name == NULL) {
74 		static int uniqstat;
75 
76 		(void) snprintf(ret->fmd_stats.fmds_name,
77 		    sizeof (ret->fmd_stats.fmds_name),
78 		    "stat.rules%d", uniqstat++);
79 	} else {
80 		(void) strlcpy(ret->fmd_stats.fmds_name, name,
81 		    sizeof (ret->fmd_stats.fmds_name));
82 	}
83 
84 	switch (t) {
85 	case STATS_COUNTER:
86 		ret->fmd_stats.fmds_type = FMD_TYPE_INT32;
87 		break;
88 
89 	case STATS_ELAPSE:
90 		ret->fmd_stats.fmds_type = FMD_TYPE_TIME;
91 		break;
92 
93 	case STATS_STRING:
94 		ret->fmd_stats.fmds_type = FMD_TYPE_STRING;
95 		break;
96 
97 	default:
98 		out(O_DIE, "stats_new: unknown type %d", t);
99 	}
100 
101 	(void) fmd_stat_create(Hdl, FMD_STAT_NOALLOC, 1, &(ret->fmd_stats));
102 
103 	return (ret);
104 }
105 
106 void
stats_delete(struct stats * sp)107 stats_delete(struct stats *sp)
108 {
109 	if (sp == NULL)
110 		return;
111 
112 	fmd_stat_destroy(Hdl, 1, &(sp->fmd_stats));
113 	FREE(sp);
114 }
115 
116 struct stats *
stats_new_counter(const char * name,const char * desc,int ext)117 stats_new_counter(const char *name, const char *desc, int ext)
118 {
119 	if (ext && !Ext)
120 		return (NULL);		/* extended stats not enabled */
121 
122 	return (stats_new(name, desc, STATS_COUNTER));
123 }
124 
125 void
stats_counter_bump(struct stats * sp)126 stats_counter_bump(struct stats *sp)
127 {
128 	if (sp == NULL)
129 		return;
130 
131 	ASSERT(sp->t == STATS_COUNTER);
132 
133 	sp->fmd_stats.fmds_value.i32++;
134 }
135 
136 void
stats_counter_add(struct stats * sp,int n)137 stats_counter_add(struct stats *sp, int n)
138 {
139 	if (sp == NULL)
140 		return;
141 
142 	ASSERT(sp->t == STATS_COUNTER);
143 
144 	sp->fmd_stats.fmds_value.i32 += n;
145 }
146 
147 void
stats_counter_reset(struct stats * sp)148 stats_counter_reset(struct stats *sp)
149 {
150 	if (sp == NULL)
151 		return;
152 
153 	ASSERT(sp->t == STATS_COUNTER);
154 
155 	sp->fmd_stats.fmds_value.i32 = 0;
156 }
157 
158 int
stats_counter_value(struct stats * sp)159 stats_counter_value(struct stats *sp)
160 {
161 	if (sp == NULL)
162 		return (0);
163 
164 	ASSERT(sp->t == STATS_COUNTER);
165 
166 	return (sp->fmd_stats.fmds_value.i32);
167 }
168 
169 struct stats *
stats_new_elapse(const char * name,const char * desc,int ext)170 stats_new_elapse(const char *name, const char *desc, int ext)
171 {
172 	if (ext && !Ext)
173 		return (NULL);		/* extended stats not enabled */
174 
175 	return (stats_new(name, desc, STATS_ELAPSE));
176 }
177 
178 void
stats_elapse_start(struct stats * sp)179 stats_elapse_start(struct stats *sp)
180 {
181 	if (sp == NULL)
182 		return;
183 
184 	ASSERT(sp->t == STATS_ELAPSE);
185 
186 	sp->start = gethrtime();
187 }
188 
189 void
stats_elapse_stop(struct stats * sp)190 stats_elapse_stop(struct stats *sp)
191 {
192 	if (sp == NULL)
193 		return;
194 
195 	ASSERT(sp->t == STATS_ELAPSE);
196 
197 	sp->stop = gethrtime();
198 	sp->fmd_stats.fmds_value.ui64 = sp->stop - sp->start;
199 }
200 
201 struct stats *
stats_new_string(const char * name,const char * desc,int ext)202 stats_new_string(const char *name, const char *desc, int ext)
203 {
204 	struct stats *r;
205 
206 	if (ext && !Ext)
207 		return (NULL);		/* extended stats not enabled */
208 
209 	r = stats_new(name, desc, STATS_STRING);
210 	return (r);
211 }
212 
213 void
stats_string_set(struct stats * sp,const char * s)214 stats_string_set(struct stats *sp, const char *s)
215 {
216 	if (sp == NULL)
217 		return;
218 
219 	ASSERT(sp->t == STATS_STRING);
220 
221 	if (sp->fmd_stats.fmds_value.str)
222 		fmd_hdl_strfree(Hdl, sp->fmd_stats.fmds_value.str);
223 	sp->fmd_stats.fmds_value.str = fmd_hdl_strdup(Hdl, s, FMD_SLEEP);
224 }
225 
226 /*
227  * stats_publish -- spew all stats
228  *
229  */
230 
231 void
stats_publish(void)232 stats_publish(void)
233 {
234 	/* nothing to do for eft */
235 }
236