Esempio n. 1
0
void stats_gauge_pass( int64_t tval, void *arg )
{
	struct timespec tv[4];
	int64_t nsec;
	char *prfx;
	ST_THR *c;
	time_t ts;
	DHASH *d;
	IOBUF *b;
	int i;

	c    = (ST_THR *) arg;
	ts   = (time_t) tvalts( tval );
	prfx = ctl->stats->gauge->prefix;

#ifdef DEBUG
	debug( "[%02d] Gauge claim", c->id );
#endif

	clock_gettime( CLOCK_REALTIME, &(tv[0]) );

	// take the data
	for( i = 0; i < c->conf->hsize; i++ )
		if( ( i % c->max ) == c->id )
			for( d = c->conf->data[i]; d; d = d->next )
				if( d->in.sum.count ) 
				{
					lock_gauge( d );

					d->proc.sum     = d->in.sum;
					// don't reset the gauge, just the count
					d->in.sum.count = 0;

					unlock_gauge( d );
				}
				else if( d->empty >= 0 )
					d->empty++;


#ifdef CALC_JITTER
	clock_gettime( CLOCK_REALTIME, &(tv[1]) );

	// sleep a bit to avoid contention
	usleep( 1000 + ( random( ) % 30011 ) );
#endif

#ifdef DEBUG
	debug( "[%02d] Gauge report", c->id );
#endif

	clock_gettime( CLOCK_REALTIME, &(tv[2]) );

	c->active = 0;
	c->points = 0;

	b = mem_new_buf( IO_BUF_SZ );

	// and report it
	for( i = 0; i < c->conf->hsize; i++ )
		if( ( i % c->max ) == c->id )
			for( d = c->conf->data[i]; d; d = d->next )
			{
				// we report gauges anyway, updated or not
				bprintf( "%s %f", d->path, d->proc.sum.total );

				if( d->proc.sum.count )
				{
					if( d->empty > 0 )
						d->empty = 0;

					// keep count
					c->points += d->proc.sum.count;
					c->active++;

					// and zero that
					d->proc.sum.count = 0;
				}
			}

	clock_gettime( CLOCK_REALTIME, &(tv[3]) );

	if( ctl->stats->self->enable )
	{
		// report some self stats
		prfx = ctl->stats->self->prefix;

		bprintf( "%s.points %d", c->wkrstr, c->points );
		bprintf( "%s.active %d", c->wkrstr, c->active );

		nsec = tsll( tv[0] ) - tval;
		bprintf( "%s.delay %lu", c->wkrstr, nsec / 1000 );

#ifdef CALC_JITTER
		nsec = tsll( tv[1] ) - tsll( tv[0] );
#else
		nsec = tsll( tv[2] ) - tsll( tv[0] );
#endif
		bprintf( "%s.steal %lu", c->wkrstr, nsec / 1000 );

		nsec = tsll( tv[3] ) - tsll( tv[2] );
		bprintf( "%s.stats %lu", c->wkrstr, nsec / 1000 );

		nsec = tsll( tv[3] ) - tval;
		bprintf( "%s.usec %lu",  c->wkrstr, nsec / 1000 );
	}

	io_buf_send( b );
}
Esempio n. 2
0
void stats_stats_pass( int64_t tval, void *arg )
{
	struct timespec tv[4];
	int64_t nsec;
	char *prfx;
	time_t ts;
	ST_THR *c;
	DHASH *d;
	IOBUF *b;
	int i;

	c  = (ST_THR *) arg;
	ts = (time_t) tvalts( tval );

#ifdef DEBUG
	debug( "[%02d] Stats claim", c->id );
#endif

	clock_gettime( CLOCK_REALTIME, &(tv[0]) );

	// take the data
	for( i = 0; i < c->conf->hsize; i++ )
		if( ( i % c->max ) == c->id )
			for( d = c->conf->data[i]; d; d = d->next )
				if( d->in.points )
				{
					lock_stats( d );

					d->proc.points = d->in.points;
					d->in.points   = NULL;

					unlock_stats( d );
				}
				else if( d->empty >= 0 )
					d->empty++;

#ifdef CALC_JITTER
	clock_gettime( CLOCK_REALTIME, &(tv[1]) );

	// sleep a bit to avoid contention
	usleep( 1000 + ( random( ) % 30011 ) );
#endif

#ifdef DEBUG
	debug( "[%02d] Stats report", c->id );
#endif

	clock_gettime( CLOCK_REALTIME, &(tv[2]) );

	c->points = 0;
	c->active = 0;

	b = mem_new_buf( IO_BUF_SZ );

	// and report it
	for( i = 0; i < c->conf->hsize; i++ )
		if( ( i % c->max ) == c->id )
			for( d = c->conf->data[i]; d; d = d->next )
				if( d->proc.points )
				{
					if( d->empty > 0 )
						d->empty = 0;

					// the buffer can get changed during
					// this function
					c->points += stats_report_one( d, c, ts, &b );
					c->active++;
				}

	// and work out how long that took
	clock_gettime( CLOCK_REALTIME, &(tv[3]) );

	if( ctl->stats->self->enable )
	{
		// report some self stats
		prfx = ctl->stats->self->prefix;

		bprintf( "%s.points %d",    c->wkrstr, c->points );
		bprintf( "%s.active %d",    c->wkrstr, c->active );
		bprintf( "%s.workspace %d", c->wkrstr, c->wkspcsz );

		nsec = tsll( tv[0] ) - tval;
		bprintf( "%s.delay %lu",    c->wkrstr, nsec / 1000 );

#ifdef CALC_JITTER
		nsec = tsll( tv[1] ) - tsll( tv[0] );
#else
		nsec = tsll( tv[2] ) - tsll( tv[0] );
#endif
		bprintf( "%s.steal %lu",    c->wkrstr, nsec / 1000 );

		nsec = tsll( tv[3] ) - tsll( tv[2] );
		bprintf( "%s.stats %lu",    c->wkrstr, nsec / 1000 );

		nsec = tsll( tv[3] ) - tval;
		bprintf( "%s.usec %lu",     c->wkrstr, nsec / 1000 );
	}

	io_buf_send( b );
}
Esempio n. 3
0
void stats_adder_pass( int64_t tval, void *arg )
{
	struct timespec tv[4];
	int64_t nsec;
	char *prfx;
	ST_THR *c;
	time_t ts;
	DHASH *d;
	IOBUF *b;
	int i;

	c    = (ST_THR *) arg;
	ts   = (time_t) tvalts( tval );
	prfx = ctl->stats->adder->prefix;

#ifdef DEBUG
	debug( "[%02d] Adder claim", c->id );
#endif

	clock_gettime( CLOCK_REALTIME, &(tv[0]) );

	// take the data
	for( i = 0; i < c->conf->hsize; i++ )
		if( ( i % c->max ) == c->id )
			for( d = c->conf->data[i]; d; d = d->next )
				if( d->in.sum.count > 0 )
				{
					lock_adder( d );

					d->proc.sum     = d->in.sum;
					d->in.sum.total = 0;
					d->in.sum.count = 0;

					unlock_adder( d );
				}
				else if( d->empty >= 0 )
					d->empty++;

	clock_gettime( CLOCK_REALTIME, &(tv[1]) );

	//debug( "[%02d] Unlocking adder lock.", c->id );

	// synth thread is waiting for this
	unlock_stthr( c );

	//debug( "[%02d] Trying to lock synth.", c->id );

	// try to lock the synth thread
	lock_synth( );

	//debug( "[%02d] Unlocking synth.", c->id );

	// and then unlock it
	unlock_synth( );

	//debug( "[%02d] Trying to get our own lock back.", c->id );

	// and lock our own again
	lock_stthr( c );

	//debug( "[%02d] Sleeping a little before processing.", c->id );

#ifdef CALC_JITTER
	// sleep a short time to avoid contention
	usleep( 1000 + ( random( ) % 30011 ) );
#endif

#ifdef DEBUG
	debug( "[%02d] Adder report", c->id );
#endif

	clock_gettime( CLOCK_REALTIME, &(tv[2]) );

	// zero the counters
	c->points = 0;
	c->active = 0;

	b = mem_new_buf( IO_BUF_SZ );

	// and report it
	for( i = 0; i < c->conf->hsize; i++ )
		if( ( i % c->max ) == c->id )
			for( d = c->conf->data[i]; d; d = d->next )
				if( d->proc.sum.count > 0 )
				{
					if( d->empty > 0 )
						d->empty = 0;

					bprintf( "%s %f", d->path, d->proc.sum.total );

					// keep count
					c->points += d->proc.sum.count;
					c->active++;

					// and zero that
					d->proc.sum.count = 0;
				}


	// and work out how long that took
	clock_gettime( CLOCK_REALTIME, &(tv[3]) );

	if( ctl->stats->self->enable )
	{
		// report some self stats
		prfx = ctl->stats->self->prefix;

		bprintf( "%s.points %d", c->wkrstr, c->points );
		bprintf( "%s.active %d", c->wkrstr, c->active );

		nsec = tsll( tv[0] ) - tval;
		bprintf( "%s.delay %lu", c->wkrstr, nsec / 1000 );

		nsec = tsll( tv[1] ) - tsll( tv[0] );
		bprintf( "%s.steal %lu", c->wkrstr, nsec / 1000 );

		nsec = tsll( tv[3] ) - tsll( tv[2] );
		bprintf( "%s.stats %lu", c->wkrstr, nsec / 1000 );

		nsec = tsll( tv[3] ) - tval;
		bprintf( "%s.usec %lu",  c->wkrstr, nsec / 1000 );
	}

	io_buf_send( b );
}
Esempio n. 4
0
// 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 );
}