[rrd-developers] Re: Creating a rrdtool alter command
Igor Sfiligoi
Igor.Sfiligoi at lnf.infn.it
Wed Mar 10 18:45:46 MET 2004
On Wednesday 10 March 2004 10:55, Stanislav Sinyagin wrote:
> > My plan was to code this as a simple C-based extention of rrdtool.
>
> I wouldn't call it simple, in case if you want it to be a really universal
> tool.
>
> Please keep us updated about your progress, I might give some input or even
> coding (though C is not my favorite).
>
> Regards,
> Stanislav
>
I have a first example code working; just the data source adding.
I am posting it as it is since Stanislav seemed to be interested ;)
rrd_alter.c:
#include "rrd_tool.h"
static int add_ds(char* ds_nam, /* IN */
char* dst, /* IN */
unsigned long u_cnt, /* IN */
rrd_value_t min, /* IN */
rrd_value_t max, /* IN */
rrd_t *rrd, /* IN/OUT */
rrd_value_t* *rra_data /* IN/OUT */
)
{
unsigned long rra_cnt = rrd->stat_head->rra_cnt;
size_t old_ds_cnt = rrd->stat_head->ds_cnt;
size_t new_ds_cnt = old_ds_cnt+1;
int old_rra_els = 0;
int new_rra_els = 0;
rrd_value_t* new_rras;
cdp_prep_t* new_cdp_prep;
int ii;
/* check for duplicate datasource names */
for(ii=0;ii<old_ds_cnt;ii++){
if(strcmp(ds_nam,rrd->ds_def[ii].ds_nam) == 0){
rrd_set_error("Duplicate DS name: %s",ds_nam);
return(-1);
}
}
if((rrd->ds_def = rrd_realloc(rrd->ds_def,
new_ds_cnt*sizeof(ds_def_t)))==NULL){
rrd_set_error("allocating rrd.ds_def");
return(-1);
}
for(ii=0;ii < rra_cnt; ii++) {
old_rra_els += rrd->rra_def[ii].row_cnt * old_ds_cnt;
new_rra_els += rrd->rra_def[ii].row_cnt * new_ds_cnt;
}
if((rrd->ds_def = rrd_realloc(rrd->ds_def,
new_ds_cnt*sizeof(ds_def_t)))==NULL){
rrd_set_error("allocating rrd.ds_def");
return(-1);
}
if((rrd->pdp_prep = rrd_realloc(rrd->pdp_prep,
new_ds_cnt*sizeof(pdp_prep_t)))==NULL){
rrd_set_error("allocating rrd.pdp_prep");
return(-1);
}
if((new_rras = (rrd_value_t *)
malloc(new_rra_els*sizeof(rrd_value_t)))==NULL){
rrd_set_error("allocating rra_data");
return(-1);
}
if((new_cdp_prep = (cdp_prep_t *)
malloc(new_ds_cnt*rra_cnt*sizeof(cdp_prep_t)))==NULL){
rrd_set_error("allocating rrd.cdp_prep");
free(new_rras);
return(-1);
}
/* insert new DS in ds_def */
memset(&rrd->ds_def[old_ds_cnt], 0, sizeof(ds_def_t));
memcpy(rrd->ds_def[old_ds_cnt].ds_nam,ds_nam,DS_NAM_SIZE);
memcpy(rrd->ds_def[old_ds_cnt].dst,dst,DST_SIZE);
rrd->ds_def[old_ds_cnt].par[DS_mrhb_cnt].u_cnt = u_cnt;
rrd->ds_def[old_ds_cnt].par[DS_min_val].u_val = min;
rrd->ds_def[old_ds_cnt].par[DS_max_val].u_val = max;
rrd->stat_head->ds_cnt++;
/* insert new DS in pdp_prep */
memset(&rrd->pdp_prep[old_ds_cnt], 0, sizeof(pdp_prep_t));
strcpy(rrd->pdp_prep[old_ds_cnt].last_ds,"UNKN");
rrd->pdp_prep[old_ds_cnt].scratch[PDP_val].u_val = 0.0;
rrd->pdp_prep[old_ds_cnt].scratch[PDP_unkn_sec_cnt].u_cnt =
rrd->live_head->last_up % rrd->stat_head->pdp_step;
{/* populate the cdp_prep with the old values+UNKN for the new elements */
for(ii=0;ii < rra_cnt;ii++) {
long idx = ii*new_ds_cnt+old_ds_cnt;
memcpy(new_cdp_prep+ii*new_ds_cnt,
rrd->cdp_prep+ii*old_ds_cnt,
old_ds_cnt*sizeof(cdp_prep_t));
new_cdp_prep[idx].scratch[CDP_val].u_val = DNAN;
new_cdp_prep[idx].scratch[CDP_unkn_pdp_cnt].u_cnt =
((rrd->live_head->last_up -
rrd->pdp_prep[idx].scratch[PDP_unkn_sec_cnt].u_cnt)
% (rrd->stat_head->pdp_step
* rrd->rra_def[ii].pdp_cnt)) / rrd->stat_head->pdp_step;
}
free(rrd->cdp_prep);
rrd->cdp_prep = new_cdp_prep;
}
{/* populate the RRAs with the old values+UNKN for the new elements */
rrd_value_t *old_ptr = *rra_data;
rrd_value_t *new_ptr = new_rras;
long i;
for(ii=0;ii < rra_cnt;ii++) {
for (i=0; i<rrd->rra_def[ii].row_cnt; i++) {
memcpy(new_ptr,old_ptr,old_ds_cnt*sizeof(rrd_value_t));
new_ptr+=old_ds_cnt;
old_ptr+=old_ds_cnt;
*new_ptr = DNAN;
new_ptr++;
}
}
free(*rra_data);
*rra_data = new_rras;
}
return 0;
}
int
rrd_alter(int argc, char **argv)
{
char *infilename;
FILE *infile;
rrd_t rrd;
rrd_value_t *rra_data;
int err = 0;
if (argc<2) {
rrd_set_error("wrong number of parameters");
return(-1);
}
infilename=argv[1];
if (rrd_open(infilename, &infile, &rrd, RRD_READWRITE)==-1) {
rrd_set_error("could not open RRD");
return(-1);
}
if (LockRRD(infile) != 0) {
rrd_set_error("could not lock original RRD");
rrd_free(&rrd);
fclose(infile);
return(-1);
}
{
int total_els = 0;
long i;
for(i=0;
i < rrd.stat_head->rra_cnt;
i++)
total_els += rrd.rra_def[i].row_cnt * rrd.stat_head->ds_cnt;
if ((rra_data = (rrd_value_t *)
malloc(total_els*sizeof(rrd_value_t)))==NULL) {
rrd_set_error("allocating rra_data");
rrd_free(&rrd);
fclose(infile);
return(-1);
}
fread(rra_data,sizeof(rrd_value_t),total_els,infile);
}
while (err==0){
static struct option long_options[] =
{
{"data-source-add", required_argument, 0, 's'},
{0,0,0,0}
};
int option_index = 0;
int opt;
opt = getopt_long(argc-1, argv+1, "s:",
long_options, &option_index);
if (opt == EOF)
break;
switch(opt) {
case 's': {/* New DS */
char ds_nam[DS_NAM_SIZE];
char dst[DST_SIZE];
unsigned long u_cnt;
char minstr[20], maxstr[20];
rrd_value_t min,max;
if (sscanf(optarg,
DS_NAM_FMT ":" DST_FMT ":%lu:%18[^:]:%18[^:]",
ds_nam,
dst,
&u_cnt,
minstr,maxstr) == 5){
if (dst_conv(dst) == -1){
rrd_set_error("Invalid DST '%s'",dst);
err = -1;
break;
}
if (minstr[0] == 'U' && minstr[1] == 0)
min = DNAN;
else
min = atof(minstr);
if (maxstr[0] == 'U' && maxstr[1] == 0)
max = DNAN;
else
max = atof(maxstr);
if (! isnan(min) &&
! isnan(max) &&
min >= max ) {
rrd_set_error("min must be less than max in DS definition");
err = -1;
break;
}
err = add_ds(ds_nam,dst,u_cnt,min,max,
&rrd,&rra_data);
} else {
rrd_set_error("Error parsing data source description '%s'",optarg);
err = -1;
break;
}
break;
}
case '?':
if (optopt != 0)
rrd_set_error("unknown option '%c'", optopt);
else
rrd_set_error("unknown option '%s'",argv[optind-1]);
err = -1;
break;
}
}
if (err!=0) {
free(rra_data);
rrd_free(&rrd);
fclose(infile);
return (-1);
}
/* write back the the data */
fseek(infile,0,SEEK_SET);
fwrite(rrd.stat_head, sizeof(stat_head_t), 1, infile);
fwrite(rrd.ds_def, sizeof(ds_def_t), rrd.stat_head->ds_cnt, infile);
fwrite(rrd.rra_def, sizeof(rra_def_t), rrd.stat_head->rra_cnt, infile);
fwrite(rrd.live_head, sizeof(live_head_t),1, infile);
fwrite(rrd.pdp_prep,sizeof(pdp_prep_t),rrd.stat_head->ds_cnt,infile);
fwrite(rrd.cdp_prep,sizeof(cdp_prep_t),
rrd.stat_head->rra_cnt*rrd.stat_head->ds_cnt,infile);
fwrite(rrd.rra_ptr,sizeof(rra_ptr_t),rrd.stat_head->rra_cnt,infile);
{
int total_els = 0;
long i;
for(i=0;
i < rrd.stat_head->rra_cnt;
i++)
total_els += rrd.rra_def[i].row_cnt * rrd.stat_head->ds_cnt;
fwrite(rra_data,sizeof(rrd_value_t),total_els,infile);
}
fflush(infile);
ftruncate(fileno(infile),ftell(infile));
fclose(infile);
return 0;
}
--
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