tigerbeetle-node 0.11.13 → 0.12.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.
- package/dist/bin/aarch64-linux-gnu/client.node +0 -0
- package/dist/bin/aarch64-linux-musl/client.node +0 -0
- package/dist/bin/aarch64-macos/client.node +0 -0
- package/dist/bin/x86_64-linux-gnu/client.node +0 -0
- package/dist/bin/x86_64-linux-musl/client.node +0 -0
- package/dist/bin/x86_64-macos/client.node +0 -0
- package/dist/index.js +33 -1
- package/dist/index.js.map +1 -1
- package/package-lock.json +66 -0
- package/package.json +6 -16
- package/src/index.ts +56 -1
- package/src/node.zig +9 -9
- package/dist/.client.node.sha256 +0 -1
- package/scripts/build_lib.sh +0 -61
- package/scripts/download_node_headers.sh +0 -32
- package/src/tigerbeetle/scripts/benchmark.bat +0 -55
- package/src/tigerbeetle/scripts/benchmark.sh +0 -66
- package/src/tigerbeetle/scripts/confirm_image.sh +0 -44
- package/src/tigerbeetle/scripts/fail_on_diff.sh +0 -9
- package/src/tigerbeetle/scripts/fuzz_loop.sh +0 -15
- package/src/tigerbeetle/scripts/fuzz_loop_hash_log.sh +0 -12
- package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +0 -7
- package/src/tigerbeetle/scripts/install.bat +0 -7
- package/src/tigerbeetle/scripts/install.sh +0 -21
- package/src/tigerbeetle/scripts/install_zig.bat +0 -113
- package/src/tigerbeetle/scripts/install_zig.sh +0 -90
- package/src/tigerbeetle/scripts/lint.zig +0 -199
- package/src/tigerbeetle/scripts/pre-commit.sh +0 -9
- package/src/tigerbeetle/scripts/scripts/benchmark.bat +0 -55
- package/src/tigerbeetle/scripts/scripts/benchmark.sh +0 -66
- package/src/tigerbeetle/scripts/scripts/confirm_image.sh +0 -44
- package/src/tigerbeetle/scripts/scripts/fail_on_diff.sh +0 -9
- package/src/tigerbeetle/scripts/scripts/fuzz_loop.sh +0 -15
- package/src/tigerbeetle/scripts/scripts/fuzz_loop_hash_log.sh +0 -12
- package/src/tigerbeetle/scripts/scripts/fuzz_unique_errors.sh +0 -7
- package/src/tigerbeetle/scripts/scripts/install.bat +0 -7
- package/src/tigerbeetle/scripts/scripts/install.sh +0 -21
- package/src/tigerbeetle/scripts/scripts/install_zig.bat +0 -113
- package/src/tigerbeetle/scripts/scripts/install_zig.sh +0 -90
- package/src/tigerbeetle/scripts/scripts/lint.zig +0 -199
- package/src/tigerbeetle/scripts/scripts/pre-commit.sh +0 -9
- package/src/tigerbeetle/scripts/scripts/shellcheck.sh +0 -5
- package/src/tigerbeetle/scripts/scripts/tests_on_alpine.sh +0 -10
- package/src/tigerbeetle/scripts/scripts/tests_on_ubuntu.sh +0 -14
- package/src/tigerbeetle/scripts/scripts/upgrade_ubuntu_kernel.sh +0 -48
- package/src/tigerbeetle/scripts/scripts/validate_docs.sh +0 -23
- package/src/tigerbeetle/scripts/scripts/vr_state_enumerate +0 -46
- package/src/tigerbeetle/scripts/shellcheck.sh +0 -5
- package/src/tigerbeetle/scripts/tests_on_alpine.sh +0 -10
- package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +0 -14
- package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +0 -48
- package/src/tigerbeetle/scripts/validate_docs.sh +0 -23
- package/src/tigerbeetle/scripts/vr_state_enumerate +0 -46
- package/src/tigerbeetle/src/benchmark.zig +0 -336
- package/src/tigerbeetle/src/config.zig +0 -233
- package/src/tigerbeetle/src/constants.zig +0 -428
- package/src/tigerbeetle/src/ewah.zig +0 -286
- package/src/tigerbeetle/src/ewah_benchmark.zig +0 -120
- package/src/tigerbeetle/src/ewah_fuzz.zig +0 -130
- package/src/tigerbeetle/src/fifo.zig +0 -120
- package/src/tigerbeetle/src/io/benchmark.zig +0 -213
- package/src/tigerbeetle/src/io/darwin.zig +0 -814
- package/src/tigerbeetle/src/io/linux.zig +0 -1071
- package/src/tigerbeetle/src/io/test.zig +0 -643
- package/src/tigerbeetle/src/io/windows.zig +0 -1183
- package/src/tigerbeetle/src/io.zig +0 -34
- package/src/tigerbeetle/src/iops.zig +0 -107
- package/src/tigerbeetle/src/lsm/README.md +0 -308
- package/src/tigerbeetle/src/lsm/binary_search.zig +0 -341
- package/src/tigerbeetle/src/lsm/bloom_filter.zig +0 -125
- package/src/tigerbeetle/src/lsm/compaction.zig +0 -603
- package/src/tigerbeetle/src/lsm/composite_key.zig +0 -77
- package/src/tigerbeetle/src/lsm/direction.zig +0 -11
- package/src/tigerbeetle/src/lsm/eytzinger.zig +0 -587
- package/src/tigerbeetle/src/lsm/eytzinger_benchmark.zig +0 -330
- package/src/tigerbeetle/src/lsm/forest.zig +0 -205
- package/src/tigerbeetle/src/lsm/forest_fuzz.zig +0 -450
- package/src/tigerbeetle/src/lsm/grid.zig +0 -573
- package/src/tigerbeetle/src/lsm/groove.zig +0 -1036
- package/src/tigerbeetle/src/lsm/k_way_merge.zig +0 -474
- package/src/tigerbeetle/src/lsm/level_iterator.zig +0 -332
- package/src/tigerbeetle/src/lsm/manifest.zig +0 -617
- package/src/tigerbeetle/src/lsm/manifest_level.zig +0 -878
- package/src/tigerbeetle/src/lsm/manifest_log.zig +0 -789
- package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +0 -691
- package/src/tigerbeetle/src/lsm/merge_iterator.zig +0 -106
- package/src/tigerbeetle/src/lsm/node_pool.zig +0 -235
- package/src/tigerbeetle/src/lsm/posted_groove.zig +0 -381
- package/src/tigerbeetle/src/lsm/segmented_array.zig +0 -1329
- package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +0 -148
- package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +0 -9
- package/src/tigerbeetle/src/lsm/set_associative_cache.zig +0 -850
- package/src/tigerbeetle/src/lsm/table.zig +0 -1009
- package/src/tigerbeetle/src/lsm/table_immutable.zig +0 -192
- package/src/tigerbeetle/src/lsm/table_iterator.zig +0 -340
- package/src/tigerbeetle/src/lsm/table_mutable.zig +0 -203
- package/src/tigerbeetle/src/lsm/test.zig +0 -439
- package/src/tigerbeetle/src/lsm/tree.zig +0 -1169
- package/src/tigerbeetle/src/lsm/tree_fuzz.zig +0 -479
- package/src/tigerbeetle/src/message_bus.zig +0 -1013
- package/src/tigerbeetle/src/message_pool.zig +0 -156
- package/src/tigerbeetle/src/ring_buffer.zig +0 -399
- package/src/tigerbeetle/src/simulator.zig +0 -580
- package/src/tigerbeetle/src/state_machine/auditor.zig +0 -578
- package/src/tigerbeetle/src/state_machine/workload.zig +0 -883
- package/src/tigerbeetle/src/state_machine.zig +0 -2099
- package/src/tigerbeetle/src/static_allocator.zig +0 -65
- package/src/tigerbeetle/src/stdx.zig +0 -171
- package/src/tigerbeetle/src/storage.zig +0 -393
- package/src/tigerbeetle/src/testing/cluster/message_bus.zig +0 -82
- package/src/tigerbeetle/src/testing/cluster/network.zig +0 -237
- package/src/tigerbeetle/src/testing/cluster/state_checker.zig +0 -169
- package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +0 -202
- package/src/tigerbeetle/src/testing/cluster.zig +0 -444
- package/src/tigerbeetle/src/testing/fuzz.zig +0 -140
- package/src/tigerbeetle/src/testing/hash_log.zig +0 -66
- package/src/tigerbeetle/src/testing/id.zig +0 -99
- package/src/tigerbeetle/src/testing/packet_simulator.zig +0 -374
- package/src/tigerbeetle/src/testing/priority_queue.zig +0 -645
- package/src/tigerbeetle/src/testing/reply_sequence.zig +0 -139
- package/src/tigerbeetle/src/testing/state_machine.zig +0 -250
- package/src/tigerbeetle/src/testing/storage.zig +0 -757
- package/src/tigerbeetle/src/testing/table.zig +0 -247
- package/src/tigerbeetle/src/testing/time.zig +0 -84
- package/src/tigerbeetle/src/tigerbeetle.zig +0 -227
- package/src/tigerbeetle/src/time.zig +0 -112
- package/src/tigerbeetle/src/tracer.zig +0 -529
- package/src/tigerbeetle/src/unit_tests.zig +0 -40
- package/src/tigerbeetle/src/vopr.zig +0 -495
- package/src/tigerbeetle/src/vsr/README.md +0 -209
- package/src/tigerbeetle/src/vsr/client.zig +0 -544
- package/src/tigerbeetle/src/vsr/clock.zig +0 -855
- package/src/tigerbeetle/src/vsr/journal.zig +0 -2415
- package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +0 -111
- package/src/tigerbeetle/src/vsr/marzullo.zig +0 -309
- package/src/tigerbeetle/src/vsr/replica.zig +0 -6616
- package/src/tigerbeetle/src/vsr/replica_format.zig +0 -219
- package/src/tigerbeetle/src/vsr/superblock.zig +0 -1631
- package/src/tigerbeetle/src/vsr/superblock_client_table.zig +0 -256
- package/src/tigerbeetle/src/vsr/superblock_free_set.zig +0 -929
- package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +0 -334
- package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +0 -390
- package/src/tigerbeetle/src/vsr/superblock_manifest.zig +0 -615
- package/src/tigerbeetle/src/vsr/superblock_quorums.zig +0 -394
- package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +0 -314
- package/src/tigerbeetle/src/vsr.zig +0 -1425
|
@@ -1,615 +0,0 @@
|
|
|
1
|
-
//! SuperBlock.Manifest maintains an on-disk registry of all ManifestLog blocks.
|
|
2
|
-
|
|
3
|
-
const std = @import("std");
|
|
4
|
-
const assert = std.debug.assert;
|
|
5
|
-
const log = std.log.scoped(.superblock_manifest);
|
|
6
|
-
const mem = std.mem;
|
|
7
|
-
|
|
8
|
-
const constants = @import("../constants.zig");
|
|
9
|
-
const stdx = @import("../stdx.zig");
|
|
10
|
-
|
|
11
|
-
// TODO Compute & use the upper bound of manifest blocks (per tree) to size the trailer zone.
|
|
12
|
-
|
|
13
|
-
/// SuperBlock.Manifest schema:
|
|
14
|
-
/// │ [manifest.count]u128 │ Tree id (for the owner of the ManifestLog)
|
|
15
|
-
/// │ [manifest.count]u128 │ ManifestLog block checksum
|
|
16
|
-
/// │ [manifest.count]u64 │ ManifestLog block address
|
|
17
|
-
/// Entries are ordered from oldest to newest.
|
|
18
|
-
pub const Manifest = struct {
|
|
19
|
-
// This is a struct-of-arrays of `BlockReference`s.
|
|
20
|
-
// Only the first `manifest.count` entries are valid.
|
|
21
|
-
// Entries are ordered from oldest to newest.
|
|
22
|
-
trees: []u128,
|
|
23
|
-
checksums: []u128,
|
|
24
|
-
addresses: []u64,
|
|
25
|
-
|
|
26
|
-
count: u32,
|
|
27
|
-
count_max: u32,
|
|
28
|
-
|
|
29
|
-
/// A map from table address to the manifest block and entry that is the latest extent version.
|
|
30
|
-
/// Used to determine whether a table should be dropped in a compaction.
|
|
31
|
-
/// Shared by all trees and sized to accommodate all possible tables.
|
|
32
|
-
tables: Tables,
|
|
33
|
-
|
|
34
|
-
/// A set of block addresses that have free entries.
|
|
35
|
-
/// Used to determine whether a block should be compacted.
|
|
36
|
-
/// Note: Some of these block addresses may yet to be appended to the manifest through a flush.
|
|
37
|
-
/// This enables us to track fragmentation even in unflushed blocks.
|
|
38
|
-
compaction_set: std.AutoHashMapUnmanaged(u64, void),
|
|
39
|
-
|
|
40
|
-
pub const Tables = std.AutoHashMapUnmanaged(TableExtentKey, TableExtent);
|
|
41
|
-
|
|
42
|
-
pub const TableExtentKey = struct {
|
|
43
|
-
tree_hash: u128,
|
|
44
|
-
table: u64,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
pub const TableExtent = struct {
|
|
48
|
-
block: u64, // ManifestLog block address.
|
|
49
|
-
entry: u32, // Index within the ManifestLog Label/TableInfo arrays.
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
pub fn init(
|
|
53
|
-
allocator: mem.Allocator,
|
|
54
|
-
manifest_block_count_max: u32,
|
|
55
|
-
// The maximum number of tables in a tree when fully loaded.
|
|
56
|
-
// The same number is the limit for all tables across the forest since most trees are small.
|
|
57
|
-
forest_table_count_max: u32,
|
|
58
|
-
) !Manifest {
|
|
59
|
-
// TODO Assert relation between manifest_block_count_max and forest_table_count_max.
|
|
60
|
-
|
|
61
|
-
const trees = try allocator.alloc(u128, manifest_block_count_max);
|
|
62
|
-
errdefer allocator.free(trees);
|
|
63
|
-
|
|
64
|
-
const checksums = try allocator.alloc(u128, manifest_block_count_max);
|
|
65
|
-
errdefer allocator.free(checksums);
|
|
66
|
-
|
|
67
|
-
const addresses = try allocator.alloc(u64, manifest_block_count_max);
|
|
68
|
-
errdefer allocator.free(addresses);
|
|
69
|
-
|
|
70
|
-
var tables = Tables{};
|
|
71
|
-
try tables.ensureTotalCapacity(allocator, forest_table_count_max);
|
|
72
|
-
errdefer tables.deinit(allocator);
|
|
73
|
-
|
|
74
|
-
var compaction_set = std.AutoHashMapUnmanaged(u64, void){};
|
|
75
|
-
try compaction_set.ensureTotalCapacity(allocator, manifest_block_count_max);
|
|
76
|
-
errdefer compaction_set.deinit(allocator);
|
|
77
|
-
|
|
78
|
-
mem.set(u128, trees, 0);
|
|
79
|
-
mem.set(u128, checksums, 0);
|
|
80
|
-
mem.set(u64, addresses, 0);
|
|
81
|
-
|
|
82
|
-
return Manifest{
|
|
83
|
-
.trees = trees,
|
|
84
|
-
.checksums = checksums,
|
|
85
|
-
.addresses = addresses,
|
|
86
|
-
.count = 0,
|
|
87
|
-
.count_max = manifest_block_count_max,
|
|
88
|
-
.tables = tables,
|
|
89
|
-
.compaction_set = compaction_set,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
pub fn deinit(manifest: *Manifest, allocator: mem.Allocator) void {
|
|
94
|
-
allocator.free(manifest.trees);
|
|
95
|
-
allocator.free(manifest.checksums);
|
|
96
|
-
allocator.free(manifest.addresses);
|
|
97
|
-
manifest.tables.deinit(allocator);
|
|
98
|
-
manifest.compaction_set.deinit(allocator);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
pub fn encode(manifest: *const Manifest, target: []align(@alignOf(u128)) u8) u64 {
|
|
102
|
-
if (constants.verify) manifest.verify();
|
|
103
|
-
|
|
104
|
-
assert(target.len > 0);
|
|
105
|
-
assert(target.len % @sizeOf(u128) == 0);
|
|
106
|
-
|
|
107
|
-
var size: u64 = 0;
|
|
108
|
-
|
|
109
|
-
const trees = target[size..][0 .. manifest.count * @sizeOf(u128)];
|
|
110
|
-
stdx.copy_disjoint(
|
|
111
|
-
.exact,
|
|
112
|
-
u128,
|
|
113
|
-
mem.bytesAsSlice(u128, trees),
|
|
114
|
-
manifest.trees[0..manifest.count],
|
|
115
|
-
);
|
|
116
|
-
size += trees.len;
|
|
117
|
-
|
|
118
|
-
const checksums = target[size..][0 .. manifest.count * @sizeOf(u128)];
|
|
119
|
-
stdx.copy_disjoint(
|
|
120
|
-
.exact,
|
|
121
|
-
u128,
|
|
122
|
-
mem.bytesAsSlice(u128, checksums),
|
|
123
|
-
manifest.checksums[0..manifest.count],
|
|
124
|
-
);
|
|
125
|
-
size += checksums.len;
|
|
126
|
-
|
|
127
|
-
const addresses = target[size..][0 .. manifest.count * @sizeOf(u64)];
|
|
128
|
-
stdx.copy_disjoint(
|
|
129
|
-
.exact,
|
|
130
|
-
u64,
|
|
131
|
-
mem.bytesAsSlice(u64, addresses),
|
|
132
|
-
manifest.addresses[0..manifest.count],
|
|
133
|
-
);
|
|
134
|
-
size += addresses.len;
|
|
135
|
-
|
|
136
|
-
mem.set(u8, target[size..], 0);
|
|
137
|
-
|
|
138
|
-
assert(@divExact(size, BlockReferenceSize) == manifest.count);
|
|
139
|
-
|
|
140
|
-
return size;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
pub fn decode(manifest: *Manifest, source: []align(@alignOf(u128)) const u8) void {
|
|
144
|
-
assert(manifest.count == 0);
|
|
145
|
-
assert(manifest.tables.count() == 0);
|
|
146
|
-
assert(manifest.compaction_set.count() == 0);
|
|
147
|
-
|
|
148
|
-
manifest.count = @intCast(u32, @divExact(source.len, BlockReferenceSize));
|
|
149
|
-
assert(manifest.count <= manifest.count_max);
|
|
150
|
-
|
|
151
|
-
var size: u64 = 0;
|
|
152
|
-
|
|
153
|
-
const trees = source[size..][0 .. manifest.count * @sizeOf(u128)];
|
|
154
|
-
stdx.copy_disjoint(
|
|
155
|
-
.exact,
|
|
156
|
-
u128,
|
|
157
|
-
manifest.trees[0..manifest.count],
|
|
158
|
-
mem.bytesAsSlice(u128, trees),
|
|
159
|
-
);
|
|
160
|
-
size += trees.len;
|
|
161
|
-
|
|
162
|
-
const checksums = source[size..][0 .. manifest.count * @sizeOf(u128)];
|
|
163
|
-
stdx.copy_disjoint(
|
|
164
|
-
.exact,
|
|
165
|
-
u128,
|
|
166
|
-
manifest.checksums[0..manifest.count],
|
|
167
|
-
mem.bytesAsSlice(u128, checksums),
|
|
168
|
-
);
|
|
169
|
-
size += checksums.len;
|
|
170
|
-
|
|
171
|
-
const addresses = source[size..][0 .. manifest.count * @sizeOf(u64)];
|
|
172
|
-
stdx.copy_disjoint(
|
|
173
|
-
.exact,
|
|
174
|
-
u64,
|
|
175
|
-
manifest.addresses[0..manifest.count],
|
|
176
|
-
mem.bytesAsSlice(u64, addresses),
|
|
177
|
-
);
|
|
178
|
-
size += addresses.len;
|
|
179
|
-
|
|
180
|
-
assert(size == source.len);
|
|
181
|
-
assert(@divExact(size, BlockReferenceSize) == manifest.count);
|
|
182
|
-
|
|
183
|
-
mem.set(u128, manifest.trees[manifest.count..], 0);
|
|
184
|
-
mem.set(u128, manifest.checksums[manifest.count..], 0);
|
|
185
|
-
mem.set(u64, manifest.addresses[manifest.count..], 0);
|
|
186
|
-
|
|
187
|
-
if (constants.verify) manifest.verify();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/// Addresses must be unique across all appends, or remove() must be called first.
|
|
191
|
-
/// Warning: The caller is responsible for ensuring that concurrent tree compactions call
|
|
192
|
-
/// append() in a deterministic order with respect to each other.
|
|
193
|
-
pub fn append(manifest: *Manifest, tree: u128, checksum: u128, address: u64) void {
|
|
194
|
-
assert(address > 0);
|
|
195
|
-
assert(manifest.index_for_address(address) == null);
|
|
196
|
-
|
|
197
|
-
if (manifest.count == manifest.count_max) {
|
|
198
|
-
@panic("superblock manifest: out of space");
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
manifest.trees[manifest.count] = tree;
|
|
202
|
-
manifest.checksums[manifest.count] = checksum;
|
|
203
|
-
manifest.addresses[manifest.count] = address;
|
|
204
|
-
manifest.count += 1;
|
|
205
|
-
|
|
206
|
-
// A newly appended manifest block may already be queued for compaction.
|
|
207
|
-
// For example, if a table is inserted and then removed before the block was flushed.
|
|
208
|
-
// TODO Optimize ManifestLog.close_block() to compact blocks internally.
|
|
209
|
-
|
|
210
|
-
log.debug("append: tree={} checksum={} address={} manifest.blocks={}/{}", .{
|
|
211
|
-
tree,
|
|
212
|
-
checksum,
|
|
213
|
-
address,
|
|
214
|
-
manifest.count,
|
|
215
|
-
manifest.count_max,
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
if (constants.verify) {
|
|
219
|
-
const index = manifest.index_for_address(address).?;
|
|
220
|
-
assert(index == manifest.count - 1);
|
|
221
|
-
manifest.verify_index_tree_checksum_address(index, tree, checksum, address);
|
|
222
|
-
manifest.verify();
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
pub fn remove(manifest: *Manifest, tree: u128, checksum: u128, address: u64) void {
|
|
227
|
-
assert(address > 0);
|
|
228
|
-
|
|
229
|
-
const index = manifest.index_for_address(address).?;
|
|
230
|
-
assert(index < manifest.count);
|
|
231
|
-
manifest.verify_index_tree_checksum_address(index, tree, checksum, address);
|
|
232
|
-
|
|
233
|
-
const tail = manifest.count - (index + 1);
|
|
234
|
-
stdx.copy_left(.inexact, u128, manifest.trees[index..], manifest.trees[index + 1 ..][0..tail]);
|
|
235
|
-
stdx.copy_left(.inexact, u128, manifest.checksums[index..], manifest.checksums[index + 1 ..][0..tail]);
|
|
236
|
-
stdx.copy_left(.inexact, u64, manifest.addresses[index..], manifest.addresses[index + 1 ..][0..tail]);
|
|
237
|
-
manifest.count -= 1;
|
|
238
|
-
|
|
239
|
-
manifest.trees[manifest.count] = 0;
|
|
240
|
-
manifest.checksums[manifest.count] = 0;
|
|
241
|
-
manifest.addresses[manifest.count] = 0;
|
|
242
|
-
|
|
243
|
-
_ = manifest.compaction_set.remove(address);
|
|
244
|
-
|
|
245
|
-
log.debug("remove: tree={} checksum={} address={} manifest.blocks={}/{}", .{
|
|
246
|
-
tree,
|
|
247
|
-
checksum,
|
|
248
|
-
address,
|
|
249
|
-
manifest.count,
|
|
250
|
-
manifest.count_max,
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
if (constants.verify) {
|
|
254
|
-
assert(manifest.index_for_address(address) == null);
|
|
255
|
-
manifest.verify();
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
fn index_for_address(manifest: *const Manifest, address: u64) ?u32 {
|
|
260
|
-
assert(address > 0);
|
|
261
|
-
|
|
262
|
-
var index: u32 = 0;
|
|
263
|
-
while (index < manifest.count) : (index += 1) {
|
|
264
|
-
if (manifest.addresses[index] == address) return index;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return null;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
pub fn queue_for_compaction(manifest: *Manifest, address: u64) void {
|
|
271
|
-
assert(address > 0);
|
|
272
|
-
|
|
273
|
-
manifest.compaction_set.putAssumeCapacity(address, {});
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
pub fn queued_for_compaction(manifest: *const Manifest, address: u64) bool {
|
|
277
|
-
assert(address > 0);
|
|
278
|
-
|
|
279
|
-
return manifest.compaction_set.contains(address);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
pub fn oldest_block_queued_for_compaction(
|
|
283
|
-
manifest: *const Manifest,
|
|
284
|
-
tree: u128,
|
|
285
|
-
) ?BlockReference {
|
|
286
|
-
var index: u32 = 0;
|
|
287
|
-
while (index < manifest.count) : (index += 1) {
|
|
288
|
-
if (manifest.trees[index] != tree) continue;
|
|
289
|
-
if (!manifest.queued_for_compaction(manifest.addresses[index])) continue;
|
|
290
|
-
|
|
291
|
-
return BlockReference{
|
|
292
|
-
.tree = manifest.trees[index],
|
|
293
|
-
.checksum = manifest.checksums[index],
|
|
294
|
-
.address = manifest.addresses[index],
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/// Inserts the table extent if it does not yet exist, and returns true.
|
|
302
|
-
/// Otherwise, returns false.
|
|
303
|
-
pub fn insert_table_extent(manifest: *Manifest, tree_hash: u128, table: u64, block: u64, entry: u32) bool {
|
|
304
|
-
assert(table > 0);
|
|
305
|
-
assert(block > 0);
|
|
306
|
-
|
|
307
|
-
var extent = manifest.tables.getOrPutAssumeCapacity(.{
|
|
308
|
-
.tree_hash = tree_hash,
|
|
309
|
-
.table = table,
|
|
310
|
-
});
|
|
311
|
-
if (extent.found_existing) return false;
|
|
312
|
-
|
|
313
|
-
extent.value_ptr.* = .{
|
|
314
|
-
.block = block,
|
|
315
|
-
.entry = entry,
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
return true;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/// Inserts or updates the table extent, and returns the previous block address if any.
|
|
322
|
-
/// The table extent must be updated immediately when appending, without delay.
|
|
323
|
-
/// Otherwise, ManifestLog.compact() may append a stale version over the latest.
|
|
324
|
-
pub fn update_table_extent(manifest: *Manifest, tree_hash: u128, table: u64, block: u64, entry: u32) ?u64 {
|
|
325
|
-
assert(table > 0);
|
|
326
|
-
assert(block > 0);
|
|
327
|
-
|
|
328
|
-
var extent = manifest.tables.getOrPutAssumeCapacity(.{
|
|
329
|
-
.tree_hash = tree_hash,
|
|
330
|
-
.table = table,
|
|
331
|
-
});
|
|
332
|
-
const previous_block = if (extent.found_existing) extent.value_ptr.block else null;
|
|
333
|
-
|
|
334
|
-
extent.value_ptr.* = .{
|
|
335
|
-
.block = block,
|
|
336
|
-
.entry = entry,
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
return previous_block;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/// Removes the table extent if { block, entry } is the latest version, and returns true.
|
|
343
|
-
/// Otherwise, returns false.
|
|
344
|
-
pub fn remove_table_extent(manifest: *Manifest, tree_hash: u128, table: u64, block: u64, entry: u32) bool {
|
|
345
|
-
assert(table > 0);
|
|
346
|
-
assert(block > 0);
|
|
347
|
-
|
|
348
|
-
const extent = manifest.tables.getPtr(.{
|
|
349
|
-
.tree_hash = tree_hash,
|
|
350
|
-
.table = table,
|
|
351
|
-
}).?;
|
|
352
|
-
if (extent.block == block and extent.entry == entry) {
|
|
353
|
-
assert(manifest.tables.remove(.{
|
|
354
|
-
.tree_hash = tree_hash,
|
|
355
|
-
.table = table,
|
|
356
|
-
}));
|
|
357
|
-
|
|
358
|
-
return true;
|
|
359
|
-
} else {
|
|
360
|
-
return false;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/// Reference to a ManifestLog block.
|
|
365
|
-
pub const BlockReference = struct {
|
|
366
|
-
tree: u128,
|
|
367
|
-
checksum: u128,
|
|
368
|
-
address: u64,
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
/// The size of an encoded BlockReference on disk, not the size of the BlockReference struct.
|
|
372
|
-
pub const BlockReferenceSize = @sizeOf(u128) + @sizeOf(u128) + @sizeOf(u64);
|
|
373
|
-
|
|
374
|
-
pub const IteratorReverse = struct {
|
|
375
|
-
manifest: *const Manifest,
|
|
376
|
-
tree: u128,
|
|
377
|
-
count: u32,
|
|
378
|
-
|
|
379
|
-
pub fn next(it: *IteratorReverse) ?BlockReference {
|
|
380
|
-
assert(it.count <= it.manifest.count);
|
|
381
|
-
|
|
382
|
-
while (it.count > 0) {
|
|
383
|
-
it.count -= 1;
|
|
384
|
-
|
|
385
|
-
if (it.manifest.trees[it.count] == it.tree) {
|
|
386
|
-
assert(it.manifest.addresses[it.count] > 0);
|
|
387
|
-
|
|
388
|
-
return BlockReference{
|
|
389
|
-
.tree = it.manifest.trees[it.count],
|
|
390
|
-
.checksum = it.manifest.checksums[it.count],
|
|
391
|
-
.address = it.manifest.addresses[it.count],
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
return null;
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
/// Return all block references for a given tree in reverse order, latest-appended-first-out.
|
|
400
|
-
/// Using a reverse iterator is an optimization to avoid redundant updates to tree manifests.
|
|
401
|
-
pub fn iterator_reverse(manifest: *const Manifest, tree: u128) IteratorReverse {
|
|
402
|
-
return IteratorReverse{
|
|
403
|
-
.manifest = manifest,
|
|
404
|
-
.tree = tree,
|
|
405
|
-
.count = manifest.count,
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
pub fn verify(manifest: *const Manifest) void {
|
|
410
|
-
assert(manifest.count <= manifest.count_max);
|
|
411
|
-
|
|
412
|
-
assert(manifest.trees.len == manifest.count_max);
|
|
413
|
-
assert(manifest.checksums.len == manifest.count_max);
|
|
414
|
-
assert(manifest.addresses.len == manifest.count_max);
|
|
415
|
-
|
|
416
|
-
for (manifest.trees[manifest.count..]) |tree| assert(tree == 0);
|
|
417
|
-
for (manifest.checksums[manifest.count..]) |checksum| assert(checksum == 0);
|
|
418
|
-
for (manifest.addresses[manifest.count..]) |address| assert(address == 0);
|
|
419
|
-
|
|
420
|
-
for (manifest.addresses[0..manifest.count]) |address| assert(address > 0);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
pub fn verify_index_tree_checksum_address(
|
|
424
|
-
manifest: *const Manifest,
|
|
425
|
-
index: u32,
|
|
426
|
-
tree: u128,
|
|
427
|
-
checksum: u128,
|
|
428
|
-
address: u64,
|
|
429
|
-
) void {
|
|
430
|
-
assert(index < manifest.count);
|
|
431
|
-
assert(address > 0);
|
|
432
|
-
|
|
433
|
-
assert(manifest.trees[index] == tree);
|
|
434
|
-
assert(manifest.checksums[index] == checksum);
|
|
435
|
-
assert(manifest.addresses[index] == address);
|
|
436
|
-
}
|
|
437
|
-
};
|
|
438
|
-
|
|
439
|
-
fn test_iterator_reverse(
|
|
440
|
-
manifest: *Manifest,
|
|
441
|
-
tree: u128,
|
|
442
|
-
expect: []const Manifest.BlockReference,
|
|
443
|
-
) !void {
|
|
444
|
-
const expectEqualSlices = std.testing.expectEqualSlices;
|
|
445
|
-
|
|
446
|
-
var reverse: [3]Manifest.BlockReference = undefined;
|
|
447
|
-
var reverse_count: usize = 0;
|
|
448
|
-
|
|
449
|
-
var it = manifest.iterator_reverse(tree);
|
|
450
|
-
while (it.next()) |block| {
|
|
451
|
-
reverse[reverse_count] = block;
|
|
452
|
-
reverse_count += 1;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
try expectEqualSlices(Manifest.BlockReference, expect, reverse[0..reverse_count]);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
fn test_codec(manifest: *Manifest) !void {
|
|
459
|
-
const testing = std.testing;
|
|
460
|
-
const expectEqual = testing.expectEqual;
|
|
461
|
-
const expectEqualSlices = testing.expectEqualSlices;
|
|
462
|
-
|
|
463
|
-
var target_a: [32]u128 = undefined;
|
|
464
|
-
const size_a = manifest.encode(mem.sliceAsBytes(&target_a));
|
|
465
|
-
try expectEqual(
|
|
466
|
-
@as(u64, manifest.count * (@sizeOf(u128) + @sizeOf(u128) + @sizeOf(u64))),
|
|
467
|
-
size_a,
|
|
468
|
-
);
|
|
469
|
-
|
|
470
|
-
// The decoded instance must match the original instance:
|
|
471
|
-
var decoded = try Manifest.init(testing.allocator, manifest.count_max, 8);
|
|
472
|
-
defer decoded.deinit(testing.allocator);
|
|
473
|
-
|
|
474
|
-
decoded.decode(mem.sliceAsBytes(&target_a)[0..size_a]);
|
|
475
|
-
|
|
476
|
-
try expectEqualSlices(u128, manifest.trees, decoded.trees);
|
|
477
|
-
try expectEqualSlices(u128, manifest.checksums, decoded.checksums);
|
|
478
|
-
try expectEqualSlices(u64, manifest.addresses, decoded.addresses);
|
|
479
|
-
try expectEqual(manifest.count_max, decoded.count_max);
|
|
480
|
-
try expectEqual(manifest.count, decoded.count);
|
|
481
|
-
|
|
482
|
-
// The decoded instance must encode correctly:
|
|
483
|
-
var target_b: [32]u128 = undefined;
|
|
484
|
-
const size_b = decoded.encode(mem.sliceAsBytes(&target_b));
|
|
485
|
-
try expectEqual(size_a, size_b);
|
|
486
|
-
try expectEqualSlices(
|
|
487
|
-
u8,
|
|
488
|
-
mem.sliceAsBytes(&target_a)[0..size_a],
|
|
489
|
-
mem.sliceAsBytes(&target_b)[0..size_b],
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
test {
|
|
494
|
-
const testing = std.testing;
|
|
495
|
-
const expectEqual = testing.expectEqual;
|
|
496
|
-
const BlockReference = Manifest.BlockReference;
|
|
497
|
-
|
|
498
|
-
var manifest = try Manifest.init(testing.allocator, 3, 8);
|
|
499
|
-
defer manifest.deinit(testing.allocator);
|
|
500
|
-
|
|
501
|
-
for (manifest.trees) |tree| try expectEqual(@as(u128, 0), tree);
|
|
502
|
-
for (manifest.checksums) |checksum| try expectEqual(@as(u128, 0), checksum);
|
|
503
|
-
for (manifest.addresses) |address| try expectEqual(@as(u64, 0), address);
|
|
504
|
-
|
|
505
|
-
// The arguments to append()/remove() are: tree, checksum, address
|
|
506
|
-
// These will be named variables and should be clear at call sites where they are used for real.
|
|
507
|
-
manifest.append(1, 2, 3);
|
|
508
|
-
try expectEqual(@as(?u32, 0), manifest.index_for_address(3));
|
|
509
|
-
|
|
510
|
-
manifest.append(2, 3, 4);
|
|
511
|
-
try expectEqual(@as(?u32, 1), manifest.index_for_address(4));
|
|
512
|
-
|
|
513
|
-
manifest.append(1, 4, 5);
|
|
514
|
-
try expectEqual(@as(?u32, 2), manifest.index_for_address(5));
|
|
515
|
-
|
|
516
|
-
try expectEqual(@as(?BlockReference, null), manifest.oldest_block_queued_for_compaction(1));
|
|
517
|
-
try expectEqual(@as(?BlockReference, null), manifest.oldest_block_queued_for_compaction(2));
|
|
518
|
-
|
|
519
|
-
manifest.queue_for_compaction(3);
|
|
520
|
-
try expectEqual(true, manifest.queued_for_compaction(3));
|
|
521
|
-
try expectEqual(
|
|
522
|
-
@as(?BlockReference, BlockReference{ .tree = 1, .checksum = 2, .address = 3 }),
|
|
523
|
-
manifest.oldest_block_queued_for_compaction(1),
|
|
524
|
-
);
|
|
525
|
-
|
|
526
|
-
manifest.queue_for_compaction(4);
|
|
527
|
-
try expectEqual(true, manifest.queued_for_compaction(4));
|
|
528
|
-
try expectEqual(
|
|
529
|
-
@as(?BlockReference, BlockReference{ .tree = 2, .checksum = 3, .address = 4 }),
|
|
530
|
-
manifest.oldest_block_queued_for_compaction(2),
|
|
531
|
-
);
|
|
532
|
-
|
|
533
|
-
manifest.queue_for_compaction(5);
|
|
534
|
-
try expectEqual(true, manifest.queued_for_compaction(5));
|
|
535
|
-
try expectEqual(
|
|
536
|
-
@as(?BlockReference, BlockReference{ .tree = 1, .checksum = 2, .address = 3 }),
|
|
537
|
-
manifest.oldest_block_queued_for_compaction(1),
|
|
538
|
-
);
|
|
539
|
-
|
|
540
|
-
try test_iterator_reverse(
|
|
541
|
-
&manifest,
|
|
542
|
-
1,
|
|
543
|
-
&[_]BlockReference{
|
|
544
|
-
.{
|
|
545
|
-
.tree = 1,
|
|
546
|
-
.checksum = 4,
|
|
547
|
-
.address = 5,
|
|
548
|
-
},
|
|
549
|
-
.{
|
|
550
|
-
.tree = 1,
|
|
551
|
-
.checksum = 2,
|
|
552
|
-
.address = 3,
|
|
553
|
-
},
|
|
554
|
-
},
|
|
555
|
-
);
|
|
556
|
-
|
|
557
|
-
try test_iterator_reverse(
|
|
558
|
-
&manifest,
|
|
559
|
-
2,
|
|
560
|
-
&[_]BlockReference{
|
|
561
|
-
.{
|
|
562
|
-
.tree = 2,
|
|
563
|
-
.checksum = 3,
|
|
564
|
-
.address = 4,
|
|
565
|
-
},
|
|
566
|
-
},
|
|
567
|
-
);
|
|
568
|
-
|
|
569
|
-
try test_codec(&manifest);
|
|
570
|
-
|
|
571
|
-
manifest.remove(1, 2, 3);
|
|
572
|
-
try expectEqual(false, manifest.queued_for_compaction(3));
|
|
573
|
-
try expectEqual(@as(?u32, null), manifest.index_for_address(3));
|
|
574
|
-
try expectEqual(@as(?u32, 0), manifest.index_for_address(4));
|
|
575
|
-
try expectEqual(@as(?u32, 1), manifest.index_for_address(5));
|
|
576
|
-
try expectEqual(
|
|
577
|
-
@as(?BlockReference, BlockReference{ .tree = 1, .checksum = 4, .address = 5 }),
|
|
578
|
-
manifest.oldest_block_queued_for_compaction(1),
|
|
579
|
-
);
|
|
580
|
-
|
|
581
|
-
try expectEqual(@as(u128, 0), manifest.trees[2]);
|
|
582
|
-
try expectEqual(@as(u128, 0), manifest.checksums[2]);
|
|
583
|
-
try expectEqual(@as(u64, 0), manifest.addresses[2]);
|
|
584
|
-
|
|
585
|
-
manifest.append(1, 2, 3);
|
|
586
|
-
try expectEqual(@as(?u32, 2), manifest.index_for_address(3));
|
|
587
|
-
|
|
588
|
-
manifest.remove(1, 4, 5);
|
|
589
|
-
try expectEqual(false, manifest.queued_for_compaction(5));
|
|
590
|
-
try expectEqual(@as(?u32, null), manifest.index_for_address(5));
|
|
591
|
-
try expectEqual(@as(?u32, 1), manifest.index_for_address(3));
|
|
592
|
-
|
|
593
|
-
manifest.remove(2, 3, 4);
|
|
594
|
-
try expectEqual(false, manifest.queued_for_compaction(4));
|
|
595
|
-
try expectEqual(@as(?u32, null), manifest.index_for_address(4));
|
|
596
|
-
try expectEqual(@as(?u32, 0), manifest.index_for_address(3));
|
|
597
|
-
|
|
598
|
-
manifest.remove(1, 2, 3);
|
|
599
|
-
try expectEqual(false, manifest.queued_for_compaction(3));
|
|
600
|
-
try expectEqual(@as(?u32, null), manifest.index_for_address(3));
|
|
601
|
-
try expectEqual(@as(?u32, null), manifest.index_for_address(4));
|
|
602
|
-
try expectEqual(@as(?u32, null), manifest.index_for_address(5));
|
|
603
|
-
|
|
604
|
-
for (manifest.trees) |tree| try expectEqual(@as(u128, 0), tree);
|
|
605
|
-
for (manifest.checksums) |checksum| try expectEqual(@as(u128, 0), checksum);
|
|
606
|
-
for (manifest.addresses) |address| try expectEqual(@as(u64, 0), address);
|
|
607
|
-
|
|
608
|
-
try expectEqual(@as(usize, 0), manifest.compaction_set.count());
|
|
609
|
-
|
|
610
|
-
try expectEqual(@as(u32, 0), manifest.count);
|
|
611
|
-
try expectEqual(@as(u32, 3), manifest.count_max);
|
|
612
|
-
|
|
613
|
-
try expectEqual(@as(?BlockReference, null), manifest.oldest_block_queued_for_compaction(1));
|
|
614
|
-
try expectEqual(@as(?BlockReference, null), manifest.oldest_block_queued_for_compaction(2));
|
|
615
|
-
}
|