use strict; use File::Path; my $package = 'org.hyperic.sigar'; my %platforms = ( A => "AIX", D => "Darwin", F => "FreeBSD", H => "HPUX", L => "Linux", S => "Solaris", W => "Win32", ); 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; } #this script generates jni code and java classes for the following table my %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', }, }, ], Swap => [ { name => 'total', type => 'Long', desc => 'Total system swap', plat => '*', cmd => { AIX => 'lsps -s', Darwin => '', 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 => '', }, }, ], 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 => 'total', type => 'Long', desc => 'Total system cpu time', plat => '*' }, ], CpuInfo => [ { name => 'vendor', type => 'String', desc => 'CPU vendor id', plat => 'AFLHSW' }, { name => 'model', type => 'String', desc => 'CPU model', plat => 'AFLHSW' }, { name => 'mhz', type => 'Int', desc => 'CPU speed', plat => 'AFHLSW' }, { name => 'cache_size', type => 'Long', desc => 'CPU cache size', plat => 'AL' }, ], 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 => '*' }, ], 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 => 'AHLSW' }, { 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 => '*' }, ], 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 => 'type', type => 'Int', desc => 'File system type', plat => '*' }, { name => 'flags', type => 'Long', desc => 'File system flags', plat => '*' }, ], FileSystemUsage => [ { name => 'total', type => 'Long', desc => 'Total bytes of filesystem', plat => '*' }, { name => 'free', type => 'Long', desc => 'Total free bytes on filesystem', plat => '*' }, { name => 'used', type => 'Long', desc => 'Total used bytes on filesystem', plat => '*' }, { name => 'avail', type => 'Long', desc => 'Total free bytes 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 => 'Long', desc => '', plat => '' }, { name => 'use_percent', type => 'Double', desc => 'Percent of disk used', 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 => '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 => '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' }, ], 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 => '' }, ], 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', }, ], 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', }, ], 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 %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 => '', }, ); my %jfields = ( Long => "J", Double => "D", Int => "I", Char => "C", String => "Ljava/lang/String;", ); my %pfields = ( Long => "sigar_uint64_t", Double => "double", Int => "IV", Char => "char", String => "char *", NetAddress => "Sigar::NetAddress", ); $jfields{'NetAddress'} = $jfields{'String'}; my %jinit = ( String => 'null', ); my %jtype = ( String => 'String', ); #alias for my $j (\%jfields, \%jinit, \%jtype) { $j->{'NetAddress'} = $j->{'String'}; } my %func_alias = ( ); my $cfile = 'javasigar_generated.c'; my $hfile = 'javasigar_generated.h'; my $pfile = 'Sigar_generated.xs'; my $dfile = 'javasigar_generated.def'; my $build_src = $ARGV[0] or die "usage: $0 build_directory"; if (! -d $build_src) { die "$build_src: $!"; } if ((stat $0)[9] < (stat "$build_src/$cfile")[9]) { print "$cfile unchanged\n"; exit; } print "generating $cfile\n"; chdir $build_src; my $jsrc = 'org/hyperic/sigar'; mkpath([$jsrc], 0, 0755) unless -d $jsrc; open CFH, ">$cfile" or die "open $cfile: $!"; open HFH, ">$hfile" or die "open $hfile: $!"; open PFH, ">$pfile" or die "open $pfile: $!"; open DFH, ">$dfile" or die "open $dfile: $!"; my $datestamp = scalar localtime; my $warning = < <<'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 ); my %has_name_arg = map { $_, 1 } qw(FileSystemUsage 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 who cpu_info file_system); #list funcs only my %field_cache; my $i = 0; while (my($class, $fields) = each %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"; my $DEVNULL = '/dev/null'; my $has_dev_null = -e $DEVNULL; while (my($name, $fields) = each %classes) { my $java_class = "$package.$name"; (my $jni_prefix = "Java.$java_class") =~ s/\./_/g; my $class = $name; my $cname; my $args_proto = ""; my($arg, $arg_type); my $args = ""; my $is_proc = 0; my $decl_string = ""; my $get_string = ""; my $release_string = ""; my $jname = lcfirst $name; #example: FileSystemUsage -> file_system_usage ($cname = $name) =~ s/([a-z])([A-Z])/$1_$2/g; $cname = lc $cname; if ($cname =~ /^proc_(\w+)/ or $cname =~ /^thread_cpu/) { unless ($proc_no_arg{$1}) { $args_proto = ", jlong pid"; $arg_type = 'sigar_pid_t'; $arg = 'pid'; $args = " $arg, "; $is_proc = 1; } } elsif ($has_name_arg{$name}) { #hallo freulien $args_proto = ", jstring jname"; $arg_type = 'const char *'; $decl_string = "const char *name;"; $get_string = "name = JENV->GetStringUTFChars(env, jname, 0);"; $release_string = "JENV->ReleaseStringUTFChars(env, jname, name);"; $arg = 'name'; $args = " $arg, "; } my $sigar_prefix = join '_', 'sigar', $cname; my $sigar_function = join '_', $sigar_prefix, 'get'; $sigar_function = $func_alias{$sigar_function} || $sigar_function; my $sigar_type = join '_', $sigar_prefix, 't'; my $nativefunc = join '_', $jni_prefix, 'gather'; my $proto = join "\n", "JNIEXPORT void JNICALL $nativefunc", "(JNIEnv *env, jobject obj, jobject sigar_obj$args_proto)"; my $jfile; if (-e "../../src/$jsrc/$name.java") { print "skipping $jfile\n"; #dont generate .java if already exists if ($has_dev_null) { $jfile = $DEVNULL; } else { $jfile = "$jsrc/nul"; #win32 /dev/null equiv } } else { $jfile = "$jsrc/$name.java"; } open JFH, ">$jfile" or die "open $jfile: $!"; print JFH $warning; my $impl = ! $get_not_impl{$cname}; print DFH $nativefunc, "\n" if $impl; print CFH <GetObjectClass(env, obj); $decl_string dSIGAR_VOID; $get_string status = $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 ($is_proc) { $jargs_proto .= ', long pid'; $jargs .= ", pid"; } elsif ($has_name_arg{$name}) { $jargs_proto .= ', String name'; $jargs .= ", name"; } my $cache_field_ids = 1; print JFH <classref = ", " (jclass)JENV->NewGlobalRef(env, cls);", " $field_class->ids = ", " malloc($field_class_max *", " sizeof(*$field_class->ids));"); my $perl_class = "Sigar::$class"; if (0) { #insert into Sigar.xs (my $perl_typedef = $perl_class) =~ s/:/_/g; print "typedef $sigar_type * $perl_typedef;\n"; } elsif (0) { #insert into typemap print "$perl_class T_PTROBJ\n"; } print PFH "\nMODULE = Sigar PACKAGE = Sigar PREFIX = sigar_\n\n"; my $xs_args = 'sigar'; if ($arg) { $xs_args .= ", $arg"; } print PFH <{type} || 'Long'; my $name = $field->{name}; my $member = $field->{member} || $name; my $desc = $field->{desc} || $name; (my $jname = $name) =~ s/_(\w)/\u$1/g; my $sig = qq("$jfields{$type}"); my $set = "JENV->Set${type}Field"; print PFH <$name; OUTPUT: RETVAL EOF 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 @macro, qq| $set(env, obj, $id_lookup, s.$member);|; my $init = $jinit{$type} || '0'; my $jtype = $jtype{$type} || lcfirst($type); my $platforms = 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.

\n"; print JFH " * Supported Platforms: $platforms.\n"; print JFH " *

\n"; if (my $cmd = ($field->{cmd} || $cmds{$class})) { print JFH " * System equivalent commands:

    \n"; for my $p (sort keys %$cmd) { print JFH " *
  • $p: $cmd->{$p}
    \n"; } print JFH " *
\n"; } print JFH " * \@return $desc\n"; print JFH " */\n"; print JFH " public $jtype get\u$jname() { return $jname; }\n"; } print JFH "\n void copyTo($name copy) {\n", @copy, " }\n"; my $code = $extra_code{$name}; 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 $impl; } else { print HFH "#define $init_define(cls)\n"; } print HFH join(' \\' . "\n", @macro), "\n\n"; print CFH "\n\n $define(cls, obj, s);" if $impl; print CFH "\n}\n" if $impl; print JFH "\n}\n"; close JFH; } my $jsigar = "../../src/jni/javasigar.c"; my(%alias) = (x => 'Sigar'); open JSIGAR, $jsigar or die "open $jsigar: $!"; while () { next unless /SIGAR_JNI([a-z]?)\(([A-Za-z_]+)\)/; my $class = ""; if ($1) { $class = $alias{$1} . "_"; } print DFH "Java_org_hyperic_sigar_$class$2\n"; } close CFH; close DFH;