rdoc: 100% documentation coverage!
[raindrops.git] / lib / raindrops / linux.rb
blob630bfe2a2a1468ba85c77c5541946e1e3511b907
1 # -*- encoding: binary -*-
3 # For reporting TCP ListenStats, users of older \Linux kernels need to ensure
4 # that the the "inet_diag" and "tcp_diag" kernel modules are loaded as they do
5 # not autoload correctly
6 module Raindrops::Linux
8   # The standard proc path for active UNIX domain sockets, feel free to call
9   # String#replace on this if your /proc is mounted in a non-standard location
10   # for whatever reason
11   PROC_NET_UNIX_ARGS = %w(/proc/net/unix)
12   defined?(::Encoding) and PROC_NET_UNIX_ARGS.push({ :encoding => "binary" })
14   # Get ListenStats from an array of +paths+
15   #
16   # Socket state mapping from integer => symbol, based on socket_state
17   # enum from include/linux/net.h in the \Linux kernel:
18   #     typedef enum {
19   #             SS_FREE = 0,              /* not allocated                */
20   #             SS_UNCONNECTED,           /* unconnected to any socket    */
21   #             SS_CONNECTING,            /* in process of connecting     */
22   #             SS_CONNECTED,             /* connected to socket          */
23   #             SS_DISCONNECTING          /* in process of disconnecting  */
24   #     } socket_state;
25   # * SS_CONNECTING maps to ListenStats#active
26   # * SS_CONNECTED maps to ListenStats#queued
27   #
28   # This method may be significantly slower than its tcp_listener_stats
29   # counterpart due to the latter being able to use inet_diag via netlink.
30   # This parses /proc/net/unix as there is no other (known) way
31   # to expose Unix domain socket statistics over netlink.
32   def unix_listener_stats(paths)
33     rv = Hash.new { |h,k| h[k.freeze] = Raindrops::ListenStats.new(0, 0) }
34     paths = paths.map do |path|
35       path = path.dup
36       path.force_encoding(Encoding::BINARY) if defined?(Encoding)
37       rv[path]
38       Regexp.escape(path)
39     end
40     paths = / 00000000 \d+ (\d+)\s+\d+ (#{paths.join('|')})$/n
42     # no point in pread since we can't stat for size on this file
43     File.read(*PROC_NET_UNIX_ARGS).scan(paths) do |s|
44       path = s.last
45       case s.first.to_i
46       when 2 then rv[path].queued += 1
47       when 3 then rv[path].active += 1
48       end
49     end
51     rv
52   end
53   module_function :unix_listener_stats
55 end # Raindrops::Linux