Line data Source code
1 : #include "../fd_util.h"
2 : #include "fd_wksp_private.h"
3 :
4 : #if FD_HAS_HOSTED
5 :
6 : /* TODO: add owner query */
7 :
8 : #include <stdio.h>
9 : #include <errno.h>
10 : #include <unistd.h>
11 : #include <fcntl.h>
12 : #include <sys/stat.h>
13 :
14 : FD_IMPORT_CSTR( fd_wksp_ctl_help, "src/util/wksp/fd_wksp_ctl_help" );
15 :
16 : /* fd_printf_wksp pretty prints the detailed workspace state to file.
17 : Includes detailed metadata integrity checking. Return value
18 : semantics are the same as for fprintf. */
19 :
20 : static int
21 : fprintf_wksp( FILE * file,
22 36 : fd_wksp_t * wksp ) {
23 :
24 36 : if( FD_UNLIKELY( !file ) ) {
25 0 : FD_LOG_WARNING(( "NULL file" ));
26 0 : return -1;
27 0 : }
28 :
29 36 : if( FD_UNLIKELY( !wksp ) ) {
30 0 : FD_LOG_WARNING(( "NULL wksp" ));
31 0 : return -1;
32 0 : }
33 :
34 36 : int ret = 0;
35 420 : # define TRAP(x) do { int _err = (x); if( _err<0 ) { fd_wksp_private_unlock( wksp ); return _err; } ret += _err; } while(0)
36 :
37 36 : ulong part_max = wksp->part_max;
38 36 : ulong gaddr_lo = wksp->gaddr_lo;
39 36 : ulong gaddr_hi = wksp->gaddr_hi;
40 :
41 36 : fd_wksp_private_pinfo_t * pinfo = fd_wksp_private_pinfo( wksp );
42 :
43 36 : TRAP( fprintf( file,
44 36 : "wksp %s\n"
45 36 : "\tmagic 0x%016lx\n"
46 36 : "\tseed %u\n"
47 36 : "\tpart_max %lu\n"
48 36 : "\tdata_max %lu\n"
49 36 : "\tgaddr [0x%016lx,0x%016lx)\n",
50 36 : wksp->name, wksp->magic, wksp->seed, part_max, wksp->data_max, gaddr_lo, gaddr_hi ) );
51 :
52 : /* TODO: considering running verify and/or doing extra metadata
53 : integrity checks */
54 :
55 36 : ulong cnt = 0UL;
56 :
57 36 : if( FD_UNLIKELY( fd_wksp_private_lock( wksp ) ) ) { cnt++; TRAP( fprintf( file, "\tlock err\n" ) ); }
58 36 : else {
59 36 : ulong used_cnt = 0UL; ulong free_cnt = 0UL;
60 36 : ulong used_sz = 0UL; ulong free_sz = 0UL;
61 36 : ulong used_max = 0UL; ulong free_max = 0UL;
62 :
63 36 : ulong cycle_tag = wksp->cycle_tag++;
64 :
65 36 : ulong last_i = FD_WKSP_PRIVATE_PINFO_IDX_NULL;
66 36 : ulong last_hi = gaddr_lo;
67 36 : ulong i = fd_wksp_private_pinfo_idx( wksp->part_head_cidx );
68 174 : while( !fd_wksp_private_pinfo_idx_is_null( i ) ) {
69 138 : if( FD_UNLIKELY( i>=part_max ) ) { cnt++; TRAP( fprintf( file, "\tindex err\n" ) ); break; }
70 138 : if( FD_UNLIKELY( pinfo[ i ].cycle_tag==cycle_tag ) ) { cnt++; TRAP( fprintf( file, "\tcycle err\n" ) ); break; }
71 138 : pinfo[ i ].cycle_tag = cycle_tag;
72 :
73 138 : ulong lo = pinfo[ i ].gaddr_lo;
74 138 : ulong hi = pinfo[ i ].gaddr_hi;
75 138 : ulong tag = pinfo[ i ].tag;
76 138 : ulong sz = hi - lo;
77 138 : ulong h = fd_wksp_private_pinfo_idx( pinfo[ i ].prev_cidx );
78 :
79 138 : int used = !!tag;
80 138 : if( used ) {
81 81 : used_cnt++;
82 81 : used_sz += sz;
83 81 : if( sz>used_max ) used_max = sz;
84 81 : } else {
85 57 : free_cnt++;
86 57 : free_sz += sz;
87 57 : if( sz>free_max ) free_max = sz;
88 57 : }
89 :
90 138 : TRAP( fprintf( file, "\tpartition [0x%016lx,0x%016lx) sz %20lu tag %20lu idx %lu", lo, hi, sz, tag, i ) );
91 138 : if( FD_UNLIKELY( h !=last_i ) ) { cnt++; TRAP( fprintf( file, ", link_err" ) ); }
92 138 : if( FD_UNLIKELY( lo!=last_hi ) ) { cnt++; TRAP( fprintf( file, ", adjacent_err" ) ); }
93 138 : if( FD_UNLIKELY( lo>=hi ) ) { cnt++; TRAP( fprintf( file, ", size_err" ) ); }
94 138 : TRAP( fprintf( file, "\n" ) );
95 :
96 138 : last_i = i;
97 138 : last_hi = hi;
98 138 : i = fd_wksp_private_pinfo_idx( pinfo[ i ].next_cidx );
99 138 : }
100 :
101 36 : ulong j = fd_wksp_private_pinfo_idx( wksp->part_tail_cidx );
102 36 : if( FD_UNLIKELY( j!=last_i ) ) { cnt++; TRAP( fprintf( file, "\ttail err\n" ) ); }
103 36 : if( FD_UNLIKELY( gaddr_hi!=last_hi ) ) { cnt++; TRAP( fprintf( file, "\tincomplete err\n" ) ); }
104 :
105 36 : TRAP( fprintf( file, "\t%20lu bytes used (%20lu blocks, largest %20lu bytes)\n", used_sz, used_cnt, used_max ) );
106 36 : TRAP( fprintf( file, "\t%20lu bytes free (%20lu blocks, largest %20lu bytes)\n", free_sz, free_cnt, free_max ) );
107 :
108 36 : fd_wksp_private_unlock( wksp );
109 36 : }
110 :
111 36 : TRAP( fprintf( file, "\t%20lu errors detected\n", cnt ) );
112 36 : # undef TRAP
113 :
114 36 : return ret;
115 36 : }
116 :
117 : static int
118 : fprintf_checkpt( FILE * file,
119 : char const * path,
120 15 : int verbose ) {
121 :
122 138 : # define TRAP(x) do { err = (x); if( FD_UNLIKELY( err<0 ) ) { ret = err; goto done; } ret += err; } while(0)
123 :
124 258 : # define TEST(c) do { if( FD_UNLIKELY( !(c) ) ) { err_info = #c; goto stream_err; } } while(0)
125 :
126 306 : # define RESTORE_ULONG(v) do { \
127 306 : err = fd_wksp_private_restore_ulong( restore, &v ); \
128 306 : if( FD_UNLIKELY( err ) ) { err_info = #v; goto io_err; } \
129 306 : } while(0)
130 :
131 135 : # define RESTORE_CSTR(v,max) do { \
132 135 : err = fd_wksp_private_restore_buf( restore, v, (max)-1UL, &v##_len ); \
133 135 : if( FD_UNLIKELY( err ) ) { err_info = #v; goto io_err; } \
134 135 : v[v##_len] = '\0'; \
135 135 : } while(0)
136 :
137 15 : # define RBUF_ALIGN (4096UL)
138 15 : # define RBUF_FOOTPRINT (65536UL)
139 :
140 15 : int fd = -1;
141 15 : fd_io_buffered_istream_t * restore = NULL;
142 15 : int ret = 0;
143 15 : int err;
144 15 : char const * err_info;
145 15 : uchar rbuf[ RBUF_FOOTPRINT ] __attribute__((aligned( RBUF_ALIGN )));
146 15 : fd_io_buffered_istream_t _restore[1];
147 :
148 15 : TRAP( fprintf( file, "checkpt %s (verbose %i)\n", path, verbose ) );
149 :
150 15 : fd = open( path, O_RDONLY, (mode_t)0 );
151 15 : if( FD_UNLIKELY( fd==-1 ) ) TRAP( fprintf( file, "\topen(O_RDONLY) failed (%i-%s)\n", errno, fd_io_strerror( errno ) ) );
152 :
153 15 : restore = fd_io_buffered_istream_init( _restore, fd, rbuf, RBUF_FOOTPRINT );
154 :
155 15 : ulong magic; RESTORE_ULONG( magic ); TEST( magic ==FD_WKSP_MAGIC );
156 15 : ulong style_ul; RESTORE_ULONG( style_ul ); int style = (int)(uint)style_ul; TEST( style_ul==(ulong)(uint)style );
157 :
158 15 : TRAP( fprintf( file,
159 15 : "\tcheckpt_magic %016lx\n"
160 15 : "\tcheckpt_style %i\n"
161 15 : , magic, style ) );
162 :
163 15 : switch( style ) {
164 :
165 15 : case FD_WKSP_CHECKPT_STYLE_RAW: {
166 :
167 : /* Print out checkpt metadata */
168 :
169 15 : ulong seed_ul; RESTORE_ULONG( seed_ul ); uint seed = (uint)seed_ul; TEST( seed_ul==(ulong)seed );
170 15 : ulong part_max; RESTORE_ULONG( part_max );
171 15 : ulong data_max; RESTORE_ULONG( data_max ); TEST( fd_wksp_footprint( part_max, data_max ) );
172 :
173 15 : ulong ts_ul; RESTORE_ULONG( ts_ul ); long ts = (long)ts_ul; TEST( ts_ul==(ulong)ts );
174 15 : ulong app_id; RESTORE_ULONG( app_id );
175 15 : ulong thread_id; RESTORE_ULONG( thread_id );
176 15 : ulong host_id; RESTORE_ULONG( host_id );
177 15 : ulong cpu_id; RESTORE_ULONG( cpu_id );
178 15 : ulong group_id; RESTORE_ULONG( group_id ); TEST( group_id>=2UL );
179 15 : ulong tid; RESTORE_ULONG( tid );
180 15 : ulong user_id; RESTORE_ULONG( user_id );
181 :
182 15 : char name[ FD_SHMEM_NAME_MAX ]; ulong name_len; RESTORE_CSTR( name, FD_SHMEM_NAME_MAX );
183 15 : TEST( fd_shmem_name_len( name )==name_len );
184 :
185 15 : char app [ FD_LOG_NAME_MAX ]; ulong app_len; RESTORE_CSTR( app, FD_LOG_NAME_MAX ); TEST( strlen( app )==app_len );
186 15 : char thread[ FD_LOG_NAME_MAX ]; ulong thread_len; RESTORE_CSTR( thread, FD_LOG_NAME_MAX ); TEST( strlen( thread )==thread_len );
187 15 : char host [ FD_LOG_NAME_MAX ]; ulong host_len; RESTORE_CSTR( host, FD_LOG_NAME_MAX ); TEST( strlen( host )==host_len );
188 15 : char cpu [ FD_LOG_NAME_MAX ]; ulong cpu_len; RESTORE_CSTR( cpu, FD_LOG_NAME_MAX ); TEST( strlen( cpu )==cpu_len );
189 15 : char group [ FD_LOG_NAME_MAX ]; ulong group_len; RESTORE_CSTR( group, FD_LOG_NAME_MAX ); TEST( strlen( group )==group_len );
190 15 : char user [ FD_LOG_NAME_MAX ]; ulong user_len; RESTORE_CSTR( user, FD_LOG_NAME_MAX ); TEST( strlen( user )==user_len );
191 :
192 15 : char ts_cstr[ FD_LOG_WALLCLOCK_CSTR_BUF_SZ ]; fd_log_wallclock_cstr( ts, ts_cstr );
193 15 : TRAP( fprintf( file,
194 15 : "\tcheckpt_ts %-20li \"%s\"\n"
195 15 : "\tcheckpt_app %-20lu \"%s\"\n"
196 15 : "\tcheckpt_thread %-20lu \"%s\"\n"
197 15 : "\tcheckpt_host %-20lu \"%s\"\n"
198 15 : "\tcheckpt_cpu %-20lu \"%s\"\n"
199 15 : "\tcheckpt_group %-20lu \"%s\"\n"
200 15 : "\tcheckpt_tid %-20lu\n"
201 15 : "\tcheckpt_user %-20lu \"%s\"\n"
202 15 : , ts, ts_cstr, app_id, app, thread_id, thread,
203 15 : host_id, host, cpu_id, cpu, group_id, group, tid, user_id, user ) );
204 :
205 15 : char buf[ 16384 ]; ulong buf_len;
206 15 : RESTORE_CSTR( buf, 16384UL ); TEST( strlen( buf )==buf_len );
207 15 : if( verbose>1 ) TRAP( fprintf( file, "\tcheckpt_build \"%s\"\n", buf ) );
208 :
209 15 : RESTORE_CSTR( buf, 16384UL ); TEST( strlen( buf )==buf_len );
210 15 : TRAP( fprintf( file,
211 15 : "\tcheckpt_info \"%s\"\n"
212 15 : "\tshmem_name \"%s\"\n"
213 15 : , buf, name ) );
214 :
215 15 : if( verbose>0 ) {
216 :
217 12 : TRAP( fprintf( file,
218 12 : "\tseed %-20u\n"
219 12 : "\tpart_max %-20lu\n"
220 12 : "\tdata_max %-20lu\n"
221 12 : , seed, part_max, data_max ) );
222 :
223 12 : ulong data_lo = fd_wksp_private_data_off( part_max );
224 12 : ulong data_hi = data_lo + data_max;
225 :
226 12 : if( verbose>1 ) TRAP( fprintf( file, "\tgaddr [0x%016lx,0x%016lx)\n", data_lo, data_hi ) );
227 :
228 12 : ulong alloc_tot = 0UL;
229 12 : ulong alloc_cnt = 0UL;
230 12 : ulong alloc_big = 0UL;
231 :
232 12 : ulong free_tot = 0UL;
233 12 : ulong free_cnt = 0UL;
234 12 : ulong free_big = 0UL;
235 :
236 12 : ulong free_lo = data_lo;
237 45 : for(;;) {
238 45 : ulong tag; RESTORE_ULONG( tag ); if( !tag ) break;
239 33 : ulong gaddr_lo; RESTORE_ULONG( gaddr_lo );
240 33 : ulong sz; RESTORE_ULONG( sz );
241 :
242 33 : ulong gaddr_hi = gaddr_lo + sz;
243 :
244 33 : TEST( (data_lo<=gaddr_lo) & (gaddr_lo<gaddr_hi) & (gaddr_hi<=data_hi) );
245 :
246 : /* Print out free partition details (implied) */
247 33 : if( free_lo<gaddr_lo ) {
248 9 : ulong free_sz = gaddr_lo - free_lo;
249 9 : if( verbose>1 )
250 6 : TRAP( fprintf( file, "\tpartition [0x%016lx,0x%016lx) sz %20lu tag %20lu\n", free_lo, gaddr_lo, free_sz, 0UL ) );
251 9 : free_tot += free_sz;
252 9 : free_cnt += 1UL;
253 9 : free_big = fd_ulong_max( free_big, free_sz );
254 9 : }
255 33 : free_lo = gaddr_hi;
256 :
257 : /* Print out allocated partition details (explicit) */
258 33 : if( verbose>1 )
259 21 : TRAP( fprintf( file, "\tpartition [0x%016lx,0x%016lx) sz %20lu tag %20lu\n", gaddr_lo, gaddr_hi, sz, tag ) );
260 33 : alloc_cnt += 1UL;
261 33 : alloc_tot += sz;
262 33 : alloc_big = fd_ulong_max( alloc_big, sz );
263 :
264 : /* Skip over partition data */
265 33 : int err = fd_io_buffered_istream_skip( restore, sz );
266 33 : if( FD_UNLIKELY( err ) ) { err_info = "partition data"; goto io_err; }
267 33 : }
268 :
269 : /* Print out any last free partition details (implied) */
270 12 : if( free_lo<data_hi ) {
271 12 : ulong free_sz = data_hi - free_lo;
272 12 : if( verbose>1 )
273 9 : TRAP( fprintf( file, "\tpartition [0x%016lx,0x%016lx) sz %20lu tag %20lu\n", free_lo, data_hi, free_sz, 0UL ) );
274 12 : free_tot += free_sz;
275 12 : free_cnt += 1UL;
276 12 : free_big = fd_ulong_max( free_big, free_sz );
277 12 : }
278 :
279 12 : TRAP( fprintf( file, "\t%20lu bytes used (%20lu blocks, largest %20lu bytes)\n"
280 12 : "\t%20lu bytes free (%20lu blocks, largest %20lu bytes)\n"
281 12 : "\t%20lu errors detected\n"
282 12 : , alloc_tot, alloc_cnt, alloc_big, free_tot, free_cnt, free_big, 0UL /* no err if we got here */ ) );
283 12 : }
284 :
285 15 : break;
286 15 : } /* FD_WKSP_CHECKPT_STYLE_RAW */
287 :
288 15 : default:
289 0 : err_info = "unsupported style";
290 0 : goto stream_err;
291 15 : }
292 :
293 15 : done:
294 15 : if( FD_LIKELY( restore ) ) fd_io_buffered_istream_fini( restore );
295 15 : if( FD_LIKELY( fd!=-1 ) ) close( fd ); /* TODO: Consider trapping (but we might be in a fprintf err) */
296 15 : fflush( file ); /* TODO: Consider trapping (but we might be in a fprintf err) */
297 15 : return ret;
298 :
299 0 : io_err:
300 0 : if( err<0 ) TRAP( fprintf( file, "\tFAIL: io: %s (unexpected end of file)\n", err_info ) );
301 0 : else TRAP( fprintf( file, "\tFAIL: io: %s (%i-%s)\n", err_info, err, fd_io_strerror( err ) ) );
302 0 : goto done;
303 :
304 0 : stream_err:
305 0 : TRAP( fprintf( file, "\tFAIL: stream: %s\n", err_info ) );
306 0 : goto done;
307 :
308 0 : # undef RBUF_FOOTPRINT
309 0 : # undef RBUF_ALIGN
310 0 : # undef RESTORE_CSTR
311 0 : # undef RESTORE_ULONG
312 0 : # undef TEST
313 0 : # undef TRAP
314 :
315 0 : }
316 :
317 : int
318 : main( int argc,
319 108 : char ** argv ) {
320 108 : fd_boot( &argc, &argv );
321 765 : # define SHIFT(n) argv+=(n),argc-=(n)
322 :
323 108 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "no arguments" ));
324 108 : char const * bin = argv[0];
325 108 : SHIFT(1);
326 :
327 108 : umask( (mode_t)0 ); /* So mode setting gets respected */
328 :
329 108 : ulong tag = 1UL;
330 :
331 108 : int cnt = 0;
332 438 : while( argc ) {
333 330 : char const * cmd = argv[0];
334 330 : SHIFT(1);
335 :
336 330 : if( !strcmp( cmd, "help" ) ) {
337 :
338 3 : fputs( fd_wksp_ctl_help, stdout );
339 :
340 3 : FD_LOG_NOTICE(( "%i: %s: success", cnt, cmd ));
341 :
342 327 : } else if( !strcmp( cmd, "tag" ) ) {
343 :
344 12 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
345 :
346 12 : tag = fd_cstr_to_ulong( argv[0] );
347 :
348 12 : FD_LOG_NOTICE(( "%i: %s %lu: success", cnt, cmd, tag ));
349 12 : SHIFT(1);
350 :
351 315 : } else if( !strcmp( cmd, "new" ) ) {
352 :
353 18 : if( FD_UNLIKELY( argc<5 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
354 :
355 18 : char const * name = argv[0];
356 18 : ulong page_cnt = fd_cstr_to_ulong ( argv[1] );
357 18 : ulong page_sz = fd_cstr_to_shmem_page_sz( argv[2] );
358 18 : char const * seq = argv[3];
359 18 : ulong mode = fd_cstr_to_ulong_octal ( argv[4] );
360 :
361 : /* Partition the pages over the seq */
362 :
363 18 : ulong sub_page_cnt[ 512 ];
364 18 : ulong sub_cpu_idx [ 512 ];
365 18 : ulong sub_cnt = fd_cstr_to_ulong_seq( seq, sub_cpu_idx, 512UL );
366 :
367 18 : if( FD_UNLIKELY( !sub_cnt ) )
368 0 : FD_LOG_ERR(( "%i: %s %s %lu %s %s 0%03lo: empty or invalid cpu sequence\n\t"
369 18 : "Do %s help for help", cnt, cmd, name, page_cnt, argv[2], seq, mode, bin ));
370 :
371 18 : if( FD_UNLIKELY( sub_cnt>512UL ) )
372 0 : FD_LOG_ERR(( "%i: %s %s %lu %s %s 0%03lo: sequence too long, increase limit in fd_wksp_ctl.c\n\t"
373 18 : "Do %s help for help", cnt, cmd, name, page_cnt, argv[2], seq, mode, bin ));
374 :
375 18 : ulong sub_page_min = page_cnt / sub_cnt;
376 18 : ulong sub_page_rem = page_cnt % sub_cnt;
377 36 : for( ulong sub_idx=0UL; sub_idx<sub_cnt; sub_idx++ ) sub_page_cnt[ sub_idx ] = sub_page_min + (ulong)(sub_idx<sub_page_rem);
378 :
379 : /* Create the workspace */
380 :
381 : /* TODO: allow user to specify seed and/or part_max */
382 18 : int err = fd_wksp_new_named( name, page_sz, sub_cnt, sub_page_cnt, sub_cpu_idx, mode, 0U, 0UL ); /* logs details */
383 18 : if( FD_UNLIKELY( err ) )
384 0 : FD_LOG_ERR(( "%i: %s %s %lu %s %s 0%03lo: fd_wksp_new_named failed (%i-%s)\n\t"
385 18 : "Do %s help for help", cnt, cmd, name, page_cnt, argv[2], seq, mode, err, fd_wksp_strerror( err ), bin ));
386 :
387 18 : FD_LOG_NOTICE(( "%i: %s %s %lu %s %s 0%03lo: success", cnt, cmd, name, page_cnt, argv[2], seq, mode ));
388 18 : SHIFT(5);
389 :
390 297 : } else if( !strcmp( cmd, "delete" ) ) {
391 :
392 18 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
393 :
394 18 : char const * name = argv[0];
395 :
396 18 : int err = fd_wksp_delete_named( name );
397 18 : if( FD_UNLIKELY( err ) )
398 0 : FD_LOG_ERR(( "%i: %s %s: fd_wksp_delete_named failed (%i-%s)\n\t"
399 18 : "Do %s help for help", cnt, cmd, name, err, fd_wksp_strerror( err ), bin ));
400 :
401 18 : FD_LOG_NOTICE(( "%i: %s %s: success", cnt, cmd, name ));
402 18 : SHIFT(1);
403 :
404 279 : } else if( !strcmp( cmd, "alloc" ) ) {
405 :
406 27 : if( FD_UNLIKELY( argc<3 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
407 :
408 27 : char const * name = argv[0];
409 27 : ulong align = fd_cstr_to_ulong( argv[1] );
410 27 : ulong sz = fd_cstr_to_ulong( argv[2] );
411 :
412 27 : char name_gaddr[ FD_WKSP_CSTR_MAX ];
413 27 : if( !fd_wksp_cstr_alloc( name, align, sz, tag, name_gaddr ) ) /* logs details */
414 0 : FD_LOG_ERR(( "%i: %s %s %lu %lu %lu: fd_wksp_cstr_alloc failed", cnt, cmd, name, align, sz, tag ));
415 27 : printf( "%s\n", name_gaddr );
416 :
417 27 : FD_LOG_NOTICE(( "%i: %s %s %lu %lu: success", cnt, cmd, name, align, sz ));
418 27 : SHIFT(3);
419 :
420 252 : } else if( !strcmp( cmd, "info" ) ) {
421 :
422 21 : if( FD_UNLIKELY( argc<2 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
423 :
424 21 : char const * name = argv[0];
425 21 : ulong tag = fd_cstr_to_ulong( argv[1] );
426 :
427 21 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
428 21 : if( FD_LIKELY( wksp ) ) {
429 18 : fd_wksp_tag_query_info_t info[1];
430 18 : ulong tag_cnt = tag ? fd_wksp_tag_query( wksp, &tag, 1UL, info, 1UL ) : 0UL; /* logs details */
431 18 : if( tag_cnt ) printf( "%s:%lu %lu\n", name, info->gaddr_lo, info->gaddr_hi - info->gaddr_lo );
432 9 : else printf( "- 0\n" );
433 18 : fd_wksp_detach( wksp ); /* logs details */
434 18 : }
435 :
436 21 : FD_LOG_NOTICE(( "%i: %s %s %lu: success", cnt, cmd, name, tag ));
437 21 : SHIFT(2);
438 :
439 231 : } else if( !strcmp( cmd, "free" ) ) {
440 :
441 9 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
442 :
443 9 : char const * name_gaddr = argv[0];
444 :
445 9 : fd_wksp_cstr_free( name_gaddr ); /* logs details */
446 :
447 9 : FD_LOG_NOTICE(( "%i: %s %s: success", cnt, cmd, name_gaddr )); /* FIXME: HMMM (print success on bad free?) */
448 9 : SHIFT(1);
449 :
450 222 : } else if( !strcmp( cmd, "tag-query" ) ) {
451 :
452 15 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
453 :
454 15 : char const * name_gaddr = argv[0];
455 :
456 15 : printf( "%lu\n", fd_wksp_cstr_tag( name_gaddr ) ); /* logs details */
457 :
458 15 : FD_LOG_NOTICE(( "%i: %s %s: success", cnt, cmd, name_gaddr ));
459 15 : SHIFT(1);
460 :
461 207 : } else if( !strcmp( cmd, "tag-free" ) ) {
462 :
463 21 : if( FD_UNLIKELY( argc<2 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
464 :
465 21 : char const * name = argv[0];
466 21 : ulong tag = fd_cstr_to_ulong( argv[1] );
467 :
468 21 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
469 21 : if( FD_LIKELY( wksp ) ) {
470 18 : fd_wksp_tag_free( wksp, &tag, 1UL ); /* logs details */
471 18 : fd_wksp_detach( wksp ); /* logs details */
472 18 : }
473 :
474 21 : FD_LOG_NOTICE(( "%i: %s %s %lu: success", cnt, cmd, name, tag ));
475 21 : SHIFT(2);
476 :
477 186 : } else if( !strcmp( cmd, "memset" ) ) {
478 :
479 6 : if( FD_UNLIKELY( argc<2 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
480 :
481 6 : char const * name_gaddr = argv[0];
482 6 : int c = fd_cstr_to_int( argv[1] );
483 :
484 6 : fd_wksp_cstr_memset( name_gaddr, c ); /* logs details */
485 :
486 6 : FD_LOG_NOTICE(( "%i: %s %s %i: success", cnt, cmd, name_gaddr, c ));
487 6 : SHIFT(2);
488 :
489 180 : } else if( !strcmp( cmd, "check" ) ) {
490 :
491 66 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
492 :
493 66 : char const * name = argv[0];
494 :
495 66 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
496 66 : if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "%i: %s %s: wksp_attach failed", cnt, cmd, name ));
497 :
498 66 : if( FD_UNLIKELY( fd_wksp_private_lock( wksp ) ) ) FD_LOG_ERR(( "%i: %s %s: failed", cnt, cmd, name )); /* logs details */
499 66 : fd_wksp_private_unlock( wksp );
500 :
501 66 : fd_wksp_detach( wksp ); /* logs details */
502 :
503 66 : FD_LOG_NOTICE(( "%i: %s %s: success", cnt, cmd, name ));
504 66 : SHIFT(1);
505 :
506 114 : } else if( !strcmp( cmd, "verify" ) ) {
507 :
508 3 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
509 :
510 3 : char const * name = argv[0];
511 :
512 3 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
513 3 : if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "%i: %s %s: wksp_attach failed", cnt, cmd, name ));
514 :
515 3 : if( FD_UNLIKELY( fd_wksp_private_lock( wksp ) ) || /* logs details */
516 3 : FD_UNLIKELY( fd_wksp_verify( wksp ) ) ) /* logs details */
517 0 : FD_LOG_ERR(( "%i: %s %s: failed", cnt, cmd, name ));
518 3 : fd_wksp_private_unlock( wksp );
519 :
520 3 : fd_wksp_detach( wksp ); /* logs details */
521 :
522 3 : FD_LOG_NOTICE(( "%i: %s %s: success", cnt, cmd, name ));
523 3 : SHIFT(1);
524 :
525 111 : } else if( !strcmp( cmd, "rebuild" ) ) {
526 :
527 6 : if( FD_UNLIKELY( argc<2 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
528 :
529 6 : char const * name = argv[0];
530 6 : char const * _seed = argv[1];
531 :
532 6 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
533 6 : if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "%i: %s %s %s: wksp_attach failed", cnt, cmd, name, _seed ));
534 :
535 6 : uint seed = strcmp( _seed, "-" ) ? fd_cstr_to_uint( _seed ) : fd_wksp_seed( wksp );
536 :
537 6 : if( FD_UNLIKELY( fd_wksp_private_lock( wksp ) ) || /* logs details */
538 6 : FD_UNLIKELY( fd_wksp_rebuild( wksp, seed ) ) ) /* logs details */
539 0 : FD_LOG_ERR(( "%i: %s %s %u: failed", cnt, cmd, name, seed ));
540 6 : fd_wksp_private_unlock( wksp );
541 :
542 6 : fd_wksp_detach( wksp ); /* logs details */
543 :
544 6 : FD_LOG_NOTICE(( "%i: %s %s %u: success", cnt, cmd, name, seed ));
545 6 : SHIFT(2);
546 :
547 105 : } else if( !strcmp( cmd, "reset" ) ) {
548 :
549 12 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
550 :
551 12 : char const * name = argv[0];
552 :
553 12 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
554 12 : if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "%i: %s %s: wksp_attach failed", cnt, cmd, name ));
555 12 : fd_wksp_reset( wksp, fd_wksp_seed( wksp ) ); /* logs details */
556 12 : fd_wksp_detach( wksp ); /* logs details */
557 :
558 12 : FD_LOG_NOTICE(( "%i: %s %s: success", cnt, cmd, name ));
559 12 : SHIFT(1);
560 :
561 93 : } else if( !strcmp( cmd, "usage" ) ) {
562 :
563 12 : if( FD_UNLIKELY( argc<2 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
564 :
565 12 : char const * name = argv[0];
566 12 : ulong tag = fd_cstr_to_ulong( argv[1] );
567 :
568 12 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
569 12 : if( FD_UNLIKELY( !wksp ) ) fprintf( stdout, "-\n" );
570 9 : else {
571 9 : fd_wksp_usage_t usage[1];
572 9 : fd_wksp_usage( wksp, &tag, 1UL, usage );
573 9 : fprintf( stdout,
574 9 : "wksp %s\n"
575 9 : "\t%20lu bytes max (%lu blocks, %lu blocks max)\n"
576 9 : "\t%20lu bytes used (%lu blocks)\n"
577 9 : "\t%20lu bytes avail (%lu blocks)\n"
578 9 : "\t%20lu bytes w/tag %4lu (%lu blocks)\n",
579 9 : wksp->name,
580 9 : usage->total_sz, usage->total_cnt, usage->total_max,
581 9 : usage->total_sz - usage->free_sz, usage->total_cnt - usage->free_cnt,
582 9 : usage->free_sz, usage->free_cnt,
583 9 : usage->used_sz, tag, usage->used_cnt );
584 9 : fd_wksp_detach( wksp ); /* logs details */
585 9 : }
586 :
587 12 : FD_LOG_NOTICE(( "%i: %s %s %lu: success", cnt, cmd, name, tag ));
588 12 : SHIFT(2);
589 :
590 81 : } else if( !strcmp( cmd, "query" ) ) {
591 :
592 36 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
593 :
594 36 : char const * name = argv[0];
595 :
596 36 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
597 36 : if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "%i: %s %s: wksp_attach failed", cnt, cmd, name ));
598 36 : fprintf_wksp( stdout, wksp ); /* logs details */
599 36 : fd_wksp_detach( wksp ); /* logs details */
600 :
601 36 : FD_LOG_NOTICE(( "%i: %s %s: success", cnt, cmd, name ));
602 36 : SHIFT(1);
603 :
604 45 : } else if( !strcmp( cmd, "checkpt" ) ) {
605 :
606 9 : if( FD_UNLIKELY( argc<5 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
607 :
608 9 : char const * name = argv[0];
609 9 : char const * path = argv[1];
610 9 : ulong mode = fd_cstr_to_ulong_octal( argv[2] );
611 9 : int style = fd_cstr_to_int ( argv[3] );
612 9 : char const * info = argv[4];
613 :
614 9 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
615 9 : if( FD_UNLIKELY( !wksp ) )
616 0 : FD_LOG_ERR(( "%i: %s %s %s 0%03lo %i ...: wksp_attach failed", cnt, cmd, name, path, mode, style ));
617 :
618 9 : int err = fd_wksp_checkpt( wksp, path, mode, style, info ); /* logs details */
619 9 : if( FD_UNLIKELY( err ) )
620 0 : FD_LOG_ERR(( "%i: %s %s %s 0%03lo %i ...: fd_wksp_checkpt failed", cnt, cmd, name, path, mode, style ));
621 :
622 9 : fd_wksp_detach( wksp ); /* logs details */
623 :
624 9 : FD_LOG_NOTICE(( "%i: %s %s %s 0%03lo %i ...: success", cnt, cmd, name, path, mode, style ));
625 9 : SHIFT(5);
626 :
627 36 : } else if( !strcmp( cmd, "checkpt-query" ) ) {
628 :
629 15 : if( FD_UNLIKELY( argc<2 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
630 :
631 15 : char const * path = argv[0];
632 15 : int verbose = fd_cstr_to_int( argv[1] );
633 :
634 15 : fprintf_checkpt( stdout, path, verbose );
635 :
636 15 : FD_LOG_NOTICE(( "%i: %s %s %i: success", cnt, cmd, path, verbose ));
637 15 : SHIFT(2);
638 :
639 21 : } else if( !strcmp( cmd, "restore" ) ) {
640 :
641 21 : if( FD_UNLIKELY( argc<3 ) ) FD_LOG_ERR(( "%i: %s: too few arguments\n\tDo %s help for help", cnt, cmd, bin ));
642 :
643 21 : char const * name = argv[0];
644 21 : char const * path = argv[1];
645 21 : char const * _seed = argv[2];
646 :
647 21 : fd_wksp_t * wksp = fd_wksp_attach( name ); /* logs details */
648 21 : if( FD_UNLIKELY( !wksp ) ) FD_LOG_ERR(( "%i: %s %s %s %s: wksp_attach failed", cnt, cmd, name, path, _seed ));
649 :
650 21 : uint seed = strcmp( _seed, "-" ) ? fd_cstr_to_uint( _seed ) : fd_wksp_seed( wksp );
651 :
652 21 : int err = fd_wksp_restore( wksp, path, seed ); /* logs details */
653 21 : if( FD_UNLIKELY( err ) ) FD_LOG_ERR(( "%i: %s %s %s %u: fd_wksp_restore failed", cnt, cmd, name, path, seed ));
654 :
655 21 : fd_wksp_detach( wksp ); /* logs details */
656 :
657 21 : FD_LOG_NOTICE(( "%i: %s %s %s %u: success", cnt, cmd, name, path, seed ));
658 21 : SHIFT(3);
659 :
660 21 : } else {
661 :
662 0 : FD_LOG_ERR(( "%i: %s: unknown command\n\t"
663 0 : "Do %s help for help", cnt, cmd, bin ));
664 :
665 0 : }
666 330 : cnt++;
667 330 : }
668 :
669 108 : if( FD_UNLIKELY( cnt<1 ) ) FD_LOG_NOTICE(( "processed %i commands\n\tDo %s help for help", cnt, bin ));
670 105 : else FD_LOG_NOTICE(( "processed %i commands", cnt ));
671 :
672 108 : # undef SHIFT
673 108 : fd_halt();
674 108 : return 0;
675 108 : }
676 :
677 : #else
678 :
679 : int
680 : main( int argc,
681 : char ** argv ) {
682 : fd_boot( &argc, &argv );
683 : if( FD_UNLIKELY( argc<1 ) ) FD_LOG_ERR(( "No arguments" ));
684 : if( FD_UNLIKELY( argc>1 ) ) FD_LOG_ERR(( "fd_wksp_ctl not supported on this platform" ));
685 : FD_LOG_NOTICE(( "processed 0 commands" ));
686 : fd_halt();
687 : return 0;
688 : }
689 :
690 : #endif
|