implement disk metrics

This commit is contained in:
Doug MacEachern 2004-12-06 03:51:15 +00:00
parent 35dfc19937
commit 5630d9a48a
2 changed files with 133 additions and 1 deletions

View File

@ -1,7 +1,7 @@
#include "sigar.h"
#include "sigar_private.h"
#include "sigar_os.h"
#include "sigar_util.h"
#include "sigar_os.h"
#include <dlfcn.h>
#include <nlist.h>
@ -144,6 +144,8 @@ int sigar_os_open(sigar_t **sigar)
(*sigar)->aix_version = atoi(name.version);
(*sigar)->diskmap = NULL;
return SIGAR_OK;
}
@ -164,6 +166,9 @@ int sigar_os_close(sigar_t *sigar)
if (sigar->perfstat.handle) {
dlclose(sigar->perfstat.handle);
}
if (sigar->diskmap) {
sigar_cache_destroy(sigar->diskmap);
}
free(sigar);
return SIGAR_OK;
}
@ -1366,10 +1371,119 @@ int sigar_file_system_list_get(sigar_t *sigar,
#define SIGAR_FS_BLOCKS_TO_BYTES(buf, f) \
((buf.f * (buf.f_bsize / 512)) >> 1)
#define LSPV_CMD "/usr/sbin/lspv"
#define FSDEV_ID(sb) (sb.st_ino + sb.st_dev)
/*
* dont have per-partition metrics on aix.
* need to build a mount point => diskname map.
* see 'lspv -l hdisk0' for example.
*/
static int create_diskmap(sigar_t *sigar)
{
FILE *fp = popen(LSPV_CMD, "r");
char buffer[BUFSIZ], *ptr;
sigar->diskmap = sigar_cache_new(25);
if (!fp) {
return ENOENT;
}
while ((ptr = fgets(buffer, sizeof(buffer), fp))) {
FILE *lfp;
char cmd[256], disk[56];
char *s = strchr(ptr, ' ');
if (s) {
*s = '\0';
}
strcpy(disk, ptr);
sprintf(cmd, LSPV_CMD " -l %s", disk);
if (!(lfp = popen(cmd, "r"))) {
continue;
}
(void)fgets(buffer, sizeof(buffer), lfp); /* skip disk: */
(void)fgets(buffer, sizeof(buffer), lfp); /* skip headers */
while ((ptr = fgets(buffer, sizeof(buffer), lfp))) {
sigar_cache_entry_t *ent;
struct stat sb;
int retval;
/* LV NAME LPs PPs DISTRIBUTION */
ptr = sigar_skip_multiple_token(ptr, 4);
SIGAR_SKIP_SPACE(ptr);
if ((s = strchr(ptr, '\n'))) {
*s = '\0';
}
if (strEQ(ptr, "N/A")) {
continue;
}
retval = stat(ptr, &sb);
ent = sigar_cache_get(sigar->diskmap, FSDEV_ID(sb));
if (retval == 0) {
ent->value = strdup(disk);
}
}
pclose(lfp);
}
pclose(fp);
}
static int get_disk_metrics(sigar_t *sigar,
sigar_file_system_usage_t *fsusage,
char *diskname)
{
/* XXX some caching can optimize */
int fd, i;
int cnt;
struct iostat iostat;
struct dkstat dkstat, *dp;
struct nlist nl[] = {
{ "iostat" },
};
if ((fd = open("/dev/mem", O_RDONLY)) <= 0) {
return errno;
}
i = knlist(nl, 1, sizeof(struct nlist));
if (i == -1) {
close(fd);
return errno;
}
if (nl[i].n_value == 0) {
return ENOENT;
}
lseek(fd, nl[0].n_value, SEEK_SET);
read(fd, &iostat, sizeof(iostat));
for (dp = iostat.dkstatp, cnt = iostat.dk_cnt;
cnt && dp;
--cnt, dp = dkstat.dknextp)
{
lseek(fd, (long)dp, SEEK_SET);
read(fd, &dkstat, sizeof(dkstat));
if (strEQ(diskname, dkstat.diskname)) {
fsusage->disk_reads = dkstat.dk_rblks;
fsusage->disk_writes = dkstat.dk_wblks;
break;
}
}
close(fd);
return SIGAR_OK;
}
int sigar_file_system_usage_get(sigar_t *sigar,
const char *dirname,
sigar_file_system_usage_t *fsusage)
{
sigar_cache_entry_t *ent;
struct stat sb;
int status;
struct statfs buf;
if (statfs((char *)dirname, &buf) != 0) {
@ -1385,6 +1499,23 @@ int sigar_file_system_usage_get(sigar_t *sigar,
SIGAR_DISK_STATS_NOTIMPL(fsusage);
if (!sigar->diskmap) {
status = create_diskmap(sigar);
if (status != SIGAR_OK) {
return SIGAR_OK;
}
}
status = stat(dirname, &sb);
if (status == 0) {
sigar_cache_entry_t *ent =
sigar_cache_get(sigar->diskmap, FSDEV_ID(sb));
if (!ent->value) {
return SIGAR_OK;
}
get_disk_metrics(sigar, fsusage, (char *)ent->value);
}
return SIGAR_OK;
}

View File

@ -62,6 +62,7 @@ struct sigar_t {
char model[128];
char self_path[SIGAR_PATH_MAX]; /* path to where libsigar.so lives */
int aix_version;
sigar_cache_t *diskmap;
};
#define HAVE_STRERROR_R