// report our own pass void stats_self_pass( int64_t tval, void *arg ) { char *prfx = ctl->stats->self->prefix; struct timespec now; time_t ts; IOBUF *b; llts( tval, now ); ts = now.tv_sec; b = mem_new_buf( IO_BUF_SZ ); // TODO - more stats // stats types b = stats_report_types( ctl->stats->stats, ts, b ); b = stats_report_types( ctl->stats->adder, ts, b ); b = stats_report_types( ctl->stats->gauge, ts, b ); // memory b = stats_report_mtype( "hosts", ctl->mem->hosts, ts, b ); b = stats_report_mtype( "points", ctl->mem->points, ts, b ); b = stats_report_mtype( "dhash", ctl->mem->dhash, ts, b ); b = stats_report_mtype( "bufs", ctl->mem->iobufs, ts, b ); b = stats_report_mtype( "iolist", ctl->mem->iolist, ts, b ); bprintf( "mem.total.kb %d", ctl->mem->curr_kb ); bprintf( "uptime %.3f", ts_diff( now, ctl->init_time, NULL ) ); io_buf_send( b ); }
// we do integer maths here to avoid creeping // double-precision addition inaccuracies void loop_control( const char *name, loop_call_fn *fp, void *arg, int usec, int flags, int offset ) { int64_t timer, intv, nsec, offs, diff, t, skips, fires; int i, ticks = 1, curr = 0; struct timespec ts; #ifdef DEBUG_LOOPS int64_t marker = 1; #endif // convert to nsec nsec = 1000 * (int64_t) usec; offs = 1000 * (int64_t) offset; // the actual sleep interval may be less // if period is too high intv = nsec; // wind down to an acceptable interval // try to avoid issues while( ( flags & LOOP_TRIM ) && intv > MAX_LOOP_NSEC && intv > offs ) { for( i = 0; i < 8; i++ ) if( ( intv % loop_control_factors[i] ) == 0 ) break; // if we can't find a suitable factor then try 2 // this may introduce long-term instability :-( if( i == 8 ) { warn( "Could not find a suitable prime factor for %s interval nsec.", name ); i = 0; } // and adjust intv /= loop_control_factors[i]; ticks *= loop_control_factors[i]; } if( ticks > 1 ) debug( "Loop %s trimmed from %ld to %ld nsec interval.", name, nsec, intv ); // get the time clock_gettime( CLOCK_REALTIME, &ts ); timer = tsll( ts ); // do we synchronise to a clock? if( flags & LOOP_SYNC ) { t = timer + offs + nsec - ( timer % nsec ); diff = t - timer; timer = t; llts( diff, ts ); nanosleep( &ts, NULL ); debug( "Pushed paper for %d usec to synchronize %s loop.", diff / 1000, name ); } fires = 0; skips = 0; // say a loop has started loop_mark_start( name ); while( ctl->run_flags & RUN_LOOP ) { // decide if we are firing the payload if( ++curr == ticks ) { #ifdef DEBUG_LOOPS if( !( flags & LOOP_SILENT ) ) debug_loop( "Calling payload %s", name ); #endif (*fp)( timer, arg ); fires++; curr = 0; } // roll on the timer timer += intv; // get the current time clock_gettime( CLOCK_REALTIME, &ts ); t = tsll( ts ); // don't do negative sleep if( t < timer ) { // and sleep diff = timer - t; llts( diff, ts ); nanosleep( &ts, NULL ); } else { skips++; #ifdef DEBUG_LOOPS if( skips == marker ) { debug( "Loop %s skips: %ld", name, skips ); marker = marker << 1; } #endif } } // and say it's finished loop_mark_done( name, skips, fires ); }
// every tick, set the time void loop_set_time( int64_t tval, void *arg ) { llts( tval, ctl->curr_time ); }