wmclockmon: update change-log
[dockapps.git] / wmsupermon / stat_dev.c
blob83c9e96b5f3888a4668315a65739cc7a07c914b1
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 */
17 originally based on
18 WMgMon - Window Maker Generic Monitor
19 by Nicolas Chauvat <nico@caesium.fr>
22 #include <stdlib.h>
23 #include <regex.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <math.h>
29 #include "expr.h"
30 #include "stat_dev.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 */
47 else
48 st->next_update=~0; /* that is never */
51 void stat_dev_update_history (stat_dev *st)
53 int i;
54 for (i=0; i <= P_HIST; i++) {
55 int j;
56 history *hist=st->hist[i];
57 if (!hist) continue;
59 /* history is updated more often than the value is sampled. Use previous
60 value to avoid a gap in the history */
61 if (hist->count == 0)
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 */
66 if (hist->count > 1)
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];
77 /* reset sample */
78 hist->data[HIST_LAST]=0;
79 hist->count=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))
93 return 0;
95 st->value[0]=st->expr->eval(st->expr, &ctx)/st->scale;
96 return 1;
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)
106 char *buf;
107 double *tmp;
108 FILE *f;
109 int matched=0;
111 f= (st->source[0] == '!') ?
112 popen(st->source+1, "r") : fopen(st->source, "r");
114 if (!f) {
115 stat_perror(st, "open");
116 return;
119 if (!st->expr) {
120 double value;
121 if (fscanf(f, "%lf", &value) == 1)
122 st->value[0]=value/st->scale;
123 goto done;
126 /* ok, doing regexp */
127 if (st->flags & F_SINGLE_LINE) {
128 struct stat stat;
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);
136 free(buf);
137 goto done;
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)
144 break;
147 done:
148 if (st->flags & F_DEBUG) {
149 if (matched)
150 printf("%-4s: %f\n", st->name, st->value[0]);
151 else
152 printf("%-4s: match failed\n", st->name);
155 tmp=st->diff_old; st->diff_old=st->diff_new; st->diff_new=tmp;
157 ret:
158 (st->source[0] == '!') ? pclose(f) : fclose(f);