Merge branch 'pull/collectd-4' into collectd-4
[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         static kstat_io_t kio;
138         int i;
139
140         if (kc == NULL)
141                 return (-1);
142
143         if (numtape <= 0)
144                 return (-1);
145
146         for (i = 0; i < numtape; i++)
147         {
148                 if (kstat_read (kc, ksp[i], &kio) == -1)
149                         continue;
150
151                 if (strncmp (ksp[i]->ks_class, "tape", 4) == 0)
152                 {
153                         tape_submit (ksp[i]->ks_name, "tape_octets", kio.reads, kio.writes);
154                         tape_submit (ksp[i]->ks_name, "tape_ops", kio.nreads, kio.nwrites);
155                         /* FIXME: Convert this to microseconds if necessary */
156                         tape_submit (ksp[i]->ks_name, "tape_time", kio.rtime, kio.wtime);
157                 }
158         }
159 #endif /* defined(HAVE_LIBKSTAT) */
160
161         return (0);
162 }
163 #endif /* TAPE_HAVE_READ */
164
165 void module_register (modreg_e load)
166 {
167         if (load & MR_DATASETS)
168         {
169                 plugin_register_data_set (&octets_ds);
170                 plugin_register_data_set (&operations_ds);
171                 plugin_register_data_set (&merged_ds);
172                 plugin_register_data_set (&time_ds);
173         }
174
175 #if TAPE_HAVE_READ
176         if (load & MR_READ)
177         {
178                 plugin_register_init ("tape", tape_init);
179                 plugin_register_read ("tape", tape_read);
180         }
181 #endif /* TAPE_HAVE_READ */
182 }