tigerbeetle-node 0.11.8 → 0.11.10
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/.client.node.sha256 +1 -1
- package/package.json +4 -3
- package/scripts/build_lib.sh +41 -0
- package/src/node.zig +1 -1
- package/src/tigerbeetle/scripts/validate_docs.sh +7 -1
- package/src/tigerbeetle/src/benchmark.zig +3 -3
- package/src/tigerbeetle/src/config.zig +31 -16
- package/src/tigerbeetle/src/constants.zig +48 -9
- package/src/tigerbeetle/src/ewah.zig +5 -5
- package/src/tigerbeetle/src/ewah_fuzz.zig +1 -1
- package/src/tigerbeetle/src/lsm/binary_search.zig +1 -1
- package/src/tigerbeetle/src/lsm/bloom_filter.zig +1 -1
- package/src/tigerbeetle/src/lsm/compaction.zig +34 -21
- package/src/tigerbeetle/src/lsm/forest_fuzz.zig +84 -104
- package/src/tigerbeetle/src/lsm/grid.zig +19 -13
- package/src/tigerbeetle/src/lsm/manifest_log.zig +8 -10
- package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +18 -13
- package/src/tigerbeetle/src/lsm/merge_iterator.zig +1 -1
- package/src/tigerbeetle/src/lsm/segmented_array.zig +17 -17
- package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +1 -1
- package/src/tigerbeetle/src/lsm/set_associative_cache.zig +1 -1
- package/src/tigerbeetle/src/lsm/table.zig +8 -20
- package/src/tigerbeetle/src/lsm/table_immutable.zig +1 -1
- package/src/tigerbeetle/src/lsm/table_iterator.zig +3 -3
- package/src/tigerbeetle/src/lsm/table_mutable.zig +14 -2
- package/src/tigerbeetle/src/lsm/test.zig +5 -4
- package/src/tigerbeetle/src/lsm/tree.zig +1 -2
- package/src/tigerbeetle/src/lsm/tree_fuzz.zig +85 -115
- package/src/tigerbeetle/src/message_bus.zig +4 -4
- package/src/tigerbeetle/src/message_pool.zig +7 -10
- package/src/tigerbeetle/src/ring_buffer.zig +22 -12
- package/src/tigerbeetle/src/simulator.zig +366 -239
- package/src/tigerbeetle/src/state_machine/auditor.zig +5 -5
- package/src/tigerbeetle/src/state_machine/workload.zig +3 -3
- package/src/tigerbeetle/src/state_machine.zig +190 -178
- package/src/tigerbeetle/src/{util.zig → stdx.zig} +2 -0
- package/src/tigerbeetle/src/storage.zig +13 -6
- package/src/tigerbeetle/src/{test → testing/cluster}/message_bus.zig +3 -3
- package/src/tigerbeetle/src/{test → testing/cluster}/network.zig +46 -22
- package/src/tigerbeetle/src/testing/cluster/state_checker.zig +169 -0
- package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +202 -0
- package/src/tigerbeetle/src/testing/cluster.zig +443 -0
- package/src/tigerbeetle/src/{test → testing}/fuzz.zig +0 -0
- package/src/tigerbeetle/src/testing/hash_log.zig +66 -0
- package/src/tigerbeetle/src/{test → testing}/id.zig +0 -0
- package/src/tigerbeetle/src/testing/packet_simulator.zig +365 -0
- package/src/tigerbeetle/src/{test → testing}/priority_queue.zig +1 -1
- package/src/tigerbeetle/src/testing/reply_sequence.zig +139 -0
- package/src/tigerbeetle/src/{test → testing}/state_machine.zig +3 -1
- package/src/tigerbeetle/src/testing/storage.zig +757 -0
- package/src/tigerbeetle/src/{test → testing}/table.zig +21 -0
- package/src/tigerbeetle/src/{test → testing}/time.zig +0 -0
- package/src/tigerbeetle/src/tigerbeetle.zig +2 -0
- package/src/tigerbeetle/src/tracer.zig +3 -3
- package/src/tigerbeetle/src/unit_tests.zig +4 -4
- package/src/tigerbeetle/src/vopr.zig +2 -2
- package/src/tigerbeetle/src/vsr/client.zig +5 -2
- package/src/tigerbeetle/src/vsr/clock.zig +93 -53
- package/src/tigerbeetle/src/vsr/journal.zig +109 -98
- package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +2 -2
- package/src/tigerbeetle/src/vsr/replica.zig +1983 -1430
- package/src/tigerbeetle/src/vsr/replica_format.zig +13 -13
- package/src/tigerbeetle/src/vsr/superblock.zig +240 -142
- package/src/tigerbeetle/src/vsr/superblock_client_table.zig +7 -7
- package/src/tigerbeetle/src/vsr/superblock_free_set.zig +1 -1
- package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +1 -1
- package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +49 -14
- package/src/tigerbeetle/src/vsr/superblock_manifest.zig +38 -19
- package/src/tigerbeetle/src/vsr/superblock_quorums.zig +48 -48
- package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +51 -51
- package/src/tigerbeetle/src/vsr.zig +99 -33
- package/src/tigerbeetle/src/demo.zig +0 -132
- package/src/tigerbeetle/src/demo_01_create_accounts.zig +0 -35
- package/src/tigerbeetle/src/demo_02_lookup_accounts.zig +0 -7
- package/src/tigerbeetle/src/demo_03_create_transfers.zig +0 -37
- package/src/tigerbeetle/src/demo_04_create_pending_transfers.zig +0 -61
- package/src/tigerbeetle/src/demo_05_post_pending_transfers.zig +0 -37
- package/src/tigerbeetle/src/demo_06_void_pending_transfers.zig +0 -24
- package/src/tigerbeetle/src/demo_07_lookup_transfers.zig +0 -7
- package/src/tigerbeetle/src/test/cluster.zig +0 -352
- package/src/tigerbeetle/src/test/conductor.zig +0 -366
- package/src/tigerbeetle/src/test/packet_simulator.zig +0 -398
- package/src/tigerbeetle/src/test/state_checker.zig +0 -169
- package/src/tigerbeetle/src/test/storage.zig +0 -864
- package/src/tigerbeetle/src/test/storage_checker.zig +0 -204
package/dist/.client.node.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
21c6105d76e0efc68fe5cbe799d363a083a9b44359e16d7dbfbb172e381ea0c3 dist/client.node
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tigerbeetle-node",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.10",
|
|
4
4
|
"description": "TigerBeetle Node.js client",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
"package.json",
|
|
19
19
|
"package-lock.json",
|
|
20
20
|
"scripts/download_node_headers.sh",
|
|
21
|
+
"scripts/build_lib.sh",
|
|
21
22
|
"src/c.zig",
|
|
22
23
|
"src/benchmark.ts",
|
|
23
24
|
"src/index.ts",
|
|
24
25
|
"src/node.zig",
|
|
25
26
|
"src/test.ts",
|
|
26
27
|
"src/tigerbeetle/src/*.zig",
|
|
27
|
-
"src/tigerbeetle/src/{c,io,lsm,
|
|
28
|
+
"src/tigerbeetle/src/{c,io,lsm,testing,vsr,state_machine}",
|
|
28
29
|
"src/tigerbeetle/scripts",
|
|
29
30
|
"src/translate.zig",
|
|
30
31
|
"tsconfig.json"
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"download_node_headers": "sh ./scripts/download_node_headers.sh",
|
|
41
42
|
"build": "npm run build_tsc && npm run build_lib",
|
|
42
43
|
"build_tsc": "./node_modules/typescript/bin/tsc",
|
|
43
|
-
"build_lib": "
|
|
44
|
+
"build_lib": "sh ./scripts/build_lib.sh",
|
|
44
45
|
"prepack": "npm run build_tsc",
|
|
45
46
|
"clean": "rm -rf build dist node_modules src/zig-cache zig"
|
|
46
47
|
},
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
# macOS 13 Ventura is not supported on Zig 0.9.x.
|
|
6
|
+
# Overriding -target is one workaround Andrew suggests.
|
|
7
|
+
# https://github.com/ziglang/zig/issues/10478#issuecomment-1294313967
|
|
8
|
+
target=""
|
|
9
|
+
if [ "$(./zig/zig targets | grep triple |cut -d '"' -f 4 | cut -d '.' -f 1,2)" = "aarch64-macos.13" ]; then
|
|
10
|
+
target="-target native-macos.11"
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
# Zig picks musl libc on RHEL instead of glibc, incorrectly
|
|
14
|
+
# https://github.com/ziglang/zig/issues/12156
|
|
15
|
+
if [ -f "/etc/redhat-release" ]; then
|
|
16
|
+
if ! grep Fedora /etc/redhat-release; then
|
|
17
|
+
target="-target native-native-gnu"
|
|
18
|
+
fi
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
if [ "$target" = "" ]; then
|
|
22
|
+
echo "Building default target"
|
|
23
|
+
else
|
|
24
|
+
echo "Building for '$target'"
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
mkdir -p dist
|
|
28
|
+
|
|
29
|
+
# Need to do string eval-ing because of shellcheck's strict string
|
|
30
|
+
# interpolation rules.
|
|
31
|
+
cmd="./zig/zig build-lib \
|
|
32
|
+
-mcpu=baseline \
|
|
33
|
+
-OReleaseSafe \
|
|
34
|
+
-dynamic \
|
|
35
|
+
-lc \
|
|
36
|
+
-isystem build/node-$(node --version)/include/node \
|
|
37
|
+
-fallow-shlib-undefined \
|
|
38
|
+
-femit-bin=dist/client.node \
|
|
39
|
+
$target src/node.zig"
|
|
40
|
+
|
|
41
|
+
eval "$cmd"
|
package/src/node.zig
CHANGED
|
@@ -13,5 +13,11 @@ if [[ -z "$BRANCH" ]]; then
|
|
|
13
13
|
# Otherwise fall back to git rev-parse
|
|
14
14
|
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
15
15
|
fi
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
REPO="https://github.com/tigerbeetledb/tigerbeetle"
|
|
18
|
+
if [[ -n "$SOURCE_REPO" ]]; then
|
|
19
|
+
REPO="${SOURCE_REPO}"
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
( cd docs_website && npm install && ./scripts/build.sh "$BRANCH" "$REPO" )
|
|
17
23
|
rm -rf docs_website
|
|
@@ -8,7 +8,7 @@ pub const log_level: std.log.Level = .err;
|
|
|
8
8
|
|
|
9
9
|
const IO = @import("io.zig").IO;
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const stdx = @import("stdx.zig");
|
|
12
12
|
const Storage = @import("storage.zig").Storage;
|
|
13
13
|
const MessagePool = @import("message_pool.zig").MessagePool;
|
|
14
14
|
const MessageBus = @import("message_bus.zig").MessageBusClient;
|
|
@@ -211,7 +211,7 @@ const TimedQueue = struct {
|
|
|
211
211
|
const message = self.client.get_message();
|
|
212
212
|
defer self.client.unref(message);
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
stdx.copy_disjoint(
|
|
215
215
|
.inexact,
|
|
216
216
|
u8,
|
|
217
217
|
message.buffer[@sizeOf(vsr.Header)..],
|
|
@@ -279,7 +279,7 @@ const TimedQueue = struct {
|
|
|
279
279
|
const message = self.client.get_message();
|
|
280
280
|
defer self.client.unref(message);
|
|
281
281
|
|
|
282
|
-
|
|
282
|
+
stdx.copy_disjoint(
|
|
283
283
|
.inexact,
|
|
284
284
|
u8,
|
|
285
285
|
message.buffer[@sizeOf(vsr.Header)..],
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
//! Raw configuration values.
|
|
2
|
+
//!
|
|
3
|
+
//! Code which needs these values should use `constants.zig` instead.
|
|
4
|
+
//! Configuration values are set from a combination of:
|
|
5
|
+
//! - default values
|
|
6
|
+
//! - `root.tigerbeetle_config`
|
|
7
|
+
//! - `@import("tigerbeetle_options")`
|
|
8
|
+
|
|
1
9
|
const builtin = @import("builtin");
|
|
2
10
|
const std = @import("std");
|
|
3
11
|
|
|
4
|
-
const build_options = @import("tigerbeetle_build_options");
|
|
5
12
|
const root = @import("root");
|
|
13
|
+
// Allow setting build-time config either via `build.zig` `Options`, or via a struct in the root file.
|
|
14
|
+
const build_options =
|
|
15
|
+
if (@hasDecl(root, "vsr_options")) root.vsr_options else @import("vsr_options");
|
|
6
16
|
|
|
7
17
|
const vsr = @import("vsr.zig");
|
|
8
18
|
const sector_size = @import("constants.zig").sector_size;
|
|
@@ -25,6 +35,7 @@ pub const Config = struct {
|
|
|
25
35
|
const ConfigProcess = struct {
|
|
26
36
|
log_level: std.log.Level = .info,
|
|
27
37
|
tracer_backend: TracerBackend = .none,
|
|
38
|
+
hash_log_mode: HashLogMode = .none,
|
|
28
39
|
verify: bool,
|
|
29
40
|
port: u16 = 3001,
|
|
30
41
|
address: []const u8 = "127.0.0.1",
|
|
@@ -68,6 +79,8 @@ const ConfigProcess = struct {
|
|
|
68
79
|
const ConfigCluster = struct {
|
|
69
80
|
cache_line_size: comptime_int = 64,
|
|
70
81
|
clients_max: usize,
|
|
82
|
+
pipeline_prepare_queue_max: usize = 8,
|
|
83
|
+
view_change_headers_max: usize = 8,
|
|
71
84
|
quorum_replication_max: u8 = 3,
|
|
72
85
|
journal_slot_count: usize = 1024,
|
|
73
86
|
message_size_max: usize = 1 * 1024 * 1024,
|
|
@@ -80,7 +93,6 @@ const ConfigCluster = struct {
|
|
|
80
93
|
lsm_batch_multiple: comptime_int = 4,
|
|
81
94
|
lsm_snapshots_max: usize = 32,
|
|
82
95
|
lsm_value_to_key_layout_ratio_min: comptime_int = 16,
|
|
83
|
-
state_machine: StateMachine = .accounting,
|
|
84
96
|
|
|
85
97
|
/// The WAL requires at least two sectors of redundant headers — otherwise we could lose them all to
|
|
86
98
|
/// a single torn write. A replica needs at least one valid redundant header to determine an
|
|
@@ -91,7 +103,7 @@ const ConfigCluster = struct {
|
|
|
91
103
|
pub const clients_max_min = 1;
|
|
92
104
|
|
|
93
105
|
/// The smallest possible message_size_max (for use in the simulator to improve performance).
|
|
94
|
-
/// The message body must have room for
|
|
106
|
+
/// The message body must have room for pipeline_prepare_queue_max headers in the DVC.
|
|
95
107
|
pub fn message_size_max_min(clients_max: usize) usize {
|
|
96
108
|
return std.math.max(
|
|
97
109
|
sector_size,
|
|
@@ -118,9 +130,10 @@ pub const TracerBackend = enum {
|
|
|
118
130
|
tracy,
|
|
119
131
|
};
|
|
120
132
|
|
|
121
|
-
pub const
|
|
122
|
-
|
|
123
|
-
|
|
133
|
+
pub const HashLogMode = enum {
|
|
134
|
+
none,
|
|
135
|
+
create,
|
|
136
|
+
check,
|
|
124
137
|
};
|
|
125
138
|
|
|
126
139
|
pub const configs = struct {
|
|
@@ -166,10 +179,12 @@ pub const configs = struct {
|
|
|
166
179
|
.verify = true,
|
|
167
180
|
},
|
|
168
181
|
.cluster = .{
|
|
169
|
-
.clients_max = 4,
|
|
182
|
+
.clients_max = 4 + 3,
|
|
183
|
+
.pipeline_prepare_queue_max = 4,
|
|
184
|
+
.view_change_headers_max = 4,
|
|
170
185
|
.journal_slot_count = Config.Cluster.journal_slot_count_min,
|
|
171
|
-
.message_size_max = Config.Cluster.message_size_max_min(
|
|
172
|
-
.storage_size_max = 1024 * 1024 * 1024,
|
|
186
|
+
.message_size_max = Config.Cluster.message_size_max_min(4),
|
|
187
|
+
.storage_size_max = 4 * 1024 * 1024 * 1024,
|
|
173
188
|
|
|
174
189
|
.block_size = sector_size,
|
|
175
190
|
.lsm_growth_factor = 4,
|
|
@@ -196,13 +211,6 @@ pub const configs = struct {
|
|
|
196
211
|
.test_min => test_min,
|
|
197
212
|
};
|
|
198
213
|
|
|
199
|
-
base.cluster.state_machine = if (@hasDecl(root, "decode_events"))
|
|
200
|
-
// TODO(DJ) This is a hack to work around the absense of tigerbeetle_build_options.
|
|
201
|
-
// This should be removed once the node client is built using `zig build`.
|
|
202
|
-
.accounting
|
|
203
|
-
else
|
|
204
|
-
@intToEnum(StateMachine, @enumToInt(build_options.config_cluster_state_machine));
|
|
205
|
-
|
|
206
214
|
// TODO Use additional build options to overwrite other fields.
|
|
207
215
|
base.process.tracer_backend = if (@hasDecl(root, "tracer_backend"))
|
|
208
216
|
// TODO(jamii)
|
|
@@ -214,6 +222,13 @@ pub const configs = struct {
|
|
|
214
222
|
// but a different type from a nominal typing perspective.
|
|
215
223
|
@intToEnum(TracerBackend, @enumToInt(build_options.tracer_backend));
|
|
216
224
|
|
|
225
|
+
base.process.hash_log_mode = if (@hasDecl(root, "decode_events"))
|
|
226
|
+
// TODO(DJ) This is a hack to work around the absense of tigerbeetle_build_options.
|
|
227
|
+
// This should be removed once the node client is built using `zig build`.
|
|
228
|
+
.none
|
|
229
|
+
else
|
|
230
|
+
@intToEnum(HashLogMode, @enumToInt(build_options.hash_log_mode));
|
|
231
|
+
|
|
217
232
|
break :current base;
|
|
218
233
|
};
|
|
219
234
|
};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
//! Constants are the configuration that the code actually imports — they include:
|
|
2
|
+
//! - all of the configuration values (flattened)
|
|
3
|
+
//! - derived configuration values,
|
|
4
|
+
|
|
1
5
|
const std = @import("std");
|
|
2
6
|
const assert = std.debug.assert;
|
|
3
7
|
const vsr = @import("vsr.zig");
|
|
@@ -18,15 +22,12 @@ else
|
|
|
18
22
|
// Default is `.none`.
|
|
19
23
|
pub const tracer_backend = config.process.tracer_backend;
|
|
20
24
|
|
|
25
|
+
// Which mode to use for ./testing/hash_log.zig.
|
|
26
|
+
pub const hash_log_mode = config.process.hash_log_mode;
|
|
27
|
+
|
|
21
28
|
/// The maximum number of replicas allowed in a cluster.
|
|
22
29
|
pub const replicas_max = 6;
|
|
23
30
|
|
|
24
|
-
pub const state_machine = config.cluster.state_machine;
|
|
25
|
-
pub const StateMachineType = switch (config.cluster.state_machine) {
|
|
26
|
-
.accounting => @import("state_machine.zig").StateMachineType,
|
|
27
|
-
.testing => @import("test/state_machine.zig").StateMachineType,
|
|
28
|
-
};
|
|
29
|
-
|
|
30
31
|
/// The maximum number of clients allowed per cluster, where each client has a unique 128-bit ID.
|
|
31
32
|
/// This impacts the amount of memory allocated at initialization by the server.
|
|
32
33
|
/// This determines the size of the VR client table used to cache replies to clients by client ID.
|
|
@@ -131,7 +132,7 @@ comptime {
|
|
|
131
132
|
assert(journal_slot_count >= Config.Cluster.journal_slot_count_min);
|
|
132
133
|
assert(journal_slot_count >= lsm_batch_multiple * 2);
|
|
133
134
|
assert(journal_slot_count % lsm_batch_multiple == 0);
|
|
134
|
-
assert(
|
|
135
|
+
assert(journal_slot_count > pipeline_prepare_queue_max);
|
|
135
136
|
|
|
136
137
|
assert(journal_size_max == journal_size_headers + journal_size_prepares);
|
|
137
138
|
}
|
|
@@ -156,12 +157,50 @@ comptime {
|
|
|
156
157
|
assert(message_size_max >= @sizeOf(vsr.Header));
|
|
157
158
|
assert(message_size_max >= sector_size);
|
|
158
159
|
assert(message_size_max >= Config.Cluster.message_size_max_min(clients_max));
|
|
160
|
+
|
|
161
|
+
// Ensure that DVC/SV messages can fit all necessary headers.
|
|
162
|
+
assert(message_body_size_max >= view_change_headers_max * @sizeOf(vsr.Header));
|
|
159
163
|
}
|
|
160
164
|
|
|
161
165
|
/// The maximum number of Viewstamped Replication prepare messages that can be inflight at a time.
|
|
162
166
|
/// This is immutable once assigned per cluster, as replicas need to know how many operations might
|
|
163
167
|
/// possibly be uncommitted during a view change, and this must be constant for all replicas.
|
|
164
|
-
pub const
|
|
168
|
+
pub const pipeline_prepare_queue_max = config.cluster.pipeline_prepare_queue_max;
|
|
169
|
+
|
|
170
|
+
/// The maximum number of Viewstamped Replication request messages that can be queued at a primary,
|
|
171
|
+
/// waiting to prepare.
|
|
172
|
+
// TODO(Zig): After 0.10, change this to simply "clients_max -| pipeline_prepare_queue_max".
|
|
173
|
+
// In Zig 0.9 compilation fails with "operation caused overflow" despite the saturating subtraction.
|
|
174
|
+
// See: https://github.com/ziglang/zig/issues/10870
|
|
175
|
+
pub const pipeline_request_queue_max =
|
|
176
|
+
if (clients_max < pipeline_prepare_queue_max)
|
|
177
|
+
0
|
|
178
|
+
else
|
|
179
|
+
clients_max - pipeline_prepare_queue_max;
|
|
180
|
+
|
|
181
|
+
comptime {
|
|
182
|
+
// A prepare-queue capacity larger than clients_max is wasted.
|
|
183
|
+
assert(pipeline_prepare_queue_max <= clients_max);
|
|
184
|
+
// A total queue capacity larger than clients_max is wasted.
|
|
185
|
+
assert(pipeline_prepare_queue_max + pipeline_request_queue_max <= clients_max);
|
|
186
|
+
assert(pipeline_prepare_queue_max > 0);
|
|
187
|
+
assert(pipeline_request_queue_max >= 0);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// The number of prepare headers to include in the body of a DVC/SV.
|
|
191
|
+
///
|
|
192
|
+
/// CRITICAL:
|
|
193
|
+
/// We must provide enough headers to cover all uncommitted headers so that the new
|
|
194
|
+
/// primary (if we are in a view change) can decide whether to discard uncommitted headers
|
|
195
|
+
/// that cannot be repaired because they are gaps. See DVCQuorum for more detail.
|
|
196
|
+
pub const view_change_headers_max = config.cluster.view_change_headers_max;
|
|
197
|
+
|
|
198
|
+
comptime {
|
|
199
|
+
assert(view_change_headers_max > 0);
|
|
200
|
+
assert(view_change_headers_max >= pipeline_prepare_queue_max);
|
|
201
|
+
assert(view_change_headers_max <= journal_slot_count);
|
|
202
|
+
assert(view_change_headers_max <= @divFloor(message_body_size_max, @sizeOf(vsr.Header)));
|
|
203
|
+
}
|
|
165
204
|
|
|
166
205
|
/// The minimum and maximum amount of time in milliseconds to wait before initiating a connection.
|
|
167
206
|
/// Exponential backoff and jitter are applied within this range.
|
|
@@ -263,7 +302,7 @@ pub const iops_write_max = journal_iops_write_max;
|
|
|
263
302
|
/// The maximum number of concurrent WAL read I/O operations to allow at once.
|
|
264
303
|
pub const journal_iops_read_max = config.process.journal_iops_read_max;
|
|
265
304
|
/// The maximum number of concurrent WAL write I/O operations to allow at once.
|
|
266
|
-
/// Ideally this is at least as high as
|
|
305
|
+
/// Ideally this is at least as high as pipeline_prepare_queue_max, but it is safe to be lower.
|
|
267
306
|
pub const journal_iops_write_max = config.process.journal_iops_write_max;
|
|
268
307
|
|
|
269
308
|
/// The number of redundant copies of the superblock in the superblock storage zone.
|
|
@@ -2,9 +2,9 @@ const std = @import("std");
|
|
|
2
2
|
const assert = std.debug.assert;
|
|
3
3
|
const math = std.math;
|
|
4
4
|
const mem = std.mem;
|
|
5
|
-
const
|
|
6
|
-
const div_ceil =
|
|
7
|
-
const disjoint_slices =
|
|
5
|
+
const stdx = @import("stdx.zig");
|
|
6
|
+
const div_ceil = stdx.div_ceil;
|
|
7
|
+
const disjoint_slices = stdx.disjoint_slices;
|
|
8
8
|
|
|
9
9
|
/// Encode or decode a bitset using Daniel Lemire's EWAH codec.
|
|
10
10
|
/// ("Histogram-Aware Sorting for Enhanced Word-Aligned Compression in Bitmap Indexes")
|
|
@@ -78,7 +78,7 @@ pub fn ewah(comptime Word: type) type {
|
|
|
78
78
|
if (marker.uniform_bit == 1) ~@as(Word, 0) else 0,
|
|
79
79
|
);
|
|
80
80
|
target_index += marker.uniform_word_count;
|
|
81
|
-
|
|
81
|
+
stdx.copy_disjoint(
|
|
82
82
|
.exact,
|
|
83
83
|
Word,
|
|
84
84
|
target_words[target_index..][0..marker.literal_word_count],
|
|
@@ -129,7 +129,7 @@ pub fn ewah(comptime Word: type) type {
|
|
|
129
129
|
.literal_word_count = @intCast(MarkerLiteralCount, literal_word_count),
|
|
130
130
|
});
|
|
131
131
|
target_index += 1;
|
|
132
|
-
|
|
132
|
+
stdx.copy_disjoint(
|
|
133
133
|
.exact,
|
|
134
134
|
Word,
|
|
135
135
|
target_words[target_index..][0..literal_word_count],
|
|
@@ -4,7 +4,7 @@ const assert = std.debug.assert;
|
|
|
4
4
|
const log = std.log.scoped(.fuzz_ewah);
|
|
5
5
|
|
|
6
6
|
const ewah = @import("./ewah.zig");
|
|
7
|
-
const fuzz = @import("./
|
|
7
|
+
const fuzz = @import("./testing/fuzz.zig");
|
|
8
8
|
|
|
9
9
|
pub const tigerbeetle_config = @import("config.zig").configs.test_min;
|
|
10
10
|
|
|
@@ -82,7 +82,7 @@ test {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
const test_bloom_filter = struct {
|
|
85
|
-
const fuzz = @import("../
|
|
85
|
+
const fuzz = @import("../testing/fuzz.zig");
|
|
86
86
|
const block_size = @import("../constants.zig").block_size;
|
|
87
87
|
|
|
88
88
|
fn random_keys(random: std.rand.Random, iter: usize) !void {
|
|
@@ -62,7 +62,12 @@ pub fn CompactionType(
|
|
|
62
62
|
const BlockWrite = struct {
|
|
63
63
|
write: Grid.Write = undefined,
|
|
64
64
|
block: *BlockPtr = undefined,
|
|
65
|
-
|
|
65
|
+
state: BlockState = .building,
|
|
66
|
+
};
|
|
67
|
+
const BlockState = enum {
|
|
68
|
+
building,
|
|
69
|
+
writable,
|
|
70
|
+
writing,
|
|
66
71
|
};
|
|
67
72
|
|
|
68
73
|
const Manifest = ManifestType(Table, Storage);
|
|
@@ -241,9 +246,9 @@ pub fn CompactionType(
|
|
|
241
246
|
.level_a_input = if (table_a) |table| table.* else null,
|
|
242
247
|
};
|
|
243
248
|
|
|
244
|
-
assert(
|
|
245
|
-
assert(
|
|
246
|
-
assert(
|
|
249
|
+
assert(compaction.index.state == .building);
|
|
250
|
+
assert(compaction.filter.state == .building);
|
|
251
|
+
assert(compaction.data.state == .building);
|
|
247
252
|
|
|
248
253
|
// TODO Implement manifest.move_table() optimization if there's only range.table_count == 1.
|
|
249
254
|
// This would do update_tables + insert_tables inline without going through the iterators.
|
|
@@ -342,6 +347,14 @@ pub fn CompactionType(
|
|
|
342
347
|
const write_callback = struct {
|
|
343
348
|
fn callback(write: *Grid.Write) void {
|
|
344
349
|
const block_write = @fieldParentPtr(BlockWrite, "write", write);
|
|
350
|
+
|
|
351
|
+
assert(block_write.state == .writing);
|
|
352
|
+
block_write.state = .building;
|
|
353
|
+
|
|
354
|
+
if (constants.verify) {
|
|
355
|
+
// We've finished writing so the block should now be zeroed.
|
|
356
|
+
assert(mem.allEqual(u8, block_write.block.*, 0));
|
|
357
|
+
}
|
|
345
358
|
block_write.block = undefined;
|
|
346
359
|
|
|
347
360
|
const _compaction = @fieldParentPtr(Compaction, @tagName(field), block_write);
|
|
@@ -350,8 +363,8 @@ pub fn CompactionType(
|
|
|
350
363
|
}.callback;
|
|
351
364
|
|
|
352
365
|
const block_write: *BlockWrite = &@field(compaction, @tagName(field));
|
|
353
|
-
if (block_write.writable) {
|
|
354
|
-
block_write.
|
|
366
|
+
if (block_write.state == .writable) {
|
|
367
|
+
block_write.state = .writing;
|
|
355
368
|
|
|
356
369
|
compaction.io_start();
|
|
357
370
|
compaction.grid.write_block(
|
|
@@ -405,9 +418,9 @@ pub fn CompactionType(
|
|
|
405
418
|
assert(!compaction.merge_iterator.?.empty());
|
|
406
419
|
}
|
|
407
420
|
|
|
408
|
-
assert(
|
|
409
|
-
assert(
|
|
410
|
-
assert(
|
|
421
|
+
assert(compaction.data.state == .building);
|
|
422
|
+
assert(compaction.filter.state == .building);
|
|
423
|
+
assert(compaction.index.state == .building);
|
|
411
424
|
|
|
412
425
|
if (!compaction.merge_iterator.?.empty()) {
|
|
413
426
|
compaction.cpu_merge();
|
|
@@ -444,9 +457,9 @@ pub fn CompactionType(
|
|
|
444
457
|
// Ensure there are values to merge and that is it safe to do so.
|
|
445
458
|
const merge_iterator = &compaction.merge_iterator.?;
|
|
446
459
|
assert(!merge_iterator.empty());
|
|
447
|
-
assert(
|
|
448
|
-
assert(
|
|
449
|
-
assert(
|
|
460
|
+
assert(compaction.data.state == .building);
|
|
461
|
+
assert(compaction.filter.state == .building);
|
|
462
|
+
assert(compaction.index.state == .building);
|
|
450
463
|
|
|
451
464
|
// Build up a data block with values merged from the read iterators.
|
|
452
465
|
// This skips tombstone values if compaction was started with the intent to drop them.
|
|
@@ -470,8 +483,8 @@ pub fn CompactionType(
|
|
|
470
483
|
|
|
471
484
|
// Mark the finished data block as writable for the next compact_tick() call.
|
|
472
485
|
compaction.data.block = &compaction.table_builder.data_block;
|
|
473
|
-
assert(
|
|
474
|
-
compaction.data.
|
|
486
|
+
assert(compaction.data.state == .building);
|
|
487
|
+
compaction.data.state = .writable;
|
|
475
488
|
}
|
|
476
489
|
|
|
477
490
|
// Finalize the filter block if it's full or if it contains pending data blocks
|
|
@@ -487,8 +500,8 @@ pub fn CompactionType(
|
|
|
487
500
|
|
|
488
501
|
// Mark the finished filter block as writable for the next compact_tick() call.
|
|
489
502
|
compaction.filter.block = &compaction.table_builder.filter_block;
|
|
490
|
-
assert(
|
|
491
|
-
compaction.filter.
|
|
503
|
+
assert(compaction.filter.state == .building);
|
|
504
|
+
compaction.filter.state = .writable;
|
|
492
505
|
}
|
|
493
506
|
|
|
494
507
|
// Finalize the index block if it's full or if it contains pending data blocks
|
|
@@ -507,8 +520,8 @@ pub fn CompactionType(
|
|
|
507
520
|
|
|
508
521
|
// Mark the finished index block as writable for the next compact_tick() call.
|
|
509
522
|
compaction.index.block = &compaction.table_builder.index_block;
|
|
510
|
-
assert(
|
|
511
|
-
compaction.index.
|
|
523
|
+
assert(compaction.index.state == .building);
|
|
524
|
+
compaction.index.state = .writable;
|
|
512
525
|
|
|
513
526
|
compaction.tables_output_count += 1;
|
|
514
527
|
assert(compaction.tables_output_count <= compaction.range.table_count);
|
|
@@ -524,9 +537,9 @@ pub fn CompactionType(
|
|
|
524
537
|
|
|
525
538
|
// Ensure merging is truly finished.
|
|
526
539
|
assert(compaction.merge_iterator.?.empty());
|
|
527
|
-
assert(
|
|
528
|
-
assert(
|
|
529
|
-
assert(
|
|
540
|
+
assert(compaction.data.state == .building);
|
|
541
|
+
assert(compaction.filter.state == .building);
|
|
542
|
+
assert(compaction.index.state == .building);
|
|
530
543
|
|
|
531
544
|
// Double check the iterators are finished as well.
|
|
532
545
|
const stream_empty = struct {
|