~ubuntu-branches/ubuntu/lucid/conky/lucid

« back to all changes in this revision

Viewing changes to .pc/debian-changes-1.8.0-1ubuntu1/src/diskio.c

  • Committer: Bazaar Package Importer
  • Author(s): Cesare Tirabassi
  • Date: 2010-04-23 11:07:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100423110702-728kaq96qjmhvh15
Tags: 1.8.0-1ubuntu1
* Fix ncurses being enabled for all binary packages (upstream default)
* Cherry pick following fixes from the 1.8.1 branch:
  - fix reversed $if_existing logic
  - fix device name parsing for diskio variables
  - fix X error when border_width is <1
  - fix parsing of TEXT section when first line is a comment
  - fix battery_bar should also work without argument
  - fix mixerbar showing wrong values
  - fix read_tcp reversed connection check logic

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
 
2
 * vim: ts=4 sw=4 noet ai cindent syntax=c
 
3
 *
 
4
 * Conky, a system monitor, based on torsmo
 
5
 *
 
6
 * Any original torsmo code is licensed under the BSD license
 
7
 *
 
8
 * All code written since the fork of torsmo is licensed under the GPL
 
9
 *
 
10
 * Please see COPYING for details
 
11
 *
 
12
 * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
 
13
 * Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al.
 
14
 * (see AUTHORS)
 
15
 * All rights reserved.
 
16
 *
 
17
 * This program is free software: you can redistribute it and/or modify
 
18
 * it under the terms of the GNU General Public License as published by
 
19
 * the Free Software Foundation, either version 3 of the License, or
 
20
 * (at your option) any later version.
 
21
 *
 
22
 * This program is distributed in the hope that it will be useful,
 
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
25
 * GNU General Public License for more details.
 
26
 * You should have received a copy of the GNU General Public License
 
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
28
 *
 
29
 */
 
30
 
 
31
#include "config.h"
 
32
#include "conky.h"      /* text_buffer_size */
 
33
#include "core.h"
 
34
#include "logging.h"
 
35
#include "diskio.h"
 
36
#include "common.h"
 
37
#include "specials.h"
 
38
#include "text_object.h"
 
39
#include <stdlib.h>
 
40
#include <limits.h>
 
41
#include <sys/stat.h>
 
42
 
 
43
/* this is the root of all per disk stats,
 
44
 * also containing the totals. */
 
45
struct diskio_stat stats = {
 
46
        .next = NULL,
 
47
        .sample = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
48
        .sample_read = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
49
        .sample_write = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
50
        .current = 0,
 
51
        .current_read = 0,
 
52
        .current_write = 0,
 
53
        .last = UINT_MAX,
 
54
        .last_read = UINT_MAX,
 
55
        .last_write = UINT_MAX,
 
56
};
 
57
 
 
58
void clear_diskio_stats(void)
 
59
{
 
60
        struct diskio_stat *cur;
 
61
        while (stats.next) {
 
62
                cur = stats.next;
 
63
                stats.next = stats.next->next;
 
64
                if (cur->dev)
 
65
                        free(cur->dev);
 
66
                free(cur);
 
67
        }
 
68
}
 
69
 
 
70
struct diskio_stat *prepare_diskio_stat(const char *s)
 
71
{
 
72
        struct stat sb;
 
73
        char stat_name[text_buffer_size], device_name[text_buffer_size];
 
74
        struct diskio_stat *cur = &stats;
 
75
 
 
76
        if (!s)
 
77
                return &stats;
 
78
 
 
79
#if defined(__FreeBSD__)
 
80
        if (strncmp(s, "/dev/", 5) == 0) {
 
81
                // supplied a /dev/device arg, so cut off the /dev part
 
82
                strncpy(device_name, s + 5, text_buffer_size);
 
83
        } else
 
84
#endif
 
85
        strncpy(device_name, s, text_buffer_size);
 
86
 
 
87
        snprintf(stat_name, text_buffer_size, "/dev/%s", device_name);
 
88
 
 
89
        if (stat(stat_name, &sb)) {
 
90
                NORM_ERR("diskio device '%s' does not exist", s);
 
91
        }
 
92
 
 
93
        /* lookup existing */
 
94
        while (cur->next) {
 
95
                cur = cur->next;
 
96
                if (!strcmp(cur->dev, device_name)) {
 
97
                        return cur;
 
98
                }
 
99
        }
 
100
 
 
101
        /* no existing found, make a new one */
 
102
        cur->next = calloc(1, sizeof(struct diskio_stat));
 
103
        cur = cur->next;
 
104
        cur->dev = strndup(device_name, text_buffer_size);
 
105
        cur->last = UINT_MAX;
 
106
        cur->last_read = UINT_MAX;
 
107
        cur->last_write = UINT_MAX;
 
108
 
 
109
        return cur;
 
110
}
 
111
 
 
112
void parse_diskio_arg(struct text_object *obj, const char *arg)
 
113
{
 
114
        obj->data.opaque = prepare_diskio_stat(arg);
 
115
}
 
116
 
 
117
/* dir indicates the direction:
 
118
 * -1: read
 
119
 *  0: read + write
 
120
 *  1: write
 
121
 */
 
122
static void print_diskio_dir(struct text_object *obj, int dir, char *p, int p_max_size)
 
123
{
 
124
        struct diskio_stat *diskio = obj->data.opaque;
 
125
        double val;
 
126
 
 
127
        if (!diskio)
 
128
                return;
 
129
 
 
130
        if (dir < 0)
 
131
                val = diskio->current_read;
 
132
        else if (dir == 0)
 
133
                val = diskio->current;
 
134
        else
 
135
                val = diskio->current_write;
 
136
 
 
137
        /* TODO: move this correction from kB to kB/s elsewhere
 
138
         * (or get rid of it??) */
 
139
        human_readable((val / update_interval) * 1024LL, p, p_max_size);
 
140
}
 
141
 
 
142
void print_diskio(struct text_object *obj, char *p, int p_max_size)
 
143
{
 
144
        print_diskio_dir(obj, 0, p, p_max_size);
 
145
}
 
146
 
 
147
void print_diskio_read(struct text_object *obj, char *p, int p_max_size)
 
148
{
 
149
        print_diskio_dir(obj, -1, p, p_max_size);
 
150
}
 
151
 
 
152
void print_diskio_write(struct text_object *obj, char *p, int p_max_size)
 
153
{
 
154
        print_diskio_dir(obj, 1, p, p_max_size);
 
155
}
 
156
 
 
157
#ifdef X11
 
158
void parse_diskiograph_arg(struct text_object *obj, const char *arg)
 
159
{
 
160
        char *buf = 0;
 
161
        buf = scan_graph(obj, arg, 0);
 
162
 
 
163
        obj->data.opaque = prepare_diskio_stat(dev_name(buf));
 
164
        if (buf)
 
165
                free(buf);
 
166
}
 
167
 
 
168
static void print_diskiograph_dir(struct text_object *obj, int dir, char *p, int p_max_size)
 
169
{
 
170
        struct diskio_stat *diskio = obj->data.opaque;
 
171
        double val;
 
172
 
 
173
        if (!diskio)
 
174
                return;
 
175
 
 
176
        if (!p_max_size)
 
177
                return;
 
178
 
 
179
        if (dir < 0)
 
180
                val = diskio->current_read;
 
181
        else if (dir == 0)
 
182
                val = diskio->current;
 
183
        else
 
184
                val = diskio->current_write;
 
185
 
 
186
        new_graph(obj, p, p_max_size, val);
 
187
}
 
188
 
 
189
void print_diskiograph(struct text_object *obj, char *p, int p_max_size)
 
190
{
 
191
        print_diskiograph_dir(obj, 0, p, p_max_size);
 
192
}
 
193
 
 
194
void print_diskiograph_read(struct text_object *obj, char *p, int p_max_size)
 
195
{
 
196
        print_diskiograph_dir(obj, -1, p, p_max_size);
 
197
}
 
198
 
 
199
void print_diskiograph_write(struct text_object *obj, char *p, int p_max_size)
 
200
{
 
201
        print_diskiograph_dir(obj, 1, p, p_max_size);
 
202
}
 
203
#endif /* X11 */
 
204
 
 
205
void update_diskio_values(struct diskio_stat *ds,
 
206
                unsigned int reads, unsigned int writes)
 
207
{
 
208
        int i;
 
209
        double sum=0, sum_r=0, sum_w=0;
 
210
 
 
211
        if (reads < ds->last_read || writes < ds->last_write) {
 
212
                /* counter overflow or reset - rebase to sane values */
 
213
                ds->last = reads+writes;
 
214
                ds->last_read = reads;
 
215
                ds->last_write = writes;
 
216
        }
 
217
        /* since the values in /proc/diskstats are absolute, we have to subtract
 
218
         * our last reading. The numbers stand for "sectors read", and we therefore
 
219
         * have to divide by two to get KB */
 
220
        ds->sample_read[0] = (reads - ds->last_read) / 2;
 
221
        ds->sample_write[0] = (writes - ds->last_write) / 2;
 
222
        ds->sample[0] = ds->sample_read[0] + ds->sample_write[0];
 
223
 
 
224
        /* compute averages */
 
225
        for (i = 0; i < (signed) info.diskio_avg_samples; i++) {
 
226
                sum += ds->sample[i];
 
227
                sum_r += ds->sample_read[i];
 
228
                sum_w += ds->sample_write[i];
 
229
        }
 
230
        ds->current = sum / (double) info.diskio_avg_samples;
 
231
        ds->current_read = sum_r / (double) info.diskio_avg_samples;
 
232
        ds->current_write = sum_w / (double) info.diskio_avg_samples;
 
233
 
 
234
        /* shift sample history */
 
235
        for (i = info.diskio_avg_samples-1; i > 0; i--) {
 
236
                ds->sample[i] = ds->sample[i-1];
 
237
                ds->sample_read[i] = ds->sample_read[i-1];
 
238
                ds->sample_write[i] = ds->sample_write[i-1];
 
239
        }
 
240
 
 
241
        /* save last */
 
242
        ds->last_read = reads;
 
243
        ds->last_write = writes;
 
244
        ds->last = ds->last_read + ds->last_write;
 
245
}
 
246