pwnedkeys-filter 0.2.1 → 0.3.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.
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