Merge remote-tracking branch 'github/pr/1749'
[collectd.git] / src / fscache.c
1 /**
2  * collectd - src/fscache.c
3  * Copyright (C) 2009 Edward "Koko" Konetzko
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; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  * Authors:
19  *   Edward "Koko" Konetzko <konetzed at quixoticagony.com>
20  **/
21
22 #include "collectd.h"
23
24 #include "common.h"
25 #include "plugin.h"
26 #include <stdio.h>  /* a header needed for FILE */
27 #include <string.h> /* a header needed for scanf function */
28 #include <stdlib.h> /* used for atoi */
29
30
31 #if !KERNEL_LINUX
32 # error "This module only supports the Linux implementation of fscache"
33 #endif
34
35 #define BUFSIZE 1024
36
37 /*
38 see /proc/fs/fscache/stats
39 see Documentation/filesystems/caching/fscache.txt in linux kernel >= 2.6.30
40
41 This shows counts of a number of events that can happen in FS-Cache:
42
43 CLASS   EVENT   MEANING
44 ======= ======= =======================================================
45 Cookies idx=N   Number of index cookies allocated
46         dat=N   Number of data storage cookies allocated
47         spc=N   Number of special cookies allocated
48 Objects alc=N   Number of objects allocated
49         nal=N   Number of object allocation failures
50         avl=N   Number of objects that reached the available state
51         ded=N   Number of objects that reached the dead state
52 ChkAux  non=N   Number of objects that didn't have a coherency check
53         ok=N    Number of objects that passed a coherency check
54         upd=N   Number of objects that needed a coherency data update
55         obs=N   Number of objects that were declared obsolete
56 Pages   mrk=N   Number of pages marked as being cached
57         unc=N   Number of uncache page requests seen
58 Acquire n=N Number of acquire cookie requests seen
59         nul=N   Number of acq reqs given a NULL parent
60         noc=N   Number of acq reqs rejected due to no cache available
61         ok=N    Number of acq reqs succeeded
62         nbf=N   Number of acq reqs rejected due to error
63         oom=N   Number of acq reqs failed on ENOMEM
64 Lookups n=N Number of lookup calls made on cache backends
65         neg=N   Number of negative lookups made
66         pos=N   Number of positive lookups made
67         crt=N   Number of objects created by lookup
68 Updates n=N Number of update cookie requests seen
69         nul=N   Number of upd reqs given a NULL parent
70         run=N   Number of upd reqs granted CPU time
71 Relinqs n=N Number of relinquish cookie requests seen
72         nul=N   Number of rlq reqs given a NULL parent
73         wcr=N   Number of rlq reqs waited on completion of creation
74 AttrChg n=N Number of attribute changed requests seen
75         ok=N    Number of attr changed requests queued
76         nbf=N   Number of attr changed rejected -ENOBUFS
77         oom=N   Number of attr changed failed -ENOMEM
78         run=N   Number of attr changed ops given CPU time
79 Allocs  n=N Number of allocation requests seen
80         ok=N    Number of successful alloc reqs
81         wt=N    Number of alloc reqs that waited on lookup completion
82         nbf=N   Number of alloc reqs rejected -ENOBUFS
83         ops=N   Number of alloc reqs submitted
84         owt=N   Number of alloc reqs waited for CPU time
85 Retrvls n=N Number of retrieval (read) requests seen
86         ok=N    Number of successful retr reqs
87         wt=N    Number of retr reqs that waited on lookup completion
88         nod=N   Number of retr reqs returned -ENODATA
89         nbf=N   Number of retr reqs rejected -ENOBUFS
90         int=N   Number of retr reqs aborted -ERESTARTSYS
91         oom=N   Number of retr reqs failed -ENOMEM
92         ops=N   Number of retr reqs submitted
93         owt=N   Number of retr reqs waited for CPU time
94 Stores  n=N Number of storage (write) requests seen
95         ok=N    Number of successful store reqs
96         agn=N   Number of store reqs on a page already pending storage
97         nbf=N   Number of store reqs rejected -ENOBUFS
98         oom=N   Number of store reqs failed -ENOMEM
99         ops=N   Number of store reqs submitted
100         run=N   Number of store reqs granted CPU time
101 Ops pend=N  Number of times async ops added to pending queues
102         run=N   Number of times async ops given CPU time
103         enq=N   Number of times async ops queued for processing
104         dfr=N   Number of async ops queued for deferred release
105         rel=N   Number of async ops released
106         gc=N    Number of deferred-release async ops garbage collected
107
108 63 events to collect in 13 groups
109 */
110 static void fscache_submit (const char *section, const char *name,
111         value_t value)
112 {
113     value_list_t vl = VALUE_LIST_INIT;
114
115     vl.values = &value;
116     vl.values_len = 1;
117
118     sstrncpy(vl.plugin, "fscache", sizeof (vl.plugin));
119     sstrncpy(vl.plugin_instance, section, sizeof (vl.plugin_instance));
120     sstrncpy(vl.type, "fscache_stat", sizeof(vl.type));
121     sstrncpy(vl.type_instance, name, sizeof(vl.type_instance));
122
123     plugin_dispatch_values (&vl);
124 }
125
126 static void fscache_read_stats_file (FILE *fh)
127 {
128     char section[DATA_MAX_NAME_LEN];
129     size_t section_len;
130
131     char linebuffer[BUFSIZE];
132
133 /*
134  *  cat /proc/fs/fscache/stats
135  *      FS-Cache statistics
136  *      Cookies: idx=2 dat=0 spc=0
137  *      Objects: alc=0 nal=0 avl=0 ded=0
138  *      ChkAux : non=0 ok=0 upd=0 obs=0
139  *      Pages  : mrk=0 unc=0
140  *      Acquire: n=2 nul=0 noc=0 ok=2 nbf=0 oom=0
141  *      Lookups: n=0 neg=0 pos=0 crt=0
142  *      Updates: n=0 nul=0 run=0
143  *      Relinqs: n=0 nul=0 wcr=0
144  *      AttrChg: n=0 ok=0 nbf=0 oom=0 run=0
145  *      Allocs : n=0 ok=0 wt=0 nbf=0
146  *      Allocs : ops=0 owt=0
147  *      Retrvls: n=0 ok=0 wt=0 nod=0 nbf=0 int=0 oom=0
148  *      Retrvls: ops=0 owt=0
149  *      Stores : n=0 ok=0 agn=0 nbf=0 oom=0
150  *      Stores : ops=0 run=0
151  *      Ops    : pend=0 run=0 enq=0
152  *      Ops    : dfr=0 rel=0 gc=0
153  */
154
155     /* Read file line by line */
156     while (fgets (linebuffer, sizeof (linebuffer), fh) != NULL)
157     {
158         char *lineptr;
159         char *fields[32];
160         int fields_num;
161
162         /* Find the colon and replace it with a null byte */
163         lineptr = strchr (linebuffer, ':');
164         if (lineptr == NULL)
165             continue;
166         *lineptr = 0;
167         lineptr++;
168
169         /* Copy and clean up the section name */
170         sstrncpy (section, linebuffer, sizeof (section));
171         section_len = strlen (section);
172         while ((section_len > 0) && isspace ((int) section[section_len - 1]))
173         {
174             section_len--;
175             section[section_len] = 0;
176         }
177         if (section_len == 0)
178             continue;
179
180         fields_num = strsplit (lineptr, fields, STATIC_ARRAY_SIZE (fields));
181         if (fields_num <= 0)
182             continue;
183
184         for (int i = 0; i < fields_num; i++)
185         {
186             char *field_name;
187             char *field_value_str;
188             value_t field_value_cnt;
189             int status;
190
191             field_name = fields[i];
192             assert (field_name != NULL);
193
194             field_value_str = strchr (field_name, '=');
195             if (field_value_str == NULL)
196                 continue;
197             *field_value_str = 0;
198             field_value_str++;
199
200             status = parse_value (field_value_str, &field_value_cnt,
201                     DS_TYPE_DERIVE);
202             if (status != 0)
203                 continue;
204
205             fscache_submit (section, field_name, field_value_cnt);
206         }
207     } /* while (fgets) */
208 } /* void fscache_read_stats_file */
209
210 static int fscache_read (void){
211     FILE *fh;
212     fh = fopen("/proc/fs/fscache/stats", "r");
213     if (fh != NULL){
214         fscache_read_stats_file(fh);
215         fclose(fh);
216
217     }else{
218         printf("cant open file\n");
219         return (-1);
220     }
221     return (0);
222 }
223
224 void module_register (void)
225 {
226     plugin_register_read ("fscache", fscache_read);
227 } /* void module_register */
228
229 /* vim: set sw=4 sts=4 et : */