Submit #3063 » kcollect_dbm.patch
usr.bin/kcollect/kcollect.c | ||
---|---|---|
#include "kcollect.h"
|
||
#include <ndbm.h>
|
||
#include <fcntl.h>
|
||
#include <errno.h>
|
||
#define SLEEP_INTERVAL 60 /* minimum is KCOLLECT_INTERVAL */
|
||
static void format_output(uintmax_t value,char fmt,uintmax_t scale, char* ret);
|
||
static void dump_text(kcollect_t *ary, size_t count, size_t total_count);
|
||
static void dump_dbm(kcollect_t *ary, size_t count, const char *datafile);
|
||
static void display_dbm(kcollect_t *ary, const char* datafile);
|
||
static void dump_fields(kcollect_t *ary);
|
||
static void adjust_fields(kcollect_t *ent, const char *fields);
|
||
... | ... | |
exit(1);
|
||
}
|
||
while ((ch = getopt(ac, av, "o:b:flsgt:xw:GW:H:")) != -1) {
|
||
while ((ch = getopt(ac, av, "o:b:d:flsgt:xw:GW:H:")) != -1) {
|
||
char *suffix;
|
||
switch(ch) {
|
||
... | ... | |
datafile = optarg;
|
||
cmd = 'b';
|
||
break;
|
||
case 'd':
|
||
datafile = optarg;
|
||
cmd= 'd';
|
||
break;
|
||
case 'f':
|
||
keepalive = 1;
|
||
break;
|
||
... | ... | |
if (count > 2)
|
||
dump_dbm(ary, count, datafile);
|
||
break;
|
||
case 'd':
|
||
if (count > 2)
|
||
display_dbm(ary,datafile);
|
||
break;
|
||
case 'l':
|
||
dump_fields(ary);
|
||
exit(0);
|
||
... | ... | |
pclose(OutFP);
|
||
}
|
||
static
|
||
void
|
||
dump_text(kcollect_t *ary, size_t count, size_t total_count)
|
||
format_output(uintmax_t value,char fmt,uintmax_t scale, char* ret)
|
||
{
|
||
int j;
|
||
int i;
|
||
uintmax_t scale;
|
||
uintmax_t value;
|
||
char fmt;
|
||
char buf[9];
|
||
struct tm *tmv;
|
||
time_t t;
|
||
for (i = count - 1; i >= 2; --i) {
|
||
if ((total_count & 15) == 0) {
|
||
printf("%8.8s", "time");
|
||
for (j = 0; j < KCOLLECT_ENTRIES; ++j) {
|
||
if (ary[1].data[j]) {
|
||
printf(" %8.8s",
|
||
(char *)&ary[1].data[j]);
|
||
}
|
||
}
|
||
printf("\n");
|
||
}
|
||
/*
|
||
* Timestamp
|
||
*/
|
||
t = ary[i].realtime.tv_sec;
|
||
if (UseGMT)
|
||
tmv = gmtime(&t);
|
||
else
|
||
tmv = localtime(&t);
|
||
strftime(buf, sizeof(buf), "%H:%M:%S", tmv);
|
||
printf("%8.8s", buf);
|
||
for (j = 0; j < KCOLLECT_ENTRIES; ++j) {
|
||
if (ary[1].data[j] == 0)
|
||
continue;
|
||
/*
|
||
* NOTE: kernel does not have to provide the scale
|
||
* (that is, the highest likely value), nor
|
||
* does it make sense in all cases.
|
||
*
|
||
* Example scale - kernel provides total amount
|
||
* of memory available for memory related
|
||
* statistics in the scale field.
|
||
*/
|
||
value = ary[i].data[j];
|
||
scale = KCOLLECT_GETSCALE(ary[0].data[j]);
|
||
fmt = KCOLLECT_GETFMT(ary[0].data[j]);
|
||
printf(" ");
|
||
switch(fmt) {
|
||
switch(fmt) {
|
||
case '2':
|
||
/*
|
||
* fractional x100
|
||
*/
|
||
printf("%5ju.%02ju", value / 100, value % 100);
|
||
sprintf(ret,"%5ju.%02ju", value / 100, value % 100);
|
||
break;
|
||
case 'p':
|
||
/*
|
||
* Percentage fractional x100 (100% = 10000)
|
||
*/
|
||
printf("%4ju.%02ju%%",
|
||
sprintf(ret,"%4ju.%02ju%%",
|
||
value / 100, value % 100);
|
||
break;
|
||
case 'm':
|
||
... | ... | |
2,
|
||
HN_FRACTIONAL |
|
||
HN_NOSPACE);
|
||
printf("%8.8s", buf);
|
||
sprintf(ret,"%8.8s", buf);
|
||
break;
|
||
case 'c':
|
||
/*
|
||
... | ... | |
HN_FRACTIONAL |
|
||
HN_NOSPACE |
|
||
HN_DIVISOR_1000);
|
||
printf("%8.8s", buf);
|
||
sprintf(ret,"%8.8s", buf);
|
||
break;
|
||
case 'b':
|
||
/*
|
||
... | ... | |
HN_FRACTIONAL |
|
||
HN_NOSPACE);
|
||
}
|
||
printf("%8.8s", buf);
|
||
sprintf(ret,"%8.8s", buf);
|
||
break;
|
||
default:
|
||
printf(" ");
|
||
sprintf(ret,"%s"," ");
|
||
break;
|
||
}
|
||
}
|
||
static
|
||
void
|
||
dump_text(kcollect_t *ary, size_t count, size_t total_count)
|
||
{
|
||
int j;
|
||
int i;
|
||
uintmax_t scale;
|
||
uintmax_t value;
|
||
char fmt;
|
||
char buf[9];
|
||
char sbuf[20];
|
||
struct tm *tmv;
|
||
time_t t;
|
||
for (i = count - 1; i >= 2; --i) {
|
||
if ((total_count & 15) == 0) {
|
||
printf("%8.8s", "time");
|
||
for (j = 0; j < KCOLLECT_ENTRIES; ++j) {
|
||
if (ary[1].data[j]) {
|
||
printf(" %8.8s",
|
||
(char *)&ary[1].data[j]);
|
||
}
|
||
}
|
||
printf("\n");
|
||
}
|
||
/*
|
||
* Timestamp
|
||
*/
|
||
t = ary[i].realtime.tv_sec;
|
||
if (UseGMT)
|
||
tmv = gmtime(&t);
|
||
else
|
||
tmv = localtime(&t);
|
||
strftime(buf, sizeof(buf), "%H:%M:%S", tmv);
|
||
printf("%8.8s", buf);
|
||
for (j = 0; j < KCOLLECT_ENTRIES; ++j) {
|
||
if (ary[1].data[j] == 0)
|
||
continue;
|
||
/*
|
||
* NOTE: kernel does not have to provide the scale
|
||
* (that is, the highest likely value), nor
|
||
* does it make sense in all cases.
|
||
*
|
||
* Example scale - kernel provides total amount
|
||
* of memory available for memory related
|
||
* statistics in the scale field.
|
||
*/
|
||
value = ary[i].data[j];
|
||
scale = KCOLLECT_GETSCALE(ary[0].data[j]);
|
||
fmt = KCOLLECT_GETFMT(ary[0].data[j]);
|
||
printf(" ");
|
||
format_output(value, fmt, scale, sbuf);
|
||
printf("%s",sbuf);
|
||
}
|
||
printf("\n");
|
||
++total_count;
|
||
}
|
||
}
|
||
static void
|
||
dump_dbm(kcollect_t *ary __unused, size_t count __unused, const char *datafile __unused)
|
||
static
|
||
void
|
||
dump_dbm(kcollect_t *ary, size_t count, const char *datafile)
|
||
{
|
||
DBM * db = dbm_open(datafile,(O_RDWR | O_CREAT),(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
|
||
if (db == NULL) {
|
||
switch (errno){
|
||
case EACCES:
|
||
printf("database file is read-only, check permissions.\n");
|
||
break;
|
||
default:
|
||
printf("opening our database produced an error (%i)\n",errno);
|
||
}
|
||
return;
|
||
}
|
||
else {
|
||
uint i;
|
||
char buf[20];
|
||
struct tm *tmv;
|
||
time_t t;
|
||
datum key;
|
||
datum value;
|
||
for (i = 2;i < (count - 1);i++) {
|
||
t = ary[i].realtime.tv_sec;
|
||
tmv = gmtime(&t);
|
||
strftime(buf, sizeof(buf), "%F %H:%M:%S", tmv);
|
||
key.dptr = buf;
|
||
key.dsize = sizeof(buf);
|
||
value.dptr = ary[i].data;
|
||
value.dsize = sizeof(ary[i].data);
|
||
if (dbm_store(db,key,value,DBM_INSERT) == -1) {
|
||
printf("error storing the value in the database file (%i)\n", errno);
|
||
break;
|
||
}
|
||
}
|
||
dbm_close(db);
|
||
}
|
||
}
|
||
static
|
||
void
|
||
display_dbm(kcollect_t *ary,const char* datafile)
|
||
{
|
||
DBM * db = dbm_open(datafile,(O_RDONLY),(S_IRUSR|S_IRGRP));
|
||
datum key;
|
||
datum value;
|
||
uint64_t data[KCOLLECT_ENTRIES];
|
||
int printHeader = 1;
|
||
if (db == NULL) {
|
||
printf("opening our database produced an error (%i)\n",errno);
|
||
return;
|
||
}
|
||
else {
|
||
for (key = dbm_firstkey(db); key.dptr !=NULL; key = dbm_nextkey(db)){
|
||
value = dbm_fetch(db, key);
|
||
if (value.dptr == NULL) {
|
||
printf("failed to retrieve data belonging to key \"%s\", exiting. (%i)\n",(char *)key.dptr,errno);
|
||
break; /* falling down to dbm_close */
|
||
}
|
||
memcpy(data,value.dptr,KCOLLECT_ENTRIES * sizeof(uint64_t));
|
||
if (printHeader) {
|
||
int c;
|
||
printf("%*s",20,"timestamp ");
|
||
for (c = 0; c < KCOLLECT_ENTRIES;c++) {
|
||
/* only display those enabled (fields) */
|
||
if(ary[1].data[c]) printf("%8.8s ", (char *)&ary[1].data[c]);
|
||
}
|
||
printf("\n");
|
||
printHeader = 0;
|
||
}
|
||
printf("%s ",(char*)key.dptr);
|
||
int c;
|
||
uintmax_t scale,fmt;
|
||
char sbuf [20];
|
||
for (c = 0;c < KCOLLECT_ENTRIES; c++) {
|
||
/* only display those enabled (fields) */
|
||
if(!ary[1].data[c]) continue;
|
||
scale = KCOLLECT_GETSCALE(ary[0].data[c]);
|
||
fmt = KCOLLECT_GETFMT(ary[0].data[c]);
|
||
format_output(data[c], fmt, scale, sbuf);
|
||
printf("%8s ",sbuf);
|
||
}
|
||
printf("\n");
|
||
}
|
||
}
|
||
dbm_close(db);
|
||
}
|
||
static void
|