RIC:1060: Change in PTL
[ric-plt/lib/rmr.git] / src / rmr / common / src / rt_generic_static.c
index 9aa58f1..5baf79a 100644 (file)
@@ -1,4 +1,4 @@
-// :vi sw=4 ts=4 noet:
+ // :vi sw=4 ts=4 noet2
 /*
 ==================================================================================
        Copyright (c) 2019-2020 Nokia
@@ -46,6 +46,8 @@
 #include <unistd.h>
 #include <netdb.h>
 #include <pthread.h>
+#include <immintrin.h>
+#include <stdbool.h>
 
 #include <RIC_message_types.h>         // needed for route manager messages
 
@@ -361,19 +363,26 @@ static void alarm_if_drops( uta_ctx_t* uctx, uta_ctx_t* pctx ) {
                        if( time( NULL ) > ok2clear ) {                 // things still stable after expiry
                                rmr_vlog( RMR_VL_INFO, "drop alarm cleared\n" );
                                alarm_raised = 0;
-                               uta_alarm( pctx, ALARM_DROPS | ALARM_CLEAR, prob_id++, "RMR message dropping has stopped" );
+                               uta_alarm( pctx, ALARM_DROPS | ALARM_CLEAR, prob_id, "RMR message dropping has stopped" );
+                               prob_id++;
                        }
                }
        }
 }
 
 // ---- utility -----------------------------------------------------------------------------------
+
+int isspace_with_fence(int c) {
+       _mm_lfence();
+       return isspace( c );
+}
+
 /*
        Little diddy to trim whitespace and trailing comments. Like shell, trailing comments
        must be at the start of a word (i.e. must be immediatly preceeded by whitespace).
 */
 static char* clip( char* buf ) {
-       char*   tok;
+       char*   tok=NULL;
 
        while( *buf && isspace( *buf ) ) {                                                      // skip leading whitespace
                buf++;
@@ -389,7 +398,7 @@ static char* clip( char* buf ) {
                }
        }
 
-       for( tok = buf + (strlen( buf ) - 1); tok > buf && isspace( *tok ); tok-- );    // trim trailing spaces too
+       for( tok = buf + (strlen( buf ) - 1); tok > buf && isspace_with_fence( *tok ); tok-- ); // trim trailing spaces too
        *(tok+1) = 0;
 
        return buf;
@@ -447,25 +456,19 @@ static char* ensure_nlterm( char* buf ) {
        is no active table (first load), so we have to account for that (no locking).
 */
 static void roll_tables( uta_ctx_t* ctx ) {
-
+       pthread_mutex_lock( ctx->rtgate );                              // must hold lock to move to active
        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
+       }else if( ctx->rtable != NULL ) {                                                       // initially there isn't one, so must check!
                ctx->old_rtable = ctx->rtable;                                  // currently active becomes old and allowed to 'drain'
                ctx->rtable = ctx->new_rtable;                                  // one we've been adding to becomes active
-               pthread_mutex_unlock( ctx->rtgate );
        } else {
                ctx->old_rtable = NULL;                                         // ensure there isn't an old reference
                ctx->rtable = ctx->new_rtable;                          // make new the active one
        }
-
        ctx->new_rtable = NULL;
+       pthread_mutex_unlock( ctx->rtgate );
 }
 
 /*
@@ -574,7 +577,6 @@ static void build_entry( uta_ctx_t* ctx, char* ts_field, uint32_t subid, char* r
        uint64_t key = 0;                       // the symtab key will be mtype or sub_id+mtype
        char*   tokens[128];
        char*   gtokens[64];
-       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)
@@ -599,6 +601,8 @@ static void build_entry( uta_ctx_t* ctx, char* ts_field, uint32_t subid, char* r
                        rte->mtype = atoi( ts_field );                                                                                                  // capture mtype for debugging
 
                        for( grp = 0, cgidx = 0; grp < ngtoks; grp++ ) {
+                               int             i;                                      // avoid sonar grumbling by defining this here
+
                                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
@@ -852,7 +856,7 @@ static void cycle_snarfed_rt( uta_ctx_t* ctx ) {
                return;
        }
 
-       if( (snarf_fname = getenv(  ENV_STASH_RT )) == NULL ) {                 // specific place to stash the rt not given
+       if( (snarf_fname = getenv(  ENV_STASH_RT )) == NULL ) {                         // specific place to stash the rt not given
                if( (seed_fname = getenv( ENV_SEED_RT )) != NULL ) {                    // no seed, we leave in the default file
                        memset( wfname, 0, sizeof( wfname ) );
                        snprintf( wfname, sizeof( wfname ) - 1, "%s.stash", seed_fname );
@@ -861,6 +865,7 @@ static void cycle_snarfed_rt( uta_ctx_t* ctx ) {
        }
 
        if( snarf_fname == NULL ) {
+               rmr_vlog( RMR_VL_DEBUG, "cycle_snarf: no file to save in" );
                return;
        }
 
@@ -891,7 +896,7 @@ static void cycle_snarfed_rt( uta_ctx_t* ctx ) {
        if( ctx->snarf_rt_fd < 0 ) {
                rmr_vlog( RMR_VL_WARN, "rmr_rtc: unable to open trt file: %s: %s\n", tfname, strerror( errno ) );
        } else {
-               if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "rmr_rtc: rt snarf file opened: %s: %s\n", tfname );
+               if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "rmr_rtc: rt snarf file opened: %s\n", tfname );
        }
 }
 
@@ -949,7 +954,7 @@ static void parse_rt_rec( uta_ctx_t* ctx,  uta_ctx_t* pctx, char* buf, int vleve
        int     grp;                                                    // group number
        rtable_ent_t const*     rte;                    // route table entry added
        char*   tokens[128];
-       char*   tok;                                            // pointer into a token or string
+       char*   tok=NULL;                                               // pointer into a token or string
        char    wbuf[1024];
 
        if( ! buf ) {
@@ -964,7 +969,7 @@ static void parse_rt_rec( uta_ctx_t* ctx,  uta_ctx_t* pctx, char* buf, int vleve
        while( *buf && isspace( *buf ) ) {                                                      // skip leading whitespace
                buf++;
        }
-       for( tok = buf + (strlen( buf ) - 1); tok > buf && isspace( *tok ); tok-- );    // trim trailing spaces too
+       for( tok = buf + (strlen( buf ) - 1); tok > buf && isspace_with_fence( *tok ); tok-- ); // trim trailing spaces too
        *(tok+1) = 0;
 
        memset( tokens, 0, sizeof( tokens ) );
@@ -1018,6 +1023,7 @@ static void parse_rt_rec( uta_ctx_t* ctx,  uta_ctx_t* pctx, char* buf, int vleve
 
                                                send_rt_ack( pctx, mbuf, ctx->table_id, RMR_OK, NULL );
                                                ctx->rtable_ready = 1;                                                  // route based sends can now happen
+                                               ctx->flags |= CFL_FULLRT;                                               // indicate we have seen a complete route table
                                        } else {
                                                if( DEBUG > 1 ) rmr_vlog_force( RMR_VL_DEBUG, "end of route table noticed, but one was not started!\n" );
                                                ctx->new_rtable = NULL;
@@ -1079,12 +1085,17 @@ static void parse_rt_rec( uta_ctx_t* ctx,  uta_ctx_t* pctx, char* buf, int vleve
                                break;
 
                        case 'u':                                                                                               // update current table, not a total replacement
+                               if( ! (ctx->flags & CFL_FULLRT) ) {                                     // we cannot update until we have a full table from route generator
+                                       rmr_vlog( RMR_VL_WARN, "route table update ignored: full table not previously recevied" );
+                                       break;
+                               }
+
                                tokens[1] = clip( tokens[1] );
                                if( strcmp( tokens[1], "end" ) == 0 ) {                         // wrap up the table we were building
                                        if( ctx->new_rtable == NULL ) {                                 // update table not in progress
                                                break;
                                        }
-                                       if( ctx && ctx->snarf_rt_fd >= 0 ) {
+                                       if( ctx->snarf_rt_fd >= 0 ) {
                                                cycle_snarfed_rt( ctx );                                        // make it available and open a new one
                                        }
 
@@ -1158,8 +1169,13 @@ static void read_static_rt( uta_ctx_t* ctx, int vlevel ) {
        char*   eor;                            // end of the record
        int             rcount = 0;                     // record count for debug
 
-       if( (fname = getenv( ENV_SEED_RT )) == NULL ) {
-               return;
+       if( (fname = ctx->seed_rt_fname) == NULL ) {
+               if( (fname = getenv( ENV_SEED_RT )) == NULL ) {
+                       return;
+               }
+
+               ctx->seed_rt_fname = strdup( fname );
+               fname = ctx->seed_rt_fname;
        }
 
        if( (fbuf = ensure_nlterm( uta_fib( fname ) ) ) == NULL ) {                     // read file into a single buffer (nil terminated string)
@@ -1347,10 +1363,7 @@ static route_table_t* uta_rt_init( uta_ctx_t* ctx ) {
                return NULL;
        }
 
-       rt->gate = ctx->rtgate;                                         // single mutex needed for all route tables
        rt->ephash = ctx->ephash;                                       // all route tables share a common endpoint hash
-       pthread_mutex_init( rt->gate, NULL );
-
        return rt;
 }
 
@@ -1487,22 +1500,27 @@ static route_table_t* uta_rt_clone( uta_ctx_t* ctx, route_table_t* srt, route_ta
        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;
+       //int counter = 0;
        route_table_t*  rt;
 
        if( ctx == NULL ) {
                return NULL;
        }
 
+       pthread_mutex_lock( ctx->rtgate );
        if( (rt = ctx->old_rtable) != NULL ) {
                ctx->old_rtable = NULL;
-               while( rt->ref_count > 0 ) {                    // wait for all who are using to stop
-                       if( counter++ > 1000 ) {
-                               rmr_vlog( RMR_VL_WARN, "rt_prep_newrt:  internal mishap, ref count on table seems wedged" );
-                               break;
-                       }
 
+               while(  rt->ref_count > 0 ) {                           // wait for all who are using to stop
+                       //if( counter++ > 1000 ) {
+                       //      rmr_vlog( RMR_VL_WARN, "rt_prep_newrt:  internal mishap, ref count on table seems wedged" );
+                       //      break;
+                       //}
+
+                       pthread_mutex_unlock( ctx->rtgate );
                        usleep( 1000 );                                         // small sleep to yield the processer if that is needed
+                       pthread_mutex_lock( ctx->rtgate );
+
                }
 
                if( rt->hash != NULL ) {
@@ -1514,6 +1532,7 @@ static route_table_t* prep_new_rt( uta_ctx_t* ctx, int all ) {
        } else {
                rt = NULL;
        }
+       pthread_mutex_unlock( ctx->rtgate );
 
        rt = uta_rt_clone( ctx, ctx->rtable, rt, all );         // also sets the ephash pointer
        if( rt != NULL ) {                                                                      // very small chance for nil, but not zero, so test
@@ -1665,4 +1684,5 @@ static inline void release_rt( uta_ctx_t* ctx, route_table_t* rt ) {
        }
        pthread_mutex_unlock( ctx->rtgate );
 }
+
 #endif