Module: Raindrops::Linux
- Included in:
- Watcher
- Defined in:
- lib/raindrops/linux.rb,
ext/raindrops/linux_inet_diag.c
Constant Summary collapse
- PROC_NET_UNIX_ARGS =
The standard proc path for active UNIX domain sockets, feel free to call String#replace on this if your /proc is mounted in a non-standard location for whatever reason
%w(/proc/net/unix)
Class Method Summary collapse
-
.Raindrops::Linux.tcp_listener_stats([addrs[, sock]]) ⇒ Hash
If specified,
addr
may be a string or array of strings representing listen addresses to filter for. -
.unix_listener_stats(paths = nil) ⇒ Object
Get ListenStats from an array of
paths
.
Class Method Details
.Raindrops::Linux.tcp_listener_stats([addrs[, sock]]) ⇒ Hash
If specified, addr
may be a string or array of strings representing listen addresses to filter for. Returns a hash with given addresses as keys and ListenStats objects as the values or a hash of all addresses.
addrs = %w(0.0.0.0:80 127.0.0.1:8080)
If addr
is nil or not specified, all (IPv4) addresses are returned. If sock
is specified, it should be a Raindrops::InetDiagSock object.
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 |
# File 'ext/raindrops/linux_inet_diag.c', line 587
static VALUE tcp_listener_stats(int argc, VALUE *argv, VALUE self)
{
VALUE *ary;
long i;
VALUE rv = rb_hash_new();
struct nogvl_args args;
VALUE addrs, sock;
rb_scan_args(argc, argv, "02", &addrs, &sock);
/*
* allocating page_size instead of OP_LEN since we'll reuse the
* buffer for recvmsg() later, we already checked for
* OPLEN <= page_size at initialization
*/
args.iov[2].iov_len = OPLEN;
args.iov[2].iov_base = alloca(page_size);
args.table = NULL;
if (NIL_P(sock))
sock = rb_funcall(cIDSock, id_new, 0);
args.fd = my_fileno(sock);
switch (TYPE(addrs)) {
case T_STRING:
rb_hash_aset(rv, addrs, tcp_stats(&args, addrs));
return rv;
case T_ARRAY:
ary = RARRAY_PTR(addrs);
i = RARRAY_LEN(addrs);
if (i == 1) {
rb_hash_aset(rv, *ary, tcp_stats(&args, *ary));
return rv;
}
for (; --i >= 0; ary++) {
union any_addr check;
parse_addr(&check, *ary);
rb_hash_aset(rv, *ary, Qtrue);
}
/* fall through */
case T_NIL:
args.table = st_init_strtable();
gen_bytecode_all(&args.iov[2]);
break;
default:
rb_raise(rb_eArgError,
"addr must be an array of strings, a string, or nil");
}
nl_errcheck(rb_thread_io_blocking_region(diag, &args, args.fd));
st_foreach(args.table, NIL_P(addrs) ? st_to_hash : st_AND_hash, rv);
st_free_table(args.table);
/* let GC deal with corner cases */
if (argc < 2) rb_io_close(sock);
return rv;
}
|
.unix_listener_stats(paths = nil) ⇒ Object
Get ListenStats from an array of paths
Socket state mapping from integer => symbol, based on socket_state enum from include/linux/net.h in the Linux kernel:
typedef enum {
SS_FREE = 0, /* not allocated */
SS_UNCONNECTED, /* unconnected to any socket */
SS_CONNECTING, /* in process of connecting */
SS_CONNECTED, /* connected to socket */
SS_DISCONNECTING /* in process of disconnecting */
} socket_state;
-
SS_CONNECTING maps to ListenStats#queued
-
SS_CONNECTED maps to ListenStats#active
This method may be significantly slower than its tcp_listener_stats counterpart due to the latter being able to use inet_diag via netlink. This parses /proc/net/unix as there is no other (known) way to expose Unix domain socket statistics over netlink.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/raindrops/linux.rb', line 39 def unix_listener_stats(paths = nil) rv = Hash.new { |h,k| h[k.freeze] = Raindrops::ListenStats.new(0, 0) } if nil == paths paths = [ '[^\n]+' ] else paths = paths.map do |path| path = path.dup path.force_encoding(Encoding::BINARY) if defined?(Encoding) if File.symlink?(path) link = path path = Pathname.new(link).realpath.to_s rv[link] = rv[path] # vivify ListenerStats else rv[path] # vivify ListenerStats end Regexp.escape(path) end end paths = /^\w+: \d+ \d+ (\d+) \d+ (\d+)\s+\d+ (#{paths.join('|')})$/n # no point in pread since we can't stat for size on this file File.read(*PROC_NET_UNIX_ARGS).scan(paths) do |s| path = s[-1] case s[0] when "00000000" # client sockets case s[1].to_i when 2 then rv[path].queued += 1 when 3 then rv[path].active += 1 end else # listeners, vivify empty stats rv[path] end end rv end |