1 /* Copyright (C) 2006 Sergei Golubchik
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License version 2
5 as published by the Free Software Foundation
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18 WMgMon - Window Maker Generic Monitor
19 by Nicolas Chauvat <nico@caesium.fr>
24 #include <sys/types.h>
32 /******************************************************************************/
33 /* stat_dev structure and related functions */
34 /******************************************************************************/
36 void stat_dev_init(stat_dev
* st
)
38 bzero(st
, sizeof(*st
));
39 st
->update_interval
=1;
40 st
->hist_update_interval
=5;
43 void stat_dev_initstat (stat_dev
* st
)
45 if (st
->flags
& F_USED
)
46 update_stat(st
); /* to get first value for DIFF */
48 st
->next_update
=~0; /* that is never */
51 void stat_dev_update_history (stat_dev
*st
)
54 for (i
=0; i
<= P_HIST
; i
++) {
56 history
*hist
=st
->hist
[i
];
59 /* history is updated more often than the value is sampled. Use previous
60 value to avoid a gap in the history */
62 hist
->data
[HIST_LAST
]=hist
->data
[HIST_LAST
-1];
64 /* we probably sampled several times since last time we updated,
65 let's normalize value by dividing by the number of times we sampled */
67 hist
->data
[HIST_LAST
] /= hist
->count
;
69 if (i
& P_LOG
&& hist
->count
)
70 hist
->data
[HIST_LAST
]=hist
->data
[HIST_LAST
]*3 <= 1 ?
71 0 : log(hist
->data
[HIST_LAST
]*3);
73 /* shift values to the left (discard his[0]) */
74 for (j
=1; j
< HIST_SIZE
; j
++)
75 hist
->data
[j
-1]=hist
->data
[j
];
78 hist
->data
[HIST_LAST
]=0;
83 /******************************************************************************/
84 /* update stat functions */
85 /******************************************************************************/
87 /* returns 1 on a match */
88 static int do_regex(stat_dev
*st
, char *str
) {
89 regmatch_t pmatch
[MAX_VAR
];
90 Econtext ctx
={str
, pmatch
, st
->diff_old
, st
->diff_new
, st
->sum_acc
};
92 if (regexec(&st
->regex
, str
, MAX_VAR
, pmatch
, 0))
95 st
->value
[0]=st
->expr
->eval(st
->expr
, &ctx
)/st
->scale
;
99 static void stat_perror(stat_dev
*st
, char *op
)
101 fprintf(stderr
, "[%s]: %s() failed: %s\n", st
->name
, op
, strerror(errno
));
104 void update_stat(stat_dev
*st
)
111 f
= (st
->source
[0] == '!') ?
112 popen(st
->source
+1, "r") : fopen(st
->source
, "r");
115 stat_perror(st
, "open");
121 if (fscanf(f
, "%lf", &value
) == 1)
122 st
->value
[0]=value
/st
->scale
;
126 /* ok, doing regexp */
127 if (st
->flags
& F_SINGLE_LINE
) {
129 if (fstat(fileno(f
), &stat
) < 0) { stat_perror(st
, "fstat"); goto ret
; }
130 if (stat
.st_size
< MIN_FILE_LEN
)
131 stat
.st_size
=MIN_FILE_LEN
; /* because /proc files may have zero length */
132 buf
=malloc(stat
.st_size
); /* and it'd better be small! */
133 if (!buf
) { stat_perror(st
, "malloc"); goto ret
; }
134 fread(buf
, stat
.st_size
, 1, f
);
135 matched
=do_regex(st
, buf
);
140 buf
=alloca(TEMP_SIZE
);
141 if (st
->nsum
) bzero(st
->sum_acc
, st
->nsum
*sizeof(double));
142 while (fgets(buf
, TEMP_SIZE
, f
)) {
143 if ((matched
|=do_regex(st
, buf
)) && !st
->nsum
)
148 if (st
->flags
& F_DEBUG
) {
150 printf("%-4s: %f\n", st
->name
, st
->value
[0]);
152 printf("%-4s: match failed\n", st
->name
);
155 tmp
=st
->diff_old
; st
->diff_old
=st
->diff_new
; st
->diff_new
=tmp
;
158 (st
->source
[0] == '!') ? pclose(f
) : fclose(f
);