disk, tape plugin: Handle different `kstat_io_t' correctly.
[collectd.git] / src / tape.c
1 /**
2  * collectd - src/tape.c
3  * Copyright (C) 2005,2006  Scott Garrett
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  *
19  * Authors:
20  *   Scott Garrett <sgarrett at technomancer.com>
21  **/
22
23 #include "collectd.h"
24 #include "common.h"
25 #include "plugin.h"
26
27 #if defined(HAVE_LIBKSTAT)
28 # define TAPE_HAVE_READ 1
29 #else
30 # define TAPE_HAVE_READ 0
31 #endif
32
33 /* 2^34 = 17179869184 = ~17.2GByte/s */
34 static data_source_t octets_dsrc[2] =
35 {
36         {"read",  DS_TYPE_COUNTER, 0, 17179869183.0},
37         {"write", DS_TYPE_COUNTER, 0, 17179869183.0}
38 };
39
40 static data_set_t octets_ds =
41 {
42         "tape_octets", 2, octets_dsrc
43 };
44
45 static data_source_t operations_dsrc[2] =
46 {
47         {"read",  DS_TYPE_COUNTER, 0, 4294967295.0},
48         {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
49 };
50
51 static data_set_t operations_ds =
52 {
53         "tape_ops", 2, operations_dsrc
54 };
55
56 static data_source_t merged_dsrc[2] =
57 {
58         {"read",  DS_TYPE_COUNTER, 0, 4294967295.0},
59         {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
60 };
61
62 static data_set_t merged_ds =
63 {
64         "tape_merged", 2, merged_dsrc
65 };
66
67 /* max is 1000000us per second. */
68 static data_source_t time_dsrc[2] =
69 {
70         {"read",  DS_TYPE_COUNTER, 0, 1000000.0},
71         {"write", DS_TYPE_COUNTER, 0, 1000000.0}
72 };
73
74 static data_set_t time_ds =
75 {
76         "tape_time", 2, time_dsrc
77 };
78
79 #if TAPE_HAVE_READ
80 #if defined(HAVE_LIBKSTAT)
81 #define MAX_NUMTAPE 256
82 extern kstat_ctl_t *kc;
83 static kstat_t *ksp[MAX_NUMTAPE];
84 static int numtape = 0;
85 #endif /* HAVE_LIBKSTAT */
86
87 static int tape_init (void)
88 {
89 #ifdef HAVE_LIBKSTAT
90         kstat_t *ksp_chain;
91
92         numtape = 0;
93
94         if (kc == NULL)
95                 return (-1);
96
97         for (numtape = 0, ksp_chain = kc->kc_chain;
98                         (numtape < MAX_NUMTAPE) && (ksp_chain != NULL);
99                         ksp_chain = ksp_chain->ks_next)
100         {
101                 if (strncmp (ksp_chain->ks_class, "tape", 4) )
102                         continue;
103                 if (ksp_chain->ks_type != KSTAT_TYPE_IO)
104                         continue;
105                 ksp[numtape++] = ksp_chain;
106         }
107 #endif
108
109         return (0);
110 }
111
112 static void tape_submit (const char *plugin_instance,
113                 const char *type,
114                 counter_t read, counter_t write)
115 {
116         value_t values[2];
117         value_list_t vl = VALUE_LIST_INIT;
118
119         values[0].counter = read;
120         values[1].counter = write;
121
122         vl.values = values;
123         vl.values_len = 2;
124         vl.time = time (NULL);
125         strcpy (vl.host, hostname_g);
126         strcpy (vl.plugin, "tape");
127         strncpy (vl.plugin_instance, plugin_instance,
128                         sizeof (vl.plugin_instance));
129
130         plugin_dispatch_values (type, &vl);
131 } /* void tape_submit */
132
133 static int tape_read (void)
134 {
135
136 #if defined(HAVE_LIBKSTAT)
137 # if HAVE_KSTAT_IO_T_WRITES && HAVE_KSTAT_IO_T_NWRITES && HAVE_KSTAT_IO_T_WTIME
138 #  define KIO_ROCTETS reads
139 #  define KIO_WOCTETS writes
140 #  define KIO_ROPS    nreads
141 #  define KIO_WOPS    nwrites
142 #  define KIO_RTIME   rtime
143 #  define KIO_WTIME   wtime
144 # elif HAVE_KSTAT_IO_T_NWRITTEN && HAVE_KSTAT_IO_T_WRITES && HAVE_KSTAT_IO_T_WTIME
145 #  define KIO_ROCTETS nread
146 #  define KIO_WOCTETS nwritten
147 #  define KIO_ROPS    reads
148 #  define KIO_WOPS    writes
149 #  define KIO_RTIME   rtime
150 #  define KIO_WTIME   wtime
151 # else
152 #  error "kstat_io_t does not have the required members"
153 # endif
154         static kstat_io_t kio;
155         int i;
156
157         if (kc == NULL)
158                 return (-1);
159
160         if (numtape <= 0)
161                 return (-1);
162
163         for (i = 0; i < numtape; i++)
164         {
165                 if (kstat_read (kc, ksp[i], &kio) == -1)
166                         continue;
167
168                 if (strncmp (ksp[i]->ks_class, "tape", 4) == 0)
169                 {
170                         tape_submit (ksp[i]->ks_name, "tape_octets",
171                                         kio.KIO_ROCTETS, kio.KIO_WOCTETS);
172                         tape_submit (ksp[i]->ks_name, "tape_ops",
173                                         kio.KIO_ROPS, kio.KIO_WOPS);
174                         /* FIXME: Convert this to microseconds if necessary */
175                         tape_submit (ksp[i]->ks_name, "tape_time",
176                                         kio.KIO_RTIME, kio.KIO_WTIME);
177                 }
178         }
179 #endif /* defined(HAVE_LIBKSTAT) */
180
181         return (0);
182 }
183 #endif /* TAPE_HAVE_READ */
184
185 void module_register (modreg_e load)
186 {
187         if (load & MR_DATASETS)
188         {
189                 plugin_register_data_set (&octets_ds);
190                 plugin_register_data_set (&operations_ds);
191                 plugin_register_data_set (&merged_ds);
192                 plugin_register_data_set (&time_ds);
193         }
194
195 #if TAPE_HAVE_READ
196         if (load & MR_READ)
197         {
198                 plugin_register_init ("tape", tape_init);
199                 plugin_register_read ("tape", tape_read);
200         }
201 #endif /* TAPE_HAVE_READ */
202 }