expanse 0.9.1 → 0.10.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/expanse.gemspec +1 -1
- data/lib/expanse.rb +88 -31
- 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: 5300ecd5bd652ecf1fd4b4ab8f360e8a92ad5243574573d61c6134b1093e33c5
|
|
4
|
+
data.tar.gz: 6a88dc9770aeb6d81165e7c0a4b57e1fc8dcb8e1901a2f8ece2972e1228438fd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1257f1f3412d1b855333a16bcd6e3eb9fb2438c278cf3b45c4167a091a70620841917b47cdce88f0791ac3f4db77e13b82c5dfd9318124795c61966aced57406
|
|
7
|
+
data.tar.gz: 3e54aa15d0a7c86a5ea1eca61a71b7f176dacadaeef87c887fd7548773d1f3a1acc752dd74e24f780ce7619c71abef49ece0d5e281a3ead78d87bf384a3bac51
|
data/expanse.gemspec
CHANGED
data/lib/expanse.rb
CHANGED
|
@@ -4,7 +4,7 @@ require "fiddle"
|
|
|
4
4
|
require "fiddle/import"
|
|
5
5
|
|
|
6
6
|
module Expanse
|
|
7
|
-
VERSION = "0.
|
|
7
|
+
VERSION = "0.10.0"
|
|
8
8
|
|
|
9
9
|
module Native
|
|
10
10
|
extend Fiddle::Importer
|
|
@@ -35,50 +35,58 @@ module Expanse
|
|
|
35
35
|
|
|
36
36
|
raise "Could not load libexpanse native library" unless loaded
|
|
37
37
|
|
|
38
|
+
# Every function whose C return type is `bool` is imported as
|
|
39
|
+
# `unsigned char`, never `int`. The System V x86-64 and AArch64 ABIs define
|
|
40
|
+
# only the low 8 bits of a `bool` return; a 32-bit read can see non-zero
|
|
41
|
+
# upper bits for `false`. Fiddle converts an `unsigned char` return through
|
|
42
|
+
# an `(unsigned char)` cast, so the call sites' `!= 0` reads exactly the
|
|
43
|
+
# byte the callee defined. `unsigned char` is used rather than Fiddle's
|
|
44
|
+
# `bool` type so the declaration does not depend on the Fiddle version.
|
|
45
|
+
|
|
38
46
|
# Library metadata
|
|
39
47
|
extern "const char* expanse_version(void)"
|
|
40
48
|
|
|
41
49
|
# Set
|
|
42
50
|
extern "void* expanse_set_new(void)"
|
|
43
51
|
extern "void expanse_set_free(void*)"
|
|
44
|
-
extern "
|
|
45
|
-
extern "
|
|
46
|
-
extern "
|
|
52
|
+
extern "unsigned char expanse_set_insert(void*, unsigned long long)"
|
|
53
|
+
extern "unsigned char expanse_set_remove(void*, unsigned long long)"
|
|
54
|
+
extern "unsigned char expanse_set_contains(void*, unsigned long long)"
|
|
47
55
|
extern "unsigned long long expanse_set_len(void*)"
|
|
48
56
|
extern "size_t expanse_set_mem_used(void*)"
|
|
49
57
|
extern "size_t expanse_set_mem_held(void*)"
|
|
50
58
|
extern "size_t expanse_set_shrink_to_fit(void*)"
|
|
51
59
|
extern "void expanse_set_clear(void*)"
|
|
52
|
-
extern "
|
|
53
|
-
extern "
|
|
54
|
-
extern "
|
|
55
|
-
extern "
|
|
60
|
+
extern "unsigned char expanse_set_first(void*, void*)"
|
|
61
|
+
extern "unsigned char expanse_set_last(void*, void*)"
|
|
62
|
+
extern "unsigned char expanse_set_next_after(void*, unsigned long long, void*)"
|
|
63
|
+
extern "unsigned char expanse_set_prev_before(void*, unsigned long long, void*)"
|
|
56
64
|
extern "unsigned long long expanse_set_count_below(void*, unsigned long long)"
|
|
57
65
|
extern "unsigned long long expanse_set_count_range(void*, unsigned long long, unsigned long long)"
|
|
58
|
-
extern "
|
|
66
|
+
extern "unsigned char expanse_set_by_count(void*, unsigned long long, void*)"
|
|
59
67
|
|
|
60
68
|
# Map
|
|
61
69
|
extern "void* expanse_map_new(void)"
|
|
62
70
|
extern "void expanse_map_free(void*)"
|
|
63
|
-
extern "
|
|
64
|
-
extern "
|
|
65
|
-
extern "
|
|
71
|
+
extern "unsigned char expanse_map_insert(void*, unsigned long long, unsigned long long, void*)"
|
|
72
|
+
extern "unsigned char expanse_map_get(void*, unsigned long long, void*)"
|
|
73
|
+
extern "unsigned char expanse_map_remove(void*, unsigned long long, void*)"
|
|
66
74
|
extern "unsigned long long expanse_map_len(void*)"
|
|
67
75
|
extern "size_t expanse_map_mem_used(void*)"
|
|
68
76
|
extern "size_t expanse_map_mem_held(void*)"
|
|
69
77
|
extern "size_t expanse_map_shrink_to_fit(void*)"
|
|
70
78
|
extern "void expanse_map_clear(void*)"
|
|
71
|
-
extern "
|
|
72
|
-
extern "
|
|
73
|
-
extern "
|
|
74
|
-
extern "
|
|
79
|
+
extern "unsigned char expanse_map_first(void*, void*, void*)"
|
|
80
|
+
extern "unsigned char expanse_map_last(void*, void*, void*)"
|
|
81
|
+
extern "unsigned char expanse_map_next_after(void*, unsigned long long, void*, void*)"
|
|
82
|
+
extern "unsigned char expanse_map_prev_before(void*, unsigned long long, void*, void*)"
|
|
75
83
|
|
|
76
84
|
# StrMap
|
|
77
85
|
extern "void* expanse_strmap_new(void)"
|
|
78
86
|
extern "void expanse_strmap_free(void*)"
|
|
79
|
-
extern "
|
|
80
|
-
extern "
|
|
81
|
-
extern "
|
|
87
|
+
extern "unsigned char expanse_strmap_insert(void*, const char*, unsigned long long, void*)"
|
|
88
|
+
extern "unsigned char expanse_strmap_get(void*, const char*, void*)"
|
|
89
|
+
extern "unsigned char expanse_strmap_remove(void*, const char*, void*)"
|
|
82
90
|
extern "unsigned long long expanse_strmap_len(void*)"
|
|
83
91
|
extern "void expanse_strmap_clear(void*)"
|
|
84
92
|
extern "size_t expanse_strmap_mem_held(void*)"
|
|
@@ -87,21 +95,25 @@ module Expanse
|
|
|
87
95
|
# BytesMap
|
|
88
96
|
extern "void* expanse_bytesmap_new(void)"
|
|
89
97
|
extern "void expanse_bytesmap_free(void*)"
|
|
90
|
-
extern "
|
|
91
|
-
extern "
|
|
92
|
-
extern "
|
|
98
|
+
extern "unsigned char expanse_bytesmap_insert(void*, const void*, size_t, unsigned long long, void*)"
|
|
99
|
+
extern "unsigned char expanse_bytesmap_get(void*, const void*, size_t, void*)"
|
|
100
|
+
extern "unsigned char expanse_bytesmap_remove(void*, const void*, size_t, void*)"
|
|
93
101
|
extern "unsigned long long expanse_bytesmap_len(void*)"
|
|
94
102
|
extern "void expanse_bytesmap_clear(void*)"
|
|
95
103
|
|
|
96
104
|
# BlobMap
|
|
97
105
|
extern "void* expanse_blob_map_new(size_t)"
|
|
106
|
+
extern "void* expanse_blob_map_new_with_capacity(size_t, size_t)"
|
|
107
|
+
extern "void expanse_blob_map_set_reclaim_at_cap(void*, unsigned char)"
|
|
108
|
+
extern "int expanse_blob_map_insert_ex(void*, unsigned long long, const void*, size_t, unsigned int)"
|
|
109
|
+
extern "int expanse_blob_map_arena_stats(void*, void*, size_t)"
|
|
98
110
|
extern "void expanse_blob_map_free(void*)"
|
|
99
|
-
extern "
|
|
100
|
-
extern "
|
|
101
|
-
extern "
|
|
111
|
+
extern "unsigned char expanse_blob_map_insert(void*, unsigned long long, const void*, size_t, unsigned int)"
|
|
112
|
+
extern "unsigned char expanse_blob_map_get(void*, unsigned long long, void*)"
|
|
113
|
+
extern "unsigned char expanse_blob_map_remove(void*, unsigned long long)"
|
|
102
114
|
extern "unsigned long long expanse_blob_map_len(void*)"
|
|
103
115
|
extern "void expanse_blob_map_clear(void*)"
|
|
104
|
-
extern "
|
|
116
|
+
extern "unsigned char expanse_blob_map_contains_key(void*, unsigned long long)"
|
|
105
117
|
end
|
|
106
118
|
|
|
107
119
|
def self.version
|
|
@@ -337,14 +349,14 @@ module Expanse
|
|
|
337
349
|
end
|
|
338
350
|
|
|
339
351
|
def []=(key, val)
|
|
340
|
-
s = key
|
|
352
|
+
s = c_key(key)
|
|
341
353
|
Native.expanse_strmap_insert(@ptr, s, val, nil)
|
|
342
354
|
val
|
|
343
355
|
end
|
|
344
356
|
alias set []=
|
|
345
357
|
|
|
346
358
|
def [](key)
|
|
347
|
-
s = key
|
|
359
|
+
s = c_key(key)
|
|
348
360
|
buf = Fiddle::Pointer.malloc(8)
|
|
349
361
|
if Native.expanse_strmap_get(@ptr, s, buf) != 0
|
|
350
362
|
buf.to_str(8).unpack1("Q<")
|
|
@@ -353,7 +365,7 @@ module Expanse
|
|
|
353
365
|
alias get []
|
|
354
366
|
|
|
355
367
|
def delete(key)
|
|
356
|
-
s = key
|
|
368
|
+
s = c_key(key)
|
|
357
369
|
buf = Fiddle::Pointer.malloc(8)
|
|
358
370
|
if Native.expanse_strmap_remove(@ptr, s, buf) != 0
|
|
359
371
|
buf.to_str(8).unpack1("Q<")
|
|
@@ -372,6 +384,20 @@ module Expanse
|
|
|
372
384
|
Native.expanse_strmap_clear(@ptr)
|
|
373
385
|
self
|
|
374
386
|
end
|
|
387
|
+
|
|
388
|
+
private
|
|
389
|
+
|
|
390
|
+
# The key as the C ABI will read it. Every expanse_strmap_* call takes the
|
|
391
|
+
# key as a NUL-terminated const char*, so a Ruby String carrying "\0" would
|
|
392
|
+
# reach the engine truncated and "a\0b" would address the entry for "a".
|
|
393
|
+
# ExpanseStrMap keys are NUL-free; reject the key instead, as the PHP
|
|
394
|
+
# binding does.
|
|
395
|
+
def c_key(key)
|
|
396
|
+
s = key.to_s
|
|
397
|
+
raise ArgumentError, 'NUL bytes ("\0") are not allowed in StrMap keys' if s.include?("\0")
|
|
398
|
+
|
|
399
|
+
s
|
|
400
|
+
end
|
|
375
401
|
end
|
|
376
402
|
|
|
377
403
|
class BytesMap
|
|
@@ -423,8 +449,16 @@ module Expanse
|
|
|
423
449
|
end
|
|
424
450
|
|
|
425
451
|
class BlobMap
|
|
426
|
-
|
|
427
|
-
|
|
452
|
+
# expanse_blob_status_t values, as set_status returns them.
|
|
453
|
+
STATUS = {
|
|
454
|
+
0 => :ok, 16 => :meta_overflow, 17 => :allocation_failed,
|
|
455
|
+
18 => :cap_refused, 19 => :arena_full, 32 => :invalid_argument
|
|
456
|
+
}.freeze
|
|
457
|
+
|
|
458
|
+
# max_capacity caps the arena's allocated chunk bytes (0: the default
|
|
459
|
+
# 1 GiB), clamped to [chunk_size, 64 GiB]; chunk_size 0 is the 2 MiB default.
|
|
460
|
+
def initialize(chunk_size: 0, max_capacity: 0)
|
|
461
|
+
@ptr = Native.expanse_blob_map_new_with_capacity(chunk_size, max_capacity)
|
|
428
462
|
ObjectSpace.define_finalizer(self, self.class.finalize(@ptr))
|
|
429
463
|
end
|
|
430
464
|
|
|
@@ -437,6 +471,29 @@ module Expanse
|
|
|
437
471
|
Native.expanse_blob_map_insert(@ptr, key, b, b.bytesize, hot_meta) != 0
|
|
438
472
|
end
|
|
439
473
|
|
|
474
|
+
# Like set, but returns why a refused insert was refused: :cap_refused (the
|
|
475
|
+
# capacity cap refused a chunk and nothing was compacted) or :arena_full
|
|
476
|
+
# (this insert compacted and the record still does not fit), among others.
|
|
477
|
+
def set_status(key, payload, hot_meta: 0)
|
|
478
|
+
b = payload.b
|
|
479
|
+
STATUS.fetch(Native.expanse_blob_map_insert_ex(@ptr, key, b, b.bytesize, hot_meta), :error)
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
# Turns the reclaim at the capacity cap on (the default) or off.
|
|
483
|
+
def reclaim_at_cap=(on)
|
|
484
|
+
Native.expanse_blob_map_set_reclaim_at_cap(@ptr, on ? 1 : 0)
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
# Arena accounting: live bytes (payloads plus 8-byte headers), allocated
|
|
488
|
+
# chunk bytes (what the cap counts), the cap, the chunk size, the switch.
|
|
489
|
+
def arena_stats
|
|
490
|
+
buf = Fiddle::Pointer.malloc(40)
|
|
491
|
+
Native.expanse_blob_map_arena_stats(@ptr, buf, 40)
|
|
492
|
+
live, allocated, cap, chunk, reclaim = buf[0, 40].unpack("Q<5")
|
|
493
|
+
{ live_bytes: live, allocated_bytes: allocated, max_capacity: cap,
|
|
494
|
+
chunk_size: chunk, reclaim_at_cap: reclaim == 1 }
|
|
495
|
+
end
|
|
496
|
+
|
|
440
497
|
def get(key)
|
|
441
498
|
# ExpanseBlobView: ptr (8B), len (8B), hot_meta (4B), is_inline (1B) + padding (3B) = 24 bytes
|
|
442
499
|
view_buf = Fiddle::Pointer.malloc(24)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: expanse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nicolas Brousse
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Ruby bindings for the expanse library.
|
|
14
14
|
email:
|