raindrops 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/GIT-VERSION-GEN +1 -1
- data/Gemfile +0 -1
- data/README +2 -2
- data/examples/linux-listener-stats.rb +1 -1
- data/ext/raindrops/extconf.rb +1 -1
- data/ext/raindrops/linux_inet_diag.c +39 -40
- data/lib/raindrops.rb +1 -1
- data/lib/raindrops/aggregate/last_data_recv.rb +2 -1
- data/lib/raindrops/aggregate/pmq.rb +3 -3
- data/lib/raindrops/last_data_recv.rb +2 -2
- data/lib/raindrops/watcher.rb +10 -9
- data/pkg.mk +5 -1
- data/raindrops.gemspec +1 -1
- data/test/ipv6_enabled.rb +1 -2
- data/test/test_aggregate_pmq.rb +1 -1
- data/test/test_linux.rb +26 -18
- data/test/test_linux_ipv6.rb +10 -10
- data/test/test_linux_middleware.rb +8 -3
- data/test/test_linux_tcp_info.rb +1 -1
- data/test/test_middleware_unicorn.rb +1 -1
- data/test/test_middleware_unicorn_ipv6.rb +1 -1
- metadata +7 -9
data/GIT-VERSION-GEN
CHANGED
data/Gemfile
CHANGED
data/README
CHANGED
@@ -62,7 +62,7 @@ Unpack it, and run "ruby setup.rb"
|
|
62
62
|
|
63
63
|
See Raindrops::Middleware and Raindrops::LastDataRecv documentation for
|
64
64
|
use Rack servers. The entire library is fully-documented and we are
|
65
|
-
responsive on the mailing list (mailto:raindrops@librelist.
|
65
|
+
responsive on the mailing list (mailto:raindrops@librelist.org) if you
|
66
66
|
have any questions or comments.
|
67
67
|
|
68
68
|
== Development
|
@@ -96,7 +96,7 @@ similar in spirit to the existing LGPL).
|
|
96
96
|
== Contact
|
97
97
|
|
98
98
|
All feedback (bug reports, user/development discussion, patches, pull
|
99
|
-
requests) go to the mailing list: mailto:raindrops@librelist.
|
99
|
+
requests) go to the mailing list: mailto:raindrops@librelist.org
|
100
100
|
|
101
101
|
The mailing list is mirrored to Gmane, all information about the
|
102
102
|
group is here:
|
@@ -21,7 +21,7 @@ queued_thresh = -1
|
|
21
21
|
trap(:INT) { exit 130 }
|
22
22
|
trap(:PIPE) { exit 0 }
|
23
23
|
|
24
|
-
|
24
|
+
OptionParser.new('', 24, ' ') do |opts|
|
25
25
|
opts.banner = usage
|
26
26
|
opts.on('-d', '--delay=DELAY', Float) { |n| delay = n }
|
27
27
|
opts.on('-t', '--queued-threshold=INT', Integer) { |n| queued_thresh = n }
|
data/ext/raindrops/extconf.rb
CHANGED
@@ -7,7 +7,7 @@ have_func('munmap', 'sys/mman.h') or abort 'munmap() not found'
|
|
7
7
|
$CPPFLAGS += " -D_GNU_SOURCE "
|
8
8
|
have_func('mremap', 'sys/mman.h')
|
9
9
|
|
10
|
-
$CPPFLAGS += " -D_BSD_SOURCE
|
10
|
+
$CPPFLAGS += " -D_BSD_SOURCE "
|
11
11
|
have_func("getpagesize", "unistd.h")
|
12
12
|
have_func('rb_thread_blocking_region')
|
13
13
|
have_func('rb_thread_io_blocking_region')
|
@@ -54,6 +54,13 @@ rb_thread_blocking_region(
|
|
54
54
|
#include <linux/rtnetlink.h>
|
55
55
|
#include <linux/inet_diag.h>
|
56
56
|
|
57
|
+
union any_addr {
|
58
|
+
struct sockaddr_storage ss;
|
59
|
+
struct sockaddr sa;
|
60
|
+
struct sockaddr_in in;
|
61
|
+
struct sockaddr_in6 in6;
|
62
|
+
};
|
63
|
+
|
57
64
|
static size_t page_size;
|
58
65
|
static unsigned g_seq;
|
59
66
|
static VALUE cListenStats, cIDSock;
|
@@ -169,7 +176,7 @@ static const char *addr_any(sa_family_t family)
|
|
169
176
|
static void bug_warn(void)
|
170
177
|
{
|
171
178
|
fprintf(stderr, "Please report how you produced this at "\
|
172
|
-
"raindrops@librelist.
|
179
|
+
"raindrops@librelist.org\n");
|
173
180
|
fflush(stderr);
|
174
181
|
}
|
175
182
|
|
@@ -180,30 +187,27 @@ static struct listen_stats *stats_for(st_table *table, struct inet_diag_msg *r)
|
|
180
187
|
struct listen_stats *stats;
|
181
188
|
size_t keylen;
|
182
189
|
size_t portlen = sizeof("65535");
|
183
|
-
|
190
|
+
union any_addr sa = { 0 };
|
184
191
|
socklen_t len = sizeof(struct sockaddr_storage);
|
185
192
|
int rc;
|
186
193
|
int flags = NI_NUMERICHOST | NI_NUMERICSERV;
|
187
194
|
|
188
|
-
switch ((ss.ss_family = r->idiag_family)) {
|
195
|
+
switch ((sa.ss.ss_family = r->idiag_family)) {
|
189
196
|
case AF_INET: {
|
190
|
-
|
191
|
-
|
192
|
-
in->sin_port = r->id.idiag_sport;
|
193
|
-
in->sin_addr.s_addr = r->id.idiag_src[0];
|
197
|
+
sa.in.sin_port = r->id.idiag_sport;
|
198
|
+
sa.in.sin_addr.s_addr = r->id.idiag_src[0];
|
194
199
|
keylen = INET_ADDRSTRLEN;
|
195
200
|
alloca_len = keylen + 1 + portlen;
|
196
201
|
key = alloca(alloca_len);
|
197
202
|
key[keylen] = 0; /* will be ':' later */
|
198
203
|
port = key + keylen + 1;
|
199
|
-
rc = getnameinfo(
|
204
|
+
rc = getnameinfo(&sa.sa, len,
|
200
205
|
key, keylen, port, portlen, flags);
|
201
206
|
break;
|
202
207
|
}
|
203
208
|
case AF_INET6: {
|
204
|
-
|
205
|
-
in6
|
206
|
-
memcpy(&in6->sin6_addr, &r->id.idiag_src, sizeof(__be32[4]));
|
209
|
+
sa.in6.sin6_port = r->id.idiag_sport;
|
210
|
+
memcpy(&sa.in6.sin6_addr, &r->id.idiag_src, sizeof(__be32[4]));
|
207
211
|
keylen = INET6_ADDRSTRLEN;
|
208
212
|
/* [ ] */
|
209
213
|
alloca_len = 1 + keylen + 1 + 1 + portlen;
|
@@ -211,7 +215,7 @@ static struct listen_stats *stats_for(st_table *table, struct inet_diag_msg *r)
|
|
211
215
|
*key = '[';
|
212
216
|
key[1 + keylen + 1] = 0; /* will be ':' later */
|
213
217
|
port = 1 + key + keylen + 1 + 1;
|
214
|
-
rc = getnameinfo(
|
218
|
+
rc = getnameinfo(&sa.sa, len,
|
215
219
|
key + 1, keylen, port, portlen, flags);
|
216
220
|
break;
|
217
221
|
}
|
@@ -227,7 +231,7 @@ static struct listen_stats *stats_for(st_table *table, struct inet_diag_msg *r)
|
|
227
231
|
keylen = strlen(key);
|
228
232
|
portlen = strlen(port);
|
229
233
|
|
230
|
-
switch (ss.ss_family) {
|
234
|
+
switch (sa.ss.ss_family) {
|
231
235
|
case AF_INET:
|
232
236
|
key[keylen] = ':';
|
233
237
|
memmove(key + keylen + 1, port, portlen + 1);
|
@@ -249,7 +253,7 @@ static struct listen_stats *stats_for(st_table *table, struct inet_diag_msg *r)
|
|
249
253
|
|
250
254
|
if (r->idiag_state == TCP_ESTABLISHED) {
|
251
255
|
int n = snprintf(key, alloca_len, "%s:%u",
|
252
|
-
addr_any(ss.ss_family),
|
256
|
+
addr_any(sa.ss.ss_family),
|
253
257
|
ntohs(r->id.idiag_sport));
|
254
258
|
if (n <= 0) {
|
255
259
|
fprintf(stderr, "BUG: snprintf: %d\n", n);
|
@@ -433,7 +437,7 @@ out:
|
|
433
437
|
}
|
434
438
|
|
435
439
|
/* populates sockaddr_storage struct by parsing +addr+ */
|
436
|
-
static void parse_addr(
|
440
|
+
static void parse_addr(union any_addr *inet, VALUE addr)
|
437
441
|
{
|
438
442
|
char *host_ptr;
|
439
443
|
char *check;
|
@@ -449,7 +453,6 @@ static void parse_addr(struct sockaddr_storage *inet, VALUE addr)
|
|
449
453
|
host_ptr = StringValueCStr(addr);
|
450
454
|
host_len = RSTRING_LEN(addr);
|
451
455
|
if (*host_ptr == '[') { /* ipv6 address format (rfc2732) */
|
452
|
-
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)inet;
|
453
456
|
rbracket = memchr(host_ptr + 1, ']', host_len - 1);
|
454
457
|
|
455
458
|
if (rbracket == NULL)
|
@@ -461,15 +464,14 @@ static void parse_addr(struct sockaddr_storage *inet, VALUE addr)
|
|
461
464
|
colon = rbracket + 1;
|
462
465
|
host_ptr++;
|
463
466
|
*rbracket = 0;
|
464
|
-
inet->ss_family = af = AF_INET6;
|
465
|
-
dst = &in6
|
466
|
-
portdst = &in6
|
467
|
+
inet->ss.ss_family = af = AF_INET6;
|
468
|
+
dst = &inet->in6.sin6_addr;
|
469
|
+
portdst = &inet->in6.sin6_port;
|
467
470
|
} else { /* ipv4 */
|
468
|
-
struct sockaddr_in *in = (struct sockaddr_in *)inet;
|
469
471
|
colon = memchr(host_ptr, ':', host_len);
|
470
|
-
inet->ss_family = af = AF_INET;
|
471
|
-
dst = &in
|
472
|
-
portdst = &in
|
472
|
+
inet->ss.ss_family = af = AF_INET;
|
473
|
+
dst = &inet->in.sin_addr;
|
474
|
+
portdst = &inet->in.sin_port;
|
473
475
|
}
|
474
476
|
|
475
477
|
if (!colon)
|
@@ -506,7 +508,7 @@ static void gen_bytecode_all(struct iovec *iov)
|
|
506
508
|
}
|
507
509
|
|
508
510
|
/* generates inet_diag bytecode to match a single addr */
|
509
|
-
static void gen_bytecode(struct iovec *iov,
|
511
|
+
static void gen_bytecode(struct iovec *iov, union any_addr *inet)
|
510
512
|
{
|
511
513
|
struct inet_diag_bc_op *op;
|
512
514
|
struct inet_diag_hostcond *cond;
|
@@ -519,25 +521,22 @@ static void gen_bytecode(struct iovec *iov, struct sockaddr_storage *inet)
|
|
519
521
|
op->no = sizeof(struct inet_diag_bc_op) + OPLEN;
|
520
522
|
|
521
523
|
cond = (struct inet_diag_hostcond *)(op + 1);
|
522
|
-
cond->family = inet->ss_family;
|
523
|
-
switch (inet->ss_family) {
|
524
|
+
cond->family = inet->ss.ss_family;
|
525
|
+
switch (inet->ss.ss_family) {
|
524
526
|
case AF_INET: {
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
cond->
|
529
|
-
sizeof(in->sin_addr.s_addr) * CHAR_BIT;
|
530
|
-
*cond->addr = in->sin_addr.s_addr;
|
527
|
+
cond->port = ntohs(inet->in.sin_port);
|
528
|
+
cond->prefix_len = inet->in.sin_addr.s_addr == 0 ? 0 :
|
529
|
+
sizeof(inet->in.sin_addr.s_addr) * CHAR_BIT;
|
530
|
+
*cond->addr = inet->in.sin_addr.s_addr;
|
531
531
|
}
|
532
532
|
break;
|
533
533
|
case AF_INET6: {
|
534
|
-
|
535
|
-
|
536
|
-
cond->port = ntohs(in6->sin6_port);
|
537
|
-
cond->prefix_len = memcmp(&in6addr_any, &in6->sin6_addr,
|
534
|
+
cond->port = ntohs(inet->in6.sin6_port);
|
535
|
+
cond->prefix_len = memcmp(&in6addr_any, &inet->in6.sin6_addr,
|
538
536
|
sizeof(struct in6_addr)) == 0 ?
|
539
|
-
0 : sizeof(in6
|
540
|
-
memcpy(&cond->addr, &in6
|
537
|
+
0 : sizeof(inet->in6.sin6_addr) * CHAR_BIT;
|
538
|
+
memcpy(&cond->addr, &inet->in6.sin6_addr,
|
539
|
+
sizeof(struct in6_addr));
|
541
540
|
}
|
542
541
|
break;
|
543
542
|
default:
|
@@ -559,7 +558,7 @@ static void nl_errcheck(VALUE r)
|
|
559
558
|
|
560
559
|
static VALUE tcp_stats(struct nogvl_args *args, VALUE addr)
|
561
560
|
{
|
562
|
-
|
561
|
+
union any_addr query_addr;
|
563
562
|
|
564
563
|
parse_addr(&query_addr, addr);
|
565
564
|
gen_bytecode(&args->iov[2], &query_addr);
|
@@ -617,7 +616,7 @@ static VALUE tcp_listener_stats(int argc, VALUE *argv, VALUE self)
|
|
617
616
|
return rv;
|
618
617
|
}
|
619
618
|
for (; --i >= 0; ary++) {
|
620
|
-
|
619
|
+
union any_addr check;
|
621
620
|
|
622
621
|
parse_addr(&check, *ary);
|
623
622
|
rb_hash_aset(rv, *ary, Qtrue);
|
data/lib/raindrops.rb
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
# Unlike many classes in this package, the core Raindrops class is
|
13
13
|
# intended to be portable to all reasonably modern *nix systems
|
14
14
|
# supporting mmap(). Please let us know if you have portability
|
15
|
-
# issues, patches or pull requests at mailto:raindrops@librelist.
|
15
|
+
# issues, patches or pull requests at mailto:raindrops@librelist.org
|
16
16
|
class Raindrops
|
17
17
|
|
18
18
|
# Used to represent the number of +active+ and +queued+ sockets for
|
@@ -46,7 +46,8 @@ module Raindrops::Aggregate::LastDataRecv
|
|
46
46
|
# for accuracy.
|
47
47
|
def self.extended(obj)
|
48
48
|
obj.raindrops_aggregate = default_aggregate
|
49
|
-
obj.setsockopt Socket::SOL_TCP, tcp_defer_accept = 9, seconds = 60
|
49
|
+
# obj.setsockopt Socket::SOL_TCP, tcp_defer_accept = 9, seconds = 60
|
50
|
+
obj.setsockopt Socket::SOL_TCP, 9, 60
|
50
51
|
end
|
51
52
|
|
52
53
|
# :stopdoc:
|
@@ -229,11 +229,11 @@ class Raindrops::Aggregate::PMQ
|
|
229
229
|
def outliers_high; aggregate.outliers_high; end
|
230
230
|
|
231
231
|
# proxy for \Aggregate#to_s
|
232
|
-
def to_s(*args); aggregate.to_s
|
232
|
+
def to_s(*args); aggregate.to_s(*args); end
|
233
233
|
|
234
234
|
# proxy for \Aggregate#each
|
235
|
-
def each; aggregate.each { |*args| yield
|
235
|
+
def each; aggregate.each { |*args| yield(*args) }; end
|
236
236
|
|
237
237
|
# proxy for \Aggregate#each_nonzero
|
238
|
-
def each_nonzero; aggregate.each_nonzero { |*args| yield
|
238
|
+
def each_nonzero; aggregate.each_nonzero { |*args| yield(*args) }; end
|
239
239
|
end
|
@@ -4,8 +4,8 @@ require "raindrops"
|
|
4
4
|
# This is highly experimental!
|
5
5
|
#
|
6
6
|
# A self-contained Rack application for aggregating in the
|
7
|
-
# +tcpi_last_data_recv+ field in +struct tcp_info+
|
8
|
-
#
|
7
|
+
# +tcpi_last_data_recv+ field in +struct+ +tcp_info+ defined in
|
8
|
+
# +/usr/include/linux/tcp.h+. This is only useful for \Linux 2.6 and later.
|
9
9
|
# This primarily supports Unicorn and derived servers, but may also be
|
10
10
|
# used with any Ruby web server using the core TCPServer class in Ruby.
|
11
11
|
#
|
data/lib/raindrops/watcher.rb
CHANGED
@@ -72,19 +72,19 @@ require "aggregate"
|
|
72
72
|
# - active_min - do not stream a line until this active count is reached
|
73
73
|
# - queued_min - do not stream a line until this queued count is reached
|
74
74
|
#
|
75
|
-
# == Response headers (mostly the same as Raindrops::LastDataRecv)
|
75
|
+
# == Response headers (mostly the same names as Raindrops::LastDataRecv)
|
76
76
|
#
|
77
|
-
# - X-Count - number of
|
77
|
+
# - X-Count - number of samples polled
|
78
78
|
# - X-Last-Reset - date since the last reset
|
79
79
|
#
|
80
80
|
# The following headers are only present if X-Count is greater than one.
|
81
81
|
#
|
82
|
-
# - X-Min - lowest
|
83
|
-
# - X-Max - highest
|
84
|
-
# - X-Mean - mean
|
85
|
-
# - X-Std-Dev - standard deviation of
|
86
|
-
# - X-Outliers-Low - number of low outliers (hopefully many
|
87
|
-
# - X-Outliers-High - number of high outliers (hopefully zero
|
82
|
+
# - X-Min - lowest number of connections recorded
|
83
|
+
# - X-Max - highest number of connections recorded
|
84
|
+
# - X-Mean - mean number of connections recorded
|
85
|
+
# - X-Std-Dev - standard deviation of connection count
|
86
|
+
# - X-Outliers-Low - number of low outliers (hopefully many for queued)
|
87
|
+
# - X-Outliers-High - number of high outliers (hopefully zero for queued)
|
88
88
|
#
|
89
89
|
# = Demo Server
|
90
90
|
#
|
@@ -228,6 +228,7 @@ class Raindrops::Watcher
|
|
228
228
|
end
|
229
229
|
|
230
230
|
def get(env)
|
231
|
+
retried = false
|
231
232
|
case env["PATH_INFO"]
|
232
233
|
when "/"
|
233
234
|
index
|
@@ -247,7 +248,7 @@ class Raindrops::Watcher
|
|
247
248
|
not_found
|
248
249
|
end
|
249
250
|
rescue Errno::EDOM
|
250
|
-
raise if
|
251
|
+
raise if retried
|
251
252
|
retried = true
|
252
253
|
wait_snapshot
|
253
254
|
retry
|
data/pkg.mk
CHANGED
@@ -69,7 +69,7 @@ doc:: .document .wrongdoc.yml $(pkg_extra)
|
|
69
69
|
$(RM) -r doc
|
70
70
|
$(WRONGDOC) all
|
71
71
|
install -m644 COPYING doc/COPYING
|
72
|
-
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
72
|
+
install -m644 $(shell LC_ALL=C grep '^[A-Z]' .document) doc/
|
73
73
|
|
74
74
|
ifneq ($(VERSION),)
|
75
75
|
pkggem := pkg/$(rfpackage)-$(VERSION).gem
|
@@ -167,5 +167,9 @@ doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
|
167
167
|
doc_gz:
|
168
168
|
for i in $(docs); do \
|
169
169
|
gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
|
170
|
+
check-warnings:
|
171
|
+
@(for i in $$(git ls-files '*.rb'| grep -v '^setup\.rb$$'); \
|
172
|
+
do $(RUBY) -d -W2 -c $$i; done) | grep -v '^Syntax OK$$' || :
|
170
173
|
|
171
174
|
.PHONY: all .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
|
175
|
+
.PHONY: check-warnings
|
data/raindrops.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.authors = ["raindrops hackers"]
|
14
14
|
s.date = Time.now.utc.strftime('%Y-%m-%d')
|
15
15
|
s.description = readme_description
|
16
|
-
s.email = %q{raindrops@librelist.
|
16
|
+
s.email = %q{raindrops@librelist.org}
|
17
17
|
s.extensions = %w(ext/raindrops/extconf.rb)
|
18
18
|
s.extra_rdoc_files = extra_rdoc_files(manifest)
|
19
19
|
s.files = manifest
|
data/test/ipv6_enabled.rb
CHANGED
data/test/test_aggregate_pmq.rb
CHANGED
@@ -49,7 +49,7 @@ class TestAggregatePMQ < Test::Unit::TestCase
|
|
49
49
|
pmq.flush
|
50
50
|
}
|
51
51
|
}
|
52
|
-
workers.each { |
|
52
|
+
workers.each { |wpid| assert Process.waitpid2(wpid).last.success? }
|
53
53
|
pmq.stop_master_loop
|
54
54
|
assert Process.waitpid2(pid).last.success?
|
55
55
|
assert_equal 400, pmq.count
|
data/test/test_linux.rb
CHANGED
@@ -11,6 +11,14 @@ class TestLinux < Test::Unit::TestCase
|
|
11
11
|
|
12
12
|
TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
|
13
13
|
|
14
|
+
def setup
|
15
|
+
@to_close = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
@to_close.each { |io| io.close unless io.closed? }
|
20
|
+
end
|
21
|
+
|
14
22
|
def test_unix
|
15
23
|
tmp = Tempfile.new("\xde\xad\xbe\xef") # valid path, really :)
|
16
24
|
File.unlink(tmp.path)
|
@@ -20,19 +28,19 @@ class TestLinux < Test::Unit::TestCase
|
|
20
28
|
assert_equal 0, stats[tmp.path].active
|
21
29
|
assert_equal 0, stats[tmp.path].queued
|
22
30
|
|
23
|
-
|
31
|
+
@to_close << UNIXSocket.new(tmp.path)
|
24
32
|
stats = unix_listener_stats([tmp.path])
|
25
33
|
assert_equal 1, stats.size
|
26
34
|
assert_equal 0, stats[tmp.path].active
|
27
35
|
assert_equal 1, stats[tmp.path].queued
|
28
36
|
|
29
|
-
|
37
|
+
@to_close << UNIXSocket.new(tmp.path)
|
30
38
|
stats = unix_listener_stats([tmp.path])
|
31
39
|
assert_equal 1, stats.size
|
32
40
|
assert_equal 0, stats[tmp.path].active
|
33
41
|
assert_equal 2, stats[tmp.path].queued
|
34
42
|
|
35
|
-
|
43
|
+
@to_close << us.accept
|
36
44
|
stats = unix_listener_stats([tmp.path])
|
37
45
|
assert_equal 1, stats.size
|
38
46
|
assert_equal 1, stats[tmp.path].active
|
@@ -43,17 +51,17 @@ class TestLinux < Test::Unit::TestCase
|
|
43
51
|
tmp = Tempfile.new("\xde\xad\xbe\xef") # valid path, really :)
|
44
52
|
File.unlink(tmp.path)
|
45
53
|
us = UNIXServer.new(tmp.path)
|
46
|
-
|
54
|
+
@to_close << UNIXSocket.new(tmp.path)
|
47
55
|
stats = unix_listener_stats
|
48
56
|
assert_equal 0, stats[tmp.path].active
|
49
57
|
assert_equal 1, stats[tmp.path].queued
|
50
58
|
|
51
|
-
|
59
|
+
@to_close << UNIXSocket.new(tmp.path)
|
52
60
|
stats = unix_listener_stats
|
53
61
|
assert_equal 0, stats[tmp.path].active
|
54
62
|
assert_equal 2, stats[tmp.path].queued
|
55
63
|
|
56
|
-
|
64
|
+
@to_close << us.accept
|
57
65
|
stats = unix_listener_stats
|
58
66
|
assert_equal 1, stats[tmp.path].active
|
59
67
|
assert_equal 1, stats[tmp.path].queued
|
@@ -69,13 +77,13 @@ class TestLinux < Test::Unit::TestCase
|
|
69
77
|
assert_equal 0, stats[addr].queued
|
70
78
|
assert_equal 0, stats[addr].active
|
71
79
|
|
72
|
-
|
80
|
+
@to_close << TCPSocket.new(TEST_ADDR, port)
|
73
81
|
stats = tcp_listener_stats(addrs)
|
74
82
|
assert_equal 1, stats.size
|
75
83
|
assert_equal 1, stats[addr].queued
|
76
84
|
assert_equal 0, stats[addr].active
|
77
85
|
|
78
|
-
|
86
|
+
@to_close << s.accept
|
79
87
|
stats = tcp_listener_stats(addrs)
|
80
88
|
assert_equal 1, stats.size
|
81
89
|
assert_equal 0, stats[addr].queued
|
@@ -93,13 +101,13 @@ class TestLinux < Test::Unit::TestCase
|
|
93
101
|
assert_equal 0, stats[addr].queued
|
94
102
|
assert_equal 0, stats[addr].active
|
95
103
|
|
96
|
-
|
104
|
+
@to_close << TCPSocket.new(TEST_ADDR, port)
|
97
105
|
stats = tcp_listener_stats(addrs, nlsock)
|
98
106
|
assert_equal 1, stats.size
|
99
107
|
assert_equal 1, stats[addr].queued
|
100
108
|
assert_equal 0, stats[addr].active
|
101
109
|
|
102
|
-
|
110
|
+
@to_close << s.accept
|
103
111
|
stats = tcp_listener_stats(addrs, nlsock)
|
104
112
|
assert_equal 1, stats.size
|
105
113
|
assert_equal 0, stats[addr].queued
|
@@ -121,7 +129,7 @@ class TestLinux < Test::Unit::TestCase
|
|
121
129
|
assert_equal 0, stats[addr2].queued
|
122
130
|
assert_equal 0, stats[addr2].active
|
123
131
|
|
124
|
-
|
132
|
+
@to_close << TCPSocket.new(TEST_ADDR, port1)
|
125
133
|
stats = tcp_listener_stats(addrs)
|
126
134
|
assert_equal 2, stats.size
|
127
135
|
assert_equal 1, stats[addr1].queued
|
@@ -137,7 +145,7 @@ class TestLinux < Test::Unit::TestCase
|
|
137
145
|
assert_equal 0, stats[addr2].queued
|
138
146
|
assert_equal 0, stats[addr2].active
|
139
147
|
|
140
|
-
|
148
|
+
@to_close << TCPSocket.new(TEST_ADDR, port2)
|
141
149
|
stats = tcp_listener_stats(addrs)
|
142
150
|
assert_equal 2, stats.size
|
143
151
|
assert_equal 0, stats[addr1].queued
|
@@ -145,7 +153,7 @@ class TestLinux < Test::Unit::TestCase
|
|
145
153
|
assert_equal 1, stats[addr2].queued
|
146
154
|
assert_equal 0, stats[addr2].active
|
147
155
|
|
148
|
-
|
156
|
+
@to_close << TCPSocket.new(TEST_ADDR, port2)
|
149
157
|
stats = tcp_listener_stats(addrs)
|
150
158
|
assert_equal 2, stats.size
|
151
159
|
assert_equal 0, stats[addr1].queued
|
@@ -153,7 +161,7 @@ class TestLinux < Test::Unit::TestCase
|
|
153
161
|
assert_equal 2, stats[addr2].queued
|
154
162
|
assert_equal 0, stats[addr2].active
|
155
163
|
|
156
|
-
|
164
|
+
@to_close << s2.accept
|
157
165
|
stats = tcp_listener_stats(addrs)
|
158
166
|
assert_equal 2, stats.size
|
159
167
|
assert_equal 0, stats[addr1].queued
|
@@ -184,7 +192,7 @@ class TestLinux < Test::Unit::TestCase
|
|
184
192
|
fork do
|
185
193
|
rda.close
|
186
194
|
wrb.close
|
187
|
-
|
195
|
+
@to_close.concat((1..nr_sock).map { s.accept })
|
188
196
|
wra.syswrite('.')
|
189
197
|
wra.close
|
190
198
|
rdb.sysread(1) # wait for parent to nuke us
|
@@ -195,7 +203,7 @@ class TestLinux < Test::Unit::TestCase
|
|
195
203
|
fork do
|
196
204
|
rda.close
|
197
205
|
wrb.close
|
198
|
-
|
206
|
+
@to_close.concat((1..nr_sock).map { TCPSocket.new(TEST_ADDR, port) })
|
199
207
|
wra.syswrite('.')
|
200
208
|
wra.close
|
201
209
|
rdb.sysread(1) # wait for parent to nuke us
|
@@ -209,7 +217,7 @@ class TestLinux < Test::Unit::TestCase
|
|
209
217
|
expect = { addr => Raindrops::ListenStats[nr_sock * nr_proc, 0] }
|
210
218
|
assert_equal expect, stats
|
211
219
|
|
212
|
-
|
220
|
+
@to_close << TCPSocket.new(TEST_ADDR, port)
|
213
221
|
stats = tcp_listener_stats(addrs)
|
214
222
|
expect = { addr => Raindrops::ListenStats[nr_sock * nr_proc, 1] }
|
215
223
|
assert_equal expect, stats
|
@@ -221,6 +229,6 @@ class TestLinux < Test::Unit::TestCase
|
|
221
229
|
|
222
230
|
wrb.syswrite('.' * (nr_proc * 2)) # broadcast a wakeup
|
223
231
|
statuses = Process.waitall
|
224
|
-
statuses.each { |(
|
232
|
+
statuses.each { |(_,status)| assert status.success?, status.inspect }
|
225
233
|
end if ENV["STRESS"].to_i != 0
|
226
234
|
end if RUBY_PLATFORM =~ /linux/
|
data/test/test_linux_ipv6.rb
CHANGED
@@ -22,13 +22,13 @@ class TestLinuxIPv6 < Test::Unit::TestCase
|
|
22
22
|
assert_equal 0, stats[addr].queued
|
23
23
|
assert_equal 0, stats[addr].active
|
24
24
|
|
25
|
-
|
25
|
+
@to_close << TCPSocket.new(TEST_ADDR, port)
|
26
26
|
stats = tcp_listener_stats(addrs)
|
27
27
|
assert_equal 1, stats.size
|
28
28
|
assert_equal 1, stats[addr].queued
|
29
29
|
assert_equal 0, stats[addr].active
|
30
30
|
|
31
|
-
|
31
|
+
@to_close << s.accept
|
32
32
|
stats = tcp_listener_stats(addrs)
|
33
33
|
assert_equal 1, stats.size
|
34
34
|
assert_equal 0, stats[addr].queued
|
@@ -48,7 +48,7 @@ class TestLinuxIPv6 < Test::Unit::TestCase
|
|
48
48
|
assert_equal 0, stats[addr2].queued
|
49
49
|
assert_equal 0, stats[addr2].active
|
50
50
|
|
51
|
-
|
51
|
+
@to_close << TCPSocket.new(TEST_ADDR, port1)
|
52
52
|
stats = tcp_listener_stats(addrs)
|
53
53
|
assert_equal 2, stats.size
|
54
54
|
assert_equal 1, stats[addr1].queued
|
@@ -64,7 +64,7 @@ class TestLinuxIPv6 < Test::Unit::TestCase
|
|
64
64
|
assert_equal 0, stats[addr2].queued
|
65
65
|
assert_equal 0, stats[addr2].active
|
66
66
|
|
67
|
-
|
67
|
+
@to_close << TCPSocket.new(TEST_ADDR, port2)
|
68
68
|
stats = tcp_listener_stats(addrs)
|
69
69
|
assert_equal 2, stats.size
|
70
70
|
assert_equal 0, stats[addr1].queued
|
@@ -72,7 +72,7 @@ class TestLinuxIPv6 < Test::Unit::TestCase
|
|
72
72
|
assert_equal 1, stats[addr2].queued
|
73
73
|
assert_equal 0, stats[addr2].active
|
74
74
|
|
75
|
-
|
75
|
+
@to_close << TCPSocket.new(TEST_ADDR, port2)
|
76
76
|
stats = tcp_listener_stats(addrs)
|
77
77
|
assert_equal 2, stats.size
|
78
78
|
assert_equal 0, stats[addr1].queued
|
@@ -80,7 +80,7 @@ class TestLinuxIPv6 < Test::Unit::TestCase
|
|
80
80
|
assert_equal 2, stats[addr2].queued
|
81
81
|
assert_equal 0, stats[addr2].active
|
82
82
|
|
83
|
-
|
83
|
+
@to_close << s2.accept
|
84
84
|
stats = tcp_listener_stats(addrs)
|
85
85
|
assert_equal 2, stats.size
|
86
86
|
assert_equal 0, stats[addr1].queued
|
@@ -116,7 +116,7 @@ class TestLinuxIPv6 < Test::Unit::TestCase
|
|
116
116
|
fork do
|
117
117
|
rda.close
|
118
118
|
wrb.close
|
119
|
-
|
119
|
+
@to_close.concat((1..nr_sock).map { s.accept })
|
120
120
|
wra.syswrite('.')
|
121
121
|
wra.close
|
122
122
|
rdb.sysread(1) # wait for parent to nuke us
|
@@ -127,7 +127,7 @@ class TestLinuxIPv6 < Test::Unit::TestCase
|
|
127
127
|
fork do
|
128
128
|
rda.close
|
129
129
|
wrb.close
|
130
|
-
|
130
|
+
@to_close.concat((1..nr_sock).map { TCPSocket.new(TEST_ADDR, port) })
|
131
131
|
wra.syswrite('.')
|
132
132
|
wra.close
|
133
133
|
rdb.sysread(1) # wait for parent to nuke us
|
@@ -141,7 +141,7 @@ class TestLinuxIPv6 < Test::Unit::TestCase
|
|
141
141
|
expect = { addr => Raindrops::ListenStats[nr_sock * nr_proc, 0] }
|
142
142
|
assert_equal expect, stats
|
143
143
|
|
144
|
-
|
144
|
+
@to_close << TCPSocket.new(TEST_ADDR, port)
|
145
145
|
stats = tcp_listener_stats(addrs)
|
146
146
|
expect = { addr => Raindrops::ListenStats[nr_sock * nr_proc, 1] }
|
147
147
|
assert_equal expect, stats
|
@@ -153,6 +153,6 @@ class TestLinuxIPv6 < Test::Unit::TestCase
|
|
153
153
|
|
154
154
|
wrb.syswrite('.' * (nr_proc * 2)) # broadcast a wakeup
|
155
155
|
statuses = Process.waitall
|
156
|
-
statuses.each { |(
|
156
|
+
statuses.each { |(_,status)| assert status.success?, status.inspect }
|
157
157
|
end if ENV["STRESS"].to_i != 0
|
158
158
|
end if RUBY_PLATFORM =~ /linux/ && ipv6_enabled?
|
@@ -11,12 +11,17 @@ class TestLinuxMiddleware < Test::Unit::TestCase
|
|
11
11
|
@resp_headers = { 'Content-Type' => 'text/plain', 'Content-Length' => '0' }
|
12
12
|
@response = [ 200, @resp_headers, [] ]
|
13
13
|
@app = lambda { |env| @response }
|
14
|
+
@to_close = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
@to_close.each { |io| io.close unless io.closed? }
|
14
19
|
end
|
15
20
|
|
16
21
|
def test_unix_listener
|
17
22
|
tmp = Tempfile.new("")
|
18
23
|
File.unlink(tmp.path)
|
19
|
-
|
24
|
+
@to_close << UNIXServer.new(tmp.path)
|
20
25
|
app = Raindrops::Middleware.new(@app, :listeners => [tmp.path])
|
21
26
|
linux_extra = "#{tmp.path} active: 0\n#{tmp.path} queued: 0\n"
|
22
27
|
response = app.call("PATH_INFO" => "/_raindrops")
|
@@ -37,8 +42,8 @@ class TestLinuxMiddleware < Test::Unit::TestCase
|
|
37
42
|
def test_unix_listener_queued
|
38
43
|
tmp = Tempfile.new("")
|
39
44
|
File.unlink(tmp.path)
|
40
|
-
|
41
|
-
|
45
|
+
@to_close << UNIXServer.new(tmp.path)
|
46
|
+
@to_close << UNIXSocket.new(tmp.path)
|
42
47
|
app = Raindrops::Middleware.new(@app, :listeners => [tmp.path])
|
43
48
|
linux_extra = "#{tmp.path} active: 0\n#{tmp.path} queued: 1\n"
|
44
49
|
response = app.call("PATH_INFO" => "/_raindrops")
|
data/test/test_linux_tcp_info.rb
CHANGED
@@ -49,7 +49,7 @@ class TestLinuxTCP_Info < Test::Unit::TestCase
|
|
49
49
|
s = TCPServer.new(TEST_ADDR, 0)
|
50
50
|
c = TCPSocket.new TEST_ADDR, s.addr[1]
|
51
51
|
c.syswrite "."
|
52
|
-
sleep
|
52
|
+
sleep(delay * 1.2)
|
53
53
|
a = s.accept
|
54
54
|
i = Raindrops::TCP_Info.new(a)
|
55
55
|
assert i.last_data_recv >= delay_ms, "#{i.last_data_recv} < #{delay_ms}"
|
@@ -24,7 +24,7 @@ class TestMiddlewareUnicorn < Test::Unit::TestCase
|
|
24
24
|
s = TCPSocket.new @host, @port
|
25
25
|
s.write "GET /_raindrops HTTP/1.0\r\n\r\n"
|
26
26
|
resp = s.read
|
27
|
-
|
27
|
+
_, body = resp.split(/\r\n\r\n/, 2)
|
28
28
|
assert_match %r{^#@addr_regexp active: 1$}, body
|
29
29
|
assert_match %r{^#@addr_regexp queued: 0$}, body
|
30
30
|
end
|
@@ -24,7 +24,7 @@ class TestMiddlewareUnicornIPv6 < Test::Unit::TestCase
|
|
24
24
|
s = TCPSocket.new @host, @port
|
25
25
|
s.write "GET /_raindrops HTTP/1.0\r\n\r\n"
|
26
26
|
resp = s.read
|
27
|
-
|
27
|
+
_, body = resp.split(/\r\n\r\n/, 2)
|
28
28
|
assert_match %r{^#@addr_regexp active: 1$}, body
|
29
29
|
assert_match %r{^#@addr_regexp queued: 0$}, body
|
30
30
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: raindrops
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 7
|
9
|
+
- 0
|
10
|
+
version: 0.7.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- raindrops hackers
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
19
|
-
default_executable:
|
18
|
+
date: 2011-06-27 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: bundler
|
@@ -41,7 +40,7 @@ description: |-
|
|
41
40
|
Rubinius on platforms supporting POSIX shared memory. It may also be
|
42
41
|
used as a generic scoreboard for sharing atomic counters across multiple
|
43
42
|
processes.
|
44
|
-
email: raindrops@librelist.
|
43
|
+
email: raindrops@librelist.org
|
45
44
|
executables: []
|
46
45
|
|
47
46
|
extensions:
|
@@ -123,7 +122,6 @@ files:
|
|
123
122
|
- test/test_raindrops_gc.rb
|
124
123
|
- test/test_struct.rb
|
125
124
|
- test/test_watcher.rb
|
126
|
-
has_rdoc: true
|
127
125
|
homepage: http://raindrops.bogomips.org/
|
128
126
|
licenses: []
|
129
127
|
|
@@ -156,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
154
|
requirements: []
|
157
155
|
|
158
156
|
rubyforge_project: rainbows
|
159
|
-
rubygems_version: 1.
|
157
|
+
rubygems_version: 1.8.5
|
160
158
|
signing_key:
|
161
159
|
specification_version: 3
|
162
160
|
summary: real-time stats for preforking Rack servers
|