Merge branch 'erlang'
This commit is contained in:
commit
0008c56119
|
@ -1625,6 +1625,13 @@ $comment
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub erl_warning_comment {
|
||||||
|
my $self = shift;
|
||||||
|
my $comment = $self->warning_comment;
|
||||||
|
$comment =~ s/^/% /mg;
|
||||||
|
"$comment\n";
|
||||||
|
}
|
||||||
|
|
||||||
sub generate {
|
sub generate {
|
||||||
my($lang, $dir) = @_ ? @_ : @ARGV;
|
my($lang, $dir) = @_ ? @_ : @ARGV;
|
||||||
|
|
||||||
|
@ -1689,7 +1696,9 @@ sub uptodate {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
my(%warning_comment) = map { $_ => \&c_warning_comment } qw(c h java);
|
my(%warning_comment) =
|
||||||
|
((map { $_ => \&c_warning_comment } qw(c h java)),
|
||||||
|
(map { $_ => \&erl_warning_comment } qw(erl hrl)));
|
||||||
|
|
||||||
sub create {
|
sub create {
|
||||||
my($self, $file) = @_;
|
my($self, $file) = @_;
|
||||||
|
@ -2777,6 +2786,168 @@ sub finish {
|
||||||
$self->SUPER::finish;
|
$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 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;
|
||||||
|
}
|
||||||
|
|
||||||
#XXX not currently supporting netware
|
#XXX not currently supporting netware
|
||||||
package SigarWrapper::Netware;
|
package SigarWrapper::Netware;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
all:
|
||||||
|
perl -Mlib=.. -MSigarWrapper -e generate Erlang .
|
||||||
|
cd src && make
|
||||||
|
cd c_src && make
|
||||||
|
|
||||||
|
shell:
|
||||||
|
make all
|
||||||
|
erl -pa ebin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cd src && make clean
|
||||||
|
cd c_src && make clean
|
|
@ -0,0 +1,40 @@
|
||||||
|
## SIGAR driver for Erlang
|
||||||
|
|
||||||
|
If you're not already familar with sigar, have a look at the [SIGAR Wiki](http://sigar.hyperic.com).
|
||||||
|
|
||||||
|
Also helpful: **../../include/sigar.h**, **../*/examples** and
|
||||||
|
**../java/src/org/hyperic/sigar/cmd/** to get an idea of what you can do.
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
The other bindings/* inline the libsigar sources by default, haven't done that yet for erl.
|
||||||
|
So, you'll need a libsigar to link against, one of:
|
||||||
|
|
||||||
|
Ant build:
|
||||||
|
|
||||||
|
cd ../java ; ant
|
||||||
|
ln -s sigar-bin/lib/libsigar-amd64-linux.so sigar-lib/lib/libsigar.so
|
||||||
|
|
||||||
|
Or, download release binary created by the ant build:
|
||||||
|
|
||||||
|
curl -o priv/libsigar.so http://svn.hyperic.org/projects/sigar_bin/dist/SIGAR_1_6_2/lib/libsigar-amd64-linux.so
|
||||||
|
|
||||||
|
Or, top-level autotools build (WIP):
|
||||||
|
|
||||||
|
cd ../.. ; ./autogen.sh && ./configure && make install
|
||||||
|
|
||||||
|
Once you have a libsigar in place, just run **make** and have a look at the **examples/**.
|
||||||
|
|
||||||
|
Note that the majority of the driver code is generated by **../SigarWrapper.pm** and output to **priv/gen**.
|
||||||
|
|
||||||
|
### ToDo/Help Wanted
|
||||||
|
|
||||||
|
* Fill out the **examples/** - currently weaksauce in part due to me having just a few hours w/ Erlang
|
||||||
|
|
||||||
|
* Build system - doubt the current will work anywhere cept Linux
|
||||||
|
|
||||||
|
* EUnit
|
||||||
|
|
||||||
|
* Other stuff Erlangers know that I don't
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
GCC = gcc
|
||||||
|
OTP_ROOT = $(shell ./check_otp -root)
|
||||||
|
EI_ROOT = $(shell ./check_otp -ei)
|
||||||
|
EI_LIB = $(EI_ROOT)/lib
|
||||||
|
EI_INC = $(EI_ROOT)/include
|
||||||
|
SIGAR_LIB = ../../java/sigar-bin/lib
|
||||||
|
LDFLAGS = -shared -L${EI_LIB} -lei -lpthread -L${SIGAR_LIB} -L../priv -lsigar
|
||||||
|
SRCS = sigar_drv.c
|
||||||
|
OUTPUT = ../priv/sigar_drv.so
|
||||||
|
CFLAGS = -Wall -fPIC -I../../../include -I${OTP_ROOT}/usr/include -I${EI_INC} -o ${OUTPUT}
|
||||||
|
|
||||||
|
all:
|
||||||
|
${GCC} ${SRCS} ${LDFLAGS} ${CFLAGS}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf ${OUTPUT} ../priv/gen/*.c ../priv/gen/*.hrl
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#copied from jungerl
|
||||||
|
if [ "$1" == "-root" -o "$1" == "" ]; then
|
||||||
|
erl -noinput -eval 'io:format("~s~n", [code:root_dir()]), halt(0).'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" == "-ei" -o "$1" == "" ]; then
|
||||||
|
erl -noinput -eval \
|
||||||
|
'case code:lib_dir("erl_interface") of
|
||||||
|
{error, bad_name} ->
|
||||||
|
io:format("not found~n", []),
|
||||||
|
halt(1);
|
||||||
|
LibDir ->
|
||||||
|
io:format("~s~n", [LibDir]),
|
||||||
|
halt(0)
|
||||||
|
end.'
|
||||||
|
fi
|
|
@ -0,0 +1,394 @@
|
||||||
|
#include <erl_driver.h>
|
||||||
|
#include <ei.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "sigar.h"
|
||||||
|
#include "sigar_fileinfo.h"
|
||||||
|
#include "sigar_format.h"
|
||||||
|
#include "sigar_ptql.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ErlDrvPort port;
|
||||||
|
sigar_t *sigar;
|
||||||
|
} sigar_drv_t;
|
||||||
|
|
||||||
|
static ErlDrvData start(ErlDrvPort port, char *cmd) {
|
||||||
|
sigar_drv_t *sd = (sigar_drv_t *)driver_alloc(sizeof(*sd));
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = sigar_open(&sd->sigar);
|
||||||
|
if (status != SIGAR_OK) {
|
||||||
|
sd->sigar = NULL;
|
||||||
|
driver_failure_posix(port, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
sd->port = port;
|
||||||
|
|
||||||
|
return (ErlDrvData)sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stop(ErlDrvData handle) {
|
||||||
|
sigar_drv_t *driver_data = (sigar_drv_t *)handle;
|
||||||
|
if (driver_data->sigar) {
|
||||||
|
sigar_close(driver_data->sigar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SIGAR_64BIT
|
||||||
|
#define str2pid(value) strtoull(value, NULL, 10)
|
||||||
|
#else
|
||||||
|
#define str2pid(value) strtoul(value, NULL, 10)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static sigar_pid_t esigar_pid_get(sigar_t *sigar, char *pid)
|
||||||
|
{
|
||||||
|
if (isdigit(*pid)) {
|
||||||
|
return str2pid(pid);
|
||||||
|
}
|
||||||
|
else if ((*pid == '$') && (*(pid + 1) == '$')) {
|
||||||
|
return sigar_pid_get(sigar);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* XXX cache queries */
|
||||||
|
sigar_ptql_query_t *query;
|
||||||
|
sigar_ptql_error_t error;
|
||||||
|
int status =
|
||||||
|
sigar_ptql_query_create(&query, (char *)pid, &error);
|
||||||
|
|
||||||
|
if (status == SIGAR_OK) {
|
||||||
|
sigar_pid_t qpid;
|
||||||
|
|
||||||
|
status = sigar_ptql_query_find_process(sigar, query, &qpid);
|
||||||
|
sigar_ptql_query_destroy(query);
|
||||||
|
if (status == SIGAR_OK) {
|
||||||
|
return qpid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esigar_to_strlist(ei_x_buff *x,
|
||||||
|
char **data, unsigned long number)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
|
ei_x_encode_list_header(x, number);
|
||||||
|
for (i=0; i<number; i++) {
|
||||||
|
ei_x_encode_string(x, data[i]);
|
||||||
|
}
|
||||||
|
ei_x_encode_empty_list(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*esigar_encoder_func_t)(ei_x_buff *x, void *data);
|
||||||
|
|
||||||
|
static void esigar_to_list(ei_x_buff *x,
|
||||||
|
char *data, unsigned long number, int size,
|
||||||
|
esigar_encoder_func_t encoder)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
|
ei_x_encode_list_header(x, number);
|
||||||
|
for (i=0; i<number; i++, data += size) {
|
||||||
|
encoder(x, data);
|
||||||
|
}
|
||||||
|
ei_x_encode_empty_list(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ESIGAR_NEW(x) \
|
||||||
|
ei_x_new_with_version(x)
|
||||||
|
|
||||||
|
#define ESIGAR_OK(x) \
|
||||||
|
ei_x_encode_tuple_header(x, 2); \
|
||||||
|
ei_x_encode_atom(x, "ok")
|
||||||
|
|
||||||
|
#define ESIGAR_ERROR(x, sigar, status) \
|
||||||
|
ei_x_encode_tuple_header(x, 2); \
|
||||||
|
ei_x_encode_atom(x, "error"); \
|
||||||
|
ei_x_encode_string(x, sigar_strerror(sigar, status))
|
||||||
|
|
||||||
|
#define ESIGAR_SEND(p, x) \
|
||||||
|
driver_output(port, (x)->buff, (x)->index); \
|
||||||
|
ei_x_free(x)
|
||||||
|
|
||||||
|
#define esigar_encode_long(x, k, v) \
|
||||||
|
ei_x_encode_tuple_header(x, 2); \
|
||||||
|
ei_x_encode_atom(x, k); \
|
||||||
|
ei_x_encode_long(x, v)
|
||||||
|
|
||||||
|
#define esigar_encode_ulonglong(x, k, v) \
|
||||||
|
ei_x_encode_tuple_header(x, 2); \
|
||||||
|
ei_x_encode_atom(x, k); \
|
||||||
|
ei_x_encode_ulonglong(x, v)
|
||||||
|
|
||||||
|
#define esigar_encode_char(x, k, v) \
|
||||||
|
ei_x_encode_tuple_header(x, 2); \
|
||||||
|
ei_x_encode_atom(x, k); \
|
||||||
|
ei_x_encode_char(x, v)
|
||||||
|
|
||||||
|
#define esigar_encode_string(x, k, v) \
|
||||||
|
ei_x_encode_tuple_header(x, 2); \
|
||||||
|
ei_x_encode_atom(x, k); \
|
||||||
|
ei_x_encode_string(x, v)
|
||||||
|
|
||||||
|
#define esigar_encode_double(x, k, v) \
|
||||||
|
ei_x_encode_tuple_header(x, 2); \
|
||||||
|
ei_x_encode_atom(x, k); \
|
||||||
|
ei_x_encode_double(x, v)
|
||||||
|
|
||||||
|
static void esigar_encode_net_address(ei_x_buff *x, const char *key,
|
||||||
|
sigar_net_address_t *address)
|
||||||
|
{
|
||||||
|
char buf[SIGAR_INET6_ADDRSTRLEN];
|
||||||
|
sigar_net_address_to_string(NULL, address, buf);
|
||||||
|
esigar_encode_string(x, key, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define esigar_encode_netaddr(x, k, v) \
|
||||||
|
esigar_encode_net_address(x, k, &v)
|
||||||
|
|
||||||
|
static void esigar_notimpl(ErlDrvPort port, sigar_t *sigar, int cmd)
|
||||||
|
{
|
||||||
|
ei_x_buff x;
|
||||||
|
|
||||||
|
ESIGAR_NEW(&x);
|
||||||
|
ESIGAR_ERROR(&x, sigar, SIGAR_ENOTIMPL);
|
||||||
|
ESIGAR_SEND(port, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "../priv/gen/sigar_drv_gen.c"
|
||||||
|
|
||||||
|
static void esigar_loadavg_get(ErlDrvPort port, sigar_t *sigar)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
ei_x_buff x;
|
||||||
|
sigar_loadavg_t loadavg;
|
||||||
|
|
||||||
|
ESIGAR_NEW(&x);
|
||||||
|
|
||||||
|
if ((status = sigar_loadavg_get(sigar, &loadavg)) == SIGAR_OK) {
|
||||||
|
ESIGAR_OK(&x);
|
||||||
|
|
||||||
|
ei_x_encode_list_header(&x, 3);
|
||||||
|
ei_x_encode_double(&x, loadavg.loadavg[0]);
|
||||||
|
ei_x_encode_double(&x, loadavg.loadavg[1]);
|
||||||
|
ei_x_encode_double(&x, loadavg.loadavg[2]);
|
||||||
|
ei_x_encode_empty_list(&x);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESIGAR_ERROR(&x, sigar, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESIGAR_SEND(port, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esigar_net_connection_list_get(ErlDrvPort port, sigar_t *sigar,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
ei_x_buff x;
|
||||||
|
sigar_net_connection_list_t list;
|
||||||
|
|
||||||
|
ei_x_new_with_version(&x);
|
||||||
|
|
||||||
|
if ((status = sigar_net_connection_list_get(sigar, &list, flags) == SIGAR_OK)) {
|
||||||
|
ESIGAR_OK(&x);
|
||||||
|
|
||||||
|
esigar_to_list(&x,
|
||||||
|
(char *)&list.data[0], list.number,
|
||||||
|
sizeof(*list.data),
|
||||||
|
(esigar_encoder_func_t)esigar_encode_net_connection);
|
||||||
|
|
||||||
|
sigar_net_connection_list_destroy(sigar, &list);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESIGAR_ERROR(&x, sigar, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESIGAR_SEND(port, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esigar_net_interface_list_get(ErlDrvPort port, sigar_t *sigar)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
ei_x_buff x;
|
||||||
|
sigar_net_interface_list_t list;
|
||||||
|
|
||||||
|
ei_x_new_with_version(&x);
|
||||||
|
|
||||||
|
if ((status = sigar_net_interface_list_get(sigar, &list) == SIGAR_OK)) {
|
||||||
|
ESIGAR_OK(&x);
|
||||||
|
|
||||||
|
esigar_to_strlist(&x, list.data, list.number);
|
||||||
|
sigar_net_interface_list_destroy(sigar, &list);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESIGAR_ERROR(&x, sigar, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESIGAR_SEND(port, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esigar_file_system_list_get(ErlDrvPort port, sigar_t *sigar)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
ei_x_buff x;
|
||||||
|
sigar_file_system_list_t list;
|
||||||
|
|
||||||
|
ei_x_new_with_version(&x);
|
||||||
|
|
||||||
|
if ((status = sigar_file_system_list_get(sigar, &list) == SIGAR_OK)) {
|
||||||
|
ESIGAR_OK(&x);
|
||||||
|
|
||||||
|
esigar_to_list(&x,
|
||||||
|
(char *)&list.data[0], list.number,
|
||||||
|
sizeof(*list.data),
|
||||||
|
(esigar_encoder_func_t)esigar_encode_file_system);
|
||||||
|
|
||||||
|
sigar_file_system_list_destroy(sigar, &list);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESIGAR_ERROR(&x, sigar, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESIGAR_SEND(port, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esigar_net_route_list_get(ErlDrvPort port, sigar_t *sigar)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
ei_x_buff x;
|
||||||
|
sigar_net_route_list_t list;
|
||||||
|
|
||||||
|
ei_x_new_with_version(&x);
|
||||||
|
|
||||||
|
if ((status = sigar_net_route_list_get(sigar, &list) == SIGAR_OK)) {
|
||||||
|
ESIGAR_OK(&x);
|
||||||
|
|
||||||
|
esigar_to_list(&x,
|
||||||
|
(char *)&list.data[0], list.number,
|
||||||
|
sizeof(*list.data),
|
||||||
|
(esigar_encoder_func_t)esigar_encode_net_route);
|
||||||
|
|
||||||
|
sigar_net_route_list_destroy(sigar, &list);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESIGAR_ERROR(&x, sigar, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESIGAR_SEND(port, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esigar_cpu_info_list_get(ErlDrvPort port, sigar_t *sigar)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
ei_x_buff x;
|
||||||
|
sigar_cpu_info_list_t list;
|
||||||
|
|
||||||
|
ei_x_new_with_version(&x);
|
||||||
|
|
||||||
|
if ((status = sigar_cpu_info_list_get(sigar, &list) == SIGAR_OK)) {
|
||||||
|
ESIGAR_OK(&x);
|
||||||
|
|
||||||
|
esigar_to_list(&x,
|
||||||
|
(char *)&list.data[0], list.number,
|
||||||
|
sizeof(*list.data),
|
||||||
|
(esigar_encoder_func_t)esigar_encode_cpu_info);
|
||||||
|
|
||||||
|
sigar_cpu_info_list_destroy(sigar, &list);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESIGAR_ERROR(&x, sigar, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESIGAR_SEND(port, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void esigar_who_list_get(ErlDrvPort port, sigar_t *sigar)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
ei_x_buff x;
|
||||||
|
sigar_who_list_t list;
|
||||||
|
|
||||||
|
ei_x_new_with_version(&x);
|
||||||
|
|
||||||
|
if ((status = sigar_who_list_get(sigar, &list) == SIGAR_OK)) {
|
||||||
|
ESIGAR_OK(&x);
|
||||||
|
|
||||||
|
esigar_to_list(&x,
|
||||||
|
(char *)&list.data[0], list.number,
|
||||||
|
sizeof(*list.data),
|
||||||
|
(esigar_encoder_func_t)esigar_encode_who);
|
||||||
|
|
||||||
|
sigar_who_list_destroy(sigar, &list);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESIGAR_ERROR(&x, sigar, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESIGAR_SEND(port, &x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void outputv(ErlDrvData handle, ErlIOVec *ev) {
|
||||||
|
sigar_drv_t *sd = (sigar_drv_t *)handle;
|
||||||
|
sigar_t *sigar = sd->sigar;
|
||||||
|
ErlDrvPort port = sd->port;
|
||||||
|
ErlDrvBinary *data = ev->binv[1];
|
||||||
|
int cmd = data->orig_bytes[0];
|
||||||
|
|
||||||
|
switch(cmd) {
|
||||||
|
case ESIGAR_NET_CONNECTION_LIST:
|
||||||
|
esigar_net_connection_list_get(port, sigar,
|
||||||
|
data->orig_bytes[1]);
|
||||||
|
break;
|
||||||
|
case ESIGAR_NET_INTERFACE_LIST:
|
||||||
|
esigar_net_interface_list_get(port, sigar);
|
||||||
|
break;
|
||||||
|
case ESIGAR_NET_ROUTE_LIST:
|
||||||
|
esigar_net_route_list_get(port, sigar);
|
||||||
|
break;
|
||||||
|
case ESIGAR_FILE_SYSTEM_LIST:
|
||||||
|
esigar_file_system_list_get(port, sigar);
|
||||||
|
break;
|
||||||
|
case ESIGAR_CPU_INFO_LIST:
|
||||||
|
esigar_cpu_info_list_get(port, sigar);
|
||||||
|
break;
|
||||||
|
case ESIGAR_WHO_LIST:
|
||||||
|
esigar_who_list_get(port, sigar);
|
||||||
|
break;
|
||||||
|
case ESIGAR_LOADAVG:
|
||||||
|
esigar_loadavg_get(port, sigar);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
esigar_dispatch(port, sigar, cmd, &data->orig_bytes[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ErlDrvEntry sigar_driver_entry = {
|
||||||
|
NULL, /* init */
|
||||||
|
start, /* startup */
|
||||||
|
stop, /* shutdown */
|
||||||
|
NULL, /* output */
|
||||||
|
NULL, /* ready_input */
|
||||||
|
NULL, /* ready_output */
|
||||||
|
"sigar_drv", /* name of the driver */
|
||||||
|
NULL, /* finish */
|
||||||
|
NULL, /* handle */
|
||||||
|
NULL, /* control */
|
||||||
|
NULL, /* timeout */
|
||||||
|
outputv, /* outputv */
|
||||||
|
NULL, /* ready_async */
|
||||||
|
NULL, /* flush */
|
||||||
|
NULL, /* call */
|
||||||
|
NULL, /* event */
|
||||||
|
ERL_DRV_EXTENDED_MARKER, /* ERL_DRV_EXTENDED_MARKER */
|
||||||
|
ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MAJOR_VERSION */
|
||||||
|
ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MINOR_VERSION */
|
||||||
|
ERL_DRV_FLAG_USE_PORT_LOCKING /* ERL_DRV_FLAGs */
|
||||||
|
};
|
||||||
|
|
||||||
|
DRIVER_INIT(sigar_driver) {
|
||||||
|
return &sigar_driver_entry;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
*.beam
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env escript
|
||||||
|
|
||||||
|
-include(sigar).
|
||||||
|
|
||||||
|
main(_) ->
|
||||||
|
{ok, S} = sigar:start(),
|
||||||
|
{ok, FsList} = sigar:file_system_list(S),
|
||||||
|
lists:map(
|
||||||
|
fun(Fs) ->
|
||||||
|
io:format("~s ~n", [sigar:get_value(dir_name, Fs)]) end,
|
||||||
|
FsList),
|
||||||
|
sigar:stop(S).
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env escript
|
||||||
|
|
||||||
|
-include(sigar).
|
||||||
|
|
||||||
|
main(_) ->
|
||||||
|
{ok, S} = sigar:start(),
|
||||||
|
{ok, Mem} = sigar:mem(S),
|
||||||
|
io:format("\tTotal\tUsed\tFree~n"),
|
||||||
|
io:format("Mem: "),
|
||||||
|
lists:map(
|
||||||
|
fun(K) ->
|
||||||
|
io:format("~w\t", [sigar:get_value(K, Mem)/1024]) end,
|
||||||
|
[total, used, free]),
|
||||||
|
io:format("~n"),
|
||||||
|
{ok, Swap} = sigar:swap(S),
|
||||||
|
io:format("Swap: "),
|
||||||
|
lists:map(
|
||||||
|
fun(K) ->
|
||||||
|
io:format("~w\t", [sigar:get_value(K, Swap)/1024]) end,
|
||||||
|
[total, used, free]),
|
||||||
|
io:format("~n"),
|
||||||
|
io:format("RAM: ~wMB~n", [sigar:get_value(ram, Mem)]),
|
||||||
|
sigar:stop(S).
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
#!/usr/bin/env escript
|
||||||
|
|
||||||
|
-include(sigar).
|
||||||
|
|
||||||
|
main(_) ->
|
||||||
|
{ok, S} = sigar:start(),
|
||||||
|
{ok, Names} = sigar:net_interface_list(S),
|
||||||
|
lists:map(
|
||||||
|
fun(K) ->
|
||||||
|
{ok, Ifconfig} = sigar:net_interface_config(S, K),
|
||||||
|
io:format("~s ~s~n", [K, sigar:get_value(address, Ifconfig)]) end,
|
||||||
|
Names),
|
||||||
|
sigar:stop(S).
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env escript
|
||||||
|
|
||||||
|
-include(sigar).
|
||||||
|
|
||||||
|
main(_) ->
|
||||||
|
{ok, S} = sigar:start(),
|
||||||
|
{ok, Mem} = sigar:proc_mem(S, "$$"),
|
||||||
|
io:format("Size\tResident~n"),
|
||||||
|
lists:map(
|
||||||
|
fun(K) ->
|
||||||
|
io:format("~w\t", [sigar:get_value(K, Mem)/1024]) end,
|
||||||
|
[size, resident]),
|
||||||
|
io:format("~n"),
|
||||||
|
sigar:stop(S).
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/env escript
|
||||||
|
|
||||||
|
-include(sigar).
|
||||||
|
|
||||||
|
main(_) ->
|
||||||
|
{ok, S} = sigar:start(),
|
||||||
|
case sigar:loadavg(S) of
|
||||||
|
{ok, Avg} ->
|
||||||
|
lists:map(
|
||||||
|
fun(A) ->
|
||||||
|
io:format("~w% ", [A]) end,
|
||||||
|
Avg);
|
||||||
|
{error, Err} ->
|
||||||
|
Err
|
||||||
|
end,
|
||||||
|
io:format("~n"),
|
||||||
|
sigar:stop(S).
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env escript
|
||||||
|
|
||||||
|
-include(sigar).
|
||||||
|
|
||||||
|
main(_) ->
|
||||||
|
{ok, S} = sigar:start(),
|
||||||
|
{ok, List} = sigar:who_list(S),
|
||||||
|
lists:map(
|
||||||
|
fun(Who) ->
|
||||||
|
lists:map(
|
||||||
|
fun(K) ->
|
||||||
|
io:format("~s\t", [sigar:get_value(K, Who)]) end,
|
||||||
|
[user, device, host]),
|
||||||
|
io:format("~n")
|
||||||
|
end, List),
|
||||||
|
sigar:stop(S).
|
|
@ -0,0 +1 @@
|
||||||
|
*.so
|
|
@ -0,0 +1,2 @@
|
||||||
|
*.c
|
||||||
|
*.hrl
|
|
@ -0,0 +1,11 @@
|
||||||
|
ERLC=erlc
|
||||||
|
EBIN=../ebin
|
||||||
|
INCLUDE=../include
|
||||||
|
EFLAGS=-I ${INCLUDE} -o ${EBIN}
|
||||||
|
SRCS=`ls *.erl`
|
||||||
|
|
||||||
|
all:
|
||||||
|
${ERLC} ${EFLAGS} ${SRCS}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf ${EBIN}/*.beam
|
|
@ -0,0 +1,87 @@
|
||||||
|
-module(sigar).
|
||||||
|
|
||||||
|
% generated by SigarWrapper.pm
|
||||||
|
-include("../priv/gen/sigar.hrl").
|
||||||
|
|
||||||
|
-export([start/0, stop/1, get_value/2]).
|
||||||
|
|
||||||
|
% handrolled wrappers
|
||||||
|
-export([loadavg/1,
|
||||||
|
net_connection_list/2,
|
||||||
|
net_interface_list/1,
|
||||||
|
net_route_list/1,
|
||||||
|
file_system_list/1,
|
||||||
|
cpu_info_list/1,
|
||||||
|
who_list/1]).
|
||||||
|
|
||||||
|
-define(NETCONN_CLIENT, 0x01).
|
||||||
|
-define(NETCONN_SERVER, 0x02).
|
||||||
|
|
||||||
|
-define(SIGAR_NETCONN_TCP, 0x10).
|
||||||
|
-define(SIGAR_NETCONN_UDP, 0x20).
|
||||||
|
-define(SIGAR_NETCONN_RAW, 0x40).
|
||||||
|
-define(SIGAR_NETCONN_UNIX, 0x80).
|
||||||
|
|
||||||
|
start() ->
|
||||||
|
case load_driver() of
|
||||||
|
ok ->
|
||||||
|
S = open_port({spawn, 'sigar_drv'}, [binary]),
|
||||||
|
{ok, {sigar, S}};
|
||||||
|
{error, Err} ->
|
||||||
|
Msg = erl_ddll:format_error(Err),
|
||||||
|
{error, Msg}
|
||||||
|
end.
|
||||||
|
|
||||||
|
% handrolled wrappers
|
||||||
|
loadavg({sigar, S}) ->
|
||||||
|
do_command(S, ?LOADAVG).
|
||||||
|
|
||||||
|
net_connection_list({sigar, S}, F) ->
|
||||||
|
do_command(S, ?NET_CONNECTION_LIST, F).
|
||||||
|
|
||||||
|
net_interface_list({sigar, S}) ->
|
||||||
|
do_command(S, ?NET_INTERFACE_LIST).
|
||||||
|
|
||||||
|
net_route_list({sigar, S}) ->
|
||||||
|
do_command(S, ?NET_ROUTE_LIST).
|
||||||
|
|
||||||
|
file_system_list({sigar, S}) ->
|
||||||
|
do_command(S, ?FILE_SYSTEM_LIST).
|
||||||
|
|
||||||
|
cpu_info_list({sigar, S}) ->
|
||||||
|
do_command(S, ?CPU_INFO_LIST).
|
||||||
|
|
||||||
|
who_list({sigar, S}) ->
|
||||||
|
do_command(S, ?WHO_LIST).
|
||||||
|
|
||||||
|
% generated by SigarWrapper.pm
|
||||||
|
-include("../priv/gen/sigar_gen.hrl").
|
||||||
|
|
||||||
|
% XXX must be a better way
|
||||||
|
get_value(Key, List) ->
|
||||||
|
case lists:keysearch(Key,1,List) of
|
||||||
|
false ->
|
||||||
|
1;
|
||||||
|
{ value, {Key, N} } ->
|
||||||
|
N
|
||||||
|
end.
|
||||||
|
|
||||||
|
stop({sigar, S}) ->
|
||||||
|
unlink(S),
|
||||||
|
port_close(S).
|
||||||
|
|
||||||
|
load_driver() ->
|
||||||
|
Dir = filename:join([filename:dirname(code:which(sigar)), "..", "priv"]),
|
||||||
|
erl_ddll:load(Dir, "sigar_drv").
|
||||||
|
|
||||||
|
do_command(S, C) ->
|
||||||
|
port_command(S, [C]),
|
||||||
|
receive
|
||||||
|
{S, {data, Bin}} -> binary_to_term(Bin)
|
||||||
|
end.
|
||||||
|
|
||||||
|
do_command(S, C, A) ->
|
||||||
|
port_command(S, [C, A]),
|
||||||
|
receive
|
||||||
|
{S, {data, Bin}} -> binary_to_term(Bin)
|
||||||
|
end.
|
Loading…
Reference in New Issue