raindrops 0.19.2 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.olddoc.yml +4 -1
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/LATEST +8 -5
- data/NEWS +10 -0
- data/README +13 -14
- data/ext/raindrops/raindrops.c +48 -15
- data/lib/raindrops.rb +24 -0
- 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
@@ -5,8 +5,11 @@ public_email: raindrops-public@yhbt.net
|
|
5
5
|
ml_url:
|
6
6
|
- https://yhbt.net/raindrops-public/
|
7
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
|
-
-
|
12
|
+
- nntps://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
|
10
13
|
- nntp://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.raindrops
|
11
14
|
source_code:
|
12
15
|
- git clone https://yhbt.net/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,7 +1,10 @@
|
|
1
|
-
=== raindrops 0.
|
1
|
+
=== raindrops 0.20.0 / 2021-12-06 23:41 UTC
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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).
|
7
10
|
|
data/NEWS
CHANGED
@@ -1,3 +1,13 @@
|
|
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
|
+
|
1
11
|
=== raindrops 0.19.2 / 2021-05-25 23:13 UTC
|
2
12
|
|
3
13
|
This release fixes compatibility with GC.compact on Ruby 3.x
|
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
94
|
* http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/raindrops-public/
|
99
|
-
*
|
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.
|
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/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: 2021-
|
11
|
+
date: 2021-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aggregate
|