Extend the node statistics to include disk and network traffic data.
This commit was SVN r27834.
Этот коммит содержится в:
родитель
54266837e9
Коммит
f29f1b731c
@ -10,7 +10,7 @@
|
||||
* University of Stuttgart. All rights reserved.
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2012 Los Alamos National Security, Inc. All rights reserved.
|
||||
* Copyright (c) 2012-2013 Los Alamos National Security, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -146,6 +146,34 @@ OBJ_CLASS_INSTANCE(opal_pstats_t, opal_list_item_t,
|
||||
opal_pstat_construct,
|
||||
NULL);
|
||||
|
||||
static void diskstat_cons(opal_diskstats_t *ptr)
|
||||
{
|
||||
ptr->disk = NULL;
|
||||
}
|
||||
static void diskstat_dest(opal_diskstats_t *ptr)
|
||||
{
|
||||
if (NULL != ptr->disk) {
|
||||
free(ptr->disk);
|
||||
}
|
||||
}
|
||||
OBJ_CLASS_INSTANCE(opal_diskstats_t,
|
||||
opal_list_item_t,
|
||||
diskstat_cons, diskstat_dest);
|
||||
|
||||
static void netstat_cons(opal_netstats_t *ptr)
|
||||
{
|
||||
ptr->interface = NULL;
|
||||
}
|
||||
static void netstat_dest(opal_netstats_t *ptr)
|
||||
{
|
||||
if (NULL != ptr->interface) {
|
||||
free(ptr->interface);
|
||||
}
|
||||
}
|
||||
OBJ_CLASS_INSTANCE(opal_netstats_t,
|
||||
opal_list_item_t,
|
||||
netstat_cons, netstat_dest);
|
||||
|
||||
static void opal_node_stats_construct(opal_node_stats_t *obj)
|
||||
{
|
||||
obj->la = 0.0;
|
||||
@ -161,10 +189,24 @@ static void opal_node_stats_construct(opal_node_stats_t *obj)
|
||||
obj->mapped = 0.0;
|
||||
obj->sample_time.tv_sec = 0;
|
||||
obj->sample_time.tv_usec = 0;
|
||||
OBJ_CONSTRUCT(&obj->diskstats, opal_list_t);
|
||||
OBJ_CONSTRUCT(&obj->netstats, opal_list_t);
|
||||
}
|
||||
static void opal_node_stats_destruct(opal_node_stats_t *obj)
|
||||
{
|
||||
opal_list_item_t *item;
|
||||
while (NULL != (item = opal_list_remove_first(&obj->diskstats))) {
|
||||
OBJ_RELEASE(item);
|
||||
}
|
||||
OBJ_DESTRUCT(&obj->diskstats);
|
||||
while (NULL != (item = opal_list_remove_first(&obj->netstats))) {
|
||||
OBJ_RELEASE(item);
|
||||
}
|
||||
OBJ_DESTRUCT(&obj->netstats);
|
||||
}
|
||||
OBJ_CLASS_INSTANCE(opal_node_stats_t, opal_object_t,
|
||||
opal_node_stats_construct,
|
||||
NULL);
|
||||
opal_node_stats_destruct);
|
||||
|
||||
|
||||
int opal_dss_open(void)
|
||||
|
@ -11,7 +11,7 @@
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012 Los Alamos National Security, Inc. All rights reserved.
|
||||
* Copyright (c) 2012-2013 Los Alamos National Security, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -34,6 +34,7 @@
|
||||
#endif
|
||||
|
||||
#include "opal/class/opal_object.h"
|
||||
#include "opal/class/opal_pointer_array.h"
|
||||
#include "opal/class/opal_list.h"
|
||||
|
||||
BEGIN_C_DECLS
|
||||
@ -139,6 +140,31 @@ typedef struct {
|
||||
struct timeval sample_time;
|
||||
} opal_pstats_t;
|
||||
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_pstats_t);
|
||||
typedef struct {
|
||||
opal_list_item_t super;
|
||||
char *disk;
|
||||
unsigned long num_reads_completed;
|
||||
unsigned long num_reads_merged;
|
||||
unsigned long num_sectors_read;
|
||||
unsigned long milliseconds_reading;
|
||||
unsigned long num_writes_completed;
|
||||
unsigned long num_writes_merged;
|
||||
unsigned long num_sectors_written;
|
||||
unsigned long milliseconds_writing;
|
||||
unsigned long num_ios_in_progress;
|
||||
unsigned long milliseconds_io;
|
||||
unsigned long weighted_milliseconds_io;
|
||||
} opal_diskstats_t;
|
||||
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_diskstats_t);
|
||||
typedef struct {
|
||||
opal_list_item_t super;
|
||||
char *interface;
|
||||
unsigned long num_bytes_read;
|
||||
unsigned long num_packets_read;
|
||||
unsigned long num_bytes_sent;
|
||||
unsigned long num_packets_sent;
|
||||
} opal_netstats_t;
|
||||
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_netstats_t);
|
||||
typedef struct {
|
||||
opal_object_t super;
|
||||
/* node-level load averages */
|
||||
@ -156,6 +182,11 @@ typedef struct {
|
||||
float mapped; /* in MBytes */
|
||||
/* time at which sample was taken */
|
||||
struct timeval sample_time;
|
||||
/* list of disk stats, one per disk */
|
||||
opal_list_t diskstats;
|
||||
/* list of net stats, one per interface */
|
||||
opal_list_t netstats;
|
||||
|
||||
} opal_node_stats_t;
|
||||
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_node_stats_t);
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
* Copyright (c) 2004-2005 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
@ -41,6 +42,7 @@
|
||||
|
||||
#include "opal/mca/base/mca_base_param.h"
|
||||
#include "opal/dss/dss_types.h"
|
||||
#include "opal/util/argv.h"
|
||||
#include "opal/util/printf.h"
|
||||
|
||||
#include "pstat_linux.h"
|
||||
@ -64,12 +66,15 @@ const opal_pstat_base_module_t opal_pstat_linux_module = {
|
||||
linux_module_fini
|
||||
};
|
||||
|
||||
#define OPAL_STAT_MAX_LENGTH 1024
|
||||
|
||||
/* Local functions */
|
||||
static char *local_getline(FILE *fp);
|
||||
static char *local_stripper(char *data);
|
||||
static void local_getfields(char *data, char ***fields);
|
||||
|
||||
/* Local data */
|
||||
static char input[256];
|
||||
static char input[OPAL_STAT_MAX_LENGTH];
|
||||
|
||||
static int linux_module_init(void)
|
||||
{
|
||||
@ -129,6 +134,9 @@ static int query(pid_t pid,
|
||||
double dtime;
|
||||
FILE *fp;
|
||||
char *dptr, *value;
|
||||
char **fields;
|
||||
opal_diskstats_t *ds;
|
||||
opal_netstats_t *ns;
|
||||
|
||||
if (NULL != stats) {
|
||||
/* record the time of this sample */
|
||||
@ -310,7 +318,7 @@ static int query(pid_t pid,
|
||||
/* not an error if we don't find this one as it
|
||||
* isn't critical
|
||||
*/
|
||||
return OPAL_SUCCESS;
|
||||
goto diskstats;
|
||||
}
|
||||
|
||||
/* absorb all of the file's contents in one gulp - we'll process
|
||||
@ -331,7 +339,7 @@ static int query(pid_t pid,
|
||||
/* see if we can open the meminfo file */
|
||||
if (NULL == (fp = fopen("/proc/meminfo", "r"))) {
|
||||
/* ignore this */
|
||||
return OPAL_SUCCESS;
|
||||
goto diskstats;
|
||||
}
|
||||
|
||||
/* read the file one line at a time */
|
||||
@ -359,19 +367,99 @@ static int query(pid_t pid,
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
diskstats:
|
||||
/* look for the diskstats file */
|
||||
if (NULL == (fp = fopen("/proc/diskstats", "r"))) {
|
||||
/* not an error if we don't find this one as it
|
||||
* isn't critical
|
||||
*/
|
||||
goto netstats;
|
||||
}
|
||||
/* read the file one line at a time */
|
||||
while (NULL != (dptr = local_getline(fp))) {
|
||||
/* look for the local disks */
|
||||
if (NULL == strstr(dptr, "sd")) {
|
||||
continue;
|
||||
}
|
||||
/* parse to extract the fields */
|
||||
fields = NULL;
|
||||
local_getfields(dptr, &fields);
|
||||
if (NULL == fields || 14 < opal_argv_count(fields)) {
|
||||
continue;
|
||||
}
|
||||
/* pack the ones of interest into the struct */
|
||||
ds = OBJ_NEW(opal_diskstats_t);
|
||||
ds->disk = strdup(fields[2]);
|
||||
ds->num_reads_completed = strtoul(fields[3], NULL, 10);
|
||||
ds->num_reads_merged = strtoul(fields[4], NULL, 10);
|
||||
ds->num_sectors_read = strtoul(fields[5], NULL, 10);
|
||||
ds->milliseconds_reading = strtoul(fields[6], NULL, 10);
|
||||
ds->num_writes_completed = strtoul(fields[7], NULL, 10);
|
||||
ds->num_writes_merged = strtoul(fields[8], NULL, 10);
|
||||
ds->num_sectors_written = strtoul(fields[9], NULL, 10);
|
||||
ds->milliseconds_writing = strtoul(fields[10], NULL, 10);
|
||||
ds->num_ios_in_progress = strtoul(fields[11], NULL, 10);
|
||||
ds->milliseconds_io = strtoul(fields[12], NULL, 10);
|
||||
ds->weighted_milliseconds_io = strtoul(fields[13], NULL, 10);
|
||||
opal_list_append(&nstats->diskstats, &ds->super);
|
||||
opal_argv_free(fields);
|
||||
}
|
||||
|
||||
netstats:
|
||||
/* look for the netstats file */
|
||||
if (NULL == (fp = fopen("/proc/net/dev", "r"))) {
|
||||
/* not an error if we don't find this one as it
|
||||
* isn't critical
|
||||
*/
|
||||
goto complete;
|
||||
}
|
||||
/* skip the first two lines as they are headers */
|
||||
local_getline(fp);
|
||||
local_getline(fp);
|
||||
/* read the file one line at a time */
|
||||
while (NULL != (dptr = local_getline(fp))) {
|
||||
/* the interface is at the start of the line */
|
||||
if (NULL == (ptr = strchr(dptr, ':'))) {
|
||||
continue;
|
||||
}
|
||||
*ptr = '\0';
|
||||
ptr++;
|
||||
/* parse to extract the fields */
|
||||
fields = NULL;
|
||||
local_getfields(ptr, &fields);
|
||||
if (NULL == fields) {
|
||||
continue;
|
||||
}
|
||||
/* pack the ones of interest into the struct */
|
||||
ns = OBJ_NEW(opal_netstats_t);
|
||||
ns->interface = strdup(dptr);
|
||||
ns->num_bytes_read = strtoul(fields[0], NULL, 10);
|
||||
ns->num_packets_read = strtoul(fields[1], NULL, 10);
|
||||
ns->num_bytes_sent = strtoul(fields[8], NULL, 10);
|
||||
ns->num_packets_sent = strtoul(fields[9], NULL, 10);
|
||||
opal_list_append(&nstats->netstats, &ns->super);
|
||||
opal_argv_free(fields);
|
||||
}
|
||||
}
|
||||
|
||||
complete:
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
static char *local_getline(FILE *fp)
|
||||
{
|
||||
char *ret;
|
||||
char *ret, *ptr;
|
||||
|
||||
ret = fgets(input, 256, fp);
|
||||
ret = fgets(input, OPAL_STAT_MAX_LENGTH, fp);
|
||||
if (NULL != ret) {
|
||||
input[strlen(input)-1] = '\0'; /* remove newline */
|
||||
return input;
|
||||
/* strip leading white space */
|
||||
ptr = input;
|
||||
while (!isalnum(*ptr)) {
|
||||
ptr++;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -402,3 +490,53 @@ static char *local_stripper(char *data)
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void local_getfields(char *dptr, char ***fields)
|
||||
{
|
||||
char *ptr, *end;
|
||||
|
||||
/* set default */
|
||||
*fields = NULL;
|
||||
|
||||
/* find the beginning */
|
||||
ptr = dptr;
|
||||
while ('\0' != *ptr && !isalnum(*ptr)) {
|
||||
ptr++;
|
||||
}
|
||||
if ('\0' == *ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* working from this point, find the end of each
|
||||
* alpha-numeric field and store it on the stack.
|
||||
* Then shift across the white space to the start
|
||||
* of the next one
|
||||
*/
|
||||
end = ptr; /* ptr points to an alnum */
|
||||
end++; /* look at next character */
|
||||
while ('\0' != *end) {
|
||||
/* find the end of this alpha string */
|
||||
while ('\0' != *end && isalnum(*end)) {
|
||||
end++;
|
||||
}
|
||||
/* terminate it */
|
||||
*end = '\0';
|
||||
/* store it on the stack */
|
||||
opal_argv_append_nosize(fields, ptr);
|
||||
/* step across any white space */
|
||||
end++;
|
||||
while ('\0' != *end && !isalnum(*end)) {
|
||||
end++;
|
||||
}
|
||||
if ('\0' == *end) {
|
||||
ptr = NULL;
|
||||
break;
|
||||
}
|
||||
ptr = end;
|
||||
end++;
|
||||
}
|
||||
if (NULL != ptr) {
|
||||
/* have a hanging field */
|
||||
opal_argv_append_nosize(fields, ptr);
|
||||
}
|
||||
}
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user