2979 lines
68 KiB
Perl
2979 lines
68 KiB
Perl
#
|
|
# Copyright (c) 2007-2009 Hyperic, Inc.
|
|
# Copyright (c) 2009 SpringSource, Inc.
|
|
# Copyright (c) 2009-2010 VMware, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
|
|
#extension source generator for all bindings
|
|
package SigarWrapper;
|
|
|
|
use strict;
|
|
use Cwd;
|
|
use Exporter;
|
|
use File::Path;
|
|
use IO::File ();
|
|
|
|
use vars qw(@ISA @EXPORT);
|
|
@ISA = qw(Exporter);
|
|
@EXPORT = qw(generate);
|
|
|
|
my %platforms = (
|
|
A => "AIX",
|
|
D => "Darwin",
|
|
F => "FreeBSD",
|
|
H => "HPUX",
|
|
L => "Linux",
|
|
S => "Solaris",
|
|
W => "Win32",
|
|
);
|
|
|
|
my %has_name_arg = map { $_, 1 } qw(FileSystemUsage DiskUsage
|
|
FileAttrs DirStat DirUsage
|
|
NetInterfaceConfig NetInterfaceStat);
|
|
|
|
my %proc_no_arg = map { $_, 1 } qw(stat);
|
|
|
|
my %get_not_impl = map { $_, 1 } qw(net_address net_route net_connection net_stat cpu_perc
|
|
arp who cpu_info file_system); #list funcs only
|
|
|
|
sub supported_platforms {
|
|
my $p = shift;
|
|
return 'Undocumented' unless $p;
|
|
if ($p eq '*') {
|
|
return 'All';
|
|
}
|
|
|
|
my @platforms;
|
|
for (split //, $p) {
|
|
push @platforms, $platforms{$_};
|
|
}
|
|
|
|
return join ", ", @platforms;
|
|
}
|
|
|
|
sub hash {
|
|
return unpack("%32C*", shift) % 65535;
|
|
}
|
|
|
|
my $nfs_v2 = [
|
|
{
|
|
name => 'null', type => 'Long',
|
|
},
|
|
{
|
|
name => 'getattr', type => 'Long',
|
|
},
|
|
{
|
|
name => 'setattr', type => 'Long',
|
|
},
|
|
{
|
|
name => 'root', type => 'Long',
|
|
},
|
|
{
|
|
name => 'lookup', type => 'Long',
|
|
},
|
|
{
|
|
name => 'readlink', type => 'Long',
|
|
},
|
|
{
|
|
name => 'read', type => 'Long',
|
|
},
|
|
{
|
|
name => 'writecache', type => 'Long',
|
|
},
|
|
{
|
|
name => 'write', type => 'Long',
|
|
},
|
|
{
|
|
name => 'create', type => 'Long',
|
|
},
|
|
{
|
|
name => 'remove', type => 'Long',
|
|
},
|
|
{
|
|
name => 'rename', type => 'Long',
|
|
},
|
|
{
|
|
name => 'link', type => 'Long',
|
|
},
|
|
{
|
|
name => 'symlink', type => 'Long',
|
|
},
|
|
{
|
|
name => 'mkdir', type => 'Long',
|
|
},
|
|
{
|
|
name => 'rmdir', type => 'Long',
|
|
},
|
|
{
|
|
name => 'readdir', type => 'Long',
|
|
},
|
|
{
|
|
name => 'fsstat', type => 'Long',
|
|
},
|
|
];
|
|
|
|
my $nfs_v3 = [
|
|
{
|
|
name => 'null', type => 'Long',
|
|
},
|
|
{
|
|
name => 'getattr', type => 'Long',
|
|
},
|
|
{
|
|
name => 'setattr', type => 'Long',
|
|
},
|
|
{
|
|
name => 'lookup', type => 'Long',
|
|
},
|
|
{
|
|
name => 'access', type => 'Long',
|
|
},
|
|
{
|
|
name => 'readlink', type => 'Long',
|
|
},
|
|
{
|
|
name => 'read', type => 'Long',
|
|
},
|
|
{
|
|
name => 'write', type => 'Long',
|
|
},
|
|
{
|
|
name => 'create', type => 'Long',
|
|
},
|
|
{
|
|
name => 'mkdir', type => 'Long',
|
|
},
|
|
{
|
|
name => 'symlink', type => 'Long',
|
|
},
|
|
{
|
|
name => 'mknod', type => 'Long',
|
|
},
|
|
{
|
|
name => 'remove', type => 'Long',
|
|
},
|
|
{
|
|
name => 'rmdir', type => 'Long',
|
|
},
|
|
{
|
|
name => 'rename', type => 'Long',
|
|
},
|
|
{
|
|
name => 'link', type => 'Long',
|
|
},
|
|
{
|
|
name => 'readdir', type => 'Long',
|
|
},
|
|
{
|
|
name => 'readdirplus', type => 'Long',
|
|
},
|
|
{
|
|
name => 'fsstat', type => 'Long',
|
|
},
|
|
{
|
|
name => 'fsinfo', type => 'Long',
|
|
},
|
|
{
|
|
name => 'pathconf', type => 'Long',
|
|
},
|
|
{
|
|
name => 'commit', type => 'Long',
|
|
},
|
|
];
|
|
|
|
use vars qw(%classes %cmds);
|
|
|
|
%classes = (
|
|
Mem => [
|
|
{
|
|
name => 'total', type => 'Long',
|
|
desc => 'Total system memory',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => 'lsattr -El sys0 -a realmem',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => '',
|
|
Win32 => 'taskman',
|
|
},
|
|
},
|
|
{
|
|
name => 'ram', type => 'Long',
|
|
desc => 'System Random Access Memory (in MB)',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => 'lsattr -El sys0 -a realmem',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'cat /proc/mtrr | head -1',
|
|
Solaris => '',
|
|
Win32 => '',
|
|
},
|
|
},
|
|
{
|
|
name => 'used', type => 'Long',
|
|
desc => 'Total used system memory',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => '',
|
|
Win32 => 'taskman',
|
|
},
|
|
},
|
|
{
|
|
name => 'free', type => 'Long',
|
|
desc => 'Total free system memory (e.g. Linux plus cached)',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => '',
|
|
Win32 => 'taskman',
|
|
},
|
|
},
|
|
{
|
|
name => 'actual_used', type => 'Long',
|
|
desc => 'Actual total used system memory (e.g. Linux minus buffers)',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => '',
|
|
Win32 => 'taskman',
|
|
},
|
|
},
|
|
{
|
|
name => 'actual_free', type => 'Long',
|
|
desc => 'Actual total free system memory',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => '',
|
|
Win32 => 'taskman',
|
|
},
|
|
},
|
|
{
|
|
name => 'used_percent', type => 'Double',
|
|
desc => 'Percent total used system memory',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => '',
|
|
Win32 => 'taskman',
|
|
},
|
|
},
|
|
{
|
|
name => 'free_percent', type => 'Double',
|
|
desc => 'Percent total free system memory',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => '',
|
|
Win32 => 'taskman',
|
|
},
|
|
},
|
|
],
|
|
Swap => [
|
|
{
|
|
name => 'total', type => 'Long',
|
|
desc => 'Total system swap',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => 'lsps -s',
|
|
Darwin => 'sysctl vm.swapusage',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => 'swap -s',
|
|
Win32 => '',
|
|
},
|
|
},
|
|
{
|
|
name => 'used', type => 'Long',
|
|
desc => 'Total used system swap',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => 'lsps -s',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => 'swap -s',
|
|
Win32 => '',
|
|
},
|
|
},
|
|
{
|
|
name => 'free', type => 'Long',
|
|
desc => 'Total free system swap',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'free',
|
|
Solaris => 'swap -s',
|
|
Win32 => '',
|
|
},
|
|
},
|
|
{
|
|
name => 'page_in', type => 'Long',
|
|
desc => 'Pages in',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'vmstat',
|
|
Solaris => 'vmstat',
|
|
Win32 => '',
|
|
},
|
|
},
|
|
{
|
|
name => 'page_out', type => 'Long',
|
|
desc => 'Pages out',
|
|
plat => '*',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'vmstat',
|
|
Solaris => 'vmstat',
|
|
Win32 => '',
|
|
},
|
|
},
|
|
],
|
|
Cpu => [
|
|
{
|
|
name => 'user', type => 'Long',
|
|
desc => 'Total system cpu user time',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'sys', type => 'Long',
|
|
desc => 'Total system cpu kernel time',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'nice', type => 'Long',
|
|
desc => 'Total system cpu nice time',
|
|
plat => 'DFHL'
|
|
},
|
|
{
|
|
name => 'idle', type => 'Long',
|
|
desc => 'Total system cpu idle time',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'wait', type => 'Long',
|
|
desc => 'Total system cpu io wait time',
|
|
plat => 'ALHS'
|
|
},
|
|
{
|
|
name => 'irq', type => 'Long',
|
|
desc => 'Total system cpu time servicing interrupts',
|
|
plat => 'FLHW'
|
|
},
|
|
{
|
|
name => 'soft_irq', type => 'Long',
|
|
desc => 'Total system cpu time servicing softirqs',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'stolen', type => 'Long',
|
|
desc => 'Total system cpu involuntary wait time',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'total', type => 'Long',
|
|
desc => 'Total system cpu time',
|
|
plat => '*'
|
|
},
|
|
],
|
|
CpuPerc => [
|
|
{
|
|
name => 'user', type => 'Double',
|
|
desc => 'Percent system cpu user time',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'sys', type => 'Double',
|
|
desc => 'Percent system cpu kernel time',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'nice', type => 'Double',
|
|
desc => 'Percent system cpu nice time',
|
|
plat => 'DFHL'
|
|
},
|
|
{
|
|
name => 'idle', type => 'Double',
|
|
desc => 'Percent system cpu idle time',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'wait', type => 'Double',
|
|
desc => 'Percent system cpu io wait time',
|
|
plat => 'ALHS'
|
|
},
|
|
{
|
|
name => 'irq', type => 'Double',
|
|
desc => 'Percent system cpu time servicing interrupts',
|
|
plat => 'FLHW'
|
|
},
|
|
{
|
|
name => 'soft_irq', type => 'Double',
|
|
desc => 'Percent system cpu time servicing softirqs',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'stolen', type => 'Double',
|
|
desc => 'Percent system cpu involuntary wait time',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'combined', type => 'Double',
|
|
desc => 'Sum of User + Sys + Nice + Wait',
|
|
plat => '*'
|
|
},
|
|
],
|
|
CpuInfo => [
|
|
{
|
|
name => 'vendor', type => 'String',
|
|
desc => 'CPU vendor id',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'model', type => 'String',
|
|
desc => 'CPU model',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'mhz', type => 'Int',
|
|
desc => 'Current CPU speed',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'mhz_max', type => 'Int',
|
|
desc => 'Maximum CPU speed',
|
|
plat => 'DL'
|
|
},
|
|
{
|
|
name => 'mhz_min', type => 'Int',
|
|
desc => 'Maximum CPU speed',
|
|
plat => 'DL'
|
|
},
|
|
{
|
|
name => 'cache_size', type => 'Long',
|
|
desc => 'CPU cache size',
|
|
plat => 'ADL'
|
|
},
|
|
{
|
|
name => 'total_cores', type => 'Int',
|
|
desc => 'Total CPU cores (logical)',
|
|
},
|
|
{
|
|
name => 'total_sockets', type => 'Int',
|
|
desc => 'Total CPU sockets (physical)',
|
|
},
|
|
{
|
|
name => 'cores_per_socket', type => 'Int',
|
|
desc => 'Number of CPU cores per CPU socket',
|
|
},
|
|
],
|
|
Uptime => [
|
|
{
|
|
name => 'uptime', type => 'Double',
|
|
desc => 'Time since machine started in seconds',
|
|
plat => '*'
|
|
},
|
|
],
|
|
ProcMem => [
|
|
{
|
|
name => 'size', type => 'Long',
|
|
desc => 'Total process virtual memory',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'resident', type => 'Long',
|
|
desc => 'Total process resident memory',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'share', type => 'Long',
|
|
desc => 'Total process shared memory',
|
|
plat => 'AHLS'
|
|
},
|
|
{
|
|
name => 'minor_faults', type => 'Long',
|
|
desc => 'non i/o page faults',
|
|
plat => 'AHLS'
|
|
},
|
|
{
|
|
name => 'major_faults', type => 'Long',
|
|
desc => 'i/o page faults',
|
|
plat => 'AHLS'
|
|
},
|
|
{
|
|
name => 'page_faults', type => 'Long',
|
|
desc => 'Total number of page faults',
|
|
plat => 'ADHLSW'
|
|
},
|
|
],
|
|
ProcCred => [
|
|
{
|
|
name => 'uid', type => 'Long',
|
|
desc => 'Process user id',
|
|
plat => 'ADFHLS'
|
|
},
|
|
{
|
|
name => 'gid', type => 'Long',
|
|
desc => 'Process group id',
|
|
plat => 'ADFHLS'
|
|
},
|
|
{
|
|
name => 'euid', type => 'Long',
|
|
desc => 'Process effective user id',
|
|
plat => 'ADFHLS'
|
|
},
|
|
{
|
|
name => 'egid', type => 'Long',
|
|
desc => 'Process effective group id',
|
|
plat => 'ADFHLS'
|
|
},
|
|
],
|
|
ProcCredName => [
|
|
{
|
|
name => 'user', type => 'String',
|
|
desc => 'Process owner user name',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'group', type => 'String',
|
|
desc => 'Process owner group name',
|
|
plat => '*'
|
|
},
|
|
],
|
|
ProcTime => [
|
|
{
|
|
name => 'start_time', type => 'Long',
|
|
desc => 'Time process was started in seconds',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'user', type => 'Long',
|
|
desc => 'Process cpu user time',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'sys', type => 'Long',
|
|
desc => 'Process cpu kernel time',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'total', type => 'Long',
|
|
desc => 'Process cpu time (sum of User and Sys)',
|
|
plat => '*'
|
|
},
|
|
],
|
|
ProcCpu => [
|
|
{
|
|
name => 'percent', type => 'Double',
|
|
desc => 'Process cpu usage',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'last_time', type => 'Long',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
],
|
|
ProcState => [
|
|
{
|
|
name => 'state', type => 'Char',
|
|
desc => 'Process state (Running, Zombie, etc.)',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'name', type => 'String',
|
|
desc => 'Name of the process program',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'ppid', type => 'Long',
|
|
desc => 'Process parent process id',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'tty', type => 'Int',
|
|
desc => 'Device number of rocess controling terminal',
|
|
plat => 'AHLS'
|
|
},
|
|
{
|
|
name => 'nice', type => 'Int',
|
|
desc => 'Nice value of process',
|
|
plat => 'ADFHLS'
|
|
},
|
|
{
|
|
name => 'priority', type => 'Int',
|
|
desc => 'Kernel scheduling priority of process',
|
|
plat => 'DFHLSW'
|
|
},
|
|
{
|
|
name => 'threads', type => 'Long',
|
|
desc => 'Number of active threads',
|
|
plat => 'ADHLSW'
|
|
},
|
|
{
|
|
name => 'processor', type => 'Int',
|
|
desc => 'Processor number last run on',
|
|
plat => 'AHLS'
|
|
},
|
|
],
|
|
ProcFd => [
|
|
{
|
|
name => 'total', type => 'Long',
|
|
desc => 'Total number of open file descriptors',
|
|
plat => 'AHLSW'
|
|
},
|
|
],
|
|
ProcStat => [
|
|
{
|
|
name => 'total', type => 'Long',
|
|
desc => 'Total number of processes',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'idle', type => 'Long',
|
|
desc => 'Total number of processes in idle state',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'running', type => 'Long',
|
|
desc => 'Total number of processes in run state',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'sleeping', type => 'Long',
|
|
desc => 'Total number of processes in sleep state',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'stopped', type => 'Long',
|
|
desc => 'Total number of processes in stop state',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'zombie', type => 'Long',
|
|
desc => 'Total number of processes in zombie state',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'threads', type => 'Long',
|
|
desc => 'Total number of threads',
|
|
plat => '*'
|
|
},
|
|
],
|
|
ProcExe => [
|
|
{
|
|
name => 'name', type => 'String',
|
|
desc => 'Name of process executable',
|
|
plat => 'FLSW',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'ls -l /proc/$$/exe',
|
|
Solaris => '',
|
|
Win32 => '',
|
|
},
|
|
},
|
|
{
|
|
name => 'cwd', type => 'String',
|
|
desc => 'Name of process current working directory',
|
|
plat => 'LSW',
|
|
cmd => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'ls -l /proc/$$/cwd',
|
|
Solaris => '',
|
|
Win32 => '',
|
|
},
|
|
},
|
|
],
|
|
ThreadCpu => [
|
|
{
|
|
name => 'user', type => 'Long',
|
|
desc => 'Thread cpu user time',
|
|
plat => 'AHLSW'
|
|
},
|
|
{
|
|
name => 'sys', type => 'Long',
|
|
desc => 'Thread cpu kernel time',
|
|
plat => 'AHLSW'
|
|
},
|
|
{
|
|
name => 'total', type => 'Long',
|
|
desc => 'Thread cpu time (sum of User and Sys)',
|
|
plat => 'AHLSW'
|
|
},
|
|
],
|
|
FileSystem => [
|
|
{
|
|
name => 'dir_name', type => 'String',
|
|
desc => 'Directory name',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'dev_name', type => 'String',
|
|
desc => 'Device name',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'type_name', type => 'String',
|
|
desc => 'File system generic type name',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'sys_type_name', type => 'String',
|
|
desc => 'File system os specific type name',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'options', type => 'String',
|
|
desc => 'File system mount options',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'type', type => 'Int',
|
|
desc => 'File system type',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'flags', type => 'Long',
|
|
desc => 'File system flags',
|
|
plat => '*'
|
|
},
|
|
],
|
|
FileSystemUsage => [
|
|
{
|
|
name => 'total', type => 'Long',
|
|
desc => 'Total Kbytes of filesystem',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'free', type => 'Long',
|
|
desc => 'Total free Kbytes on filesystem',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'used', type => 'Long',
|
|
desc => 'Total used Kbytes on filesystem',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'avail', type => 'Long',
|
|
desc => 'Total free Kbytes on filesystem available to caller',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'files', type => 'Long',
|
|
desc => 'Total number of file nodes on the filesystem',
|
|
plat => 'ADFHLS'
|
|
},
|
|
{
|
|
name => 'free_files', type => 'Long',
|
|
desc => 'Number of free file nodes on the filesystem',
|
|
plat => 'ADFHLS'
|
|
},
|
|
{
|
|
name => 'disk_reads', type => 'Long',
|
|
desc => 'Number of physical disk reads',
|
|
plat => 'AFHLSW'
|
|
},
|
|
{
|
|
name => 'disk_writes', type => 'Long',
|
|
desc => 'Number of physical disk writes',
|
|
plat => 'AFHLSW'
|
|
},
|
|
{
|
|
name => 'disk_read_bytes', type => 'Long',
|
|
desc => 'Number of physical disk bytes read',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'disk_write_bytes', type => 'Long',
|
|
desc => 'Number of physical disk bytes written',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'disk_queue', type => 'Double',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'disk_service_time', type => 'Double',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'use_percent', type => 'Double',
|
|
desc => 'Percent of disk used',
|
|
plat => '*'
|
|
},
|
|
],
|
|
DiskUsage => [
|
|
{
|
|
name => 'reads', type => 'Long',
|
|
desc => 'Number of physical disk reads',
|
|
plat => 'AFHLSW'
|
|
},
|
|
{
|
|
name => 'writes', type => 'Long',
|
|
desc => 'Number of physical disk writes',
|
|
plat => 'AFHLSW'
|
|
},
|
|
{
|
|
name => 'read_bytes', type => 'Long',
|
|
desc => 'Number of physical disk bytes read',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'write_bytes', type => 'Long',
|
|
desc => 'Number of physical disk bytes written',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'queue', type => 'Double',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'service_time', type => 'Double',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
],
|
|
FileAttrs => [
|
|
{
|
|
name => 'permissions', type => 'Long',
|
|
},
|
|
{
|
|
name => 'type', type => 'Int',
|
|
},
|
|
{
|
|
name => 'uid', type => 'Long',
|
|
},
|
|
{
|
|
name => 'gid', type => 'Long',
|
|
},
|
|
{
|
|
name => 'inode', type => 'Long',
|
|
},
|
|
{
|
|
name => 'device', type => 'Long',
|
|
},
|
|
{
|
|
name => 'nlink', type => 'Long',
|
|
},
|
|
{
|
|
name => 'size', type => 'Long',
|
|
},
|
|
{
|
|
name => 'atime', type => 'Long',
|
|
},
|
|
{
|
|
name => 'ctime', type => 'Long',
|
|
},
|
|
{
|
|
name => 'mtime', type => 'Long',
|
|
},
|
|
],
|
|
DirStat => [
|
|
{
|
|
name => 'total', type => 'Long',
|
|
},
|
|
{
|
|
name => 'files', type => 'Long',
|
|
},
|
|
{
|
|
name => 'subdirs', type => 'Long',
|
|
},
|
|
{
|
|
name => 'symlinks', type => 'Long',
|
|
},
|
|
{
|
|
name => 'chrdevs', type => 'Long',
|
|
},
|
|
{
|
|
name => 'blkdevs', type => 'Long',
|
|
},
|
|
{
|
|
name => 'sockets', type => 'Long',
|
|
},
|
|
{
|
|
name => 'disk_usage', type => 'Long',
|
|
},
|
|
],
|
|
NetInfo => [
|
|
{
|
|
name => 'default_gateway', type => 'String',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'default_gateway_interface', type => 'String',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'host_name', type => 'String',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'domain_name', type => 'String',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'primary_dns', type => 'String',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'secondary_dns', type => 'String',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
],
|
|
NetRoute => [
|
|
{
|
|
name => 'destination', type => 'NetAddress',
|
|
desc => '',
|
|
plat => 'HLW'
|
|
},
|
|
{
|
|
name => 'gateway', type => 'NetAddress',
|
|
desc => '',
|
|
plat => 'HLW'
|
|
},
|
|
{
|
|
name => 'flags', type => 'Long',
|
|
desc => '',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'refcnt', type => 'Long',
|
|
desc => '',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'use', type => 'Long',
|
|
desc => '',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'metric', type => 'Long',
|
|
desc => '',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'mask', type => 'NetAddress',
|
|
desc => '',
|
|
plat => 'HL'
|
|
},
|
|
{
|
|
name => 'mtu', type => 'Long',
|
|
desc => '',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'window', type => 'Long',
|
|
desc => '',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'irtt', type => 'Long',
|
|
desc => '',
|
|
plat => 'L'
|
|
},
|
|
{
|
|
name => 'ifname', type => 'String',
|
|
desc => '',
|
|
plat => 'L'
|
|
},
|
|
],
|
|
NetInterfaceConfig => [
|
|
{
|
|
name => 'name', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'hwaddr', type => 'NetAddress',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'type', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'description', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'address', type => 'NetAddress',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'address6', type => 'NetAddress',
|
|
desc => '',
|
|
},
|
|
{
|
|
name => 'prefix6_length', type => 'Int',
|
|
desc => '',
|
|
},
|
|
{
|
|
name => 'scope6', type => 'Int',
|
|
desc => '',
|
|
},
|
|
{
|
|
name => 'destination', type => 'NetAddress',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'broadcast', type => 'NetAddress',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'netmask', type => 'NetAddress',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'flags', type => 'Long',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'mtu', type => 'Long',
|
|
desc => '',
|
|
plat => 'DFL'
|
|
},
|
|
{
|
|
name => 'metric', type => 'Long',
|
|
desc => '',
|
|
plat => 'DFL'
|
|
},
|
|
{
|
|
name => 'tx_queue_len', type => 'Int',
|
|
desc => '',
|
|
plat => 'L'
|
|
},
|
|
],
|
|
NetInterfaceStat => [
|
|
{
|
|
name => 'rx_bytes', type => 'Long',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'rx_packets', type => 'Long',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'rx_errors', type => 'Long',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'rx_dropped', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'rx_overruns', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'rx_frame', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'tx_bytes', type => 'Long',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'tx_packets', type => 'Long',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'tx_errors', type => 'Long',
|
|
desc => '*',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'tx_dropped', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'tx_overruns', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'tx_collisions', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'tx_carrier', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'speed', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
],
|
|
NetConnection => [
|
|
{
|
|
name => 'local_port', type => 'Long',
|
|
desc => '',
|
|
plat => 'LFSW'
|
|
},
|
|
{
|
|
name => 'local_address', type => 'NetAddress',
|
|
desc => '',
|
|
plat => 'LFSW'
|
|
},
|
|
{
|
|
name => 'remote_port', type => 'Long',
|
|
desc => '',
|
|
plat => 'LFSW'
|
|
},
|
|
{
|
|
name => 'remote_address', type => 'NetAddress',
|
|
desc => '',
|
|
plat => 'LFSW'
|
|
},
|
|
{
|
|
name => 'type', type => 'Int',
|
|
desc => '',
|
|
plat => 'LFSW'
|
|
},
|
|
{
|
|
name => 'state', type => 'Int',
|
|
desc => '',
|
|
plat => 'LFSW'
|
|
},
|
|
{
|
|
name => 'send_queue', type => 'Long',
|
|
desc => '',
|
|
plat => 'LFS'
|
|
},
|
|
{
|
|
name => 'receive_queue', type => 'Long',
|
|
desc => '',
|
|
plat => 'LFS'
|
|
},
|
|
],
|
|
#only for jfieldId cache/setters
|
|
NetStat => [
|
|
{
|
|
name => 'tcp_inbound_total', type => 'Int',
|
|
},
|
|
{
|
|
name => 'tcp_outbound_total', type => 'Int',
|
|
},
|
|
{
|
|
name => 'all_inbound_total', type => 'Int',
|
|
},
|
|
{
|
|
name => 'all_outbound_total', type => 'Int',
|
|
},
|
|
],
|
|
Tcp => [
|
|
{
|
|
name => 'active_opens', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'passive_opens', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'attempt_fails', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'estab_resets', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'curr_estab', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'in_segs', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'out_segs', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'retrans_segs', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'in_errs', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'out_rsts', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
],
|
|
NfsClientV2 => $nfs_v2,
|
|
NfsServerV2 => $nfs_v2,
|
|
NfsClientV3 => $nfs_v3,
|
|
NfsServerV3 => $nfs_v3,
|
|
ResourceLimit => [
|
|
{
|
|
name => 'cpu_cur',
|
|
},
|
|
{
|
|
name => 'cpu_max',
|
|
},
|
|
{
|
|
name => 'file_size_cur',
|
|
},
|
|
{
|
|
name => 'file_size_max',
|
|
},
|
|
{
|
|
name => 'pipe_size_max',
|
|
},
|
|
{
|
|
name => 'pipe_size_cur',
|
|
},
|
|
{
|
|
name => 'data_cur',
|
|
},
|
|
{
|
|
name => 'data_max',
|
|
},
|
|
{
|
|
name => 'stack_cur',
|
|
},
|
|
{
|
|
name => 'stack_max',
|
|
},
|
|
{
|
|
name => 'core_cur',
|
|
},
|
|
{
|
|
name => 'core_max',
|
|
},
|
|
{
|
|
name => 'memory_cur',
|
|
},
|
|
{
|
|
name => 'memory_max',
|
|
},
|
|
{
|
|
name => 'processes_cur',
|
|
},
|
|
{
|
|
name => 'processes_max',
|
|
},
|
|
{
|
|
name => 'open_files_cur',
|
|
},
|
|
{
|
|
name => 'open_files_max',
|
|
},
|
|
{
|
|
name => 'virtual_memory_cur',
|
|
},
|
|
{
|
|
name => 'virtual_memory_max',
|
|
},
|
|
],
|
|
SysInfo => [
|
|
{
|
|
name => 'name', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'version', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'arch', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'machine', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'description', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'patch_level', type => 'String',
|
|
desc => '',
|
|
plat => 'W'
|
|
},
|
|
{
|
|
name => 'vendor', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'vendor_version', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'vendor_name', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'vendor_code_name', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
],
|
|
Arp => [
|
|
{
|
|
name => 'ifname', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'hwaddr', type => 'NetAddress',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'type', type => 'String',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'address', type => 'NetAddress',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
{
|
|
name => 'flags', type => 'Long',
|
|
desc => '',
|
|
plat => '*'
|
|
},
|
|
],
|
|
Who => [
|
|
{
|
|
name => 'user', type => 'String',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'device', type => 'String',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'host', type => 'String',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
{
|
|
name => 'time', type => 'Long',
|
|
desc => '',
|
|
plat => ''
|
|
},
|
|
],
|
|
);
|
|
|
|
$classes{DirUsage} = $classes{DirStat};
|
|
|
|
my(%extends) = (
|
|
ProcCpu => 'ProcTime',
|
|
);
|
|
|
|
while (my($subclass, $superclass) = each %extends) {
|
|
push @{ $classes{$subclass} }, @{ $classes{$superclass} };
|
|
}
|
|
|
|
%cmds = (
|
|
Mem => {
|
|
AIX => 'top',
|
|
Darwin => 'top',
|
|
FreeBSD => 'top',
|
|
HPUX => 'top',
|
|
Linux => 'top',
|
|
Solaris => 'top',
|
|
Win32 => 'taskman',
|
|
},
|
|
Swap => {
|
|
AIX => 'top',
|
|
Darwin => 'top',
|
|
FreeBSD => 'top',
|
|
HPUX => 'top',
|
|
Linux => 'top',
|
|
Solaris => 'top',
|
|
Win32 => 'taskman',
|
|
},
|
|
Cpu => {
|
|
AIX => 'top',
|
|
Darwin => 'top',
|
|
FreeBSD => 'top',
|
|
HPUX => 'top',
|
|
Linux => 'top',
|
|
Solaris => 'top',
|
|
Win32 => 'taskman',
|
|
},
|
|
CpuInfo => {
|
|
AIX => 'lsattr -El proc0',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'cat /proc/cpuinfo',
|
|
Solaris => 'psrinfo -v',
|
|
Win32 => '',
|
|
},
|
|
Uptime => {
|
|
AIX => 'uptime',
|
|
Darwin => 'uptime',
|
|
FreeBSD => 'uptime',
|
|
HPUX => 'uptime',
|
|
Linux => 'uptime',
|
|
Solaris => 'uptime',
|
|
Win32 => '',
|
|
},
|
|
ProcMem => {
|
|
AIX => 'top, ps',
|
|
Darwin => 'top, ps',
|
|
FreeBSD => 'top, ps',
|
|
HPUX => 'top, ps',
|
|
Linux => 'top, ps',
|
|
Solaris => 'top, ps',
|
|
Win32 => 'taskman',
|
|
},
|
|
ProcCred => {
|
|
AIX => 'top, ps',
|
|
Darwin => 'top, ps',
|
|
FreeBSD => 'top, ps',
|
|
HPUX => 'top, ps',
|
|
Linux => 'top, ps',
|
|
Solaris => 'top, ps',
|
|
Win32 => 'taskman',
|
|
},
|
|
ProcTime => {
|
|
AIX => 'top, ps',
|
|
Darwin => 'top, ps',
|
|
FreeBSD => 'top, ps',
|
|
HPUX => 'top, ps',
|
|
Linux => 'top, ps',
|
|
Solaris => 'top, ps',
|
|
Win32 => 'taskman',
|
|
},
|
|
ProcState => {
|
|
AIX => 'top, ps',
|
|
Darwin => 'top, ps',
|
|
FreeBSD => 'top, ps',
|
|
HPUX => 'top, ps',
|
|
Linux => 'top, ps',
|
|
Solaris => 'top, ps',
|
|
Win32 => 'taskman',
|
|
},
|
|
ProcFd => {
|
|
AIX => 'lsof',
|
|
Darwin => 'lsof',
|
|
FreeBSD => 'lsof',
|
|
HPUX => 'lsof',
|
|
Linux => 'lsof',
|
|
Solaris => 'lsof',
|
|
Win32 => '',
|
|
},
|
|
ProcStat => {
|
|
AIX => 'top, ps',
|
|
Darwin => 'top, ps',
|
|
FreeBSD => 'top, ps',
|
|
HPUX => 'top, ps',
|
|
Linux => 'top, ps',
|
|
Solaris => 'top, ps',
|
|
Win32 => 'taskman',
|
|
},
|
|
FileSystemUsage => {
|
|
AIX => 'df',
|
|
Darwin => 'df',
|
|
FreeBSD => 'df',
|
|
HPUX => 'df',
|
|
Linux => 'df',
|
|
Solaris => 'df',
|
|
Win32 => '',
|
|
},
|
|
NetRoute => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'route -n',
|
|
Solaris => '',
|
|
Win32 => '',
|
|
},
|
|
NetInterfaceConfig => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'ifconfig',
|
|
Solaris => 'ifconfig -a',
|
|
Win32 => '',
|
|
},
|
|
NetInterfaceStat => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '/usr/sbin/lanadmin -g mibstats 0, netstat -i',
|
|
Linux => 'ifconfig',
|
|
Solaris => '',
|
|
Win32 => '',
|
|
},
|
|
NetConnection => {
|
|
AIX => '',
|
|
Darwin => '',
|
|
FreeBSD => '',
|
|
HPUX => '',
|
|
Linux => 'netstat',
|
|
Solaris => '',
|
|
Win32 => '',
|
|
},
|
|
Tcp => {
|
|
Linux => 'cat /proc/net/snmp',
|
|
Solaris => 'netstat -s -P tcp',
|
|
},
|
|
);
|
|
|
|
sub warning_comment {
|
|
my $self = shift;
|
|
|
|
return "WARNING: this file was generated by $0
|
|
on $self->{timestamp}.
|
|
Any changes made here will be LOST.";
|
|
}
|
|
|
|
sub c_warning_comment {
|
|
my $self = shift;
|
|
my $comment = $self->warning_comment;
|
|
$comment =~ s/^/ * /mg;
|
|
return <<EOF
|
|
/*****************************************************
|
|
$comment
|
|
*****************************************************/
|
|
EOF
|
|
}
|
|
|
|
sub erl_warning_comment {
|
|
my $self = shift;
|
|
my $comment = $self->warning_comment;
|
|
$comment =~ s/^/% /mg;
|
|
"$comment\n";
|
|
}
|
|
|
|
sub generate {
|
|
my($lang, $dir) = @_ ? @_ : @ARGV;
|
|
|
|
my $mtime = (stat __FILE__)[9];
|
|
|
|
my $cwd = cwd();
|
|
unless (-d $dir) {
|
|
die "Invalid build directory '$dir'";
|
|
}
|
|
|
|
chdir $dir;
|
|
my(%param) = (
|
|
build_dir => $dir,
|
|
mtime => $mtime,
|
|
);
|
|
|
|
my $package = __PACKAGE__ . "::$lang";
|
|
eval "require $package";
|
|
|
|
unless ($package->can('new')) {
|
|
die "unsupported language: $lang";
|
|
}
|
|
$@ = '';
|
|
|
|
my $wrapper = $package->new(%param);
|
|
unless ($wrapper->uptodate($wrapper->sources)) {
|
|
eval {
|
|
$wrapper->start();
|
|
|
|
my $mappings = $wrapper->get_mappings;
|
|
for my $func (@$mappings) {
|
|
$wrapper->generate_class($func);
|
|
}
|
|
|
|
$wrapper->finish;
|
|
};
|
|
}
|
|
die $@ if $@;
|
|
chdir $cwd;
|
|
}
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
return bless {
|
|
timestamp => scalar localtime,
|
|
@_
|
|
}, $class;
|
|
}
|
|
|
|
sub uptodate {
|
|
my $self = shift;
|
|
for my $file (@_) {
|
|
my $mtime = (stat $file)[9];
|
|
if ($mtime > $self->{mtime}) {
|
|
print "$file up-to-date\n";
|
|
}
|
|
else {
|
|
print "$file needs update\n";
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
my(%warning_comment) =
|
|
((map { $_ => \&c_warning_comment } qw(c h java)),
|
|
(map { $_ => \&erl_warning_comment } qw(erl hrl)));
|
|
|
|
sub create {
|
|
my($self, $file) = @_;
|
|
my $handle = SigarWrapper::File->create($file);
|
|
if ($file =~ /\.(\w+)$/) {
|
|
my $comment = $warning_comment{$1};
|
|
$handle->print($self->$comment()) if $comment;
|
|
}
|
|
return $self->{files}->{$file} = $handle;
|
|
}
|
|
|
|
sub start {
|
|
}
|
|
|
|
sub finish {
|
|
my $self = shift;
|
|
while (my($file, $handle) = each %{ $self->{files} }) {
|
|
next unless $handle->opened;
|
|
if ($handle->close) {
|
|
#print "closing $file\n";
|
|
}
|
|
else {
|
|
warn "close($file): $!";
|
|
}
|
|
}
|
|
}
|
|
|
|
my @mappings;
|
|
|
|
sub get_mappings {
|
|
if (@mappings != 0) {
|
|
return \@mappings;
|
|
}
|
|
|
|
while (my($name, $fields) = each %classes) {
|
|
#example: FileSystemUsage -> file_system_usage
|
|
(my $cname = $name) =~ s/([a-z])([A-Z])/$1_$2/g;
|
|
$cname = lc $cname;
|
|
|
|
my $func = {
|
|
name => $name,
|
|
cname => $cname,
|
|
};
|
|
push @mappings, $func;
|
|
|
|
if (($cname =~ /^proc_(\w+)/ and !$proc_no_arg{$1}) ||
|
|
($cname =~ /^thread_cpu/))
|
|
{
|
|
$func->{num_args} = 1;
|
|
$func->{arg_type} = 'sigar_pid_t';
|
|
$func->{arg} = 'pid';
|
|
$func->{is_proc} = 1;
|
|
}
|
|
elsif ($has_name_arg{$name}) {
|
|
$func->{num_args} = 1;
|
|
$func->{arg_type} = 'const char *';
|
|
$func->{arg} = 'name';
|
|
}
|
|
else {
|
|
$func->{num_args} = 0;
|
|
}
|
|
|
|
if ($get_not_impl{$cname}) {
|
|
$func->{has_get} = 0;
|
|
}
|
|
else {
|
|
$func->{has_get} = 1;
|
|
}
|
|
|
|
my $sigar_prefix = $func->{sigar_prefix} = join '_', 'sigar', $cname;
|
|
|
|
$func->{sigar_function} = join '_', $sigar_prefix, 'get';
|
|
|
|
$func->{sigar_type} = join '_', $sigar_prefix, 't';
|
|
|
|
$func->{fields} = $fields;
|
|
|
|
for my $field (@$fields) {
|
|
$field->{type} ||= 'Long';
|
|
}
|
|
}
|
|
|
|
return \@mappings;
|
|
}
|
|
|
|
package SigarWrapper::File;
|
|
|
|
use vars qw(@ISA);
|
|
@ISA = qw(IO::File);
|
|
|
|
my $DEVNULL = '/dev/null';
|
|
my $has_dev_null = -e $DEVNULL;
|
|
|
|
sub println {
|
|
shift->print(@_, "\n");
|
|
}
|
|
|
|
sub create {
|
|
my($class, $file) = @_;
|
|
|
|
my $handle = $class->SUPER::new($file || devnull(), "w") or die "open $file: $!";
|
|
print "generating $file\n" if $file;
|
|
return $handle;
|
|
}
|
|
|
|
sub devnull {
|
|
if ($has_dev_null) {
|
|
return $DEVNULL;
|
|
}
|
|
else {
|
|
return "./nul"; #win32 /dev/null equiv
|
|
}
|
|
}
|
|
|
|
package SigarWrapper::Java;
|
|
|
|
use vars qw(@ISA);
|
|
@ISA = qw(SigarWrapper);
|
|
|
|
my %field_types = (
|
|
Long => "J",
|
|
Double => "D",
|
|
Int => "I",
|
|
Char => "C",
|
|
String => "Ljava/lang/String;",
|
|
);
|
|
|
|
my %init = (
|
|
String => 'null',
|
|
);
|
|
|
|
my %type = (
|
|
String => 'String',
|
|
);
|
|
|
|
#alias
|
|
for my $j (\%field_types, \%init, \%type) {
|
|
$j->{'NetAddress'} = $j->{'String'};
|
|
}
|
|
|
|
#XXX kinda ugly having this here
|
|
#will consider moving elsewhere if there
|
|
#are more cases like this.
|
|
my %extra_code = (
|
|
FileSystem => <<'EOF',
|
|
public static final int TYPE_UNKNOWN = 0;
|
|
public static final int TYPE_NONE = 1;
|
|
public static final int TYPE_LOCAL_DISK = 2;
|
|
public static final int TYPE_NETWORK = 3;
|
|
public static final int TYPE_RAM_DISK = 4;
|
|
public static final int TYPE_CDROM = 5;
|
|
public static final int TYPE_SWAP = 6;
|
|
|
|
public String toString() {
|
|
return this.getDirName();
|
|
}
|
|
EOF
|
|
NetConnection => <<'EOF',
|
|
public native String getTypeString();
|
|
|
|
public native static String getStateString(int state);
|
|
|
|
public String getStateString() {
|
|
return getStateString(this.state);
|
|
}
|
|
EOF
|
|
Mem => <<'EOF',
|
|
public String toString() {
|
|
return
|
|
"Mem: " +
|
|
(this.total / 1024) + "K av, " +
|
|
(this.used / 1024) + "K used, " +
|
|
(this.free / 1024) + "K free";
|
|
}
|
|
EOF
|
|
ResourceLimit => <<'EOF',
|
|
public static native long INFINITY();
|
|
EOF
|
|
Swap => <<'EOF',
|
|
public String toString() {
|
|
return
|
|
"Swap: " +
|
|
(this.total / 1024) + "K av, " +
|
|
(this.used / 1024) + "K used, " +
|
|
(this.free / 1024) + "K free";
|
|
}
|
|
EOF
|
|
ProcState => <<'EOF',
|
|
public static final char SLEEP = 'S';
|
|
public static final char RUN = 'R';
|
|
public static final char STOP = 'T';
|
|
public static final char ZOMBIE = 'Z';
|
|
public static final char IDLE = 'D';
|
|
EOF
|
|
ProcMem => <<'EOF',
|
|
/**
|
|
* @deprecated
|
|
* @see #getResident()
|
|
*/
|
|
public long getRss() { return getResident(); }
|
|
/**
|
|
* @deprecated
|
|
* @see #getSize()
|
|
*/
|
|
public long getVsize() { return getSize(); }
|
|
EOF
|
|
);
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
my $self = $class->SUPER::new(@_);
|
|
$self->{jsrc} = 'org/hyperic/sigar';
|
|
return $self;
|
|
}
|
|
|
|
my $jni_file = 'javasigar_generated';
|
|
|
|
sub sources {
|
|
return map { "$jni_file.$_" } qw(c h);
|
|
}
|
|
|
|
sub start {
|
|
my $self = shift;
|
|
$self->SUPER::start;
|
|
my $jsrc = $self->{jsrc};
|
|
File::Path::mkpath([$jsrc], 0, 0755) unless -d $jsrc;
|
|
$self->{package} = 'org.hyperic.sigar';
|
|
|
|
$self->{cfh} = $self->create("$jni_file.c");
|
|
my $hfh = $self->{hfh} = $self->create("$jni_file.h");
|
|
|
|
my %field_cache;
|
|
my $i = 0;
|
|
while (my($class, $fields) = each %SigarWrapper::classes) {
|
|
next if $field_cache{$class}++;
|
|
print $hfh "#define JSIGAR_FIELDS_\U$class $i\n";
|
|
$i++;
|
|
my $n = 0;
|
|
for my $field (@$fields) {
|
|
my $name = $field->{name};
|
|
print $hfh "# define JSIGAR_FIELDS_\U${class}_${name} $n\n";
|
|
$n++;
|
|
}
|
|
print $hfh "# define JSIGAR_FIELDS_\U${class}_MAX $n\n";
|
|
}
|
|
print $hfh "#define JSIGAR_FIELDS_MAX $i\n";
|
|
}
|
|
|
|
sub jname {
|
|
my $jname = shift;
|
|
#special case for nfs
|
|
return $jname eq 'null' ? "_$jname" : $jname;
|
|
}
|
|
|
|
#using mega-method pattern here
|
|
sub generate_class {
|
|
my($self, $func) = @_;
|
|
|
|
my $cfh = $self->{cfh};
|
|
my $hfh = $self->{hfh};
|
|
|
|
my $class = $func->{name};
|
|
my $cname = $func->{cname};
|
|
|
|
my $java_class = "$self->{package}.$class";
|
|
(my $jni_prefix = "Java.$java_class") =~ s/\./_/g;
|
|
|
|
my $args_proto = "";
|
|
my $args = "";
|
|
my $decl_string = "";
|
|
my $get_string = "";
|
|
my $release_string = "";
|
|
|
|
my $jname = lcfirst $class;
|
|
|
|
if ($func->{num_args} == 1) {
|
|
$args = " $func->{arg}, ";
|
|
if ($func->{is_proc}) {
|
|
$args_proto = ", jlong pid";
|
|
}
|
|
else {
|
|
$args_proto = ", jstring jname";
|
|
$decl_string = "const char *name;";
|
|
$get_string = "name = jname ? JENV->GetStringUTFChars(env, jname, 0) : NULL;";
|
|
$release_string = "if (jname) JENV->ReleaseStringUTFChars(env, jname, name);";
|
|
}
|
|
}
|
|
|
|
my $nativefunc = join '_', $jni_prefix, 'gather';
|
|
|
|
my $proto = join "\n",
|
|
"JNIEXPORT void JNICALL $nativefunc",
|
|
"(JNIEnv *env, jobject obj, jobject sigar_obj$args_proto)";
|
|
|
|
my $jfh = $self->create_jfile($class);
|
|
|
|
print $cfh <<EOF if $func->{has_get};
|
|
|
|
$proto;
|
|
|
|
$proto
|
|
{
|
|
$func->{sigar_type} s;
|
|
int status;
|
|
jclass cls = JENV->GetObjectClass(env, obj);
|
|
$decl_string
|
|
dSIGAR_VOID;
|
|
|
|
$get_string
|
|
|
|
status = $func->{sigar_function}(sigar,${args}&s);
|
|
|
|
$release_string
|
|
|
|
if (status != SIGAR_OK) {
|
|
sigar_throw_error(env, jsigar, status);
|
|
return;
|
|
}
|
|
|
|
EOF
|
|
|
|
my $jargs_proto = 'Sigar sigar';
|
|
my $jargs = 'sigar';
|
|
|
|
if ($func->{is_proc}) {
|
|
$jargs_proto .= ', long pid';
|
|
$jargs .= ", pid";
|
|
}
|
|
elsif ($func->{num_args} == 1) {
|
|
$jargs_proto .= ', String name';
|
|
$jargs .= ", name";
|
|
}
|
|
|
|
my $cache_field_ids = 1;
|
|
|
|
my $uid = 0;
|
|
|
|
for my $field (@{ $func->{fields} }) {
|
|
$uid +=
|
|
SigarWrapper::hash($field->{type}) +
|
|
SigarWrapper::hash($field->{name});
|
|
}
|
|
|
|
print $jfh <<EOF;
|
|
package $self->{package};
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* $class sigar class.
|
|
*/
|
|
public class $class implements java.io.Serializable {
|
|
|
|
private static final long serialVersionUID = ${uid}L;
|
|
|
|
public $class() { }
|
|
|
|
public native void gather($jargs_proto) throws SigarException;
|
|
|
|
/**
|
|
* This method is not intended to be called directly.
|
|
* use Sigar.get$class() instead.
|
|
* \@exception SigarException on failure.
|
|
* \@see $self->{package}.Sigar#get$class
|
|
*/
|
|
static $class fetch($jargs_proto) throws SigarException {
|
|
$class $jname = new $class();
|
|
$jname.gather($jargs);
|
|
return $jname;
|
|
}
|
|
|
|
EOF
|
|
|
|
my(@copy, @tostring);
|
|
my $setter = "JAVA_SIGAR_SET_FIELDS_\U$class";
|
|
my $getter = "JAVA_SIGAR_GET_FIELDS_\U$class";
|
|
my @setter = ("\#define $setter(cls, obj, s)");
|
|
my @getter = ("\#define $getter(obj, s)");
|
|
my $init_define = "JAVA_SIGAR_INIT_FIELDS_\U$class";
|
|
my $field_class_ix = "JSIGAR_FIELDS_\U$class";
|
|
my $field_class_ix = "JSIGAR_FIELDS_\U$class";
|
|
my $field_class_max = $field_class_ix . '_MAX';
|
|
my $field_class = "jsigar->fields[$field_class_ix]";
|
|
|
|
my @init_fields = ("#define $init_define(cls)",
|
|
" if (!$field_class) {",
|
|
" $field_class = ",
|
|
" malloc(sizeof(*$field_class));",
|
|
" $field_class->classref = ",
|
|
" (jclass)JENV->NewGlobalRef(env, cls);",
|
|
" $field_class->ids = ",
|
|
" malloc($field_class_max *",
|
|
" sizeof(*$field_class->ids));");
|
|
|
|
for my $field (@{ $func->{fields} }) {
|
|
my $type = $field->{type};
|
|
my $name = $field->{name};
|
|
my $member = $field->{member} || $name;
|
|
my $desc = $field->{desc} || $name;
|
|
(my $jname = $name) =~ s/_(\w)/\u$1/g;
|
|
my $getter = "get\u$jname";
|
|
$jname = jname($jname);
|
|
my $sig = qq("$field_types{$type}");
|
|
my $set = "JENV->Set${type}Field";
|
|
my $get = "JENV->Get${type}Field";
|
|
|
|
my $field_ix = $field_class_ix . "_\U$name";
|
|
my $get_id = qq|JENV->GetFieldID(env, cls, "$jname", $sig)|;
|
|
my $id_cache = "$field_class->ids[$field_ix]";
|
|
|
|
my $id_lookup = $cache_field_ids ?
|
|
$id_cache : $get_id;
|
|
|
|
push @init_fields,
|
|
" $id_cache = ",
|
|
" $get_id;";
|
|
|
|
push @setter,
|
|
qq| $set(env, obj, $id_lookup, s.$member);|;
|
|
push @getter,
|
|
qq| s.$member = $get(env, obj, $id_lookup);|;
|
|
|
|
my $init = $init{$type} || '0';
|
|
my $jtype = $type{$type} || lcfirst($type);
|
|
my $platforms = SigarWrapper::supported_platforms($field->{plat});
|
|
|
|
print $jfh " $jtype $jname = $init;\n\n";
|
|
push @copy, " copy.$jname = this.$jname;\n";
|
|
push @tostring, $jname;
|
|
|
|
#documentation
|
|
print $jfh " /**\n";
|
|
print $jfh " * Get the $desc.<p>\n";
|
|
print $jfh " * Supported Platforms: $platforms.\n";
|
|
print $jfh " * <p>\n";
|
|
if (my $cmd = ($field->{cmd} || $SigarWrapper::cmds{$class})) {
|
|
print $jfh " * System equivalent commands:<ul>\n";
|
|
for my $p (sort keys %$cmd) {
|
|
print $jfh " * <li> $p: <code>$cmd->{$p}</code><br>\n";
|
|
}
|
|
print $jfh " * </ul>\n";
|
|
}
|
|
print $jfh " * \@return $desc\n";
|
|
print $jfh " */\n";
|
|
|
|
print $jfh " public $jtype $getter() { return $jname; }\n";
|
|
}
|
|
|
|
print $jfh "\n void copyTo($class copy) {\n", @copy, " }\n";
|
|
|
|
my $code = $extra_code{$class};
|
|
if ($code) {
|
|
print $jfh $code;
|
|
}
|
|
|
|
my $num_fields = @tostring;
|
|
print $jfh "\n public Map toMap() {\n";
|
|
print $jfh " Map map = new HashMap();\n";
|
|
for (my $i=0; $i<$num_fields; $i++) {
|
|
my $jfield = $tostring[$i];
|
|
my $sfield = "str${jfield}";
|
|
print $jfh " String $sfield = \n";
|
|
print $jfh " String.valueOf(this.$jfield);\n";
|
|
print $jfh qq{ if (!"-1".equals($sfield))\n};
|
|
print $jfh qq{ map.put("\u$jfield", $sfield);\n};
|
|
}
|
|
print $jfh " return map;\n";
|
|
print $jfh " }\n";
|
|
|
|
if (!$code or $code !~ /toString/) {
|
|
print $jfh "\n public String toString() {\n";
|
|
print $jfh " return toMap().toString();\n";
|
|
print $jfh " }\n";
|
|
}
|
|
|
|
push @init_fields, " }";
|
|
|
|
if ($cache_field_ids) {
|
|
print $hfh join(' \\' . "\n", @init_fields), "\n\n";
|
|
print $cfh "\n\n $init_define(cls);\n\n" if $func->{has_get};
|
|
}
|
|
else {
|
|
print $hfh "#define $init_define(cls)\n";
|
|
}
|
|
|
|
print $hfh join(' \\' . "\n", @setter), "\n\n";
|
|
print $hfh join(' \\' . "\n", @getter), "\n\n";
|
|
print $cfh "\n\n $setter(cls, obj, s);" if $func->{has_get};
|
|
|
|
print $cfh "\n}\n" if $func->{has_get};
|
|
print $jfh "\n}\n";
|
|
|
|
close $jfh;
|
|
}
|
|
|
|
sub finish {
|
|
my $self = shift;
|
|
$self->SUPER::finish;
|
|
}
|
|
|
|
sub create_jfile {
|
|
my($self, $name) = @_;
|
|
my $jsrc = $self->{jsrc};
|
|
my $jfile = "$jsrc/$name.java";
|
|
if (-e "../../src/$jsrc/$name.java") {
|
|
print "skipping $jfile\n";
|
|
#dont generate .java if already exists
|
|
$jfile = undef;
|
|
}
|
|
return $self->create($jfile);
|
|
}
|
|
|
|
package SigarWrapper::Perl;
|
|
|
|
use vars qw(@ISA);
|
|
@ISA = qw(SigarWrapper);
|
|
|
|
my %field_types = (
|
|
Long => "sigar_uint64_t",
|
|
Double => "double",
|
|
Int => "IV",
|
|
Char => "char",
|
|
String => "char *",
|
|
NetAddress => "Sigar::NetAddress",
|
|
);
|
|
|
|
my $xs_file = 'Sigar_generated.xs';
|
|
|
|
sub sources {
|
|
return $xs_file;
|
|
}
|
|
|
|
sub start {
|
|
my $self = shift;
|
|
$self->SUPER::start;
|
|
$self->{xfh} = $self->create($xs_file);
|
|
}
|
|
|
|
sub generate_class {
|
|
my($self, $func) = @_;
|
|
|
|
my $fh = $self->{xfh};
|
|
my $class = $func->{name};
|
|
my $cname = $func->{cname};
|
|
my $perl_class = "Sigar::$class";
|
|
my $proto = 'VALUE obj';
|
|
my $args = 'sigar';
|
|
|
|
if ($func->{num_args} == 1) {
|
|
$args .= ", $func->{arg}";
|
|
}
|
|
|
|
print $fh "\nMODULE = Sigar PACKAGE = Sigar PREFIX = sigar_\n\n";
|
|
|
|
print $fh <<EOF if $func->{has_get};
|
|
$perl_class
|
|
$cname($args)
|
|
Sigar sigar
|
|
EOF
|
|
if ($func->{arg}) {
|
|
print $fh " $func->{arg_type} $func->{arg}\n" if $func->{has_get};
|
|
}
|
|
|
|
print $fh <<EOF if $func->{has_get};
|
|
|
|
PREINIT:
|
|
int status;
|
|
|
|
CODE:
|
|
RETVAL = safemalloc(sizeof(*RETVAL));
|
|
if ((status = $func->{sigar_function}($args, RETVAL)) != SIGAR_OK) {
|
|
SIGAR_CROAK(sigar, "$cname");
|
|
}
|
|
|
|
OUTPUT:
|
|
RETVAL
|
|
EOF
|
|
|
|
print $fh <<EOF;
|
|
|
|
MODULE = Sigar PACKAGE = $perl_class PREFIX = sigar_
|
|
|
|
void
|
|
DESTROY(obj)
|
|
$perl_class obj
|
|
|
|
CODE:
|
|
safefree(obj);
|
|
|
|
EOF
|
|
|
|
for my $field (@{ $func->{fields} }) {
|
|
my $name = $field->{name};
|
|
my $type = $field_types{ $field->{type} };
|
|
|
|
print $fh <<EOF;
|
|
$type
|
|
$name($cname)
|
|
$perl_class $cname
|
|
|
|
CODE:
|
|
RETVAL = $cname->$name;
|
|
|
|
OUTPUT:
|
|
RETVAL
|
|
|
|
EOF
|
|
}
|
|
}
|
|
|
|
sub finish {
|
|
my $self = shift;
|
|
$self->SUPER::finish;
|
|
}
|
|
|
|
package SigarWrapper::Ruby;
|
|
|
|
use vars qw(@ISA);
|
|
@ISA = qw(SigarWrapper);
|
|
|
|
my %field_types = (
|
|
Long => "rb_ll2inum",
|
|
Double => "rb_float_new",
|
|
Int => "rb_int2inum",
|
|
Char => "CHR2FIX",
|
|
String => "rb_str_new2",
|
|
NetAddress => "rb_sigar_net_address_to_s",
|
|
);
|
|
|
|
my $rx_file = 'rbsigar_generated.rx';
|
|
|
|
sub sources {
|
|
return $rx_file;
|
|
}
|
|
|
|
sub start {
|
|
my $self = shift;
|
|
$self->SUPER::start;
|
|
$self->{cfh} = $self->create($rx_file);
|
|
}
|
|
|
|
sub add_method {
|
|
my($self, $class, $name) = @_;
|
|
push @{ $self->{methods}->{$class} }, $name;
|
|
}
|
|
|
|
sub generate_class {
|
|
my($self, $func) = @_;
|
|
|
|
my $fh = $self->{cfh};
|
|
my $class = $func->{name};
|
|
my $cname = $func->{cname};
|
|
my $ruby_class = "rb_cSigar$class";
|
|
my $proto = 'VALUE obj';
|
|
my $args = 'sigar';
|
|
|
|
if ($func->{num_args} == 1) {
|
|
my $arg_type;
|
|
if ($func->{is_proc}) {
|
|
$arg_type = 'OBJ2PID';
|
|
}
|
|
else {
|
|
$arg_type = 'StringValuePtr';
|
|
}
|
|
$proto .= ", VALUE $func->{arg}";
|
|
$args .= ", $arg_type($func->{arg})";
|
|
}
|
|
|
|
print $fh <<EOF if $func->{has_get};
|
|
static VALUE $ruby_class;
|
|
|
|
static VALUE rb_sigar_$cname($proto)
|
|
{
|
|
SIGAR_GET;
|
|
|
|
int status;
|
|
$func->{sigar_type} *RETVAL = malloc(sizeof(*RETVAL));
|
|
|
|
if ((status = $func->{sigar_function}($args, RETVAL)) != SIGAR_OK) {
|
|
free(RETVAL);
|
|
rb_raise(rb_eArgError, "%s", sigar_strerror(sigar, status));
|
|
return Qnil;
|
|
}
|
|
|
|
return Data_Wrap_Struct($ruby_class, 0, rb_sigar_free, RETVAL);
|
|
}
|
|
EOF
|
|
|
|
for my $field (@{ $func->{fields} }) {
|
|
my $name = $field->{name};
|
|
my $type = $field_types{ $field->{type} };
|
|
|
|
$self->add_method($class, $name);
|
|
|
|
print $fh <<EOF;
|
|
static VALUE rb_sigar_${class}_${name}(VALUE self)
|
|
{
|
|
$func->{sigar_type} *$cname;
|
|
Data_Get_Struct(self, $func->{sigar_type}, $cname);
|
|
return $type($cname->$name);
|
|
}
|
|
EOF
|
|
}
|
|
}
|
|
|
|
sub finish {
|
|
my $self = shift;
|
|
|
|
my $fh = $self->{cfh};
|
|
|
|
print $fh "static void rb_sigar_define_module_methods(VALUE rclass)\n{\n";
|
|
|
|
my $mappings = SigarWrapper::get_mappings();
|
|
|
|
for my $func (@$mappings) {
|
|
my $name = $func->{cname};
|
|
my $args = $func->{num_args};
|
|
next unless $func->{has_get};
|
|
print $fh qq{ rb_define_method(rclass, "$name", rb_sigar_$name, $args);\n};
|
|
}
|
|
|
|
for my $class (sort keys %{ $self->{methods} }) {
|
|
my $rclass = "rb_cSigar$class";
|
|
print $fh qq{ $rclass = rb_define_class_under(rclass, "$class", rb_cObject);\n};
|
|
for my $method (@{ $self->{methods}->{$class} }) {
|
|
print $fh qq{ rb_define_method($rclass, "$method", rb_sigar_${class}_$method, 0);\n};
|
|
}
|
|
}
|
|
|
|
print $fh "}\n";
|
|
|
|
$self->SUPER::finish;
|
|
}
|
|
|
|
package SigarWrapper::PHP;
|
|
|
|
use vars qw(@ISA);
|
|
@ISA = qw(SigarWrapper);
|
|
|
|
my %field_types = (
|
|
Long => "RETURN_LONG",
|
|
Double => "RETURN_DOUBLE",
|
|
Int => "RETURN_LONG",
|
|
Char => "RETURN_LONG",
|
|
String => "PHP_SIGAR_RETURN_STRING",
|
|
NetAddress => "PHP_SIGAR_RETURN_NETADDR",
|
|
);
|
|
|
|
my $php_file = 'php_sigar_generated.c';
|
|
|
|
sub sources {
|
|
return $php_file;
|
|
}
|
|
|
|
sub start {
|
|
my $self = shift;
|
|
$self->SUPER::start;
|
|
$self->{cfh} = $self->create($php_file);
|
|
}
|
|
|
|
sub generate_class {
|
|
my($self, $func) = @_;
|
|
|
|
my $cfh = $self->{cfh};
|
|
my $class = $func->{name};
|
|
my $cname = $func->{cname};
|
|
my $php_class = "Sigar::$class";
|
|
my $parse_args = "";
|
|
my $vars = "";
|
|
my $args = 'sigar';
|
|
my $arginfo = $args;
|
|
|
|
if ($func->{num_args} == 1) {
|
|
if ($func->{is_proc}) {
|
|
$parse_args = 'zSIGAR_PARSE_PID;';
|
|
$arginfo .= '_pid';
|
|
$vars = "long $func->{arg};\n";
|
|
}
|
|
else {
|
|
$parse_args .= 'zSIGAR_PARSE_NAME;';
|
|
$arginfo .= '_name';
|
|
$vars = "char *$func->{arg}; int $func->{arg}_len;\n";
|
|
}
|
|
$args .= ", $func->{arg}";
|
|
}
|
|
|
|
my $prefix = "php_$func->{sigar_prefix}_";
|
|
my $functions = $prefix . 'functions';
|
|
my $handlers = $prefix . 'object_handlers';
|
|
my $init = $prefix . 'init';
|
|
|
|
my $ctor = $prefix . 'new';
|
|
|
|
my(@functions);
|
|
|
|
for my $field (@{ $func->{fields} }) {
|
|
my $name = $field->{name};
|
|
my $type = $field_types{ $field->{type} };
|
|
my $method = $prefix . $name;
|
|
|
|
push @functions, { name => $name, me => $method };
|
|
print $cfh <<EOF;
|
|
static PHP_FUNCTION($method)
|
|
{
|
|
$func->{sigar_type} *$cname = ($func->{sigar_type} *)zSIGAR_OBJ;
|
|
$type($cname->$name);
|
|
}
|
|
EOF
|
|
}
|
|
|
|
print $cfh <<EOF;
|
|
static zend_object_handlers $handlers;
|
|
|
|
static zend_object_value $ctor(zend_class_entry *class_type TSRMLS_DC)
|
|
{
|
|
return php_sigar_ctor(php_sigar_obj_dtor,
|
|
&$handlers,
|
|
NULL,
|
|
class_type);
|
|
}
|
|
|
|
static zend_function_entry ${functions}[] = {
|
|
EOF
|
|
|
|
for my $func (@functions) {
|
|
print $cfh " PHP_ME_MAPPING($func->{name}, $func->{me}, NULL)\n";
|
|
}
|
|
|
|
print $cfh <<EOF;
|
|
{NULL, NULL, NULL}
|
|
};
|
|
EOF
|
|
|
|
print $cfh <<EOF;
|
|
static void $init(void)
|
|
{
|
|
zend_class_entry ce;
|
|
|
|
PHP_SIGAR_INIT_HANDLERS($handlers);
|
|
INIT_CLASS_ENTRY(ce, "$php_class", $functions);
|
|
ce.create_object = $ctor;
|
|
zend_register_internal_class(&ce TSRMLS_CC);
|
|
}
|
|
EOF
|
|
|
|
print $cfh <<EOF if $func->{has_get};
|
|
static PHP_FUNCTION($func->{sigar_function})
|
|
{
|
|
int status;
|
|
zSIGAR;
|
|
|
|
$func->{sigar_type} *RETVAL = emalloc(sizeof(*RETVAL));
|
|
$vars
|
|
$parse_args
|
|
|
|
if ((status = $func->{sigar_function}($args, RETVAL)) != SIGAR_OK) {
|
|
efree(RETVAL);
|
|
RETURN_FALSE;
|
|
}
|
|
else {
|
|
php_sigar_obj_new("$php_class", return_value)->ptr = RETVAL;
|
|
}
|
|
}
|
|
EOF
|
|
}
|
|
|
|
sub finish {
|
|
my $self = shift;
|
|
|
|
my $mappings = $self->get_mappings;
|
|
my $cfh = $self->{cfh};
|
|
my $nl = '\\' . "\n";
|
|
|
|
print $cfh "#define PHP_SIGAR_FUNCTIONS $nl";
|
|
for my $func (@$mappings) {
|
|
next unless $func->{has_get};
|
|
#XXX PHP_ME_MAPPING has another arg in 5.2
|
|
print $cfh " PHP_ME_MAPPING($func->{cname}, $func->{sigar_function}, NULL)";
|
|
if ($func == $mappings->[-1]) {
|
|
print $cfh "\n";
|
|
}
|
|
else {
|
|
print $cfh $nl;
|
|
}
|
|
}
|
|
|
|
print $cfh "#define PHP_SIGAR_INIT $nl";
|
|
for my $func (@$mappings) {
|
|
print $cfh " php_$func->{sigar_prefix}_init()";
|
|
if ($func == $mappings->[-1]) {
|
|
print $cfh "\n";
|
|
}
|
|
else {
|
|
print $cfh ";$nl";
|
|
}
|
|
}
|
|
|
|
$self->SUPER::finish;
|
|
}
|
|
|
|
package SigarWrapper::Python;
|
|
|
|
use vars qw(@ISA);
|
|
@ISA = qw(SigarWrapper);
|
|
|
|
my %field_types = (
|
|
Long => "PyLong_FromUnsignedLongLong",
|
|
Double => "PyFloat_FromDouble",
|
|
Int => "PyInt_FromLong",
|
|
Char => "PySigarInt_FromChar",
|
|
String => "PyString_FromString",
|
|
NetAddress => "PySigarString_FromNetAddr",
|
|
);
|
|
|
|
my $c_file = '_sigar_generated.c';
|
|
|
|
sub sources {
|
|
return $c_file;
|
|
}
|
|
|
|
sub start {
|
|
my $self = shift;
|
|
$self->SUPER::start;
|
|
$self->{cfh} = $self->create($c_file);
|
|
}
|
|
|
|
sub pyclass {
|
|
my $class = shift;
|
|
return "Sigar.$class";
|
|
}
|
|
|
|
sub pytype {
|
|
my $class = shift;
|
|
return 'pysigar_PySigar' . $class . 'Type';
|
|
}
|
|
|
|
sub generate_class {
|
|
my($self, $func) = @_;
|
|
|
|
my $cfh = $self->{cfh};
|
|
my $pyclass = pyclass($func->{name});
|
|
my $pytype = pytype($func->{name});
|
|
my $cname = $func->{cname};
|
|
my $parse_args = "";
|
|
my $vars = "";
|
|
my $args = 'sigar';
|
|
|
|
if ($func->{num_args} == 1) {
|
|
if ($func->{is_proc}) {
|
|
$parse_args = 'PySigar_ParsePID;';
|
|
$vars = "long $func->{arg};\n";
|
|
}
|
|
else {
|
|
$parse_args .= 'PySigar_ParseName;';
|
|
$vars = "char *$func->{arg}; int $func->{arg}_len;\n";
|
|
}
|
|
$args .= ", $func->{arg}";
|
|
}
|
|
|
|
my $prefix = "py$func->{sigar_prefix}_";
|
|
my $methods = $prefix . 'methods';
|
|
my $dtor = 'pysigar_free';
|
|
|
|
for my $field (@{ $func->{fields} }) {
|
|
my $name = $field->{name};
|
|
my $type = $field_types{ $field->{type} };
|
|
my $method = $prefix . $name;
|
|
|
|
print $cfh <<EOF;
|
|
static PyObject *$method(PyObject *self, PyObject *args)
|
|
{
|
|
$func->{sigar_type} *$cname = ($func->{sigar_type} *)PySIGAR_OBJ->ptr;
|
|
return $type($cname->$name);
|
|
}
|
|
EOF
|
|
}
|
|
|
|
print $cfh "static PyMethodDef $methods [] = {\n";
|
|
for my $field (@{ $func->{fields} }) {
|
|
my $name = $field->{name};
|
|
print $cfh qq( { "$name", ${prefix}$name, METH_NOARGS, "$name" },\n);
|
|
}
|
|
print $cfh " {NULL}\n};\n";
|
|
|
|
print $cfh <<EOF;
|
|
static PyTypeObject $pytype = {
|
|
PyObject_HEAD_INIT(NULL)
|
|
0, /*ob_size*/
|
|
"$pyclass", /*tp_name*/
|
|
sizeof(PySigarObject), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
pysigar_free, /*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
0, /*tp_getattr*/
|
|
0, /*tp_setattr*/
|
|
0, /*tp_compare*/
|
|
0, /*tp_repr*/
|
|
0, /*tp_as_number*/
|
|
0, /*tp_as_sequence*/
|
|
0, /*tp_as_mapping*/
|
|
0, /*tp_hash */
|
|
0, /*tp_call*/
|
|
0, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
PySigar_TPFLAGS, /*tp_flags*/
|
|
0, /*tp_doc*/
|
|
0, /*tp_traverse*/
|
|
0, /*tp_clear*/
|
|
0, /*tp_richcompare*/
|
|
0, /*tp_weaklistoffset*/
|
|
0, /*tp_iter*/
|
|
0, /*tp_iternext*/
|
|
$methods, /*tp_methods*/
|
|
0, /*tp_members*/
|
|
0, /*tp_getset*/
|
|
0, /*tp_base*/
|
|
0, /*tp_dict*/
|
|
0, /*tp_descr_get*/
|
|
0, /*tp_descr_set*/
|
|
0, /*tp_dictoffset*/
|
|
0, /*tp_init*/
|
|
0, /*tp_alloc*/
|
|
0 /*tp_new*/
|
|
};
|
|
EOF
|
|
|
|
print $cfh <<EOF if $func->{has_get};
|
|
static PyObject *py$func->{sigar_function}(PyObject *self, PyObject *args)
|
|
{
|
|
int status;
|
|
sigar_t *sigar = PySIGAR;
|
|
$func->{sigar_type} *RETVAL = malloc(sizeof(*RETVAL));
|
|
$vars
|
|
$parse_args
|
|
|
|
if ((status = $func->{sigar_function}($args, RETVAL)) != SIGAR_OK) {
|
|
free(RETVAL);
|
|
PySigar_Croak();
|
|
return NULL;
|
|
}
|
|
else {
|
|
PyObject *self = PySigar_new($pytype);
|
|
PySIGAR_OBJ->ptr = RETVAL;
|
|
return self;
|
|
}
|
|
}
|
|
EOF
|
|
}
|
|
|
|
sub finish {
|
|
my $self = shift;
|
|
|
|
my $mappings = $self->get_mappings;
|
|
my $cfh = $self->{cfh};
|
|
my $nl = '\\' . "\n";
|
|
|
|
print $cfh "#define PY_SIGAR_METHODS $nl";
|
|
for my $func (@$mappings) {
|
|
next unless $func->{has_get};
|
|
my $arginfo = $func->{num_args} ? 'METH_VARARGS' : 'METH_NOARGS';
|
|
print $cfh qq( {"$func->{cname}", py$func->{sigar_function}, $arginfo, NULL},);
|
|
if ($func == $mappings->[-1]) {
|
|
print $cfh "\n";
|
|
}
|
|
else {
|
|
print $cfh $nl;
|
|
}
|
|
}
|
|
|
|
print $cfh "#define PY_SIGAR_ADD_TYPES $nl";
|
|
for my $func (@$mappings) {
|
|
my $pyclass = pyclass($func->{name});
|
|
my $pytype = pytype($func->{name});
|
|
print $cfh qq{ PySigar_AddType("$pyclass", $pytype)};
|
|
if ($func == $mappings->[-1]) {
|
|
print $cfh "\n";
|
|
}
|
|
else {
|
|
print $cfh ";$nl";
|
|
}
|
|
}
|
|
|
|
$self->SUPER::finish;
|
|
}
|
|
|
|
package SigarWrapper::Erlang;
|
|
|
|
use vars qw(@ISA);
|
|
@ISA = qw(SigarWrapper);
|
|
|
|
my %field_types = (
|
|
Long => "esigar_encode_ulonglong",
|
|
Double => "esigar_encode_double",
|
|
Int => "esigar_encode_long",
|
|
Char => "esigar_encode_char",
|
|
String => "esigar_encode_string",
|
|
NetAddress => "esigar_encode_netaddr",
|
|
);
|
|
|
|
my $c_file = 'priv/gen/sigar_drv_gen.c';
|
|
my $h_file = 'priv/gen/sigar.hrl';
|
|
my $g_file = 'priv/gen/sigar_gen.hrl';
|
|
|
|
sub sources {
|
|
return $c_file;
|
|
}
|
|
|
|
sub start {
|
|
my $self = shift;
|
|
$self->SUPER::start;
|
|
$self->{cfh} = $self->create($c_file);
|
|
$self->{hfh} = $self->create($h_file);
|
|
$self->{gfh} = $self->create($g_file);
|
|
}
|
|
|
|
sub generate_class {
|
|
my($self, $func) = @_;
|
|
|
|
my $cfh = $self->{cfh};
|
|
my $cname = $func->{cname};
|
|
my $parse_args = "";
|
|
my $vars = "";
|
|
my $args = 'sigar';
|
|
|
|
if ($func->{num_args} == 1) {
|
|
if ($func->{is_proc}) {
|
|
$parse_args = 'pid = esigar_pid_get(sigar, bytes);';
|
|
$vars = "long $func->{arg};\n";
|
|
}
|
|
else {
|
|
$parse_args .= 'name = bytes;';
|
|
$vars = "char *$func->{arg};\n";
|
|
}
|
|
$args .= ", $func->{arg}";
|
|
}
|
|
|
|
my $encoder = "esigar_encode_$cname";
|
|
my $n = scalar @{ $func->{fields} };
|
|
|
|
print $cfh <<EOF;
|
|
static void $encoder(ei_x_buff *x,
|
|
$func->{sigar_type} *$cname)
|
|
{
|
|
ei_x_encode_list_header(x, $n);
|
|
EOF
|
|
|
|
for my $field (@{ $func->{fields} }) {
|
|
my $name = $field->{name};
|
|
my $type = $field_types{ $field->{type} };
|
|
|
|
print $cfh qq{ $type(x, "$name", $cname->$name);\n};
|
|
}
|
|
|
|
print $cfh " ei_x_encode_empty_list(x);\n}\n\n";
|
|
|
|
print $cfh <<EOF if $func->{has_get};
|
|
static int e$func->{sigar_function}(ErlDrvPort port, sigar_t *sigar, char *bytes)
|
|
{
|
|
int status;
|
|
ei_x_buff x;
|
|
$func->{sigar_type} $cname;
|
|
$vars
|
|
$parse_args
|
|
|
|
ESIGAR_NEW(&x);
|
|
if ((status = $func->{sigar_function}($args, &$cname)) == SIGAR_OK) {
|
|
ESIGAR_OK(&x);
|
|
|
|
$encoder(&x, &$cname);
|
|
|
|
ESIGAR_SEND(port, &x);
|
|
}
|
|
else {
|
|
ESIGAR_ERROR(&x, sigar, status);
|
|
}
|
|
return status;
|
|
}
|
|
EOF
|
|
}
|
|
|
|
my(@nongens) =
|
|
qw{net_interface_list net_route_list net_connection_list
|
|
file_system_list cpu_info_list arp_list who_list
|
|
loadavg};
|
|
|
|
sub finish {
|
|
my $self = shift;
|
|
|
|
my $mappings = $self->get_mappings;
|
|
my $cfh = $self->{cfh};
|
|
my $hfh = $self->{hfh};
|
|
my $gfh = $self->{gfh};
|
|
my $ncmd = 1;
|
|
|
|
for my $ngen (@nongens) {
|
|
my $cmd = uc $ngen;
|
|
print $cfh "#define ESIGAR_$cmd $ncmd\n";
|
|
print $hfh "-define($cmd, $ncmd).\n";
|
|
$ncmd++;
|
|
}
|
|
|
|
for my $func (@$mappings) {
|
|
next unless $func->{has_get};
|
|
my $name = $func->{cname};
|
|
my $cmd = uc $name;
|
|
my $nargs = 1 + $func->{num_args};
|
|
print $cfh "#define ESIGAR_$cmd $ncmd\n";
|
|
print $hfh "-define($cmd, $ncmd).\n";
|
|
print $hfh "-export([$name/$nargs]).\n";
|
|
$ncmd++;
|
|
}
|
|
|
|
print $cfh <<EOF;
|
|
|
|
static int esigar_dispatch(ErlDrvPort port, sigar_t *sigar, int cmd, char *bytes) {
|
|
switch (cmd) {
|
|
EOF
|
|
for my $func (@$mappings) {
|
|
next unless $func->{has_get};
|
|
my $name = $func->{cname};
|
|
my $cmd = uc $name;
|
|
my $arg = "";
|
|
if ($func->{num_args}) {
|
|
$arg = ", Arg";
|
|
}
|
|
|
|
print $gfh <<EOF;
|
|
$name({sigar, S}$arg) ->
|
|
do_command(S, ?$cmd$arg).
|
|
|
|
EOF
|
|
print $cfh <<EOF
|
|
case ESIGAR_$cmd:
|
|
return e$func->{sigar_function}(port, sigar, bytes);
|
|
EOF
|
|
}
|
|
print $cfh <<EOF;
|
|
default:
|
|
esigar_notimpl(port, sigar, cmd);
|
|
return SIGAR_ENOTIMPL;
|
|
}
|
|
}
|
|
EOF
|
|
|
|
$self->SUPER::finish;
|
|
}
|
|
|
|
1;
|
|
__END__
|