raindrops 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.olddoc.yml +12 -10
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +1 -1
- data/LATEST +6 -38
- data/NEWS +50 -0
- data/README +16 -16
- data/examples/linux-listener-stats.rb +1 -2
- data/examples/watcher_demo.ru +1 -1
- data/ext/raindrops/extconf.rb +2 -1
- data/ext/raindrops/linux_inet_diag.c +17 -38
- data/ext/raindrops/raindrops.c +48 -15
- data/ext/raindrops/tcp_info.c +0 -1
- data/lib/raindrops/aggregate/pmq.rb +6 -6
- data/lib/raindrops/linux.rb +4 -5
- data/lib/raindrops/middleware/proxy.rb +2 -2
- data/lib/raindrops/middleware.rb +2 -2
- data/lib/raindrops/watcher.rb +7 -7
- data/lib/raindrops.rb +25 -1
- data/pkg.mk +3 -2
- data/raindrops.gemspec +2 -2
- data/test/ipv6_enabled.rb +4 -4
- data/test/test_linux.rb +3 -2
- data/test/test_linux_all_tcp_listen_stats_leak.rb +2 -2
- data/test/test_raindrops.rb +43 -1
- data/test/test_tcp_info.rb +4 -4
- data/test/test_watcher.rb +9 -9
- metadata +5 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6f78e29ec57e3f3710146a423cf60915d23a5f4366d70dcabbbef74fb69f71f3
|
|
4
|
+
data.tar.gz: 8a369d49c33a67af3b6acccaf64b04ed192cba9d163c8d48944cfac887511885
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b9e5de8e7a7a84038bbe19a954d3d559ebec3ed4c7f68db2e2ada6373b045f4fbcd784c5d5b91005cad1d87f1db93f9dc31c9f7fc59ae56a7f73b98d9a96bf2e
|
|
7
|
+
data.tar.gz: 9913e9205b2527b9f5bd1bae58b0c2c8962505e87280c06257f603fb722978d6656c99cfa0a297ccd0734a7d6110b0a6ecd5155fec9870ec40a31044a00def4d
|
data/.olddoc.yml
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
cgit_url: https://
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
public_email: raindrops-public@bogomips.org
|
|
2
|
+
cgit_url: https://yhbt.net/raindrops.git/
|
|
3
|
+
rdoc_url: https://yhbt.net/raindrops/
|
|
4
|
+
public_email: raindrops-public@yhbt.net
|
|
6
5
|
ml_url:
|
|
7
|
-
- https://
|
|
8
|
-
- http://
|
|
6
|
+
- https://yhbt.net/raindrops-public/
|
|
7
|
+
- http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/raindrops-public
|
|
8
|
+
imap_url:
|
|
9
|
+
- imaps://yhbt.net/inbox.comp.lang.ruby.raindrops.0
|
|
10
|
+
- imap://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.raindrops.0
|
|
9
11
|
nntp_url:
|
|
10
|
-
-
|
|
11
|
-
- nntp://
|
|
12
|
+
- nntps://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
|
|
13
|
+
- nntp://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.raindrops
|
|
12
14
|
source_code:
|
|
13
|
-
- git clone
|
|
14
|
-
- git clone
|
|
15
|
+
- git clone https://yhbt.net/raindrops.git
|
|
16
|
+
- torsocks git clone http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/raindrops.git
|
data/GIT-VERSION-FILE
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
GIT_VERSION = 0.
|
|
1
|
+
GIT_VERSION = 0.20.0
|
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
data/LATEST
CHANGED
|
@@ -1,42 +1,10 @@
|
|
|
1
|
-
=== raindrops 0.
|
|
1
|
+
=== raindrops 0.20.0 / 2021-12-06 23:41 UTC
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Raindrops::TCP for portably mapping TCP state names to
|
|
6
|
-
platform-dependent numeric values:
|
|
3
|
+
Raindrops may now use file-backed mmap() rather than anonymous
|
|
4
|
+
memory. Thanks to KJ Tsanaktsidis for the patch:
|
|
7
5
|
|
|
8
|
-
|
|
6
|
+
https://yhbt.net/raindrops-public/20211125065618.3432-1-ktsanaktsidis@zendesk.com/T/
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
these changes to raindrops.
|
|
13
|
-
|
|
14
|
-
There's also a few internal cleanups, and documentation
|
|
15
|
-
improvements, including some fixes to the largely-forgotten
|
|
16
|
-
Raindrops::Aggreage::PMQ class:
|
|
17
|
-
|
|
18
|
-
https://bogomips.org/raindrops/Raindrops/Aggregate/PMQ.html
|
|
19
|
-
|
|
20
|
-
20 changes since 0.17.0:
|
|
21
|
-
|
|
22
|
-
test_inet_diag_socket: fix Fixnum deprecation warning
|
|
23
|
-
TODO: add item for IPv6 breakage
|
|
24
|
-
ext: fix documentation for C ext-defined classes
|
|
25
|
-
TCP_Info: custom documentation for #get!
|
|
26
|
-
TypedData C-API conversion
|
|
27
|
-
test_watcher: disable test correctly when aggregate is missing
|
|
28
|
-
tcp_info: support this struct under FreeBSD
|
|
29
|
-
define Raindrops::TCP hash for TCP states
|
|
30
|
-
linux_inet_diag: reduce stack usage and simplify
|
|
31
|
-
avoid reading errno repeatedly
|
|
32
|
-
aggregate/pmq: avoid false sharing of lock buffers
|
|
33
|
-
aggregate/pmq: remove io-extra requirement
|
|
34
|
-
aggregate/pmq: avoid File#stat allocation
|
|
35
|
-
Merge remote-tracking branch 'origin/freebsd'
|
|
36
|
-
Merge remote-tracking branch 'origin/aggregate-pmq'
|
|
37
|
-
doc: remove private email support address
|
|
38
|
-
doc: update location of TCP_INFO-related stuff
|
|
39
|
-
build: avoid olddoc for building the RubyGem
|
|
40
|
-
doc: document Raindrops::TCP hash
|
|
41
|
-
aggregate/pmq: update version numbers for Ruby and Linux
|
|
8
|
+
The documentation is also updated to note our mail archives are now
|
|
9
|
+
available via IMAP(S).
|
|
42
10
|
|
data/NEWS
CHANGED
|
@@ -1,3 +1,53 @@
|
|
|
1
|
+
=== raindrops 0.20.0 / 2021-12-06 23:41 UTC
|
|
2
|
+
|
|
3
|
+
Raindrops may now use file-backed mmap() rather than anonymous
|
|
4
|
+
memory. Thanks to KJ Tsanaktsidis for the patch:
|
|
5
|
+
|
|
6
|
+
https://yhbt.net/raindrops-public/20211125065618.3432-1-ktsanaktsidis@zendesk.com/T/
|
|
7
|
+
|
|
8
|
+
The documentation is also updated to note our mail archives are now
|
|
9
|
+
available via IMAP(S).
|
|
10
|
+
|
|
11
|
+
=== raindrops 0.19.2 / 2021-05-25 23:13 UTC
|
|
12
|
+
|
|
13
|
+
This release fixes compatibility with GC.compact on Ruby 3.x
|
|
14
|
+
when using ListenStats on Linux. The listener stats
|
|
15
|
+
functionality is rarely used and does not affect most users
|
|
16
|
+
who just have raindrops installed for shared atomic counters.
|
|
17
|
+
|
|
18
|
+
=== raindrops 0.19.1 / 2020-01-08 09:31 UTC
|
|
19
|
+
|
|
20
|
+
This release fixes some warnings on newer Rubies.
|
|
21
|
+
|
|
22
|
+
We're no longer on bogomips.org since it's due
|
|
23
|
+
for expiry and I can't pay extortionists for a .org, so
|
|
24
|
+
s/bogomips.org/yhbt.net/ for now, and be prepared to move again
|
|
25
|
+
when extortionists move onto extorting the .net TLD.
|
|
26
|
+
|
|
27
|
+
doc: switch homepage to dark216
|
|
28
|
+
ext/raindrops/extconf: fix cflags reset on ancient CC
|
|
29
|
+
fixes for newer rubies
|
|
30
|
+
replace bogomips.org with yhbt.net
|
|
31
|
+
|
|
32
|
+
=== raindrops 0.19.0 - Rack 2.x middleware compatibility / 2017-08-09 23:52 UTC
|
|
33
|
+
|
|
34
|
+
This release fixes Rack 2.x compatibility for the few users of
|
|
35
|
+
Raindrops::Middleware
|
|
36
|
+
<https://bogomips.org/raindrops/Raindrops/Middleware.html>.
|
|
37
|
+
Thanks to Dmytro Shteflyuk for this release.
|
|
38
|
+
|
|
39
|
+
No need to upgrade unless you use Raindrops::Middleware with
|
|
40
|
+
Rack 2.x.
|
|
41
|
+
|
|
42
|
+
There's also a few minor, inconsequential cleanups.
|
|
43
|
+
|
|
44
|
+
Dmytro Shteflyuk (1):
|
|
45
|
+
Properly override respond_to? in Raindrops::Middleware::Proxy
|
|
46
|
+
|
|
47
|
+
Eric Wong (2):
|
|
48
|
+
Ruby thread compatibility updates
|
|
49
|
+
tcp_info: remove unnecessary extconf.h include
|
|
50
|
+
|
|
1
51
|
=== raindrops 0.18.0 / 2017-03-23 02:44 UTC
|
|
2
52
|
|
|
3
53
|
The most notable feature of this release is the addition of
|
data/README
CHANGED
|
@@ -58,24 +58,20 @@ If you use RubyGems:
|
|
|
58
58
|
|
|
59
59
|
See Raindrops::Middleware and Raindrops::LastDataRecv documentation for
|
|
60
60
|
use Rack servers. The entire library is fully-documented and we are
|
|
61
|
-
responsive on the
|
|
62
|
-
(mailto:raindrops-public@
|
|
63
|
-
you have any questions or comments.
|
|
61
|
+
responsive on the publicly archived mailbox
|
|
62
|
+
(mailto:raindrops-public@yhbt.net) if you have any questions or comments.
|
|
64
63
|
|
|
65
64
|
== Development
|
|
66
65
|
|
|
67
66
|
You can get the latest source via git from the following locations:
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
https://yhbt.net/raindrops.git
|
|
69
|
+
http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/raindrops.git
|
|
70
|
+
http://repo.or.cz/w/raindrops.git (gitweb mirror)
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
tarballs here:
|
|
72
|
+
Snapshots and tarballs are available.
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
* http://repo.or.cz/w/raindrops.git (gitweb)
|
|
77
|
-
|
|
78
|
-
Inline patches (from "git format-patch") to the mailing list are
|
|
74
|
+
Inline patches (from "git format-patch") to the mailbox are
|
|
79
75
|
preferred because they allow code review and comments in the reply to
|
|
80
76
|
the patch.
|
|
81
77
|
|
|
@@ -89,13 +85,17 @@ raindrops is licensed under the LGPL-2.1+
|
|
|
89
85
|
== Contact
|
|
90
86
|
|
|
91
87
|
All feedback (bug reports, user/development discussion, patches, pull
|
|
92
|
-
requests) go to the
|
|
93
|
-
mailto:raindrops-public@
|
|
88
|
+
requests) go to the publicly archived mailbox:
|
|
89
|
+
mailto:raindrops-public@yhbt.net
|
|
94
90
|
|
|
95
|
-
|
|
91
|
+
Mail archives are available over HTTP(S), IMAP(S) and NNTP(S):
|
|
96
92
|
|
|
97
|
-
* https://
|
|
98
|
-
*
|
|
93
|
+
* https://yhbt.net/raindrops-public/
|
|
94
|
+
* http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/raindrops-public/
|
|
95
|
+
* imaps://yhbt.net/inbox.comp.lang.ruby.raindrops.0
|
|
96
|
+
* imap://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.raindrops.0
|
|
97
|
+
* nntps://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
|
|
98
|
+
* nntp://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.raindrops
|
|
99
99
|
|
|
100
100
|
Since archives are public, scrub sensitive information and
|
|
101
101
|
use anonymity tools such as Tor or Mixmaster if you deem necessary.
|
|
@@ -15,7 +15,6 @@ end
|
|
|
15
15
|
usage = "Usage: #$0 [-d DELAY] [-t QUEUED_THRESHOLD] ADDR..."
|
|
16
16
|
ARGV.size > 0 or abort usage
|
|
17
17
|
delay = false
|
|
18
|
-
all = false
|
|
19
18
|
queued_thresh = -1
|
|
20
19
|
# "normal" exits when driven on the command-line
|
|
21
20
|
trap(:INT) { exit 130 }
|
|
@@ -25,7 +24,7 @@ OptionParser.new('', 24, ' ') do |opts|
|
|
|
25
24
|
opts.banner = usage
|
|
26
25
|
opts.on('-d', '--delay=DELAY', Float) { |n| delay = n }
|
|
27
26
|
opts.on('-t', '--queued-threshold=INT', Integer) { |n| queued_thresh = n }
|
|
28
|
-
opts.on('-a', '--all') {
|
|
27
|
+
opts.on('-a', '--all') { } # noop
|
|
29
28
|
opts.parse! ARGV
|
|
30
29
|
end
|
|
31
30
|
|
data/examples/watcher_demo.ru
CHANGED
data/ext/raindrops/extconf.rb
CHANGED
|
@@ -112,6 +112,7 @@ EOF
|
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
have_func("getpagesize", "unistd.h")
|
|
115
|
+
have_func('rb_thread_call_without_gvl')
|
|
115
116
|
have_func('rb_thread_blocking_region')
|
|
116
117
|
have_func('rb_thread_io_blocking_region')
|
|
117
118
|
|
|
@@ -142,7 +143,7 @@ SRC
|
|
|
142
143
|
$defs.push(format("-DHAVE_GCC_ATOMIC_BUILTINS"))
|
|
143
144
|
true
|
|
144
145
|
else
|
|
145
|
-
|
|
146
|
+
$CFLAGS = prev_cflags
|
|
146
147
|
false
|
|
147
148
|
end
|
|
148
149
|
end
|
|
@@ -1,46 +1,24 @@
|
|
|
1
1
|
#include <ruby.h>
|
|
2
2
|
#include <stdarg.h>
|
|
3
|
-
#
|
|
4
|
-
# include <ruby/st.h>
|
|
5
|
-
#else
|
|
6
|
-
# include <st.h>
|
|
7
|
-
#endif
|
|
3
|
+
#include <ruby/st.h>
|
|
8
4
|
#include "my_fileno.h"
|
|
9
5
|
#ifdef __linux__
|
|
10
6
|
|
|
11
|
-
/* Ruby 1.8.6+ macros (for compatibility with Ruby 1.9) */
|
|
12
|
-
#ifndef RSTRING_LEN
|
|
13
|
-
# define RSTRING_LEN(s) (RSTRING(s)->len)
|
|
14
|
-
#endif
|
|
15
|
-
|
|
16
|
-
/* partial emulation of the 1.9 rb_thread_blocking_region under 1.8 */
|
|
17
|
-
#if !defined(HAVE_RB_THREAD_BLOCKING_REGION) && \
|
|
18
|
-
!defined(HAVE_RB_THREAD_IO_BLOCKING_REGION)
|
|
19
|
-
# include <rubysig.h>
|
|
20
|
-
# define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
|
|
21
|
-
typedef void rb_unblock_function_t(void *);
|
|
22
|
-
typedef VALUE rb_blocking_function_t(void *);
|
|
23
|
-
static VALUE
|
|
24
|
-
rb_thread_blocking_region(
|
|
25
|
-
rb_blocking_function_t *func, void *data1,
|
|
26
|
-
rb_unblock_function_t *ubf, void *data2)
|
|
27
|
-
{
|
|
28
|
-
VALUE rv;
|
|
29
|
-
|
|
30
|
-
TRAP_BEG;
|
|
31
|
-
rv = func(data1);
|
|
32
|
-
TRAP_END;
|
|
33
|
-
|
|
34
|
-
return rv;
|
|
35
|
-
}
|
|
36
|
-
#endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
|
|
37
|
-
|
|
38
7
|
#ifdef HAVE_RB_THREAD_IO_BLOCKING_REGION
|
|
8
|
+
/* Ruby 1.9.3 and 2.0.0 */
|
|
39
9
|
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *, void *, int);
|
|
10
|
+
# define rd_fd_region(fn,data,fd) \
|
|
11
|
+
rb_thread_io_blocking_region((fn),(data),(fd))
|
|
12
|
+
#elif defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && \
|
|
13
|
+
defined(HAVE_RUBY_THREAD_H) && HAVE_RUBY_THREAD_H
|
|
14
|
+
/* in case Ruby 2.0+ ever drops rb_thread_io_blocking_region: */
|
|
15
|
+
# include <ruby/thread.h>
|
|
16
|
+
# define COMPAT_FN (void *(*)(void *))
|
|
17
|
+
# define rd_fd_region(fn,data,fd) \
|
|
18
|
+
rb_thread_call_without_gvl(COMPAT_FN(fn),(data),RUBY_UBF_IO,NULL)
|
|
40
19
|
#else
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
#endif /* HAVE_RB_THREAD_IO_BLOCKING_REGION */
|
|
20
|
+
# error Ruby <= 1.8 not supported
|
|
21
|
+
#endif
|
|
44
22
|
|
|
45
23
|
#include <assert.h>
|
|
46
24
|
#include <errno.h>
|
|
@@ -227,7 +205,7 @@ static void bug_warn_nogvl(const char *fmt, ...)
|
|
|
227
205
|
va_end(ap);
|
|
228
206
|
|
|
229
207
|
fprintf(stderr, "Please report how you produced this at "\
|
|
230
|
-
"raindrops-public@
|
|
208
|
+
"raindrops-public@yhbt.net\n");
|
|
231
209
|
fflush(stderr);
|
|
232
210
|
}
|
|
233
211
|
|
|
@@ -608,7 +586,7 @@ static VALUE tcp_stats(struct nogvl_args *args, VALUE addr)
|
|
|
608
586
|
gen_bytecode(&args->iov[2], &query_addr);
|
|
609
587
|
|
|
610
588
|
memset(&args->stats, 0, sizeof(struct listen_stats));
|
|
611
|
-
nl_errcheck(
|
|
589
|
+
nl_errcheck(rd_fd_region(diag, args, args->fd));
|
|
612
590
|
|
|
613
591
|
return rb_listen_stats(&args->stats);
|
|
614
592
|
}
|
|
@@ -685,7 +663,7 @@ static VALUE tcp_listener_stats(int argc, VALUE *argv, VALUE self)
|
|
|
685
663
|
"addr must be an array of strings, a string, or nil");
|
|
686
664
|
}
|
|
687
665
|
|
|
688
|
-
nl_errcheck(
|
|
666
|
+
nl_errcheck(rd_fd_region(diag, &args, args.fd));
|
|
689
667
|
|
|
690
668
|
st_foreach(args.table, NIL_P(addrs) ? st_to_hash : st_AND_hash, rv);
|
|
691
669
|
st_free_table(args.table);
|
|
@@ -718,6 +696,7 @@ void Init_raindrops_linux_inet_diag(void)
|
|
|
718
696
|
rb_define_singleton_method(cIDSock, "new", ids_s_new, 0);
|
|
719
697
|
|
|
720
698
|
cListenStats = rb_const_get(cRaindrops, rb_intern("ListenStats"));
|
|
699
|
+
rb_gc_register_mark_object(cListenStats); /* pin */
|
|
721
700
|
|
|
722
701
|
rb_define_module_function(mLinux, "tcp_listener_stats",
|
|
723
702
|
tcp_listener_stats, -1);
|
data/ext/raindrops/raindrops.c
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <assert.h>
|
|
5
5
|
#include <errno.h>
|
|
6
6
|
#include <stddef.h>
|
|
7
|
+
#include <string.h>
|
|
7
8
|
#include "raindrops_atomic.h"
|
|
8
9
|
|
|
9
10
|
#ifndef SIZET2NUM
|
|
@@ -34,9 +35,17 @@ struct raindrops {
|
|
|
34
35
|
size_t size;
|
|
35
36
|
size_t capa;
|
|
36
37
|
pid_t pid;
|
|
38
|
+
VALUE io;
|
|
37
39
|
struct raindrop *drops;
|
|
38
40
|
};
|
|
39
41
|
|
|
42
|
+
/* called by GC */
|
|
43
|
+
static void rd_mark(void *ptr)
|
|
44
|
+
{
|
|
45
|
+
struct raindrops *r = ptr;
|
|
46
|
+
rb_gc_mark(r->io);
|
|
47
|
+
}
|
|
48
|
+
|
|
40
49
|
/* called by GC */
|
|
41
50
|
static void rd_free(void *ptr)
|
|
42
51
|
{
|
|
@@ -60,7 +69,7 @@ static size_t rd_memsize(const void *ptr)
|
|
|
60
69
|
|
|
61
70
|
static const rb_data_type_t rd_type = {
|
|
62
71
|
"raindrops",
|
|
63
|
-
{
|
|
72
|
+
{ rd_mark, rd_free, rd_memsize, /* reserved */ },
|
|
64
73
|
/* parent, data, [ flags ] */
|
|
65
74
|
};
|
|
66
75
|
|
|
@@ -87,16 +96,10 @@ static struct raindrops *get(VALUE self)
|
|
|
87
96
|
}
|
|
88
97
|
|
|
89
98
|
/*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* Initializes a Raindrops object to hold +size+ counters. +size+ is
|
|
94
|
-
* only a hint and the actual number of counters the object has is
|
|
95
|
-
* dependent on the CPU model, number of cores, and page size of
|
|
96
|
-
* the machine. The actual size of the object will always be equal
|
|
97
|
-
* or greater than the specified +size+.
|
|
99
|
+
* This is the _actual_ implementation of #initialize - the Ruby wrapper
|
|
100
|
+
* handles keyword-argument handling then calls this method.
|
|
98
101
|
*/
|
|
99
|
-
static VALUE
|
|
102
|
+
static VALUE init_cimpl(VALUE self, VALUE size, VALUE io, VALUE zero)
|
|
100
103
|
{
|
|
101
104
|
struct raindrops *r = DATA_PTR(self);
|
|
102
105
|
int tries = 1;
|
|
@@ -113,9 +116,19 @@ static VALUE init(VALUE self, VALUE size)
|
|
|
113
116
|
r->capa = tmp / raindrop_size;
|
|
114
117
|
assert(PAGE_ALIGN(raindrop_size * r->capa) == tmp && "not aligned");
|
|
115
118
|
|
|
119
|
+
r->io = io;
|
|
120
|
+
|
|
116
121
|
retry:
|
|
117
|
-
r->
|
|
118
|
-
|
|
122
|
+
if (RTEST(r->io)) {
|
|
123
|
+
int fd = NUM2INT(rb_funcall(r->io, rb_intern("fileno"), 0));
|
|
124
|
+
rb_funcall(r->io, rb_intern("truncate"), 1, SIZET2NUM(tmp));
|
|
125
|
+
r->drops = mmap(NULL, tmp,
|
|
126
|
+
PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
|
127
|
+
} else {
|
|
128
|
+
r->drops = mmap(NULL, tmp,
|
|
129
|
+
PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
|
|
130
|
+
-1, 0);
|
|
131
|
+
}
|
|
119
132
|
if (r->drops == MAP_FAILED) {
|
|
120
133
|
int err = errno;
|
|
121
134
|
|
|
@@ -127,6 +140,9 @@ retry:
|
|
|
127
140
|
}
|
|
128
141
|
r->pid = getpid();
|
|
129
142
|
|
|
143
|
+
if (RTEST(zero))
|
|
144
|
+
memset(r->drops, 0, tmp);
|
|
145
|
+
|
|
130
146
|
return self;
|
|
131
147
|
}
|
|
132
148
|
|
|
@@ -217,14 +233,16 @@ static VALUE capa(VALUE self)
|
|
|
217
233
|
* call-seq:
|
|
218
234
|
* rd.dup -> rd_copy
|
|
219
235
|
*
|
|
220
|
-
* Duplicates and snapshots the current state of a Raindrops object.
|
|
236
|
+
* Duplicates and snapshots the current state of a Raindrops object. Even
|
|
237
|
+
* if the given Raindrops object is backed by a file, the copy will be backed
|
|
238
|
+
* by independent, anonymously mapped memory.
|
|
221
239
|
*/
|
|
222
240
|
static VALUE init_copy(VALUE dest, VALUE source)
|
|
223
241
|
{
|
|
224
242
|
struct raindrops *dst = DATA_PTR(dest);
|
|
225
243
|
struct raindrops *src = get(source);
|
|
226
244
|
|
|
227
|
-
|
|
245
|
+
init_cimpl(dest, SIZET2NUM(src->size), Qnil, Qfalse);
|
|
228
246
|
memcpy(dst->drops, src->drops, raindrop_size * src->size);
|
|
229
247
|
|
|
230
248
|
return dest;
|
|
@@ -375,6 +393,20 @@ static VALUE evaporate_bang(VALUE self)
|
|
|
375
393
|
return Qnil;
|
|
376
394
|
}
|
|
377
395
|
|
|
396
|
+
/*
|
|
397
|
+
* call-seq:
|
|
398
|
+
* to_io -> IO
|
|
399
|
+
*
|
|
400
|
+
* Returns the IO object backing the memory for this raindrop, if
|
|
401
|
+
* one was specified when constructing this Raindrop. If this
|
|
402
|
+
* Raindrop is backed by anonymous memory, this method returns nil.
|
|
403
|
+
*/
|
|
404
|
+
static VALUE to_io(VALUE self)
|
|
405
|
+
{
|
|
406
|
+
struct raindrops *r = get(self);
|
|
407
|
+
return r->io;
|
|
408
|
+
}
|
|
409
|
+
|
|
378
410
|
void Init_raindrops_ext(void)
|
|
379
411
|
{
|
|
380
412
|
VALUE cRaindrops = rb_define_class("Raindrops", rb_cObject);
|
|
@@ -433,7 +465,7 @@ void Init_raindrops_ext(void)
|
|
|
433
465
|
|
|
434
466
|
rb_define_alloc_func(cRaindrops, alloc);
|
|
435
467
|
|
|
436
|
-
|
|
468
|
+
rb_define_private_method(cRaindrops, "initialize_cimpl", init_cimpl, 3);
|
|
437
469
|
rb_define_method(cRaindrops, "incr", incr, -1);
|
|
438
470
|
rb_define_method(cRaindrops, "decr", decr, -1);
|
|
439
471
|
rb_define_method(cRaindrops, "to_ary", to_ary, 0);
|
|
@@ -444,6 +476,7 @@ void Init_raindrops_ext(void)
|
|
|
444
476
|
rb_define_method(cRaindrops, "capa", capa, 0);
|
|
445
477
|
rb_define_method(cRaindrops, "initialize_copy", init_copy, 1);
|
|
446
478
|
rb_define_method(cRaindrops, "evaporate!", evaporate_bang, 0);
|
|
479
|
+
rb_define_method(cRaindrops, "to_io", to_io, 0);
|
|
447
480
|
|
|
448
481
|
#ifdef __linux__
|
|
449
482
|
Init_raindrops_linux_inet_diag();
|
data/ext/raindrops/tcp_info.c
CHANGED
|
@@ -142,8 +142,8 @@ class Raindrops::Aggregate::PMQ
|
|
|
142
142
|
warn "Unhandled exception in #{__FILE__}:#{__LINE__}: #{e}"
|
|
143
143
|
break
|
|
144
144
|
end while true
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
ensure
|
|
146
|
+
flush_master
|
|
147
147
|
end
|
|
148
148
|
|
|
149
149
|
# Loads the last shared \Aggregate from the master thread/process
|
|
@@ -175,14 +175,14 @@ class Raindrops::Aggregate::PMQ
|
|
|
175
175
|
# worker thread or process
|
|
176
176
|
def stop_master_loop
|
|
177
177
|
sleep 0.1 until mq_send(false)
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
rescue Errno::EINTR
|
|
179
|
+
retry
|
|
180
180
|
end
|
|
181
181
|
|
|
182
182
|
def lock! io, type # :nodoc:
|
|
183
183
|
io.fcntl Fcntl::F_SETLKW, type
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
rescue Errno::EINTR
|
|
185
|
+
retry
|
|
186
186
|
end
|
|
187
187
|
|
|
188
188
|
# we use both a mutex for thread-safety and fcntl lock for process-safety
|
data/lib/raindrops/linux.rb
CHANGED
|
@@ -14,8 +14,7 @@ module Raindrops::Linux
|
|
|
14
14
|
# The standard proc path for active UNIX domain sockets, feel free to call
|
|
15
15
|
# String#replace on this if your /proc is mounted in a non-standard location
|
|
16
16
|
# for whatever reason
|
|
17
|
-
PROC_NET_UNIX_ARGS =
|
|
18
|
-
defined?(::Encoding) and PROC_NET_UNIX_ARGS.push({ :encoding => "binary" })
|
|
17
|
+
PROC_NET_UNIX_ARGS = [ '/proc/net/unix', { encoding: "binary" }]
|
|
19
18
|
|
|
20
19
|
# Get ListenStats from an array of +paths+
|
|
21
20
|
#
|
|
@@ -42,11 +41,11 @@ module Raindrops::Linux
|
|
|
42
41
|
else
|
|
43
42
|
paths = paths.map do |path|
|
|
44
43
|
path = path.dup
|
|
45
|
-
path.force_encoding(Encoding::BINARY)
|
|
44
|
+
path.force_encoding(Encoding::BINARY)
|
|
46
45
|
if File.symlink?(path)
|
|
47
46
|
link = path
|
|
48
47
|
path = File.readlink(link)
|
|
49
|
-
path.force_encoding(Encoding::BINARY)
|
|
48
|
+
path.force_encoding(Encoding::BINARY)
|
|
50
49
|
rv[link] = rv[path] # vivify ListenerStats
|
|
51
50
|
else
|
|
52
51
|
rv[path] # vivify ListenerStats
|
|
@@ -57,7 +56,7 @@ module Raindrops::Linux
|
|
|
57
56
|
paths = /^\w+: \d+ \d+ (\d+) \d+ (\d+)\s+\d+ (#{paths.join('|')})$/n
|
|
58
57
|
|
|
59
58
|
# no point in pread since we can't stat for size on this file
|
|
60
|
-
File.read(
|
|
59
|
+
File.read(PROC_NET_UNIX_ARGS[0], encoding: 'binary').scan(paths) do |s|
|
|
61
60
|
path = s[-1]
|
|
62
61
|
case s[0]
|
|
63
62
|
when "00000000" # client sockets
|
|
@@ -27,9 +27,9 @@ class Raindrops::Middleware::Proxy
|
|
|
27
27
|
|
|
28
28
|
# Rack servers use +respond_to?+ to check for the presence of +close+
|
|
29
29
|
# and +to_path+ methods.
|
|
30
|
-
def respond_to?(m)
|
|
30
|
+
def respond_to?(m, include_all = false)
|
|
31
31
|
m = m.to_sym
|
|
32
|
-
:close == m || @body.respond_to?(m)
|
|
32
|
+
:close == m || @body.respond_to?(m, include_all)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
# Avoid breaking users of non-standard extensions (e.g. #body)
|
data/lib/raindrops/middleware.rb
CHANGED
|
@@ -62,9 +62,9 @@ require 'raindrops'
|
|
|
62
62
|
# = Demo Server
|
|
63
63
|
#
|
|
64
64
|
# There is a server running this middleware (and Watcher) at
|
|
65
|
-
# https://raindrops-demo
|
|
65
|
+
# https://yhbt.net/raindrops-demo/_raindrops
|
|
66
66
|
#
|
|
67
|
-
# Also check out the Watcher demo at https://raindrops-demo
|
|
67
|
+
# Also check out the Watcher demo at https://yhbt.net/raindrops-demo/
|
|
68
68
|
#
|
|
69
69
|
# The demo server is only limited to 30 users, so be sure not to abuse it
|
|
70
70
|
# by using the /tail/ endpoint too much.
|
data/lib/raindrops/watcher.rb
CHANGED
|
@@ -35,28 +35,28 @@ require "aggregate"
|
|
|
35
35
|
# Returns a plain text summary + histogram with X-* HTTP headers for
|
|
36
36
|
# active connections.
|
|
37
37
|
#
|
|
38
|
-
# e.g.: curl https://raindrops-demo
|
|
38
|
+
# e.g.: curl https://yhbt.net/raindrops-demo/active/0.0.0.0%3A80.txt
|
|
39
39
|
#
|
|
40
40
|
# === GET /active/$LISTENER.html
|
|
41
41
|
#
|
|
42
42
|
# Returns an HTML summary + histogram with X-* HTTP headers for
|
|
43
43
|
# active connections.
|
|
44
44
|
#
|
|
45
|
-
# e.g.: curl https://raindrops-demo
|
|
45
|
+
# e.g.: curl https://yhbt.net/raindrops-demo/active/0.0.0.0%3A80.html
|
|
46
46
|
#
|
|
47
47
|
# === GET /queued/$LISTENER.txt
|
|
48
48
|
#
|
|
49
49
|
# Returns a plain text summary + histogram with X-* HTTP headers for
|
|
50
50
|
# queued connections.
|
|
51
51
|
#
|
|
52
|
-
# e.g.: curl https://raindrops-demo
|
|
52
|
+
# e.g.: curl https://yhbt.net/raindrops-demo/queued/0.0.0.0%3A80.txt
|
|
53
53
|
#
|
|
54
54
|
# === GET /queued/$LISTENER.html
|
|
55
55
|
#
|
|
56
56
|
# Returns an HTML summary + histogram with X-* HTTP headers for
|
|
57
57
|
# queued connections.
|
|
58
58
|
#
|
|
59
|
-
# e.g.: curl https://raindrops-demo
|
|
59
|
+
# e.g.: curl https://yhbt.net/raindrops-demo/queued/0.0.0.0%3A80.html
|
|
60
60
|
#
|
|
61
61
|
# === POST /reset/$LISTENER
|
|
62
62
|
#
|
|
@@ -95,9 +95,9 @@ require "aggregate"
|
|
|
95
95
|
#
|
|
96
96
|
# = Demo Server
|
|
97
97
|
#
|
|
98
|
-
# There is a server running this app at https://raindrops-demo
|
|
98
|
+
# There is a server running this app at https://yhbt.net/raindrops-demo/
|
|
99
99
|
# The Raindrops::Middleware demo is also accessible at
|
|
100
|
-
# https://raindrops-demo
|
|
100
|
+
# https://yhbt.net/raindrops-demo/_raindrops
|
|
101
101
|
#
|
|
102
102
|
# The demo server is only limited to 30 users, so be sure not to abuse it
|
|
103
103
|
# by using the /tail/ endpoint too much.
|
|
@@ -106,7 +106,7 @@ class Raindrops::Watcher
|
|
|
106
106
|
attr_reader :snapshot
|
|
107
107
|
include Rack::Utils
|
|
108
108
|
include Raindrops::Linux
|
|
109
|
-
DOC_URL = "https://
|
|
109
|
+
DOC_URL = "https://yhbt.net/raindrops/Raindrops/Watcher.html"
|
|
110
110
|
Peak = Struct.new(:first, :last)
|
|
111
111
|
|
|
112
112
|
def initialize(opts = {})
|
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-public@
|
|
15
|
+
# issues, patches or pull requests at mailto:raindrops-public@yhbt.net
|
|
16
16
|
class Raindrops
|
|
17
17
|
|
|
18
18
|
# Used to represent the number of +active+ and +queued+ sockets for
|
|
@@ -36,6 +36,30 @@ class Raindrops
|
|
|
36
36
|
def total
|
|
37
37
|
active + queued
|
|
38
38
|
end
|
|
39
|
+
end unless defined? ListenStats
|
|
40
|
+
|
|
41
|
+
# call-seq:
|
|
42
|
+
# Raindrops.new(size, io: nil) -> raindrops object
|
|
43
|
+
#
|
|
44
|
+
# Initializes a Raindrops object to hold +size+ counters. +size+ is
|
|
45
|
+
# only a hint and the actual number of counters the object has is
|
|
46
|
+
# dependent on the CPU model, number of cores, and page size of
|
|
47
|
+
# the machine. The actual size of the object will always be equal
|
|
48
|
+
# or greater than the specified +size+.
|
|
49
|
+
# If +io+ is provided, then the Raindrops memory will be backed by
|
|
50
|
+
# the specified file; otherwise, it will allocate anonymous memory.
|
|
51
|
+
# The IO object must respond to +truncate+, as this is used to set
|
|
52
|
+
# the size of the file.
|
|
53
|
+
# If +zero+ is provided, then the memory region is zeroed prior to
|
|
54
|
+
# returning. This is only meaningful if +io+ is also provided; in
|
|
55
|
+
# that case it controls whether any existing counter values in +io+
|
|
56
|
+
# are retained (false) or whether it is entirely zeroed (true).
|
|
57
|
+
def initialize(size, io: nil, zero: false)
|
|
58
|
+
# This ruby wrapper exists to handle the keyword-argument handling,
|
|
59
|
+
# which is otherwise kind of awkward in C. We delegate the keyword
|
|
60
|
+
# arguments to the _actual_ initialize implementation as positional
|
|
61
|
+
# args.
|
|
62
|
+
initialize_cimpl(size, io, zero)
|
|
39
63
|
end
|
|
40
64
|
|
|
41
65
|
autoload :Linux, 'raindrops/linux'
|
data/pkg.mk
CHANGED
|
@@ -60,7 +60,7 @@ doc:: .document .olddoc.yml $(pkg_extra) $(PLACEHOLDERS)
|
|
|
60
60
|
-find lib -type f -name '*.rbc' -exec rm -f '{}' ';'
|
|
61
61
|
-find ext -type f -name '*.rbc' -exec rm -f '{}' ';'
|
|
62
62
|
$(RM) -r doc
|
|
63
|
-
$(RDOC) -f
|
|
63
|
+
$(RDOC) -f dark216
|
|
64
64
|
$(OLDDOC) merge
|
|
65
65
|
install -m644 COPYING doc/COPYING
|
|
66
66
|
install -m644 NEWS doc/NEWS
|
|
@@ -127,7 +127,8 @@ publish_doc:
|
|
|
127
127
|
-git set-file-times
|
|
128
128
|
$(MAKE) doc
|
|
129
129
|
$(MAKE) doc_gz
|
|
130
|
-
$(RSYNC) -av doc/ $(RSYNC_DEST)/
|
|
130
|
+
$(RSYNC) -av doc/ $(RSYNC_DEST)/ \
|
|
131
|
+
--exclude index.html* --exclude created.rid*
|
|
131
132
|
git ls-files | xargs touch
|
|
132
133
|
endif
|
|
133
134
|
|
data/raindrops.gemspec
CHANGED
|
@@ -8,13 +8,13 @@ Gem::Specification.new do |s|
|
|
|
8
8
|
s.version = (ENV["VERSION"] ||= '0.18.0').dup
|
|
9
9
|
s.authors = ["raindrops hackers"]
|
|
10
10
|
s.description = File.read('README').split("\n\n")[1]
|
|
11
|
-
s.email = %q{raindrops-public@
|
|
11
|
+
s.email = %q{raindrops-public@yhbt.net}
|
|
12
12
|
s.extensions = %w(ext/raindrops/extconf.rb)
|
|
13
13
|
s.extra_rdoc_files = IO.readlines('.document').map!(&:chomp!).keep_if do |f|
|
|
14
14
|
File.exist?(f)
|
|
15
15
|
end
|
|
16
16
|
s.files = manifest
|
|
17
|
-
s.homepage = 'https://
|
|
17
|
+
s.homepage = 'https://yhbt.net/raindrops/'
|
|
18
18
|
s.summary = 'real-time stats for preforking Rack servers'
|
|
19
19
|
s.required_ruby_version = '>= 1.9.3'
|
|
20
20
|
s.test_files = test_files
|
data/test/ipv6_enabled.rb
CHANGED
|
@@ -2,8 +2,8 @@ def ipv6_enabled?
|
|
|
2
2
|
tmp = TCPServer.new(ENV["TEST_HOST6"] || '::1', 0)
|
|
3
3
|
tmp.close
|
|
4
4
|
true
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
rescue => e
|
|
6
|
+
warn "skipping IPv6 tests, host does not seem to be IPv6 enabled:"
|
|
7
|
+
warn " #{e.class}: #{e}"
|
|
8
|
+
false
|
|
9
9
|
end
|
data/test/test_linux.rb
CHANGED
|
@@ -76,6 +76,7 @@ class TestLinux < Test::Unit::TestCase
|
|
|
76
76
|
|
|
77
77
|
assert_equal 0, stats[tmp.path].active
|
|
78
78
|
assert_equal 0, stats[tmp.path].queued
|
|
79
|
+
us.close
|
|
79
80
|
end
|
|
80
81
|
|
|
81
82
|
def test_unix_resolves_symlinks
|
|
@@ -151,8 +152,8 @@ class TestLinux < Test::Unit::TestCase
|
|
|
151
152
|
assert_equal 1, stats.size
|
|
152
153
|
assert_equal 0, stats[addr].queued
|
|
153
154
|
assert_equal 1, stats[addr].active
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
ensure
|
|
156
|
+
nlsock.close
|
|
156
157
|
end
|
|
157
158
|
|
|
158
159
|
def test_tcp_multi
|
data/test/test_raindrops.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# -*- encoding: binary -*-
|
|
2
2
|
require 'test/unit'
|
|
3
3
|
require 'raindrops'
|
|
4
|
+
require 'tempfile'
|
|
4
5
|
|
|
5
6
|
class TestRaindrops < Test::Unit::TestCase
|
|
6
7
|
|
|
@@ -134,7 +135,7 @@ class TestRaindrops < Test::Unit::TestCase
|
|
|
134
135
|
assert_equal 0, rd[rd.capa - 1]
|
|
135
136
|
assert_equal 1, rd.incr(rd.capa - 1)
|
|
136
137
|
assert_raises(ArgumentError) { rd[rd.capa] }
|
|
137
|
-
|
|
138
|
+
rescue RangeError
|
|
138
139
|
end # if RUBY_PLATFORM =~ /linux/
|
|
139
140
|
|
|
140
141
|
def test_evaporate
|
|
@@ -162,4 +163,45 @@ class TestRaindrops < Test::Unit::TestCase
|
|
|
162
163
|
assert status.success?
|
|
163
164
|
assert_equal [ 1, 2 ], tmp.to_ary
|
|
164
165
|
end
|
|
166
|
+
|
|
167
|
+
def test_io_backed
|
|
168
|
+
file = Tempfile.new('test_io_backed')
|
|
169
|
+
rd = Raindrops.new(4, io: file, zero: true)
|
|
170
|
+
rd[0] = 123
|
|
171
|
+
rd[1] = 456
|
|
172
|
+
|
|
173
|
+
assert_equal 123, rd[0]
|
|
174
|
+
assert_equal 456, rd[1]
|
|
175
|
+
|
|
176
|
+
rd.evaporate!
|
|
177
|
+
|
|
178
|
+
file.rewind
|
|
179
|
+
data = file.read
|
|
180
|
+
assert_equal 123, data.unpack('L!')[0]
|
|
181
|
+
assert_equal 456, data[Raindrops::SIZE..data.size].unpack('L!')[0]
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def test_io_backed_reuse
|
|
185
|
+
file = Tempfile.new('test_io_backed')
|
|
186
|
+
rd = Raindrops.new(4, io: file, zero: true)
|
|
187
|
+
rd[0] = 123
|
|
188
|
+
rd[1] = 456
|
|
189
|
+
rd.evaporate!
|
|
190
|
+
|
|
191
|
+
rd = Raindrops.new(4, io: file, zero: false)
|
|
192
|
+
assert_equal 123, rd[0]
|
|
193
|
+
assert_equal 456, rd[1]
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def test_iobacked_noreuse
|
|
197
|
+
file = Tempfile.new('test_io_backed')
|
|
198
|
+
rd = Raindrops.new(4, io: file, zero: true)
|
|
199
|
+
rd[0] = 123
|
|
200
|
+
rd[1] = 456
|
|
201
|
+
rd.evaporate!
|
|
202
|
+
|
|
203
|
+
rd = Raindrops.new(4, io: file, zero: true)
|
|
204
|
+
assert_equal 0, rd[0]
|
|
205
|
+
assert_equal 0, rd[1]
|
|
206
|
+
end
|
|
165
207
|
end
|
data/test/test_tcp_info.rb
CHANGED
|
@@ -60,10 +60,10 @@ class TestTCP_Info < Test::Unit::TestCase
|
|
|
60
60
|
a = s.accept
|
|
61
61
|
i = Raindrops::TCP_Info.new(a)
|
|
62
62
|
assert i.last_data_recv >= delay_ms, "#{i.last_data_recv} < #{delay_ms}"
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
ensure
|
|
64
|
+
c.close if c
|
|
65
|
+
a.close if a
|
|
66
|
+
s.close
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
def test_tcp_server_state_closed
|
data/test/test_watcher.rb
CHANGED
|
@@ -118,28 +118,28 @@ class TestWatcher < Test::Unit::TestCase
|
|
|
118
118
|
|
|
119
119
|
def test_x_current_header
|
|
120
120
|
env = @req.class.env_for "/active/#@addr.txt"
|
|
121
|
-
|
|
121
|
+
_status, headers, _body = @app.call(env)
|
|
122
122
|
assert_equal "0", headers["X-Current"], headers.inspect
|
|
123
123
|
|
|
124
124
|
env = @req.class.env_for "/queued/#@addr.txt"
|
|
125
|
-
|
|
125
|
+
_status, headers, _body = @app.call(env)
|
|
126
126
|
assert_equal "1", headers["X-Current"], headers.inspect
|
|
127
127
|
|
|
128
128
|
@ios << @srv.accept
|
|
129
129
|
sleep 0.1
|
|
130
130
|
|
|
131
131
|
env = @req.class.env_for "/queued/#@addr.txt"
|
|
132
|
-
|
|
132
|
+
_status, headers, _body = @app.call(env)
|
|
133
133
|
assert_equal "0", headers["X-Current"], headers.inspect
|
|
134
134
|
|
|
135
135
|
env = @req.class.env_for "/active/#@addr.txt"
|
|
136
|
-
|
|
136
|
+
_status, headers, _body = @app.call(env)
|
|
137
137
|
assert_equal "1", headers["X-Current"], headers.inspect
|
|
138
138
|
end
|
|
139
139
|
|
|
140
140
|
def test_peaks
|
|
141
141
|
env = @req.class.env_for "/active/#@addr.txt"
|
|
142
|
-
|
|
142
|
+
_status, headers, _body = @app.call(env.dup)
|
|
143
143
|
start = headers["X-First-Peak-At"]
|
|
144
144
|
assert headers["X-First-Peak-At"], headers.inspect
|
|
145
145
|
assert headers["X-Last-Peak-At"], headers.inspect
|
|
@@ -148,14 +148,14 @@ class TestWatcher < Test::Unit::TestCase
|
|
|
148
148
|
before = headers["X-Last-Peak-At"]
|
|
149
149
|
|
|
150
150
|
env = @req.class.env_for "/queued/#@addr.txt"
|
|
151
|
-
|
|
151
|
+
_status, headers, _body = @app.call(env)
|
|
152
152
|
assert_nothing_raised { Time.parse(headers["X-First-Peak-At"]) }
|
|
153
153
|
assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
|
|
154
154
|
assert_equal before, headers["X-Last-Peak-At"], "should not change"
|
|
155
155
|
|
|
156
156
|
sleep 2
|
|
157
157
|
env = @req.class.env_for "/active/#@addr.txt"
|
|
158
|
-
|
|
158
|
+
_status, headers, _body = @app.call(env.dup)
|
|
159
159
|
assert_equal before, headers["X-Last-Peak-At"], headers.inspect
|
|
160
160
|
|
|
161
161
|
@ios << @srv.accept
|
|
@@ -167,7 +167,7 @@ class TestWatcher < Test::Unit::TestCase
|
|
|
167
167
|
end
|
|
168
168
|
sleep 0.1
|
|
169
169
|
env = @req.class.env_for "/queued/#@addr.txt"
|
|
170
|
-
|
|
170
|
+
_status, headers, _body = @app.call(env.dup)
|
|
171
171
|
assert headers["X-Last-Peak-At"], headers.inspect
|
|
172
172
|
assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
|
|
173
173
|
assert before != headers["X-Last-Peak-At"]
|
|
@@ -177,7 +177,7 @@ class TestWatcher < Test::Unit::TestCase
|
|
|
177
177
|
sleep 2
|
|
178
178
|
|
|
179
179
|
env = @req.class.env_for "/queued/#@addr.txt"
|
|
180
|
-
|
|
180
|
+
_status, headers, _body = @app.call(env)
|
|
181
181
|
assert_equal "0", headers["X-Current"]
|
|
182
182
|
assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
|
|
183
183
|
assert_equal queued_before, headers["X-Last-Peak-At"], "should not change"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: raindrops
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.20.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- raindrops hackers
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-12-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: aggregate
|
|
@@ -78,7 +78,7 @@ description: |-
|
|
|
78
78
|
should support any Rack HTTP server on platforms supporting POSIX shared
|
|
79
79
|
memory. It may also be used as a generic scoreboard for sharing atomic
|
|
80
80
|
counters across multiple processes.
|
|
81
|
-
email: raindrops-public@
|
|
81
|
+
email: raindrops-public@yhbt.net
|
|
82
82
|
executables: []
|
|
83
83
|
extensions:
|
|
84
84
|
- ext/raindrops/extconf.rb
|
|
@@ -149,7 +149,7 @@ files:
|
|
|
149
149
|
- test/test_struct.rb
|
|
150
150
|
- test/test_tcp_info.rb
|
|
151
151
|
- test/test_watcher.rb
|
|
152
|
-
homepage: https://
|
|
152
|
+
homepage: https://yhbt.net/raindrops/
|
|
153
153
|
licenses:
|
|
154
154
|
- LGPL-2.1+
|
|
155
155
|
metadata: {}
|
|
@@ -168,8 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
168
168
|
- !ruby/object:Gem::Version
|
|
169
169
|
version: '0'
|
|
170
170
|
requirements: []
|
|
171
|
-
|
|
172
|
-
rubygems_version: 2.6.10
|
|
171
|
+
rubygems_version: 3.0.2
|
|
173
172
|
signing_key:
|
|
174
173
|
specification_version: 4
|
|
175
174
|
summary: real-time stats for preforking Rack servers
|