tigerbeetle-node 0.4.2 → 0.5.2
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/README.md +19 -5
- package/dist/benchmark.js.map +1 -1
- package/dist/index.d.ts +18 -16
- package/dist/index.js +35 -13
- package/dist/index.js.map +1 -1
- package/dist/test.js +12 -0
- package/dist/test.js.map +1 -1
- package/package.json +2 -2
- package/scripts/postinstall.sh +2 -2
- package/src/benchmark.ts +2 -2
- package/src/index.ts +29 -4
- package/src/node.zig +120 -17
- package/src/test.ts +14 -0
- package/src/tigerbeetle/scripts/install.sh +1 -1
- package/src/tigerbeetle/scripts/install_zig.bat +109 -0
- package/src/tigerbeetle/scripts/install_zig.sh +4 -2
- package/src/tigerbeetle/scripts/lint.zig +8 -2
- package/src/tigerbeetle/scripts/vopr.bat +48 -0
- package/src/tigerbeetle/src/benchmark.zig +10 -8
- package/src/tigerbeetle/src/cli.zig +6 -4
- package/src/tigerbeetle/src/config.zig +2 -2
- package/src/tigerbeetle/src/demo.zig +119 -89
- package/src/tigerbeetle/src/demo_01_create_accounts.zig +5 -3
- package/src/tigerbeetle/src/demo_02_lookup_accounts.zig +2 -3
- package/src/tigerbeetle/src/demo_03_create_transfers.zig +5 -3
- package/src/tigerbeetle/src/demo_04_create_transfers_two_phase_commit.zig +5 -3
- package/src/tigerbeetle/src/demo_05_accept_transfers.zig +5 -3
- package/src/tigerbeetle/src/demo_06_reject_transfers.zig +5 -3
- package/src/tigerbeetle/src/demo_07_lookup_transfers.zig +7 -0
- package/src/tigerbeetle/src/io/benchmark.zig +238 -0
- package/src/tigerbeetle/src/{io_darwin.zig → io/darwin.zig} +89 -124
- package/src/tigerbeetle/src/io/linux.zig +933 -0
- package/src/tigerbeetle/src/io/test.zig +621 -0
- package/src/tigerbeetle/src/io.zig +7 -1328
- package/src/tigerbeetle/src/main.zig +18 -10
- package/src/tigerbeetle/src/message_bus.zig +43 -60
- package/src/tigerbeetle/src/message_pool.zig +3 -2
- package/src/tigerbeetle/src/ring_buffer.zig +135 -68
- package/src/tigerbeetle/src/simulator.zig +41 -37
- package/src/tigerbeetle/src/state_machine.zig +851 -26
- package/src/tigerbeetle/src/storage.zig +49 -46
- package/src/tigerbeetle/src/test/cluster.zig +2 -2
- package/src/tigerbeetle/src/test/message_bus.zig +6 -6
- package/src/tigerbeetle/src/test/network.zig +3 -3
- package/src/tigerbeetle/src/test/packet_simulator.zig +32 -29
- package/src/tigerbeetle/src/test/state_checker.zig +2 -2
- package/src/tigerbeetle/src/test/state_machine.zig +4 -0
- package/src/tigerbeetle/src/test/storage.zig +39 -19
- package/src/tigerbeetle/src/test/time.zig +2 -2
- package/src/tigerbeetle/src/tigerbeetle.zig +6 -129
- package/src/tigerbeetle/src/time.zig +6 -5
- package/src/tigerbeetle/src/vsr/client.zig +11 -11
- package/src/tigerbeetle/src/vsr/clock.zig +26 -43
- package/src/tigerbeetle/src/vsr/journal.zig +7 -6
- package/src/tigerbeetle/src/vsr/marzullo.zig +6 -3
- package/src/tigerbeetle/src/vsr/replica.zig +51 -48
- package/src/tigerbeetle/src/vsr.zig +24 -20
- package/src/translate.zig +55 -55
|
@@ -55,8 +55,10 @@ pub const Storage = struct {
|
|
|
55
55
|
/// Tick at which this read is considered "completed" and the callback should be called.
|
|
56
56
|
done_at_tick: u64,
|
|
57
57
|
|
|
58
|
-
fn less_than(
|
|
59
|
-
|
|
58
|
+
fn less_than(context: void, a: *Read, b: *Read) math.Order {
|
|
59
|
+
_ = context;
|
|
60
|
+
|
|
61
|
+
return math.order(a.done_at_tick, b.done_at_tick);
|
|
60
62
|
}
|
|
61
63
|
};
|
|
62
64
|
|
|
@@ -67,8 +69,10 @@ pub const Storage = struct {
|
|
|
67
69
|
/// Tick at which this write is considered "completed" and the callback should be called.
|
|
68
70
|
done_at_tick: u64,
|
|
69
71
|
|
|
70
|
-
fn less_than(
|
|
71
|
-
|
|
72
|
+
fn less_than(context: void, a: *Write, b: *Write) math.Order {
|
|
73
|
+
_ = context;
|
|
74
|
+
|
|
75
|
+
return math.order(a.done_at_tick, b.done_at_tick);
|
|
72
76
|
}
|
|
73
77
|
};
|
|
74
78
|
|
|
@@ -92,13 +96,13 @@ pub const Storage = struct {
|
|
|
92
96
|
// allow faults in certian areas which differ between replicas.
|
|
93
97
|
faulty_areas: FaultyAreas,
|
|
94
98
|
|
|
95
|
-
reads: std.PriorityQueue(*Storage.Read),
|
|
96
|
-
writes: std.PriorityQueue(*Storage.Write),
|
|
99
|
+
reads: std.PriorityQueue(*Storage.Read, void, Storage.Read.less_than),
|
|
100
|
+
writes: std.PriorityQueue(*Storage.Write, void, Storage.Write.less_than),
|
|
97
101
|
|
|
98
102
|
ticks: u64 = 0,
|
|
99
103
|
|
|
100
104
|
pub fn init(
|
|
101
|
-
allocator:
|
|
105
|
+
allocator: mem.Allocator,
|
|
102
106
|
size: u64,
|
|
103
107
|
options: Storage.Options,
|
|
104
108
|
replica_index: u8,
|
|
@@ -112,13 +116,13 @@ pub const Storage = struct {
|
|
|
112
116
|
// TODO: random data
|
|
113
117
|
mem.set(u8, memory, 0);
|
|
114
118
|
|
|
115
|
-
var reads = std.PriorityQueue(*Storage.Read
|
|
119
|
+
var reads = std.PriorityQueue(*Storage.Read, void, Storage.Read.less_than).init(allocator, {});
|
|
116
120
|
errdefer reads.deinit();
|
|
117
|
-
try reads.
|
|
121
|
+
try reads.ensureTotalCapacity(config.io_depth_read);
|
|
118
122
|
|
|
119
|
-
var writes = std.PriorityQueue(*Storage.Write
|
|
123
|
+
var writes = std.PriorityQueue(*Storage.Write, void, Storage.Write.less_than).init(allocator, {});
|
|
120
124
|
errdefer writes.deinit();
|
|
121
|
-
try writes.
|
|
125
|
+
try writes.ensureTotalCapacity(config.io_depth_write);
|
|
122
126
|
|
|
123
127
|
return Storage{
|
|
124
128
|
.memory = memory,
|
|
@@ -138,7 +142,7 @@ pub const Storage = struct {
|
|
|
138
142
|
storage.writes.len = 0;
|
|
139
143
|
}
|
|
140
144
|
|
|
141
|
-
pub fn deinit(storage: *Storage, allocator:
|
|
145
|
+
pub fn deinit(storage: *Storage, allocator: mem.Allocator) void {
|
|
142
146
|
allocator.free(storage.memory);
|
|
143
147
|
storage.reads.deinit();
|
|
144
148
|
storage.writes.deinit();
|
|
@@ -186,7 +190,7 @@ pub const Storage = struct {
|
|
|
186
190
|
// Randomly corrupt one of the faulty sectors the read targeted
|
|
187
191
|
// TODO: inject more realistic and varied storage faults as described above.
|
|
188
192
|
const sector_count = @divExact(faulty.len, config.sector_size);
|
|
189
|
-
const faulty_sector = storage.prng.random.uintLessThan(u64, sector_count);
|
|
193
|
+
const faulty_sector = storage.prng.random().uintLessThan(u64, sector_count);
|
|
190
194
|
const faulty_sector_offset = faulty_sector * config.sector_size;
|
|
191
195
|
const faulty_sector_bytes = faulty[faulty_sector_offset..][0..config.sector_size];
|
|
192
196
|
|
|
@@ -195,7 +199,7 @@ pub const Storage = struct {
|
|
|
195
199
|
storage.replica_index,
|
|
196
200
|
});
|
|
197
201
|
|
|
198
|
-
storage.prng.random.bytes(faulty_sector_bytes);
|
|
202
|
+
storage.prng.random().bytes(faulty_sector_bytes);
|
|
199
203
|
}
|
|
200
204
|
|
|
201
205
|
mem.copy(u8, read.buffer, storage.memory[read.offset..][0..read.buffer.len]);
|
|
@@ -230,7 +234,7 @@ pub const Storage = struct {
|
|
|
230
234
|
// Randomly corrupt one of the faulty sectors the write targeted
|
|
231
235
|
// TODO: inject more realistic and varied storage faults as described above.
|
|
232
236
|
const sector_count = @divExact(faulty.len, config.sector_size);
|
|
233
|
-
const faulty_sector = storage.prng.random.uintLessThan(u64, sector_count);
|
|
237
|
+
const faulty_sector = storage.prng.random().uintLessThan(u64, sector_count);
|
|
234
238
|
const faulty_sector_offset = faulty_sector * config.sector_size;
|
|
235
239
|
const faulty_sector_bytes = faulty[faulty_sector_offset..][0..config.sector_size];
|
|
236
240
|
|
|
@@ -239,7 +243,7 @@ pub const Storage = struct {
|
|
|
239
243
|
storage.replica_index,
|
|
240
244
|
});
|
|
241
245
|
|
|
242
|
-
storage.prng.random.bytes(faulty_sector_bytes);
|
|
246
|
+
storage.prng.random().bytes(faulty_sector_bytes);
|
|
243
247
|
}
|
|
244
248
|
|
|
245
249
|
write.callback(write);
|
|
@@ -265,18 +269,18 @@ pub const Storage = struct {
|
|
|
265
269
|
}
|
|
266
270
|
|
|
267
271
|
fn latency(storage: *Storage, min: u64, mean: u64) u64 {
|
|
268
|
-
return min + @floatToInt(u64, @intToFloat(f64, mean - min) * storage.prng.random.floatExp(f64));
|
|
272
|
+
return min + @floatToInt(u64, @intToFloat(f64, mean - min) * storage.prng.random().floatExp(f64));
|
|
269
273
|
}
|
|
270
274
|
|
|
271
275
|
/// Return true with probability x/100.
|
|
272
276
|
fn x_in_100(storage: *Storage, x: u8) bool {
|
|
273
277
|
assert(x <= 100);
|
|
274
|
-
return x > storage.prng.random.uintLessThan(u8, 100);
|
|
278
|
+
return x > storage.prng.random().uintLessThan(u8, 100);
|
|
275
279
|
}
|
|
276
280
|
|
|
277
281
|
/// The return value is a slice into the provided out array.
|
|
278
282
|
pub fn generate_faulty_areas(
|
|
279
|
-
prng:
|
|
283
|
+
prng: std.rand.Random,
|
|
280
284
|
size: u64,
|
|
281
285
|
replica_count: u8,
|
|
282
286
|
out: *[config.replicas_max]FaultyAreas,
|
|
@@ -287,6 +291,7 @@ pub const Storage = struct {
|
|
|
287
291
|
// We need to ensure there is message_size_max fault-free padding
|
|
288
292
|
// between faulty areas of memory so that a single message
|
|
289
293
|
// cannot straddle the corruptable areas of a majority of replicas.
|
|
294
|
+
comptime assert(config.replicas_max == 6);
|
|
290
295
|
switch (replica_count) {
|
|
291
296
|
1 => {
|
|
292
297
|
// If there is only one replica in the cluster, storage faults are not recoverable.
|
|
@@ -332,6 +337,21 @@ pub const Storage = struct {
|
|
|
332
337
|
out[3] = .{ .first_offset = 2 * message_size_max, .period = 6 * message_size_max };
|
|
333
338
|
out[4] = .{ .first_offset = 4 * message_size_max, .period = 6 * message_size_max };
|
|
334
339
|
},
|
|
340
|
+
6 => {
|
|
341
|
+
// 0123456789
|
|
342
|
+
// 0X X
|
|
343
|
+
// 1X X
|
|
344
|
+
// 2 X X
|
|
345
|
+
// 3 X X
|
|
346
|
+
// 4 X X
|
|
347
|
+
// 5 X X
|
|
348
|
+
out[0] = .{ .first_offset = 0 * message_size_max, .period = 6 * message_size_max };
|
|
349
|
+
out[1] = .{ .first_offset = 0 * message_size_max, .period = 6 * message_size_max };
|
|
350
|
+
out[2] = .{ .first_offset = 2 * message_size_max, .period = 6 * message_size_max };
|
|
351
|
+
out[3] = .{ .first_offset = 2 * message_size_max, .period = 6 * message_size_max };
|
|
352
|
+
out[4] = .{ .first_offset = 4 * message_size_max, .period = 6 * message_size_max };
|
|
353
|
+
out[5] = .{ .first_offset = 4 * message_size_max, .period = 6 * message_size_max };
|
|
354
|
+
},
|
|
335
355
|
else => unreachable,
|
|
336
356
|
}
|
|
337
357
|
|
|
@@ -65,11 +65,11 @@ pub const Time = struct {
|
|
|
65
65
|
},
|
|
66
66
|
.non_ideal => {
|
|
67
67
|
const phase: f64 = @intToFloat(f64, ticks) * 2 * std.math.pi /
|
|
68
|
-
(@intToFloat(f64, self.offset_coefficient_B) + self.prng.random.floatNorm(f64) * 10);
|
|
68
|
+
(@intToFloat(f64, self.offset_coefficient_B) + self.prng.random().floatNorm(f64) * 10);
|
|
69
69
|
const unscaled = std.math.sin(phase);
|
|
70
70
|
const scaled = @intToFloat(f64, self.offset_coefficient_A) * unscaled;
|
|
71
71
|
return @floatToInt(i64, std.math.floor(scaled)) +
|
|
72
|
-
self.prng.random.intRangeAtMost(
|
|
72
|
+
self.prng.random().intRangeAtMost(
|
|
73
73
|
i64,
|
|
74
74
|
-@intCast(i64, self.offset_coefficient_C),
|
|
75
75
|
self.offset_coefficient_C,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const builtin = @import("builtin");
|
|
2
3
|
const assert = std.debug.assert;
|
|
3
4
|
|
|
4
5
|
pub const config = @import("config.zig");
|
|
@@ -32,24 +33,6 @@ pub const Account = packed struct {
|
|
|
32
33
|
return (self.flags.credits_must_not_exceed_debits and
|
|
33
34
|
self.credits_reserved + self.credits_accepted + amount > self.debits_accepted);
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
-
pub fn jsonStringify(self: Account, options: std.json.StringifyOptions, writer: anytype) !void {
|
|
37
|
-
try writer.writeAll("{");
|
|
38
|
-
try std.fmt.format(writer, "\"id\":{},", .{self.id});
|
|
39
|
-
try std.fmt.format(writer, "\"user_data\":\"{x:0>32}\",", .{self.user_data});
|
|
40
|
-
try std.fmt.format(writer, "\"reserved\":\"{x:0>48}\",", .{self.reserved});
|
|
41
|
-
try std.fmt.format(writer, "\"unit\":{},", .{self.unit});
|
|
42
|
-
try std.fmt.format(writer, "\"code\":{},", .{self.code});
|
|
43
|
-
try writer.writeAll("\"flags\":");
|
|
44
|
-
try std.json.stringify(self.flags, .{}, writer);
|
|
45
|
-
try writer.writeAll(",");
|
|
46
|
-
try std.fmt.format(writer, "\"debits_reserved\":{},", .{self.debits_reserved});
|
|
47
|
-
try std.fmt.format(writer, "\"debits_accepted\":{},", .{self.debits_accepted});
|
|
48
|
-
try std.fmt.format(writer, "\"credits_reserved\":{},", .{self.credits_reserved});
|
|
49
|
-
try std.fmt.format(writer, "\"credits_accepted\":{},", .{self.credits_accepted});
|
|
50
|
-
try std.fmt.format(writer, "\"timestamp\":\"{}\"", .{self.timestamp});
|
|
51
|
-
try writer.writeAll("}");
|
|
52
|
-
}
|
|
53
36
|
};
|
|
54
37
|
|
|
55
38
|
pub const AccountFlags = packed struct {
|
|
@@ -71,14 +54,6 @@ pub const AccountFlags = packed struct {
|
|
|
71
54
|
comptime {
|
|
72
55
|
assert(@sizeOf(AccountFlags) == @sizeOf(u32));
|
|
73
56
|
}
|
|
74
|
-
|
|
75
|
-
pub fn jsonStringify(
|
|
76
|
-
self: AccountFlags,
|
|
77
|
-
options: std.json.StringifyOptions,
|
|
78
|
-
writer: anytype,
|
|
79
|
-
) !void {
|
|
80
|
-
try writer.writeAll("{}");
|
|
81
|
-
}
|
|
82
57
|
};
|
|
83
58
|
|
|
84
59
|
pub const Transfer = packed struct {
|
|
@@ -99,27 +74,6 @@ pub const Transfer = packed struct {
|
|
|
99
74
|
comptime {
|
|
100
75
|
assert(@sizeOf(Transfer) == 128);
|
|
101
76
|
}
|
|
102
|
-
|
|
103
|
-
pub fn jsonStringify(
|
|
104
|
-
self: Transfer,
|
|
105
|
-
options: std.json.StringifyOptions,
|
|
106
|
-
writer: anytype,
|
|
107
|
-
) !void {
|
|
108
|
-
try writer.writeAll("{");
|
|
109
|
-
try std.fmt.format(writer, "\"id\":{},", .{self.id});
|
|
110
|
-
try std.fmt.format(writer, "\"debit_account_id\":{},", .{self.debit_account_id});
|
|
111
|
-
try std.fmt.format(writer, "\"credit_account_id\":{},", .{self.credit_account_id});
|
|
112
|
-
try std.fmt.format(writer, "\"user_data\":\"{x:0>32}\",", .{self.user_data});
|
|
113
|
-
try std.fmt.format(writer, "\"reserved\":\"{x:0>64}\",", .{self.reserved});
|
|
114
|
-
try std.fmt.format(writer, "\"code\":{},", .{self.code});
|
|
115
|
-
try writer.writeAll("\"flags\":");
|
|
116
|
-
try std.json.stringify(self.flags, .{}, writer);
|
|
117
|
-
try writer.writeAll(",");
|
|
118
|
-
try std.fmt.format(writer, "\"amount\":{},", .{self.amount});
|
|
119
|
-
try std.fmt.format(writer, "\"timeout\":{},", .{self.timeout});
|
|
120
|
-
try std.fmt.format(writer, "\"timestamp\":{}", .{self.timestamp});
|
|
121
|
-
try writer.writeAll("}");
|
|
122
|
-
}
|
|
123
77
|
};
|
|
124
78
|
|
|
125
79
|
pub const TransferFlags = packed struct {
|
|
@@ -131,19 +85,6 @@ pub const TransferFlags = packed struct {
|
|
|
131
85
|
comptime {
|
|
132
86
|
assert(@sizeOf(TransferFlags) == @sizeOf(u32));
|
|
133
87
|
}
|
|
134
|
-
|
|
135
|
-
pub fn jsonStringify(
|
|
136
|
-
self: TransferFlags,
|
|
137
|
-
options: std.json.StringifyOptions,
|
|
138
|
-
writer: anytype,
|
|
139
|
-
) !void {
|
|
140
|
-
try writer.writeAll("{");
|
|
141
|
-
try std.fmt.format(writer, "\"accept\":{},", .{self.accept});
|
|
142
|
-
try std.fmt.format(writer, "\"reject\":{},", .{self.reject});
|
|
143
|
-
try std.fmt.format(writer, "\"auto_commit\":{},", .{self.auto_commit});
|
|
144
|
-
try std.fmt.format(writer, "\"condition\":{}", .{self.condition});
|
|
145
|
-
try writer.writeAll("}");
|
|
146
|
-
}
|
|
147
88
|
};
|
|
148
89
|
|
|
149
90
|
pub const Commit = packed struct {
|
|
@@ -158,22 +99,6 @@ pub const Commit = packed struct {
|
|
|
158
99
|
comptime {
|
|
159
100
|
assert(@sizeOf(Commit) == 64);
|
|
160
101
|
}
|
|
161
|
-
|
|
162
|
-
pub fn jsonStringify(
|
|
163
|
-
self: Commit,
|
|
164
|
-
options: std.json.StringifyOptions,
|
|
165
|
-
writer: anytype,
|
|
166
|
-
) !void {
|
|
167
|
-
try writer.writeAll("{");
|
|
168
|
-
try std.fmt.format(writer, "\"id\":{},", .{self.id});
|
|
169
|
-
try std.fmt.format(writer, "\"reserved\":\"{x:0>64}\",", .{self.reserved});
|
|
170
|
-
try std.fmt.format(writer, "\"code\":{},", .{self.code});
|
|
171
|
-
try writer.writeAll("\"flags\":");
|
|
172
|
-
try std.json.stringify(self.flags, .{}, writer);
|
|
173
|
-
try writer.writeAll(",");
|
|
174
|
-
try std.fmt.format(writer, "\"timestamp\":{}", .{self.timestamp});
|
|
175
|
-
try writer.writeAll("}");
|
|
176
|
-
}
|
|
177
102
|
};
|
|
178
103
|
|
|
179
104
|
pub const CommitFlags = packed struct {
|
|
@@ -185,21 +110,9 @@ pub const CommitFlags = packed struct {
|
|
|
185
110
|
comptime {
|
|
186
111
|
assert(@sizeOf(CommitFlags) == @sizeOf(u32));
|
|
187
112
|
}
|
|
188
|
-
|
|
189
|
-
pub fn jsonStringify(
|
|
190
|
-
self: CommitFlags,
|
|
191
|
-
options: std.json.StringifyOptions,
|
|
192
|
-
writer: anytype,
|
|
193
|
-
) !void {
|
|
194
|
-
try writer.writeAll("{");
|
|
195
|
-
try std.fmt.format(writer, "\"accept\":{},", .{self.accept});
|
|
196
|
-
try std.fmt.format(writer, "\"reject\":{},", .{self.reject});
|
|
197
|
-
try std.fmt.format(writer, "\"preimage\":{}", .{self.preimage});
|
|
198
|
-
try writer.writeAll("}");
|
|
199
|
-
}
|
|
200
113
|
};
|
|
201
114
|
|
|
202
|
-
pub const CreateAccountResult =
|
|
115
|
+
pub const CreateAccountResult = enum(u32) {
|
|
203
116
|
ok,
|
|
204
117
|
linked_event_failed,
|
|
205
118
|
exists,
|
|
@@ -214,7 +127,7 @@ pub const CreateAccountResult = packed enum(u32) {
|
|
|
214
127
|
reserved_flag_padding,
|
|
215
128
|
};
|
|
216
129
|
|
|
217
|
-
pub const CreateTransferResult =
|
|
130
|
+
pub const CreateTransferResult = enum(u32) {
|
|
218
131
|
ok,
|
|
219
132
|
linked_event_failed,
|
|
220
133
|
exists,
|
|
@@ -241,7 +154,7 @@ pub const CreateTransferResult = packed enum(u32) {
|
|
|
241
154
|
timeout_reserved_for_two_phase_commit,
|
|
242
155
|
};
|
|
243
156
|
|
|
244
|
-
pub const CommitTransferResult =
|
|
157
|
+
pub const CommitTransferResult = enum(u32) {
|
|
245
158
|
ok,
|
|
246
159
|
linked_event_failed,
|
|
247
160
|
reserved_field,
|
|
@@ -249,7 +162,6 @@ pub const CommitTransferResult = packed enum(u32) {
|
|
|
249
162
|
transfer_not_found,
|
|
250
163
|
transfer_not_two_phase_commit,
|
|
251
164
|
transfer_expired,
|
|
252
|
-
already_auto_committed,
|
|
253
165
|
already_committed,
|
|
254
166
|
already_committed_but_accepted,
|
|
255
167
|
already_committed_but_rejected,
|
|
@@ -271,17 +183,6 @@ pub const CreateAccountsResult = packed struct {
|
|
|
271
183
|
comptime {
|
|
272
184
|
assert(@sizeOf(CreateAccountsResult) == 8);
|
|
273
185
|
}
|
|
274
|
-
|
|
275
|
-
pub fn jsonStringify(
|
|
276
|
-
self: CreateAccountResults,
|
|
277
|
-
options: std.json.StringifyOptions,
|
|
278
|
-
writer: anytype,
|
|
279
|
-
) !void {
|
|
280
|
-
try writer.writeAll("{");
|
|
281
|
-
try std.fmt.format(writer, "\"index\":{},", .{self.index});
|
|
282
|
-
try std.fmt.format(writer, "\"result\":\"{}\"", .{@tagName(self.result)});
|
|
283
|
-
try writer.writeAll("}");
|
|
284
|
-
}
|
|
285
186
|
};
|
|
286
187
|
|
|
287
188
|
pub const CreateTransfersResult = packed struct {
|
|
@@ -291,17 +192,6 @@ pub const CreateTransfersResult = packed struct {
|
|
|
291
192
|
comptime {
|
|
292
193
|
assert(@sizeOf(CreateTransfersResult) == 8);
|
|
293
194
|
}
|
|
294
|
-
|
|
295
|
-
pub fn jsonStringify(
|
|
296
|
-
self: CreateTransferResults,
|
|
297
|
-
options: std.json.StringifyOptions,
|
|
298
|
-
writer: anytype,
|
|
299
|
-
) !void {
|
|
300
|
-
try writer.writeAll("{");
|
|
301
|
-
try std.fmt.format(writer, "\"index\":{},", .{self.index});
|
|
302
|
-
try std.fmt.format(writer, "\"result\":\"{}\"", .{@tagName(self.result)});
|
|
303
|
-
try writer.writeAll("}");
|
|
304
|
-
}
|
|
305
195
|
};
|
|
306
196
|
|
|
307
197
|
pub const CommitTransfersResult = packed struct {
|
|
@@ -311,28 +201,15 @@ pub const CommitTransfersResult = packed struct {
|
|
|
311
201
|
comptime {
|
|
312
202
|
assert(@sizeOf(CommitTransfersResult) == 8);
|
|
313
203
|
}
|
|
314
|
-
|
|
315
|
-
pub fn jsonStringify(
|
|
316
|
-
self: CommitTransferResults,
|
|
317
|
-
options: std.json.StringifyOptions,
|
|
318
|
-
writer: anytype,
|
|
319
|
-
) !void {
|
|
320
|
-
try writer.writeAll("{");
|
|
321
|
-
try std.fmt.format(writer, "\"index\":{},", .{self.index});
|
|
322
|
-
try std.fmt.format(writer, "\"result\":\"{}\"", .{@tagName(self.result)});
|
|
323
|
-
try writer.writeAll("}");
|
|
324
|
-
}
|
|
325
204
|
};
|
|
326
205
|
|
|
327
206
|
comptime {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
if (target.os.tag != .linux and !target.isDarwin()) {
|
|
207
|
+
if (builtin.target.os.tag != .linux and !builtin.target.isDarwin()) {
|
|
331
208
|
@compileError("linux or macos required for io");
|
|
332
209
|
}
|
|
333
210
|
|
|
334
211
|
// We require little-endian architectures everywhere for efficient network deserialization:
|
|
335
|
-
if (target.cpu.arch.endian() !=
|
|
212
|
+
if (builtin.target.cpu.arch.endian() != .Little) {
|
|
336
213
|
@compileError("big-endian systems not supported");
|
|
337
214
|
}
|
|
338
215
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const builtin = @import("builtin");
|
|
2
3
|
const assert = std.debug.assert;
|
|
3
|
-
const is_darwin =
|
|
4
|
+
const is_darwin = builtin.target.isDarwin();
|
|
4
5
|
const config = @import("./config.zig");
|
|
5
6
|
|
|
6
7
|
pub const Time = struct {
|
|
@@ -40,7 +41,7 @@ pub const Time = struct {
|
|
|
40
41
|
// For more detail and why CLOCK_MONOTONIC_RAW is even worse than CLOCK_MONOTONIC,
|
|
41
42
|
// see https://github.com/ziglang/zig/pull/933#discussion_r656021295.
|
|
42
43
|
var ts: std.os.timespec = undefined;
|
|
43
|
-
std.os.clock_gettime(std.os.
|
|
44
|
+
std.os.clock_gettime(std.os.CLOCK.BOOTTIME, &ts) catch @panic("CLOCK_BOOTTIME required");
|
|
44
45
|
break :blk @intCast(u64, ts.tv_sec) * std.time.ns_per_s + @intCast(u64, ts.tv_nsec);
|
|
45
46
|
};
|
|
46
47
|
|
|
@@ -52,14 +53,14 @@ pub const Time = struct {
|
|
|
52
53
|
|
|
53
54
|
/// A timestamp to measure real (i.e. wall clock) time, meaningful across systems, and reboots.
|
|
54
55
|
/// This clock is affected by discontinuous jumps in the system time.
|
|
55
|
-
pub fn realtime(
|
|
56
|
+
pub fn realtime(_: *Self) i64 {
|
|
56
57
|
// macos has supported clock_gettime() since 10.12:
|
|
57
58
|
// https://opensource.apple.com/source/Libc/Libc-1158.1.2/gen/clock_gettime.3.auto.html
|
|
58
59
|
|
|
59
60
|
var ts: std.os.timespec = undefined;
|
|
60
|
-
std.os.clock_gettime(std.os.
|
|
61
|
+
std.os.clock_gettime(std.os.CLOCK.REALTIME, &ts) catch unreachable;
|
|
61
62
|
return @as(i64, ts.tv_sec) * std.time.ns_per_s + ts.tv_nsec;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
pub fn tick(
|
|
65
|
+
pub fn tick(_: *Self) void {}
|
|
65
66
|
};
|
|
@@ -30,7 +30,7 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
30
30
|
message: *Message,
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
allocator:
|
|
33
|
+
allocator: mem.Allocator,
|
|
34
34
|
message_bus: *MessageBus,
|
|
35
35
|
|
|
36
36
|
/// A universally unique identifier for the client (must not be zero).
|
|
@@ -82,7 +82,7 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
82
82
|
prng: std.rand.DefaultPrng,
|
|
83
83
|
|
|
84
84
|
pub fn init(
|
|
85
|
-
allocator:
|
|
85
|
+
allocator: mem.Allocator,
|
|
86
86
|
id: u128,
|
|
87
87
|
cluster: u32,
|
|
88
88
|
replica_count: u8,
|
|
@@ -115,7 +115,7 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
115
115
|
return self;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
pub fn deinit(
|
|
118
|
+
pub fn deinit(_: *Self) void {}
|
|
119
119
|
|
|
120
120
|
pub fn on_message(self: *Self, message: *Message) void {
|
|
121
121
|
log.debug("{}: on_message: {}", .{ self.id, message.header });
|
|
@@ -238,7 +238,7 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
238
238
|
assert(eviction.header.client == self.id);
|
|
239
239
|
assert(eviction.header.view >= self.view);
|
|
240
240
|
|
|
241
|
-
log.
|
|
241
|
+
log.err("{}: session evicted: too many concurrent client sessions", .{self.id});
|
|
242
242
|
@panic("session evicted: too many concurrent client sessions");
|
|
243
243
|
}
|
|
244
244
|
|
|
@@ -279,7 +279,7 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
279
279
|
return;
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
-
if (self.request_queue.
|
|
282
|
+
if (self.request_queue.head_ptr()) |inflight| {
|
|
283
283
|
if (reply.header.request < inflight.message.header.request) {
|
|
284
284
|
log.debug("{}: on_reply: ignoring (request {} < {})", .{
|
|
285
285
|
self.id,
|
|
@@ -334,7 +334,7 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
334
334
|
|
|
335
335
|
// We must process the next request before releasing control back to the callback.
|
|
336
336
|
// Otherwise, requests may run through send_request_for_the_first_time() more than once.
|
|
337
|
-
if (self.request_queue.
|
|
337
|
+
if (self.request_queue.head_ptr()) |next_request| {
|
|
338
338
|
self.send_request_for_the_first_time(next_request.message);
|
|
339
339
|
}
|
|
340
340
|
|
|
@@ -361,9 +361,9 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
fn on_request_timeout(self: *Self) void {
|
|
364
|
-
self.request_timeout.backoff(
|
|
364
|
+
self.request_timeout.backoff(self.prng.random());
|
|
365
365
|
|
|
366
|
-
const message = self.request_queue.
|
|
366
|
+
const message = self.request_queue.head_ptr().?.message;
|
|
367
367
|
assert(message.header.command == .request);
|
|
368
368
|
assert(message.header.request < self.request_number);
|
|
369
369
|
assert(message.header.checksum == self.parent);
|
|
@@ -435,7 +435,7 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
435
435
|
|
|
436
436
|
fn send_header_to_replica(self: *Self, replica: u8, header: Header) void {
|
|
437
437
|
const message = self.create_message_from_header(header) orelse {
|
|
438
|
-
log.
|
|
438
|
+
log.err("{}: no header-only message available, dropping message to replica {}", .{
|
|
439
439
|
self.id,
|
|
440
440
|
replica,
|
|
441
441
|
});
|
|
@@ -448,7 +448,7 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
448
448
|
|
|
449
449
|
fn send_header_to_replicas(self: *Self, header: Header) void {
|
|
450
450
|
const message = self.create_message_from_header(header) orelse {
|
|
451
|
-
log.
|
|
451
|
+
log.err("{}: no header-only message available, dropping message to replicas", .{
|
|
452
452
|
self.id,
|
|
453
453
|
});
|
|
454
454
|
return;
|
|
@@ -478,7 +478,7 @@ pub fn Client(comptime StateMachine: type, comptime MessageBus: type) type {
|
|
|
478
478
|
}
|
|
479
479
|
|
|
480
480
|
fn send_request_for_the_first_time(self: *Self, message: *Message) void {
|
|
481
|
-
assert(self.request_queue.
|
|
481
|
+
assert(self.request_queue.head_ptr().?.message == message);
|
|
482
482
|
|
|
483
483
|
assert(message.header.command == .request);
|
|
484
484
|
assert(message.header.parent == 0);
|