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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e1444bc6e35e67993745b3627e848537490fd3b02a67e12be9721b031e22e70
4
- data.tar.gz: 9ed2dff40418e89a71ecf18cfb74b72d28d9570ceef314ee1c81bdff19ed832a
3
+ metadata.gz: 6f78e29ec57e3f3710146a423cf60915d23a5f4366d70dcabbbef74fb69f71f3
4
+ data.tar.gz: 8a369d49c33a67af3b6acccaf64b04ed192cba9d163c8d48944cfac887511885
5
5
  SHA512:
6
- metadata.gz: ccb15ce6a96c1619d53d6090851ef8152ebd673b2db8aed9c6d4bb42757de2d9d051888d3f105d6d3461683eb33575d343e7d31a1ddb91a8f9914bb4e6abcb81
7
- data.tar.gz: ce265e39bf3217f3b62931ead0fff78e7e118785466bc0eecff1858f9d808982c12b14f2645ecfffd96c8cb8e0a1a72ac03c0d6ad220c84950dfd2fe05d7f258
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
- - nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
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.19.2
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.19.2
4
+ DEF_VER=v0.20.0
5
5
 
6
6
  LF='
7
7
  '
data/LATEST CHANGED
@@ -1,7 +1,10 @@
1
- === raindrops 0.19.2 / 2021-05-25 23:13 UTC
1
+ === raindrops 0.20.0 / 2021-12-06 23:41 UTC
2
2
 
3
- This release fixes compatibility with GC.compact on Ruby 3.x
4
- when using ListenStats on Linux. The listener stats
5
- functionality is rarely used and does not affect most users
6
- who just have raindrops installed for shared atomic counters.
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 publically archived mailing list
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
- git://yhbt.net/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://yhbt.net/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,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 publically archived mailing list:
88
+ requests) go to the publicly archived mailbox:
93
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
93
  * https://yhbt.net/raindrops-public/
98
94
  * http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/raindrops-public/
99
- * nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
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.
@@ -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();
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'
@@ -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.19.2
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-05-25 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