From e5582816c607095d3fca284ab5b2cfe96eb3bb89 Mon Sep 17 00:00:00 2001 From: Doug MacEachern Date: Sun, 5 Dec 2004 01:18:57 +0000 Subject: [PATCH] start disk i/o metrics --- bindings/dotnet/src/Sigar.cs | 2 + bindings/java/src/jni/generate.pl | 10 ++ .../hyperic/sigar/test/TestFileSystem.java | 2 + include/sigar.h | 4 +- src/os/win32/win32_sigar.c | 99 +++++++++++++++++++ 5 files changed, 116 insertions(+), 1 deletion(-) diff --git a/bindings/dotnet/src/Sigar.cs b/bindings/dotnet/src/Sigar.cs index 533d85f6..15283522 100644 --- a/bindings/dotnet/src/Sigar.cs +++ b/bindings/dotnet/src/Sigar.cs @@ -358,6 +358,8 @@ namespace Hyperic.Sigar { public readonly ulong Avail; private readonly ulong NA_Files; //XXX not implemented private readonly ulong NA_FreeFiles; + private readonly ulong DiskReads; + private readonly ulong DiskWrites; public readonly double UsePercent; [DllImport(Sigar.LIBSIGAR)] diff --git a/bindings/java/src/jni/generate.pl b/bindings/java/src/jni/generate.pl index 92522beb..63ef53ca 100644 --- a/bindings/java/src/jni/generate.pl +++ b/bindings/java/src/jni/generate.pl @@ -468,6 +468,16 @@ my %classes = ( desc => 'Number of free file nodes on the filesystem', plat => 'ADFHLS' }, + { + name => 'disk_reads', type => 'Long', + desc => 'Number of physical disk reads', + plat => 'W' + }, + { + name => 'disk_writes', type => 'Long', + desc => 'Number of physical disk writes', + plat => 'W' + }, { name => 'use_percent', type => 'Double', desc => 'Percent of disk used', diff --git a/bindings/java/src/net/hyperic/sigar/test/TestFileSystem.java b/bindings/java/src/net/hyperic/sigar/test/TestFileSystem.java index c0021375..57fb3e20 100644 --- a/bindings/java/src/net/hyperic/sigar/test/TestFileSystem.java +++ b/bindings/java/src/net/hyperic/sigar/test/TestFileSystem.java @@ -43,6 +43,8 @@ public class TestFileSystem extends SigarTestCase { double usePercent = usage.getUsePercent() * 100; traceln("Used=" + usePercent + "%"); assertTrue(usePercent <= 100.0); + traceln("DiskReads=" + usage.getDiskReads()); + traceln("DiskWrites=" + usage.getDiskWrites()); break; } } diff --git a/include/sigar.h b/include/sigar.h index a0ee2165..fccd929f 100644 --- a/include/sigar.h +++ b/include/sigar.h @@ -340,7 +340,9 @@ typedef struct { free, avail, files, - free_files; + free_files, + disk_reads, + disk_writes; double use_percent; } sigar_file_system_usage_t; diff --git a/src/os/win32/win32_sigar.c b/src/os/win32/win32_sigar.c index 848b4210..4eb7703e 100644 --- a/src/os/win32/win32_sigar.c +++ b/src/os/win32/win32_sigar.c @@ -13,6 +13,7 @@ #define PERF_TITLE_PROC 230 #define PERF_TITLE_PROC_KEY "230" #define PERF_TITLE_CPU_KEY "238" +#define PERF_TITLE_DISK_KEY "236" #define PERF_TITLE_CPU_USER 142 #define PERF_TITLE_CPU_IDLE 1746 @@ -50,6 +51,15 @@ typedef enum { PERF_IX_MAX } perf_proc_offsets_t; +typedef enum { + PERF_IX_DISK_READ, + PERF_IX_DISK_WRITE, + PERF_IX_DISK_MAX +} perf_disk_offsets_t; + +#define PERF_TITLE_DISK_READ 208 +#define PERF_TITLE_DISK_WRITE 210 + /* * diff is: * ExW -> ExA @@ -1330,6 +1340,89 @@ SIGAR_DECLARE(int) sigar_file_system_list_get(sigar_t *sigar, return SIGAR_OK; } +static PERF_INSTANCE_DEFINITION *get_disk_instance(sigar_t *sigar, + DWORD *perf_offsets, + DWORD *num, DWORD *err) +{ + PERF_OBJECT_TYPE *object = get_perf_object(sigar, "236", err); + PERF_INSTANCE_DEFINITION *inst; + PERF_COUNTER_DEFINITION *counter; + DWORD i; + + if (!object) { + return NULL; + } + + if (object->NumInstances < 1) { + *err = ENOENT; + return NULL; + } + + for (i=0, counter = PdhFirstCounter(object); + iNumCounters; + i++, counter = PdhNextCounter(counter)) + { + DWORD offset = counter->CounterOffset; + + switch (counter->CounterNameTitleIndex) { + case PERF_TITLE_DISK_READ: + perf_offsets[PERF_IX_DISK_READ] = offset; + break; + case PERF_TITLE_DISK_WRITE: + perf_offsets[PERF_IX_DISK_WRITE] = offset; + break; + } + } + + if (num) { + *num = object->NumInstances; + } + + return PdhFirstInstance(object); +} + +static int get_disk_metrics(sigar_t *sigar, + const char *dirname, + sigar_file_system_usage_t *fsusage) +{ + DWORD i, err; + PERF_OBJECT_TYPE *object = + get_perf_object(sigar, PERF_TITLE_CPU_KEY, &err); + PERF_INSTANCE_DEFINITION *inst; + PERF_COUNTER_DEFINITION *counter; + DWORD perf_offsets[PERF_IX_DISK_MAX]; + + if (!object) { + return err; + } + + memset(&perf_offsets, 0, sizeof(perf_offsets)); + inst = get_disk_instance(sigar, (DWORD*)&perf_offsets, 0, &err); + + if (!inst) { + return err; + } + + for (i=0, inst = PdhFirstInstance(object); + iNumInstances; + i++, inst = PdhNextInstance(inst)) + { + char drive[MAX_PATH]; + PERF_COUNTER_BLOCK *counter_block = PdhGetCounterBlock(inst); + wchar_t *name = (wchar_t *)((BYTE *)inst + inst->NameOffset); + + SIGAR_W2A(name, drive, sizeof(drive)); + + if (strnEQ(drive, dirname, 2)) { + fsusage->disk_reads = PERF_VAL(PERF_IX_DISK_READ); + fsusage->disk_writes = PERF_VAL(PERF_IX_DISK_WRITE); + return SIGAR_OK; + } + } + + return ENOENT; +} + SIGAR_DECLARE(int) sigar_file_system_usage_get(sigar_t *sigar, const char *dirname, @@ -1337,6 +1430,7 @@ sigar_file_system_usage_get(sigar_t *sigar, { BOOL retval; ULARGE_INTEGER avail, total, free; + int status; /* prevent dialog box if A:\ drive is empty */ UINT errmode = SetErrorMode(SEM_FAILCRITICALERRORS); @@ -1361,6 +1455,11 @@ sigar_file_system_usage_get(sigar_t *sigar, fsusage->files = 0; fsusage->free_files = 0; + status = get_disk_metrics(sigar, dirname, fsusage); + if (status != SIGAR_OK) { + fsusage->disk_reads = fsusage->disk_writes = 0; + } + return SIGAR_OK; }