Hello community,

here is the log from the commit of package rubygem-raindrops for 
openSUSE:Factory checked in at 2017-03-31 15:07:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-raindrops (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-raindrops.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-raindrops"

Fri Mar 31 15:07:58 2017 rev:2 rq:482291 version:0.18.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-raindrops/rubygem-raindrops.changes      
2016-09-21 18:47:41.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.rubygem-raindrops.new/rubygem-raindrops.changes 
2017-03-31 15:07:59.265106423 +0200
@@ -1,0 +2,48 @@
+Thu Mar 23 05:35:23 UTC 2017 - co...@suse.com
+
+- updated to version 0.18.0
+ see installed NEWS
+
+  === raindrops 0.18.0 / 2017-03-23 02:44 UTC
+  
+    The most notable feature of this release is the addition of
+    FreeBSD and OpenBSD TCP_INFO support.  This includes the
+    Raindrops::TCP for portably mapping TCP state names to
+    platform-dependent numeric values:
+  
+      https://bogomips.org/raindrops/Raindrops.html#TCP
+  
+    Thanks to Jeremy Evans and Simon Eskildsen on the
+    unicorn-pub...@bogomips.org mailing list for inspiring
+    these changes to raindrops.
+  
+    There's also a few internal cleanups, and documentation
+    improvements, including some fixes to the largely-forgotten
+    Raindrops::Aggreage::PMQ class:
+  
+      https://bogomips.org/raindrops/Raindrops/Aggregate/PMQ.html
+  
+    20 changes since 0.17.0:
+  
+          test_inet_diag_socket: fix Fixnum deprecation warning
+          TODO: add item for IPv6 breakage
+          ext: fix documentation for C ext-defined classes
+          TCP_Info: custom documentation for #get!
+          TypedData C-API conversion
+          test_watcher: disable test correctly when aggregate is missing
+          tcp_info: support this struct under FreeBSD
+          define Raindrops::TCP hash for TCP states
+          linux_inet_diag: reduce stack usage and simplify
+          avoid reading errno repeatedly
+          aggregate/pmq: avoid false sharing of lock buffers
+          aggregate/pmq: remove io-extra requirement
+          aggregate/pmq: avoid File#stat allocation
+          Merge remote-tracking branch 'origin/freebsd'
+          Merge remote-tracking branch 'origin/aggregate-pmq'
+          doc: remove private email support address
+          doc: update location of TCP_INFO-related stuff
+          build: avoid olddoc for building the RubyGem
+          doc: document Raindrops::TCP hash
+          aggregate/pmq: update version numbers for Ruby and Linux
+
+-------------------------------------------------------------------

Old:
----
  raindrops-0.17.0.gem

New:
----
  raindrops-0.18.0.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-raindrops.spec ++++++
--- /var/tmp/diff_new_pack.g7PCqC/_old  2017-03-31 15:07:59.841025001 +0200
+++ /var/tmp/diff_new_pack.g7PCqC/_new  2017-03-31 15:07:59.845024436 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-raindrops
 #
-# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,12 +24,12 @@
 #
 
 Name:           rubygem-raindrops
-Version:        0.17.0
+Version:        0.18.0
 Release:        0
 %define mod_name raindrops
 %define mod_full_name %{mod_name}-%{version}
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-BuildRequires:  %{rubydevel}
+BuildRequires:  %{rubydevel >= 1.9.3}
 BuildRequires:  %{rubygem gem2rpm}
 BuildRequires:  ruby-macros >= 5
 Url:            https://bogomips.org/raindrops/

++++++ raindrops-0.17.0.gem -> raindrops-0.18.0.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.document new/.document
--- old/.document       2016-07-31 17:20:21.000000000 +0200
+++ new/.document       2017-03-23 03:45:38.000000000 +0100
@@ -4,4 +4,4 @@
 lib
 ext/raindrops/raindrops.c
 ext/raindrops/linux_inet_diag.c
-ext/raindrops/linux_tcp_info.c
+ext/raindrops/tcp_info.c
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.manifest new/.manifest
--- old/.manifest       2016-07-31 17:20:21.000000000 +0200
+++ new/.manifest       2017-03-23 03:45:38.000000000 +0100
@@ -22,10 +22,10 @@
 examples/zbatery.conf.rb
 ext/raindrops/extconf.rb
 ext/raindrops/linux_inet_diag.c
-ext/raindrops/linux_tcp_info.c
 ext/raindrops/my_fileno.h
 ext/raindrops/raindrops.c
 ext/raindrops/raindrops_atomic.h
+ext/raindrops/tcp_info.c
 lib/raindrops.rb
 lib/raindrops/aggregate.rb
 lib/raindrops/aggregate/last_data_recv.rb
@@ -49,11 +49,11 @@
 test/test_linux_all_tcp_listen_stats_leak.rb
 test/test_linux_ipv6.rb
 test/test_linux_middleware.rb
-test/test_linux_tcp_info.rb
 test/test_middleware.rb
 test/test_middleware_unicorn.rb
 test/test_middleware_unicorn_ipv6.rb
 test/test_raindrops.rb
 test/test_raindrops_gc.rb
 test/test_struct.rb
+test/test_tcp_info.rb
 test/test_watcher.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.olddoc.yml new/.olddoc.yml
--- old/.olddoc.yml     2016-07-31 17:20:21.000000000 +0200
+++ new/.olddoc.yml     2017-03-23 03:45:38.000000000 +0100
@@ -3,7 +3,6 @@
 git_url: git://bogomips.org/raindrops.git
 rdoc_url: https://bogomips.org/raindrops/
 public_email: raindrops-pub...@bogomips.org
-private_email: raindr...@bogomips.org
 ml_url:
 - https://bogomips.org/raindrops-public/
 - http://ou63pmih66umazou.onion/raindrops-public
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/GIT-VERSION-FILE new/GIT-VERSION-FILE
--- old/GIT-VERSION-FILE        2016-07-31 17:20:21.000000000 +0200
+++ new/GIT-VERSION-FILE        2017-03-23 03:45:38.000000000 +0100
@@ -1 +1 @@
-GIT_VERSION = 0.17.0
+GIT_VERSION = 0.18.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/GIT-VERSION-GEN new/GIT-VERSION-GEN
--- old/GIT-VERSION-GEN 2016-07-31 17:20:21.000000000 +0200
+++ new/GIT-VERSION-GEN 2017-03-23 03:45:38.000000000 +0100
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v0.17.0
+DEF_VER=v0.18.0
 
 LF='
 '
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/LATEST new/LATEST
--- old/LATEST  2016-07-31 17:20:21.000000000 +0200
+++ new/LATEST  2017-03-23 03:45:38.000000000 +0100
@@ -1,17 +1,42 @@
-=== raindrops 0.17.0 - rack 2.x updates / 2016-07-31 15:19 UTC
+=== raindrops 0.18.0 / 2017-03-23 02:44 UTC
 
-  This release features minor updates to support rack 2.x
-  while maintaining support for rack 1.2 and later.
-  As a result, Ruby 1.8.6 compatibility is gone, but
-  Ruby 1.8.7 probably still works, for now.
-
-  There's also a minor warning fix, doc updates, and
-  the homepage now supports HTTPS (HTTP remains supported)
-
-  5 changes since raindrops 0.16.0:
-        drop Rack::Utils.bytesize dependency
-        gemspec: bump Rack dependency
-        linux_inet_diag: GCC attribute format check
-        use HTTPS and move homepage to https://bogomips.org/raindrops/
-        examples: add yahns config, zbatery is abandoned
+  The most notable feature of this release is the addition of
+  FreeBSD and OpenBSD TCP_INFO support.  This includes the
+  Raindrops::TCP for portably mapping TCP state names to
+  platform-dependent numeric values:
+
+    https://bogomips.org/raindrops/Raindrops.html#TCP
+
+  Thanks to Jeremy Evans and Simon Eskildsen on the
+  unicorn-pub...@bogomips.org mailing list for inspiring
+  these changes to raindrops.
+
+  There's also a few internal cleanups, and documentation
+  improvements, including some fixes to the largely-forgotten
+  Raindrops::Aggreage::PMQ class:
+
+    https://bogomips.org/raindrops/Raindrops/Aggregate/PMQ.html
+
+  20 changes since 0.17.0:
+
+        test_inet_diag_socket: fix Fixnum deprecation warning
+        TODO: add item for IPv6 breakage
+        ext: fix documentation for C ext-defined classes
+        TCP_Info: custom documentation for #get!
+        TypedData C-API conversion
+        test_watcher: disable test correctly when aggregate is missing
+        tcp_info: support this struct under FreeBSD
+        define Raindrops::TCP hash for TCP states
+        linux_inet_diag: reduce stack usage and simplify
+        avoid reading errno repeatedly
+        aggregate/pmq: avoid false sharing of lock buffers
+        aggregate/pmq: remove io-extra requirement
+        aggregate/pmq: avoid File#stat allocation
+        Merge remote-tracking branch 'origin/freebsd'
+        Merge remote-tracking branch 'origin/aggregate-pmq'
+        doc: remove private email support address
+        doc: update location of TCP_INFO-related stuff
+        build: avoid olddoc for building the RubyGem
+        doc: document Raindrops::TCP hash
+        aggregate/pmq: update version numbers for Ruby and Linux
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/NEWS new/NEWS
--- old/NEWS    2016-07-31 17:20:21.000000000 +0200
+++ new/NEWS    2017-03-23 03:45:38.000000000 +0100
@@ -1,3 +1,45 @@
+=== raindrops 0.18.0 / 2017-03-23 02:44 UTC
+
+  The most notable feature of this release is the addition of
+  FreeBSD and OpenBSD TCP_INFO support.  This includes the
+  Raindrops::TCP for portably mapping TCP state names to
+  platform-dependent numeric values:
+
+    https://bogomips.org/raindrops/Raindrops.html#TCP
+
+  Thanks to Jeremy Evans and Simon Eskildsen on the
+  unicorn-pub...@bogomips.org mailing list for inspiring
+  these changes to raindrops.
+
+  There's also a few internal cleanups, and documentation
+  improvements, including some fixes to the largely-forgotten
+  Raindrops::Aggreage::PMQ class:
+
+    https://bogomips.org/raindrops/Raindrops/Aggregate/PMQ.html
+
+  20 changes since 0.17.0:
+
+        test_inet_diag_socket: fix Fixnum deprecation warning
+        TODO: add item for IPv6 breakage
+        ext: fix documentation for C ext-defined classes
+        TCP_Info: custom documentation for #get!
+        TypedData C-API conversion
+        test_watcher: disable test correctly when aggregate is missing
+        tcp_info: support this struct under FreeBSD
+        define Raindrops::TCP hash for TCP states
+        linux_inet_diag: reduce stack usage and simplify
+        avoid reading errno repeatedly
+        aggregate/pmq: avoid false sharing of lock buffers
+        aggregate/pmq: remove io-extra requirement
+        aggregate/pmq: avoid File#stat allocation
+        Merge remote-tracking branch 'origin/freebsd'
+        Merge remote-tracking branch 'origin/aggregate-pmq'
+        doc: remove private email support address
+        doc: update location of TCP_INFO-related stuff
+        build: avoid olddoc for building the RubyGem
+        doc: document Raindrops::TCP hash
+        aggregate/pmq: update version numbers for Ruby and Linux
+
 === raindrops 0.17.0 - rack 2.x updates / 2016-07-31 15:19 UTC
 
   This release features minor updates to support rack 2.x
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/README new/README
--- old/README  2016-07-31 17:20:21.000000000 +0200
+++ new/README  2017-03-23 03:45:38.000000000 +0100
@@ -58,7 +58,8 @@
 
 See Raindrops::Middleware and Raindrops::LastDataRecv documentation for
 use Rack servers.  The entire library is fully-documented and we are
-responsive on the mailing list (mailto:raindrops-pub...@bogomips.org) if
+responsive on the publically archived mailing list
+(mailto:raindrops-pub...@bogomips.org) if
 you have any questions or comments.
 
 == Development
@@ -88,9 +89,13 @@
 == Contact
 
 All feedback (bug reports, user/development discussion, patches, pull
-requests) go to the mailing list: mailto:raindrops-pub...@bogomips.org
+requests) go to the publically archived mailing list:
+mailto:raindrops-pub...@bogomips.org
 
 Mailing list archives are available over HTTPS and NNTP:
 
 * https://bogomips.org/raindrops-public/
 * nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
+
+Since archives are public, scrub sensitive information and
+use anonymity tools such as Tor or Mixmaster if you deem necessary.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/TODO new/TODO
--- old/TODO    2016-07-31 17:20:21.000000000 +0200
+++ new/TODO    2017-03-23 03:45:38.000000000 +0100
@@ -1,2 +1,3 @@
+* fix IPv6 inet_diag reporting for Raindrops::Middleware
 * pure Ruby version for non-forking servers (patches welcome!)
 * unix_diag and udp_diag support
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/raindrops/extconf.rb new/ext/raindrops/extconf.rb
--- old/ext/raindrops/extconf.rb        2016-07-31 17:20:21.000000000 +0200
+++ new/ext/raindrops/extconf.rb        2017-03-23 03:45:38.000000000 +0100
@@ -1,4 +1,5 @@
 require 'mkmf'
+require 'shellwords'
 
 dir_config('atomic_ops')
 have_func('mmap', 'sys/mman.h') or abort 'mmap() not found'
@@ -6,9 +7,110 @@
 
 $CPPFLAGS += " -D_GNU_SOURCE "
 have_func('mremap', 'sys/mman.h')
-have_header('linux/tcp.h')
+headers = %w(sys/types.h netdb.h string.h sys/socket.h netinet/in.h)
+if have_header('linux/tcp.h')
+  headers << 'linux/tcp.h'
+else
+  %w(netinet/tcp.h netinet/tcp_fsm.h).each { |h|
+    have_header(h, headers) and headers << h
+  }
+end
 
 $CPPFLAGS += " -D_BSD_SOURCE "
+
+if have_type("struct tcp_info", headers)
+  %w(
+    tcpi_state
+    tcpi_ca_state
+    tcpi_retransmits
+    tcpi_probes
+    tcpi_backoff
+    tcpi_options
+    tcpi_snd_wscale
+    tcpi_rcv_wscale
+    tcpi_rto
+    tcpi_ato
+    tcpi_snd_mss
+    tcpi_rcv_mss
+    tcpi_unacked
+    tcpi_sacked
+    tcpi_lost
+    tcpi_retrans
+    tcpi_fackets
+    tcpi_last_data_sent
+    tcpi_last_ack_sent
+    tcpi_last_data_recv
+    tcpi_last_ack_recv
+    tcpi_pmtu
+    tcpi_rcv_ssthresh
+    tcpi_rtt
+    tcpi_rttvar
+    tcpi_snd_ssthresh
+    tcpi_snd_cwnd
+    tcpi_advmss
+    tcpi_reordering
+    tcpi_rcv_rtt
+    tcpi_rcv_space
+    tcpi_total_retrans
+    tcpi_snd_wnd
+    tcpi_snd_bwnd
+    tcpi_snd_nxt
+    tcpi_rcv_nxt
+    tcpi_toe_tid
+    tcpi_snd_rexmitpack
+    tcpi_rcv_ooopack
+    tcpi_snd_zerowin
+  ).each do |field|
+    cfunc = "tcp_info_#{field}"
+    if have_struct_member('struct tcp_info', field, headers)
+      func_body = <<EOF
+static VALUE #{cfunc}(VALUE self)
+{
+       struct tcp_info *info = DATA_PTR(self);
+       return UINT2NUM((uint32_t)info->#{field});
+}
+EOF
+      func_body.delete!("\n")
+      $defs << "-DCFUNC_#{cfunc}=#{Shellwords.shellescape(func_body)}"
+    else
+      func_body = "static inline void #{cfunc}(void) {}"
+      $defs << "-DCFUNC_#{cfunc}=#{Shellwords.shellescape(func_body)}"
+      cfunc = 'rb_f_notimplement'.freeze
+    end
+    rbmethod = %Q("#{field.sub(/\Atcpi_/, ''.freeze)}")
+    $defs << "-DDEFINE_METHOD_tcp_info_#{field}=" \
+            "#{Shellwords.shellescape(
+                %Q[rb_define_method(cTCP_Info,#{rbmethod},#{cfunc},0)])}"
+  end
+  tcp_state_map = {
+    ESTABLISHED: %w(TCP_ESTABLISHED TCPS_ESTABLISHED),
+    SYN_SENT: %w(TCP_SYN_SENT TCPS_SYN_SENT),
+    SYN_RECV: %w(TCP_SYN_RECV TCPS_SYN_RECEIVED),
+    FIN_WAIT1: %w(TCP_FIN_WAIT1 TCPS_FIN_WAIT_1),
+    FIN_WAIT2: %w(TCP_FIN_WAIT2 TCPS_FIN_WAIT_2),
+    TIME_WAIT: %w(TCP_TIME_WAIT TCPS_TIME_WAIT),
+    CLOSE: %w(TCP_CLOSE TCPS_CLOSED),
+    CLOSE_WAIT: %w(TCP_CLOSE_WAIT TCPS_CLOSE_WAIT),
+    LAST_ACK: %w(TCP_LAST_ACK TCPS_LAST_ACK),
+    LISTEN: %w(TCP_LISTEN TCPS_LISTEN),
+    CLOSING: %w(TCP_CLOSING TCPS_CLOSING),
+  }
+  nstate = 0
+  tcp_state_map.each do |state, try|
+    try.each do |os_name|
+      have_const(os_name, headers) or next
+      tcp_state_map[state] = os_name
+      nstate += 1
+    end
+  end
+  if nstate == tcp_state_map.size
+    $defs << '-DRAINDROPS_TCP_STATES_ALL_KNOWN=1'
+    tcp_state_map.each do |state, name|
+      $defs << "-DRAINDROPS_TCP_#{state}=#{name}"
+    end
+  end
+end
+
 have_func("getpagesize", "unistd.h")
 have_func('rb_thread_blocking_region')
 have_func('rb_thread_io_blocking_region')
@@ -53,4 +155,5 @@
 
   apt-get install libatomic-ops-dev
 SRC
+create_header # generate extconf.h to avoid excessively long command-line
 create_makefile('raindrops_ext')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/raindrops/linux_inet_diag.c 
new/ext/raindrops/linux_inet_diag.c
--- old/ext/raindrops/linux_inet_diag.c 2016-07-31 17:20:21.000000000 +0200
+++ new/ext/raindrops/linux_inet_diag.c 2017-03-23 03:45:38.000000000 +0100
@@ -233,80 +233,70 @@
 
 static struct listen_stats *stats_for(st_table *table, struct inet_diag_msg *r)
 {
-       char *key, *port, *old_key;
+       char *host, *key, *port, *old_key;
        size_t alloca_len;
        struct listen_stats *stats;
-       socklen_t keylen;
+       socklen_t hostlen;
        socklen_t portlen = (socklen_t)sizeof("65535");
-       union any_addr sa;
-       socklen_t len = sizeof(struct sockaddr_storage);
-       int rc;
-       int flags = NI_NUMERICHOST | NI_NUMERICSERV;
+       int n;
+       const void *src = r->id.idiag_src;
 
-       switch ((sa.ss.ss_family = r->idiag_family)) {
+       switch (r->idiag_family) {
        case AF_INET: {
-               sa.in.sin_port = r->id.idiag_sport;
-               sa.in.sin_addr.s_addr = r->id.idiag_src[0];
-               keylen = INET_ADDRSTRLEN;
-               alloca_len = keylen + 1 + portlen;
-               key = alloca(alloca_len);
-               key[keylen] = 0; /* will be ':' later */
-               port = key + keylen + 1;
-               rc = getnameinfo(&sa.sa, len,
-                                key, keylen, port, portlen, flags);
+               hostlen = INET_ADDRSTRLEN;
+               alloca_len = hostlen + portlen;
+               host = key = alloca(alloca_len);
                break;
                }
        case AF_INET6: {
-               sa.in6.sin6_port = r->id.idiag_sport;
-               memcpy(&sa.in6.sin6_addr, &r->id.idiag_src, sizeof(__be32[4]));
-               keylen = INET6_ADDRSTRLEN;
-                         /* [            ] */
-               alloca_len = 1 + keylen + 1 + 1 + portlen;
+               hostlen = INET6_ADDRSTRLEN;
+               alloca_len = 1 + hostlen + 1 + portlen;
                key = alloca(alloca_len);
-               *key = '[';
-               key[1 + keylen + 1] = 0; /* will be ':' later */
-               port = 1 + key + keylen + 1 + 1;
-               rc = getnameinfo(&sa.sa, len,
-                                key + 1, keylen, port, portlen, flags);
+               host = key + 1;
                break;
                }
        default:
                assert(0 && "unsupported address family, could that be IPv7?!");
        }
-       if (rc != 0) {
-               bug_warn_nogvl("BUG: getnameinfo: %s\n", gai_strerror(rc));
-               *key = 0;
+       if (!inet_ntop(r->idiag_family, src, host, hostlen)) {
+               bug_warn_nogvl("BUG: inet_ntop: %s\n", strerror(errno));
+               *key = '\0';
+               *host = '\0';
        }
-
-       keylen = (socklen_t)strlen(key);
-       portlen = (socklen_t)strlen(port);
-
-       switch (sa.ss.ss_family) {
+       hostlen = (socklen_t)strlen(host);
+       switch (r->idiag_family) {
        case AF_INET:
-               key[keylen] = ':';
-               memmove(key + keylen + 1, port, portlen + 1);
+               host[hostlen] = ':';
+               port = host + hostlen + 1;
                break;
        case AF_INET6:
-               key[keylen] = ']';
-               key[keylen + 1] = ':';
-               memmove(key + keylen + 2, port, portlen + 1);
-               keylen++;
+               key[0] = '[';
+               host[hostlen] = ']';
+               host[hostlen + 1] = ':';
+               port = host + hostlen + 2;
                break;
        default:
                assert(0 && "unsupported address family, could that be IPv7?!");
        }
 
+       n = snprintf(port, portlen, "%u", ntohs(r->id.idiag_sport));
+       if (n <= 0) {
+               bug_warn_nogvl("BUG: snprintf port: %d\n", n);
+               *key = '\0';
+       }
+
        if (st_lookup(table, (st_data_t)key, (st_data_t *)&stats))
                return stats;
 
        old_key = key;
 
        if (r->idiag_state == TCP_ESTABLISHED) {
-               int n = snprintf(key, alloca_len, "%s:%u",
-                                addr_any(sa.ss.ss_family),
+               n = snprintf(key, alloca_len, "%s:%u",
+                                addr_any(r->idiag_family),
                                 ntohs(r->id.idiag_sport));
                if (n <= 0) {
                        bug_warn_nogvl("BUG: snprintf: %d\n", n);
+                       *key = '\0';
                }
                if (st_lookup(table, (st_data_t)key, (st_data_t *)&stats))
                        return stats;
@@ -319,8 +309,9 @@
                        memcpy(key, old_key, n + 1);
                }
        } else {
-               key = xmalloc(keylen + 1 + portlen + 1);
-               memcpy(key, old_key, keylen + 1 + portlen + 1);
+               size_t old_len = strlen(old_key) + 1;
+               key = xmalloc(old_len);
+               memcpy(key, old_key, old_len);
        }
        stats = xcalloc(1, sizeof(struct listen_stats));
        st_insert(table, (st_data_t)key, (st_data_t)stats);
@@ -709,11 +700,12 @@
 
 void Init_raindrops_linux_inet_diag(void)
 {
-       VALUE cRaindrops = rb_const_get(rb_cObject, rb_intern("Raindrops"));
+       VALUE cRaindrops = rb_define_class("Raindrops", rb_cObject);
        VALUE mLinux = rb_define_module_under(cRaindrops, "Linux");
+       VALUE Socket;
 
        rb_require("socket");
-       cIDSock = rb_const_get(rb_cObject, rb_intern("Socket"));
+       Socket = rb_const_get(rb_cObject, rb_intern("Socket"));
        id_new = rb_intern("new");
 
        /*
@@ -722,7 +714,7 @@
         * This is a subclass of +Socket+ specifically for talking
         * to the inet_diag facility of Netlink.
         */
-       cIDSock = rb_define_class_under(cRaindrops, "InetDiagSocket", cIDSock);
+       cIDSock = rb_define_class_under(cRaindrops, "InetDiagSocket", Socket);
        rb_define_singleton_method(cIDSock, "new", ids_s_new, 0);
 
        cListenStats = rb_const_get(cRaindrops, rb_intern("ListenStats"));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/raindrops/linux_tcp_info.c 
new/ext/raindrops/linux_tcp_info.c
--- old/ext/raindrops/linux_tcp_info.c  2016-07-31 17:20:21.000000000 +0200
+++ new/ext/raindrops/linux_tcp_info.c  1970-01-01 01:00:00.000000000 +0100
@@ -1,173 +0,0 @@
-#if defined(__linux__) && defined(HAVE_LINUX_TCP_H)
-#include <ruby.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <linux/tcp.h>
-#ifdef TCP_INFO
-#include "my_fileno.h"
-
-#define TCPI_ATTR_READER(x) \
-static VALUE tcp_info_##x(VALUE self) \
-{ \
-       struct tcp_info *info = DATA_PTR(self); \
-       return UINT2NUM((uint32_t)info->tcpi_##x); \
-}
-
-TCPI_ATTR_READER(state)
-TCPI_ATTR_READER(ca_state)
-TCPI_ATTR_READER(retransmits)
-TCPI_ATTR_READER(probes)
-TCPI_ATTR_READER(backoff)
-TCPI_ATTR_READER(options)
-TCPI_ATTR_READER(snd_wscale)
-TCPI_ATTR_READER(rcv_wscale)
-TCPI_ATTR_READER(rto)
-TCPI_ATTR_READER(ato)
-TCPI_ATTR_READER(snd_mss)
-TCPI_ATTR_READER(rcv_mss)
-TCPI_ATTR_READER(unacked)
-TCPI_ATTR_READER(sacked)
-TCPI_ATTR_READER(lost)
-TCPI_ATTR_READER(retrans)
-TCPI_ATTR_READER(fackets)
-TCPI_ATTR_READER(last_data_sent)
-TCPI_ATTR_READER(last_ack_sent)
-TCPI_ATTR_READER(last_data_recv)
-TCPI_ATTR_READER(last_ack_recv)
-TCPI_ATTR_READER(pmtu)
-TCPI_ATTR_READER(rcv_ssthresh)
-TCPI_ATTR_READER(rtt)
-TCPI_ATTR_READER(rttvar)
-TCPI_ATTR_READER(snd_ssthresh)
-TCPI_ATTR_READER(snd_cwnd)
-TCPI_ATTR_READER(advmss)
-TCPI_ATTR_READER(reordering)
-TCPI_ATTR_READER(rcv_rtt)
-TCPI_ATTR_READER(rcv_space)
-TCPI_ATTR_READER(total_retrans)
-
-static VALUE alloc(VALUE klass)
-{
-       struct tcp_info *info = xmalloc(sizeof(struct tcp_info));
-
-       /* Data_Make_Struct has an extra memset 0 which is so wasteful */
-       return Data_Wrap_Struct(klass, NULL, -1, info);
-}
-
-/*
- * call-seq:
- *
- *     Raindrops::TCP_Info.new(tcp_socket)     -> TCP_Info object
- *
- * Reads a TCP_Info object from any given +tcp_socket+.  See the tcp(7)
- * manpage and /usr/include/linux/tcp.h for more details.
- */
-static VALUE init(VALUE self, VALUE io)
-{
-       int fd = my_fileno(io);
-       struct tcp_info *info = DATA_PTR(self);
-       socklen_t len = (socklen_t)sizeof(struct tcp_info);
-       int rc = getsockopt(fd, IPPROTO_TCP, TCP_INFO, info, &len);
-
-       if (rc != 0)
-               rb_sys_fail("getsockopt");
-
-       return self;
-}
-
-void Init_raindrops_linux_tcp_info(void)
-{
-       VALUE cRaindrops = rb_const_get(rb_cObject, rb_intern("Raindrops"));
-       VALUE cTCP_Info;
-
-       /*
-        * Document-class: Raindrops::TCP_Info
-        *
-        * This is used to wrap "struct tcp_info" as described in tcp(7)
-        * and /usr/include/linux/tcp.h.  The following readers methods
-        * are defined corresponding to the "tcpi_" fields in the
-        * tcp_info struct.
-        *
-        * In particular, the +last_data_recv+ field is useful for measuring
-        * the amount of time a client spent in the listen queue before
-        * +accept()+, but only if +TCP_DEFER_ACCEPT+ is used with the
-        * listen socket (it is on by default in Unicorn).
-        *
-        * - state
-        * - ca_state
-        * - retransmits
-        * - probes
-        * - backoff
-        * - options
-        * - snd_wscale
-        * - rcv_wscale
-        * - rto
-        * - ato
-        * - snd_mss
-        * - rcv_mss
-        * - unacked
-        * - sacked
-        * - lost
-        * - retrans
-        * - fackets
-        * - last_data_sent
-        * - last_ack_sent
-        * - last_data_recv
-        * - last_ack_recv
-        * - pmtu
-        * - rcv_ssthresh
-        * - rtt
-        * - rttvar
-        * - snd_ssthresh
-        * - snd_cwnd
-        * - advmss
-        * - reordering
-        * - rcv_rtt
-        * - rcv_space
-        * - total_retrans
-        *
-        * https://kernel.org/doc/man-pages/online/pages/man7/tcp.7.html
-        */
-       cTCP_Info = rb_define_class_under(cRaindrops, "TCP_Info", rb_cObject);
-       rb_define_alloc_func(cTCP_Info, alloc);
-       rb_define_private_method(cTCP_Info, "initialize", init, 1);
-       rb_define_method(cTCP_Info, "get!", init, 1);
-
-#define TCPI_DEFINE_METHOD(x) \
-       rb_define_method(cTCP_Info, #x, tcp_info_##x, 0)
-
-       TCPI_DEFINE_METHOD(state);
-       TCPI_DEFINE_METHOD(ca_state);
-       TCPI_DEFINE_METHOD(retransmits);
-       TCPI_DEFINE_METHOD(probes);
-       TCPI_DEFINE_METHOD(backoff);
-       TCPI_DEFINE_METHOD(options);
-       TCPI_DEFINE_METHOD(snd_wscale);
-       TCPI_DEFINE_METHOD(rcv_wscale);
-       TCPI_DEFINE_METHOD(rto);
-       TCPI_DEFINE_METHOD(ato);
-       TCPI_DEFINE_METHOD(snd_mss);
-       TCPI_DEFINE_METHOD(rcv_mss);
-       TCPI_DEFINE_METHOD(unacked);
-       TCPI_DEFINE_METHOD(sacked);
-       TCPI_DEFINE_METHOD(lost);
-       TCPI_DEFINE_METHOD(retrans);
-       TCPI_DEFINE_METHOD(fackets);
-       TCPI_DEFINE_METHOD(last_data_sent);
-       TCPI_DEFINE_METHOD(last_ack_sent);
-       TCPI_DEFINE_METHOD(last_data_recv);
-       TCPI_DEFINE_METHOD(last_ack_recv);
-       TCPI_DEFINE_METHOD(pmtu);
-       TCPI_DEFINE_METHOD(rcv_ssthresh);
-       TCPI_DEFINE_METHOD(rtt);
-       TCPI_DEFINE_METHOD(rttvar);
-       TCPI_DEFINE_METHOD(snd_ssthresh);
-       TCPI_DEFINE_METHOD(snd_cwnd);
-       TCPI_DEFINE_METHOD(advmss);
-       TCPI_DEFINE_METHOD(reordering);
-       TCPI_DEFINE_METHOD(rcv_rtt);
-       TCPI_DEFINE_METHOD(rcv_space);
-       TCPI_DEFINE_METHOD(total_retrans);
-}
-#endif /* TCP_INFO */
-#endif /* defined(__linux__) && defined(HAVE_LINUX_TCP_H) */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/raindrops/raindrops.c 
new/ext/raindrops/raindrops.c
--- old/ext/raindrops/raindrops.c       2016-07-31 17:20:21.000000000 +0200
+++ new/ext/raindrops/raindrops.c       2017-03-23 03:45:38.000000000 +0100
@@ -38,7 +38,7 @@
 };
 
 /* called by GC */
-static void gcfree(void *ptr)
+static void rd_free(void *ptr)
 {
        struct raindrops *r = ptr;
 
@@ -51,11 +51,24 @@
        xfree(ptr);
 }
 
+static size_t rd_memsize(const void *ptr)
+{
+       const struct raindrops *r = ptr;
+
+       return r->drops == MAP_FAILED ? 0 : raindrop_size * r->capa;
+}
+
+static const rb_data_type_t rd_type = {
+       "raindrops",
+       { NULL, rd_free, rd_memsize, /* reserved */ },
+       /* parent, data, [ flags ] */
+};
+
 /* automatically called at creation (before initialize) */
 static VALUE alloc(VALUE klass)
 {
        struct raindrops *r;
-       VALUE rv = Data_Make_Struct(klass, struct raindrops, NULL, gcfree, r);
+       VALUE rv = TypedData_Make_Struct(klass, struct raindrops, &rd_type, r);
 
        r->drops = MAP_FAILED;
        return rv;
@@ -65,7 +78,7 @@
 {
        struct raindrops *r;
 
-       Data_Get_Struct(self, struct raindrops, r);
+       TypedData_Get_Struct(self, struct raindrops, &rd_type, r);
 
        if (r->drops == MAP_FAILED)
                rb_raise(rb_eStandardError, "invalid or freed Raindrops");
@@ -104,7 +117,9 @@
        r->drops = mmap(NULL, tmp,
                        PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
        if (r->drops == MAP_FAILED) {
-               if ((errno == EAGAIN || errno == ENOMEM) && tries-- > 0) {
+               int err = errno;
+
+               if ((err == EAGAIN || err == ENOMEM) && tries-- > 0) {
                        rb_gc();
                        goto retry;
                }
@@ -140,7 +155,9 @@
 
        rv = mremap(old_address, old_size, new_size, MREMAP_MAYMOVE);
        if (rv == MAP_FAILED) {
-               if (errno == EAGAIN || errno == ENOMEM) {
+               int err = errno;
+
+               if (err == EAGAIN || err == ENOMEM) {
                        rb_gc();
                        rv = mremap(old_address, old_size, new_size, 0);
                }
@@ -323,7 +340,9 @@
 
 #ifdef __linux__
 void Init_raindrops_linux_inet_diag(void);
-void Init_raindrops_linux_tcp_info(void);
+#endif
+#ifdef HAVE_TYPE_STRUCT_TCP_INFO
+void Init_raindrops_tcp_info(void);
 #endif
 
 #ifndef _SC_NPROCESSORS_CONF
@@ -428,6 +447,8 @@
 
 #ifdef __linux__
        Init_raindrops_linux_inet_diag();
-       Init_raindrops_linux_tcp_info();
+#endif
+#ifdef HAVE_TYPE_STRUCT_TCP_INFO
+       Init_raindrops_tcp_info();
 #endif
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/raindrops/tcp_info.c new/ext/raindrops/tcp_info.c
--- old/ext/raindrops/tcp_info.c        1970-01-01 01:00:00.000000000 +0100
+++ new/ext/raindrops/tcp_info.c        2017-03-23 03:45:38.000000000 +0100
@@ -0,0 +1,246 @@
+#include <ruby.h>
+#include "extconf.h"
+#include <sys/socket.h>
+#include <netinet/in.h>
+#if defined(HAVE_LINUX_TCP_H)
+#  include <linux/tcp.h>
+#else
+#  if defined(HAVE_NETINET_TCP_H)
+#    include <netinet/tcp.h>
+#  endif
+#  if defined(HAVE_NETINET_TCP_FSM_H)
+#    include <netinet/tcp_fsm.h>
+#  endif
+#endif
+
+#ifdef HAVE_TYPE_STRUCT_TCP_INFO
+#include "my_fileno.h"
+
+CFUNC_tcp_info_tcpi_state
+CFUNC_tcp_info_tcpi_ca_state
+CFUNC_tcp_info_tcpi_retransmits
+CFUNC_tcp_info_tcpi_probes
+CFUNC_tcp_info_tcpi_backoff
+CFUNC_tcp_info_tcpi_options
+CFUNC_tcp_info_tcpi_snd_wscale
+CFUNC_tcp_info_tcpi_rcv_wscale
+CFUNC_tcp_info_tcpi_rto
+CFUNC_tcp_info_tcpi_ato
+CFUNC_tcp_info_tcpi_snd_mss
+CFUNC_tcp_info_tcpi_rcv_mss
+CFUNC_tcp_info_tcpi_unacked
+CFUNC_tcp_info_tcpi_sacked
+CFUNC_tcp_info_tcpi_lost
+CFUNC_tcp_info_tcpi_retrans
+CFUNC_tcp_info_tcpi_fackets
+CFUNC_tcp_info_tcpi_last_data_sent
+CFUNC_tcp_info_tcpi_last_ack_sent
+CFUNC_tcp_info_tcpi_last_data_recv
+CFUNC_tcp_info_tcpi_last_ack_recv
+CFUNC_tcp_info_tcpi_pmtu
+CFUNC_tcp_info_tcpi_rcv_ssthresh
+CFUNC_tcp_info_tcpi_rtt
+CFUNC_tcp_info_tcpi_rttvar
+CFUNC_tcp_info_tcpi_snd_ssthresh
+CFUNC_tcp_info_tcpi_snd_cwnd
+CFUNC_tcp_info_tcpi_advmss
+CFUNC_tcp_info_tcpi_reordering
+CFUNC_tcp_info_tcpi_rcv_rtt
+CFUNC_tcp_info_tcpi_rcv_space
+CFUNC_tcp_info_tcpi_total_retrans
+
+static size_t tcpi_memsize(const void *ptr)
+{
+       return sizeof(struct tcp_info);
+}
+
+static const rb_data_type_t tcpi_type = {
+       "tcp_info",
+       { NULL, RUBY_TYPED_DEFAULT_FREE, tcpi_memsize, /* reserved */ },
+       /* parent, data, [ flags ] */
+};
+
+static VALUE alloc(VALUE klass)
+{
+       struct tcp_info *info;
+
+       return TypedData_Make_Struct(klass, struct tcp_info, &tcpi_type, info);
+}
+
+/*
+ * call-seq:
+ *
+ *     Raindrops::TCP_Info.new(tcp_socket)     -> TCP_Info object
+ *
+ * Reads a TCP_Info object from any given +tcp_socket+.  See the tcp(7)
+ * manpage and /usr/include/linux/tcp.h for more details.
+ */
+static VALUE init(VALUE self, VALUE io)
+{
+       int fd = my_fileno(io);
+       struct tcp_info *info = DATA_PTR(self);
+       socklen_t len = (socklen_t)sizeof(struct tcp_info);
+       int rc = getsockopt(fd, IPPROTO_TCP, TCP_INFO, info, &len);
+
+       if (rc != 0)
+               rb_sys_fail("getsockopt");
+
+       return self;
+}
+
+void Init_raindrops_tcp_info(void)
+{
+       VALUE cRaindrops = rb_define_class("Raindrops", rb_cObject);
+       VALUE cTCP_Info;
+
+       /*
+        * Document-class: Raindrops::TCP_Info
+        *
+        * This is used to wrap "struct tcp_info" as described in tcp(7)
+        * and /usr/include/linux/tcp.h.  The following readers methods
+        * are defined corresponding to the "tcpi_" fields in the
+        * tcp_info struct.
+        *
+        * As of raindrops 0.18.0+, this is supported on FreeBSD and OpenBSD
+        * systems as well as Linux, although not all fields exist or
+        * match the documentation, below.
+        *
+        * In particular, the +last_data_recv+ field is useful for measuring
+        * the amount of time a client spent in the listen queue before
+        * +accept()+, but only if +TCP_DEFER_ACCEPT+ is used with the
+        * listen socket (it is on by default in Unicorn).
+        *
+        * - state
+        * - ca_state
+        * - retransmits
+        * - probes
+        * - backoff
+        * - options
+        * - snd_wscale
+        * - rcv_wscale
+        * - rto
+        * - ato
+        * - snd_mss
+        * - rcv_mss
+        * - unacked
+        * - sacked
+        * - lost
+        * - retrans
+        * - fackets
+        * - last_data_sent
+        * - last_ack_sent
+        * - last_data_recv
+        * - last_ack_recv
+        * - pmtu
+        * - rcv_ssthresh
+        * - rtt
+        * - rttvar
+        * - snd_ssthresh
+        * - snd_cwnd
+        * - advmss
+        * - reordering
+        * - rcv_rtt
+        * - rcv_space
+        * - total_retrans
+        *
+        * https://kernel.org/doc/man-pages/online/pages/man7/tcp.7.html
+        */
+       cTCP_Info = rb_define_class_under(cRaindrops, "TCP_Info", rb_cObject);
+       rb_define_alloc_func(cTCP_Info, alloc);
+       rb_define_private_method(cTCP_Info, "initialize", init, 1);
+
+       /*
+        * Document-method: Raindrops::TCP_Info#get!
+        *
+        * call-seq:
+        *
+        *      info = Raindrops::TCP_Info.new(tcp_socket)
+        *      info.get!(tcp_socket)
+        *
+        * Update an existing TCP_Info objects with the latest stats
+        * from the given socket.  This even allows sharing TCP_Info
+        * objects between different sockets to avoid garbage.
+        */
+       rb_define_method(cTCP_Info, "get!", init, 1);
+
+       DEFINE_METHOD_tcp_info_tcpi_state;
+       DEFINE_METHOD_tcp_info_tcpi_ca_state;
+       DEFINE_METHOD_tcp_info_tcpi_retransmits;
+       DEFINE_METHOD_tcp_info_tcpi_probes;
+       DEFINE_METHOD_tcp_info_tcpi_backoff;
+       DEFINE_METHOD_tcp_info_tcpi_options;
+       DEFINE_METHOD_tcp_info_tcpi_snd_wscale;
+       DEFINE_METHOD_tcp_info_tcpi_rcv_wscale;
+       DEFINE_METHOD_tcp_info_tcpi_rto;
+       DEFINE_METHOD_tcp_info_tcpi_ato;
+       DEFINE_METHOD_tcp_info_tcpi_snd_mss;
+       DEFINE_METHOD_tcp_info_tcpi_rcv_mss;
+       DEFINE_METHOD_tcp_info_tcpi_unacked;
+       DEFINE_METHOD_tcp_info_tcpi_sacked;
+       DEFINE_METHOD_tcp_info_tcpi_lost;
+       DEFINE_METHOD_tcp_info_tcpi_retrans;
+       DEFINE_METHOD_tcp_info_tcpi_fackets;
+       DEFINE_METHOD_tcp_info_tcpi_last_data_sent;
+       DEFINE_METHOD_tcp_info_tcpi_last_ack_sent;
+       DEFINE_METHOD_tcp_info_tcpi_last_data_recv;
+       DEFINE_METHOD_tcp_info_tcpi_last_ack_recv;
+       DEFINE_METHOD_tcp_info_tcpi_pmtu;
+       DEFINE_METHOD_tcp_info_tcpi_rcv_ssthresh;
+       DEFINE_METHOD_tcp_info_tcpi_rtt;
+       DEFINE_METHOD_tcp_info_tcpi_rttvar;
+       DEFINE_METHOD_tcp_info_tcpi_snd_ssthresh;
+       DEFINE_METHOD_tcp_info_tcpi_snd_cwnd;
+       DEFINE_METHOD_tcp_info_tcpi_advmss;
+       DEFINE_METHOD_tcp_info_tcpi_reordering;
+       DEFINE_METHOD_tcp_info_tcpi_rcv_rtt;
+       DEFINE_METHOD_tcp_info_tcpi_rcv_space;
+       DEFINE_METHOD_tcp_info_tcpi_total_retrans;
+
+#ifdef RAINDROPS_TCP_STATES_ALL_KNOWN
+
+       /*
+        * Document-const: Raindrops::TCP
+         *
+         * This is a frozen hash storing the numeric values
+         * maps platform-independent symbol keys to
+         * platform-dependent numeric values. These states
+         * are all valid values for the Raindrops::TCP_Info#state field.
+         *
+         * The platform-independent names of the keys in this hash are:
+         *
+         *  - :ESTABLISHED
+         *  - :SYN_SENT
+         *  - :SYN_RECV
+         *  - :FIN_WAIT1
+         *  - :FIN_WAIT2
+         *  - :TIME_WAIT
+         *  - :CLOSE
+         *  - :CLOSE_WAIT
+         *  - :LAST_ACK
+         *  - :LISTEN
+         *  - :CLOSING
+         *
+         * This is only supported on platforms where TCP_Info is supported,
+         * currently FreeBSD, OpenBSD, and Linux-based systems.
+         */
+       {
+#define TCPSET(n,v) rb_hash_aset(tcp, ID2SYM(rb_intern(#n)), INT2NUM(v))
+               VALUE tcp = rb_hash_new();
+               TCPSET(ESTABLISHED, RAINDROPS_TCP_ESTABLISHED);
+               TCPSET(SYN_SENT, RAINDROPS_TCP_SYN_SENT);
+               TCPSET(SYN_RECV, RAINDROPS_TCP_SYN_RECV);
+               TCPSET(FIN_WAIT1, RAINDROPS_TCP_FIN_WAIT1);
+               TCPSET(FIN_WAIT2, RAINDROPS_TCP_FIN_WAIT2);
+               TCPSET(TIME_WAIT, RAINDROPS_TCP_TIME_WAIT);
+               TCPSET(CLOSE, RAINDROPS_TCP_CLOSE);
+               TCPSET(CLOSE_WAIT, RAINDROPS_TCP_CLOSE_WAIT);
+               TCPSET(LAST_ACK, RAINDROPS_TCP_LAST_ACK);
+               TCPSET(LISTEN, RAINDROPS_TCP_LISTEN);
+               TCPSET(CLOSING, RAINDROPS_TCP_CLOSING);
+#undef TCPSET
+               OBJ_FREEZE(tcp);
+               rb_define_const(cRaindrops, "TCP", tcp);
+       }
+#endif
+}
+#endif /* HAVE_STRUCT_TCP_INFO */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/raindrops/aggregate/pmq.rb 
new/lib/raindrops/aggregate/pmq.rb
--- old/lib/raindrops/aggregate/pmq.rb  2016-07-31 17:20:21.000000000 +0200
+++ new/lib/raindrops/aggregate/pmq.rb  2017-03-23 03:45:38.000000000 +0100
@@ -3,10 +3,10 @@
 require "aggregate"
 require "posix_mq"
 require "fcntl"
-require "io/extra"
 require "thread"
+require "stringio"
 
-# \Aggregate + POSIX message queues support for Ruby 1.9 and \Linux
+# \Aggregate + POSIX message queues support for Ruby 1.9+ and \Linux
 #
 # This class is duck-type compatible with \Aggregate and allows us to
 # aggregate and share statistics from multiple processes/threads aided
@@ -14,12 +14,11 @@
 # Raindrops::LastDataRecv Rack application, but can be used independently
 # on compatible Runtimes.
 #
-# Unlike the core of raindrops, this is only supported on Ruby 1.9 and
-# Linux 2.6.  Using this class requires the following additional RubyGems
+# Unlike the core of raindrops, this is only supported on Ruby 1.9+ and
+# Linux 2.6+.  Using this class requires the following additional RubyGems
 # or libraries:
 #
 # * aggregate (tested with 0.2.2)
-# * io-extra  (tested with 1.2.3)
 # * posix_mq  (tested with 1.0.0)
 #
 # == Design
@@ -39,9 +38,9 @@
   # :stopdoc:
   # These constants are for Linux.  This is designed for aggregating
   # TCP_INFO.
-  RDLOCK = [ Fcntl::F_RDLCK ].pack("s @256")
-  WRLOCK = [ Fcntl::F_WRLCK ].pack("s @256")
-  UNLOCK = [ Fcntl::F_UNLCK ].pack("s @256")
+  RDLOCK = [ Fcntl::F_RDLCK ].pack("s @256".freeze).freeze
+  WRLOCK = [ Fcntl::F_WRLCK ].pack("s @256".freeze).freeze
+  UNLOCK = [ Fcntl::F_UNLCK ].pack("s @256".freeze).freeze
   # :startdoc:
 
   # returns the number of dropped messages sent to a POSIX message
@@ -84,6 +83,7 @@
       @wr = File.open(t.path, "wb")
       @rd = File.open(t.path, "rb")
     end
+    @wr.sync = true
     @cached_aggregate = @aggregate
     flush_master
     @mq_send = if opts[:lossy]
@@ -151,7 +151,10 @@
     @cached_aggregate ||= begin
       flush
       Marshal.load(synchronize(@rd, RDLOCK) do |rd|
-        IO.pread rd.fileno, rd.stat.size, 0
+        dst = StringIO.new
+        dst.binmode
+        IO.copy_stream(rd, dst, rd.size, 0)
+        dst.string
       end)
     end
   end
@@ -163,7 +166,8 @@
     dump = Marshal.dump @aggregate
     synchronize(@wr, WRLOCK) do |wr|
       wr.truncate 0
-      IO.pwrite wr.fileno, dump, 0
+      wr.rewind
+      wr.write(dump)
     end
   end
 
@@ -185,10 +189,12 @@
   def synchronize io, type # :nodoc:
     @mutex.synchronize do
       begin
+        type = type.dup
         lock! io, type
         yield io
       ensure
-        lock! io, UNLOCK
+        lock! io, type.replace(UNLOCK)
+        type.clear
       end
     end
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2016-07-31 17:20:21.000000000 +0200
+++ new/metadata        2017-03-23 03:45:38.000000000 +0100
@@ -1,14 +1,14 @@
 --- !ruby/object:Gem::Specification
 name: raindrops
 version: !ruby/object:Gem::Version
-  version: 0.17.0
+  version: 0.18.0
 platform: ruby
 authors:
 - raindrops hackers
 autorequire: 
 bindir: bin
 cert_chain: []
-date: 2016-07-31 00:00:00.000000000 Z
+date: 2017-03-23 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: aggregate
@@ -39,26 +39,6 @@
       - !ruby/object:Gem::Version
         version: '3.0'
 - !ruby/object:Gem::Dependency
-  name: io-extra
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '1.2'
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: 1.2.3
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '1.2'
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: 1.2.3
-- !ruby/object:Gem::Dependency
   name: posix_mq
   requirement: !ruby/object:Gem::Requirement
     requirements:
@@ -92,27 +72,13 @@
     - - "<"
       - !ruby/object:Gem::Version
         version: '3.0'
-- !ruby/object:Gem::Dependency
-  name: olddoc
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '1.0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '1.0'
 description: |-
   raindrops is a real-time stats toolkit to show statistics for Rack HTTP
   servers.  It is designed for preforking servers such as unicorn, but
   should support any Rack HTTP server on platforms supporting POSIX shared
   memory.  It may also be used as a generic scoreboard for sharing atomic
   counters across multiple processes.
-email: raindr...@bogomips.org
+email: raindrops-pub...@bogomips.org
 executables: []
 extensions:
 - ext/raindrops/extconf.rb
@@ -120,19 +86,9 @@
 - README
 - LICENSE
 - NEWS
-- lib/raindrops.rb
-- lib/raindrops/aggregate.rb
-- lib/raindrops/aggregate/last_data_recv.rb
-- lib/raindrops/aggregate/pmq.rb
-- lib/raindrops/last_data_recv.rb
-- lib/raindrops/linux.rb
-- lib/raindrops/middleware.rb
-- lib/raindrops/middleware/proxy.rb
-- lib/raindrops/struct.rb
-- lib/raindrops/watcher.rb
 - ext/raindrops/raindrops.c
 - ext/raindrops/linux_inet_diag.c
-- ext/raindrops/linux_tcp_info.c
+- ext/raindrops/tcp_info.c
 files:
 - ".document"
 - ".gitattributes"
@@ -158,10 +114,10 @@
 - examples/zbatery.conf.rb
 - ext/raindrops/extconf.rb
 - ext/raindrops/linux_inet_diag.c
-- ext/raindrops/linux_tcp_info.c
 - ext/raindrops/my_fileno.h
 - ext/raindrops/raindrops.c
 - ext/raindrops/raindrops_atomic.h
+- ext/raindrops/tcp_info.c
 - lib/raindrops.rb
 - lib/raindrops/aggregate.rb
 - lib/raindrops/aggregate/last_data_recv.rb
@@ -185,13 +141,13 @@
 - test/test_linux_all_tcp_listen_stats_leak.rb
 - test/test_linux_ipv6.rb
 - test/test_linux_middleware.rb
-- test/test_linux_tcp_info.rb
 - test/test_middleware.rb
 - test/test_middleware_unicorn.rb
 - test/test_middleware_unicorn_ipv6.rb
 - test/test_raindrops.rb
 - test/test_raindrops_gc.rb
 - test/test_struct.rb
+- test/test_tcp_info.rb
 - test/test_watcher.rb
 homepage: https://bogomips.org/raindrops/
 licenses:
@@ -205,7 +161,7 @@
   requirements:
   - - ">="
     - !ruby/object:Gem::Version
-      version: '0'
+      version: 1.9.3
 required_rubygems_version: !ruby/object:Gem::Requirement
   requirements:
   - - ">="
@@ -213,7 +169,7 @@
       version: '0'
 requirements: []
 rubyforge_project: 
-rubygems_version: 2.6.6
+rubygems_version: 2.6.10
 signing_key: 
 specification_version: 4
 summary: real-time stats for preforking Rack servers
@@ -226,11 +182,11 @@
 - test/test_linux_all_tcp_listen_stats_leak.rb
 - test/test_linux_ipv6.rb
 - test/test_linux_middleware.rb
-- test/test_linux_tcp_info.rb
 - test/test_middleware.rb
 - test/test_middleware_unicorn.rb
 - test/test_middleware_unicorn_ipv6.rb
 - test/test_raindrops.rb
 - test/test_raindrops_gc.rb
 - test/test_struct.rb
+- test/test_tcp_info.rb
 - test/test_watcher.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/raindrops.gemspec new/raindrops.gemspec
--- old/raindrops.gemspec       2016-07-31 17:20:21.000000000 +0200
+++ new/raindrops.gemspec       2017-03-23 03:45:38.000000000 +0100
@@ -1,30 +1,26 @@
 # -*- encoding: binary -*-
-ENV["VERSION"] or abort "VERSION= must be specified"
-manifest = File.readlines('.manifest').map! { |x| x.chomp! }
+manifest = File.exist?('.manifest') ?
+  IO.readlines('.manifest').map!(&:chomp!) : `git ls-files`.split("\n")
 test_files = manifest.grep(%r{\Atest/test_.*\.rb\z})
-require 'olddoc'
-extend Olddoc::Gemspec
-name, summary, title = readme_metadata
 
 Gem::Specification.new do |s|
   s.name = %q{raindrops}
-  s.version = ENV["VERSION"].dup
-
+  s.version = (ENV["VERSION"] ||= '0.18.0').dup
   s.authors = ["raindrops hackers"]
-  s.description = readme_description
-  s.email = %q{raindr...@bogomips.org}
+  s.description = File.read('README').split("\n\n")[1]
+  s.email = %q{raindrops-pub...@bogomips.org}
   s.extensions = %w(ext/raindrops/extconf.rb)
-  s.extra_rdoc_files = extra_rdoc_files(manifest)
+  s.extra_rdoc_files = IO.readlines('.document').map!(&:chomp!).keep_if do |f|
+    File.exist?(f)
+  end
   s.files = manifest
-  s.homepage = Olddoc.config['rdoc_url']
-  s.summary = summary
+  s.homepage = 'https://bogomips.org/raindrops/'
+  s.summary = 'real-time stats for preforking Rack servers'
+  s.required_ruby_version = '>= 1.9.3'
   s.test_files = test_files
   s.add_development_dependency('aggregate', '~> 0.2')
   s.add_development_dependency('test-unit', '~> 3.0')
-  s.add_development_dependency('io-extra', [ '~> 1.2', '>= 1.2.3'])
   s.add_development_dependency('posix_mq', '~> 2.0')
   s.add_development_dependency('rack', [ '>= 1.2', '< 3.0' ])
-  s.add_development_dependency('olddoc', '~> 1.0')
-
   s.licenses = %w(LGPL-2.1+)
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/test_aggregate_pmq.rb 
new/test/test_aggregate_pmq.rb
--- old/test/test_aggregate_pmq.rb      2016-07-31 17:20:21.000000000 +0200
+++ new/test/test_aggregate_pmq.rb      2017-03-23 03:45:38.000000000 +0100
@@ -3,7 +3,7 @@
 pmq = begin
   Raindrops::Aggregate::PMQ
 rescue LoadError => e
-  warn "W: #{e} skipping test"
+  warn "W: #{e} skipping #{__FILE__}"
   false
 end
 if RUBY_VERSION.to_f < 1.9
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/test_inet_diag_socket.rb 
new/test/test_inet_diag_socket.rb
--- old/test/test_inet_diag_socket.rb   2016-07-31 17:20:21.000000000 +0200
+++ new/test/test_inet_diag_socket.rb   2017-03-23 03:45:38.000000000 +0100
@@ -8,7 +8,7 @@
   def test_new
     sock = Raindrops::InetDiagSocket.new
     assert_kind_of Socket, sock
-    assert_kind_of Fixnum, sock.fileno
+    assert_kind_of Integer, sock.fileno
     flags = sock.fcntl(Fcntl::F_GETFD)
     assert_equal Fcntl::FD_CLOEXEC, flags & Fcntl::FD_CLOEXEC
     assert_nil sock.close
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/test_last_data_recv_unicorn.rb 
new/test/test_last_data_recv_unicorn.rb
--- old/test/test_last_data_recv_unicorn.rb     2016-07-31 17:20:21.000000000 
+0200
+++ new/test/test_last_data_recv_unicorn.rb     2017-03-23 03:45:38.000000000 
+0100
@@ -7,7 +7,7 @@
 pmq = begin
   Raindrops::Aggregate::PMQ
 rescue LoadError => e
-  warn "W: #{e} skipping test"
+  warn "W: #{e} skipping #{__FILE__}"
   false
 end
 if RUBY_VERSION.to_f < 1.9
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/test_linux_tcp_info.rb 
new/test/test_linux_tcp_info.rb
--- old/test/test_linux_tcp_info.rb     2016-07-31 17:20:21.000000000 +0200
+++ new/test/test_linux_tcp_info.rb     1970-01-01 01:00:00.000000000 +0100
@@ -1,68 +0,0 @@
-# -*- encoding: binary -*-
-require 'test/unit'
-require 'tempfile'
-require 'raindrops'
-require 'socket'
-require 'pp'
-$stderr.sync = $stdout.sync = true
-class TestLinuxTCP_Info < Test::Unit::TestCase
-
-  TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
-
-  # Linux kernel commit 5ee3afba88f5a79d0bff07ddd87af45919259f91
-  TCP_INFO_useful_listenq = `uname -r`.strip >= '2.6.24'
-
-
-  def test_tcp_server
-    s = TCPServer.new(TEST_ADDR, 0)
-    rv = Raindrops::TCP_Info.new s
-    c = TCPSocket.new TEST_ADDR, s.addr[1]
-    tmp = Raindrops::TCP_Info.new s
-    TCP_INFO_useful_listenq and assert_equal 1, tmp.unacked
-
-    assert_equal 0, rv.unacked
-    a = s.accept
-    tmp = Raindrops::TCP_Info.new s
-    assert_equal 0, tmp.unacked
-    before = tmp.object_id
-
-    tmp.get!(s)
-    assert_equal before, tmp.object_id
-
-    ensure
-      c.close if c
-      a.close if a
-      s.close
-  end
-
-  def test_accessors
-    s = TCPServer.new TEST_ADDR, 0
-    tmp = Raindrops::TCP_Info.new s
-    tcp_info_methods = tmp.methods - Object.new.methods
-    assert tcp_info_methods.size >= 32
-    tcp_info_methods.each do |m|
-      next if m.to_sym == :get!
-      val = tmp.__send__ m
-      assert_kind_of Integer, val
-      assert val >= 0
-    end
-    ensure
-      s.close
-  end
-
-  def test_tcp_server_delayed
-    delay = 0.010
-    delay_ms = (delay * 1000).to_i
-    s = TCPServer.new(TEST_ADDR, 0)
-    c = TCPSocket.new TEST_ADDR, s.addr[1]
-    c.syswrite "."
-    sleep(delay * 1.2)
-    a = s.accept
-    i = Raindrops::TCP_Info.new(a)
-    assert i.last_data_recv >= delay_ms, "#{i.last_data_recv} < #{delay_ms}"
-    ensure
-      c.close if c
-      a.close if a
-      s.close
-  end
-end if RUBY_PLATFORM =~ /linux/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/test_tcp_info.rb new/test/test_tcp_info.rb
--- old/test/test_tcp_info.rb   1970-01-01 01:00:00.000000000 +0100
+++ new/test/test_tcp_info.rb   2017-03-23 03:45:38.000000000 +0100
@@ -0,0 +1,88 @@
+# -*- encoding: binary -*-
+require 'test/unit'
+require 'tempfile'
+require 'raindrops'
+require 'socket'
+require 'pp'
+$stderr.sync = $stdout.sync = true
+class TestTCP_Info < Test::Unit::TestCase
+
+  TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
+
+  # Linux kernel commit 5ee3afba88f5a79d0bff07ddd87af45919259f91
+  TCP_INFO_useful_listenq = `uname -r`.strip >= '2.6.24'
+
+  def test_tcp_server_unacked
+    return if RUBY_PLATFORM !~ /linux/ # unacked not implemented on others...
+    s = TCPServer.new(TEST_ADDR, 0)
+    rv = Raindrops::TCP_Info.new s
+    c = TCPSocket.new TEST_ADDR, s.addr[1]
+    tmp = Raindrops::TCP_Info.new s
+    TCP_INFO_useful_listenq and assert_equal 1, tmp.unacked
+
+    assert_equal 0, rv.unacked
+    a = s.accept
+    tmp = Raindrops::TCP_Info.new s
+    assert_equal 0, tmp.unacked
+    before = tmp.object_id
+
+    tmp.get!(s)
+    assert_equal before, tmp.object_id
+
+  ensure
+    [ c, a, s ].compact.each(&:close)
+  end
+
+  def test_accessors
+    s = TCPServer.new TEST_ADDR, 0
+    tmp = Raindrops::TCP_Info.new s
+    tcp_info_methods = tmp.methods - Object.new.methods
+    assert tcp_info_methods.size >= 32
+    tcp_info_methods.each do |m|
+      next if m.to_sym == :get!
+      next if ! tmp.respond_to?(m)
+      val = tmp.__send__ m
+      assert_kind_of Integer, val
+      assert val >= 0
+    end
+    assert tmp.respond_to?(:state), 'every OS knows about TCP state, right?'
+  ensure
+    s.close
+  end
+
+  def test_tcp_server_delayed
+    delay = 0.010
+    delay_ms = (delay * 1000).to_i
+    s = TCPServer.new(TEST_ADDR, 0)
+    c = TCPSocket.new TEST_ADDR, s.addr[1]
+    c.syswrite "."
+    sleep(delay * 1.2)
+    a = s.accept
+    i = Raindrops::TCP_Info.new(a)
+    assert i.last_data_recv >= delay_ms, "#{i.last_data_recv} < #{delay_ms}"
+    ensure
+      c.close if c
+      a.close if a
+      s.close
+  end
+
+  def test_tcp_server_state_closed
+    s = TCPServer.new(TEST_ADDR, 0)
+    c = TCPSocket.new(TEST_ADDR, s.addr[1])
+    i = Raindrops::TCP_Info.allocate
+    a = s.accept
+    i.get!(a)
+    state = i.state
+    if Raindrops.const_defined?(:TCP)
+      assert_equal state, Raindrops::TCP[:ESTABLISHED]
+    end
+    c = c.close
+    sleep(0.01) # wait for kernel to update state
+    i.get!(a)
+    assert_not_equal state, i.state
+  ensure
+    s.close if s
+    c.close if c
+    a.close if a
+  end
+end if defined? Raindrops::TCP_Info
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/test_watcher.rb new/test/test_watcher.rb
--- old/test/test_watcher.rb    2016-07-31 17:20:21.000000000 +0200
+++ new/test/test_watcher.rb    2017-03-23 03:45:38.000000000 +0100
@@ -2,6 +2,11 @@
 require "test/unit"
 require "rack"
 require "raindrops"
+begin
+  require 'aggregate'
+rescue LoadError => e
+  warn "W: #{e} skipping #{__FILE__}"
+end
 
 class TestWatcher < Test::Unit::TestCase
   TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
@@ -178,4 +183,4 @@
     assert_equal queued_before, headers["X-Last-Peak-At"], "should not change"
     assert_equal start, headers["X-First-Peak-At"]
   end
-end if RUBY_PLATFORM =~ /linux/
+end if RUBY_PLATFORM =~ /linux/ && defined?(Aggregate)


Reply via email to