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.
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 |
# File 'ext/raindrops/linux_inet_diag.c', line 625
static VALUE tcp_listener_stats(int argc, VALUE *argv, VALUE self)
{
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: {
long i;
long len = RARRAY_LEN(addrs);
VALUE cur;
if (len == 1) {
cur = rb_ary_entry(addrs, 0);
rb_hash_aset(rv, cur, tcp_stats(&args, cur));
return rv;
}
for (i = 0; i < len; i++) {
union any_addr check;
VALUE cur = rb_ary_entry(addrs, i);
parse_addr(&check, cur);
rb_hash_aset(rv, cur, 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 |