b2b4c9690be220632d4e1f46bc61d11fa6593372
[kai/samba.git] / examples / perfcounter / perf_writer_disk.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Performance Counter Daemon
4  *
5  *  Copyright (C) Marcin Krzysztof Porwit    2005
6  *  
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *  
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *  
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include "perf.h"
23
24 void init_diskdata_desc(PERF_DATA_BLOCK *data)
25 {
26         init_perf_counter(&(data->diskInfo.diskObjDesc),
27                           &(data->diskInfo.diskObjDesc),
28                           get_counter_id(data),
29                           "Logical Disk",
30                           "The Logical Disk object consists of counters that show information about disks.",
31                           0,
32                           PERF_OBJECT);
33         init_perf_counter(&(data->diskInfo.freeMegs),
34                           &(data->diskInfo.diskObjDesc),
35                           get_counter_id(data),
36                           "Megabytes Free",
37                           "The amount of available disk space, in megabytes.",
38                           PERF_SIZE_LARGE | PERF_TYPE_NUMBER | PERF_NUMBER_DECIMAL | PERF_DISPLAY_NO_SUFFIX,
39                           PERF_COUNTER);
40         init_perf_counter(&(data->diskInfo.writesPerSec),
41                           &(data->diskInfo.diskObjDesc),
42                           get_counter_id(data),
43                           "Writes/sec",
44                           "The number of writes per second to that disk.",
45                           PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_DELTA_COUNTER | PERF_DISPLAY_PER_SEC,
46                           PERF_COUNTER);
47         init_perf_counter(&(data->diskInfo.readsPerSec),
48                           &(data->diskInfo.diskObjDesc),
49                           get_counter_id(data),
50                           "Reads/sec",
51                           "The number of reads of that disk per second.",
52                           PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_DELTA_COUNTER | PERF_DISPLAY_PER_SEC,
53                           PERF_COUNTER);
54
55         return;
56 }
57 void init_num_disks(PERF_DATA_BLOCK *data)
58 {
59         FILE *mtab;
60         char buf[PROC_BUF];
61         char *start, *stop;
62         int i = 0, num;
63
64         if(!(mtab = fopen("/etc/mtab", "r")))
65         {
66                 perror("init_disk_names: fopen");
67                 exit(1);
68         }
69
70         rewind(mtab);
71         fflush(mtab);
72
73         while(fgets(buf, sizeof(buf), mtab))
74         {
75                 if(start = strstr(buf, "/dev/"))
76                 {
77                         if(start = strstr(start, "da"))
78                         {
79                                 i++;
80                         }
81                 }
82         }
83
84         data->diskInfo.numDisks = i;
85         fclose(mtab);
86
87         return;
88 }
89         
90 void init_disk_names(PERF_DATA_BLOCK *data)
91 {
92         FILE *mtab;
93         char buf[PROC_BUF];
94         char *start, *stop;
95         int i = 0, num;
96
97         if(!(mtab = fopen("/etc/mtab", "r")))
98         {
99                 perror("init_disk_names: fopen");
100                 exit(1);
101         }
102
103         rewind(mtab);
104         fflush(mtab);
105
106         while(fgets(buf, sizeof(buf), mtab))
107         {
108                 if(start = strstr(buf, "/dev/"))
109                 {
110                         if(start = strstr(start, "da"))
111                         {
112                                 start -=1;
113                                 stop = strstr(start, " ");
114                                 memcpy(data->diskInfo.mdata[i].name, start, stop - start);
115                                 start = stop +1;
116                                 stop = strstr(start, " ");
117                                 memcpy(data->diskInfo.mdata[i].mountpoint, start, stop - start);
118                                 i++;
119                         }
120                 }
121         }
122
123         fclose(mtab);
124
125         return;
126 }
127
128 void get_diskinfo(PERF_DATA_BLOCK *data)
129 {
130         int i;
131         DiskData *p;
132         struct statfs statfsbuf;
133         int status, num;
134         char buf[LARGE_BUF], *start;
135         FILE *diskstats;
136         long reads, writes, discard;
137
138         diskstats = fopen("/proc/diskstats", "r");
139         rewind(diskstats);
140         fflush(diskstats);
141         status = fread(buf, sizeof(char), LARGE_BUF, diskstats);
142         fclose(diskstats);
143
144         for(i = 0; i < data->diskInfo.numDisks; i++)
145         {
146                 p = &(data->diskInfo.data[i]);
147                 status = statfs(data->diskInfo.mdata[i].mountpoint, &statfsbuf);
148                 p->freeMegs = (statfsbuf.f_bfree*statfsbuf.f_bsize)/1048576;
149                 start = strstr(buf, data->diskInfo.mdata[i].name);
150                 start += strlen(data->diskInfo.mdata[i].name) + 1;
151                 num = sscanf(start, "%u %u %u %u",
152                              &reads,
153                              &discard, 
154                              &writes, 
155                              &discard);
156                 p->writesPerSec = writes;
157                 p->readsPerSec = reads;
158                 fprintf(stderr, "%s:\t%u\t%u\n",
159                         data->diskInfo.mdata[i].mountpoint,
160                         reads, writes);
161         }
162         return;
163 }
164 void init_disk_data(PERF_DATA_BLOCK *data)
165 {
166         init_diskdata_desc(data);
167         
168         init_num_disks(data);
169
170         data->diskInfo.mdata = calloc(data->diskInfo.numDisks, sizeof(DiskMetaData));
171         if(!data->diskInfo.mdata)
172         {
173                 fatal("init_disk_data: out of memory");
174         }
175
176         init_disk_names(data);
177
178         data->diskInfo.data = calloc(data->diskInfo.numDisks, sizeof(DiskData));
179         if(!data->diskInfo.data)
180         {
181                 fatal("init_disk_data: out of memory");
182         }
183
184         get_diskinfo(data);
185
186         return;
187 }
188
189 void output_disk_desc(PERF_DATA_BLOCK *data, RuntimeSettings rt)
190 {
191         output_perf_desc(data->diskInfo.diskObjDesc, rt);
192         output_perf_desc(data->diskInfo.freeMegs, rt);
193         output_perf_desc(data->diskInfo.writesPerSec, rt);
194         output_perf_desc(data->diskInfo.readsPerSec, rt);
195         output_num_instances(data->diskInfo.diskObjDesc, data->diskInfo.numDisks, rt);
196
197         return;
198 }
199
200 void output_diskinfo(PERF_DATA_BLOCK *data, RuntimeSettings rt, int tdb_flags)
201 {
202         int i;
203         
204         output_perf_counter(data->diskInfo.freeMegs,
205                             data->diskInfo.data[0].freeMegs,
206                             rt, tdb_flags);
207         output_perf_counter(data->diskInfo.writesPerSec,
208                             (unsigned long long)data->diskInfo.data[0].writesPerSec,
209                             rt, tdb_flags);
210         output_perf_counter(data->diskInfo.readsPerSec,
211                             (unsigned long long)data->diskInfo.data[0].readsPerSec,
212                             rt, tdb_flags);
213
214         for(i = 0; i < data->diskInfo.numDisks; i++)
215         {
216                 output_perf_instance(data->diskInfo.diskObjDesc.index,
217                                      i,
218                                      (void *)&(data->diskInfo.data[i]),
219                                      sizeof(DiskData),
220                                      data->diskInfo.mdata[i].mountpoint,
221                                      rt, tdb_flags);
222         }
223
224         return;
225 }