tigerbeetle-node 0.10.0 → 0.11.1

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 (109) hide show
  1. package/README.md +302 -101
  2. package/dist/index.d.ts +70 -72
  3. package/dist/index.js +70 -72
  4. package/dist/index.js.map +1 -1
  5. package/package.json +9 -8
  6. package/scripts/download_node_headers.sh +14 -7
  7. package/src/index.ts +6 -10
  8. package/src/node.zig +6 -3
  9. package/src/tigerbeetle/scripts/benchmark.sh +4 -4
  10. package/src/tigerbeetle/scripts/confirm_image.sh +44 -0
  11. package/src/tigerbeetle/scripts/fuzz_loop.sh +15 -0
  12. package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +7 -0
  13. package/src/tigerbeetle/scripts/install.sh +19 -4
  14. package/src/tigerbeetle/scripts/install_zig.bat +5 -1
  15. package/src/tigerbeetle/scripts/install_zig.sh +24 -14
  16. package/src/tigerbeetle/scripts/pre-commit.sh +9 -0
  17. package/src/tigerbeetle/scripts/shellcheck.sh +5 -0
  18. package/src/tigerbeetle/scripts/tests_on_alpine.sh +10 -0
  19. package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +14 -0
  20. package/src/tigerbeetle/scripts/validate_docs.sh +17 -0
  21. package/src/tigerbeetle/src/benchmark.zig +29 -13
  22. package/src/tigerbeetle/src/c/tb_client/context.zig +248 -47
  23. package/src/tigerbeetle/src/c/tb_client/echo_client.zig +108 -0
  24. package/src/tigerbeetle/src/c/tb_client/packet.zig +2 -2
  25. package/src/tigerbeetle/src/c/tb_client/signal.zig +2 -4
  26. package/src/tigerbeetle/src/c/tb_client/thread.zig +17 -257
  27. package/src/tigerbeetle/src/c/tb_client.h +118 -84
  28. package/src/tigerbeetle/src/c/tb_client.zig +88 -23
  29. package/src/tigerbeetle/src/c/tb_client_header_test.zig +135 -0
  30. package/src/tigerbeetle/src/c/test.zig +371 -1
  31. package/src/tigerbeetle/src/cli.zig +37 -7
  32. package/src/tigerbeetle/src/config.zig +58 -17
  33. package/src/tigerbeetle/src/demo.zig +5 -2
  34. package/src/tigerbeetle/src/demo_01_create_accounts.zig +1 -1
  35. package/src/tigerbeetle/src/demo_03_create_transfers.zig +13 -0
  36. package/src/tigerbeetle/src/ewah.zig +11 -33
  37. package/src/tigerbeetle/src/ewah_benchmark.zig +8 -9
  38. package/src/tigerbeetle/src/io/linux.zig +1 -1
  39. package/src/tigerbeetle/src/lsm/README.md +308 -0
  40. package/src/tigerbeetle/src/lsm/binary_search.zig +137 -10
  41. package/src/tigerbeetle/src/lsm/bloom_filter.zig +43 -0
  42. package/src/tigerbeetle/src/lsm/compaction.zig +376 -397
  43. package/src/tigerbeetle/src/lsm/composite_key.zig +2 -0
  44. package/src/tigerbeetle/src/lsm/eytzinger.zig +1 -1
  45. package/src/tigerbeetle/src/{eytzinger_benchmark.zig → lsm/eytzinger_benchmark.zig} +34 -21
  46. package/src/tigerbeetle/src/lsm/forest.zig +21 -447
  47. package/src/tigerbeetle/src/lsm/forest_fuzz.zig +414 -0
  48. package/src/tigerbeetle/src/lsm/grid.zig +170 -76
  49. package/src/tigerbeetle/src/lsm/groove.zig +197 -133
  50. package/src/tigerbeetle/src/lsm/k_way_merge.zig +40 -18
  51. package/src/tigerbeetle/src/lsm/level_iterator.zig +28 -9
  52. package/src/tigerbeetle/src/lsm/manifest.zig +93 -180
  53. package/src/tigerbeetle/src/lsm/manifest_level.zig +161 -454
  54. package/src/tigerbeetle/src/lsm/manifest_log.zig +243 -356
  55. package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +665 -0
  56. package/src/tigerbeetle/src/lsm/node_pool.zig +4 -0
  57. package/src/tigerbeetle/src/lsm/posted_groove.zig +65 -76
  58. package/src/tigerbeetle/src/lsm/segmented_array.zig +580 -251
  59. package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +148 -0
  60. package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +9 -0
  61. package/src/tigerbeetle/src/lsm/set_associative_cache.zig +62 -12
  62. package/src/tigerbeetle/src/lsm/table.zig +115 -68
  63. package/src/tigerbeetle/src/lsm/table_immutable.zig +30 -23
  64. package/src/tigerbeetle/src/lsm/table_iterator.zig +27 -17
  65. package/src/tigerbeetle/src/lsm/table_mutable.zig +63 -12
  66. package/src/tigerbeetle/src/lsm/test.zig +61 -56
  67. package/src/tigerbeetle/src/lsm/tree.zig +450 -407
  68. package/src/tigerbeetle/src/lsm/tree_fuzz.zig +461 -0
  69. package/src/tigerbeetle/src/main.zig +83 -8
  70. package/src/tigerbeetle/src/message_bus.zig +20 -9
  71. package/src/tigerbeetle/src/message_pool.zig +22 -19
  72. package/src/tigerbeetle/src/ring_buffer.zig +7 -3
  73. package/src/tigerbeetle/src/simulator.zig +179 -119
  74. package/src/tigerbeetle/src/state_machine.zig +381 -246
  75. package/src/tigerbeetle/src/static_allocator.zig +65 -0
  76. package/src/tigerbeetle/src/storage.zig +3 -7
  77. package/src/tigerbeetle/src/test/accounting/auditor.zig +577 -0
  78. package/src/tigerbeetle/src/test/accounting/workload.zig +823 -0
  79. package/src/tigerbeetle/src/test/cluster.zig +33 -81
  80. package/src/tigerbeetle/src/test/conductor.zig +366 -0
  81. package/src/tigerbeetle/src/test/fuzz.zig +121 -0
  82. package/src/tigerbeetle/src/test/id.zig +89 -0
  83. package/src/tigerbeetle/src/test/network.zig +45 -19
  84. package/src/tigerbeetle/src/test/packet_simulator.zig +40 -29
  85. package/src/tigerbeetle/src/test/priority_queue.zig +645 -0
  86. package/src/tigerbeetle/src/test/state_checker.zig +91 -69
  87. package/src/tigerbeetle/src/test/state_machine.zig +11 -35
  88. package/src/tigerbeetle/src/test/storage.zig +470 -106
  89. package/src/tigerbeetle/src/test/storage_checker.zig +204 -0
  90. package/src/tigerbeetle/src/tigerbeetle.zig +15 -16
  91. package/src/tigerbeetle/src/unit_tests.zig +13 -1
  92. package/src/tigerbeetle/src/util.zig +97 -11
  93. package/src/tigerbeetle/src/vopr.zig +495 -0
  94. package/src/tigerbeetle/src/vsr/client.zig +21 -3
  95. package/src/tigerbeetle/src/vsr/journal.zig +293 -212
  96. package/src/tigerbeetle/src/vsr/replica.zig +1086 -515
  97. package/src/tigerbeetle/src/vsr/superblock.zig +382 -637
  98. package/src/tigerbeetle/src/vsr/superblock_client_table.zig +14 -16
  99. package/src/tigerbeetle/src/vsr/superblock_free_set.zig +416 -153
  100. package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +332 -0
  101. package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +349 -0
  102. package/src/tigerbeetle/src/vsr/superblock_manifest.zig +62 -12
  103. package/src/tigerbeetle/src/vsr/superblock_quorums.zig +394 -0
  104. package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +312 -0
  105. package/src/tigerbeetle/src/vsr.zig +94 -60
  106. package/src/tigerbeetle/scripts/vopr.bat +0 -48
  107. package/src/tigerbeetle/scripts/vopr.sh +0 -33
  108. package/src/tigerbeetle/src/benchmark_array_search.zig +0 -317
  109. package/src/tigerbeetle/src/benchmarks/perf.zig +0 -299
@@ -7,7 +7,6 @@
7
7
 
8
8
  typedef __uint128_t tb_uint128_t;
9
9
 
10
-
11
10
  typedef enum TB_ACCOUNT_FLAGS {
12
11
  TB_ACCOUNT_LINKED = 1 << 0,
13
12
  TB_ACCOUNT_DEBITS_MUST_NOT_EXCEED_CREDITS = 1 << 1,
@@ -18,20 +17,21 @@ typedef struct tb_account_t {
18
17
  tb_uint128_t id;
19
18
  tb_uint128_t user_data;
20
19
  uint8_t reserved[48];
21
- uint16_t unit;
20
+ uint32_t ledger;
22
21
  uint16_t code;
23
- uint32_t flags;
24
- uint64_t debits_reserved;
25
- uint64_t debits_accepted;
26
- uint64_t credits_reserved;
27
- uint64_t credits_accepted;
22
+ uint16_t flags;
23
+ uint64_t debits_pending;
24
+ uint64_t debits_posted;
25
+ uint64_t credits_pending;
26
+ uint64_t credits_posted;
28
27
  uint64_t timestamp;
29
28
  } tb_account_t;
30
29
 
31
30
  typedef enum TB_TRANSFER_FLAGS {
32
31
  TB_TRANSFER_LINKED = 1 << 0,
33
- TB_TRANSFER_TWO_PHASE_COMMIT = 1 << 1,
34
- TB_TRANSFER_CONDITION = 1 << 2,
32
+ TB_TRANSFER_PENDING = 1 << 1,
33
+ TB_TRANSFER_POST_PENDING_TRANSFER = 1 << 2,
34
+ TB_TRANSFER_VOID_PENDING_TRANSFER = 1 << 3,
35
35
  } TB_TRANSFER_FLAGS;
36
36
 
37
37
  typedef struct tb_transfer_t {
@@ -39,111 +39,132 @@ typedef struct tb_transfer_t {
39
39
  tb_uint128_t debit_account_id;
40
40
  tb_uint128_t credit_account_id;
41
41
  tb_uint128_t user_data;
42
- uint8_t reserved[32];
42
+ tb_uint128_t reserved;
43
+ tb_uint128_t pending_id;
43
44
  uint64_t timeout;
44
- uint32_t code;
45
- uint32_t flags;
45
+ uint32_t ledger;
46
+ uint16_t code;
47
+ uint16_t flags;
46
48
  uint64_t amount;
47
49
  uint64_t timestamp;
48
50
  } tb_transfer_t;
49
51
 
50
- typedef enum TB_COMMIT_FLAGS {
51
- TB_COMMIT_LINKED = 1 << 0,
52
- TB_COMMIT_REJECT = 1 << 1,
53
- TB_COMMIT_PREIMAGE = 1 << 2,
54
- } TB_COMMIT_FLAGS;
55
-
56
- typedef struct tb_commit_t {
57
- tb_uint128_t id;
58
- uint8_t reserved[32];
59
- uint32_t code;
60
- uint32_t flags;
61
- uint64_t timestamp;
62
- } tb_commit_t;
63
-
64
52
  typedef enum TB_CREATE_ACCOUNT_RESULT {
65
53
  TB_CREATE_ACCOUNT_OK,
66
54
  TB_CREATE_ACCOUNT_LINKED_EVENT_FAILED,
67
- TB_CREATE_ACCOUNT_EXISTS,
55
+ TB_CREATE_ACCOUNT_LINKED_EVENT_CHAIN_OPEN,
56
+
57
+ TB_CREATE_ACCOUNT_RESERVED_FLAG,
58
+ TB_CREATE_ACCOUNT_RESERVED_FIELD,
59
+
60
+ TB_CREATE_ACCOUNT_ID_MUST_NOT_BE_ZERO,
61
+ TB_CREATE_ACCOUNT_ID_MUST_NOT_BE_INT_MAX,
62
+ TB_CREATE_ACCOUNT_LEDGER_MUST_NOT_BE_ZERO,
63
+ TB_CREATE_ACCOUNT_CODE_MUST_NOT_BE_ZERO,
64
+ TB_CREATE_ACCOUNT_DEBITS_PENDING_MUST_BE_ZERO,
65
+ TB_CREATE_ACCOUNT_DEBITS_POSTED_MUST_BE_ZERO,
66
+ TB_CREATE_ACCOUNT_CREDITS_PENDING_MUST_BE_ZERO,
67
+ TB_CREATE_ACCOUNT_CREDITS_POSTED_MUST_BE_ZERO,
68
+
69
+ TB_CREATE_ACCOUNT_MUTUALLY_EXCLUSIVE_FLAGS,
70
+
71
+ TB_CREATE_ACCOUNT_EXISTS_WITH_DIFFERENT_FLAGS,
68
72
  TB_CREATE_ACCOUNT_EXISTS_WITH_DIFFERENT_USER_DATA,
69
- TB_CREATE_ACCOUNT_EXISTS_WITH_DIFFERENT_RESERVED_FIELD,
70
- TB_CREATE_ACCOUNT_EXISTS_WITH_DIFFERENT_UNIT,
73
+ TB_CREATE_ACCOUNT_EXISTS_WITH_DIFFERENT_LEDGER,
71
74
  TB_CREATE_ACCOUNT_EXISTS_WITH_DIFFERENT_CODE,
72
- TB_CREATE_ACCOUNT_EXISTS_WITH_DIFFERENT_FLAGS,
73
- TB_CREATE_ACCOUNT_EXCEEDS_CREDITS,
74
- TB_CREATE_ACCOUNT_EXCEEDS_DEBITS,
75
- TB_CREATE_ACCOUNT_RESERVE_FAILED,
76
- TB_CREATE_ACCOUNT_RESERVE_FLAG_PADDING
75
+ TB_CREATE_ACCOUNT_EXISTS
77
76
  } TB_CREATE_ACCOUNT_RESULT;
78
77
 
79
78
  typedef enum TB_CREATE_TRANSFER_RESULT {
80
79
  TB_CREATE_TRANSFER_OK,
81
80
  TB_CREATE_TRANSFER_LINKED_EVENT_FAILED,
82
- TB_CREATE_TRANSFER_EXISTS,
81
+ TB_CREATE_TRANSFER_LINKED_EVENT_CHAIN_OPEN,
82
+
83
+ TB_CREATE_TRANSFER_RESERVED_FLAG,
84
+ TB_CREATE_TRANSFER_RESERVED_FIELD,
85
+
86
+ TB_CREATE_TRANSFER_ID_MUST_NOT_BE_ZERO,
87
+ TB_CREATE_TRANSFER_ID_MUST_NOT_BE_INT_MAX,
88
+ TB_CREATE_TRANSFER_DEBIT_ACCOUNT_ID_MUST_NOT_BE_ZERO,
89
+ TB_CREATE_TRANSFER_DEBIT_ACCOUNT_ID_MUST_NOT_BE_INT_MAX,
90
+ TB_CREATE_TRANSFER_CREDIT_ACCOUNT_ID_MUST_NOT_BE_ZERO,
91
+ TB_CREATE_TRANSFER_CREDIT_ACCOUNT_ID_MUST_NOT_BE_INT_MAX,
92
+ TB_CREATE_TRANSFER_ACCOUNTS_MUST_BE_DIFFERENT,
93
+
94
+ TB_CREATE_TRANSFER_PENDING_ID_MUST_BE_ZERO,
95
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_MUST_TIMEOUT,
96
+
97
+ TB_CREATE_TRANSFER_LEDGER_MUST_NOT_BE_ZERO,
98
+ TB_CREATE_TRANSFER_CODE_MUST_NOT_BE_ZERO,
99
+ TB_CREATE_TRANSFER_AMOUNT_MUST_NOT_BE_ZERO,
100
+
101
+ TB_CREATE_TRANSFER_DEBIT_ACCOUNT_NOT_FOUND,
102
+ TB_CREATE_TRANSFER_CREDIT_ACCOUNT_NOT_FOUND,
103
+
104
+ TB_CREATE_TRANSFER_ACCOUNTS_MUST_HAVE_THE_SAME_LEDGER,
105
+ TB_CREATE_TRANSFER_TRANSFER_MUST_HAVE_THE_SAME_LEDGER_AS_ACCOUNTS,
106
+
107
+ TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_FLAGS,
83
108
  TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_DEBIT_ACCOUNT_ID,
84
109
  TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_CREDIT_ACCOUNT_ID,
85
110
  TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_USER_DATA,
86
- TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_RESERVED_FIELD,
111
+ TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_PENDING_ID,
112
+ TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_TIMEOUT,
87
113
  TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_CODE,
88
114
  TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_AMOUNT,
89
- TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_TIMEOUT,
90
- TB_CREATE_TRANSFER_EXISTS_WITH_DIFFERENT_FLAGS,
91
- TB_CREATE_TRANSFER_EXISTS_AND_ALREADY_COMMITTED_AND_ACCEPTED,
92
- TB_CREATE_TRANSFER_EXISTS_AND_ALREADY_COMMITTED_AND_REJECTED,
93
- TB_CREATE_TRANSFER_RESERVED_FIELD,
94
- TB_CREATE_TRANSFER_RESERVED_FLAG_PADDING,
95
- TB_CREATE_TRANSFER_DEBIT_ACCOUNT_NOT_FOUND,
96
- TB_CREATE_TRANSFER_CREDIT_ACCOUNT_NOT_FOUND,
97
- TB_CREATE_TRANSFER_ACCOUNTS_ARE_THE_SAME,
98
- TB_CREATE_TRANSFER_ACCOUNTS_HAVE_DIFFERENT_UNITS,
99
- TB_CREATE_TRANSFER_AMOUNT_IS_ZERO,
115
+ TB_CREATE_TRANSFER_EXISTS,
116
+
117
+ TB_CREATE_TRANSFER_OVERFLOWS_DEBITS_PENDING,
118
+ TB_CREATE_TRANSFER_OVERFLOWS_CREDITS_PENDING,
119
+ TB_CREATE_TRANSFER_OVERFLOWS_DEBITS_POSTED,
120
+ TB_CREATE_TRANSFER_OVERFLOWS_CREDITS_POSTED,
121
+ TB_CREATE_TRANSFER_OVERFLOWS_DEBITS,
122
+ TB_CREATE_TRANSFER_OVERFLOWS_CREDITS,
123
+ TB_CREATE_TRANSFER_OVERFLOWS_TIMEOUT,
124
+
100
125
  TB_CREATE_TRANSFER_EXCEEDS_CREDITS,
101
126
  TB_CREATE_TRANSFER_EXCEEDS_DEBITS,
102
- TB_CREATE_TRANSFER_TWO_PHASE_COMMIT_MUST_TIMEOUT,
103
- TB_CREATE_TRANSFER_TIMEOUT_RESERVED_FOR_TWO_PHASE_COMMIT
104
- } TB_CREATE_TRANSFER_RESULT;
105
127
 
106
- typedef enum TB_COMMIT_TRANSFER_RESULT {
107
- TB_COMMIT_TRANSFER_OK,
108
- TB_COMMIT_TRANSFER_LINKED_EVENT_FAILED,
109
- TB_COMMIT_TRANSFER_RESERVE_FAILED,
110
- TB_COMMIT_TRANSFER_RESERVE_FLAG_PADDING,
111
- TB_COMMIT_TRANSFER_NOT_FOUND,
112
- TB_COMMIT_TRANSFER_NOT_TWO_PHASE_COMMIT,
113
- TB_COMMIT_TRANSFER_EXPIRED,
114
- TB_COMMIT_TRANSFER_ALREADY_COMMITTED,
115
- TB_COMMIT_TRANSFER_ALREADY_COMMITTED_BUT_ACCEPTED,
116
- TB_COMMIT_TRANSFER_ALREADY_COMMITTED_BUT_REJECTED,
117
- TB_COMMIT_TRANSFER_DEBIT_ACCOUNT_NOT_FOUND,
118
- TB_COMMIT_TRANSFER_CREDIT_ACCOUNT_NOT_FOUND,
119
- TB_COMMIT_TRANSFER_EXCEEDS_CREDITS,
120
- TB_COMMIT_TRANSFER_EXCEEDS_DEBITS,
121
- TB_COMMIT_TRANSFER_CONDITION_REQUIRES_PREIMAGE,
122
- TB_COMMIT_TRANSFER_PREIMAGE_REQUIRES_CONDITION,
123
- TB_COMMIT_TRANSFER_PREIMAGE_INVALID
124
- } TB_COMMIT_TRANSFER_RESULT;
128
+ TB_CREATE_TRANSFER_CANNOT_POST_AND_VOID_PENDING_TRANSFER,
129
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_CANNOT_POST_OR_VOID_ANOTHER,
130
+ TB_CREATE_TRANSFER_TIMEOUT_RESERVED_FOR_PENDING_TRANSFER,
131
+
132
+ TB_CREATE_TRANSFER_PENDING_ID_MUST_NOT_BE_ZERO,
133
+ TB_CREATE_TRANSFER_PENDING_ID_MUST_NOT_BE_INT_MAX,
134
+ TB_CREATE_TRANSFER_PENDING_ID_MUST_BE_DIFFERENT,
135
+
136
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_NOT_FOUND,
137
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_NOT_PENDING,
138
+
139
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_HAS_DIFFERENT_DEBIT_ACCOUNT_ID,
140
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_HAS_DIFFERENT_CREDIT_ACCOUNT_ID,
141
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_HAS_DIFFERENT_LEDGER,
142
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_HAS_DIFFERENT_CODE,
143
+
144
+ TB_CREATE_TRANSFER_EXCEEDS_PENDING_TRANSFER_AMOUNT,
145
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_HAS_DIFFERENT_AMOUNT,
146
+
147
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_ALREADY_POSTED,
148
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_ALREADY_VOIDED,
149
+
150
+ TB_CREATE_TRANSFER_PENDING_TRANSFER_EXPIRED,
151
+ } TB_CREATE_TRANSFER_RESULT;
125
152
 
126
153
  typedef struct tb_create_accounts_result_t {
127
154
  uint32_t index;
128
- TB_CREATE_ACCOUNT_RESULT result;
155
+ uint32_t result;
129
156
  } tb_create_accounts_result_t;
130
157
 
131
158
  typedef struct tb_create_transfers_result_t {
132
159
  uint32_t index;
133
- TB_CREATE_TRANSFER_RESULT result;
160
+ uint32_t result;
134
161
  } tb_create_transfers_result_t;
135
162
 
136
- typedef struct tb_commit_transfers_result_t {
137
- uint32_t index;
138
- TB_COMMIT_TRANSFER_RESULT result;
139
- } tb_commit_transfers_result_t;
140
-
141
163
  typedef enum TB_OPERATION {
142
164
  TB_OP_CREATE_ACCOUNTS = 3,
143
165
  TB_OP_CREATE_TRANSFERS = 4,
144
- TB_OP_COMMIT_TRANSFERS = 5,
145
- TB_OP_LOOKUP_ACCOUNTS = 6,
146
- TB_OP_LOOKUP_TRANSFERS = 7
166
+ TB_OP_LOOKUP_ACCOUNTS = 5,
167
+ TB_OP_LOOKUP_TRANSFERS = 6
147
168
  } TB_OPERATION;
148
169
 
149
170
  typedef enum TB_PACKET_STATUS {
@@ -173,9 +194,11 @@ typedef enum TB_STATUS {
173
194
  TB_STATUS_SUCCESS = 0,
174
195
  TB_STATUS_UNEXPECTED = 1,
175
196
  TB_STATUS_OUT_OF_MEMORY = 2,
176
- TB_STATUS_INVALID_ADDRESS = 3,
177
- TB_STATUS_SYSTEM_RESOURCES = 4,
178
- TB_STATUS_NETWORK_SUBSYSTEM = 5,
197
+ TB_STATUS_ADDRESS_INVALID = 3,
198
+ TB_STATUS_ADDRESS_LIMIT_EXCEEDED = 4,
199
+ TB_STATUS_PACKETS_COUNT_INVALID = 5,
200
+ TB_STATUS_SYSTEM_RESOURCES = 6,
201
+ TB_STATUS_NETWORK_SUBSYSTEM = 7,
179
202
  } TB_STATUS;
180
203
 
181
204
  TB_STATUS tb_client_init(
@@ -184,7 +207,18 @@ TB_STATUS tb_client_init(
184
207
  uint32_t cluster_id,
185
208
  const char* address_ptr,
186
209
  uint32_t address_len,
187
- uint32_t num_packets,
210
+ uint32_t packets_count,
211
+ uintptr_t on_completion_ctx,
212
+ void (*on_completion_fn)(uintptr_t, tb_client_t, tb_packet_t*, const uint8_t*, uint32_t)
213
+ );
214
+
215
+ TB_STATUS tb_client_init_echo(
216
+ tb_client_t* out_client,
217
+ tb_packet_list_t* out_packets,
218
+ uint32_t cluster_id,
219
+ const char* address_ptr,
220
+ uint32_t address_len,
221
+ uint32_t packets_count,
188
222
  uintptr_t on_completion_ctx,
189
223
  void (*on_completion_fn)(uintptr_t, tb_client_t, tb_packet_t*, const uint8_t*, uint32_t)
190
224
  );
@@ -198,4 +232,4 @@ void tb_client_deinit(
198
232
  tb_client_t client
199
233
  );
200
234
 
201
- #endif // TB_CLIENT_C
235
+ #endif // TB_CLIENT_C
@@ -10,7 +10,9 @@ pub const tb_status_t = enum(c_int) {
10
10
  success = 0,
11
11
  unexpected,
12
12
  out_of_memory,
13
- invalid_address,
13
+ address_invalid,
14
+ address_limit_exceeded,
15
+ packets_count_invalid,
14
16
  system_resources,
15
17
  network_subsystem,
16
18
  };
@@ -23,9 +25,26 @@ pub const tb_completion_t = fn (
23
25
  result_len: u32,
24
26
  ) callconv(.C) void;
25
27
 
28
+ const config = @import("../config.zig");
29
+ const Storage = @import("../storage.zig").Storage;
30
+ const MessageBus = @import("../message_bus.zig").MessageBusClient;
31
+ const StateMachine = @import("../state_machine.zig").StateMachineType(Storage, .{
32
+ .message_body_size_max = config.message_body_size_max,
33
+ });
34
+
26
35
  const ContextType = @import("tb_client/context.zig").ContextType;
27
36
  const ContextImplementation = @import("tb_client/context.zig").ContextImplementation;
28
37
 
38
+ const DefaultContext = blk: {
39
+ const Client = @import("../vsr/client.zig").Client(StateMachine, MessageBus);
40
+ break :blk ContextType(Client);
41
+ };
42
+
43
+ const TestingContext = blk: {
44
+ const EchoClient = @import("tb_client/echo_client.zig").EchoClient(StateMachine, MessageBus);
45
+ break :blk ContextType(EchoClient);
46
+ };
47
+
29
48
  pub fn context_to_client(implementation: *ContextImplementation) tb_client_t {
30
49
  return @ptrCast(tb_client_t, implementation);
31
50
  }
@@ -34,21 +53,10 @@ fn client_to_context(tb_client: tb_client_t) *ContextImplementation {
34
53
  return @ptrCast(*ContextImplementation, @alignCast(@alignOf(ContextImplementation), tb_client));
35
54
  }
36
55
 
37
- const DefaultContext = blk: {
38
- const Storage = @import("../storage.zig").Storage;
39
- const MessageBus = @import("../message_bus.zig").MessageBusClient;
40
- const StateMachine = @import("../state_machine.zig").StateMachineType(Storage);
41
- break :blk ContextType(StateMachine, MessageBus);
42
- };
43
-
44
- // const TestingContext = blk: {
45
- // const MessageBus = @import("test_message_bus.zig").MessageBusClient;
46
- // const StateMachine = @import("../state_machine.zig").StateMachine;
47
- // break :blk ContextType(StateMachine, MessageBus);
48
- // };
49
-
50
56
  // Pick the most suitable allocator
51
- const global_allocator = if (builtin.link_libc)
57
+ const global_allocator = if (builtin.is_test)
58
+ std.testing.allocator
59
+ else if (builtin.link_libc)
52
60
  std.heap.c_allocator
53
61
  else if (builtin.target.os.tag == .windows)
54
62
  (struct {
@@ -63,28 +71,85 @@ pub export fn tb_client_init(
63
71
  cluster_id: u32,
64
72
  addresses_ptr: [*:0]const u8,
65
73
  addresses_len: u32,
66
- num_packets: u32,
74
+ packets_count: u32,
67
75
  on_completion_ctx: usize,
68
76
  on_completion_fn: tb_completion_t,
69
77
  ) tb_status_t {
70
- var init_fn = DefaultContext.init;
71
- // if (addresses_len == 0) {
72
- // init_fn = TestingContext.init;
73
- // }
78
+ return init(
79
+ DefaultContext,
80
+ out_client,
81
+ out_packets,
82
+ cluster_id,
83
+ addresses_ptr,
84
+ addresses_len,
85
+ packets_count,
86
+ on_completion_ctx,
87
+ on_completion_fn,
88
+ );
89
+ }
74
90
 
75
- return (init_fn)(
76
- global_allocator,
91
+ pub export fn tb_client_init_echo(
92
+ out_client: *tb_client_t,
93
+ out_packets: *tb_packet_list_t,
94
+ cluster_id: u32,
95
+ addresses_ptr: [*:0]const u8,
96
+ addresses_len: u32,
97
+ packets_count: u32,
98
+ on_completion_ctx: usize,
99
+ on_completion_fn: tb_completion_t,
100
+ ) tb_status_t {
101
+ return init(
102
+ TestingContext,
77
103
  out_client,
78
104
  out_packets,
79
105
  cluster_id,
80
106
  addresses_ptr,
81
107
  addresses_len,
82
- num_packets,
108
+ packets_count,
83
109
  on_completion_ctx,
84
110
  on_completion_fn,
85
111
  );
86
112
  }
87
113
 
114
+ fn init(
115
+ comptime Context: type,
116
+ out_client: *tb_client_t,
117
+ out_packets: *tb_packet_list_t,
118
+ cluster_id: u32,
119
+ addresses_ptr: [*:0]const u8,
120
+ addresses_len: u32,
121
+ packets_count: u32,
122
+ on_completion_ctx: usize,
123
+ on_completion_fn: tb_completion_t,
124
+ ) tb_status_t {
125
+ const addresses = @ptrCast([*]const u8, addresses_ptr)[0..addresses_len];
126
+ const context = Context.init(
127
+ global_allocator,
128
+ cluster_id,
129
+ addresses,
130
+ packets_count,
131
+ on_completion_ctx,
132
+ on_completion_fn,
133
+ ) catch |err| switch (err) {
134
+ error.Unexpected => return .unexpected,
135
+ error.OutOfMemory => return .out_of_memory,
136
+ error.AddressInvalid => return .address_invalid,
137
+ error.AddressLimitExceeded => return .address_limit_exceeded,
138
+ error.PacketsCountInvalid => return .packets_count_invalid,
139
+ error.SystemResources => return .system_resources,
140
+ error.NetworkSubsystemFailed => return .network_subsystem,
141
+ };
142
+
143
+ out_client.* = context_to_client(&context.implementation);
144
+ var list = tb_packet_list_t{};
145
+ for (context.packets) |*packet| {
146
+ list.push(tb_packet_list_t.from(packet));
147
+ }
148
+
149
+ out_packets.* = list;
150
+ return .success;
151
+ }
152
+
88
153
  pub export fn tb_client_submit(
89
154
  client: tb_client_t,
90
155
  packets: *tb_packet_list_t,
@@ -0,0 +1,135 @@
1
+ const std = @import("std");
2
+ const assert = std.debug.assert;
3
+
4
+ const tb = @import("../tigerbeetle.zig");
5
+ const tb_client = @import("./tb_client.zig");
6
+ const c = @cImport(@cInclude("tb_client.h"));
7
+
8
+ fn to_lowercase(comptime input: []const u8) []const u8 {
9
+ comptime var lowercase: [input.len]u8 = undefined;
10
+ inline for (input) |char, i| {
11
+ const is_uppercase = (char >= 'A') and (char <= 'Z');
12
+ lowercase[i] = char + (@as(u8, @boolToInt(is_uppercase)) * 32);
13
+ }
14
+ return &lowercase;
15
+ }
16
+
17
+ fn to_uppercase(comptime input: []const u8) []const u8 {
18
+ comptime var uppercase: [input.len]u8 = undefined;
19
+ inline for (input) |char, i| {
20
+ const is_lowercase = (char >= 'a') and (char <= 'z');
21
+ uppercase[i] = char - (@as(u8, @boolToInt(is_lowercase)) * 32);
22
+ }
23
+ return &uppercase;
24
+ }
25
+
26
+ fn to_snakecase(comptime input: []const u8) []const u8 {
27
+ comptime var output: []const u8 = &.{};
28
+ inline for (input) |char, i| {
29
+ const is_uppercase = (char >= 'A') and (char <= 'Z');
30
+ if (is_uppercase and i > 0) output = "_" ++ output;
31
+ output = output ++ &[_]u8{char};
32
+ }
33
+ return output;
34
+ }
35
+
36
+ test "valid tb_client.h" {
37
+ @setEvalBranchQuota(10_000);
38
+
39
+ inline for (.{
40
+ .{ tb.Account, "tb_account_t" },
41
+ .{ tb.Transfer, "tb_transfer_t" },
42
+ .{ tb.AccountFlags, "TB_ACCOUNT_FLAGS" },
43
+ .{ tb.TransferFlags, "TB_TRANSFER_FLAGS" },
44
+ .{ tb.CreateAccountResult, "TB_CREATE_ACCOUNT_RESULT" },
45
+ .{ tb.CreateTransferResult, "TB_CREATE_TRANSFER_RESULT" },
46
+ .{ tb.CreateAccountsResult, "tb_create_accounts_result_t" },
47
+ .{ tb.CreateTransfersResult, "tb_create_transfers_result_t" },
48
+
49
+ .{ u128, "tb_uint128_t" },
50
+ .{ tb_client.tb_status_t, "TB_STATUS" },
51
+ .{ tb_client.tb_client_t, "tb_client_t" },
52
+ .{ tb_client.tb_packet_t, "tb_packet_t" },
53
+ .{ tb_client.tb_packet_list_t, "tb_packet_list_t" },
54
+ .{ tb_client.tb_packet_status_t, "TB_PACKET_STATUS" },
55
+ }) |c_export| {
56
+ const ty: type = c_export[0];
57
+ const c_type_name = @as([]const u8, c_export[1]);
58
+ const c_type: type = @field(c, c_type_name);
59
+
60
+ switch (@typeInfo(ty)) {
61
+ .Int => comptime assert(ty == c_type),
62
+ .Pointer => comptime assert(@sizeOf(ty) == @sizeOf(c_type)),
63
+ .Enum => {
64
+ const prefix_offset = comptime std.mem.lastIndexOf(u8, c_type_name, "_").?;
65
+ comptime var c_enum_prefix: []const u8 = c_type_name[0 .. prefix_offset + 1];
66
+ comptime assert(c_type == c_uint);
67
+
68
+ // TB_STATUS is a special case in naming
69
+ if (comptime std.mem.eql(u8, c_type_name, "TB_STATUS")) {
70
+ c_enum_prefix = c_type_name ++ "_";
71
+ }
72
+
73
+ // Compare the enum int values in C to the enum int values in Zig.
74
+ inline for (std.meta.fields(ty)) |field| {
75
+ const c_enum_field = comptime to_uppercase(to_snakecase(field.name));
76
+ const c_value = @field(c, c_enum_prefix ++ c_enum_field);
77
+
78
+ const zig_value = @enumToInt(@field(ty, field.name));
79
+ comptime assert(zig_value == c_value);
80
+ }
81
+ },
82
+ .Struct => |type_info| switch (type_info.layout) {
83
+ .Auto => @compileError("struct must be extern or packed to be used in C"),
84
+ .Packed => {
85
+ const prefix_offset = comptime std.mem.lastIndexOf(u8, c_type_name, "_").?;
86
+ const c_enum_prefix = c_type_name[0 .. prefix_offset + 1];
87
+ comptime assert(c_type == c_uint);
88
+
89
+ inline for (std.meta.fields(ty)) |field| {
90
+ if (comptime !std.mem.eql(u8, field.name, "padding")) {
91
+ // Get the bit value in the C enum.
92
+ const c_enum_field = comptime to_uppercase(to_snakecase(field.name));
93
+ const c_value = @field(c, c_enum_prefix ++ c_enum_field);
94
+
95
+ // Compare the bit value to the packed struct's field.
96
+ comptime var instance = std.mem.zeroes(ty);
97
+ @field(instance, field.name) = true;
98
+ comptime assert(@bitCast(u16, instance) == c_value);
99
+ }
100
+ }
101
+ },
102
+ .Extern => {
103
+ // Ensure structs are effectively the same.
104
+ comptime assert(@sizeOf(ty) == @sizeOf(c_type));
105
+ comptime assert(@alignOf(ty) == @alignOf(c_type));
106
+
107
+ inline for (std.meta.fields(ty)) |field| {
108
+ // In C, packed structs and enums are replaced with integers.
109
+ comptime var field_type = field.field_type;
110
+ switch (@typeInfo(field_type)) {
111
+ .Struct => |info| {
112
+ comptime assert(info.layout == .Packed);
113
+ comptime assert(@sizeOf(field_type) <= @sizeOf(u128));
114
+ field_type = std.meta.Int(.unsigned, @bitSizeOf(field_type));
115
+ },
116
+ .Enum => |info| field_type = info.tag_type,
117
+ else => {},
118
+ }
119
+
120
+ // In C, pointers are opaque so we compare only the field sizes,
121
+ comptime var c_field_type = @TypeOf(@field(@as(c_type, undefined), field.name));
122
+ switch (@typeInfo(c_field_type)) {
123
+ .Pointer => |info| {
124
+ comptime assert(info.size == .C);
125
+ comptime assert(@sizeOf(c_field_type) == @sizeOf(field_type));
126
+ },
127
+ else => comptime assert(c_field_type == field_type),
128
+ }
129
+ }
130
+ },
131
+ },
132
+ else => |i| @compileLog("TODO", i),
133
+ }
134
+ }
135
+ }