changes related to temperature and layout
[monky] / src / diskio.c
index 6a53a07..d9b2f3f 100644 (file)
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
+ * vim: ts=4 sw=4 noet ai cindent syntax=c
+ *
  * Conky, a system monitor, based on torsmo
  *
  * Any original torsmo code is licensed under the BSD license
@@ -8,7 +10,7 @@
  * Please see COPYING for details
  *
  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
- * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
+ * Copyright (c) 2005-2010 Brenden Matthews, Philip Kovacs, et. al.
  * (see AUTHORS)
  * All rights reserved.
  *
 
 #include "config.h"
 #include "conky.h"     /* text_buffer_size */
+#include "core.h"
 #include "logging.h"
 #include "diskio.h"
 #include "common.h"
+#include "specials.h"
+#include "text_object.h"
 #include <stdlib.h>
 #include <limits.h>
-/* The following ifdefs were adapted from gkrellm */
-#include <linux/major.h>
-
-#if !defined(MD_MAJOR)
-#define MD_MAJOR 9
-#endif
-
-#if !defined(LVM_BLK_MAJOR)
-#define LVM_BLK_MAJOR 58
-#endif
-
-#if !defined(NBD_MAJOR)
-#define NBD_MAJOR 43
-#endif
+#include <sys/stat.h>
 
 /* this is the root of all per disk stats,
  * also containing the totals. */
-static struct diskio_stat stats = {
+struct diskio_stat stats = {
        .next = NULL,
        .sample = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        .sample_read = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -69,36 +61,142 @@ void clear_diskio_stats(void)
        while (stats.next) {
                cur = stats.next;
                stats.next = stats.next->next;
+               if (cur->dev)
+                       free(cur->dev);
                free(cur);
        }
 }
 
 struct diskio_stat *prepare_diskio_stat(const char *s)
 {
+       struct stat sb;
+       char stat_name[text_buffer_size], device_name[text_buffer_size];
        struct diskio_stat *cur = &stats;
 
        if (!s)
                return &stats;
 
+       strncpy(device_name, s, text_buffer_size);
+
+       snprintf(stat_name, text_buffer_size, "/dev/%s", device_name);
+
+       if (stat(stat_name, &sb)) {
+               NORM_ERR("diskio device '%s' does not exist", s);
+       }
+
        /* lookup existing */
        while (cur->next) {
                cur = cur->next;
-               if (!strcmp(cur->dev, s))
+               if (!strcmp(cur->dev, device_name)) {
                        return cur;
+               }
        }
 
        /* no existing found, make a new one */
-       cur->next = malloc(sizeof(struct diskio_stat));
+       cur->next = calloc(1, sizeof(struct diskio_stat));
        cur = cur->next;
-       memset(cur, 0, sizeof(struct diskio_stat));
-       cur->dev = strndup(s, text_buffer_size);
+       cur->dev = strndup(device_name, text_buffer_size);
        cur->last = UINT_MAX;
        cur->last_read = UINT_MAX;
        cur->last_write = UINT_MAX;
+
        return cur;
 }
 
-static void update_diskio_values(struct diskio_stat *ds,
+void parse_diskio_arg(struct text_object *obj, const char *arg)
+{
+       obj->data.opaque = prepare_diskio_stat(arg);
+}
+
+/* dir indicates the direction:
+ * -1: read
+ *  0: read + write
+ *  1: write
+ */
+static void print_diskio_dir(struct text_object *obj, int dir, char *p, int p_max_size)
+{
+       struct diskio_stat *diskio = obj->data.opaque;
+       double val;
+
+       if (!diskio)
+               return;
+
+       if (dir < 0)
+               val = diskio->current_read;
+       else if (dir == 0)
+               val = diskio->current;
+       else
+               val = diskio->current_write;
+
+       /* TODO: move this correction from kB to kB/s elsewhere
+        * (or get rid of it??) */
+       human_readable((val / update_interval) * 1024LL, p, p_max_size);
+}
+
+void print_diskio(struct text_object *obj, char *p, int p_max_size)
+{
+       print_diskio_dir(obj, 0, p, p_max_size);
+}
+
+void print_diskio_read(struct text_object *obj, char *p, int p_max_size)
+{
+       print_diskio_dir(obj, -1, p, p_max_size);
+}
+
+void print_diskio_write(struct text_object *obj, char *p, int p_max_size)
+{
+       print_diskio_dir(obj, 1, p, p_max_size);
+}
+
+#ifdef X11
+void parse_diskiograph_arg(struct text_object *obj, const char *arg)
+{
+       char *buf = 0;
+       buf = scan_graph(obj, arg, 0);
+
+       obj->data.opaque = prepare_diskio_stat(dev_name(buf));
+       if (buf)
+               free(buf);
+}
+
+static void print_diskiograph_dir(struct text_object *obj, int dir, char *p, int p_max_size)
+{
+       struct diskio_stat *diskio = obj->data.opaque;
+       double val;
+
+       if (!diskio)
+               return;
+
+       if (!p_max_size)
+               return;
+
+       if (dir < 0)
+               val = diskio->current_read;
+       else if (dir == 0)
+               val = diskio->current;
+       else
+               val = diskio->current_write;
+
+       new_graph(obj, p, p_max_size, val);
+}
+
+void print_diskiograph(struct text_object *obj, char *p, int p_max_size)
+{
+       print_diskiograph_dir(obj, 0, p, p_max_size);
+}
+
+void print_diskiograph_read(struct text_object *obj, char *p, int p_max_size)
+{
+       print_diskiograph_dir(obj, -1, p, p_max_size);
+}
+
+void print_diskiograph_write(struct text_object *obj, char *p, int p_max_size)
+{
+       print_diskiograph_dir(obj, 1, p, p_max_size);
+}
+#endif /* X11 */
+
+void update_diskio_values(struct diskio_stat *ds,
                unsigned int reads, unsigned int writes)
 {
        int i;
@@ -110,7 +208,7 @@ static void update_diskio_values(struct diskio_stat *ds,
                ds->last_read = reads;
                ds->last_write = writes;
        }
-       /* since the values in /proc/diskstats are absolute, we have to substract
+       /* since the values in /proc/diskstats are absolute, we have to subtract
         * our last reading. The numbers stand for "sectors read", and we therefore
         * have to divide by two to get KB */
        ds->sample_read[0] = (reads - ds->last_read) / 2;
@@ -140,54 +238,3 @@ static void update_diskio_values(struct diskio_stat *ds,
        ds->last = ds->last_read + ds->last_write;
 }
 
-void update_diskio(void)
-{
-       FILE *fp;
-       static int rep = 0;
-
-       struct diskio_stat *cur;
-       char buf[512], devbuf[64];
-       unsigned int major, minor;
-       unsigned int reads, writes;
-       unsigned int total_reads=0, total_writes=0;
-       int col_count = 0;
-
-       stats.current = 0;
-       stats.current_read = 0;
-       stats.current_write = 0;
-
-       if (!(fp = open_file("/proc/diskstats", &rep))) {
-               return;
-       }
-
-       /* read reads and writes from all disks (minor = 0), including cd-roms
-        * and floppies, and sum them up */
-       while (fgets(buf, 512, fp)) {
-               col_count = sscanf(buf, "%u %u %s %*u %*u %u %*u %*u %*u %u", &major,
-                       &minor, devbuf, &reads, &writes);
-               /* ignore subdevices (they have only 3 matching entries in their line)
-                * and virtual devices (LVM, network block devices, RAM disks, Loopback)
-                *
-                * XXX: ignore devices which are part of a SW RAID (MD_MAJOR) */
-               if (col_count == 5 && major != LVM_BLK_MAJOR && major != NBD_MAJOR
-                               && major != RAMDISK_MAJOR && major != LOOP_MAJOR && minor==0) {
-                       total_reads += reads;
-                       total_writes += writes;
-               } else {
-                       col_count = sscanf(buf, "%u %u %s %*u %u %*u %u",
-                               &major, &minor, devbuf, &reads, &writes);
-                       if (col_count != 5) {
-                               continue;
-                       }
-               }
-               cur = stats.next;
-               while (cur && strcmp(devbuf, cur->dev))
-                       cur = cur->next;
-
-               if (cur)
-                       update_diskio_values(cur, reads, writes);
-       }
-       update_diskio_values(&stats, total_reads, total_writes);
-       fclose(fp);
-}
-