tigerbeetle-node 0.4.3 → 0.5.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/README.md +20 -4
- 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 +1 -1
- package/src/benchmark.ts +2 -2
- package/src/index.ts +29 -4
- package/src/node.zig +103 -2
- 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/vopr.bat +48 -0
- package/src/tigerbeetle/src/benchmark.zig +2 -2
- package/src/tigerbeetle/src/demo.zig +8 -0
- package/src/tigerbeetle/src/demo_07_lookup_transfers.zig +8 -0
- package/src/tigerbeetle/src/io.zig +2 -2
- package/src/tigerbeetle/src/io_darwin.zig +4 -0
- package/src/tigerbeetle/src/message_bus.zig +3 -3
- package/src/tigerbeetle/src/ring_buffer.zig +135 -68
- package/src/tigerbeetle/src/state_machine.zig +808 -14
- package/src/tigerbeetle/src/test/state_checker.zig +1 -1
- package/src/tigerbeetle/src/test/storage.zig +16 -0
- package/src/tigerbeetle/src/tigerbeetle.zig +0 -1
- package/src/tigerbeetle/src/vsr/client.zig +4 -4
- package/src/tigerbeetle/src/vsr/replica.zig +2 -2
|
@@ -14,51 +14,84 @@ pub fn RingBuffer(comptime T: type, comptime size: usize) type {
|
|
|
14
14
|
/// The number of items in the buffer.
|
|
15
15
|
count: usize = 0,
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
self.buffer[(self.index + self.count) % self.buffer.len] = item;
|
|
22
|
-
self.count += 1;
|
|
17
|
+
// TODO add doc comments to these functions:
|
|
18
|
+
pub inline fn head(self: Self) ?T {
|
|
19
|
+
if (self.empty()) return null;
|
|
20
|
+
return self.buffer[self.index];
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return
|
|
23
|
+
pub inline fn head_ptr(self: *Self) ?*T {
|
|
24
|
+
if (self.empty()) return null;
|
|
25
|
+
return &self.buffer[self.index];
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
pub fn peek_ptr(self: *Self) ?*T {
|
|
28
|
+
pub inline fn tail(self: Self) ?T {
|
|
32
29
|
if (self.empty()) return null;
|
|
33
|
-
return
|
|
30
|
+
return self.buffer[(self.index + self.count - 1) % self.buffer.len];
|
|
34
31
|
}
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
pub fn pop(self: *Self) ?T {
|
|
33
|
+
pub inline fn tail_ptr(self: *Self) ?*T {
|
|
38
34
|
if (self.empty()) return null;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
return &self.buffer[(self.index + self.count - 1) % self.buffer.len];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
pub inline fn next_tail(self: Self) ?T {
|
|
39
|
+
if (self.full()) return null;
|
|
40
|
+
return self.buffer[(self.index + self.count) % self.buffer.len];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
pub inline fn next_tail_ptr(self: *Self) ?*T {
|
|
44
|
+
if (self.full()) return null;
|
|
45
|
+
return &self.buffer[(self.index + self.count) % self.buffer.len];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
pub inline fn advance_head(self: *Self) void {
|
|
49
|
+
self.index += 1;
|
|
50
|
+
self.index %= self.buffer.len;
|
|
51
|
+
self.count -= 1;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
pub inline fn advance_tail(self: *Self) void {
|
|
55
|
+
assert(self.count < self.buffer.len);
|
|
56
|
+
self.count += 1;
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
/// Returns whether the ring buffer is completely full.
|
|
47
|
-
pub fn full(self:
|
|
60
|
+
pub inline fn full(self: Self) bool {
|
|
48
61
|
return self.count == self.buffer.len;
|
|
49
62
|
}
|
|
50
63
|
|
|
51
64
|
/// Returns whether the ring buffer is completely empty.
|
|
52
|
-
pub fn empty(self:
|
|
65
|
+
pub inline fn empty(self: Self) bool {
|
|
53
66
|
return self.count == 0;
|
|
54
67
|
}
|
|
55
68
|
|
|
69
|
+
// Higher level, less error-prone wrappers:
|
|
70
|
+
|
|
71
|
+
/// Add an element to the RingBuffer. Returns an error if the buffer
|
|
72
|
+
/// is already full and the element could not be added.
|
|
73
|
+
pub fn push(self: *Self, item: T) error{NoSpaceLeft}!void {
|
|
74
|
+
const ptr = self.next_tail_ptr() orelse return error.NoSpaceLeft;
|
|
75
|
+
ptr.* = item;
|
|
76
|
+
self.advance_tail();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// Remove and return the next item, if any.
|
|
80
|
+
pub fn pop(self: *Self) ?T {
|
|
81
|
+
const result = self.head() orelse return null;
|
|
82
|
+
self.advance_head();
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
|
|
56
86
|
pub const Iterator = struct {
|
|
57
87
|
ring: *Self,
|
|
58
88
|
count: usize = 0,
|
|
59
89
|
|
|
60
90
|
pub fn next(it: *Iterator) ?T {
|
|
61
|
-
|
|
91
|
+
assert(it.count <= it.ring.count);
|
|
92
|
+
if (it.count == it.ring.count) return null;
|
|
93
|
+
defer it.count += 1;
|
|
94
|
+
return it.ring.buffer[(it.ring.index + it.count) % it.ring.buffer.len];
|
|
62
95
|
}
|
|
63
96
|
|
|
64
97
|
pub fn next_ptr(it: *Iterator) ?*T {
|
|
@@ -79,43 +112,6 @@ pub fn RingBuffer(comptime T: type, comptime size: usize) type {
|
|
|
79
112
|
|
|
80
113
|
const testing = std.testing;
|
|
81
114
|
|
|
82
|
-
test "push/peek/pop/full/empty" {
|
|
83
|
-
var fifo = RingBuffer(u32, 3){};
|
|
84
|
-
|
|
85
|
-
try testing.expect(!fifo.full());
|
|
86
|
-
try testing.expect(fifo.empty());
|
|
87
|
-
|
|
88
|
-
try fifo.push(1);
|
|
89
|
-
try testing.expectEqual(@as(?u32, 1), fifo.peek());
|
|
90
|
-
|
|
91
|
-
try testing.expect(!fifo.full());
|
|
92
|
-
try testing.expect(!fifo.empty());
|
|
93
|
-
|
|
94
|
-
try fifo.push(2);
|
|
95
|
-
try testing.expectEqual(@as(?u32, 1), fifo.peek());
|
|
96
|
-
|
|
97
|
-
try fifo.push(3);
|
|
98
|
-
try testing.expectError(error.NoSpaceLeft, fifo.push(4));
|
|
99
|
-
|
|
100
|
-
try testing.expect(fifo.full());
|
|
101
|
-
try testing.expect(!fifo.empty());
|
|
102
|
-
|
|
103
|
-
try testing.expectEqual(@as(?u32, 1), fifo.peek());
|
|
104
|
-
try testing.expectEqual(@as(?u32, 1), fifo.pop());
|
|
105
|
-
|
|
106
|
-
try testing.expect(!fifo.full());
|
|
107
|
-
try testing.expect(!fifo.empty());
|
|
108
|
-
|
|
109
|
-
fifo.peek_ptr().?.* += 1000;
|
|
110
|
-
|
|
111
|
-
try testing.expectEqual(@as(?u32, 1002), fifo.pop());
|
|
112
|
-
try testing.expectEqual(@as(?u32, 3), fifo.pop());
|
|
113
|
-
try testing.expectEqual(@as(?u32, null), fifo.pop());
|
|
114
|
-
|
|
115
|
-
try testing.expect(!fifo.full());
|
|
116
|
-
try testing.expect(fifo.empty());
|
|
117
|
-
}
|
|
118
|
-
|
|
119
115
|
fn test_iterator(comptime T: type, ring: *T, values: []const u32) !void {
|
|
120
116
|
const ring_index = ring.index;
|
|
121
117
|
|
|
@@ -133,22 +129,41 @@ fn test_iterator(comptime T: type, ring: *T, values: []const u32) !void {
|
|
|
133
129
|
try testing.expectEqual(ring_index, ring.index);
|
|
134
130
|
}
|
|
135
131
|
|
|
136
|
-
test "
|
|
132
|
+
test "RingBuffer: low level interface" {
|
|
137
133
|
const Ring = RingBuffer(u32, 2);
|
|
138
134
|
|
|
139
135
|
var ring = Ring{};
|
|
140
136
|
try test_iterator(Ring, &ring, &[_]u32{});
|
|
141
137
|
|
|
142
|
-
try ring.
|
|
138
|
+
try testing.expectEqual(@as(?u32, null), ring.head());
|
|
139
|
+
try testing.expectEqual(@as(?*u32, null), ring.head_ptr());
|
|
140
|
+
try testing.expectEqual(@as(?u32, null), ring.tail());
|
|
141
|
+
try testing.expectEqual(@as(?*u32, null), ring.tail_ptr());
|
|
142
|
+
|
|
143
|
+
ring.next_tail_ptr().?.* = 0;
|
|
144
|
+
ring.advance_tail();
|
|
145
|
+
try testing.expectEqual(@as(?u32, 0), ring.tail());
|
|
146
|
+
try testing.expectEqual(@as(u32, 0), ring.tail_ptr().?.*);
|
|
143
147
|
try test_iterator(Ring, &ring, &[_]u32{0});
|
|
144
148
|
|
|
145
|
-
|
|
149
|
+
ring.next_tail_ptr().?.* = 1;
|
|
150
|
+
ring.advance_tail();
|
|
151
|
+
try testing.expectEqual(@as(?u32, 1), ring.tail());
|
|
152
|
+
try testing.expectEqual(@as(u32, 1), ring.tail_ptr().?.*);
|
|
146
153
|
try test_iterator(Ring, &ring, &[_]u32{ 0, 1 });
|
|
147
154
|
|
|
148
|
-
try testing.expectEqual(@as(?u32,
|
|
155
|
+
try testing.expectEqual(@as(?u32, null), ring.next_tail());
|
|
156
|
+
try testing.expectEqual(@as(?*u32, null), ring.next_tail_ptr());
|
|
157
|
+
|
|
158
|
+
try testing.expectEqual(@as(?u32, 0), ring.head());
|
|
159
|
+
try testing.expectEqual(@as(u32, 0), ring.head_ptr().?.*);
|
|
160
|
+
ring.advance_head();
|
|
149
161
|
try test_iterator(Ring, &ring, &[_]u32{1});
|
|
150
162
|
|
|
151
|
-
|
|
163
|
+
ring.next_tail_ptr().?.* = 2;
|
|
164
|
+
ring.advance_tail();
|
|
165
|
+
try testing.expectEqual(@as(?u32, 2), ring.tail());
|
|
166
|
+
try testing.expectEqual(@as(u32, 2), ring.tail_ptr().?.*);
|
|
152
167
|
try test_iterator(Ring, &ring, &[_]u32{ 1, 2 });
|
|
153
168
|
|
|
154
169
|
var iterator = ring.iterator();
|
|
@@ -156,15 +171,67 @@ test "iterator" {
|
|
|
156
171
|
item_ptr.* += 1000;
|
|
157
172
|
}
|
|
158
173
|
|
|
159
|
-
try testing.expectEqual(@as(?u32, 1001), ring.
|
|
174
|
+
try testing.expectEqual(@as(?u32, 1001), ring.head());
|
|
175
|
+
try testing.expectEqual(@as(u32, 1001), ring.head_ptr().?.*);
|
|
176
|
+
ring.advance_head();
|
|
160
177
|
try test_iterator(Ring, &ring, &[_]u32{1002});
|
|
161
178
|
|
|
162
|
-
|
|
179
|
+
ring.next_tail_ptr().?.* = 3;
|
|
180
|
+
ring.advance_tail();
|
|
181
|
+
try testing.expectEqual(@as(?u32, 3), ring.tail());
|
|
182
|
+
try testing.expectEqual(@as(u32, 3), ring.tail_ptr().?.*);
|
|
163
183
|
try test_iterator(Ring, &ring, &[_]u32{ 1002, 3 });
|
|
164
184
|
|
|
165
|
-
try testing.expectEqual(@as(?u32, 1002), ring.
|
|
185
|
+
try testing.expectEqual(@as(?u32, 1002), ring.head());
|
|
186
|
+
try testing.expectEqual(@as(u32, 1002), ring.head_ptr().?.*);
|
|
187
|
+
ring.advance_head();
|
|
166
188
|
try test_iterator(Ring, &ring, &[_]u32{3});
|
|
167
189
|
|
|
168
|
-
try testing.expectEqual(@as(?u32, 3), ring.
|
|
190
|
+
try testing.expectEqual(@as(?u32, 3), ring.head());
|
|
191
|
+
try testing.expectEqual(@as(u32, 3), ring.head_ptr().?.*);
|
|
192
|
+
ring.advance_head();
|
|
169
193
|
try test_iterator(Ring, &ring, &[_]u32{});
|
|
194
|
+
|
|
195
|
+
try testing.expectEqual(@as(?u32, null), ring.head());
|
|
196
|
+
try testing.expectEqual(@as(?*u32, null), ring.head_ptr());
|
|
197
|
+
try testing.expectEqual(@as(?u32, null), ring.tail());
|
|
198
|
+
try testing.expectEqual(@as(?*u32, null), ring.tail_ptr());
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
test "RingBuffer: push/pop high level interface" {
|
|
202
|
+
var fifo = RingBuffer(u32, 3){};
|
|
203
|
+
|
|
204
|
+
try testing.expect(!fifo.full());
|
|
205
|
+
try testing.expect(fifo.empty());
|
|
206
|
+
|
|
207
|
+
try fifo.push(1);
|
|
208
|
+
try testing.expectEqual(@as(?u32, 1), fifo.head());
|
|
209
|
+
|
|
210
|
+
try testing.expect(!fifo.full());
|
|
211
|
+
try testing.expect(!fifo.empty());
|
|
212
|
+
|
|
213
|
+
try fifo.push(2);
|
|
214
|
+
try testing.expectEqual(@as(?u32, 1), fifo.head());
|
|
215
|
+
|
|
216
|
+
try fifo.push(3);
|
|
217
|
+
try testing.expectError(error.NoSpaceLeft, fifo.push(4));
|
|
218
|
+
|
|
219
|
+
try testing.expect(fifo.full());
|
|
220
|
+
try testing.expect(!fifo.empty());
|
|
221
|
+
|
|
222
|
+
try testing.expectEqual(@as(?u32, 1), fifo.head());
|
|
223
|
+
try testing.expectEqual(@as(?u32, 1), fifo.pop());
|
|
224
|
+
|
|
225
|
+
try testing.expect(!fifo.full());
|
|
226
|
+
try testing.expect(!fifo.empty());
|
|
227
|
+
|
|
228
|
+
try fifo.push(4);
|
|
229
|
+
|
|
230
|
+
try testing.expectEqual(@as(?u32, 2), fifo.pop());
|
|
231
|
+
try testing.expectEqual(@as(?u32, 3), fifo.pop());
|
|
232
|
+
try testing.expectEqual(@as(?u32, 4), fifo.pop());
|
|
233
|
+
try testing.expectEqual(@as(?u32, null), fifo.pop());
|
|
234
|
+
|
|
235
|
+
try testing.expect(!fifo.full());
|
|
236
|
+
try testing.expect(fifo.empty());
|
|
170
237
|
}
|