[rrd-developers] modified reduce_data()

Alex van den Bogaerdt alex at slot.hollandcasino.nl
Sun Feb 4 19:04:37 MET 2001


Hi,

I spent quite some time on RRDtool now and I am more and more
capable of modifying the source.

While I was doing so, I found a bug in reduce_data() or at least
I think it is one.  Anyway, I completely rewrote it and the
resulting function is included next.  I didn't write it as a
patch, just edit rrd_graph.c and insert it. Rename the original
function to orig_reduce_data() or so :)

One question/problem remains: shouldn't the xff factor be used
in this function ?!?

Please try the new function and let me know if anything is
wrong with it.

Thanks,
Alex

void
reduce_data(
    enum cf_en     cf,         /* which consolidation function ?*/
    unsigned long  cur_step,   /* step the data currently is in */
    time_t         *start,     /* start, end and step as requested ... */
    time_t         *end,       /* ... by the application will be   ... */
    unsigned long  *step,      /* ... adjusted to represent reality    */
    unsigned long  *ds_cnt,    /* number of data sources in file */
    rrd_value_t    **data)     /* two dimensional array containing the data */
{
    int i,reduce_factor = ceil((double)(*step) / (double)cur_step);
    unsigned long col,dst_row,row_cnt,start_offset,end_offset,skiprows=0;
    rrd_value_t    *srcptr,*dstptr;

    (*step) = cur_step*reduce_factor; /* set new step size for reduced data */
    dstptr = *data;
    srcptr = *data;

    /* We were given one extra row at the beginning of the interval.
    ** We also need to return one extra row.  The extra interval is
    ** the one defined by the start time in both cases.  It is not
    ** used when graphing but maybe we can use it while reducing the
    ** data.
    */
    row_cnt = ((*end)-(*start))/cur_step +1;

    /* alter start and end so that they are multiples of the new steptime.
    ** End will be shifted towards the future and start will be shifted
    ** towards the past in order to include the requested interval
    */ 
    end_offset = (*end) % (*step);
    if (end_offset) end_offset = (*step)-end_offset;
    start_offset = (*start) % (*step);
    (*end) = (*end)+end_offset;
    (*start) = (*start)-start_offset;

    /* The first destination row is unknown yet it still needs
    ** to be present in the returned data.  Skip it.
    ** Don't make it NaN or we might overwrite the source.
    */
    dstptr += (*ds_cnt);

    /* Depending on the amount of extra data needed at the
    ** start of the destination, three things can happen:
    ** -1- start_offset == 0:  skip the extra source row
    ** -2- start_offset == cur_step: do nothing
    ** -3- start_offset > cur_step: skip some source rows and 
    **                      fill one destination row with NaN
    */
    if (start_offset==0) {
	srcptr+=(*ds_cnt);
	row_cnt--;
    } else if (start_offset!=cur_step) {
	skiprows=((*step)-start_offset)/cur_step+1;
	srcptr += ((*ds_cnt)*skiprows);
	row_cnt-=skiprows;
	for (col=0;col<(*ds_cnt);col++) *dstptr++=DNAN;
    }

    /* If we had to alter the endtime, there won't be
    ** enough data to fill the last row.  This means
    ** we have to skip some rows at the end
    */
    if (end_offset) {
	skiprows = ((*step)-end_offset)/cur_step;
	row_cnt-=skiprows;
    }

    /* Now combine reduce_factor intervals at a time
    ** into one interval for the destination.
    */

/* Sanity check: row_cnt should be multiple of reduce_factor */
    if (row_cnt%reduce_factor) {
	printf("SANITY CHECK: %lu rows cannot be reduced by %i \n",
				row_cnt,reduce_factor);
	printf("BUG in reduce_data()\n");
	exit(1);
    }

    for (dst_row=0;row_cnt>=reduce_factor;dst_row++) {
	for (col=0;col<(*ds_cnt);col++) {
	    rrd_value_t newval=DNAN;
	    unsigned long validval=0;

	    for (i=0;i<reduce_factor;i++) {
		if (isnan(srcptr[i*(*ds_cnt)+col])) {
		    continue;
		}
		validval++;
		if (isnan(newval)) newval = srcptr[i*(*ds_cnt)+col];
		else {
		    switch (cf) {
			case CF_AVERAGE:
			    newval += srcptr[i*(*ds_cnt)+col];
			    break;
			case CF_MINIMUM:
			    newval = min (newval,srcptr[i*(*ds_cnt)+col]);
			    break;
			case CF_MAXIMUM:
			    newval = max (newval,srcptr[i*(*ds_cnt)+col]);
			    break;
			case CF_LAST:
			    newval = srcptr[i*(*ds_cnt)+col];
			    break;
		    }
		}
	    }
	    if (validval == 0){newval = DNAN;} else{
		switch (cf) {
		    case CF_AVERAGE:		
			newval /= validval;
			break;
		    case CF_MINIMUM:
		    case CF_MAXIMUM:
		    case CF_LAST:
			break;
		}
	    }
	    *dstptr++=newval;
	}
	srcptr+=(*ds_cnt)*reduce_factor;
	row_cnt-=reduce_factor;
    }

    /* If we had to alter the endtime, we didn't have enough
    ** source rows to fill the last row. Fill it with NaN.
    */
    if (end_offset!=0) for (col=0;col<(*ds_cnt);col++) *dstptr++ = DNAN;
}

--
Unsubscribe mailto:rrd-developers-request at list.ee.ethz.ch?subject=unsubscribe
Help        mailto:rrd-developers-request at list.ee.ethz.ch?subject=help
Archive     http://www.ee.ethz.ch/~slist/rrd-developers
WebAdmin    http://www.ee.ethz.ch/~slist/lsg2.cgi



More information about the rrd-developers mailing list