fix Ruby warnings
[raindrops.git] / lib / raindrops / aggregate / last_data_recv.rb
blobeca89a29511b17175948d27d964f3e937d5a75a0
1 # -*- encoding: binary -*-
2 require "socket"
5 # This module is used to extend TCPServer and Kgio::TCPServer objects
6 # and aggregate +last_data_recv+ times for all accepted clients. It
7 # is designed to be used with Raindrops::LastDataRecv Rack application
8 # but can be easily changed to work with other stats collection devices.
10 # Methods wrapped include:
11 # - TCPServer#accept
12 # - TCPServer#accept_nonblock
13 # - Kgio::TCPServer#kgio_accept
14 # - Kgio::TCPServer#kgio_tryaccept
15 module Raindrops::Aggregate::LastDataRecv
16   # :stopdoc:
17   TCP_Info = Raindrops::TCP_Info
18   # :startdoc:
20   # The integer value of +last_data_recv+ is sent to this object.
21   # This is usually a duck type compatible with the \Aggregate class,
22   # but can be *anything* that accepts the *<<* method.
23   attr_accessor :raindrops_aggregate
25   @@default_aggregate = nil
27   # By default, this is a Raindrops::Aggregate::PMQ object
28   # It may be anything that responds to *<<*
29   def self.default_aggregate
30     @@default_aggregate ||= Raindrops::Aggregate::PMQ.new
31   end
33   # Assign any object that responds to *<<*
34   def self.default_aggregate=(agg)
35     @@default_aggregate = agg
36   end
38   # automatically extends any TCPServer objects used by Unicorn
39   def self.cornify!
40     Unicorn::HttpServer::LISTENERS.each do |sock|
41       sock.extend(self) if TCPServer === sock
42     end
43   end
45   # each extended object needs to have TCP_DEFER_ACCEPT enabled
46   # for accuracy.
47   def self.extended(obj)
48     obj.raindrops_aggregate = default_aggregate
49     # obj.setsockopt Socket::SOL_TCP, tcp_defer_accept = 9, seconds = 60
50     obj.setsockopt Socket::SOL_TCP, 9, 60
51   end
53   # :stopdoc:
55   def kgio_tryaccept(*args)
56     count! super
57   end
59   def kgio_accept(*args)
60     count! super
61   end
63   def accept
64     count! super
65   end
67   def accept_nonblock
68     count! super
69   end
71   # :startdoc:
73   # The +last_data_recv+ member of Raindrops::TCP_Info can be used to
74   # infer the time a client spent in the listen queue before it was
75   # accepted.
76   #
77   # We require TCP_DEFER_ACCEPT on the listen socket for
78   # +last_data_recv+ to be accurate
79   def count!(io)
80     if io
81       x = TCP_Info.new(io)
82       @raindrops_aggregate << x.last_data_recv
83     end
84     io
85   end
86 end