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,643 +0,0 @@
1
- const std = @import("std");
2
- const builtin = @import("builtin");
3
- const os = std.os;
4
- const testing = std.testing;
5
- const assert = std.debug.assert;
6
-
7
- const Time = @import("../time.zig").Time;
8
- const IO = @import("../io.zig").IO;
9
-
10
- test "write/read/close" {
11
- try struct {
12
- const Context = @This();
13
-
14
- io: IO,
15
- done: bool = false,
16
- fd: os.fd_t,
17
-
18
- write_buf: [20]u8 = [_]u8{97} ** 20,
19
- read_buf: [20]u8 = [_]u8{98} ** 20,
20
-
21
- written: usize = 0,
22
- read: usize = 0,
23
-
24
- fn run_test() !void {
25
- const path = "test_io_write_read_close";
26
- const file = try std.fs.cwd().createFile(path, .{ .read = true, .truncate = true });
27
- defer std.fs.cwd().deleteFile(path) catch {};
28
-
29
- var self: Context = .{
30
- .io = try IO.init(32, 0),
31
- .fd = file.handle,
32
- };
33
- defer self.io.deinit();
34
-
35
- var completion: IO.Completion = undefined;
36
-
37
- self.io.write(
38
- *Context,
39
- &self,
40
- write_callback,
41
- &completion,
42
- self.fd,
43
- &self.write_buf,
44
- 10,
45
- );
46
- while (!self.done) try self.io.tick();
47
-
48
- try testing.expectEqual(self.write_buf.len, self.written);
49
- try testing.expectEqual(self.read_buf.len, self.read);
50
- try testing.expectEqualSlices(u8, &self.write_buf, &self.read_buf);
51
- }
52
-
53
- fn write_callback(
54
- self: *Context,
55
- completion: *IO.Completion,
56
- result: IO.WriteError!usize,
57
- ) void {
58
- self.written = result catch @panic("write error");
59
- self.io.read(*Context, self, read_callback, completion, self.fd, &self.read_buf, 10);
60
- }
61
-
62
- fn read_callback(
63
- self: *Context,
64
- completion: *IO.Completion,
65
- result: IO.ReadError!usize,
66
- ) void {
67
- self.read = result catch @panic("read error");
68
- self.io.close(*Context, self, close_callback, completion, self.fd);
69
- }
70
-
71
- fn close_callback(
72
- self: *Context,
73
- completion: *IO.Completion,
74
- result: IO.CloseError!void,
75
- ) void {
76
- _ = completion;
77
- _ = result catch @panic("close error");
78
-
79
- self.done = true;
80
- }
81
- }.run_test();
82
- }
83
-
84
- test "accept/connect/send/receive" {
85
- try struct {
86
- const Context = @This();
87
-
88
- io: *IO,
89
- done: bool = false,
90
- server: os.socket_t,
91
- client: os.socket_t,
92
-
93
- accepted_sock: os.socket_t = undefined,
94
-
95
- send_buf: [10]u8 = [_]u8{ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 },
96
- recv_buf: [5]u8 = [_]u8{ 0, 1, 0, 1, 0 },
97
-
98
- sent: usize = 0,
99
- received: usize = 0,
100
-
101
- fn run_test() !void {
102
- var io = try IO.init(32, 0);
103
- defer io.deinit();
104
-
105
- const address = try std.net.Address.parseIp4("127.0.0.1", 3131);
106
- const kernel_backlog = 1;
107
- const server = try io.open_socket(address.any.family, os.SOCK.STREAM, os.IPPROTO.TCP);
108
- defer os.closeSocket(server);
109
-
110
- const client = try io.open_socket(address.any.family, os.SOCK.STREAM, os.IPPROTO.TCP);
111
- defer os.closeSocket(client);
112
-
113
- try os.setsockopt(
114
- server,
115
- os.SOL.SOCKET,
116
- os.SO.REUSEADDR,
117
- &std.mem.toBytes(@as(c_int, 1)),
118
- );
119
- try os.bind(server, &address.any, address.getOsSockLen());
120
- try os.listen(server, kernel_backlog);
121
-
122
- var self: Context = .{
123
- .io = &io,
124
- .server = server,
125
- .client = client,
126
- };
127
-
128
- var client_completion: IO.Completion = undefined;
129
- self.io.connect(
130
- *Context,
131
- &self,
132
- connect_callback,
133
- &client_completion,
134
- client,
135
- address,
136
- );
137
-
138
- var server_completion: IO.Completion = undefined;
139
- self.io.accept(*Context, &self, accept_callback, &server_completion, server);
140
-
141
- while (!self.done) try self.io.tick();
142
-
143
- try testing.expectEqual(self.send_buf.len, self.sent);
144
- try testing.expectEqual(self.recv_buf.len, self.received);
145
-
146
- try testing.expectEqualSlices(u8, self.send_buf[0..self.received], &self.recv_buf);
147
- }
148
-
149
- fn connect_callback(
150
- self: *Context,
151
- completion: *IO.Completion,
152
- result: IO.ConnectError!void,
153
- ) void {
154
- _ = result catch @panic("connect error");
155
-
156
- self.io.send(
157
- *Context,
158
- self,
159
- send_callback,
160
- completion,
161
- self.client,
162
- &self.send_buf,
163
- );
164
- }
165
-
166
- fn send_callback(
167
- self: *Context,
168
- completion: *IO.Completion,
169
- result: IO.SendError!usize,
170
- ) void {
171
- _ = completion;
172
-
173
- self.sent = result catch @panic("send error");
174
- }
175
-
176
- fn accept_callback(
177
- self: *Context,
178
- completion: *IO.Completion,
179
- result: IO.AcceptError!os.socket_t,
180
- ) void {
181
- self.accepted_sock = result catch @panic("accept error");
182
- self.io.recv(
183
- *Context,
184
- self,
185
- recv_callback,
186
- completion,
187
- self.accepted_sock,
188
- &self.recv_buf,
189
- );
190
- }
191
-
192
- fn recv_callback(
193
- self: *Context,
194
- completion: *IO.Completion,
195
- result: IO.RecvError!usize,
196
- ) void {
197
- _ = completion;
198
-
199
- self.received = result catch @panic("recv error");
200
- self.done = true;
201
- }
202
- }.run_test();
203
- }
204
-
205
- test "timeout" {
206
- const ms = 20;
207
- const margin = 5;
208
- const count = 10;
209
-
210
- try struct {
211
- const Context = @This();
212
-
213
- io: IO,
214
- timer: *Time,
215
- count: u32 = 0,
216
- stop_time: u64 = 0,
217
-
218
- fn run_test() !void {
219
- var timer = Time{};
220
- const start_time = timer.monotonic();
221
- var self: Context = .{
222
- .timer = &timer,
223
- .io = try IO.init(32, 0),
224
- };
225
- defer self.io.deinit();
226
-
227
- var completions: [count]IO.Completion = undefined;
228
- for (completions) |*completion| {
229
- self.io.timeout(
230
- *Context,
231
- &self,
232
- timeout_callback,
233
- completion,
234
- ms * std.time.ns_per_ms,
235
- );
236
- }
237
- while (self.count < count) try self.io.tick();
238
-
239
- try self.io.tick();
240
- try testing.expectEqual(@as(u32, count), self.count);
241
-
242
- try testing.expectApproxEqAbs(
243
- @as(f64, ms),
244
- @intToFloat(f64, (self.stop_time - start_time) / std.time.ns_per_ms),
245
- margin,
246
- );
247
- }
248
-
249
- fn timeout_callback(
250
- self: *Context,
251
- completion: *IO.Completion,
252
- result: IO.TimeoutError!void,
253
- ) void {
254
- _ = completion;
255
- _ = result catch @panic("timeout error");
256
-
257
- if (self.stop_time == 0) self.stop_time = self.timer.monotonic();
258
- self.count += 1;
259
- }
260
- }.run_test();
261
- }
262
-
263
- test "submission queue full" {
264
- const ms = 20;
265
- const count = 10;
266
-
267
- try struct {
268
- const Context = @This();
269
-
270
- io: IO,
271
- count: u32 = 0,
272
-
273
- fn run_test() !void {
274
- var self: Context = .{ .io = try IO.init(1, 0) };
275
- defer self.io.deinit();
276
-
277
- var completions: [count]IO.Completion = undefined;
278
- for (completions) |*completion| {
279
- self.io.timeout(
280
- *Context,
281
- &self,
282
- timeout_callback,
283
- completion,
284
- ms * std.time.ns_per_ms,
285
- );
286
- }
287
- while (self.count < count) try self.io.tick();
288
-
289
- try self.io.tick();
290
- try testing.expectEqual(@as(u32, count), self.count);
291
- }
292
-
293
- fn timeout_callback(
294
- self: *Context,
295
- completion: *IO.Completion,
296
- result: IO.TimeoutError!void,
297
- ) void {
298
- _ = completion;
299
- _ = result catch @panic("timeout error");
300
-
301
- self.count += 1;
302
- }
303
- }.run_test();
304
- }
305
-
306
- test "tick to wait" {
307
- // Use only IO.tick() to see if pending IO is actually processsed
308
-
309
- try struct {
310
- const Context = @This();
311
-
312
- io: IO,
313
- accepted: os.socket_t = IO.INVALID_SOCKET,
314
- connected: bool = false,
315
- received: bool = false,
316
-
317
- fn run_test() !void {
318
- var self: Context = .{ .io = try IO.init(1, 0) };
319
- defer self.io.deinit();
320
-
321
- const address = try std.net.Address.parseIp4("127.0.0.1", 3131);
322
- const kernel_backlog = 1;
323
-
324
- const server = try self.io.open_socket(address.any.family, os.SOCK.STREAM, os.IPPROTO.TCP);
325
- defer os.closeSocket(server);
326
-
327
- try os.setsockopt(
328
- server,
329
- os.SOL.SOCKET,
330
- os.SO.REUSEADDR,
331
- &std.mem.toBytes(@as(c_int, 1)),
332
- );
333
- try os.bind(server, &address.any, address.getOsSockLen());
334
- try os.listen(server, kernel_backlog);
335
-
336
- const client = try self.io.open_socket(address.any.family, os.SOCK.STREAM, os.IPPROTO.TCP);
337
- defer os.closeSocket(client);
338
-
339
- // Start the accept
340
- var server_completion: IO.Completion = undefined;
341
- self.io.accept(*Context, &self, accept_callback, &server_completion, server);
342
-
343
- // Start the connect
344
- var client_completion: IO.Completion = undefined;
345
- self.io.connect(
346
- *Context,
347
- &self,
348
- connect_callback,
349
- &client_completion,
350
- client,
351
- address,
352
- );
353
-
354
- // Tick the IO to drain the accept & connect completions
355
- assert(!self.connected);
356
- assert(self.accepted == IO.INVALID_SOCKET);
357
-
358
- while (self.accepted == IO.INVALID_SOCKET or !self.connected)
359
- try self.io.tick();
360
-
361
- assert(self.connected);
362
- assert(self.accepted != IO.INVALID_SOCKET);
363
- defer os.closeSocket(self.accepted);
364
-
365
- // Start receiving on the client
366
- var recv_completion: IO.Completion = undefined;
367
- var recv_buffer: [64]u8 = undefined;
368
- std.mem.set(u8, &recv_buffer, 0xaa);
369
- self.io.recv(
370
- *Context,
371
- &self,
372
- recv_callback,
373
- &recv_completion,
374
- client,
375
- &recv_buffer,
376
- );
377
-
378
- // Drain out the recv completion from any internal IO queues
379
- try self.io.tick();
380
- try self.io.tick();
381
- try self.io.tick();
382
-
383
- // Complete the recv() *outside* of the IO instance.
384
- // Other tests already check .tick() with IO based completions.
385
- // This simulates IO being completed by an external system
386
- var send_buf = std.mem.zeroes([64]u8);
387
- const wrote = try os_send(self.accepted, &send_buf, 0);
388
- try testing.expectEqual(wrote, send_buf.len);
389
-
390
- // Wait for the recv() to complete using only IO.tick().
391
- // If tick is broken, then this will deadlock
392
- assert(!self.received);
393
- while (!self.received) {
394
- try self.io.tick();
395
- }
396
-
397
- // Make sure the receive actually happened
398
- assert(self.received);
399
- try testing.expect(std.mem.eql(u8, &recv_buffer, &send_buf));
400
- }
401
-
402
- fn accept_callback(
403
- self: *Context,
404
- completion: *IO.Completion,
405
- result: IO.AcceptError!os.socket_t,
406
- ) void {
407
- _ = completion;
408
-
409
- assert(self.accepted == IO.INVALID_SOCKET);
410
- self.accepted = result catch @panic("accept error");
411
- }
412
-
413
- fn connect_callback(
414
- self: *Context,
415
- completion: *IO.Completion,
416
- result: IO.ConnectError!void,
417
- ) void {
418
- _ = completion;
419
- _ = result catch @panic("connect error");
420
-
421
- assert(!self.connected);
422
- self.connected = true;
423
- }
424
-
425
- fn recv_callback(
426
- self: *Context,
427
- completion: *IO.Completion,
428
- result: IO.RecvError!usize,
429
- ) void {
430
- _ = completion;
431
- _ = result catch |err| std.debug.panic("recv error: {}", .{err});
432
-
433
- assert(!self.received);
434
- self.received = true;
435
- }
436
-
437
- // TODO: use os.send() instead when it gets fixed for windows
438
- fn os_send(sock: os.socket_t, buf: []const u8, flags: u32) !usize {
439
- if (builtin.target.os.tag != .windows) {
440
- return os.send(sock, buf, flags);
441
- }
442
-
443
- const rc = os.windows.sendto(sock, buf.ptr, buf.len, flags, null, 0);
444
- if (rc == os.windows.ws2_32.SOCKET_ERROR) {
445
- switch (os.windows.ws2_32.WSAGetLastError()) {
446
- .WSAEACCES => return error.AccessDenied,
447
- .WSAEADDRNOTAVAIL => return error.AddressNotAvailable,
448
- .WSAECONNRESET => return error.ConnectionResetByPeer,
449
- .WSAEMSGSIZE => return error.MessageTooBig,
450
- .WSAENOBUFS => return error.SystemResources,
451
- .WSAENOTSOCK => return error.FileDescriptorNotASocket,
452
- .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported,
453
- .WSAEDESTADDRREQ => unreachable, // A destination address is required.
454
- .WSAEFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small.
455
- .WSAEHOSTUNREACH => return error.NetworkUnreachable,
456
- // TODO: WSAEINPROGRESS, WSAEINTR
457
- .WSAEINVAL => unreachable,
458
- .WSAENETDOWN => return error.NetworkSubsystemFailed,
459
- .WSAENETRESET => return error.ConnectionResetByPeer,
460
- .WSAENETUNREACH => return error.NetworkUnreachable,
461
- .WSAENOTCONN => return error.SocketNotConnected,
462
- .WSAESHUTDOWN => unreachable, // The socket has been shut down; it is not possible to WSASendTo on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH.
463
- .WSAEWOULDBLOCK => return error.WouldBlock,
464
- .WSANOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function.
465
- else => |err| return os.windows.unexpectedWSAError(err),
466
- }
467
- } else {
468
- return @intCast(usize, rc);
469
- }
470
- }
471
- }.run_test();
472
- }
473
-
474
- test "pipe data over socket" {
475
- try struct {
476
- io: IO,
477
- tx: Pipe,
478
- rx: Pipe,
479
- server: Socket = .{},
480
-
481
- const buffer_size = 1 * 1024 * 1024;
482
-
483
- const Context = @This();
484
- const Socket = struct {
485
- fd: os.socket_t = IO.INVALID_SOCKET,
486
- completion: IO.Completion = undefined,
487
- };
488
- const Pipe = struct {
489
- socket: Socket = .{},
490
- buffer: []u8,
491
- transferred: usize = 0,
492
- };
493
-
494
- fn run() !void {
495
- const tx_buf = try testing.allocator.alloc(u8, buffer_size);
496
- defer testing.allocator.free(tx_buf);
497
- const rx_buf = try testing.allocator.alloc(u8, buffer_size);
498
- defer testing.allocator.free(rx_buf);
499
-
500
- std.mem.set(u8, tx_buf, 1);
501
- std.mem.set(u8, rx_buf, 0);
502
- var self = Context{
503
- .io = try IO.init(32, 0),
504
- .tx = .{ .buffer = tx_buf },
505
- .rx = .{ .buffer = rx_buf },
506
- };
507
- defer self.io.deinit();
508
-
509
- self.server.fd = try self.io.open_socket(os.AF.INET, os.SOCK.STREAM, os.IPPROTO.TCP);
510
- defer os.closeSocket(self.server.fd);
511
-
512
- const address = try std.net.Address.parseIp4("127.0.0.1", 3131);
513
- try os.setsockopt(
514
- self.server.fd,
515
- os.SOL.SOCKET,
516
- os.SO.REUSEADDR,
517
- &std.mem.toBytes(@as(c_int, 1)),
518
- );
519
-
520
- try os.bind(self.server.fd, &address.any, address.getOsSockLen());
521
- try os.listen(self.server.fd, 1);
522
-
523
- self.io.accept(
524
- *Context,
525
- &self,
526
- on_accept,
527
- &self.server.completion,
528
- self.server.fd,
529
- );
530
-
531
- self.tx.socket.fd = try self.io.open_socket(os.AF.INET, os.SOCK.STREAM, os.IPPROTO.TCP);
532
- defer os.closeSocket(self.tx.socket.fd);
533
-
534
- self.io.connect(
535
- *Context,
536
- &self,
537
- on_connect,
538
- &self.tx.socket.completion,
539
- self.tx.socket.fd,
540
- address,
541
- );
542
-
543
- var tick: usize = 0xdeadbeef;
544
- while (self.rx.transferred != self.rx.buffer.len) : (tick +%= 1) {
545
- if (tick % 61 == 0) {
546
- const timeout_ns = tick % (10 * std.time.ns_per_ms);
547
- try self.io.run_for_ns(@intCast(u63, timeout_ns));
548
- } else {
549
- try self.io.tick();
550
- }
551
- }
552
-
553
- try testing.expect(self.server.fd != IO.INVALID_SOCKET);
554
- try testing.expect(self.tx.socket.fd != IO.INVALID_SOCKET);
555
- try testing.expect(self.rx.socket.fd != IO.INVALID_SOCKET);
556
- os.closeSocket(self.rx.socket.fd);
557
-
558
- try testing.expectEqual(self.tx.transferred, buffer_size);
559
- try testing.expectEqual(self.rx.transferred, buffer_size);
560
- try testing.expect(std.mem.eql(u8, self.tx.buffer, self.rx.buffer));
561
- }
562
-
563
- fn on_accept(
564
- self: *Context,
565
- completion: *IO.Completion,
566
- result: IO.AcceptError!os.socket_t,
567
- ) void {
568
- assert(self.rx.socket.fd == IO.INVALID_SOCKET);
569
- assert(&self.server.completion == completion);
570
- self.rx.socket.fd = result catch |err| std.debug.panic("accept error {}", .{err});
571
-
572
- assert(self.rx.transferred == 0);
573
- self.do_receiver(0);
574
- }
575
-
576
- fn on_connect(
577
- self: *Context,
578
- completion: *IO.Completion,
579
- result: IO.ConnectError!void,
580
- ) void {
581
- _ = completion;
582
- _ = result catch unreachable;
583
-
584
- assert(self.tx.socket.fd != IO.INVALID_SOCKET);
585
- assert(&self.tx.socket.completion == completion);
586
-
587
- assert(self.tx.transferred == 0);
588
- self.do_sender(0);
589
- }
590
-
591
- fn do_sender(self: *Context, bytes: usize) void {
592
- self.tx.transferred += bytes;
593
- assert(self.tx.transferred <= self.tx.buffer.len);
594
-
595
- if (self.tx.transferred < self.tx.buffer.len) {
596
- self.io.send(
597
- *Context,
598
- self,
599
- on_send,
600
- &self.tx.socket.completion,
601
- self.tx.socket.fd,
602
- self.tx.buffer[self.tx.transferred..],
603
- );
604
- }
605
- }
606
-
607
- fn on_send(
608
- self: *Context,
609
- completion: *IO.Completion,
610
- result: IO.SendError!usize,
611
- ) void {
612
- const bytes = result catch |err| std.debug.panic("send error: {}", .{err});
613
- assert(&self.tx.socket.completion == completion);
614
- self.do_sender(bytes);
615
- }
616
-
617
- fn do_receiver(self: *Context, bytes: usize) void {
618
- self.rx.transferred += bytes;
619
- assert(self.rx.transferred <= self.rx.buffer.len);
620
-
621
- if (self.rx.transferred < self.rx.buffer.len) {
622
- self.io.recv(
623
- *Context,
624
- self,
625
- on_recv,
626
- &self.rx.socket.completion,
627
- self.rx.socket.fd,
628
- self.rx.buffer[self.rx.transferred..],
629
- );
630
- }
631
- }
632
-
633
- fn on_recv(
634
- self: *Context,
635
- completion: *IO.Completion,
636
- result: IO.RecvError!usize,
637
- ) void {
638
- const bytes = result catch |err| std.debug.panic("recv error: {}", .{err});
639
- assert(&self.rx.socket.completion == completion);
640
- self.do_receiver(bytes);
641
- }
642
- }.run();
643
- }