X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Frmr%2Fcommon%2Fsrc%2Frt_generic_static.c;h=f93963c4a65584158dfd0ba5042b3da5ef6404da;hb=ce1c741c01e8387cb095dac5e36a4d8ad91d006d;hp=bf7bfdc896b5aeb893d7b2a63be2a9826087f4fd;hpb=353bafbe34c601eda6649ea7dcfdcf285d796d5a;p=ric-plt%2Flib%2Frmr.git diff --git a/src/rmr/common/src/rt_generic_static.c b/src/rmr/common/src/rt_generic_static.c index bf7bfdc..f93963c 100644 --- a/src/rmr/common/src/rt_generic_static.c +++ b/src/rmr/common/src/rt_generic_static.c @@ -57,6 +57,7 @@ a current symtab. */ typedef struct thing_list { + int error; // if a realloc failed, this will be set int nalloc; int nused; void** things; @@ -85,6 +86,7 @@ static void ep_stats( void* st, void* entry, char const* name, void* thing, void (*counter)++; } else { rmr_vlog( RMR_VL_DEBUG, "ep_stas: nil counter %p %p %p", st, entry, name ); // dummy refs + return; } rmr_vlog_force( RMR_VL_DEBUG, "rt endpoint: target=%s open=%d\n", ep->name, ep->open ); @@ -208,7 +210,19 @@ static void rt_epcounts( route_table_t* rt, char* id ) { return; } - rmr_sym_foreach_class( rt->hash, 1, ep_counts, id ); // run endpoints in the active table + rmr_sym_foreach_class( rt->ephash, 1, ep_counts, id ); // run endpoints in the active table +} + + +static void dump_tables( uta_ctx_t *ctx ) { + if( ctx->old_rtable != NULL ) { + rmr_vlog_force( RMR_VL_DEBUG, "old route table: (ref_count=%d)\n", ctx->old_rtable->ref_count ); + rt_stats( ctx->old_rtable ); + } else { + rmr_vlog_force( RMR_VL_DEBUG, "old route table was empty\n" ); + } + rmr_vlog_force( RMR_VL_DEBUG, "new route table:\n" ); + rt_stats( ctx->rtable ); } // ------------ route manager communication ------------------------------------------------- @@ -390,6 +404,13 @@ static char* ensure_nlterm( char* buf ) { */ static void roll_tables( uta_ctx_t* ctx ) { + if( ctx->new_rtable == NULL || ctx->new_rtable->error ) { + rmr_vlog( RMR_VL_WARN, "new route table NOT rolled in: nil pointer or error indicated\n" ); + ctx->old_rtable = ctx->new_rtable; + ctx->new_rtable = NULL; + return; + } + if( ctx->rtable != NULL ) { // initially there isn't one, so must check! pthread_mutex_lock( ctx->rtgate ); // must hold lock to move to active ctx->old_rtable = ctx->rtable; // currently active becomes old and allowed to 'drain' @@ -403,6 +424,42 @@ static void roll_tables( uta_ctx_t* ctx ) { ctx->new_rtable = NULL; } +/* + Given a thing list, extend the array of pointers by 1/2 of the current + number allocated. If we cannot realloc an array, then we set the error + flag. Unlikely, but will prevent a crash, AND will prevent us from + trying to use the table since we couldn't capture everything. +*/ +static void extend_things( thing_list_t* tl ) { + int old_alloc; + void* old_things; + void* old_names; + + if( tl == NULL ) { + return; + } + + old_alloc = tl->nalloc; // capture current things + old_things = tl->things; + old_names = tl->names; + + tl->nalloc += tl->nalloc/2; // new allocation size + + tl->things = (void **) malloc( sizeof( void * ) * tl->nalloc ); // allocate larger arrays + tl->names = (const char **) malloc( sizeof( char * ) * tl->nalloc ); + + if( tl->things == NULL || tl->names == NULL ){ // if either failed, then set error + tl->error = 1; + return; + } + + memcpy( tl->things, old_things, sizeof( void * ) * old_alloc ); + memcpy( tl->names, old_names, sizeof( void * ) * old_alloc ); + + free( old_things ); + free( old_names ); +} + // ------------ entry update functions --------------------------------------------------------------- /* Given a message type create a route table entry and add to the hash keyed on the @@ -476,6 +533,8 @@ static void build_entry( uta_ctx_t* ctx, char* ts_field, uint32_t subid, char* r int i; int ngtoks; // number of tokens in the group list int grp; // index into group list + int cgidx; // contiguous group index (prevents the addition of a contiguous group without ep) + int has_ep = FALSE; // indicates if an endpoint was added in a given round robin group ts_field = clip( ts_field ); // ditch extra whitespace and trailing comments rr_field = clip( rr_field ); @@ -495,14 +554,19 @@ static void build_entry( uta_ctx_t* ctx, char* ts_field, uint32_t subid, char* r rte = uta_add_rte( ctx->new_rtable, key, ngtoks ); // get/create entry for this key rte->mtype = atoi( ts_field ); // capture mtype for debugging - for( grp = 0; grp < ngtoks; grp++ ) { - if( (ntoks = uta_rmip_tokenise( gtokens[grp], ctx->ip_list, tokens, 64, ',' )) > 0 ) { // remove any referneces to our ip addrs + for( grp = 0, cgidx = 0; grp < ngtoks; grp++ ) { + if( (ntoks = uta_rmip_tokenise( gtokens[grp], ctx->ip_list, tokens, 64, ',' )) > 0 ) { // remove any references to our ip addrs for( i = 0; i < ntoks; i++ ) { if( strcmp( tokens[i], ctx->my_name ) != 0 ) { // don't add if it is us -- cannot send to ourself if( DEBUG > 1 || (vlevel > 1)) rmr_vlog_force( RMR_VL_DEBUG, "add endpoint ts=%s %s\n", ts_field, tokens[i] ); - uta_add_ep( ctx->new_rtable, rte, tokens[i], grp ); + uta_add_ep( ctx->new_rtable, rte, tokens[i], cgidx ); + has_ep = TRUE; } } + if( has_ep ) { + cgidx++; // only increment to the next contiguous group if the current one has at least one endpoint + has_ep = FALSE; + } } } } @@ -829,18 +893,10 @@ static void parse_rt_rec( uta_ctx_t* ctx, uta_ctx_t* pctx, char* buf, int vleve } if( ctx->new_rtable ) { - if( DEBUG > 1 || (vlevel > 1) ) rmr_vlog( RMR_VL_DEBUG, "end of route table noticed\n" ); roll_tables( ctx ); // roll active to old, and new to active with proper locking - - if( vlevel > 0 ) { - if( ctx->old_rtable != NULL ) { - rmr_vlog_force( RMR_VL_DEBUG, "old route table: (ref_count=%d)\n", ctx->old_rtable->ref_count ); - rt_stats( ctx->old_rtable ); - } else { - rmr_vlog_force( RMR_VL_DEBUG, "old route table was empty\n" ); - } - rmr_vlog_force( RMR_VL_DEBUG, "new route table:\n" ); - rt_stats( ctx->rtable ); + if( DEBUG > 1 || (vlevel > 1) ) { + rmr_vlog( RMR_VL_DEBUG, "end of route table noticed\n" ); + dump_tables( ctx ); } send_rt_ack( pctx, mbuf, ctx->table_id, RMR_OK, NULL ); @@ -925,17 +981,9 @@ static void parse_rt_rec( uta_ctx_t* ctx, uta_ctx_t* pctx, char* buf, int vleve if( ctx->new_rtable ) { roll_tables( ctx ); // roll active to old, and new to active with proper locking - if( DEBUG > 1 || (vlevel > 1) ) rmr_vlog_force( RMR_VL_DEBUG, "end of rt update noticed\n" ); - - if( vlevel > 0 ) { - if( ctx->old_rtable != NULL ) { - rmr_vlog_force( RMR_VL_DEBUG, "old route table: (ref_count=%d)\n", ctx->old_rtable->ref_count ); - rt_stats( ctx->old_rtable ); - } else { - rmr_vlog_force( RMR_VL_DEBUG, "old route table was empty\n" ); - } - rmr_vlog_force( RMR_VL_DEBUG, "updated route table:\n" ); - rt_stats( ctx->rtable ); + if( DEBUG > 1 || (vlevel > 1) ) { + rmr_vlog_force( RMR_VL_DEBUG, "end of rt update noticed\n" ); + dump_tables( ctx ); } send_rt_ack( pctx, mbuf, ctx->table_id, RMR_OK, NULL ); @@ -1028,7 +1076,7 @@ static void read_static_rt( uta_ctx_t* ctx, int vlevel ) { } /* - Callback driven for each named thing in a symtab. We collect the pointers to those + Callback driven for each thing in a symtab. We collect the pointers to those things for later use (cloning). */ static void collect_things( void* st, void* entry, char const* name, void* thing, void* vthing_list ) { @@ -1043,8 +1091,12 @@ static void collect_things( void* st, void* entry, char const* name, void* thing return; } - tl->names[tl->nused] = name; // the name/key + tl->names[tl->nused] = name; // the name/key (space 0 uses int keys, so name can be nil and that is OK) tl->things[tl->nused++] = thing; // save a reference to the thing + + if( tl->nused >= tl->nalloc ) { + extend_things( tl ); // not enough allocated + } } /* @@ -1082,7 +1134,9 @@ static void del_rte( void* st, void* entry, char const* name, void* thing, void* for( i = 0; i < rte->nrrgroups; i++ ) { if( rte->rrgroups[i] ) { free( rte->rrgroups[i]->epts ); // ditch list of endpoint pointers (end points are reused; don't trash them) + free( rte->rrgroups[i] ); // but must free the rrg itself too } + } free( rte->rrgroups ); @@ -1212,24 +1266,47 @@ static route_table_t* rt_clone_space( uta_ctx_t* ctx, route_table_t* srt, route_ things.nalloc = 2048; things.nused = 0; + things.error = 0; things.things = (void **) malloc( sizeof( void * ) * things.nalloc ); - memset( things.things, 0, sizeof( sizeof( void * ) * things.nalloc ) ); things.names = (const char **) malloc( sizeof( char * ) * things.nalloc ); - memset( things.names, 0, sizeof( char * ) * things.nalloc ); - if( things.things == NULL ) { + if( things.things == NULL || things.names == NULL ){ + if( things.things != NULL ) { + free( things.things ); + } + if( things.names != NULL ) { + free( things.names ); + } + if( free_on_err ) { rmr_sym_free( nrt->hash ); free( nrt ); nrt = NULL; + } else { + nrt->error = 1; } return nrt; } + memset( things.things, 0, sizeof( sizeof( void * ) * things.nalloc ) ); + memset( things.names, 0, sizeof( char * ) * things.nalloc ); sst = srt->hash; // convenience pointers (src symtab) nst = nrt->hash; rmr_sym_foreach_class( sst, space, collect_things, &things ); // collect things from this space + if( things.error ) { // something happened and capture failed + rmr_vlog( RMR_VL_ERR, "unable to clone route table: unable to capture old contents\n" ); + free( things.things ); + free( things.names ); + if( free_on_err ) { + rmr_sym_free( nrt->hash ); + free( nrt ); + nrt = NULL; + } else { + nrt->error = 1; + } + return nrt; + } if( DEBUG ) rmr_vlog_force( RMR_VL_DEBUG, "clone space cloned %d things in space %d\n", things.nused, space ); for( i = 0; i < things.nused; i++ ) { @@ -1285,6 +1362,9 @@ static route_table_t* uta_rt_clone( uta_ctx_t* ctx, route_table_t* srt, route_ta If the old table doesn't exist, then a new table is created and the new pointer is set to reference it. + + The ME namespace references endpoints which do not need to be released, therefore we + do not need to run that portion of the table to deref like we do for the RTEs. */ static route_table_t* prep_new_rt( uta_ctx_t* ctx, int all ) { int counter = 0; @@ -1309,12 +1389,20 @@ static route_table_t* prep_new_rt( uta_ctx_t* ctx, int all ) { rmr_sym_foreach_class( rt->hash, 0, del_rte, NULL ); // deref and drop if needed rmr_sym_clear( rt->hash ); // clear all entries from the old table } + + rt->error = 0; // table with errors can be here, so endure clear before attempt to load } else { rt = NULL; } rt = uta_rt_clone( ctx, ctx->rtable, rt, all ); // also sets the ephash pointer - rt->ref_count = 0; // take no chances; ensure it's 0! + if( rt != NULL ) { // very small chance for nil, but not zero, so test + rt->ref_count = 0; // take no chances; ensure it's 0! + } else { + rmr_vlog( RMR_VL_ERR, "route table clone returned nil; marking dummy table as error\n" ); + rt = uta_rt_init( ctx ); // must hav something, but mark it in error state + rt->error = 1; + } return rt; }