pwnedkeys-filter 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pwnedkeys/filter.rb +42 -22
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 796245e9ca46b1a37b657cac0f5cbd0157c132e7f1d887e5f2f4f1392e61473c
4
- data.tar.gz: 37806ed3fe2de6c008ccc2cf7de48c1a73d426d29e54aadd7b7a77496f31f4f7
3
+ metadata.gz: d9b4bf18eed6656efcf56a7f0dce23cccf9f088475b5122d7f6bb7f736a06434
4
+ data.tar.gz: e349b79a836c22e7d59b24c51b839c4c7baa1e05cf8de33ba6538d53e586bc1e
5
5
  SHA512:
6
- metadata.gz: 34d5b2e319c3018c0778489ef5896a3b6a09d1b0bde206daef1d61452072f7cddfb7754a14ff207131c093e1c1780910c190a29b51f0ad5a42da155e7d158f4b
7
- data.tar.gz: 47bf7be5f1ff4a5e6b55a9626c513b40117a647e3215b219b8204a60d50c2d93ec928926fdd495500b41619f28d6be60cc90efeca0136819eba645d01f2d330d
6
+ metadata.gz: d701e80b8ad0c933c0a12c7901da61257c12f4bb666484d2254df6ed8d2427d7eae6a1ef36d7143230c235db9ab3c10ff1328af4fda0454bcde084110f6bae50
7
+ data.tar.gz: 914e681aceaecf1614ddf2e3a4f5c85f960fffb3b9532c762c4795c8038f456680bbcc53bad7e0a32284aad1ab1ba22ca1cea341d81ba5efcc0d5ef0c8dfc941
@@ -17,7 +17,8 @@ module Pwnedkeys
17
17
  class FilterClosedError < Error; end
18
18
 
19
19
  class Header
20
- attr_reader :signature, :revision, :update_time, :entry_count, :hash_count, :hash_length
20
+ attr_reader :signature, :update_time, :entry_count, :hash_count, :hash_length
21
+ attr_accessor :revision
21
22
 
22
23
  def self.from_fd(fd)
23
24
  fd.seek(0)
@@ -44,14 +45,15 @@ module Pwnedkeys
44
45
  to_s.length
45
46
  end
46
47
 
47
- def update!
48
- @revision += 1
49
- end
50
-
51
48
  def entry_added!
52
49
  @update_time = Time.now
53
50
  @entry_count += 1
54
51
  end
52
+
53
+ def to_fd(fd)
54
+ fd.rewind
55
+ fd.write(self.to_s)
56
+ end
55
57
  end
56
58
  private_constant :Header
57
59
 
@@ -168,6 +170,12 @@ module Pwnedkeys
168
170
  #
169
171
  # @param filename [String] the file to open.
170
172
  #
173
+ # @param sync [Boolean] whether or not to sync the data to persistent storage
174
+ # after each call to `#add`. Turning this off can improve bulk addition
175
+ # performance, at the cost of potential data loss in the event of catastrophe.
176
+ #
177
+ # @param revision [Integer] set an explicit revision number for changes.
178
+ #
171
179
  # @raise [SystemCallError] if anything low-level goes wrong, you will get some
172
180
  # sort of `Errno`-related exception raised, such as `ENOENT` (the file you
173
181
  # specified does not exist) or `EPERM` (you don't have access to the file
@@ -178,8 +186,8 @@ module Pwnedkeys
178
186
  #
179
187
  # @return [Pwnedkeys::Filter]
180
188
  #
181
- def self.open(filename)
182
- filter = Pwnedkeys::Filter.new(filename)
189
+ def self.open(filename, sync: true, revision: nil)
190
+ filter = Pwnedkeys::Filter.new(filename, sync: sync, revision: revision)
183
191
 
184
192
  if block_given?
185
193
  begin
@@ -198,9 +206,11 @@ module Pwnedkeys
198
206
  #
199
207
  # @see .open
200
208
  #
201
- def initialize(filename)
202
- @fd = File.open(filename, File::RDWR, binmode: true)
203
- @header = Header.from_fd(@fd)
209
+ def initialize(filename, sync: true, revision: nil)
210
+ @fd = File.open(filename, File::RDWR, binmode: true)
211
+ refresh_header
212
+
213
+ @sync, @revision = sync, revision
204
214
  end
205
215
 
206
216
  # Query the bloom filter.
@@ -233,8 +243,8 @@ module Pwnedkeys
233
243
  # probabilistic nature of the bloom filter structure, it is possible to
234
244
  # add two completely different keys and yet it looks like the "same"
235
245
  # key to the bloom filter. Adding two colliding keys isn't a fatal
236
- # error, but it is a hint that perhaps the existing filter is getting
237
- # a little too full.
246
+ # error, but if it starts to happen regularly, it is a hint that perhaps
247
+ # the existing filter is getting a little too full.
238
248
  #
239
249
  # @raise [Pwnedkeys::Filter::FilterClosedError] if you try to add a key
240
250
  # to a filter object which has had {#close} called on it.
@@ -248,6 +258,7 @@ module Pwnedkeys
248
258
 
249
259
  begin
250
260
  @fd.flock(File::LOCK_EX)
261
+ refresh_header
251
262
  filter_positions(spki.to_der).each do |n|
252
263
  @fd.seek(n / 8 + @header.header_size, :SET)
253
264
  byte = @fd.read(1).ord
@@ -259,18 +270,13 @@ module Pwnedkeys
259
270
  @fd.write(new_byte.chr)
260
271
  end
261
272
 
262
- @header.entry_added!
273
+ @revision ||= @header.revision + 1
263
274
 
264
- # Only update the revision if this is the first add in this filter,
265
- # because otherwise the revision counter would just be the same as the
266
- # entry counter, and that would be pointless.
267
- unless @already_modified
268
- @header.update!
269
- end
275
+ @header.revision = @revision
276
+ @header.entry_added!
270
277
 
271
- @fd.seek(0)
272
- @fd.write(@header.to_s)
273
- @fd.fdatasync
278
+ @header.to_fd(@fd)
279
+ @fd.fdatasync if @sync
274
280
  ensure
275
281
  @fd.flock(File::LOCK_UN)
276
282
  end
@@ -278,6 +284,16 @@ module Pwnedkeys
278
284
  @already_modified = true
279
285
  end
280
286
 
287
+ # Force a sync of newly-added data to disk.
288
+ #
289
+ # This method is only of interest if the filter was opened with `sync:
290
+ # false`, because otherwise data will already have been synced to disk as
291
+ # part of the call to {#add}.
292
+ #
293
+ def sync
294
+ @fd.fdatasync if @fd
295
+ end
296
+
281
297
  # Signal that the filter should be closed for further querying and manipulation.
282
298
  #
283
299
  # @return [void]
@@ -304,6 +320,10 @@ module Pwnedkeys
304
320
 
305
321
  private
306
322
 
323
+ def refresh_header
324
+ @header = Header.from_fd(@fd)
325
+ end
326
+
307
327
  def hash_count
308
328
  @header.hash_count
309
329
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwnedkeys-filter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Palmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-04 00:00:00.000000000 Z
11
+ date: 2020-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: openssl-additions