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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b8dbbea0d1ec6311fe4433caa527f1ca5483f63b
4
- data.tar.gz: e89d864999d618bc1c93df83569d7326924dfa74
2
+ SHA256:
3
+ metadata.gz: 6f78e29ec57e3f3710146a423cf60915d23a5f4366d70dcabbbef74fb69f71f3
4
+ data.tar.gz: 8a369d49c33a67af3b6acccaf64b04ed192cba9d163c8d48944cfac887511885
5
5
  SHA512:
6
- metadata.gz: fe837f974b975b0582c9a86d041acd823dc78b83aaffc2d35bb721d6da2544a6771fbf53d3ea8a2db6240b0ef05d463bd9572e85375f3600227f08fd44fb6cdd
7
- data.tar.gz: 9b380c94a516fbb9df57773f19722314a5c294810ed7f0e4b3027e7a3581c6aefcb0c6f5d5326c4400024e55cf856350e396e37934c781042098297239baafb4
6
+ metadata.gz: b9e5de8e7a7a84038bbe19a954d3d559ebec3ed4c7f68db2e2ada6373b045f4fbcd784c5d5b91005cad1d87f1db93f9dc31c9f7fc59ae56a7f73b98d9a96bf2e
7
+ data.tar.gz: 9913e9205b2527b9f5bd1bae58b0c2c8962505e87280c06257f603fb722978d6656c99cfa0a297ccd0734a7d6110b0a6ecd5155fec9870ec40a31044a00def4d
data/.olddoc.yml CHANGED
@@ -1,14 +1,16 @@
1
1
  ---
2
- cgit_url: https://bogomips.org/raindrops.git
3
- git_url: git://bogomips.org/raindrops.git
4
- rdoc_url: https://bogomips.org/raindrops/
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://bogomips.org/raindrops-public/
8
- - http://ou63pmih66umazou.onion/raindrops-public
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
- - nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
11
- - nntp://ou63pmih66umazou.onion/inbox.comp.lang.ruby.raindrops
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 git://bogomips.org/raindrops.git
14
- - git clone https://bogomips.org/raindrops.git
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.18.0
1
+ GIT_VERSION = 0.20.0
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.18.0
4
+ DEF_VER=v0.20.0
5
5
 
6
6
  LF='
7
7
  '
data/GNUmakefile CHANGED
@@ -1,4 +1,4 @@
1
1
  all::
2
- RSYNC_DEST := bogomips.org:/srv/bogomips/raindrops
2
+ RSYNC_DEST := yhbt.net:/srv/yhbt/raindrops
3
3
  rfpackage := raindrops
4
4
  include pkg.mk
data/LATEST CHANGED
@@ -1,42 +1,10 @@
1
- === raindrops 0.18.0 / 2017-03-23 02:44 UTC
1
+ === raindrops 0.20.0 / 2021-12-06 23:41 UTC
2
2
 
3
- The most notable feature of this release is the addition of
4
- FreeBSD and OpenBSD TCP_INFO support. This includes the
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
- https://bogomips.org/raindrops/Raindrops.html#TCP
6
+ https://yhbt.net/raindrops-public/20211125065618.3432-1-ktsanaktsidis@zendesk.com/T/
9
7
 
10
- Thanks to Jeremy Evans and Simon Eskildsen on the
11
- unicorn-public@bogomips.org mailing list for inspiring
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 publically archived mailing list
62
- (mailto:raindrops-public@bogomips.org) if
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
- git://bogomips.org/raindrops.git
70
- git://repo.or.cz/raindrops.git (mirror)
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
- You may browse the code from the web and download the latest snapshot
73
- tarballs here:
72
+ Snapshots and tarballs are available.
74
73
 
75
- * https://bogomips.org/raindrops.git
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 publically archived mailing list:
93
- mailto:raindrops-public@bogomips.org
88
+ requests) go to the publicly archived mailbox:
89
+ mailto:raindrops-public@yhbt.net
94
90
 
95
- Mailing list archives are available over HTTPS and NNTP:
91
+ Mail archives are available over HTTP(S), IMAP(S) and NNTP(S):
96
92
 
97
- * https://bogomips.org/raindrops-public/
98
- * nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
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') { all = true }
27
+ opts.on('-a', '--all') { } # noop
29
28
  opts.parse! ARGV
30
29
  end
31
30
 
@@ -1,5 +1,5 @@
1
1
  # This is a snippet of the config that powers
2
- # https://raindrops-demo.bogomips.org/
2
+ # https://yhbt.net/raindrops-demo/
3
3
  # This may be used with the packaged zbatery.conf.rb
4
4
  #
5
5
  # zbatery -c zbatery.conf.ru watcher_demo.ru -E none
@@ -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
- prev_cflags = $CFLAGS
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
- #ifdef HAVE_RUBY_ST_H
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
- # define rb_thread_io_blocking_region(fn,data,fd) \
42
- rb_thread_blocking_region((fn),(data),RUBY_UBF_IO,0)
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@bogomips.org\n");
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(rb_thread_io_blocking_region(diag, args, args->fd));
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(rb_thread_io_blocking_region(diag, &args, args.fd));
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);
@@ -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
- { NULL, rd_free, rd_memsize, /* reserved */ },
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
- * call-seq:
91
- * Raindrops.new(size) -> raindrops object
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 init(VALUE self, VALUE size)
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->drops = mmap(NULL, tmp,
118
- PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
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
- init(dest, SIZET2NUM(src->size));
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
- rb_define_method(cRaindrops, "initialize", init, 1);
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();
@@ -1,5 +1,4 @@
1
1
  #include <ruby.h>
2
- #include "extconf.h"
3
2
  #include <sys/socket.h>
4
3
  #include <netinet/in.h>
5
4
  #if defined(HAVE_LINUX_TCP_H)
@@ -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
- ensure
146
- flush_master
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
- rescue Errno::EINTR
179
- retry
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
- rescue Errno::EINTR
185
- retry
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
@@ -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 = %w(/proc/net/unix)
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) if defined?(Encoding)
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) if defined?(Encoding)
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(*PROC_NET_UNIX_ARGS).scan(paths) do |s|
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)
@@ -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.bogomips.org/_raindrops
65
+ # https://yhbt.net/raindrops-demo/_raindrops
66
66
  #
67
- # Also check out the Watcher demo at https://raindrops-demo.bogomips.org/
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.
@@ -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.bogomips.org/active/0.0.0.0%3A80.txt
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.bogomips.org/active/0.0.0.0%3A80.html
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.bogomips.org/queued/0.0.0.0%3A80.txt
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.bogomips.org/queued/0.0.0.0%3A80.html
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.bogomips.org/
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.bogomips.org/_raindrops
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://bogomips.org/raindrops/Raindrops/Watcher.html"
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@bogomips.org
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 oldweb
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@bogomips.org}
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://bogomips.org/raindrops/'
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
- rescue => e
6
- warn "skipping IPv6 tests, host does not seem to be IPv6 enabled:"
7
- warn " #{e.class}: #{e}"
8
- false
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
- ensure
155
- nlsock.close
155
+ ensure
156
+ nlsock.close
156
157
  end
157
158
 
158
159
  def test_tcp_multi
@@ -37,7 +37,7 @@ class TestLinuxAllTcpListenStatsLeak < Test::Unit::TestCase
37
37
  end
38
38
  cur_kb = rss_kb
39
39
  p [ :cur_kb, cur_kb ]
40
- ensure
41
- s.close
40
+ ensure
41
+ s.close
42
42
  end
43
43
  end if ENV["STRESS"].to_i != 0
@@ -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
- rescue RangeError
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
@@ -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
- ensure
64
- c.close if c
65
- a.close if a
66
- s.close
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
- status, headers, body = @app.call(env)
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
- status, headers, body = @app.call(env)
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
- status, headers, body = @app.call(env)
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
- status, headers, body = @app.call(env)
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
- status, headers, body = @app.call(env.dup)
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
- status, headers, body = @app.call(env)
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
- status, headers, body = @app.call(env.dup)
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
- status, headers, body = @app.call(env.dup)
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
- status, headers, body = @app.call(env)
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.18.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: 2017-03-23 00:00:00.000000000 Z
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@bogomips.org
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://bogomips.org/raindrops/
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
- rubyforge_project:
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