Node interfaces
Node interfaces report metrics related to a set of components or individual components of a remote node in the cluster. The components include processors or memory, and individual components include a processor, network interface, or memory page of the remote node in the cluster.
The remote node must belong to one of the clusters of the current node, which uses the perfstat API.
perfstat_subsystem_node
as the naming convention and a
common signature:
Item | Descriptor |
---|---|
perfstat_cpu_node | Retrieves the usage metrics of an individual processor on a remote node. |
perfstat_disk_node | Retrieves the usage metrics of an individual disk on a remote node. |
perfstat_diskadapter_node | Retrieves the adapter metrics of a disk on a remote node. |
perfstat_diskpath_node | Retrieves the path metrics of a disk on a remote node. |
perfstat_logicalvolume_node | Retrieves the usage metrics of a logical volume on a remote node. |
perfstat_memory_page_node | Retrieves the usage metrics of a memory page size on a remote node. |
perfstat_netbuffer_node | Retrieves the buffer allocation metrics of a network on a remote node. |
perfstat_netinterface_node | Retrieves the interface metrics of a network on a remote size node. |
perfstat_pagingspace_node | Retrieves the space metrics of a page on a remote node. |
perfstat_protocol_node | Retrieves the protocol-related metrics of a network on a remote node. |
perfstat_tape_node | Retrieves the usage metrics of a tape on a remote node. |
perfstat_volumegroup_node | Retrieves the usage metrics of a volume group on a remote node. |
perfstat_cpu_total_node | Retrieves the summary on the usage metrics of a processor on a remote node. |
perfstat_partition_total_node | Retrieves the partition metrics on a remote node. |
perfstat_tape_total_node | Retrieves the summary on the usage metrics of a tape on a remote node. |
perfstat_memory_total_node | Retrieves the summary on the usage metrics of a memory on a remote node. |
perfstat_netinterface_total_node | Retrieves the summary on the usage metrics of a network interface on a remote node. |
perfstat_disk_total_node | Retrieves the summary on the usage metrics of a disk on a remote node. |
perfstat_subsystem_node
interface except the
perfstat_memory_page_node interface:
int perfstat_subsystem_node(perfstat_id_node_t *name,
perfstat_subsystem_t *userbuff,
int sizeof_struct,
int desired_number);
perfstat_memory_page_node
interface:
int perfstat_memory_page_node(perfstat_id_node_t *name,
perfstat_psize_t *psize;
perfstat_subsystem_t *userbuff,
int sizeof_struct,
int desired_number);
perfstat_subsystem_node
interface:
Item | Descriptor |
---|---|
perfstat_id_node_t *name | Specify the name of the node in name->u.nodename format.
The name must contain the name of the first component. For example,
hdisk2 for perfstat_disk_node(), where hdisk 2 is the name of the
disk for which you require the statistics. Note: When you specify a nodename, it must be initialized
as NODENAME.
|
perfstat_subsystem_t *userbuff | Points to a memory area that has enough space for the returned structure. |
int sizeof_struct | Sets this parameter to the size of
perfstat_subsystem_t . |
int desired_number | Specifies the number of structures of type
perfstat_subsystem_t to return to a userbuff field. |
The perfstat_subsystem_node
interface return -1 value
for error. Otherwise it returns the number of structures copied. The field namename is set
to the name of the next available structure, and an exceptional case when userbuff equals
NULL
and desired_number equals 0
, the total number of structures available
is returned.
perfstat_disk_node
interface:
#include <stdio.h>
#include <stdlib.h>
#include <libperfstat.h>
#define INTERVAL_DEFAULT 2
#define COUNT_DEFAULT 10
int main(int argc, char* argv[])
{
int i, ret, tot;
int interval = INTERVAL_DEFAULT, count = COUNT_DEFAULT;
int collect_remote_node_stats = 0;
char nodename[MAXHOSTNAMELEN];
perfstat_disk_t *statp;
perfstat_id_t first;
perfstat_id_node_t nodeid;
/* Process the arguments */
while ((i = getopt(argc, argv, "i:c:n:")) != EOF)
{
switch(i)
{
case 'i':/* Interval */
interval = atoi(optarg);
if( interval <= 0 )
interval = INTERVAL_DEFAULT;
break;
case 'c':/* Number of interations */
count = atoi(optarg);
if( count <= 0 )
count = COUNT_DEFAULT;
break;
case 'n':/* Node name in a cluster environment */
strncpy(nodename, optarg, MAXHOSTNAMELEN);
nodename[MAXHOSTNAMELEN-1] = '\0';
collect_remote_node_stats = 1;
break;
default:
/* Invalid arguments. Print the usage and terminate */
fprintf (stderr, "usage: %s [-i <interval in seconds>] [-c <number of iterations>] [-n <node name in the cluster>]\n", argv[0]);
}
}
if(collect_remote_node_stats)
{
/* perfstat_config needs to be called to enable cluster statistics collection */
ret = perfstat_config(PERFSTAT_ENABLE|PERFSTAT_CLUSTER_STATS, NULL);
if (ret == -1)
{
perror("cluster statistics collection is not available");
exit(-1);
}
}
/* check how many perfstat_disk_t structures are available */
if(collect_remote_node_stats)
{
strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
nodeid.spec = NODENAME;
tot = perfstat_disk_node(&nodeid, NULL, sizeof(perfstat_disk_t), 0);
}
else
{
tot = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0);
}
/* check for error */
if (tot < 0)
{
perror("perfstat_disk");
exit(-1);
}
if (tot == 0)
{
printf("No disks found\n");
exit(-1);
}
/* allocate enough memory for all the structures */
statp = calloc(tot, sizeof(perfstat_disk_t));
if(statp==NULL){
printf("No sufficient memory\n");
exit(-1);
}
if(collect_remote_node_stats)
{
/* Remember nodename is already set */
/* Now set name to first interface */
strcpy(nodeid.name, FIRST_DISK);
/* ask to get all the structures available in one call */
/* return code is number of structures returned */
ret = perfstat_disk_node(&nodeid, statp,
sizeof(perfstat_disk_t), tot);
}
else
{
/* set name to first interface */
strcpy(first.name, FIRST_DISK);
/* ask to get all the structures available in one call */
/* return code is number of structures returned */
ret = perfstat_disk(&first, statp,
sizeof(perfstat_disk_t), tot);
}
/* check for error */
if (ret <= 0)
{
perror("perfstat_disk");
exit(-1);
}
/* print statistics for each of the disks */
for (i = 0; i < ret; i++) {
printf("\nStatistics for disk : %s\n", statp[i].name);
printf("-------------------\n");
printf("description : %s\n", statp[i].description);
printf("volume group name : %s\n", statp[i].vgname);
printf("adapter name : %s\n", statp[i].adapter);
printf("size : %llu MB\n", statp[i].size);
printf("free space : %llu MB\n", statp[i].free);
printf("number of blocks read : %llu blocks of %llu bytes\n", statp[i].rblks, statp[i].bsize);
printf("number of blocks written : %llu blocks of %llu bytes\n", statp[i].wblks, statp[i].bsize);
}
if(collect_remote_node_stats) {
/* Now disable cluster statistics by calling perfstat_config */
perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL);
}
}
The
program displays an output that is similar to the following example
output:Statistics for disk : hdisk0
----------------------------
description : Virtual SCSI Disk Drive
volume group name : rootvg
adapter name : vscsi0
size : 25568 MB
free space : 19616 MB
number of blocks read : 315130 blocks of 512 bytes
number of blocks written : 228352 blocks of 512 bytes
#include <stdio.h>
#include <libperfstat.h>
#define INTERVAL_DEFAULT 2
#define COUNT_DEFAULT 10
int main(int argc, char* argv[])
{
perfstat_memory_total_t minfo;
perfstat_id_node_t nodeid;
char nodename[MAXHOSTNAMELEN];
int interval = INTERVAL_DEFAULT, count = COUNT_DEFAULT;
int collect_remote_node_stats = 0;
int i, rc;
/* Process the arguments */
while ((i = getopt(argc, argv, "i:c:n:")) != EOF)
{
switch(i)
{
case 'i': /* Interval */
interval = atoi(optarg);
if( interval <= 0 )
interval = INTERVAL_DEFAULT;
break;
case 'c': /* Number of iterations */
count = atoi(optarg);
if( count <= 0 )
count = COUNT_DEFAULT;
break;
case 'n': /* Node name in a cluster environment */
strncpy(nodename, optarg, MAXHOSTNAMELEN);
nodename[MAXHOSTNAMELEN-1] = '\0';
collect_remote_node_stats = 1;
break;
default:
/* Invalid arguments. Print the usage and end */
fprintf (stderr, "usage: %s [-i <interval in seconds>] [-c <number of iterations>] [-n <node name in the cluster>]\n", argv[0]);
}
}
if(collect_remote_node_stats)
{
/* perfstat_config needs to be called to enable cluster statistics collection */
rc = perfstat_config(PERFSTAT_ENABLE|PERFSTAT_CLUSTER_STATS, NULL);
if (rc == -1)
{
perror("cluster statistics collection is not available");
exit(-1);
}
}
if(collect_remote_node_stats)
{
strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
nodeid.spec = NODENAME;
rc = perfstat_memory_total_node(&nodeid, &minfo, sizeof(perfstat_memory_total_t), 1);
}
else
{
rc = perfstat_memory_total(NULL, &minfo, sizeof(perfstat_memory_total_t), 1);
}
if (rc != 1) {
perror("perfstat_memory_total");
exit(-1);
}
printf("Memory statistics\n");
printf("-----------------\n");
printf("real memory size : %llu MB\n",
minfo.real_total*4096/1024/1024);
printf("reserved paging space : %llu MB\n",minfo.pgsp_rsvd);
printf("virtual memory size : %llu MB\n",
minfo.virt_total*4096/1024/1024);
printf("number of free pages : %llu\n",minfo.real_free);
printf("number of pinned pages : %llu\n",minfo.real_pinned);
printf("number of pages in file cache : %llu\n",minfo.numperm);
printf("total paging space pages : %llu\n",minfo.pgsp_total);
printf("free paging space pages : %llu\n", minfo.pgsp_free);
printf("used paging space : %3.2f%%\n",
(float)(minfo.pgsp_total-minfo.pgsp_free)*100.0/
(float)minfo.pgsp_total);
printf("number of paging space page ins : %llu\n",minfo.pgspins);
printf("number of paging space page outs : %llu\n",minfo.pgspouts);
printf("number of page ins : %llu\n",minfo.pgins);
printf("number of page outs : %llu\n",minfo.pgouts);
if(collect_remote_node_stats) {
/* Now disable cluster statistics by calling perfstat_config */
perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL);
}
}
The
program displays an output that is similar to the following example
output:Memory statistics
-----------------
real memory size : 4096 MB
reserved paging space : 512 MB
virtual memory size : 4608 MB
number of free pages : 768401
number of pinned pages : 237429
number of pages in file cache : 21473
total paging space pages : 131072
free paging space pages : 128821
used paging space : 1.72%
number of paging space page ins : 0
number of paging space page outs : 0
number of page ins : 37301
number of page outs : 9692
perfstat_cluster_total
interface is used to retrieve cluster statistics
from the perfstat_cluster_total_t
structure, which is defined in the
libperfstat.h
file. The following selected fields are from the
perfstat_cpu_total_t
structure:
Item | Descriptor |
---|---|
name | Specifies the name of the cluster. |
Type | Specifies the set of bits that describes the cluster. |
num_nodes | Specifies the number of nodes in the cluster. |
node_data | Points to a memory area that describes the details of all the nodes. |
num_disks | Specifies the number of disks in the cluster. |
disk_data | Points to a memory area that describes the details of all the disks. |
For a complete list of parameters related to the perfstat_cluster_total_t
structure, see the libperfstat.h header file.
perfstat_cluster_total
interface:
#include <stdio.h>
#include <libperfstat.h>
typedef enum {
DISPLAY_DEFAULT = 0,
DISPLAY_NODE_DATA = 1,
DISPLAY_DISK_DATA = 2
} display_t;
int main(int argc, char* argv[])
{
perfstat_cluster_total_t cstats;
perfstat_node_data_t *node_details;
perfstat_disk_data_t *disk_details;
perfstat_id_node_t nodeid;
display_t display = DISPLAY_DEFAULT;
int num_nodes;
int i, rc;
/* Process the arguments */
while ((i = getopt(argc, argv, "lnd")) != EOF)
{
switch(i)
{
case 'n': /* Request to display node data */
display |= DISPLAY_NODE_DATA;
break;
case 'd': /* Request to diplay disk data */
display |= DISPLAY_DISK_DATA;
break;
case 'h': /* Print help message */
default:
/* Print the usage and end */
fprintf (stderr, "usage: %s [-n] [-d]\n", argv[0]);
exit(-1);
}
}
/* perfstat_config needs to be called to enable cluster statistics collection */
rc = perfstat_config(PERFSTAT_ENABLE|PERFSTAT_CLUSTER_STATS, NULL);
if (rc == -1)
{
perror("cluster statistics collection is not available");
exit(-1);
}
/* Collect cluster statistics */
strncpy(nodeid.u.nodename, FIRST_CLUSTERNAME, MAXHOSTNAMELEN);
nodeid.spec = CLUSTERNAME;
cstats.node_data = NULL; /* To indicate no interest in node details */
cstats.disk_data = NULL; /* To indicate no interest in disk details */
rc = perfstat_cluster_total(&nodeid, &cstats, sizeof(perfstat_cluster_total_t), 1);
if (rc == -1)
{
perror("perfstat_cluster_total failed");
exit(-1);
}
fprintf(stdout, "Cluster statistics\n");
fprintf(stdout, "------------------\n");
fprintf(stdout, "Cluster Name : %s\n", cstats.name);
fprintf(stdout, "Cluster type : ");
if (cstats.type.b.is_local)
fprintf(stdout, "LOCAL\n");
else if (cstats.type.b.is_zone)
fprintf(stdout, "ZONE\n");
else if (cstats.type.b.is_link)
fprintf(stdout, "LINK\n");
fprintf(stdout, "Number of nodes : %u\n", cstats.num_nodes);
fprintf(stdout, "Number of disks : %u\n", cstats.num_disks);
/* check if the user requested node data */
if(((display & DISPLAY_NODE_DATA) && (cstats.num_nodes > 0)) ||
((display & DISPLAY_DISK_DATA) && (cstats.num_disks > 0)))
{
if(display & DISPLAY_NODE_DATA)
{
cstats.sizeof_node_data = sizeof(perfstat_node_data_t);
/* Make sure you allocate at least cstats.num_nodes */
/* Otherwise, perfstat_cluster_total() fails with ENOSPC */
cstats.node_data = (perfstat_node_data_t *) malloc(cstats.sizeof_node_data * cstats.num_nodes);
if(cstats.node_data == NULL)
{
perror("malloc failed for node_data");
exit(-1);
}
}
if(display & DISPLAY_DISK_DATA)
{
cstats.sizeof_disk_data = sizeof(perfstat_disk_data_t);
/* Make sure you allocate at least cstats.num_disks */
/* Otherwise, perfstat_cluster_total() fails with ENOSPC */
cstats.disk_data = (perfstat_disk_data_t *) malloc(cstats.sizeof_disk_data * cstats.num_disks);
if(cstats.disk_data == NULL)
{
perror("malloc failed for disk_data");
exit(-1);
}
}
rc = perfstat_cluster_total(&nodeid, &cstats, sizeof(perfstat_cluster_total_t), 1);
if (rc == -1)
{
perror("perfstat_cluster_total failed");
exit(-1);
}
if(display & DISPLAY_NODE_DATA)
{
fprintf(stdout, "\nNode details:\n");
fprintf(stdout, "-------------\n");
node_details = cstats.node_data;
for (i = 0; i < cstats.num_nodes; i++, node_details++)
{
fprintf(stdout, "Node name : %s\n", node_details->name);
fprintf(stdout, "Node shorthand id : %llu\n",
node_details->shorthand_id);
fprintf(stdout, "Status of the node : ");
if (node_details->status.b.is_up)
fprintf(stdout, "UP\n");
else if (node_details->status.b.is_down)
fprintf(stdout, "DOWN\n");
fprintf(stdout, "Number of clusters the node is participating : %u\n", node_details->num_clusters);
fprintf(stdout, "Number of zones the node is participating : %u\n", node_details->num_zones);
fprintf(stdout, "Number of points of contact to the node :%u\n", node_details->num_points_of_contact);
fprintf(stdout, "\n");
}
}
if(display & DISPLAY_DISK_DATA)
{
fprintf(stdout, "\nDisk details:\n");
fprintf(stdout, "-------------\n");
disk_details = cstats.disk_data;
for (i = 0; i < cstats.num_disks; i++, disk_details++)
{
fprintf(stdout, "Disk name : %s\n", disk_details->name);
fprintf(stdout, "Status of the disk :");
if (disk_details->status.b.is_found)
{
fprintf(stdout, " FOUND");
if (disk_details->status.b.is_ready)
fprintf(stdout, " | READY");
else
fprintf(stdout, " | NOT READY");
}
else
fprintf(stdout, " NOT FOUND");
fprintf(stdout, "\n");
fprintf(stdout, "\n");
}
}
}
/* Now disable cluster statistics by calling perfstat_config */
perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL);
}
perfstat_node_list
interface is used to retrieve the list of nodes in the
perfstat_node_t
structure, which is defined in the libperfstat.h
file. The following selected fields are from the perfstat_node_t
structure:
Item | Descriptor |
---|---|
nodeid | Specifies the identifier of the node. |
nodename | Specifies the name of the node. |
perfstat_node_list
interface:
#include <stdio.h>
#include <libperfstat.h>
int main(int argc, char* argv[])
{
perfstat_id_node_t nodeid;
perfstat_node_t *node_list;
int num_nodes;
int i, rc;
/* perfstat_config needs to be called to enable cluster statistics collection */
rc = perfstat_config(PERFSTAT_ENABLE|PERFSTAT_CLUSTER_STATS, NULL);
if (rc == -1)
{
perror("cluster statistics collection is not available");
exit(-1);
}
strncpy(nodeid.u.nodename, FIRST_CLUSTERNAME, MAXHOSTNAMELEN);
nodeid.spec = CLUSTERNAME;
num_nodes = perfstat_node_list(&nodeid, NULL, sizeof(perfstat_node_t), 0);
if (num_nodes == -1)
{
perror("perfstat_node_list failed");
exit(-1);
}
if (num_nodes == 0)
{ /* This cannot happen */
fprintf(stdout, "No nodes in the cluster.\n");
exit(-1);
}
node_list = (perfstat_node_t *) malloc(sizeof(perfstat_node_t) * num_nodes);
num_nodes = perfstat_node_list(&nodeid, node_list, sizeof(perfstat_node_t), num_nodes);
if (num_nodes == -1)
{
perror("perfstat_node_list failed");
exit(-1);
}
fprintf(stdout, "Number of nodes : %d\n\n", num_nodes);
for (i = 0; i < num_nodes; i++)
{
fprintf(stdout, "Node name : %s\n", node_list[i].nodename);
fprintf(stdout, "Node id : %llu\n", node_list[i].nodeid);
fprintf(stdout, "\n");
}
/* Now disable cluster statistics by calling perfstat_config */
perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL);
return (0);
}
The perfstat_cluster_disk interface is used to retrieve the list of disks in
the perfstat_disk_data_t
structure. The perfstat_cluster_disk
interface is defined in the libperfstat.h file.
The following example code shows the usage of the perfstat_cluster_disk subroutine:
#include <stdio.h>
#include <libperfstat.h>
typedef enum {
DISPLAY_NODE_DATA = 1,
DISPLAY_DISK_DATA = 2,
} display_t;
int main(int argc, char* argv[])
{
perfstat_node_data_t *node_details;
perfstat_disk_data_t *disk_details;
perfstat_id_node_t nodeid;
char nodename[MAXHOSTNAMELEN];
display_t display = DISPLAY_DISK_DATA;
int num_nodes;
int i, rc, num_of_disks = 0;
/* Process the arguments */
while ((i = getopt(argc, argv, "n:d")) != EOF)
{
switch(i)
{
case 'n': /* Request to display node data */
display |= DISPLAY_NODE_DATA;
strncpy(nodename,optarg,MAXHOSTNAMELEN);
break;
case 'd': /* Request to diplay disk data */
display |= DISPLAY_DISK_DATA;
break;
case 'h': /* Print help message */
default:
/* Print the usage and terminate */
fprintf (stderr, "usage: %s [-n <nodename>] [-d]\n", argv[0]);
exit(-1);
}
}
/* perfstat_config needs to be called to enable cluster statistics collection */
rc = perfstat_config(PERFSTAT_ENABLE|PERFSTAT_CLUSTER_STATS, NULL);
if (rc == -1)
{
perror("cluster statistics collection is not available");
exit(-1);
}
/*If Node details are specified pass that data as input to get the disk details
for that node . Else pass FIRST_NODENAME */
if (display & DISPLAY_NODE_DATA)
{
strncpy(nodeid.u.nodename,nodename,MAXHOSTNAMELEN);
}
else
strncpy(nodeid.u.nodename, FIRST_NODENAME, MAXHOSTNAMELEN);
nodeid.spec = NODENAME;
/*Get the number of disks for that node */
num_of_disks = perfstat_cluster_disk(&nodeid,NULL, sizeof(perfstat_disk_data_t), 0);
if (num_of_disks == -1)
{
perror("perfstat_cluster_disk failed");
exit(-1);
}
disk_details = (perfstat_disk_data_t *)calloc(num_of_disks,sizeof(perfstat_disk_data_t));
/* collect all the disk data for the node */
if(!disk_details){
perror("calloc");
exit(-1);
}
num_of_disks = perfstat_cluster_disk(&nodeid,disk_details,sizeof(perfstat_disk_data_t),num_of_disks);
fprintf(stdout, "Disk Details\n");
fprintf(stdout, "------------------\n");
for(i = 0; i < num_of_disks; i++)
{
fprintf(stdout,"Disk Name:%s\t UDID:%s\n",disk_details[i].name,disk_details[i].uuid);
}
/* Now disable cluster statistics by calling perfstat_config */
perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL);
free(disk_details);
disk_details = NULL;
}