raindrops 0.19.1 → 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 +4 -4
- data/.olddoc.yml +7 -4
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/LATEST +6 -10
- data/NEWS +17 -0
- data/README +14 -15
- data/ext/raindrops/linux_inet_diag.c +1 -0
- data/ext/raindrops/raindrops.c +48 -15
- data/lib/raindrops.rb +24 -0
- data/pkg.mk +2 -1
- data/test/test_raindrops.rb +42 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
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
@@ -4,10 +4,13 @@ rdoc_url: https://yhbt.net/raindrops/
|
|
4
4
|
public_email: raindrops-public@yhbt.net
|
5
5
|
ml_url:
|
6
6
|
- https://yhbt.net/raindrops-public/
|
7
|
-
- http://
|
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
|
8
11
|
nntp_url:
|
9
|
-
-
|
10
|
-
- nntp://
|
12
|
+
- nntps://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
|
13
|
+
- nntp://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.raindrops
|
11
14
|
source_code:
|
12
15
|
- git clone https://yhbt.net/raindrops.git
|
13
|
-
- torsocks git clone http://
|
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/LATEST
CHANGED
@@ -1,14 +1,10 @@
|
|
1
|
-
=== raindrops 0.
|
1
|
+
=== raindrops 0.20.0 / 2021-12-06 23:41 UTC
|
2
2
|
|
3
|
-
|
3
|
+
Raindrops may now use file-backed mmap() rather than anonymous
|
4
|
+
memory. Thanks to KJ Tsanaktsidis for the patch:
|
4
5
|
|
5
|
-
|
6
|
-
for expiry and I can't pay extortionists for a .org, so
|
7
|
-
s/bogomips.org/yhbt.net/ for now, and be prepared to move again
|
8
|
-
when extortionists move onto extorting the .net TLD.
|
6
|
+
https://yhbt.net/raindrops-public/20211125065618.3432-1-ktsanaktsidis@zendesk.com/T/
|
9
7
|
|
10
|
-
|
11
|
-
|
12
|
-
fixes for newer rubies
|
13
|
-
replace bogomips.org with yhbt.net
|
8
|
+
The documentation is also updated to note our mail archives are now
|
9
|
+
available via IMAP(S).
|
14
10
|
|
data/NEWS
CHANGED
@@ -1,3 +1,20 @@
|
|
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
|
+
|
1
18
|
=== raindrops 0.19.1 / 2020-01-08 09:31 UTC
|
2
19
|
|
3
20
|
This release fixes some warnings on newer Rubies.
|
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@yhbt.net) 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
|
-
|
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,14 +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
|
88
|
+
requests) go to the publicly archived mailbox:
|
93
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
93
|
* https://yhbt.net/raindrops-public/
|
98
|
-
* http://
|
99
|
-
*
|
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
|
100
99
|
|
101
100
|
Since archives are public, scrub sensitive information and
|
102
101
|
use anonymity tools such as Tor or Mixmaster if you deem necessary.
|
@@ -696,6 +696,7 @@ void Init_raindrops_linux_inet_diag(void)
|
|
696
696
|
rb_define_singleton_method(cIDSock, "new", ids_s_new, 0);
|
697
697
|
|
698
698
|
cListenStats = rb_const_get(cRaindrops, rb_intern("ListenStats"));
|
699
|
+
rb_gc_register_mark_object(cListenStats); /* pin */
|
699
700
|
|
700
701
|
rb_define_module_function(mLinux, "tcp_listener_stats",
|
701
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/lib/raindrops.rb
CHANGED
@@ -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
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
|
|
@@ -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
|
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
|