tigerbeetle-node 0.11.12 → 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.
Files changed (143) hide show
  1. package/README.md +212 -196
  2. package/dist/bin/aarch64-linux-gnu/client.node +0 -0
  3. package/dist/bin/aarch64-linux-musl/client.node +0 -0
  4. package/dist/bin/aarch64-macos/client.node +0 -0
  5. package/dist/bin/x86_64-linux-gnu/client.node +0 -0
  6. package/dist/bin/x86_64-linux-musl/client.node +0 -0
  7. package/dist/bin/x86_64-macos/client.node +0 -0
  8. package/dist/index.js +33 -1
  9. package/dist/index.js.map +1 -1
  10. package/package-lock.json +66 -0
  11. package/package.json +8 -17
  12. package/src/index.ts +56 -1
  13. package/src/node.zig +10 -9
  14. package/dist/.client.node.sha256 +0 -1
  15. package/scripts/build_lib.sh +0 -61
  16. package/scripts/download_node_headers.sh +0 -32
  17. package/src/tigerbeetle/scripts/benchmark.bat +0 -48
  18. package/src/tigerbeetle/scripts/benchmark.sh +0 -66
  19. package/src/tigerbeetle/scripts/confirm_image.sh +0 -44
  20. package/src/tigerbeetle/scripts/fuzz_loop.sh +0 -15
  21. package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +0 -7
  22. package/src/tigerbeetle/scripts/install.bat +0 -7
  23. package/src/tigerbeetle/scripts/install.sh +0 -21
  24. package/src/tigerbeetle/scripts/install_zig.bat +0 -113
  25. package/src/tigerbeetle/scripts/install_zig.sh +0 -90
  26. package/src/tigerbeetle/scripts/lint.zig +0 -199
  27. package/src/tigerbeetle/scripts/pre-commit.sh +0 -9
  28. package/src/tigerbeetle/scripts/scripts/benchmark.bat +0 -48
  29. package/src/tigerbeetle/scripts/scripts/benchmark.sh +0 -66
  30. package/src/tigerbeetle/scripts/scripts/confirm_image.sh +0 -44
  31. package/src/tigerbeetle/scripts/scripts/fuzz_loop.sh +0 -15
  32. package/src/tigerbeetle/scripts/scripts/fuzz_unique_errors.sh +0 -7
  33. package/src/tigerbeetle/scripts/scripts/install.bat +0 -7
  34. package/src/tigerbeetle/scripts/scripts/install.sh +0 -21
  35. package/src/tigerbeetle/scripts/scripts/install_zig.bat +0 -113
  36. package/src/tigerbeetle/scripts/scripts/install_zig.sh +0 -90
  37. package/src/tigerbeetle/scripts/scripts/lint.zig +0 -199
  38. package/src/tigerbeetle/scripts/scripts/pre-commit.sh +0 -9
  39. package/src/tigerbeetle/scripts/scripts/shellcheck.sh +0 -5
  40. package/src/tigerbeetle/scripts/scripts/tests_on_alpine.sh +0 -10
  41. package/src/tigerbeetle/scripts/scripts/tests_on_ubuntu.sh +0 -14
  42. package/src/tigerbeetle/scripts/scripts/upgrade_ubuntu_kernel.sh +0 -48
  43. package/src/tigerbeetle/scripts/scripts/validate_docs.sh +0 -23
  44. package/src/tigerbeetle/scripts/scripts/vr_state_enumerate +0 -46
  45. package/src/tigerbeetle/scripts/shellcheck.sh +0 -5
  46. package/src/tigerbeetle/scripts/tests_on_alpine.sh +0 -10
  47. package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +0 -14
  48. package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +0 -48
  49. package/src/tigerbeetle/scripts/validate_docs.sh +0 -23
  50. package/src/tigerbeetle/scripts/vr_state_enumerate +0 -46
  51. package/src/tigerbeetle/src/benchmark.zig +0 -314
  52. package/src/tigerbeetle/src/config.zig +0 -234
  53. package/src/tigerbeetle/src/constants.zig +0 -436
  54. package/src/tigerbeetle/src/ewah.zig +0 -286
  55. package/src/tigerbeetle/src/ewah_benchmark.zig +0 -120
  56. package/src/tigerbeetle/src/ewah_fuzz.zig +0 -130
  57. package/src/tigerbeetle/src/fifo.zig +0 -120
  58. package/src/tigerbeetle/src/io/benchmark.zig +0 -213
  59. package/src/tigerbeetle/src/io/darwin.zig +0 -814
  60. package/src/tigerbeetle/src/io/linux.zig +0 -1062
  61. package/src/tigerbeetle/src/io/test.zig +0 -643
  62. package/src/tigerbeetle/src/io/windows.zig +0 -1183
  63. package/src/tigerbeetle/src/io.zig +0 -34
  64. package/src/tigerbeetle/src/iops.zig +0 -107
  65. package/src/tigerbeetle/src/lsm/README.md +0 -308
  66. package/src/tigerbeetle/src/lsm/binary_search.zig +0 -341
  67. package/src/tigerbeetle/src/lsm/bloom_filter.zig +0 -125
  68. package/src/tigerbeetle/src/lsm/compaction.zig +0 -603
  69. package/src/tigerbeetle/src/lsm/composite_key.zig +0 -77
  70. package/src/tigerbeetle/src/lsm/direction.zig +0 -11
  71. package/src/tigerbeetle/src/lsm/eytzinger.zig +0 -587
  72. package/src/tigerbeetle/src/lsm/eytzinger_benchmark.zig +0 -330
  73. package/src/tigerbeetle/src/lsm/forest.zig +0 -204
  74. package/src/tigerbeetle/src/lsm/forest_fuzz.zig +0 -401
  75. package/src/tigerbeetle/src/lsm/grid.zig +0 -573
  76. package/src/tigerbeetle/src/lsm/groove.zig +0 -972
  77. package/src/tigerbeetle/src/lsm/k_way_merge.zig +0 -474
  78. package/src/tigerbeetle/src/lsm/level_iterator.zig +0 -332
  79. package/src/tigerbeetle/src/lsm/manifest.zig +0 -617
  80. package/src/tigerbeetle/src/lsm/manifest_level.zig +0 -877
  81. package/src/tigerbeetle/src/lsm/manifest_log.zig +0 -789
  82. package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +0 -691
  83. package/src/tigerbeetle/src/lsm/merge_iterator.zig +0 -106
  84. package/src/tigerbeetle/src/lsm/node_pool.zig +0 -235
  85. package/src/tigerbeetle/src/lsm/posted_groove.zig +0 -378
  86. package/src/tigerbeetle/src/lsm/segmented_array.zig +0 -1328
  87. package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +0 -148
  88. package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +0 -9
  89. package/src/tigerbeetle/src/lsm/set_associative_cache.zig +0 -850
  90. package/src/tigerbeetle/src/lsm/table.zig +0 -1031
  91. package/src/tigerbeetle/src/lsm/table_immutable.zig +0 -203
  92. package/src/tigerbeetle/src/lsm/table_iterator.zig +0 -340
  93. package/src/tigerbeetle/src/lsm/table_mutable.zig +0 -220
  94. package/src/tigerbeetle/src/lsm/test.zig +0 -438
  95. package/src/tigerbeetle/src/lsm/tree.zig +0 -1193
  96. package/src/tigerbeetle/src/lsm/tree_fuzz.zig +0 -474
  97. package/src/tigerbeetle/src/message_bus.zig +0 -1012
  98. package/src/tigerbeetle/src/message_pool.zig +0 -156
  99. package/src/tigerbeetle/src/ring_buffer.zig +0 -399
  100. package/src/tigerbeetle/src/simulator.zig +0 -569
  101. package/src/tigerbeetle/src/state_machine/auditor.zig +0 -577
  102. package/src/tigerbeetle/src/state_machine/workload.zig +0 -883
  103. package/src/tigerbeetle/src/state_machine.zig +0 -1881
  104. package/src/tigerbeetle/src/static_allocator.zig +0 -65
  105. package/src/tigerbeetle/src/stdx.zig +0 -162
  106. package/src/tigerbeetle/src/storage.zig +0 -393
  107. package/src/tigerbeetle/src/testing/cluster/message_bus.zig +0 -82
  108. package/src/tigerbeetle/src/testing/cluster/network.zig +0 -237
  109. package/src/tigerbeetle/src/testing/cluster/state_checker.zig +0 -169
  110. package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +0 -202
  111. package/src/tigerbeetle/src/testing/cluster.zig +0 -443
  112. package/src/tigerbeetle/src/testing/fuzz.zig +0 -140
  113. package/src/tigerbeetle/src/testing/hash_log.zig +0 -66
  114. package/src/tigerbeetle/src/testing/id.zig +0 -99
  115. package/src/tigerbeetle/src/testing/packet_simulator.zig +0 -364
  116. package/src/tigerbeetle/src/testing/priority_queue.zig +0 -645
  117. package/src/tigerbeetle/src/testing/reply_sequence.zig +0 -139
  118. package/src/tigerbeetle/src/testing/state_machine.zig +0 -249
  119. package/src/tigerbeetle/src/testing/storage.zig +0 -757
  120. package/src/tigerbeetle/src/testing/table.zig +0 -247
  121. package/src/tigerbeetle/src/testing/time.zig +0 -84
  122. package/src/tigerbeetle/src/tigerbeetle.zig +0 -227
  123. package/src/tigerbeetle/src/time.zig +0 -112
  124. package/src/tigerbeetle/src/tracer.zig +0 -529
  125. package/src/tigerbeetle/src/unit_tests.zig +0 -42
  126. package/src/tigerbeetle/src/vopr.zig +0 -495
  127. package/src/tigerbeetle/src/vsr/README.md +0 -209
  128. package/src/tigerbeetle/src/vsr/client.zig +0 -544
  129. package/src/tigerbeetle/src/vsr/clock.zig +0 -853
  130. package/src/tigerbeetle/src/vsr/journal.zig +0 -2413
  131. package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +0 -111
  132. package/src/tigerbeetle/src/vsr/marzullo.zig +0 -309
  133. package/src/tigerbeetle/src/vsr/replica.zig +0 -6381
  134. package/src/tigerbeetle/src/vsr/replica_format.zig +0 -219
  135. package/src/tigerbeetle/src/vsr/superblock.zig +0 -1631
  136. package/src/tigerbeetle/src/vsr/superblock_client_table.zig +0 -256
  137. package/src/tigerbeetle/src/vsr/superblock_free_set.zig +0 -929
  138. package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +0 -334
  139. package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +0 -390
  140. package/src/tigerbeetle/src/vsr/superblock_manifest.zig +0 -615
  141. package/src/tigerbeetle/src/vsr/superblock_quorums.zig +0 -394
  142. package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +0 -314
  143. package/src/tigerbeetle/src/vsr.zig +0 -1352
@@ -1,247 +0,0 @@
1
- const std = @import("std");
2
- const assert = std.debug.assert;
3
-
4
- /// Parse a "table" of data with the specified schema.
5
- /// See test cases for example usage.
6
- // TODO(Zig): Change this to a a purely comptime function returning a slice
7
- // once Zig's "runtime value cannot be passed to comptime arg" bugs are fixed.
8
- pub fn parse(comptime Row: type, comptime table_string: []const u8) std.BoundedArray(Row, 128) {
9
- var rows = std.BoundedArray(Row, 128).init(0) catch unreachable;
10
- var row_strings = std.mem.tokenize(u8, table_string, "\n");
11
- while (row_strings.next()) |row_string| {
12
- // Ignore blank line.
13
- if (row_string.len == 0) continue;
14
-
15
- var columns = std.mem.tokenize(u8, row_string, " ");
16
- const row = parse_data(Row, &columns);
17
- rows.appendAssumeCapacity(row);
18
-
19
- // Ignore trailing line comment.
20
- if (columns.next()) |last| assert(std.mem.eql(u8, last, "//"));
21
- }
22
- return rows;
23
- }
24
-
25
- fn parse_data(comptime Data: type, tokens: *std.mem.TokenIterator(u8)) Data {
26
- return switch (@typeInfo(Data)) {
27
- .Optional => |info| parse_data(info.child, tokens),
28
- .Enum => field(Data, tokens.next().?),
29
- .Void => assert(tokens.next() == null),
30
- .Bool => {
31
- const token = tokens.next().?;
32
- inline for (.{ "0", "false", "F" }) |t| {
33
- if (std.mem.eql(u8, token, t)) return false;
34
- }
35
- inline for (.{ "1", "true", "T" }) |t| {
36
- if (std.mem.eql(u8, token, t)) return true;
37
- }
38
- std.debug.panic("Unknown boolean: {s}", .{token});
39
- },
40
- .Int => |info| {
41
- const max = std.math.maxInt(Data);
42
- const token = tokens.next().?;
43
- // If the first character is a letter ("a-zA-Z"), ignore it. (For example, "A1" → 1).
44
- // This serves as a comment, to help visually disambiguate sequential integer columns.
45
- const offset: usize = if (std.ascii.isAlpha(token[0])) 1 else 0;
46
- // Negative unsigned values are computed relative to the maxInt.
47
- if (info.signedness == .unsigned and token[offset] == '-') {
48
- return max - (std.fmt.parseInt(Data, token[offset + 1 ..], 10) catch unreachable);
49
- }
50
- return std.fmt.parseInt(Data, token[offset..], 10) catch unreachable;
51
- },
52
- .Struct => {
53
- var data: Data = undefined;
54
- inline for (std.meta.fields(Data)) |value_field| {
55
- // The repeated else branch seems to be necessary to keep Zig from complaining:
56
- // control flow attempts to use compile-time variable at runtime
57
- if (value_field.default_value != null) {
58
- if (eat(tokens, "_")) {
59
- @field(data, value_field.name) = value_field.default_value.?;
60
- } else {
61
- @field(data, value_field.name) = parse_data(value_field.field_type, tokens);
62
- }
63
- } else {
64
- @field(data, value_field.name) = parse_data(value_field.field_type, tokens);
65
- }
66
- }
67
- return data;
68
- },
69
- .Array => |info| {
70
- var values: Data = undefined;
71
- for (values[0..]) |*value| {
72
- value.* = parse_data(info.child, tokens);
73
- }
74
- return values;
75
- },
76
- .Union => |info| {
77
- const variant_string = tokens.next().?;
78
- inline for (info.fields) |variant_field| {
79
- if (std.mem.eql(u8, variant_field.name, variant_string)) {
80
- return @unionInit(
81
- Data,
82
- variant_field.name,
83
- parse_data(variant_field.field_type, tokens),
84
- );
85
- }
86
- }
87
- std.debug.panic("Unknown union variant: {s}", .{variant_string});
88
- },
89
- else => @compileError("Unimplemented column type: " ++ @typeName(Data)),
90
- };
91
- }
92
-
93
- fn eat(tokens: *std.mem.TokenIterator(u8), token: []const u8) bool {
94
- var index_before = tokens.index;
95
- if (std.mem.eql(u8, tokens.next().?, token)) return true;
96
- tokens.index = index_before;
97
- return false;
98
- }
99
-
100
- /// TODO This function is a workaround for a comptime bug:
101
- /// error: unable to evaluate constant expression
102
- /// .Enum => @field(Column, column_string),
103
- fn field(comptime Enum: type, name: []const u8) Enum {
104
- inline for (std.meta.fields(Enum)) |variant| {
105
- if (std.mem.eql(u8, variant.name, name)) {
106
- return @field(Enum, variant.name);
107
- }
108
- }
109
- std.debug.panic("Unkown field name={s} for type={}", .{ name, Enum });
110
- }
111
-
112
- fn test_parse(
113
- comptime Row: type,
114
- comptime rows_expect: []const Row,
115
- comptime string: []const u8,
116
- ) !void {
117
- const rows_actual = parse(Row, string).constSlice();
118
- try std.testing.expectEqual(rows_expect.len, rows_actual.len);
119
-
120
- for (rows_expect) |row, i| {
121
- try std.testing.expectEqual(row, rows_actual[i]);
122
- }
123
- }
124
-
125
- test "comment" {
126
- try test_parse(struct {
127
- a: u8,
128
- }, &.{
129
- .{ .a = 1 },
130
- },
131
- \\
132
- \\ 1 // Comment
133
- \\
134
- );
135
- }
136
-
137
- test "enum" {
138
- try test_parse(enum { a, b, c }, &.{ .c, .b, .a },
139
- \\ c
140
- \\ b
141
- \\ a
142
- );
143
- }
144
-
145
- test "bool" {
146
- try test_parse(struct { i: bool }, &.{
147
- .{ .i = false },
148
- .{ .i = true },
149
- .{ .i = false },
150
- .{ .i = true },
151
- .{ .i = false },
152
- .{ .i = true },
153
- },
154
- \\ 0
155
- \\ 1
156
- \\ false
157
- \\ true
158
- \\ F
159
- \\ T
160
- );
161
- }
162
-
163
- test "int" {
164
- try test_parse(struct { i: usize }, &.{
165
- .{ .i = 1 },
166
- .{ .i = 2 },
167
- .{ .i = 3 },
168
- .{ .i = 4 },
169
- .{ .i = std.math.maxInt(usize) - 5 },
170
- .{ .i = std.math.maxInt(usize) },
171
- },
172
- \\ 1
173
- \\ 2
174
- \\ A3
175
- \\ a4
176
- // For unsigned integers, `-n` is interpreted as `maxInt(Int) - n`.
177
- \\ -5
178
- \\ -0
179
- );
180
- }
181
-
182
- test "struct" {
183
- try test_parse(struct {
184
- c1: enum { a, b, c, d },
185
- c2: u8,
186
- c3: u16 = 30,
187
- c4: ?u32 = null,
188
- c5: bool = false,
189
- }, &.{
190
- .{ .c1 = .a, .c2 = 1, .c3 = 10, .c4 = 1000, .c5 = true },
191
- .{ .c1 = .b, .c2 = 2, .c3 = 20, .c4 = null, .c5 = true },
192
- .{ .c1 = .c, .c2 = 3, .c3 = 30, .c4 = null, .c5 = false },
193
- .{ .c1 = .d, .c2 = 4, .c3 = 30, .c4 = null, .c5 = false },
194
- },
195
- \\ a 1 10 1000 1
196
- \\ b 2 20 _ T
197
- \\ c 3 _ _ F
198
- \\ d 4 _ _ _
199
- );
200
- }
201
-
202
- test "struct (nested)" {
203
- try test_parse(struct {
204
- a: u32,
205
- b: struct {
206
- b1: u8,
207
- b2: u8,
208
- },
209
- c: u32,
210
- }, &.{
211
- .{ .a = 1, .b = .{ .b1 = 2, .b2 = 3 }, .c = 4 },
212
- .{ .a = 5, .b = .{ .b1 = 6, .b2 = 7 }, .c = 8 },
213
- },
214
- \\ 1 2 3 4
215
- \\ 5 6 7 8
216
- );
217
- }
218
-
219
- test "array" {
220
- try test_parse(struct {
221
- a: u32,
222
- b: [2]u32,
223
- c: u32,
224
- }, &.{
225
- .{ .a = 1, .b = .{ 2, 3 }, .c = 4 },
226
- .{ .a = 5, .b = .{ 6, 7 }, .c = 8 },
227
- },
228
- \\ 1 2 3 4
229
- \\ 5 6 7 8
230
- );
231
- }
232
-
233
- test "union" {
234
- try test_parse(union(enum) {
235
- a: struct { b: u8, c: i8 },
236
- d: u8,
237
- e: void,
238
- }, &.{
239
- .{ .a = .{ .b = 1, .c = -2 } },
240
- .{ .d = 3 },
241
- .{ .e = {} },
242
- },
243
- \\a 1 -2
244
- \\d 3
245
- \\e
246
- );
247
- }
@@ -1,84 +0,0 @@
1
- const std = @import("std");
2
- const assert = std.debug.assert;
3
-
4
- pub const OffsetType = enum {
5
- linear,
6
- periodic,
7
- step,
8
- non_ideal,
9
- };
10
-
11
- pub const Time = struct {
12
- const Self = @This();
13
-
14
- /// The duration of a single tick in nanoseconds.
15
- resolution: u64,
16
-
17
- offset_type: OffsetType,
18
-
19
- /// Co-efficients to scale the offset according to the `offset_type`.
20
- /// Linear offset is described as A * x + B: A is the drift per tick and B the initial offset.
21
- /// Periodic is described as A * sin(x * pi / B): A controls the amplitude and B the period in
22
- /// terms of ticks.
23
- /// Step function represents a discontinuous jump in the wall-clock time. B is the period in
24
- /// which the jumps occur. A is the amplitude of the step.
25
- /// Non-ideal is similar to periodic except the phase is adjusted using a random number taken
26
- /// from a normal distribution with mean=0, stddev=10. Finally, a random offset (up to
27
- /// offset_coefficientC) is added to the result.
28
- offset_coefficient_A: i64,
29
- offset_coefficient_B: i64,
30
- offset_coefficient_C: u32 = 0,
31
-
32
- prng: std.rand.DefaultPrng = std.rand.DefaultPrng.init(0),
33
-
34
- /// The number of ticks elapsed since initialization.
35
- ticks: u64 = 0,
36
-
37
- /// The instant in time chosen as the origin of this time source.
38
- epoch: i64 = 0,
39
-
40
- pub fn monotonic(self: *Self) u64 {
41
- return self.ticks * self.resolution;
42
- }
43
-
44
- pub fn realtime(self: *Self) i64 {
45
- return self.epoch + @intCast(i64, self.monotonic()) - self.offset(self.ticks);
46
- }
47
-
48
- pub fn offset(self: *Self, ticks: u64) i64 {
49
- switch (self.offset_type) {
50
- .linear => {
51
- const drift_per_tick = self.offset_coefficient_A;
52
- return @intCast(i64, ticks) * drift_per_tick + @intCast(
53
- i64,
54
- self.offset_coefficient_B,
55
- );
56
- },
57
- .periodic => {
58
- const unscaled = std.math.sin(@intToFloat(f64, ticks) * 2 * std.math.pi /
59
- @intToFloat(f64, self.offset_coefficient_B));
60
- const scaled = @intToFloat(f64, self.offset_coefficient_A) * unscaled;
61
- return @floatToInt(i64, std.math.floor(scaled));
62
- },
63
- .step => {
64
- return if (ticks > self.offset_coefficient_B) self.offset_coefficient_A else 0;
65
- },
66
- .non_ideal => {
67
- const phase: f64 = @intToFloat(f64, ticks) * 2 * std.math.pi /
68
- (@intToFloat(f64, self.offset_coefficient_B) + self.prng.random().floatNorm(f64) * 10);
69
- const unscaled = std.math.sin(phase);
70
- const scaled = @intToFloat(f64, self.offset_coefficient_A) * unscaled;
71
- return @floatToInt(i64, std.math.floor(scaled)) +
72
- self.prng.random().intRangeAtMost(
73
- i64,
74
- -@intCast(i64, self.offset_coefficient_C),
75
- self.offset_coefficient_C,
76
- );
77
- },
78
- }
79
- }
80
-
81
- pub fn tick(self: *Self) void {
82
- self.ticks += 1;
83
- }
84
- };
@@ -1,227 +0,0 @@
1
- const std = @import("std");
2
- const builtin = @import("builtin");
3
- const assert = std.debug.assert;
4
-
5
- pub const Account = extern struct {
6
- id: u128,
7
- /// Opaque third-party identifier to link this account (many-to-one) to an external entity.
8
- user_data: u128,
9
- /// Reserved for accounting policy primitives.
10
- reserved: [48]u8,
11
- ledger: u32,
12
- /// A chart of accounts code describing the type of account (e.g. clearing, settlement).
13
- code: u16,
14
- flags: AccountFlags,
15
- debits_pending: u64,
16
- debits_posted: u64,
17
- credits_pending: u64,
18
- credits_posted: u64,
19
- timestamp: u64 = 0,
20
-
21
- comptime {
22
- assert(@sizeOf(Account) == 128);
23
- assert(@bitSizeOf(Account) == @sizeOf(Account) * 8);
24
- }
25
-
26
- pub fn debits_exceed_credits(self: *const Account, amount: u64) bool {
27
- return (self.flags.debits_must_not_exceed_credits and
28
- self.debits_pending + self.debits_posted + amount > self.credits_posted);
29
- }
30
-
31
- pub fn credits_exceed_debits(self: *const Account, amount: u64) bool {
32
- return (self.flags.credits_must_not_exceed_debits and
33
- self.credits_pending + self.credits_posted + amount > self.debits_posted);
34
- }
35
- };
36
-
37
- pub const AccountFlags = packed struct {
38
- /// When the .linked flag is specified, it links an event with the next event in the batch, to
39
- /// create a chain of events, of arbitrary length, which all succeed or fail together. The tail
40
- /// of a chain is denoted by the first event without this flag. The last event in a batch may
41
- /// therefore never have the .linked flag set as this would leave a chain open-ended. Multiple
42
- /// chains or individual events may coexist within a batch to succeed or fail independently.
43
- /// Events within a chain are executed within order, or are rolled back on error, so that the
44
- /// effect of each event in the chain is visible to the next, and so that the chain is either
45
- /// visible or invisible as a unit to subsequent events after the chain. The event that was the
46
- /// first to break the chain will have a unique error result. Other events in the chain will
47
- /// have their error result set to .linked_event_failed.
48
- linked: bool = false,
49
- debits_must_not_exceed_credits: bool = false,
50
- credits_must_not_exceed_debits: bool = false,
51
- padding: u13 = 0,
52
-
53
- comptime {
54
- assert(@sizeOf(AccountFlags) == @sizeOf(u16));
55
- }
56
- };
57
-
58
- pub const Transfer = extern struct {
59
- id: u128,
60
- debit_account_id: u128,
61
- credit_account_id: u128,
62
- /// Opaque third-party identifier to link this transfer (many-to-one) to an external entity.
63
- user_data: u128,
64
- /// Reserved for accounting policy primitives.
65
- reserved: u128,
66
- /// If this transfer will post or void a pending transfer, the id of that pending transfer.
67
- pending_id: u128,
68
- timeout: u64,
69
- ledger: u32,
70
- /// A chart of accounts code describing the reason for the transfer (e.g. deposit, settlement).
71
- code: u16,
72
- flags: TransferFlags,
73
- amount: u64,
74
- timestamp: u64 = 0,
75
-
76
- comptime {
77
- assert(@sizeOf(Transfer) == 128);
78
- assert(@bitSizeOf(Transfer) == @sizeOf(Transfer) * 8);
79
- }
80
- };
81
-
82
- pub const TransferFlags = packed struct {
83
- linked: bool = false,
84
- pending: bool = false,
85
- post_pending_transfer: bool = false,
86
- void_pending_transfer: bool = false,
87
- padding: u12 = 0,
88
-
89
- comptime {
90
- assert(@sizeOf(TransferFlags) == @sizeOf(u16));
91
- }
92
- };
93
-
94
- pub const CreateAccountResult = enum(u32) {
95
- ok,
96
- linked_event_failed,
97
- linked_event_chain_open,
98
- timestamp_must_be_zero,
99
-
100
- reserved_flag,
101
- reserved_field,
102
-
103
- id_must_not_be_zero,
104
- id_must_not_be_int_max,
105
- ledger_must_not_be_zero,
106
- code_must_not_be_zero,
107
- debits_pending_must_be_zero,
108
- debits_posted_must_be_zero,
109
- credits_pending_must_be_zero,
110
- credits_posted_must_be_zero,
111
-
112
- mutually_exclusive_flags,
113
-
114
- exists_with_different_flags,
115
- exists_with_different_user_data,
116
- exists_with_different_ledger,
117
- exists_with_different_code,
118
- exists,
119
- };
120
-
121
- pub const CreateTransferResult = enum(u32) {
122
- ok,
123
- linked_event_failed,
124
- linked_event_chain_open,
125
- timestamp_must_be_zero,
126
-
127
- reserved_flag,
128
- reserved_field,
129
-
130
- id_must_not_be_zero,
131
- id_must_not_be_int_max,
132
- debit_account_id_must_not_be_zero,
133
- debit_account_id_must_not_be_int_max,
134
- credit_account_id_must_not_be_zero,
135
- credit_account_id_must_not_be_int_max,
136
- accounts_must_be_different,
137
-
138
- pending_id_must_be_zero,
139
-
140
- ledger_must_not_be_zero,
141
- code_must_not_be_zero,
142
- amount_must_not_be_zero,
143
-
144
- debit_account_not_found,
145
- credit_account_not_found,
146
-
147
- accounts_must_have_the_same_ledger,
148
- transfer_must_have_the_same_ledger_as_accounts,
149
-
150
- exists_with_different_flags,
151
- exists_with_different_debit_account_id,
152
- exists_with_different_credit_account_id,
153
- exists_with_different_user_data,
154
- exists_with_different_pending_id,
155
- exists_with_different_timeout,
156
- exists_with_different_code,
157
- exists_with_different_amount,
158
- exists,
159
-
160
- overflows_debits_pending,
161
- overflows_credits_pending,
162
- overflows_debits_posted,
163
- overflows_credits_posted,
164
- overflows_debits,
165
- overflows_credits,
166
- overflows_timeout,
167
-
168
- exceeds_credits,
169
- exceeds_debits,
170
-
171
- cannot_post_and_void_pending_transfer,
172
- pending_transfer_cannot_post_or_void_another,
173
- timeout_reserved_for_pending_transfer,
174
-
175
- pending_id_must_not_be_zero,
176
- pending_id_must_not_be_int_max,
177
- pending_id_must_be_different,
178
-
179
- pending_transfer_not_found,
180
- pending_transfer_not_pending,
181
-
182
- pending_transfer_has_different_debit_account_id,
183
- pending_transfer_has_different_credit_account_id,
184
- pending_transfer_has_different_ledger,
185
- pending_transfer_has_different_code,
186
-
187
- exceeds_pending_transfer_amount,
188
- pending_transfer_has_different_amount,
189
-
190
- pending_transfer_already_posted,
191
- pending_transfer_already_voided,
192
-
193
- pending_transfer_expired,
194
- };
195
-
196
- pub const CreateAccountsResult = extern struct {
197
- index: u32,
198
- result: CreateAccountResult,
199
-
200
- comptime {
201
- assert(@sizeOf(CreateAccountsResult) == 8);
202
- assert(@bitSizeOf(CreateAccountsResult) == @sizeOf(CreateAccountsResult) * 8);
203
- }
204
- };
205
-
206
- pub const CreateTransfersResult = extern struct {
207
- index: u32,
208
- result: CreateTransferResult,
209
-
210
- comptime {
211
- assert(@sizeOf(CreateTransfersResult) == 8);
212
- assert(@bitSizeOf(CreateTransfersResult) == @sizeOf(CreateTransfersResult) * 8);
213
- }
214
- };
215
-
216
- comptime {
217
- const target = builtin.target;
218
-
219
- if (target.os.tag != .linux and !target.isDarwin() and target.os.tag != .windows) {
220
- @compileError("linux, windows or macos is required for io");
221
- }
222
-
223
- // We require little-endian architectures everywhere for efficient network deserialization:
224
- if (target.cpu.arch.endian() != .Little) {
225
- @compileError("big-endian systems not supported");
226
- }
227
- }
@@ -1,112 +0,0 @@
1
- const std = @import("std");
2
- const builtin = @import("builtin");
3
-
4
- const os = std.os;
5
- const assert = std.debug.assert;
6
- const is_darwin = builtin.target.os.tag.isDarwin();
7
- const is_windows = builtin.target.os.tag == .windows;
8
-
9
- pub const Time = struct {
10
- const Self = @This();
11
-
12
- /// Hardware and/or software bugs can mean that the monotonic clock may regress.
13
- /// One example (of many): https://bugzilla.redhat.com/show_bug.cgi?id=448449
14
- /// We crash the process for safety if this ever happens, to protect against infinite loops.
15
- /// It's better to crash and come back with a valid monotonic clock than get stuck forever.
16
- monotonic_guard: u64 = 0,
17
-
18
- /// A timestamp to measure elapsed time, meaningful only on the same system, not across reboots.
19
- /// Always use a monotonic timestamp if the goal is to measure elapsed time.
20
- /// This clock is not affected by discontinuous jumps in the system time, for example if the
21
- /// system administrator manually changes the clock.
22
- pub fn monotonic(self: *Self) u64 {
23
- const m = blk: {
24
- // Uses QueryPerformanceCounter() on windows due to it being the highest precision timer
25
- // available while also accounting for time spent suspended by default:
26
- // https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryunbiasedinterrupttime#remarks
27
- if (is_windows) {
28
- // QPF need not be globally cached either as it ends up being a load from read-only
29
- // memory mapped to all processed by the kernel called KUSER_SHARED_DATA (See "QpcFrequency")
30
- // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-kuser_shared_data
31
- // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm
32
- const qpc = os.windows.QueryPerformanceCounter();
33
- const qpf = os.windows.QueryPerformanceFrequency();
34
-
35
- // 10Mhz (1 qpc tick every 100ns) is a common QPF on modern systems.
36
- // We can optimize towards this by converting to ns via a single multiply.
37
- // https://github.com/microsoft/STL/blob/785143a0c73f030238ef618890fd4d6ae2b3a3a0/stl/inc/chrono#L694-L701
38
- const common_qpf = 10_000_000;
39
- if (qpf == common_qpf) break :blk qpc * (std.time.ns_per_s / common_qpf);
40
-
41
- // Convert qpc to nanos using fixed point to avoid expensive extra divs and overflow.
42
- const scale = (std.time.ns_per_s << 32) / qpf;
43
- break :blk @truncate(u64, (@as(u96, qpc) * scale) >> 32);
44
- }
45
-
46
- // Uses mach_continuous_time() instead of mach_absolute_time() as it counts while suspended.
47
- // https://developer.apple.com/documentation/kernel/1646199-mach_continuous_time
48
- // https://opensource.apple.com/source/Libc/Libc-1158.1.2/gen/clock_gettime.c.auto.html
49
- if (is_darwin) {
50
- const darwin = struct {
51
- const mach_timebase_info_t = os.darwin.mach_timebase_info_data;
52
- extern "c" fn mach_timebase_info(info: *mach_timebase_info_t) os.darwin.kern_return_t;
53
- extern "c" fn mach_continuous_time() u64;
54
- };
55
-
56
- // mach_timebase_info() called through libc already does global caching for us
57
- // https://opensource.apple.com/source/xnu/xnu-7195.81.3/libsyscall/wrappers/mach_timebase_info.c.auto.html
58
- var info: darwin.mach_timebase_info_t = undefined;
59
- if (darwin.mach_timebase_info(&info) != 0) @panic("mach_timebase_info() failed");
60
-
61
- const now = darwin.mach_continuous_time();
62
- return (now * info.numer) / info.denom;
63
- }
64
-
65
- // The true monotonic clock on Linux is not in fact CLOCK_MONOTONIC:
66
- // CLOCK_MONOTONIC excludes elapsed time while the system is suspended (e.g. VM migration).
67
- // CLOCK_BOOTTIME is the same as CLOCK_MONOTONIC but includes elapsed time during a suspend.
68
- // For more detail and why CLOCK_MONOTONIC_RAW is even worse than CLOCK_MONOTONIC,
69
- // see https://github.com/ziglang/zig/pull/933#discussion_r656021295.
70
- var ts: os.timespec = undefined;
71
- os.clock_gettime(os.CLOCK.BOOTTIME, &ts) catch @panic("CLOCK_BOOTTIME required");
72
- break :blk @intCast(u64, ts.tv_sec) * std.time.ns_per_s + @intCast(u64, ts.tv_nsec);
73
- };
74
-
75
- // "Oops!...I Did It Again"
76
- if (m < self.monotonic_guard) @panic("a hardware/kernel bug regressed the monotonic clock");
77
- self.monotonic_guard = m;
78
- return m;
79
- }
80
-
81
- /// A timestamp to measure real (i.e. wall clock) time, meaningful across systems, and reboots.
82
- /// This clock is affected by discontinuous jumps in the system time.
83
- pub fn realtime(_: *Self) i64 {
84
- if (is_windows) {
85
- const kernel32 = struct {
86
- extern "kernel32" fn GetSystemTimePreciseAsFileTime(
87
- lpFileTime: *os.windows.FILETIME,
88
- ) callconv(os.windows.WINAPI) void;
89
- };
90
-
91
- var ft: os.windows.FILETIME = undefined;
92
- kernel32.GetSystemTimePreciseAsFileTime(&ft);
93
- const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
94
-
95
- // FileTime is in units of 100 nanoseconds
96
- // and uses the NTFS/Windows epoch of 1601-01-01 instead of Unix Epoch 1970-01-01.
97
- const epoch_adjust = std.time.epoch.windows * (std.time.ns_per_s / 100);
98
- return (@bitCast(i64, ft64) + epoch_adjust) * 100;
99
- }
100
-
101
- if (is_darwin) {
102
- // macos has supported clock_gettime() since 10.12:
103
- // https://opensource.apple.com/source/Libc/Libc-1158.1.2/gen/clock_gettime.3.auto.html
104
- }
105
-
106
- var ts: os.timespec = undefined;
107
- os.clock_gettime(os.CLOCK.REALTIME, &ts) catch unreachable;
108
- return @as(i64, ts.tv_sec) * std.time.ns_per_s + ts.tv_nsec;
109
- }
110
-
111
- pub fn tick(_: *Self) void {}
112
- };