diff options
-rw-r--r-- | hash.c | 139 | ||||
-rw-r--r-- | hash.h | 40 | ||||
-rw-r--r-- | lcd4linux.conf.sample | 12 | ||||
-rw-r--r-- | plugin_proc_stat.c | 80 | ||||
-rw-r--r-- | timer.c | 10 |
5 files changed, 220 insertions, 61 deletions
@@ -1,4 +1,4 @@ -/* $Id: hash.c,v 1.4 2004/01/18 06:54:08 reinelt Exp $ +/* $Id: hash.c,v 1.5 2004/01/18 09:01:45 reinelt Exp $ * * hashes (associative arrays) * @@ -23,6 +23,9 @@ * * * $Log: hash.c,v $ + * Revision 1.5 2004/01/18 09:01:45 reinelt + * /proc/stat parsing finished + * * Revision 1.4 2004/01/18 06:54:08 reinelt * bug in expr.c fixed (thanks to Xavier) * some progress with /proc/stat parsing @@ -60,6 +63,9 @@ #include "hash.h" +#define FILTER_SLOTS 64 + + // bsearch compare function for hash entries static int hash_lookup_f (const void *a, const void *b) { @@ -80,21 +86,21 @@ static int hash_sort_f (const void *a, const void *b) } - -// insert a key/val pair into the hash table +// search an entry in the hash table: // If the table is flagged "sorted", the entry is looked // up using the bsearch function. If the table is -// unsorted, it will be searched in a linear way if the entry -// does already exist. -// If the entry does already exist, it will be overwritten, -// and the table stays sorted (if it has been before). -// Otherwise, the entry is appended at the end, and -// the table will be flagged 'unsorted' afterwards +// unsorted, it will be searched in a linear way -void hash_set (HASH *Hash, char *key, char *val) +static HASH_ITEM* hash_lookup (HASH *Hash, char *key, int sortit) { HASH_ITEM *Item=NULL; + // maybe sort the array + if (sortit && !Hash->sorted) { + qsort(Hash->Items, Hash->nItems, sizeof(HASH_ITEM), hash_sort_f); + Hash->sorted=1; + } + // lookup using bsearch if (Hash->sorted) { Item=bsearch(key, Hash->Items, Hash->nItems, sizeof(HASH_ITEM), hash_lookup_f); @@ -110,37 +116,127 @@ void hash_set (HASH *Hash, char *key, char *val) } } } + + return Item; + +} + + +// insert a key/val pair into the hash table +// If the entry does already exist, it will be overwritten, +// and the table stays sorted (if it has been before). +// Otherwise, the entry is appended at the end, and +// the table will be flagged 'unsorted' afterwards + +static HASH_ITEM* hash_set_string (HASH *Hash, char *key, char *val) +{ + HASH_ITEM *Item; + + Item=hash_lookup (Hash, key, 0); // entry already exists? if (Item!=NULL) { if (Item->val) free (Item->val); - Item->val=strdup(val); - return; + Item->val = strdup(val); + return Item; } // add entry Hash->sorted=0; Hash->nItems++; Hash->Items=realloc(Hash->Items,Hash->nItems*sizeof(HASH_ITEM)); - Hash->Items[Hash->nItems-1].key=strdup(key); - Hash->Items[Hash->nItems-1].val=strdup(val); + + Item=&(Hash->Items[Hash->nItems-1]); + + Item->key = strdup(key); + Item->val = strdup(val); + Item->Slot = NULL; + + return Item; } -char *hash_get (HASH *Hash, char *key) +// insert a string into the hash table +void hash_set (HASH *Hash, char *key, char *val) +{ + hash_set_string (Hash, key, val); +} + + +// insert a string into the hash table +// convert it into a number, and store it in the +// filter table, too +void hash_set_filter (HASH *Hash, char *key, char *val) { + double number=atof(val); HASH_ITEM *Item; - if (!Hash->sorted) { - qsort(Hash->Items, Hash->nItems, sizeof(HASH_ITEM), hash_sort_f); - Hash->sorted=1; + Item=hash_set_string (Hash, key, val); + + // allocate filter table + if (Item->Slot==NULL) { + Item->Slot = malloc(FILTER_SLOTS*sizeof(HASH_SLOT)); + memset(Item->Slot, 0, FILTER_SLOTS*sizeof(HASH_SLOT)); } - Item=bsearch(key, Hash->Items, Hash->nItems, sizeof(HASH_ITEM), hash_lookup_f); + // shift filter table + memmove (Item->Slot+1, Item->Slot, (FILTER_SLOTS-1)*sizeof(HASH_SLOT)); + + // set first entry + gettimeofday(&(Item->Slot[0].time), NULL); + Item->Slot[0].val=number; +} + +// get a string from the hash table +char *hash_get (HASH *Hash, char *key) +{ + HASH_ITEM *Item=hash_lookup(Hash, key, 1); return Item?Item->val:NULL; } +// get a delta value from the filter table +double hash_get_filter (HASH *Hash, char *key, int delay) +{ + HASH_ITEM *Item; + struct timeval now, end; + int i; + double dv, dt; + + // lookup item + Item=hash_lookup(Hash, key, 1); + if (Item==NULL) return 0.0; + if (Item->Slot==NULL) return 0.0; + + // prepare timing values + now=Item->Slot[0].time; + end.tv_sec = now.tv_sec; + end.tv_usec = now.tv_usec-1000*delay; + if (end.tv_usec<0) { + end.tv_sec--; + end.tv_usec += 1000000; + } + + // search filter slot + for (i=1; i<FILTER_SLOTS; i++) { + if (Item->Slot[i].time.tv_sec==0) break; + if (timercmp(&Item->Slot[i].time, &end, <)) break; + } + + // empty slot => use the one before + if (Item->Slot[i].time.tv_sec==0) i--; + + // not enough slots available... + if (i==0) return 0.0; + + // delta value, delta time + dv = Item->Slot[0].val - Item->Slot[i].val; + dt = (now.tv_sec - Item->Slot[i].time.tv_sec) + (now.tv_usec - Item->Slot[i].time.tv_usec)/1000000.0; + + if (dt > 0.0 && dv >= 0.0) return dv/dt; + return 0.0; +} + void hash_destroy (HASH *Hash) { @@ -150,8 +246,9 @@ void hash_destroy (HASH *Hash) // free all entries for (i=0;i<Hash->nItems; i++) { - if (Hash->Items[i].key) free (Hash->Items[i].key); - if (Hash->Items[i].val) free (Hash->Items[i].val); + if (Hash->Items[i].key) free (Hash->Items[i].key); + if (Hash->Items[i].val) free (Hash->Items[i].val); + if (Hash->Items[i].Slot) free (Hash->Items[i].Slot); } // free hash table @@ -1,4 +1,4 @@ -/* $Id: hash.h,v 1.4 2004/01/16 11:12:26 reinelt Exp $ +/* $Id: hash.h,v 1.5 2004/01/18 09:01:45 reinelt Exp $ * * hashes (associative arrays) * @@ -23,6 +23,9 @@ * * * $Log: hash.h,v $ + * Revision 1.5 2004/01/18 09:01:45 reinelt + * /proc/stat parsing finished + * * Revision 1.4 2004/01/16 11:12:26 reinelt * some bugs in plugin_xmms fixed, parsing moved to own function * plugin_proc_stat nearly finished @@ -46,9 +49,21 @@ #ifndef _HASH_H_ #define _HASH_H_ + +// struct timeval +#include <sys/time.h> + + typedef struct { - char *key; - char *val; + struct timeval time; + double val; +} HASH_SLOT; + + +typedef struct { + char *key; + char *val; + HASH_SLOT *Slot; } HASH_ITEM; @@ -59,19 +74,10 @@ typedef struct { } HASH; -typedef struct { - // struct timeval time; - double val; -} FILTER_SLOT; - -typedef struct { - char *key; - int nSlots; - FILTER_SLOT *Slots; -} FILTER_ITEM; - -void hash_set (HASH *Hash, char *key, char *val); -char *hash_get (HASH *Hash, char *key); -void hash_destroy (HASH *Hash); +void hash_set (HASH *Hash, char *key, char *val); +void hash_set_filter (HASH *Hash, char *key, char *val); +char *hash_get (HASH *Hash, char *key); +double hash_get_filter (HASH *Hash, char *key, int delay); +void hash_destroy (HASH *Hash); #endif diff --git a/lcd4linux.conf.sample b/lcd4linux.conf.sample index 7d48af3..4082210 100644 --- a/lcd4linux.conf.sample +++ b/lcd4linux.conf.sample @@ -35,6 +35,17 @@ Widget RAM { update tick } +Widget Busy { + class 'Text' + expression cpu('busy', 500) + prefix 'Busy ' + postfix '%' + width 10 + precision 1 + align 'R' + update tick +} + Widget Load { class 'Text' expression loadavg(1) @@ -56,6 +67,7 @@ Layout Default { Col10 'RAM' } Row3 { + Col1 'Busy' } Row4 { Col1 'Load' diff --git a/plugin_proc_stat.c b/plugin_proc_stat.c index 5c9f65e..3857995 100644 --- a/plugin_proc_stat.c +++ b/plugin_proc_stat.c @@ -1,4 +1,4 @@ -/* $Id: plugin_proc_stat.c,v 1.4 2004/01/18 06:54:08 reinelt Exp $ +/* $Id: plugin_proc_stat.c,v 1.5 2004/01/18 09:01:45 reinelt Exp $ * * plugin for /proc/stat parsing * @@ -23,6 +23,9 @@ * * * $Log: plugin_proc_stat.c,v $ + * Revision 1.5 2004/01/18 09:01:45 reinelt + * /proc/stat parsing finished + * * Revision 1.4 2004/01/18 06:54:08 reinelt * bug in expr.c fixed (thanks to Xavier) * some progress with /proc/stat parsing @@ -67,6 +70,7 @@ static HASH Stat = { 0, 0, NULL }; + static int renew(int msec) { static struct timeval end = {0, 0}; @@ -89,13 +93,10 @@ static int renew(int msec) static void hash_set1 (char *key1, char *val) { - double number; - - number=atof(val); - - hash_set (&Stat, key1, val); + hash_set_filter (&Stat, key1, val); } + static void hash_set2 (char *key1, char *key2, char *val) { char key[32]; @@ -104,6 +105,7 @@ static void hash_set2 (char *key1, char *key2, char *val) hash_set1 (key, val); } + static void hash_set3 (char *key1, char *key2, char *key3, char *val) { char key[32]; @@ -120,8 +122,7 @@ static int parse_proc_stat (void) // update every 10 msec if (!renew(10)) return 0; - // stream=fopen("/proc/stat", "r"); - stream=fopen("proc_stat", "r"); + stream=fopen("/proc/stat", "r"); if (stream==NULL) { error ("fopen(/proc/stat) failed: %s", strerror(errno)); return -1; @@ -191,26 +192,71 @@ static int parse_proc_stat (void) return 0; } -static void my_proc_stat (RESULT *result, RESULT *arg1) + +static void my_proc_stat (RESULT *result, int argc, RESULT *argv[]) { - char *key, *val; - + char *string; + double number; + if (parse_proc_stat()<0) { SetResult(&result, R_STRING, ""); return; } - key=R2S(arg1); - val=hash_get(&Stat, key); - if (val==NULL) val=""; + switch (argc) { + case 1: + string=hash_get(&Stat, R2S(argv[0])); + if (string==NULL) string=""; + SetResult(&result, R_STRING, string); + break; + case 2: + number=hash_get_filter(&Stat, R2S(argv[0]), R2N(argv[1])); + SetResult(&result, R_NUMBER, &number); + break; + default: + error ("proc_stat(): wrong number of parameters"); + SetResult(&result, R_STRING, ""); + } +} + + +static void my_cpu (RESULT *result, RESULT *arg1, RESULT *arg2) +{ + char *key; + int delay; + double value; + double cpu_user, cpu_nice, cpu_system, cpu_idle, cpu_total; + + if (parse_proc_stat()<0) { + SetResult(&result, R_STRING, ""); + return; + } + + key = R2S(arg1); + delay = R2N(arg2); + + cpu_user = hash_get_filter(&Stat, "cpu.user", delay); + cpu_nice = hash_get_filter(&Stat, "cpu.nice", delay); + cpu_system = hash_get_filter(&Stat, "cpu.system", delay); + cpu_idle = hash_get_filter(&Stat, "cpu.idle", delay); - SetResult(&result, R_STRING, val); + cpu_total = cpu_user+cpu_nice+cpu_system+cpu_idle; + + if (strcasecmp(key, "user" )==0) value=cpu_user; + else if (strcasecmp(key, "nice" )==0) value=cpu_nice; + else if (strcasecmp(key, "system")==0) value=cpu_system; + else if (strcasecmp(key, "idle" )==0) value=cpu_idle; + else if (strcasecmp(key, "busy" )==0) value=cpu_total-cpu_idle; + + value = 100*value/cpu_total; + + SetResult(&result, R_NUMBER, &value); } int plugin_init_proc_stat (void) { - AddFunction ("stat", 1, my_proc_stat); + AddFunction ("proc_stat", -1, my_proc_stat); + AddFunction ("cpu", 2, my_cpu); return 0; } - @@ -1,4 +1,4 @@ -/* $Id: timer.c,v 1.1 2004/01/13 08:18:20 reinelt Exp $ +/* $Id: timer.c,v 1.2 2004/01/18 09:01:45 reinelt Exp $ * * generic timer handling * @@ -21,6 +21,9 @@ * * * $Log: timer.c,v $ + * Revision 1.2 2004/01/18 09:01:45 reinelt + * /proc/stat parsing finished + * * Revision 1.1 2004/01/13 08:18:20 reinelt * timer queues added * liblcd4linux deactivated turing transformation to new layout @@ -142,11 +145,6 @@ int timer_process (struct timespec *delay) } } - if (flag) { - // Fixme: if at least one timer has been processed, do a flush() - - } - // find next timer flag=1; min=-1; |