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