|
| 1 | +/* The tower command prints the tower forks tree structure and leaves. |
| 2 | + This is a standalone application that can be run to inspect the tower |
| 3 | + tile's fork structure. */ |
| 4 | + |
| 5 | +#include "../../shared/fd_config.h" /* config_t */ |
| 6 | +#include "../../shared_dev/commands/dev.h" |
| 7 | +#include "../../../discof/tower/fd_tower_tile.c" |
| 8 | +#include "../../../choreo/tower/fd_tower_forks.h" |
| 9 | + |
| 10 | +#include <stdio.h> |
| 11 | +#include <unistd.h> |
| 12 | + |
| 13 | +fd_topo_run_tile_t |
| 14 | +fdctl_tile_run( fd_topo_tile_t const * tile ); |
| 15 | + |
| 16 | +/* ctx_t is defined in fd_tower_tile.c, we just need to access it */ |
| 17 | + |
| 18 | +static void |
| 19 | +tower_ctx_wksp( args_t * args, |
| 20 | + config_t * config, |
| 21 | + ctx_t ** tower_ctx, |
| 22 | + fd_topo_wksp_t ** tower_wksp ) { |
| 23 | + (void)args; |
| 24 | + |
| 25 | + fd_topo_t * topo = &config->topo; |
| 26 | + |
| 27 | + ulong tile_id = fd_topo_find_tile( topo, "tower", 0UL ); |
| 28 | + if( FD_UNLIKELY( tile_id==ULONG_MAX ) ) FD_LOG_ERR(( "tower tile not found" )); |
| 29 | + |
| 30 | + fd_topo_tile_t * tile = &topo->tiles[ tile_id ]; |
| 31 | + |
| 32 | + /* Get the workspace that contains the tile's scratch memory */ |
| 33 | + ulong scratch_wksp_id = topo->objs[ tile->tile_obj_id ].wksp_id; |
| 34 | + if( FD_UNLIKELY( scratch_wksp_id>=topo->wksp_cnt ) ) FD_LOG_ERR(( "invalid workspace id %lu for tile scratch", scratch_wksp_id )); |
| 35 | + |
| 36 | + fd_topo_wksp_t * _tower_wksp = &topo->workspaces[ scratch_wksp_id ]; |
| 37 | + fd_topo_join_workspace( topo, _tower_wksp, FD_SHMEM_JOIN_MODE_READ_ONLY ); |
| 38 | + |
| 39 | + /* Access the tower tile scratch memory where tower_tile_ctx is stored */ |
| 40 | + void * scratch = fd_topo_obj_laddr( topo, tile->tile_obj_id ); |
| 41 | + if( FD_UNLIKELY( !scratch ) ) FD_LOG_ERR(( "Failed to access tower tile scratch memory" )); |
| 42 | + |
| 43 | + FD_SCRATCH_ALLOC_INIT( l, scratch ); |
| 44 | + ctx_t * _tower_ctx = FD_SCRATCH_ALLOC_APPEND( l, alignof(ctx_t), sizeof(ctx_t) ); |
| 45 | + |
| 46 | + *tower_ctx = _tower_ctx; |
| 47 | + *tower_wksp = _tower_wksp; |
| 48 | +} |
| 49 | + |
| 50 | +static void |
| 51 | +print_all_forks( fd_wksp_t * wksp, ctx_t * tower_ctx, fd_forks_t * forks ) { |
| 52 | + printf( "\n[Tower Forks]\n" ); |
| 53 | + printf( "=============\n" ); |
| 54 | + printf( "%-15s | %-15s | %-10s | %-10s\n", "Slot", "Parent Slot", "Voted", "Confirmed" ); |
| 55 | + printf( "%-15s-+-%-15s-+-%-10s-+-%-10s\n", "---------------", "---------------", "----------", "----------" ); |
| 56 | + |
| 57 | + /* Iterate through all map slots */ |
| 58 | + ulong tower_forks_gaddr = fd_wksp_gaddr_fast( tower_ctx->wksp, forks->tower_forks ); |
| 59 | + fd_tower_forks_t * map = (fd_tower_forks_t *)fd_wksp_laddr_fast( wksp, tower_forks_gaddr ); |
| 60 | + ulong slot_count = 0; |
| 61 | + |
| 62 | + for( ulong slot_idx = 0UL; slot_idx < fd_tower_forks_slot_cnt( map ); slot_idx++ ) { |
| 63 | + fd_tower_forks_t * fork = &map[ slot_idx ]; |
| 64 | + /* Check if key is valid (not MAP_KEY_NULL which is ULONG_MAX) */ |
| 65 | + if( !fd_tower_forks_key_inval( fork->slot ) ) { |
| 66 | + printf( "%-15lu | ", fork->slot ); |
| 67 | + if( fork->parent_slot == ULONG_MAX ) { |
| 68 | + printf( "%-15s | ", "NULL" ); |
| 69 | + } else { |
| 70 | + printf( "%-15lu | ", fork->parent_slot ); |
| 71 | + } |
| 72 | + printf( "%-10s | ", fork->voted ? "Yes" : "No" ); |
| 73 | + printf( "%-10s\n", fork->confirmed ? "Yes" : "No" ); |
| 74 | + slot_count++; |
| 75 | + } |
| 76 | + } |
| 77 | + |
| 78 | + printf( "\n[Tower Leaves]\n" ); |
| 79 | + printf( "==============\n" ); |
| 80 | + |
| 81 | + ulong tower_leaves_dlist_gaddr = fd_wksp_gaddr_fast( tower_ctx->wksp, forks->tower_leaves_dlist ); |
| 82 | + fd_tower_leaves_dlist_t * leaves_dlist = (fd_tower_leaves_dlist_t *)fd_wksp_laddr_fast( wksp, tower_leaves_dlist_gaddr ); |
| 83 | + ulong tower_leaves_pool_gaddr = fd_wksp_gaddr_fast( tower_ctx->wksp, forks->tower_leaves_pool ); |
| 84 | + fd_tower_leaf_t * leaves_pool = (fd_tower_leaf_t *)fd_wksp_laddr_fast( wksp, tower_leaves_pool_gaddr ); |
| 85 | + |
| 86 | + ulong leaf_count = 0; |
| 87 | + for( fd_tower_leaves_dlist_iter_t iter = fd_tower_leaves_dlist_iter_fwd_init( leaves_dlist, leaves_pool ); |
| 88 | + !fd_tower_leaves_dlist_iter_done( iter, leaves_dlist, leaves_pool ); |
| 89 | + iter = fd_tower_leaves_dlist_iter_fwd_next( iter, leaves_dlist, leaves_pool ) ) { |
| 90 | + fd_tower_leaf_t * leaf = fd_tower_leaves_dlist_iter_ele( iter, leaves_dlist, leaves_pool ); |
| 91 | + if( FD_LIKELY( leaf ) ) { |
| 92 | + fd_tower_forks_t * fork = fd_tower_forks_query( map, leaf->slot, NULL ); |
| 93 | + printf( "Leaf slot: %lu", leaf->slot ); |
| 94 | + if( fork->voted ) printf( " [voted]" ); |
| 95 | + if( fork->confirmed ) printf( " [confirmed]" ); |
| 96 | + printf( "\n" ); |
| 97 | + leaf_count++; |
| 98 | + } |
| 99 | + } |
| 100 | + printf( "\nTotal leaves: %lu\n", leaf_count ); |
| 101 | + printf( "Total slots: %lu\n", slot_count ); |
| 102 | + printf( "\n" ); |
| 103 | +} |
| 104 | + |
| 105 | +static void |
| 106 | +tower_cmd_fn_forks( args_t * args, |
| 107 | + config_t * config ) { |
| 108 | + ctx_t * tower_ctx; |
| 109 | + fd_topo_wksp_t * tower_wksp; |
| 110 | + tower_ctx_wksp( args, config, &tower_ctx, &tower_wksp ); |
| 111 | + |
| 112 | + ulong forks_laddr = fd_wksp_gaddr_fast( tower_ctx->wksp, tower_ctx->forks ); |
| 113 | + fd_forks_t * forks = (fd_forks_t *)fd_wksp_laddr( tower_wksp->wksp, forks_laddr ); |
| 114 | + |
| 115 | + for( ;; ) { |
| 116 | + print_all_forks( tower_wksp->wksp, tower_ctx, forks ); |
| 117 | + sleep( 1 ); |
| 118 | + } |
| 119 | +} |
| 120 | + |
| 121 | +static const char * HELP = |
| 122 | + "\n\n" |
| 123 | + "usage: tower [-h] {forks}\n" |
| 124 | + "\n" |
| 125 | + "positional arguments:\n" |
| 126 | + " {forks}\n" |
| 127 | + " forks prints the tower forks tree structure and leaves\n" |
| 128 | + "\n" |
| 129 | + "optional arguments:\n" |
| 130 | + " -h, --help show this help message and exit\n"; |
| 131 | + |
| 132 | +static const char * FORKS_HELP = |
| 133 | + "\n\n" |
| 134 | + "usage: tower forks [-h]\n" |
| 135 | + "\n" |
| 136 | + "optional arguments:\n" |
| 137 | + " -h, --help show this help message and exit\n"; |
| 138 | + |
| 139 | +void |
| 140 | +tower_cmd_help( char const * arg ) { |
| 141 | + if ( FD_LIKELY( !arg ) ) FD_LOG_NOTICE(( "%s", HELP )); |
| 142 | + else if ( FD_LIKELY( !strcmp( arg, "forks" ) ) ) FD_LOG_NOTICE(( "%s", FORKS_HELP )); |
| 143 | + else FD_LOG_NOTICE(( "%s", HELP )); |
| 144 | +} |
| 145 | + |
| 146 | +void |
| 147 | +tower_cmd_args( int * pargc, |
| 148 | + char *** pargv, |
| 149 | + args_t * args ) { |
| 150 | + |
| 151 | + /* help */ |
| 152 | + args->tower.help = fd_env_strip_cmdline_contains( pargc, pargv, "--help" ); |
| 153 | + args->tower.help = args->tower.help || fd_env_strip_cmdline_contains( pargc, pargv, "-h" ); |
| 154 | + |
| 155 | + /* positional arg */ |
| 156 | + args->tower.pos_arg = (*pargv)[0]; |
| 157 | + if( FD_UNLIKELY( !args->tower.pos_arg ) ) { |
| 158 | + args->tower.help = 1; |
| 159 | + return; |
| 160 | + } |
| 161 | + |
| 162 | + (*pargc)--; |
| 163 | +} |
| 164 | + |
| 165 | +static void |
| 166 | +tower_cmd_fn( args_t * args, |
| 167 | + config_t * config ) { |
| 168 | + |
| 169 | + if( args->tower.help ) { |
| 170 | + tower_cmd_help( args->tower.pos_arg ); |
| 171 | + return; |
| 172 | + } |
| 173 | + |
| 174 | + if ( !strcmp( args->tower.pos_arg, "forks" ) ) tower_cmd_fn_forks( args, config ); |
| 175 | + else tower_cmd_help( NULL ); |
| 176 | +} |
| 177 | + |
| 178 | +action_t fd_action_tower = { |
| 179 | + .name = "tower", |
| 180 | + .args = tower_cmd_args, |
| 181 | + .fn = tower_cmd_fn, |
| 182 | + .perm = dev_cmd_perm, |
| 183 | +}; |
0 commit comments