Line data Source code
1 : #include "../../disco/topo/fd_topo.h"
2 : #include "../../util/pod/fd_pod_format.h"
3 : #include "../../funk/fd_funk.h"
4 : #include "../../flamenco/runtime/fd_hashes.h"
5 : #include "../../flamenco/runtime/fd_txncache.h"
6 : #include "../../flamenco/snapshot/fd_snapshot_create.h"
7 : #include "../../flamenco/runtime/fd_runtime.h"
8 : #include "../../flamenco/runtime/fd_runtime_public.h"
9 :
10 : #include "generated/fd_batch_tile_seccomp.h"
11 :
12 : #include <errno.h>
13 : #include <unistd.h>
14 :
15 0 : #define REPLAY_OUT_IDX (0UL)
16 0 : #define EAH_REPLAY_OUT_SIG (0UL)
17 :
18 0 : #define MEM_FOOTPRINT (8UL<<30)
19 :
20 : struct fd_snapshot_tile_ctx {
21 : /* User defined parameters. */
22 : ulong full_interval;
23 : ulong incremental_interval;
24 : char const * out_dir;
25 :
26 : /* Shared data structures. */
27 : fd_txncache_t * status_cache;
28 : ulong * is_constipated;
29 : fd_funk_t funk[1];
30 :
31 : /* File descriptors used for snapshot generation. */
32 : int tmp_fd;
33 : int tmp_inc_fd;
34 : int full_snapshot_fd;
35 : int incremental_snapshot_fd;
36 :
37 : /* Metadata from the full snapshot used for incremental snapshots. */
38 : ulong last_full_snap_slot;
39 : fd_hash_t last_hash;
40 : ulong last_capitalization;
41 :
42 : /* Replay out link fields for epoch account hash. */
43 : fd_wksp_t * replay_out_mem;
44 : ulong replay_out_chunk;
45 :
46 : fd_wksp_t * runtime_public_wksp;
47 : fd_runtime_public_t * runtime_public;
48 :
49 : /* Bump allocator */
50 : fd_spad_t * spad;
51 : };
52 : typedef struct fd_snapshot_tile_ctx fd_snapshot_tile_ctx_t;
53 :
54 :
55 : FD_FN_CONST static inline ulong
56 0 : scratch_align( void ) {
57 0 : return 128UL;
58 0 : }
59 :
60 : FD_FN_PURE static inline ulong
61 0 : scratch_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) {
62 0 : ulong l = FD_LAYOUT_INIT;
63 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_snapshot_tile_ctx_t), sizeof(fd_snapshot_tile_ctx_t) );
64 0 : l = FD_LAYOUT_APPEND( l, fd_spad_align(), fd_spad_footprint( MEM_FOOTPRINT ) );
65 0 : return FD_LAYOUT_FINI( l, scratch_align() );
66 0 : }
67 :
68 : static void
69 : privileged_init( fd_topo_t * topo FD_PARAM_UNUSED,
70 0 : fd_topo_tile_t * tile ) {
71 :
72 : /* First open the relevant files here. TODO: We eventually want to extend
73 : this to support multiple files. */
74 :
75 0 : char tmp_dir_buf[ FD_SNAPSHOT_DIR_MAX ];
76 0 : int err = snprintf( tmp_dir_buf, FD_SNAPSHOT_DIR_MAX, "%s/%s", tile->batch.out_dir, FD_SNAPSHOT_TMP_ARCHIVE );
77 0 : if( FD_UNLIKELY( err<0 ) ) {
78 0 : FD_LOG_ERR(( "Failed to format directory string" ));
79 0 : }
80 :
81 0 : char tmp_inc_dir_buf[ FD_SNAPSHOT_DIR_MAX ];
82 0 : err = snprintf( tmp_inc_dir_buf, FD_SNAPSHOT_DIR_MAX, "%s/%s", tile->batch.out_dir, FD_SNAPSHOT_TMP_INCR_ARCHIVE );
83 0 : if( FD_UNLIKELY( err<0 ) ) {
84 0 : FD_LOG_ERR(( "Failed to format directory string" ));
85 0 : }
86 :
87 0 : char zstd_dir_buf[ FD_SNAPSHOT_DIR_MAX ];
88 0 : err = snprintf( zstd_dir_buf, FD_SNAPSHOT_DIR_MAX, "%s/%s", tile->batch.out_dir, FD_SNAPSHOT_TMP_FULL_ARCHIVE_ZSTD );
89 0 : if( FD_UNLIKELY( err<0 ) ) {
90 0 : FD_LOG_ERR(( "Failed to format directory string" ));
91 0 : }
92 :
93 0 : char zstd_inc_dir_buf[ FD_SNAPSHOT_DIR_MAX ];
94 0 : err = snprintf( zstd_inc_dir_buf, FD_SNAPSHOT_DIR_MAX, "%s/%s", tile->batch.out_dir, FD_SNAPSHOT_TMP_INCR_ARCHIVE_ZSTD );
95 0 : if( FD_UNLIKELY( err<0 ) ) {
96 0 : FD_LOG_ERR(( "Failed to format directory string" ));
97 0 : }
98 :
99 : /* Create and open the relevant files for snapshots. */
100 :
101 0 : tile->batch.tmp_fd = open( tmp_dir_buf, O_CREAT | O_RDWR | O_TRUNC, 0644 );
102 0 : if( FD_UNLIKELY( tile->batch.tmp_fd==-1 ) ) {
103 0 : FD_LOG_ERR(( "Failed to open and create tarball for file=%s (%i-%s)", tmp_dir_buf, errno, fd_io_strerror( errno ) ));
104 0 : }
105 :
106 0 : tile->batch.tmp_inc_fd = open( tmp_inc_dir_buf, O_CREAT | O_RDWR | O_TRUNC, 0644 );
107 0 : if( FD_UNLIKELY( tile->batch.tmp_inc_fd==-1 ) ) {
108 0 : FD_LOG_ERR(( "Failed to open and create tarball for file=%s (%i-%s)", tmp_inc_dir_buf, errno, fd_io_strerror( errno ) ));
109 0 : }
110 :
111 0 : tile->batch.full_snapshot_fd = open( zstd_dir_buf, O_RDWR | O_CREAT | O_TRUNC, 0644 );
112 0 : if( FD_UNLIKELY( tile->batch.full_snapshot_fd==-1 ) ) {
113 0 : FD_LOG_WARNING(( "Failed to open the snapshot file (%i-%s)", errno, fd_io_strerror( errno ) ));
114 0 : }
115 :
116 0 : tile->batch.incremental_snapshot_fd = open( zstd_inc_dir_buf, O_RDWR | O_CREAT | O_TRUNC, 0644 );
117 0 : if( FD_UNLIKELY( tile->batch.incremental_snapshot_fd==-1 ) ) {
118 0 : FD_LOG_WARNING(( "Failed to open the snapshot file (%i-%s)", errno, fd_io_strerror( errno ) ));
119 0 : }
120 0 : }
121 :
122 : static void
123 : unprivileged_init( fd_topo_t * topo,
124 0 : fd_topo_tile_t * tile ) {
125 :
126 0 : void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id );
127 :
128 0 : if( FD_UNLIKELY( tile->out_cnt!=1UL || strcmp( topo->links[ tile->out_link_id[ REPLAY_OUT_IDX ] ].name, "batch_replay" ) ) ) {
129 0 : FD_LOG_ERR(( "batch tile has none or unexpected output links %lu %s",
130 0 : tile->out_cnt, topo->links[ tile->out_link_id[ REPLAY_OUT_IDX ] ].name ));
131 0 : }
132 :
133 : /**********************************************************************/
134 : /* scratch (bump)-allocate memory owned by the replay tile */
135 : /**********************************************************************/
136 :
137 : /* Do not modify order! This is join-order in unprivileged_init. */
138 :
139 0 : FD_SCRATCH_ALLOC_INIT( l, scratch );
140 0 : fd_snapshot_tile_ctx_t * ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_snapshot_tile_ctx_t), sizeof(fd_snapshot_tile_ctx_t) );
141 0 : memset( ctx, 0, sizeof(fd_snapshot_tile_ctx_t) );
142 0 : void * spad_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_spad_align(), fd_spad_footprint( MEM_FOOTPRINT ) );
143 0 : ulong scratch_alloc_mem = FD_SCRATCH_ALLOC_FINI ( l, scratch_align() );
144 :
145 0 : if( FD_UNLIKELY( scratch_alloc_mem > (ulong)scratch + scratch_footprint(tile) ) ) {
146 0 : FD_LOG_ERR(( "scratch overflow" ));
147 0 : }
148 :
149 0 : ctx->full_interval = tile->batch.full_interval;
150 0 : ctx->incremental_interval = tile->batch.incremental_interval;
151 0 : ctx->out_dir = tile->batch.out_dir;
152 0 : ctx->tmp_fd = tile->batch.tmp_fd;
153 0 : ctx->tmp_inc_fd = tile->batch.tmp_inc_fd;
154 0 : ctx->full_snapshot_fd = tile->batch.full_snapshot_fd;
155 0 : ctx->incremental_snapshot_fd = tile->batch.incremental_snapshot_fd;
156 :
157 : /**********************************************************************/
158 : /* spads */
159 : /**********************************************************************/
160 : /* FIXME: Define a bound for the size of the spad. It likely needs to be
161 : larger than this. */
162 0 : uchar * spad_mem_cur = spad_mem;
163 0 : ctx->spad = fd_spad_join( fd_spad_new( spad_mem_cur, MEM_FOOTPRINT ) );
164 :
165 : /**********************************************************************/
166 : /* funk */
167 : /**********************************************************************/
168 :
169 0 : if( FD_UNLIKELY( !fd_funk_join( ctx->funk, fd_topo_obj_laddr( topo, tile->batch.funk_obj_id ) ) ) ) {
170 0 : FD_LOG_ERR(( "Failed to join database cache" ));
171 0 : }
172 :
173 : /**********************************************************************/
174 : /* status cache */
175 : /**********************************************************************/
176 :
177 0 : ulong status_cache_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "txncache" );
178 0 : if( FD_UNLIKELY( status_cache_obj_id==ULONG_MAX ) ) {
179 0 : FD_LOG_ERR(( "no status cache object id" ));
180 0 : }
181 :
182 0 : ctx->status_cache = fd_txncache_join( fd_topo_obj_laddr( topo, status_cache_obj_id ) );
183 0 : if( FD_UNLIKELY( !ctx->status_cache ) ) {
184 0 : FD_LOG_ERR(( "no status cache" ));
185 0 : }
186 :
187 : /**********************************************************************/
188 : /* constipated fseq */
189 : /**********************************************************************/
190 :
191 0 : ulong constipated_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "constipate" );
192 0 : if( FD_UNLIKELY( constipated_obj_id==ULONG_MAX ) ) {
193 0 : FD_LOG_ERR(( "no constipated object id" ));
194 0 : }
195 0 : ctx->is_constipated = fd_fseq_join( fd_topo_obj_laddr( topo, constipated_obj_id ) );
196 0 : if( FD_UNLIKELY( !ctx->is_constipated ) ) {
197 0 : FD_LOG_ERR(( "replay tile has no constipated fseq" ));
198 0 : }
199 0 : fd_fseq_update( ctx->is_constipated, 0UL );
200 0 : if( FD_UNLIKELY( fd_fseq_query( ctx->is_constipated ) ) ) {
201 0 : FD_LOG_ERR(( "constipated fseq is not zero" ));
202 0 : }
203 :
204 : /**********************************************************************/
205 : /* snapshot */
206 : /**********************************************************************/
207 :
208 : /* Zero init all of the fields used for incremental snapshot generation
209 : that must be persisted across snapshot creation. */
210 :
211 0 : ctx->last_full_snap_slot = 0UL;
212 0 : ctx->last_capitalization = 0UL;
213 0 : fd_memset( &ctx->last_hash, 0, sizeof(fd_hash_t) );
214 :
215 : /****************************************************************************/
216 : /* Replay Tile Link */
217 : /****************************************************************************/
218 :
219 : /* Set up replay output */
220 0 : fd_topo_link_t * replay_out = &topo->links[ tile->out_link_id[ REPLAY_OUT_IDX ] ];
221 0 : ctx->replay_out_mem = topo->workspaces[ topo->objs[ replay_out->dcache_obj_id ].wksp_id ].wksp;
222 0 : ctx->replay_out_chunk = fd_dcache_compact_chunk0( ctx->replay_out_mem, replay_out->dcache );;
223 :
224 : /* replay public setup */
225 0 : ulong replay_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "runtime_pub" );
226 0 : FD_TEST( replay_obj_id!=ULONG_MAX );
227 0 : ctx->runtime_public_wksp = topo->workspaces[ topo->objs[ replay_obj_id ].wksp_id ].wksp;
228 :
229 0 : if( ctx->runtime_public_wksp==NULL ) {
230 0 : FD_LOG_ERR(( "no runtime_public workspace" ));
231 0 : }
232 :
233 0 : ctx->runtime_public = fd_runtime_public_join( fd_topo_obj_laddr( topo, replay_obj_id ) );
234 0 : FD_TEST( ctx->runtime_public!=NULL );
235 0 : }
236 :
237 : static void
238 0 : produce_snapshot( fd_snapshot_tile_ctx_t * ctx, ulong batch_fseq ) {
239 :
240 0 : ulong is_incremental = fd_batch_fseq_is_incremental( batch_fseq );
241 0 : ulong snapshot_slot = fd_batch_fseq_get_slot( batch_fseq );
242 :
243 0 : if( !is_incremental ) {
244 0 : ctx->last_full_snap_slot = snapshot_slot;
245 0 : }
246 :
247 0 : FD_LOG_WARNING(( "Creating snapshot incremental=%lu slot=%lu", is_incremental, snapshot_slot ));
248 :
249 0 : fd_snapshot_ctx_t snapshot_ctx = {
250 0 : .features = &ctx->runtime_public->features,
251 0 : .slot = snapshot_slot,
252 0 : .out_dir = ctx->out_dir,
253 0 : .is_incremental = (uchar)is_incremental,
254 0 : .funk = ctx->funk,
255 0 : .status_cache = ctx->status_cache,
256 0 : .tmp_fd = is_incremental ? ctx->tmp_inc_fd : ctx->tmp_fd,
257 0 : .snapshot_fd = is_incremental ? ctx->incremental_snapshot_fd : ctx->full_snapshot_fd,
258 : /* These parameters are ignored if the snapshot is not incremental. */
259 0 : .last_snap_slot = ctx->last_full_snap_slot,
260 0 : .last_snap_acc_hash = &ctx->last_hash,
261 0 : .last_snap_capitalization = ctx->last_capitalization,
262 0 : .spad = ctx->spad
263 0 : };
264 :
265 : /* If this isn't the first snapshot that this tile is creating, the
266 : permissions should be made to not acessible by users and should be
267 : renamed to the constant file that is expected. */
268 :
269 0 : char proc_filename[ FD_SNAPSHOT_DIR_MAX ];
270 0 : char prev_filename[ FD_SNAPSHOT_DIR_MAX ];
271 0 : char new_filename [ FD_SNAPSHOT_DIR_MAX ];
272 0 : snprintf( proc_filename, FD_SNAPSHOT_DIR_MAX, "/proc/self/fd/%d", is_incremental ? ctx->incremental_snapshot_fd : ctx->full_snapshot_fd );
273 0 : long len = readlink( proc_filename, prev_filename, FD_SNAPSHOT_DIR_MAX );
274 0 : if( FD_UNLIKELY( len<=0L ) ) {
275 0 : FD_LOG_ERR(( "Failed to readlink the snapshot file" ));
276 0 : }
277 0 : prev_filename[ len ] = '\0';
278 :
279 0 : int err = snprintf( new_filename, FD_SNAPSHOT_DIR_MAX, "%s/%s", ctx->out_dir, is_incremental ? FD_SNAPSHOT_TMP_INCR_ARCHIVE_ZSTD : FD_SNAPSHOT_TMP_FULL_ARCHIVE_ZSTD );
280 0 : if( FD_UNLIKELY( err<0 ) ) {
281 0 : FD_LOG_ERR(( "Can't format filename" ));
282 0 : return;
283 0 : }
284 :
285 0 : err = rename( prev_filename, new_filename );
286 0 : if( FD_UNLIKELY( err ) ) {
287 0 : FD_LOG_ERR(( "Failed to rename file from %s to %s", prev_filename, new_filename ));
288 0 : }
289 0 : FD_LOG_NOTICE(( "Renaming file from %s to %s", prev_filename, new_filename ));
290 :
291 0 : err = ftruncate( snapshot_ctx.tmp_fd, 0UL );
292 0 : if( FD_UNLIKELY( err==-1 ) ) {
293 0 : FD_LOG_ERR(( "Failed to truncate the temporary file (%i-%s)", errno, fd_io_strerror( errno ) ));
294 0 : }
295 :
296 0 : err = ftruncate( snapshot_ctx.snapshot_fd, 0UL );
297 0 : if( FD_UNLIKELY( err==-1 ) ) {
298 0 : FD_LOG_ERR(( "Failed to truncate the snapshot file (%i-%s)", errno, fd_io_strerror( errno ) ));
299 0 : }
300 :
301 0 : long seek = lseek( snapshot_ctx.tmp_fd, 0UL, SEEK_SET );
302 0 : if( FD_UNLIKELY( seek!=0L ) ) {
303 0 : FD_LOG_ERR(( "Failed to seek to the beginning of the file" ));
304 0 : }
305 :
306 : /* Now that the files are in an expected state, create the snapshot. */
307 0 : FD_SPAD_FRAME_BEGIN( snapshot_ctx.spad ) {
308 0 : fd_snapshot_create_new_snapshot( &snapshot_ctx, &ctx->last_hash, &ctx->last_capitalization );
309 0 : } FD_SPAD_FRAME_END;
310 :
311 0 : if( is_incremental ) {
312 0 : FD_LOG_NOTICE(( "Done creating a snapshot in %s", snapshot_ctx.out_dir ));
313 0 : FD_LOG_ERR(("Successful exit" ));
314 0 : }
315 :
316 0 : FD_LOG_NOTICE(( "Done creating a snapshot in %s", snapshot_ctx.out_dir ));
317 :
318 : /* At this point the snapshot has been successfully created, so we can
319 : unconstipate funk and any related data structures in the replay tile. */
320 :
321 0 : fd_fseq_update( ctx->is_constipated, 0UL );
322 :
323 0 : }
324 :
325 : static fd_funk_txn_t*
326 0 : get_eah_txn( fd_funk_t * funk, ulong slot ) {
327 :
328 0 : fd_funk_txn_all_iter_t txn_iter[1];
329 0 : for( fd_funk_txn_all_iter_new( funk, txn_iter ); !fd_funk_txn_all_iter_done( txn_iter ); fd_funk_txn_all_iter_next( txn_iter ) ) {
330 0 : fd_funk_txn_t * txn = fd_funk_txn_all_iter_ele( txn_iter );
331 0 : if( txn->xid.ul[0]==slot ) {
332 0 : FD_LOG_NOTICE(( "Found transaction for eah" ));
333 0 : return txn;
334 0 : }
335 0 : }
336 0 : FD_LOG_NOTICE(( "Calculating eah from root" ));
337 0 : return NULL;
338 0 : }
339 :
340 : static void
341 0 : produce_eah( fd_snapshot_tile_ctx_t * ctx, fd_stem_context_t * stem, ulong batch_fseq ) {
342 0 : ulong eah_slot = fd_batch_fseq_get_slot( batch_fseq );
343 :
344 0 : if( FD_FEATURE_ACTIVE_( eah_slot, ctx->runtime_public->features, accounts_lt_hash ) )
345 0 : return;
346 :
347 0 : ulong tsorig = (ulong)fd_frag_meta_ts_comp( fd_tickcount() );
348 :
349 0 : FD_LOG_WARNING(( "Begining to produce epoch account hash in background for slot=%lu", eah_slot ));
350 :
351 : /* TODO: Perhaps it makes sense to factor this out into a function in the
352 : runtime as this could technically be considered a layering violation. */
353 :
354 : /* First, we must retrieve the corresponding slot_bank. We have the guarantee
355 : that the root record is frozen from the replay tile. */
356 :
357 0 : fd_funk_t * funk = ctx->funk;
358 0 : fd_funk_txn_t * eah_txn = get_eah_txn( funk, eah_slot );
359 0 : fd_funk_rec_key_t slot_id = fd_runtime_slot_bank_key();
360 0 : fd_funk_rec_query_t query[1];
361 0 : fd_funk_rec_t const * slot_rec = fd_funk_rec_query_try( funk, eah_txn, &slot_id, query );
362 0 : if( FD_UNLIKELY( !slot_rec ) ) {
363 0 : FD_LOG_ERR(( "Failed to read slot bank record: missing record" ));
364 0 : }
365 0 : void * slot_val = fd_funk_val( slot_rec, fd_funk_wksp( funk ) );
366 :
367 0 : if( FD_UNLIKELY( fd_funk_val_sz( slot_rec )<sizeof(uint) ) ) {
368 0 : FD_LOG_ERR(( "Failed to read slot bank record: empty record" ));
369 0 : }
370 :
371 0 : uint slot_magic = *(uint*)slot_val;
372 0 : FD_SPAD_FRAME_BEGIN( ctx->spad ) {
373 0 : if( FD_UNLIKELY( slot_magic!=FD_RUNTIME_ENC_BINCODE ) ) {
374 0 : FD_LOG_ERR(( "Slot bank record has wrong magic" ));
375 0 : }
376 :
377 0 : int err;
378 0 : fd_slot_bank_t * slot_bank = fd_bincode_decode_spad( slot_bank, ctx->spad, (uchar *)slot_val+sizeof(uint), fd_funk_val_sz( slot_rec )-sizeof(uint), &err );
379 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) {
380 0 : FD_LOG_ERR(( "Failed to read slot bank record: invalid decode" ));
381 0 : continue;
382 0 : }
383 :
384 : /* At this point, calculate the epoch account hash. */
385 :
386 0 : fd_hash_t epoch_account_hash = {0};
387 :
388 0 : fd_accounts_hash( funk, slot_bank, &epoch_account_hash, ctx->spad, &ctx->runtime_public->features, NULL, NULL );
389 :
390 0 : FD_LOG_NOTICE(( "Done computing epoch account hash (%s)", FD_BASE58_ENC_32_ALLOCA( &epoch_account_hash ) ));
391 :
392 : /* Once the hash is calculated, we are ready to push the computed hash
393 : onto the out link to replay. We don't need to add any other information
394 : as this is the only type of message that is transmitted. */
395 :
396 0 : uchar * out_buf = fd_chunk_to_laddr( ctx->replay_out_mem, ctx->replay_out_chunk );
397 0 : fd_memcpy( out_buf, epoch_account_hash.uc, sizeof(fd_hash_t) );
398 0 : ulong tspub = (ulong)fd_frag_meta_ts_comp( fd_tickcount() );
399 0 : fd_stem_publish( stem, 0UL, EAH_REPLAY_OUT_SIG, ctx->replay_out_chunk, sizeof(fd_hash_t), 0UL, tsorig, tspub );
400 :
401 : /* Reset the fseq allowing for the un-constipation of funk and allow for
402 : snapshots to be created again. */
403 :
404 0 : fd_fseq_update( ctx->is_constipated, 0UL );
405 0 : } FD_SPAD_FRAME_END;
406 :
407 0 : FD_TEST( !fd_funk_rec_query_test( query ) );
408 0 : }
409 :
410 : static void
411 : after_credit( fd_snapshot_tile_ctx_t * ctx,
412 : fd_stem_context_t * stem,
413 : int * opt_poll_in FD_PARAM_UNUSED,
414 0 : int * charge_busy FD_PARAM_UNUSED ) {
415 :
416 0 : ulong batch_fseq = fd_fseq_query( ctx->is_constipated );
417 :
418 : /* If batch_fseq == 0, this means that we don't want to calculate/produce
419 : anything. Keep this tile spinning. */
420 0 : if( !batch_fseq ) {
421 0 : return;
422 0 : }
423 :
424 0 : if( fd_batch_fseq_is_snapshot( batch_fseq ) ) {
425 0 : produce_snapshot( ctx, batch_fseq );
426 0 : } else {
427 : // We need features to disable this...
428 0 : produce_eah( ctx, stem, batch_fseq );
429 0 : }
430 0 : }
431 :
432 : static ulong
433 : populate_allowed_seccomp( fd_topo_t const * topo,
434 : fd_topo_tile_t const * tile,
435 : ulong out_cnt,
436 0 : struct sock_filter * out ) {
437 0 : (void)topo;
438 :
439 0 : populate_sock_filter_policy_fd_batch_tile( out_cnt,
440 0 : out,
441 0 : (uint)fd_log_private_logfile_fd(),
442 0 : (uint)tile->batch.tmp_fd,
443 0 : (uint)tile->batch.tmp_inc_fd,
444 0 : (uint)tile->batch.full_snapshot_fd,
445 0 : (uint)tile->batch.incremental_snapshot_fd );
446 0 : return sock_filter_policy_fd_batch_tile_instr_cnt;
447 0 : }
448 :
449 : static ulong
450 : populate_allowed_fds( fd_topo_t const * topo,
451 : fd_topo_tile_t const * tile,
452 : ulong out_fds_cnt,
453 0 : int * out_fds ) {
454 0 : (void)topo;
455 :
456 0 : if( FD_UNLIKELY( out_fds_cnt<2UL ) ) {
457 0 : FD_LOG_ERR(( "out_fds_cnt %lu", out_fds_cnt ));
458 0 : }
459 :
460 0 : ulong out_cnt = 0UL;
461 0 : out_fds[ out_cnt++ ] = 2; /* stderr */
462 0 : if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
463 0 : out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
464 :
465 0 : out_fds[ out_cnt++ ] = tile->batch.tmp_fd;
466 0 : out_fds[ out_cnt++ ] = tile->batch.tmp_inc_fd;
467 0 : out_fds[ out_cnt++ ] = tile->batch.full_snapshot_fd;
468 0 : out_fds[ out_cnt++ ] = tile->batch.incremental_snapshot_fd;
469 0 : return out_cnt;
470 0 : }
471 :
472 0 : #define STEM_BURST (1UL)
473 :
474 0 : #define STEM_CALLBACK_CONTEXT_TYPE fd_snapshot_tile_ctx_t
475 0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_snapshot_tile_ctx_t)
476 :
477 0 : #define STEM_CALLBACK_AFTER_CREDIT after_credit
478 :
479 : #include "../../disco/stem/fd_stem.c"
480 :
481 : fd_topo_run_tile_t fd_tile_batch = {
482 : .name = "batch",
483 : .populate_allowed_seccomp = populate_allowed_seccomp,
484 : .populate_allowed_fds = populate_allowed_fds,
485 : .scratch_align = scratch_align,
486 : .scratch_footprint = scratch_footprint,
487 : .privileged_init = privileged_init,
488 : .unprivileged_init = unprivileged_init,
489 : .run = stem_run,
490 : };
|