コード例 #1
1
ファイル: rrdtoolmodule.c プロジェクト: OPSF/uClinux
static PyObject *
PyRRD_info(PyObject UNUSED(*self), PyObject *args)
{
    PyObject        *r, *t, *ds;
    rrd_t            rrd;
    FILE            *in_file;
    char            *filename;
    unsigned long   i, j;

    if (! PyArg_ParseTuple(args, "s:info", &filename))
        return NULL;

    if (rrd_open(filename, &in_file, &rrd, RRD_READONLY) == -1) {
        PyErr_SetString(ErrorObject, rrd_get_error());
        rrd_clear_error();
        return NULL;
    }
    fclose(in_file);

#define DICTSET_STR(dict, name, value) \
    t = PyString_FromString(value); \
    PyDict_SetItemString(dict, name, t); \
    Py_DECREF(t);

#define DICTSET_CNT(dict, name, value) \
    t = PyInt_FromLong((long)value); \
    PyDict_SetItemString(dict, name, t); \
    Py_DECREF(t);

#define DICTSET_VAL(dict, name, value) \
    t = isnan(value) ? (Py_INCREF(Py_None), Py_None) :  \
        PyFloat_FromDouble((double)value); \
    PyDict_SetItemString(dict, name, t); \
    Py_DECREF(t);

    r = PyDict_New();

    DICTSET_STR(r, "filename", filename);
    DICTSET_STR(r, "rrd_version", rrd.stat_head->version);
    DICTSET_CNT(r, "step", rrd.stat_head->pdp_step);
    DICTSET_CNT(r, "last_update", rrd.live_head->last_up);

    ds = PyDict_New();
    PyDict_SetItemString(r, "ds", ds);
    Py_DECREF(ds);

    for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
        PyObject    *d;

        d = PyDict_New();
        PyDict_SetItemString(ds, rrd.ds_def[i].ds_nam, d);
        Py_DECREF(d);

        DICTSET_STR(d, "ds_name", rrd.ds_def[i].ds_nam);
        DICTSET_STR(d, "type", rrd.ds_def[i].dst);
        DICTSET_CNT(d, "minimal_heartbeat", rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);
        DICTSET_VAL(d, "min", rrd.ds_def[i].par[DS_min_val].u_val);
        DICTSET_VAL(d, "max", rrd.ds_def[i].par[DS_max_val].u_val);
        DICTSET_STR(d, "last_ds", rrd.pdp_prep[i].last_ds);
        DICTSET_VAL(d, "value", rrd.pdp_prep[i].scratch[PDP_val].u_val);
        DICTSET_CNT(d, "unknown_sec", rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
    }

    ds = PyList_New(rrd.stat_head->rra_cnt);
    PyDict_SetItemString(r, "rra", ds);
    Py_DECREF(ds);

    for (i = 0; i < rrd.stat_head->rra_cnt; i++) {
        PyObject    *d, *cdp;

        d = PyDict_New();
        PyList_SET_ITEM(ds, i, d);

        DICTSET_STR(d, "cf", rrd.rra_def[i].cf_nam);
        DICTSET_CNT(d, "rows", rrd.rra_def[i].row_cnt);
        DICTSET_CNT(d, "pdp_per_row", rrd.rra_def[i].pdp_cnt);
        DICTSET_VAL(d, "xff", rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);

        cdp = PyList_New(rrd.stat_head->ds_cnt);
        PyDict_SetItemString(d, "cdp_prep", cdp);
        Py_DECREF(cdp);

        for (j = 0; j < rrd.stat_head->ds_cnt; j++) {
            PyObject    *cdd;

            cdd = PyDict_New();
            PyList_SET_ITEM(cdp, j, cdd);

            DICTSET_VAL(cdd, "value",
                    rrd.cdp_prep[i*rrd.stat_head->ds_cnt+j].scratch[CDP_val].u_val);
            DICTSET_CNT(cdd, "unknown_datapoints",
                    rrd.cdp_prep[i*rrd.stat_head->ds_cnt+j].scratch[CDP_unkn_pdp_cnt].u_cnt);
        }
    }

    rrd_free(&rrd);

    return r;
}
コード例 #2
0
ファイル: rrd_last.c プロジェクト: GrumpyOldTroll/rrdtool
time_t rrd_last_r(
    const char *filename)
{
    time_t    lastup = -1;
    rrd_file_t *rrd_file;

    rrd_t     rrd;

    rrd_init(&rrd);
    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
    if (rrd_file != NULL) {
        lastup = rrd.live_head->last_up;
        rrd_close(rrd_file);
    }
    rrd_free(&rrd);
    return (lastup);
}
コード例 #3
0
ファイル: rrd_last.c プロジェクト: blair/orca
time_t
rrd_last(int argc, char **argv)
{
    FILE	*in_file;
    time_t       lastup;

    rrd_t	 rrd;

    if(argc < 2){
        rrd_set_error("please specify an rrd");
        return(-1);
    }
    if(rrd_open(argv[1], &in_file, &rrd, RRD_READONLY)==-1){
        return(-1);
    }
    lastup = rrd.live_head->last_up;
    rrd_free(&rrd);
    fclose(in_file);
    return(lastup);
}
コード例 #4
0
ファイル: rrd_first.c プロジェクト: GrumpyOldTroll/rrdtool
time_t rrd_first_r(
    const char *filename,
    const int rraindex)
{
    off_t     rra_start, timer;
    time_t    then = -1;
    rrd_t     rrd;
    rrd_file_t *rrd_file;

    rrd_init(&rrd);
    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
    if (rrd_file == NULL) {
        goto err_free;
    }

    if ((rraindex < 0) || (rraindex >= (int) rrd.stat_head->rra_cnt)) {
        rrd_set_error("invalid rraindex number");
        goto err_close;
    }

    rra_start = rrd_file->header_len;
    rrd_seek(rrd_file,
             (rra_start +
              (rrd.rra_ptr[rraindex].cur_row + 1) *
              rrd.stat_head->ds_cnt * sizeof(rrd_value_t)), SEEK_SET);
    timer = -(long)(rrd.rra_def[rraindex].row_cnt - 1);
    if (rrd.rra_ptr[rraindex].cur_row + 1 > rrd.rra_def[rraindex].row_cnt) {
        rrd_seek(rrd_file, rra_start, SEEK_SET);
    }
    then = (rrd.live_head->last_up -
            rrd.live_head->last_up %
            (rrd.rra_def[rraindex].pdp_cnt * rrd.stat_head->pdp_step)) +
        (timer * rrd.rra_def[rraindex].pdp_cnt * rrd.stat_head->pdp_step);
  err_close:
    rrd_close(rrd_file);
  err_free:
    rrd_free(&rrd);
    return (then);
}
コード例 #5
0
ファイル: rrd_dump.c プロジェクト: nirgal/rrdtool-1.x
int rrd_dump_cb_r(
    const char *filename,
    int opt_header,
    rrd_output_callback_t cb,
    void *user)
{
    unsigned int i, ii, ix, iii = 0;
    time_t    now;
    char      somestring[255];
    rrd_value_t my_cdp;
    off_t     rra_base, rra_start, rra_next;
    rrd_file_t *rrd_file;
    rrd_t     rrd;
    rrd_value_t value;
    struct tm tm;

//These two macros are local defines to clean up visible code from its redndancy
//and make it easier to read.
#define CB_PUTS(str)                                            \
    do {							\
        size_t len = strlen(str);				\
								\
        if (cb((str), len, user) != len)                        \
            goto err_out;                                       \
    } while (0);
#define CB_FMTS(...) do {                                       \
    char buffer[256];                                           \
    rrd_snprintf (buffer, sizeof(buffer), __VA_ARGS__);         \
    CB_PUTS (buffer);                                           \
    } while (0)
//These macros are to be undefined at the end of this function

    //Check if we got a (valid) callback method
    if (!cb) {
        return (-1);
    }

    rrd_init(&rrd);

    rrd_file = rrd_open(filename, &rrd, RRD_READONLY | RRD_READAHEAD);
    if (rrd_file == NULL) {
        rrd_free(&rrd);
        return (-1);
    }

    if (opt_header == 1) {
        CB_PUTS("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
        CB_PUTS("<!DOCTYPE rrd SYSTEM \"http://oss.oetiker.ch/rrdtool/rrdtool.dtd\">\n");
        CB_PUTS("<!-- Round Robin Database Dump -->\n");
        CB_PUTS("<rrd>\n");
    } else if (opt_header == 2) {
        CB_PUTS("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
        CB_PUTS("<!-- Round Robin Database Dump -->\n");
        CB_PUTS("<rrd xmlns=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml\" "
                "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
        CB_PUTS("\txsi:schemaLocation=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml "
                "http://oss.oetiker.ch/rrdtool/rrdtool-dump.xsd\">\n");
    } else {
        CB_PUTS("<!-- Round Robin Database Dump -->\n");
        CB_PUTS("<rrd>\n");
    }

    if (atoi(rrd.stat_head->version) <= 3) {
        CB_FMTS("\t<version>%s</version>\n", RRD_VERSION3);
    } else {
        CB_FMTS("\t<version>%s</version>\n", rrd.stat_head->version);
    }
    
    CB_FMTS("\t<step>%lu</step> <!-- Seconds -->\n",
        rrd.stat_head->pdp_step);

#ifdef HAVE_STRFTIME
    localtime_r(&rrd.live_head->last_up, &tm);
    strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %Z", &tm);
#else
# error "Need strftime"
#endif
    CB_FMTS("\t<lastupdate>%lld</lastupdate> <!-- %s -->\n\n",
        (long long int) rrd.live_head->last_up, somestring);
    for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
        CB_PUTS("\t<ds>\n");

        CB_FMTS("\t\t<name> %s </name>\n", rrd.ds_def[i].ds_nam);

        CB_FMTS("\t\t<type> %s </type>\n", rrd.ds_def[i].dst);

        if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
            CB_FMTS("\t\t<minimal_heartbeat>%lu</minimal_heartbeat>\n",
                    rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);

            if (isnan(rrd.ds_def[i].par[DS_min_val].u_val)) {
                CB_PUTS("\t\t<min>NaN</min>\n");
            } else {
                CB_FMTS("\t\t<min>%0.10e</min>\n",
                    rrd.ds_def[i].par[DS_min_val].u_val);
            }
            
            if (isnan(rrd.ds_def[i].par[DS_max_val].u_val)) {
                CB_PUTS("\t\t<max>NaN</max>\n");
            } else {
                CB_FMTS("\t\t<max>%0.10e</max>\n",
                    rrd.ds_def[i].par[DS_max_val].u_val);
            }
        } else {        /* DST_CDEF */
            char     *str = NULL;

            rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),
                rrd.ds_def, &str);

            //Splitting into 3 writes to avoid allocating memory
            //This is better compared to snprintf as str may be of arbitrary size
            CB_PUTS("\t\t<cdef> ");
            CB_PUTS(str);
            CB_PUTS(" </cdef>\n");

            free(str);
        }

        CB_PUTS("\n\t\t<!-- PDP Status -->\n");
        CB_FMTS("\t\t<last_ds>%s</last_ds>\n",
            rrd.pdp_prep[i].last_ds);

        if (isnan(rrd.pdp_prep[i].scratch[PDP_val].u_val)) {
            CB_PUTS("\t\t<value>NaN</value>\n");
        } else {
            CB_FMTS("\t\t<value>%0.10e</value>\n",
                rrd.pdp_prep[i].scratch[PDP_val].u_val);
        }

        CB_FMTS("\t\t<unknown_sec> %lu </unknown_sec>\n",
            rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);

        CB_PUTS("\t</ds>\n\n");
    }

    CB_PUTS("\t<!-- Round Robin Archives -->\n");

    rra_base = rrd_file->header_len;
    rra_next = rra_base;

    for (i = 0; i < rrd.stat_head->rra_cnt; i++) {

        long      timer = 0;

        rra_start = rra_next;
        rra_next += (rrd.stat_head->ds_cnt
                     * rrd.rra_def[i].row_cnt * sizeof(rrd_value_t));

        CB_PUTS("\t<rra>\n");

        CB_FMTS("\t\t<cf>%s</cf>\n", rrd.rra_def[i].cf_nam);

        CB_FMTS("\t\t<pdp_per_row>%lu</pdp_per_row> <!-- %lu seconds -->\n\n",
            rrd.rra_def[i].pdp_cnt, 
            rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);

        /* support for RRA parameters */
        CB_PUTS("\t\t<params>\n");

        switch (cf_conv(rrd.rra_def[i].cf_nam)) {
        case CF_HWPREDICT:
        case CF_MHWPREDICT:
            CB_FMTS("\t\t<hw_alpha>%0.10e</hw_alpha>\n",
                rrd.rra_def[i].par[RRA_hw_alpha].u_val);

            CB_FMTS("\t\t<hw_beta>%0.10e</hw_beta>\n",
                rrd.rra_def[i].par[RRA_hw_beta].u_val);

            CB_FMTS("\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
                rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
            break;
        case CF_SEASONAL:
        case CF_DEVSEASONAL:
            CB_FMTS("\t\t<seasonal_gamma>%0.10e</seasonal_gamma>\n",
                rrd.rra_def[i].par[RRA_seasonal_gamma].u_val);

            CB_FMTS("\t\t<seasonal_smooth_idx>%lu</seasonal_smooth_idx>\n",
                rrd.rra_def[i].par[RRA_seasonal_smooth_idx].u_cnt);

            if (atoi(rrd.stat_head->version) >= 4) {
                CB_FMTS("\t\t<smoothing_window>%0.10e</smoothing_window>\n",
                    rrd.rra_def[i].par[RRA_seasonal_smoothing_window].u_val);
            }

            CB_FMTS("\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
                rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
            break;
        case CF_FAILURES:
            CB_FMTS("\t\t<delta_pos>%0.10e</delta_pos>\n",
                rrd.rra_def[i].par[RRA_delta_pos].u_val);

            CB_FMTS("\t\t<delta_neg>%0.10e</delta_neg>\n",
                rrd.rra_def[i].par[RRA_delta_neg].u_val);

            CB_FMTS("\t\t<window_len>%lu</window_len>\n",
                rrd.rra_def[i].par[RRA_window_len].u_cnt);

            CB_FMTS("\t\t<failure_threshold>%lu</failure_threshold>\n",
                rrd.rra_def[i].par[RRA_failure_threshold].u_cnt);

            /* fall thru */
        case CF_DEVPREDICT:
            CB_FMTS("\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
                rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
            break;
        case CF_AVERAGE:
        case CF_MAXIMUM:
        case CF_MINIMUM:
        case CF_LAST:
        default:
            CB_FMTS("\t\t<xff>%0.10e</xff>\n",
                rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
            break;
        }

        CB_PUTS("\t\t</params>\n");
        CB_PUTS("\t\t<cdp_prep>\n");

        for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++) {
            unsigned long ivalue;

            CB_PUTS("\t\t\t<ds>\n");
            /* support for exporting all CDP parameters */
            /* parameters common to all CFs */
            /* primary_val and secondary_val do not need to be saved between updates
             * so strictly speaking they could be omitted.
             * However, they can be useful for diagnostic purposes, so are included here. */
            value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                scratch[CDP_primary_val].u_val;
            if (isnan(value)) {
                CB_PUTS("\t\t\t<primary_value>NaN</primary_value>\n");
            } else {
                CB_FMTS("\t\t\t<primary_value>%0.10e</primary_value>\n", value);
            }

            value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                scratch[CDP_secondary_val].u_val;
            if (isnan(value)) {
                CB_PUTS("\t\t\t<secondary_value>NaN</secondary_value>\n");
            } else {
                CB_FMTS("\t\t\t<secondary_value>%0.10e</secondary_value>\n", value);
            }

            switch (cf_conv(rrd.rra_def[i].cf_nam)) {
            case CF_HWPREDICT:
            case CF_MHWPREDICT:
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_intercept].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<intercept>NaN</intercept>\n");
                } else {
                    CB_FMTS("\t\t\t<intercept>%0.10e</intercept>\n", value);
                }

                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_last_intercept].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<last_intercept>NaN</last_intercept>\n");
                } else {
                    CB_FMTS("\t\t\t<last_intercept>%0.10e</last_intercept>\n", value);
                }

                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_slope].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<slope>NaN</slope>\n");
                } else {
                    CB_FMTS("\t\t\t<slope>%0.10e</slope>\n", value);
                }

                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_last_slope].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<last_slope>NaN</last_slope>\n");
                } else {
                    CB_FMTS("\t\t\t<last_slope>%0.10e</last_slope>\n", value);
                }

                ivalue = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_null_count].u_cnt;
                CB_FMTS("\t\t\t<nan_count>%lu</nan_count>\n", ivalue);

                ivalue = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_last_null_count].u_cnt;
                CB_FMTS("\t\t\t<last_nan_count>%lu</last_nan_count>\n", ivalue);
                break;
            case CF_SEASONAL:
            case CF_DEVSEASONAL:
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_seasonal].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<seasonal>NaN</seasonal>\n");
                } else {
                    CB_FMTS("\t\t\t<seasonal>%0.10e</seasonal>\n", value);
                }

                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_last_seasonal].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<last_seasonal>NaN</last_seasonal>\n");
                } else {
                    CB_FMTS("\t\t\t<last_seasonal>%0.10e</last_seasonal>\n", value);
                }

                ivalue = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_init_seasonal].u_cnt;
                CB_FMTS("\t\t\t<init_flag>%lu</init_flag>\n", ivalue);
                break;
            case CF_DEVPREDICT:
                break;
            case CF_FAILURES:
            {
                unsigned short vidx;
                char *violations_array = (char *) ((void *)
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].scratch);
                CB_PUTS("\t\t\t<history>");
                for (vidx = 0;
                    vidx < rrd.rra_def[i].par[RRA_window_len].u_cnt;
                    ++vidx) {
                    CB_FMTS("%d", violations_array[vidx]);
                }
                CB_PUTS("</history>\n");
            }
                break;
            case CF_AVERAGE:
            case CF_MAXIMUM:
            case CF_MINIMUM:
            case CF_LAST:
            default:
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].scratch[CDP_val].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<value>NaN</value>\n");
                } else {
                    CB_FMTS("\t\t\t<value>%0.10e</value>\n", value);
                }

                CB_FMTS("\t\t\t<unknown_datapoints>%lu</unknown_datapoints>\n",
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                        scratch[CDP_unkn_pdp_cnt].u_cnt);
                break;
            }
            CB_PUTS("\t\t\t</ds>\n");
        }
        CB_PUTS("\t\t</cdp_prep>\n");

        CB_PUTS("\t\t<database>\n");
        rrd_seek(rrd_file, (rra_start + (rrd.rra_ptr[i].cur_row + 1)
                            * rrd.stat_head->ds_cnt
                            * sizeof(rrd_value_t)), SEEK_SET);
        timer = -(long)(rrd.rra_def[i].row_cnt - 1);
        ii = rrd.rra_ptr[i].cur_row;
        for (ix = 0; ix < rrd.rra_def[i].row_cnt; ix++) {
            ii++;
            if (ii >= rrd.rra_def[i].row_cnt) {
                rrd_seek(rrd_file, rra_start, SEEK_SET);
                ii = 0; /* wrap if max row cnt is reached */
            }
            now = (rrd.live_head->last_up
                   - rrd.live_head->last_up
                   % (rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step))
                + (timer * rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);

            timer++;
#if HAVE_STRFTIME
            localtime_r(&now, &tm);
            strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %Z", &tm);
#else
# error "Need strftime"
#endif
            CB_FMTS("\t\t\t<!-- %s / %lld --> <row>",  somestring, (long long int) now);
            for (iii = 0; iii < rrd.stat_head->ds_cnt; iii++) {
                rrd_read(rrd_file, &my_cdp, sizeof(rrd_value_t) * 1);
                if (isnan(my_cdp)) {
                    CB_PUTS("<v>NaN</v>");
                } else {
                    CB_FMTS("<v>%0.10e</v>", my_cdp);
                }
            }
            CB_PUTS("</row>\n");
        }
        CB_PUTS("\t\t</database>\n\t</rra>\n");
    }

    CB_PUTS("</rrd>\n");

    rrd_free(&rrd);

    return rrd_close(rrd_file);

err_out:
    rrd_set_error("error writing output file: %s", rrd_strerror(errno));
    rrd_free(&rrd);
    rrd_close(rrd_file);
    return (-1);

//Undefining the previously defined shortcuts
//See start of this function
#undef CB_PUTS
#undef CB_FMTS
//End of macro undefining

}
コード例 #6
0
int rrd_tune(
    int argc,
    char **argv)
{
    rrd_t     rrd;
    int       matches;
    int       optcnt = 0;
    long      ds;
    char      ds_nam[DS_NAM_SIZE];
    char      ds_new[DS_NAM_SIZE];
    long      heartbeat;
    double    min = 0;
    double    max = 0;
    char      dst[DST_SIZE];
    int       rc = -1;
    int       opt_newstep = -1;
    rrd_file_t *rrd_file = NULL;
    char      *opt_daemon = NULL;
    char      double_str[ 12 ];
    const char *in_filename = NULL;
    struct option long_options[] = {
        {"heartbeat", required_argument, 0, 'h'},
        {"minimum", required_argument, 0, 'i'},
        {"maximum", required_argument, 0, 'a'},
        {"data-source-type", required_argument, 0, 'd'},
        {"data-source-rename", required_argument, 0, 'r'},
        /* added parameter tuning options for aberrant behavior detection */
        {"deltapos", required_argument, 0, 'p'},
        {"deltaneg", required_argument, 0, 'n'},
        {"window-length", required_argument, 0, 'w'},
        {"failure-threshold", required_argument, 0, 'f'},
        {"alpha", required_argument, 0, 'x'},
        {"beta", required_argument, 0, 'y'},
        {"gamma", required_argument, 0, 'z'},
        {"gamma-deviation", required_argument, 0, 'v'},
        {"smoothing-window", required_argument, 0, 's'},
        {"smoothing-window-deviation", required_argument, 0, 'S'},
        {"aberrant-reset", required_argument, 0, 'b'},
	// integration of rrd_modify functionality.
        {"step", required_argument, 0, 't'},
	/* unfortunately, '-d' is already taken */
        {"daemon", required_argument, 0, 'D'},
        {0, 0, 0, 0}
    };

    optind = 0;
    opterr = 0;         /* initialize getopt */

    /* before we open the input RRD, we should flush it from any caching
    daemon, because we might totally rewrite it later on */

    /* for this, we FIRST have to find the daemon, this means we must parse options twice... */
    
    while (1) {
	int option_index = 0;
	int opt = getopt_long(argc, argv, "h:i:a:d:r:p:n:w:f:x:y:z:v:b:",
			      long_options, &option_index);
        if (opt == EOF)
            break;
	switch (opt) {
	case 'D':
            if (opt_daemon != NULL)
		free (opt_daemon);
            opt_daemon = strdup (optarg);
            if (opt_daemon == NULL)
            {
                rrd_set_error ("strdup failed.");
                return (-1);
            }
            break;
	default:
	    break;
	}
    }
    
    // connect to daemon (will take care of environment variable automatically)
    if (rrdc_connect(opt_daemon) != 0) {
    	rrd_set_error("Cannot connect to daemon");
	return 1;
    }

    if (opt_daemon) {
	free(opt_daemon);
	opt_daemon = NULL;
    }

    if (optind < 0 || optind >= argc) {
	// missing file name...
	rrd_set_error("missing file name");
	goto done;
    }
    
    /* NOTE: getopt_long reorders argv and places all NON option arguments to
    the back, starting with optind. This means the file name has travelled to
    argv[optind] */
    
    in_filename = argv[optind];
    
    if (rrdc_is_any_connected()) {
	// is it a good idea to just ignore the error ????
	rrdc_flush(in_filename);
	rrd_clear_error();
    }

    optind = 0;
    opterr = 0;         /* re-initialize getopt */
    
    rrd_init(&rrd);
    rrd_file = rrd_open(in_filename, &rrd, RRD_READWRITE | RRD_READAHEAD | RRD_READVALUES);
    if (rrd_file == NULL) {
	goto done;
    }

    while (1) {
        int       option_index = 0;
        int       opt;
        unsigned int strtod_ret_val;

        opt = getopt_long(argc, argv, "h:i:a:d:r:p:n:w:f:x:y:z:v:b:",
                          long_options, &option_index);
        if (opt == EOF)
            break;

        optcnt++;
        switch (opt) {
        case 'h':
            if ((matches =
		 sscanf(optarg, DS_NAM_FMT ":%ld", ds_nam,
			&heartbeat)) != 2) {
                rrd_set_error("invalid arguments for heartbeat");
		goto done;
            }
            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }
            rrd.ds_def[ds].par[DS_mrhb_cnt].u_cnt = heartbeat;
            break;

        case 'i':
            matches = sscanf(optarg, DS_NAM_FMT ":%[0-9.e+-]", ds_nam, double_str);
            if( matches >= 1 ) {
                strtod_ret_val = rrd_strtodbl( double_str, NULL, &min, NULL );
            }

            if ((matches < 1) || (strtod_ret_val != 2)) {
                rrd_set_error("invalid arguments for minimum ds value");
		goto done;
            }

            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }

            if (matches == 1)
                min = DNAN;
            rrd.ds_def[ds].par[DS_min_val].u_val = min;
            break;

        case 'a':
            matches = sscanf(optarg, DS_NAM_FMT ":%[0-9.e+-]", ds_nam, double_str);
            if( matches >= 1 ) {
                strtod_ret_val = rrd_strtodbl( double_str, NULL, &max, NULL );
            }

            if ((matches < 1 ) || (strtod_ret_val != 2)) {
                rrd_set_error("invalid arguments for maximum ds value");
		goto done;
            }

            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }

            if (matches == 1)
                max = DNAN;
            rrd.ds_def[ds].par[DS_max_val].u_val = max;
            break;

        case 'd':
            if ((matches =
                 sscanf(optarg, DS_NAM_FMT ":" DST_FMT, ds_nam, dst)) != 2) {
                rrd_set_error("invalid arguments for data source type");
		goto done;
	    }
            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }
            if ((int) dst_conv(dst) == -1) {
		goto done;
            }
            /* only reset when something is changed */
            if (strncmp(rrd.ds_def[ds].dst, dst, DST_SIZE - 1) != 0) {
                strncpy(rrd.ds_def[ds].dst, dst, DST_SIZE - 1);
                rrd.ds_def[ds].dst[DST_SIZE - 1] = '\0';

                rrd.pdp_prep[ds].last_ds[0] = 'U';
                rrd.pdp_prep[ds].last_ds[1] = 'N';
                rrd.pdp_prep[ds].last_ds[2] = 'K';
                rrd.pdp_prep[ds].last_ds[3] = 'N';
                rrd.pdp_prep[ds].last_ds[4] = '\0';
            }
            break;
        case 'r':
            if ((matches =
                 sscanf(optarg, DS_NAM_FMT ":" DS_NAM_FMT, ds_nam,
                        ds_new)) != 2) {
                rrd_set_error("invalid arguments for data source type");
		goto done;
            }
            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }
            strncpy(rrd.ds_def[ds].ds_nam, ds_new, DS_NAM_SIZE - 1);
            rrd.ds_def[ds].ds_nam[DS_NAM_SIZE - 1] = '\0';
            break;
        case 'p':
            if (set_deltaarg(&rrd, RRA_delta_pos, optarg)) {
		goto done;
            }
            break;
        case 'n':
            if (set_deltaarg(&rrd, RRA_delta_neg, optarg)) {
		goto done;
            }
            break;
        case 'f':
            if (set_windowarg(&rrd, RRA_failure_threshold, optarg)) {
		goto done;
            }
            break;
        case 'w':
            if (set_windowarg(&rrd, RRA_window_len, optarg)) {
		goto done;
            }
            break;
        case 'x':
            if (set_hwarg(&rrd, CF_HWPREDICT, RRA_hw_alpha, optarg)) {
                if (set_hwarg(&rrd, CF_MHWPREDICT, RRA_hw_alpha, optarg)) {
		    goto done;
                }
                rrd_clear_error();
            }
            break;
        case 'y':
            if (set_hwarg(&rrd, CF_HWPREDICT, RRA_hw_beta, optarg)) {
                if (set_hwarg(&rrd, CF_MHWPREDICT, RRA_hw_beta, optarg)) {
		    goto done;
                }
                rrd_clear_error();
            }
            break;
        case 'z':
            if (set_hwarg(&rrd, CF_SEASONAL, RRA_seasonal_gamma, optarg)) {
		goto done;
            }
            break;
        case 'v':
            if (set_hwarg(&rrd, CF_DEVSEASONAL, RRA_seasonal_gamma, optarg)) {
		goto done;
	    }
            break;
        case 'b':
            if (sscanf(optarg, DS_NAM_FMT, ds_nam) != 1) {
                rrd_set_error("invalid argument for aberrant-reset");
		goto done;
            }
            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
                /* ds_match handles it own errors */
		goto done;
            }
            reset_aberrant_coefficients(&rrd, rrd_file, (unsigned long) ds);
            if (rrd_test_error()) {
		goto done;
            }
            break;
        case 's':
            if (atoi(rrd.stat_head->version) < atoi(RRD_VERSION4)) {
                strcpy(rrd.stat_head->version, RRD_VERSION4);    /* smoothing_window causes Version 4 */
            }
            if (set_hwsmootharg
                (&rrd, CF_SEASONAL, RRA_seasonal_smoothing_window, optarg)) {
		goto done;
            }
            break;
        case 'S':
            if (atoi(rrd.stat_head->version) < atoi(RRD_VERSION4)) {
                strcpy(rrd.stat_head->version, RRD_VERSION4);    /* smoothing_window causes Version 4 */
            }
            if (set_hwsmootharg
                (&rrd, CF_DEVSEASONAL, RRA_seasonal_smoothing_window,
                 optarg)) {
		goto done;
            }
            break;
	case 't':
	    opt_newstep = atoi(optarg);
	    break;
	case 'D':
	    // ignore, handled in previous argv parsing round
	    break;
        case '?':
            if (optopt != 0)
                rrd_set_error("unknown option '%c'", optopt);
            else
                rrd_set_error("unknown option '%s'", argv[optind - 1]);
	    goto done;
        }
    }
    if (optcnt > 0) {
        rrd_seek(rrd_file, 0, SEEK_SET);
        rrd_write(rrd_file, rrd.stat_head, sizeof(stat_head_t) * 1);
        rrd_write(rrd_file, rrd.ds_def,
                  sizeof(ds_def_t) * rrd.stat_head->ds_cnt);
        /* need to write rra_defs for RRA parameter changes */
        rrd_write(rrd_file, rrd.rra_def,
                  sizeof(rra_def_t) * rrd.stat_head->rra_cnt);
    }
    
    if (optind >= argc) {
        int       i;

        for (i = 0; i < (int) rrd.stat_head->ds_cnt; i++)
            if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
                printf("DS[%s] typ: %s\thbt: %ld\tmin: %1.4f\tmax: %1.4f\n",
                       rrd.ds_def[i].ds_nam,
                       rrd.ds_def[i].dst,
                       rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt,
                       rrd.ds_def[i].par[DS_min_val].u_val,
                       rrd.ds_def[i].par[DS_max_val].u_val);
            } else {
                char     *buffer = NULL;

                rpn_compact2str((rpn_cdefds_t *) &
                                (rrd.ds_def[i].par[DS_cdef]), rrd.ds_def,
                                &buffer);
                printf("DS[%s] typ: %s\tcdef: %s\n", rrd.ds_def[i].ds_nam,
                       rrd.ds_def[i].dst, buffer);
                if (buffer) free(buffer);
            }
    }

    optind = handle_modify(&rrd, in_filename, argc, argv, optind + 1, opt_newstep);
    if (optind < 0) {
	goto done;
    }
    
    rc = 0;
done:
    if (in_filename && rrdc_is_any_connected()) {
        // save any errors....
        char *e = strdup(rrd_get_error());
	// is it a good idea to just ignore the error ????
	rrdc_forget(in_filename);
	rrd_clear_error();
        
        if (e && *e) {
            rrd_set_error(e);
        }
        if (e) free(e);
        
    }
    if (rrd_file) {
	rrd_close(rrd_file);
    }
    rrd_free(&rrd);
    return rc;
}
コード例 #7
0
ファイル: rrd_info.c プロジェクト: DigiTempReader/rrdtool-1.x
rrd_info_t *rrd_info_r(
    const char *filename)
{
    unsigned int i, ii = 0;
    rrd_t     rrd;
    rrd_info_t *data = NULL, *cd;
    rrd_infoval_t info;
    rrd_file_t *rrd_file;
    enum cf_en current_cf;
    enum dst_en current_ds;

    rrd_init(&rrd);
    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
    if (rrd_file == NULL)
        goto err_free;

    info.u_str = filename;
    cd = rrd_info_push(NULL, sprintf_alloc("filename"), RD_I_STR, info);
    data = cd;

    info.u_str = rrd.stat_head->version;
    cd = rrd_info_push(cd, sprintf_alloc("rrd_version"), RD_I_STR, info);

    info.u_cnt = rrd.stat_head->pdp_step;
    cd = rrd_info_push(cd, sprintf_alloc("step"), RD_I_CNT, info);

    info.u_cnt = rrd.live_head->last_up;
    cd = rrd_info_push(cd, sprintf_alloc("last_update"), RD_I_CNT, info);

    info.u_cnt = rrd_get_header_size(&rrd);
    cd = rrd_info_push(cd, sprintf_alloc("header_size"), RD_I_CNT, info);

    for (i = 0; i < rrd.stat_head->ds_cnt; i++) {

        info.u_cnt=i;
        cd= rrd_info_push(cd,sprintf_alloc("ds[%s].index",
                                     rrd.ds_def[i].ds_nam),
                     RD_I_CNT, info);
    
        info.u_str = rrd.ds_def[i].dst;
        cd = rrd_info_push(cd, sprintf_alloc("ds[%s].type",
                                             rrd.ds_def[i].ds_nam),
                           RD_I_STR, info);

        current_ds = dst_conv(rrd.ds_def[i].dst);
        switch (current_ds) {
        case DST_CDEF:
        {
            char     *buffer = NULL;

            rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),
                            rrd.ds_def, &buffer);
            info.u_str = buffer;
            cd = rrd_info_push(cd,
                               sprintf_alloc("ds[%s].cdef",
                                             rrd.ds_def[i].ds_nam), RD_I_STR,
                               info);
            free(buffer);
        }
            break;
        default:
            info.u_cnt = rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt;
            cd = rrd_info_push(cd,
                               sprintf_alloc("ds[%s].minimal_heartbeat",
                                             rrd.ds_def[i].ds_nam), RD_I_CNT,
                               info);

            info.u_val = rrd.ds_def[i].par[DS_min_val].u_val;
            cd = rrd_info_push(cd,
                               sprintf_alloc("ds[%s].min",
                                             rrd.ds_def[i].ds_nam), RD_I_VAL,
                               info);

            info.u_val = rrd.ds_def[i].par[DS_max_val].u_val;
            cd = rrd_info_push(cd,
                               sprintf_alloc("ds[%s].max",
                                             rrd.ds_def[i].ds_nam), RD_I_VAL,
                               info);
            break;
        }

        info.u_str = rrd.pdp_prep[i].last_ds;
        cd = rrd_info_push(cd,
                           sprintf_alloc("ds[%s].last_ds",
                                         rrd.ds_def[i].ds_nam), RD_I_STR,
                           info);

        info.u_val = rrd.pdp_prep[i].scratch[PDP_val].u_val;
        cd = rrd_info_push(cd,
                           sprintf_alloc("ds[%s].value",
                                         rrd.ds_def[i].ds_nam), RD_I_VAL,
                           info);

        info.u_cnt = rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt;
        cd = rrd_info_push(cd,
                           sprintf_alloc("ds[%s].unknown_sec",
                                         rrd.ds_def[i].ds_nam), RD_I_CNT,
                           info);
    }

    for (i = 0; i < rrd.stat_head->rra_cnt; i++) {
        info.u_str = rrd.rra_def[i].cf_nam;
        cd = rrd_info_push(cd, sprintf_alloc("rra[%d].cf", i), RD_I_STR,
                           info);
        current_cf = cf_conv(rrd.rra_def[i].cf_nam);

        info.u_cnt = rrd.rra_def[i].row_cnt;
        cd = rrd_info_push(cd, sprintf_alloc("rra[%d].rows", i), RD_I_CNT,
                           info);

        info.u_cnt = rrd.rra_ptr[i].cur_row;
        cd = rrd_info_push(cd, sprintf_alloc("rra[%d].cur_row", i), RD_I_CNT,
                           info);

        info.u_cnt = rrd.rra_def[i].pdp_cnt;
        cd = rrd_info_push(cd, sprintf_alloc("rra[%d].pdp_per_row", i),
                           RD_I_CNT, info);

        switch (current_cf) {
        case CF_HWPREDICT:
        case CF_MHWPREDICT:
            info.u_val = rrd.rra_def[i].par[RRA_hw_alpha].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].alpha", i),
                               RD_I_VAL, info);
            info.u_val = rrd.rra_def[i].par[RRA_hw_beta].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].beta", i), RD_I_VAL,
                               info);
            break;
        case CF_SEASONAL:
        case CF_DEVSEASONAL:
            info.u_val = rrd.rra_def[i].par[RRA_seasonal_gamma].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].gamma", i),
                               RD_I_VAL, info);
            if (atoi(rrd.stat_head->version) >= 4) {
                info.u_val =
                    rrd.rra_def[i].par[RRA_seasonal_smoothing_window].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc("rra[%d].smoothing_window",
                                                 i), RD_I_VAL, info);
            }
            break;
        case CF_FAILURES:
            info.u_val = rrd.rra_def[i].par[RRA_delta_pos].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].delta_pos", i),
                               RD_I_VAL, info);
            info.u_val = rrd.rra_def[i].par[RRA_delta_neg].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].delta_neg", i),
                               RD_I_VAL, info);
            info.u_cnt = rrd.rra_def[i].par[RRA_failure_threshold].u_cnt;
            cd = rrd_info_push(cd,
                               sprintf_alloc("rra[%d].failure_threshold", i),
                               RD_I_CNT, info);
            info.u_cnt = rrd.rra_def[i].par[RRA_window_len].u_cnt;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].window_length", i),
                               RD_I_CNT, info);
            break;
        case CF_DEVPREDICT:
            break;
        default:
            info.u_val = rrd.rra_def[i].par[RRA_cdp_xff_val].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].xff", i), RD_I_VAL,
                               info);
            break;
        }

        for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++) {
            switch (current_cf) {
            case CF_HWPREDICT:
            case CF_MHWPREDICT:
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_hw_intercept].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].intercept", i, ii),
                                   RD_I_VAL, info);
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_hw_slope].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc("rra[%d].cdp_prep[%d].slope",
                                                 i, ii), RD_I_VAL, info);
                info.u_cnt =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_null_count].u_cnt;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].NaN_count", i, ii),
                                   RD_I_CNT, info);
                break;
            case CF_SEASONAL:
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_hw_seasonal].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].seasonal", i, ii),
                                   RD_I_VAL, info);
                break;
            case CF_DEVSEASONAL:
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_seasonal_deviation].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].deviation", i, ii),
                                   RD_I_VAL, info);
                break;
            case CF_DEVPREDICT:
                break;
            case CF_FAILURES:
            {
                unsigned short j;
                char     *violations_array;
                char      history[MAX_FAILURES_WINDOW_LEN + 1];

                violations_array =
                    (char *) rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                          ii].scratch;
                for (j = 0; j < rrd.rra_def[i].par[RRA_window_len].u_cnt; ++j)
                    history[j] = (violations_array[j] == 1) ? '1' : '0';
                history[j] = '\0';
                info.u_str = history;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].history", i, ii),
                                   RD_I_STR, info);
            }
                break;
            default:
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_val].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc("rra[%d].cdp_prep[%d].value",
                                                 i, ii), RD_I_VAL, info);
                info.u_cnt =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_unkn_pdp_cnt].u_cnt;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].unknown_datapoints",
                                    i, ii), RD_I_CNT, info);
                break;
            }
        }
    }

    rrd_close(rrd_file);
  err_free:
    rrd_free(&rrd);
    return (data);
}
コード例 #8
0
ファイル: rrd_fetch.c プロジェクト: ndksys01/rrdtool-1.x
int rrd_fetch_fn(
    const char *filename,   /* name of the rrd */
    enum cf_en cf_idx,  /* which consolidation function ? */
    time_t *start,
    time_t *end,        /* which time frame do you want ?
                         * will be changed to represent reality */
    unsigned long *step,    /* which stepsize do you want? 
                             * will be changed to represent reality */
    unsigned long *ds_cnt,  /* number of data sources in file */
    char ***ds_namv,    /* names of data_sources */
    rrd_value_t **data)
{                       /* two dimensional array containing the data */
    long      i, ii;
    time_t    cal_start, cal_end, rra_start_time, rra_end_time;
    long      best_full_rra = 0, best_part_rra = 0, chosen_rra =
        0, rra_pointer = 0;
    long      best_full_step_diff = 0, best_part_step_diff =
        0, tmp_step_diff = 0, tmp_match = 0, best_match = 0;
    long      full_match, rra_base;
    off_t     start_offset, end_offset;
    int       first_full = 1;
    int       first_part = 1;
    rrd_t     rrd;
    rrd_file_t *rrd_file;
    rrd_value_t *data_ptr;
    unsigned long rows;

#ifdef DEBUG
    fprintf(stderr, "Entered rrd_fetch_fn() searching for the best match\n");
    fprintf(stderr, "Looking for: start %10lu end %10lu step %5lu\n",
            *start, *end, *step);
#endif

#ifdef HAVE_LIBDBI
    /* handle libdbi datasources */
    if (strncmp("sql//",filename,5)==0 || strncmp("sql||",filename,5)==0) {
	return rrd_fetch_fn_libdbi(filename,cf_idx,start,end,step,ds_cnt,ds_namv,data);
    }
#endif

    rrd_init(&rrd);
    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
    if (rrd_file == NULL)
        goto err_free;

    /* when was the really last update of this file ? */

    if (((*ds_namv) =
         (char **) malloc(rrd.stat_head->ds_cnt * sizeof(char *))) == NULL) {
        rrd_set_error("malloc fetch ds_namv array");
        goto err_close;
    }

    for (i = 0; (unsigned long) i < rrd.stat_head->ds_cnt; i++) {
        if ((((*ds_namv)[i]) = (char*)malloc(sizeof(char) * DS_NAM_SIZE)) == NULL) {
            rrd_set_error("malloc fetch ds_namv entry");
            goto err_free_ds_namv;
        }
        strncpy((*ds_namv)[i], rrd.ds_def[i].ds_nam, DS_NAM_SIZE - 1);
        (*ds_namv)[i][DS_NAM_SIZE - 1] = '\0';

    }

    /* find the rra which best matches the requirements */
    for (i = 0; (unsigned) i < rrd.stat_head->rra_cnt; i++) {
      enum cf_en rratype=cf_conv(rrd.rra_def[i].cf_nam);
      /* handle this RRA */
      if (
	  /* if we found a direct match */
	  (rratype == cf_idx)
	  || 
	  /*if we found a DS with interval 1 
	    and CF (requested,available) are MIN,MAX,AVERAGE,LAST
	  */
	  ( 
	      /* only if we are on interval 1 */
	      (rrd.rra_def[i].pdp_cnt==1) 
	      && ( 
		  /* and requested CF is MIN,MAX,AVERAGE,LAST */
		  (cf_idx == CF_MINIMUM)
		  ||(cf_idx == CF_MAXIMUM)
		  ||(cf_idx == CF_AVERAGE)
		  ||(cf_idx == CF_LAST)
		  )
	      && (
		  /* and found CF is MIN,MAX,AVERAGE,LAST */
		  (rratype == CF_MINIMUM)
		  ||(rratype == CF_MAXIMUM)
		  ||(rratype == CF_AVERAGE)
		  ||(rratype == CF_LAST)
		  )
	      )
	  ){

            cal_end = (rrd.live_head->last_up - (rrd.live_head->last_up
                                                 % (rrd.rra_def[i].pdp_cnt
                                                    *
                                                    rrd.stat_head->
                                                    pdp_step)));
            cal_start =
                (cal_end -
                 (rrd.rra_def[i].pdp_cnt * rrd.rra_def[i].row_cnt *
                  rrd.stat_head->pdp_step));

            full_match = *end - *start;
#ifdef DEBUG
            fprintf(stderr, "Considering: start %10lu end %10lu step %5lu ",
                    cal_start, cal_end,
                    rrd.stat_head->pdp_step * rrd.rra_def[i].pdp_cnt);
#endif
            /* we need step difference in either full or partial case */
            tmp_step_diff = labs(*step - (rrd.stat_head->pdp_step
                                          * rrd.rra_def[i].pdp_cnt));
            /* best full match */
            if (cal_start <= *start) {
                if (first_full || (tmp_step_diff < best_full_step_diff)) {
                    first_full = 0;
                    best_full_step_diff = tmp_step_diff;
                    best_full_rra = i;
#ifdef DEBUG
                    fprintf(stderr, "best full match so far\n");
                } else {
                    fprintf(stderr, "full match, not best\n");
#endif
                }

            } else {
                /* best partial match */
                tmp_match = full_match;
                if (cal_start > *start)
                    tmp_match -= (cal_start - *start);
                if (first_part ||
                    (best_match < tmp_match) ||
                    (best_match == tmp_match &&
                     tmp_step_diff < best_part_step_diff)) {
#ifdef DEBUG
                    fprintf(stderr, "best partial so far\n");
#endif
                    first_part = 0;
                    best_match = tmp_match;
                    best_part_step_diff = tmp_step_diff;
                    best_part_rra = i;
                } else {
#ifdef DEBUG
                    fprintf(stderr, "partial match, not best\n");
#endif
                }
            }
        }
    }

    /* lets see how the matching went. */
    if (first_full == 0)
        chosen_rra = best_full_rra;
    else if (first_part == 0)
        chosen_rra = best_part_rra;
    else {
        rrd_set_error
            ("the RRD does not contain an RRA matching the chosen CF");
        goto err_free_all_ds_namv;
    }

    /* set the wish parameters to their real values */
    *step = rrd.stat_head->pdp_step * rrd.rra_def[chosen_rra].pdp_cnt;
    *start -= (*start % *step);
    *end += (*step - *end % *step);
    rows = (*end - *start) / *step + 1;

#ifdef DEBUG
    fprintf(stderr,
            "We found:    start %10lu end %10lu step %5lu rows  %lu\n",
            *start, *end, *step, rows);
#endif

/* Start and end are now multiples of the step size.  The amount of
** steps we want is (end-start)/step and *not* an extra one.
** Reasoning:  if step is s and we want to graph from t to t+s,
** we need exactly ((t+s)-t)/s rows.  The row to collect from the
** database is the one with time stamp (t+s) which means t to t+s.
*/
    *ds_cnt = rrd.stat_head->ds_cnt;
    if (((*data) = (rrd_value_t*)malloc(*ds_cnt * rows * sizeof(rrd_value_t))) == NULL) {
        rrd_set_error("malloc fetch data area");
        goto err_free_all_ds_namv;
    }

    data_ptr = (*data);

    /* find base address of rra */
    rra_base = rrd_file->header_len;
    for (i = 0; i < chosen_rra; i++)
        rra_base += (*ds_cnt * rrd.rra_def[i].row_cnt * sizeof(rrd_value_t));

    /* find start and end offset */
    rra_end_time = (rrd.live_head->last_up
                    - (rrd.live_head->last_up % *step));
    rra_start_time = (rra_end_time
                      - (*step * (rrd.rra_def[chosen_rra].row_cnt - 1)));
    /* here's an error by one if we don't be careful */
    start_offset = ((long long)*start + (long long)*step - (long long)rra_start_time) / (long long) *step;
    end_offset = ((long long)rra_end_time - (long long)*end) / (long long) *step;
#ifdef DEBUG
    fprintf(stderr,
            "start %10lu step %10lu rra_start %lld, rra_end %lld, start_off %lld, end_off %lld\n",
            *start, *step,(long long)rra_start_time, (long long)rra_end_time, (long long)start_offset, (long long)end_offset);
#endif
    /* only seek if the start time is before the end time */
    if (*start <= rra_end_time && *end >= rra_start_time - (off_t)*step ){
        if (start_offset <= 0)
            rra_pointer = rrd.rra_ptr[chosen_rra].cur_row + 1;
        else
            rra_pointer = rrd.rra_ptr[chosen_rra].cur_row + 1 + start_offset;

        rra_pointer = rra_pointer % (signed) rrd.rra_def[chosen_rra].row_cnt;
         
        if (rrd_seek(rrd_file, (rra_base + (rra_pointer * (*ds_cnt)
                                        * sizeof(rrd_value_t))),
                 SEEK_SET) != 0) {
            rrd_set_error("seek error in RRA");
            goto err_free_data;
        }
#ifdef DEBUG
        fprintf(stderr, "First Seek: rra_base %lu rra_pointer %lu\n",
                rra_base, rra_pointer);
#endif
    }
    
    /* step trough the array */

    for (i = start_offset;
         i < (signed) rrd.rra_def[chosen_rra].row_cnt - end_offset; i++) {
        /* no valid data yet */
        if (i < 0) {
#ifdef DEBUG
            fprintf(stderr, "pre fetch %li -- ", i);
#endif
            for (ii = 0; (unsigned) ii < *ds_cnt; ii++) {
                *(data_ptr++) = DNAN;
#ifdef DEBUG
                fprintf(stderr, "%10.2f ", *(data_ptr - 1));
#endif
            }
        }
        /* past the valid data area */
        else if (i >= (signed) rrd.rra_def[chosen_rra].row_cnt) {
#ifdef DEBUG
            fprintf(stderr, "past fetch %li -- ", i);
#endif
            for (ii = 0; (unsigned) ii < *ds_cnt; ii++) {
                *(data_ptr++) = DNAN;
#ifdef DEBUG
                fprintf(stderr, "%10.2f ", *(data_ptr - 1));
#endif
            }
        } else {
            /* OK we are inside the valid area but the pointer has to 
             * be wrapped*/
            if (rra_pointer >= (signed) rrd.rra_def[chosen_rra].row_cnt) {
                rra_pointer -= rrd.rra_def[chosen_rra].row_cnt;
                if (rrd_seek(rrd_file, (rra_base + rra_pointer * (*ds_cnt)
                                        * sizeof(rrd_value_t)),
                             SEEK_SET) != 0) {
                    rrd_set_error("wrap seek in RRA did fail");
                    goto err_free_data;
                }
#ifdef DEBUG
                fprintf(stderr, "wrap seek ...\n");
#endif
            }

            if (rrd_read(rrd_file, data_ptr, sizeof(rrd_value_t) * (*ds_cnt))
                != (ssize_t) (sizeof(rrd_value_t) * (*ds_cnt))) {
                rrd_set_error("fetching cdp from rra");
                goto err_free_data;
            }
#ifdef DEBUG
            fprintf(stderr, "post fetch %li -- ", i);
            for (ii = 0; ii < *ds_cnt; ii++)
                fprintf(stderr, "%10.2f ", *(data_ptr + ii));
#endif
            data_ptr += *ds_cnt;
            rra_pointer++;
        }
#ifdef DEBUG
        fprintf(stderr, "\n");
#endif

    }

    rrd_close(rrd_file);
    rrd_free(&rrd);
    return (0);
  err_free_data:
    free(*data);
    *data = NULL;
  err_free_all_ds_namv:
    for (i = 0; (unsigned long) i < rrd.stat_head->ds_cnt; ++i)
        free((*ds_namv)[i]);
  err_free_ds_namv:
    free(*ds_namv);
  err_close:
    rrd_close(rrd_file);
  err_free:
    rrd_free(&rrd);
    return (-1);
}
コード例 #9
0
int
rrd_tune(int argc, char **argv)    
{   
    rrd_t               rrd;
    FILE               *rrd_file;
    int                 matches;
    int                 optcnt = 0;
    long                ds;
    char                ds_nam[DS_NAM_SIZE];
    char                ds_new[DS_NAM_SIZE];
    long                heartbeat;
    double              min;
    double              max;
    char                dst[DST_SIZE];
    optind = 0; opterr = 0;  /* initialize getopt */


    if(rrd_open(argv[1],&rrd_file,&rrd, RRD_READWRITE)==-1){
        return -1;
    }

    
    while (1){
	static struct option long_options[] =
	{
	    {"heartbeat",        required_argument, 0, 'h'},
	    {"minimum",          required_argument, 0, 'i'},
	    {"maximum",          required_argument, 0, 'a'},
	    {"data-source-type", required_argument, 0, 'd'},
	    {"data-source-rename", required_argument, 0, 'r'},
	    /* added parameter tuning options for aberrant behavior detection */
		{"deltapos",required_argument,0,'p'},
		{"deltaneg",required_argument,0,'n'},
		{"window-length",required_argument,0,'w'},
		{"failure-threshold",required_argument,0,'f'},
	    {"alpha",required_argument,0,'x'},
	    {"beta",required_argument,0,'y'},
	    {"gamma",required_argument,0,'z'},
	    {"gamma-deviation",required_argument,0,'v'},
		{"aberrant-reset",required_argument,0,'b'},
	    {0,0,0,0}
	};
	int option_index = 0;
	int opt;
	opt = getopt_long(argc, argv, "h:i:a:d:r:p:n:w:f:x:y:z:v:b:", 
			  long_options, &option_index);
	if (opt == EOF)
	    break;
	
	optcnt++;
	switch(opt) {	    
	case 'h':
	    if ((matches = sscanf(optarg, DS_NAM_FMT ":%ld",ds_nam,&heartbeat)) != 2){
		rrd_set_error("invalid arguments for heartbeat");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
                fclose(rrd_file);
		return -1;
	    }
	    rrd.ds_def[ds].par[DS_mrhb_cnt].u_cnt = heartbeat;
	    break;

	case 'i':
	    if ((matches = sscanf(optarg,DS_NAM_FMT ":%lf",ds_nam,&min)) <1){
		rrd_set_error("invalid arguments for minimum ds value");
		rrd_free(&rrd);
                fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
                fclose(rrd_file);
		return -1;
	    }

	    if(matches == 1)
		min= DNAN;
	    rrd.ds_def[ds].par[DS_min_val].u_val = min;
	    break;

	case 'a':
	    if ((matches = sscanf(optarg, DS_NAM_FMT ":%lf",ds_nam,&max)) <1){
		rrd_set_error("invalid arguments for maximum ds value");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if(matches == 1) 
		max= DNAN; 
	    rrd.ds_def[ds].par[DS_max_val].u_val = max;
	    break;

	case 'd':
	    if ((matches = sscanf(optarg, DS_NAM_FMT ":" DST_FMT ,ds_nam,dst)) != 2){
		rrd_set_error("invalid arguments for data source type");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((int)dst_conv(dst) == -1){
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    strncpy(rrd.ds_def[ds].dst,dst,DST_SIZE-1);
	    rrd.ds_def[ds].dst[DST_SIZE-1]='\0';

	    rrd.pdp_prep[ds].last_ds[0] = 'U';
	    rrd.pdp_prep[ds].last_ds[1] = 'N';
	    rrd.pdp_prep[ds].last_ds[2] = 'K';
	    rrd.pdp_prep[ds].last_ds[3] = 'N';
	    rrd.pdp_prep[ds].last_ds[4] = '\0';
	    
	    break;
	case 'r':
	    if ((matches = 
		 sscanf(optarg,DS_NAM_FMT ":" DS_NAM_FMT , ds_nam,ds_new)) != 2){
		rrd_set_error("invalid arguments for data source type");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    strncpy(rrd.ds_def[ds].ds_nam,ds_new,DS_NAM_SIZE-1);
	    rrd.ds_def[ds].ds_nam[DS_NAM_SIZE-1]='\0';
	    break;
    case 'p':
		if (set_deltaarg(&rrd,RRA_delta_pos,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'n':
		if (set_deltaarg(&rrd,RRA_delta_neg,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'f':
		if (set_windowarg(&rrd,RRA_failure_threshold,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'w':
		if (set_windowarg(&rrd,RRA_window_len,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'x':
		if (set_hwarg(&rrd,CF_HWPREDICT,RRA_hw_alpha,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'y':
		if (set_hwarg(&rrd,CF_HWPREDICT,RRA_hw_beta,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'z':
		if (set_hwarg(&rrd,CF_SEASONAL,RRA_seasonal_gamma,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'v':
		if (set_hwarg(&rrd,CF_DEVSEASONAL,RRA_seasonal_gamma,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'b':
		if (sscanf(optarg,DS_NAM_FMT,ds_nam) != 1){
		rrd_set_error("invalid argument for aberrant-reset");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
	    /* ds_match handles it own errors */	
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    reset_aberrant_coefficients(&rrd,rrd_file,(unsigned long) ds);
		if (rrd_test_error()) {
		   rrd_free(&rrd);
		   fclose(rrd_file);
		   return -1;
		}
		break;
	case '?':
            if (optopt != 0)
                rrd_set_error("unknown option '%c'", optopt);
            else
                rrd_set_error("unknown option '%s'",argv[optind-1]);
	    rrd_free(&rrd);	    
            fclose(rrd_file);
            return -1;
        }
    }
	if(optcnt>0){
	
	fseek(rrd_file,0,SEEK_SET);
	fwrite(rrd.stat_head,
	       sizeof(stat_head_t),1, rrd_file);
	fwrite(rrd.ds_def,
	       sizeof(ds_def_t), rrd.stat_head->ds_cnt, rrd_file);
	/* need to write rra_defs for RRA parameter changes */
	fwrite(rrd.rra_def, sizeof(rra_def_t), rrd.stat_head->rra_cnt,
		   rrd_file);
    } else {
	int i;
	for(i=0;i< (int)rrd.stat_head->ds_cnt;i++)
		if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
	    printf("DS[%s] typ: %s\thbt: %ld\tmin: %1.4f\tmax: %1.4f\n",
		   rrd.ds_def[i].ds_nam,
		   rrd.ds_def[i].dst,
		   rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt,
		   rrd.ds_def[i].par[DS_min_val].u_val,
		   rrd.ds_def[i].par[DS_max_val].u_val);
		} else {
		char *buffer = NULL;
		rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),rrd.ds_def,&buffer);
		printf("DS[%s] typ: %s\tcdef: %s\n", rrd.ds_def[i].ds_nam,rrd.ds_def[i].dst,buffer);
	    free(buffer);
		}
    }
    fclose(rrd_file);
    rrd_free(&rrd);
    return 0;
}
コード例 #10
0
ファイル: rrd_fetch.c プロジェクト: OPSF/uClinux
int
rrd_fetch_fn(
    char           *filename,  /* name of the rrd */
    enum cf_en     cf_idx,         /* which consolidation function ?*/
    time_t         *start,
    time_t         *end,       /* which time frame do you want ?
			        * will be changed to represent reality */
    unsigned long  *step,      /* which stepsize do you want? 
				* will be changed to represent reality */
    unsigned long  *ds_cnt,    /* number of data sources in file */
    char           ***ds_namv,   /* names of data_sources */
    rrd_value_t    **data)     /* two dimensional array containing the data */
{
    long           i,ii;
    FILE           *in_file;
    time_t         cal_start,cal_end, rra_start_time,rra_end_time;
    long  best_full_rra=0, best_part_rra=0, chosen_rra=0, rra_pointer=0;
    long  best_step_diff=0, tmp_step_diff=0, tmp_match=0, best_match=0;
    long  full_match, rra_base;
    long           start_offset, end_offset;
    int            first_full = 1;
    int            first_part = 1;
    rrd_t     rrd;
    rrd_value_t    *data_ptr;
    unsigned long  rows = (*end - *start) / *step;

#ifdef DEBUG
fprintf(stderr,"Entered rrd_fetch_fn() searching for the best match\n");
fprintf(stderr,"Looking for: start %10lu end %10lu step %5lu rows  %lu\n",
						*start,*end,*step,rows);
#endif

    if(rrd_open(filename,&in_file,&rrd, RRD_READONLY)==-1)
	return(-1);
    
    /* when was the really last update of this file ? */

    if (((*ds_namv) = (char **) malloc(rrd.stat_head->ds_cnt * sizeof(char*)))==NULL){
	rrd_set_error("malloc fetch ds_namv array");
	rrd_free(&rrd);
	fclose(in_file);
	return(-1);
    }
    
    for(i=0;(unsigned long)i<rrd.stat_head->ds_cnt;i++){
	if ((((*ds_namv)[i]) = malloc(sizeof(char) * DS_NAM_SIZE))==NULL){
	    rrd_set_error("malloc fetch ds_namv entry");
	    rrd_free(&rrd);
	    free(*ds_namv);
	    fclose(in_file);
	    return(-1);
	}
	strncpy((*ds_namv)[i],rrd.ds_def[i].ds_nam,DS_NAM_SIZE-1);
	(*ds_namv)[i][DS_NAM_SIZE-1]='\0';

    }
    
    /* find the rra which best matches the requirements */
    for(i=0;(unsigned)i<rrd.stat_head->rra_cnt;i++){
	if(cf_conv(rrd.rra_def[i].cf_nam) == cf_idx){
	    
	    cal_end = (rrd.live_head->last_up - (rrd.live_head->last_up 
			  % (rrd.rra_def[i].pdp_cnt 
			     * rrd.stat_head->pdp_step)));
	    cal_start = (cal_end 
			 - (rrd.rra_def[i].pdp_cnt 
			    * rrd.rra_def[i].row_cnt
			    * rrd.stat_head->pdp_step));

	    full_match = *end -*start;
#ifdef DEBUG
fprintf(stderr,"Considering: start %10lu end %10lu step %5lu ",
							cal_start,cal_end,
			rrd.stat_head->pdp_step * rrd.rra_def[i].pdp_cnt);
#endif
 	    /* we need step difference in either full or partial case */
 	    tmp_step_diff = labs(*step - (rrd.stat_head->pdp_step
					   * rrd.rra_def[i].pdp_cnt));
	    /* best full match */
	    if(cal_end >= *end 
	       && cal_start <= *start){
		if (first_full || (tmp_step_diff < best_step_diff)){
		    first_full=0;
		    best_step_diff = tmp_step_diff;
		    best_full_rra=i;
#ifdef DEBUG
fprintf(stderr,"best full match so far\n");
#endif
		} else {
#ifdef DEBUG
fprintf(stderr,"full match, not best\n");
#endif
		}
		
	    } else {
		/* best partial match */
		tmp_match = full_match;
		if (cal_start>*start)
		    tmp_match -= (cal_start-*start);
		if (cal_end<*end)
		    tmp_match -= (*end-cal_end);		
		if (first_part ||
                    (best_match < tmp_match) ||
                    (best_match == tmp_match && 
                     tmp_step_diff < best_step_diff)){ 
#ifdef DEBUG
fprintf(stderr,"best partial so far\n");
#endif
		    first_part=0;
		    best_match = tmp_match;
		    best_step_diff = tmp_step_diff;
		    best_part_rra =i;
		} else {
#ifdef DEBUG
fprintf(stderr,"partial match, not best\n");
#endif
		}
	    }
	}
    }

    /* lets see how the matching went. */
    if (first_full==0)
	chosen_rra = best_full_rra;
    else if (first_part==0)
	chosen_rra = best_part_rra;
    else {
	rrd_set_error("the RRD does not contain an RRA matching the chosen CF");
	rrd_free(&rrd);
	fclose(in_file);
	return(-1);
    }
	
    /* set the wish parameters to their real values */
    *step = rrd.stat_head->pdp_step * rrd.rra_def[chosen_rra].pdp_cnt;
    *start -= (*start % *step);
    if (*end % *step) *end += (*step - *end % *step);
    rows = (*end - *start) / *step;

#ifdef DEBUG
    fprintf(stderr,"We found:    start %10lu end %10lu step %5lu rows  %lu\n",
						*start,*end,*step,rows);
#endif

/* Start and end are now multiples of the step size.  The amount of
** steps we want is (end-start)/step and *not* an extra one.
** Reasoning:  if step is s and we want to graph from t to t+s,
** we need exactly ((t+s)-t)/s rows.  The row to collect from the
** database is the one with time stamp (t+s) which means t to t+s.
*/
    *ds_cnt =   rrd.stat_head->ds_cnt; 
    if (((*data) = malloc(*ds_cnt * rows * sizeof(rrd_value_t)))==NULL){
	rrd_set_error("malloc fetch data area");
	for (i=0;(unsigned long)i<*ds_cnt;i++)
	      free((*ds_namv)[i]);
	free(*ds_namv);
	rrd_free(&rrd);
	fclose(in_file);
	return(-1);
    }
    
    data_ptr=(*data);
    
    /* find base address of rra */
    rra_base=ftell(in_file);
    for(i=0;i<chosen_rra;i++)
	rra_base += ( *ds_cnt
		      * rrd.rra_def[i].row_cnt
		      * sizeof(rrd_value_t));

    /* find start and end offset */
    rra_end_time = (rrd.live_head->last_up 
		    - (rrd.live_head->last_up % *step));
    rra_start_time = (rra_end_time
		 - ( *step * (rrd.rra_def[chosen_rra].row_cnt-1)));
    /* here's an error by one if we don't be careful */
    start_offset =(long)(*start + *step - rra_start_time) / (long)*step;
    end_offset = (long)(rra_end_time - *end ) / (long)*step; 
#ifdef DEBUG
    fprintf(stderr,"rra_start %lu, rra_end %lu, start_off %li, end_off %li\n",
	    rra_start_time,rra_end_time,start_offset,end_offset);
#endif

    /* fill the gap at the start if needs be */

    if (start_offset <= 0)
	rra_pointer = rrd.rra_ptr[chosen_rra].cur_row+1;
    else 
	rra_pointer = rrd.rra_ptr[chosen_rra].cur_row+1+start_offset;
    
    if(fseek(in_file,(rra_base 
		   + (rra_pointer
		      * *ds_cnt
		      * sizeof(rrd_value_t))),SEEK_SET) != 0){
	rrd_set_error("seek error in RRA");
	for (i=0;(unsigned)i<*ds_cnt;i++)
	      free((*ds_namv)[i]);
	free(*ds_namv);
	rrd_free(&rrd);
	free(*data);
	*data = NULL;
	fclose(in_file);
	return(-1);

    }
#ifdef DEBUG
    fprintf(stderr,"First Seek: rra_base %lu rra_pointer %lu\n",
	    rra_base, rra_pointer);
#endif
    /* step trough the array */

    for (i=start_offset;
	 i< (signed)rrd.rra_def[chosen_rra].row_cnt - end_offset;
	 i++){
	/* no valid data yet */
	if (i<0) {
#ifdef DEBUG
	    fprintf(stderr,"pre fetch %li -- ",i);
#endif
	    for(ii=0;(unsigned)ii<*ds_cnt;ii++){
		*(data_ptr++) = DNAN;
#ifdef DEBUG
		fprintf(stderr,"%10.2f ",*(data_ptr-1));
#endif
	    }
	} 
	/* past the valid data area */
	else if (i >= (signed)rrd.rra_def[chosen_rra].row_cnt) {
#ifdef DEBUG
	    fprintf(stderr,"post fetch %li -- ",i);
#endif
	    for(ii=0;(unsigned)ii<*ds_cnt;ii++){
		*(data_ptr++) = DNAN;
#ifdef DEBUG
		fprintf(stderr,"%10.2f ",*(data_ptr-1));
#endif
	    }
	} else {
	    /* OK we are inside the valid area but the pointer has to 
	     * be wrapped*/
	    if (rra_pointer >= (signed)rrd.rra_def[chosen_rra].row_cnt) {
		rra_pointer -= rrd.rra_def[chosen_rra].row_cnt;
		if(fseek(in_file,(rra_base+rra_pointer
			       * *ds_cnt
			       * sizeof(rrd_value_t)),SEEK_SET) != 0){
		    rrd_set_error("wrap seek in RRA did fail");
		    for (ii=0;(unsigned)ii<*ds_cnt;ii++)
			free((*ds_namv)[ii]);
		    free(*ds_namv);
		    rrd_free(&rrd);
		    free(*data);
		    *data = NULL;
		    fclose(in_file);
		    return(-1);
		}
#ifdef DEBUG
		fprintf(stderr,"wrap seek ...\n");
#endif	    
	    }
	    
	    if(fread(data_ptr,
		     sizeof(rrd_value_t),
		     *ds_cnt,in_file) != rrd.stat_head->ds_cnt){
		rrd_set_error("fetching cdp from rra");
		for (ii=0;(unsigned)ii<*ds_cnt;ii++)
		    free((*ds_namv)[ii]);
		free(*ds_namv);
		rrd_free(&rrd);
		free(*data);
		*data = NULL;
		fclose(in_file);
		return(-1);
	    }
#ifdef DEBUG
	    fprintf(stderr,"post fetch %li -- ",i);
	    for(ii=0;ii<*ds_cnt;ii++)
		fprintf(stderr,"%10.2f ",*(data_ptr+ii));
#endif
	    data_ptr += *ds_cnt;
	    rra_pointer ++;
	}
#ifdef DEBUG
	    fprintf(stderr,"\n");
#endif	    
	
    }
    rrd_free(&rrd);
    fclose(in_file);
    return(0);
}
コード例 #11
0
ファイル: rrd_create.c プロジェクト: blair/orca
int
rrd_create(int argc, char **argv) 
{
    rrd_t          rrd;
    long                i,long_tmp;
    time_t             last_up;
    struct rrd_time_value last_up_tv;
    char *parsetime_error = NULL;

    /* init last_up */
    last_up = time(NULL)-10;
    /* init rrd clean */
    rrd_init(&rrd);
    /* static header */
    if((rrd.stat_head = calloc(1,sizeof(stat_head_t)))==NULL){
	rrd_set_error("allocating rrd.stat_head");
	return(-1);
    }

    /* live header */
    if((rrd.live_head = calloc(1,sizeof(live_head_t)))==NULL){
	rrd_set_error("allocating rrd.live_head");
	return(-1);
    }

    /* set some defaults */
    strcpy(rrd.stat_head->cookie,RRD_COOKIE);
    strcpy(rrd.stat_head->version,RRD_VERSION);
    rrd.stat_head->float_cookie = FLOAT_COOKIE;
    rrd.stat_head->ds_cnt = 0; /* this will be adjusted later */
    rrd.stat_head->rra_cnt = 0; /* ditto */
    rrd.stat_head->pdp_step = 300; /* 5 minute default */

    /* a default value */
    rrd.ds_def = NULL;
    rrd.rra_def = NULL;
    
    while (1){
	static struct option long_options[] =
	{
	    {"start",      required_argument, 0, 'b'},
	    {"step",        required_argument,0,'s'},
	    {0,0,0,0}
	};
	int option_index = 0;
	int opt;
	opt = getopt_long(argc, argv, "b:s:", 
			  long_options, &option_index);
	
	if (opt == EOF)
	  break;
	
	switch(opt) {
	case 'b':
            if ((parsetime_error = parsetime(optarg, &last_up_tv))) {
                rrd_set_error("start time: %s", parsetime_error );
		rrd_free(&rrd);
                return(-1);
	    }
	    if (last_up_tv.type == RELATIVE_TO_END_TIME ||
		last_up_tv.type == RELATIVE_TO_START_TIME) {
		rrd_set_error("specifying time relative to the 'start' "
                              "or 'end' makes no sense here");
		rrd_free(&rrd);
		return(-1);
	    }

	    last_up = mktime(&last_up_tv.tm) + last_up_tv.offset;
	    
	    if (last_up < 3600*24*365*10){
		rrd_set_error("the first entry to the RRD should be after 1980");
		rrd_free(&rrd);
		return(-1);
	    }	
	    break;

	case 's':
	    long_tmp = atol(optarg);
	    if (long_tmp < 1){
		rrd_set_error("step size should be no less than one second");
		rrd_free(&rrd);
		return(-1);
	    }
	    rrd.stat_head->pdp_step = long_tmp;
	    break;

	case '?':
            if (optopt != 0)
                rrd_set_error("unknown option '%c'", optopt);
            else
                rrd_set_error("unknown option '%s'",argv[optind-1]);
            rrd_free(&rrd);
	    return(-1);
	}
    }
    rrd.live_head->last_up = last_up;

    for(i=optind+1;i<argc;i++){
	char minstr[DS_NAM_SIZE], maxstr[DS_NAM_SIZE];	
	int ii;
	if (strncmp(argv[i],"DS:",3)==0){
	    size_t old_size = sizeof(ds_def_t)*(rrd.stat_head->ds_cnt);
	    if((rrd.ds_def = rrd_realloc(rrd.ds_def,
				     old_size+sizeof(ds_def_t)))==NULL){
		rrd_set_error("allocating rrd.ds_def");
		rrd_free(&rrd);
		return(-1);	
	    }
	    memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t));
	    if (sscanf(&argv[i][3],
		       DS_NAM_FMT ":" DST_FMT ":%lu:%18[^:]:%18[^:]",
		       rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
		       rrd.ds_def[rrd.stat_head->ds_cnt].dst,
		       &rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_mrhb_cnt].u_cnt,
		       minstr,maxstr) == 5){
		/* check for duplicate datasource names */
		for(ii=0;ii<rrd.stat_head->ds_cnt;ii++){
			if(strcmp(rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
			  	  rrd.ds_def[ii].ds_nam) == 0){
				rrd_set_error("Duplicate DS name: %s",rrd.ds_def[ii].ds_nam);
		                rrd_free(&rrd);
                                return(-1);
			}				                                
		}
		if(dst_conv(rrd.ds_def[rrd.stat_head->ds_cnt].dst) == -1){
		    rrd_free(&rrd);
		    return (-1);
		}
		if (minstr[0] == 'U' && minstr[1] == 0)
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val = DNAN;
		else
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val = atof(minstr);
		
		if (maxstr[0] == 'U' && maxstr[1] == 0)
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val = DNAN;
		else
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val  = atof(maxstr);
		
		if (! isnan(rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val) &&
		    ! isnan(rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val) &&
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val
		    >= rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val ) {
		    rrd_set_error("min must be less than max in DS definition");
		    rrd_free(&rrd);
		    return (-1);		
		}
		rrd.stat_head->ds_cnt++;	    
	    } else {
		rrd_set_error("can't parse argument '%s'",argv[i]);
		rrd_free(&rrd);
		return (-1);		
	    }
	} else if (strncmp(argv[i],"RRA:",3)==0){
	    size_t old_size = sizeof(rra_def_t)*(rrd.stat_head->rra_cnt);
	    if((rrd.rra_def = rrd_realloc(rrd.rra_def,
				      old_size+sizeof(rra_def_t)))==NULL){
		rrd_set_error("allocating rrd.rra_def");
		rrd_free(&rrd);
		return(-1);	
	    }
	    memset(&rrd.rra_def[rrd.stat_head->rra_cnt], 0, sizeof(rra_def_t));
	    if (sscanf(&argv[i][4],
		       CF_NAM_FMT ":%lf:%lu:%lu",
		       rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam,
		       &rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_cdp_xff_val].u_val,
		       &rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt,
		       &rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt) == 4){
		if(cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) == -1){
		    rrd_free(&rrd);
		    return (-1);
		}
	        if (rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_cdp_xff_val].u_val<0.0 ||
		    rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_cdp_xff_val].u_val>=1.0) {
		    rrd_set_error("the xff must always be >= 0 and < 1");
		    rrd_free(&rrd);
		    return (-1);
		}
		rrd.stat_head->rra_cnt++;	    		
	    }
	    else {  
		rrd_set_error("can't parse argument '%s'",argv[i]);
		rrd_free(&rrd);
		return (-1);		
	    }

	} else {
	    rrd_set_error("can't parse argument '%s'",argv[i]);
	    rrd_free(&rrd);
            return -1;
	}
    }


    if (rrd.stat_head->rra_cnt < 1){
	rrd_set_error("you must define at least one Round Robin Archive");
	rrd_free(&rrd);
	return(-1);
    }

    if (rrd.stat_head->ds_cnt < 1){
	rrd_set_error("you must define at least one Data Source");
	rrd_free(&rrd);
	return(-1);
    }
    return rrd_create_fn(argv[optind],&rrd);
}
コード例 #12
0
ファイル: rrd_create.c プロジェクト: blair/orca
int
rrd_create_fn(char *file_name, rrd_t *rrd)
{
    unsigned long    i,ii;
    FILE             *rrd_file;
    rrd_value_t       unknown = DNAN ;

    if ((rrd_file = fopen(file_name,"wb")) == NULL ) {
	rrd_set_error("creating '%s': %s",file_name,strerror(errno));
	free(rrd->stat_head);
	free(rrd->ds_def);
	free(rrd->rra_def);
	return(-1);
    }
    
    fwrite(rrd->stat_head,
	   sizeof(stat_head_t), 1, rrd_file);

    fwrite(rrd->ds_def,
	   sizeof(ds_def_t), rrd->stat_head->ds_cnt, rrd_file);

    fwrite(rrd->rra_def,
	   sizeof(rra_def_t), rrd->stat_head->rra_cnt, rrd_file);
    
    fwrite(rrd->live_head,
	   sizeof(live_head_t),1, rrd_file);

    if((rrd->pdp_prep = calloc(1,sizeof(pdp_prep_t))) == NULL){
	rrd_set_error("allocating pdp_prep");
	rrd_free(rrd);
	fclose(rrd_file);
	return(-1);
    }

    strcpy(rrd->pdp_prep->last_ds,"UNKN");

    rrd->pdp_prep->scratch[PDP_val].u_val = 0.0;
    rrd->pdp_prep->scratch[PDP_unkn_sec_cnt].u_cnt = 
	rrd->live_head->last_up % rrd->stat_head->pdp_step;

    for(i=0; i < rrd->stat_head->ds_cnt; i++)
	fwrite( rrd->pdp_prep,sizeof(pdp_prep_t),1,rrd_file);
    
    if((rrd->cdp_prep = calloc(1,sizeof(cdp_prep_t))) == NULL){
	rrd_set_error("allocating cdp_prep");
	rrd_free(rrd);
	fclose(rrd_file);
	return(-1);
    }

    /* can not be zero because we don't know nothing ... */
    rrd->cdp_prep->scratch[CDP_val].u_val = DNAN;
    for(i=0; i < rrd->stat_head->rra_cnt; i++) {

	/* startup missing pdp count */
	rrd->cdp_prep->scratch[CDP_unkn_pdp_cnt].u_cnt = 
	    ((rrd->live_head->last_up -
	     rrd->pdp_prep->scratch[PDP_unkn_sec_cnt].u_cnt)
	    % (rrd->stat_head->pdp_step 
	       * rrd->rra_def[i].pdp_cnt)) / rrd->stat_head->pdp_step;	


	for(ii=0; ii < rrd->stat_head->ds_cnt; ii++) {
	    fwrite( rrd->cdp_prep,sizeof(cdp_prep_t),1,rrd_file);
	}
    }

    /* now, we must make sure that the rest of the rrd
       struct is properly initialized */

    if((rrd->rra_ptr = calloc(1,sizeof(rra_ptr_t))) == NULL) {
	rrd_set_error("allocating rra_ptr");
	rrd_free(rrd);
	fclose(rrd_file);
	return(-1);
    }

    rrd->rra_ptr->cur_row = 0;
    for(i=0; i <rrd->stat_head->rra_cnt; i++)
	fwrite( rrd->rra_ptr,
		sizeof(rra_ptr_t), 1,rrd_file);



    /* write the empty data area */
    for(i=0; 
	i <  rrd->stat_head->rra_cnt;
	i++)
	{
	    for(ii=0; 
		ii <  rrd->rra_def[i].row_cnt 
		    * rrd->stat_head->ds_cnt;
		ii++){
		fwrite(&unknown,sizeof(rrd_value_t),1,rrd_file);
	    }
	}

    /* lets see if we had an error */
    if(ferror(rrd_file)){
	rrd_set_error("a file error occurred while creating '%s'",file_name);
	fclose(rrd_file);	
	rrd_free(rrd);
	return(-1);
    }

    fclose(rrd_file);    
    rrd_free(rrd);
    return (0);
}
コード例 #13
0
ファイル: rrd_restore.c プロジェクト: OPSF/uClinux
int
rrd_restore(int argc, char **argv) 
{
    rrd_t          rrd;
    char          *buf;
	char			rc = 0;
	char			force_overwrite = 0;	

    /* init rrd clean */
    optind = 0; opterr = 0;  /* initialize getopt */
    rrd_init(&rrd);
    if (argc<3) {
		rrd_set_error("usage rrdtool %s [--range-check/-r] [--force-overwrite/-f] file.xml file.rrd",argv[0]);
		return -1;
    }
	
	while (1) {
		static struct option long_options[] =
		{
			{"range-check",      required_argument, 0,  'r'},
			{"force-overwrite",	required_argument, 0,	'f'},
			{0,0,0,0}
		};
		int option_index = 0;
		int opt;
		
		
		opt = getopt_long(argc, argv, "r:f", long_options, &option_index);
		
		if (opt == EOF)
			break;
		
		switch(opt) {
		case 'r':
			rc=1;
			break;
		case 'f':
			force_overwrite=1;
			break;
		default:
			rrd_set_error("usage rrdtool %s [--range-check|-r] [--force-overwrite/-f]  file.xml file.rrd",argv[0]);
                	return -1;
			break;
		}
    }
	
    if (readfile(argv[optind],&buf,0)==-1){
      return -1;
    }
    if (xml2rrd(buf,&rrd,rc)==-1) {
	rrd_free(&rrd);
	free(buf);
	return -1;
    }
    free(buf);
    if(rrd_write(argv[optind+1],&rrd,force_overwrite)==-1){
	rrd_free(&rrd);	
	return -1;	
    };
    rrd_free(&rrd);    
    return 0;
}
コード例 #14
0
ファイル: rrd_dump.c プロジェクト: OPSF/uClinux
int
rrd_dump_r(char *filename)    
{   
    unsigned int i,ii,ix,iii=0;
    time_t       now;
    char         somestring[255];
    rrd_value_t  my_cdp;
    long         rra_base, rra_start, rra_next;
    FILE        *in_file;
    rrd_t        rrd;
    rrd_value_t  value;
    struct tm    tm;
    if(rrd_open(filename, &in_file,&rrd, RRD_READONLY)==-1){
	rrd_free(&rrd);
	return(-1);
    }

    puts("<!-- Round Robin Database Dump -->");
    puts("<rrd>");
    printf("\t<version> %s </version>\n",RRD_VERSION);
    printf("\t<step> %lu </step> <!-- Seconds -->\n",rrd.stat_head->pdp_step);
#if HAVE_STRFTIME
    localtime_r(&rrd.live_head->last_up, &tm);
    strftime(somestring,200,"%Y-%m-%d %H:%M:%S %Z",
	     &tm);
#else
# error "Need strftime"
#endif
    printf("\t<lastupdate> %ld </lastupdate> <!-- %s -->\n\n",
	   rrd.live_head->last_up,somestring);
    for(i=0;i<rrd.stat_head->ds_cnt;i++){
	printf("\t<ds>\n");
	printf("\t\t<name> %s </name>\n",rrd.ds_def[i].ds_nam);
	printf("\t\t<type> %s </type>\n",rrd.ds_def[i].dst);
    if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
	printf("\t\t<minimal_heartbeat> %lu </minimal_heartbeat>\n",rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);
	if (isnan(rrd.ds_def[i].par[DS_min_val].u_val)){
	  printf("\t\t<min> NaN </min>\n");
	} else {
	  printf("\t\t<min> %0.10e </min>\n",rrd.ds_def[i].par[DS_min_val].u_val);
	}
	if (isnan(rrd.ds_def[i].par[DS_max_val].u_val)){
	  printf("\t\t<max> NaN </max>\n");
	} else {
	  printf("\t\t<max> %0.10e </max>\n",rrd.ds_def[i].par[DS_max_val].u_val);
	}
    } else { /* DST_CDEF */
	  char *str;
	  rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),rrd.ds_def,&str);
	  printf("\t\t<cdef> %s </cdef>\n", str);
	  free(str);
	}
	printf("\n\t\t<!-- PDP Status -->\n");
	printf("\t\t<last_ds> %s </last_ds>\n",rrd.pdp_prep[i].last_ds);
	if (isnan(rrd.pdp_prep[i].scratch[PDP_val].u_val)){
	  printf("\t\t<value> NaN </value>\n");
	} else {
	  printf("\t\t<value> %0.10e </value>\n",rrd.pdp_prep[i].scratch[PDP_val].u_val);
	}
	printf("\t\t<unknown_sec> %lu </unknown_sec>\n",
	       rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
	
	printf("\t</ds>\n\n");
    }

    puts("<!-- Round Robin Archives -->");

    rra_base=ftell(in_file);    
    rra_next = rra_base;

    for(i=0;i<rrd.stat_head->rra_cnt;i++){
	
	long timer=0;
	rra_start= rra_next;
	rra_next +=  ( rrd.stat_head->ds_cnt
                      * rrd.rra_def[i].row_cnt
                      * sizeof(rrd_value_t));
	printf("\t<rra>\n");
	printf("\t\t<cf> %s </cf>\n",rrd.rra_def[i].cf_nam);
	printf("\t\t<pdp_per_row> %lu </pdp_per_row> <!-- %lu seconds -->\n\n",
	       rrd.rra_def[i].pdp_cnt, rrd.rra_def[i].pdp_cnt
	       *rrd.stat_head->pdp_step);
	/* support for RRA parameters */
	printf("\t\t<params>\n");
	switch(cf_conv(rrd.rra_def[i].cf_nam)) {
	case CF_HWPREDICT:
	   printf("\t\t<hw_alpha> %0.10e </hw_alpha>\n", 
		  rrd.rra_def[i].par[RRA_hw_alpha].u_val);
	   printf("\t\t<hw_beta> %0.10e </hw_beta>\n", 
		  rrd.rra_def[i].par[RRA_hw_beta].u_val);
	   printf("\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
		  rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
	   break;
	case CF_SEASONAL:
	case CF_DEVSEASONAL:
	   printf("\t\t<seasonal_gamma> %0.10e </seasonal_gamma>\n", 
		  rrd.rra_def[i].par[RRA_seasonal_gamma].u_val);
	   printf("\t\t<seasonal_smooth_idx> %lu </seasonal_smooth_idx>\n",
		  rrd.rra_def[i].par[RRA_seasonal_smooth_idx].u_cnt);
	   printf("\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
		  rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
	   break;
	case CF_FAILURES:
	   printf("\t\t<delta_pos> %0.10e </delta_pos>\n", 
		  rrd.rra_def[i].par[RRA_delta_pos].u_val);
	   printf("\t\t<delta_neg> %0.10e </delta_neg>\n", 
		  rrd.rra_def[i].par[RRA_delta_neg].u_val);
	   printf("\t\t<window_len> %lu </window_len>\n",
		  rrd.rra_def[i].par[RRA_window_len].u_cnt);
	   printf("\t\t<failure_threshold> %lu </failure_threshold>\n",
		  rrd.rra_def[i].par[RRA_failure_threshold].u_cnt);
		  /* fall thru */
	case CF_DEVPREDICT:
	   printf("\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
		  rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
	   break;
	case CF_AVERAGE:
	case CF_MAXIMUM:
	case CF_MINIMUM:
	case CF_LAST:
	default:
	   printf("\t\t<xff> %0.10e </xff>\n", rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
	   break;
	}
	printf("\t\t</params>\n");
	printf("\t\t<cdp_prep>\n");
	for(ii=0;ii<rrd.stat_head->ds_cnt;ii++){
		unsigned long ivalue;
		printf("\t\t\t<ds>\n");
		/* support for exporting all CDP parameters */
		/* parameters common to all CFs */
		    /* primary_val and secondary_val do not need to be saved between updates
			 * so strictly speaking they could be omitted.
			 * However, they can be useful for diagnostic purposes, so are included here. */
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt
			   +ii].scratch[CDP_primary_val].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<primary_value> NaN </primary_value>\n");
			} else {
			   printf("\t\t\t<primary_value> %0.10e </primary_value>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_secondary_val].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<secondary_value> NaN </secondary_value>\n");
			} else {
			   printf("\t\t\t<secondary_value> %0.10e </secondary_value>\n", value);
			}
		switch(cf_conv(rrd.rra_def[i].cf_nam)) {
		case CF_HWPREDICT:
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_intercept].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<intercept> NaN </intercept>\n");
			} else {
			   printf("\t\t\t<intercept> %0.10e </intercept>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_last_intercept].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<last_intercept> NaN </last_intercept>\n");
			} else {
			   printf("\t\t\t<last_intercept> %0.10e </last_intercept>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_slope].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<slope> NaN </slope>\n");
			} else {
			   printf("\t\t\t<slope> %0.10e </slope>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_last_slope].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<last_slope> NaN </last_slope>\n");
			} else {
			   printf("\t\t\t<last_slope> %0.10e </last_slope>\n", value);
			}
			ivalue = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_null_count].u_cnt;
			printf("\t\t\t<nan_count> %lu </nan_count>\n", ivalue);
			ivalue = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_last_null_count].u_cnt;
			printf("\t\t\t<last_nan_count> %lu </last_nan_count>\n", ivalue);
			break;
		case CF_SEASONAL:
		case CF_DEVSEASONAL:
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_seasonal].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<seasonal> NaN </seasonal>\n");
			} else {
			   printf("\t\t\t<seasonal> %0.10e </seasonal>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_last_seasonal].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<last_seasonal> NaN </last_seasonal>\n");
			} else {
			   printf("\t\t\t<last_seasonal> %0.10e </last_seasonal>\n", value);
			}
	        ivalue = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_init_seasonal].u_cnt;
			printf("\t\t\t<init_flag> %lu </init_flag>\n", ivalue);
			break;
		case CF_DEVPREDICT:
			break;
		case CF_FAILURES:
		    {
            unsigned short vidx;
			char *violations_array = (char *) ((void*) 
			   rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch);
			printf("\t\t\t<history> ");
			for (vidx = 0; vidx < rrd.rra_def[i].par[RRA_window_len].u_cnt; ++vidx)
			{
				printf("%d",violations_array[vidx]);
			}
			printf(" </history>\n");
			}
			break;
		case CF_AVERAGE:
		case CF_MAXIMUM:
		case CF_MINIMUM:
		case CF_LAST:
		default:
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_val].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<value> NaN </value>\n");
			} else {
			   printf("\t\t\t<value> %0.10e </value>\n", value);
			}
		    printf("\t\t\t<unknown_datapoints> %lu </unknown_datapoints>\n",
		       rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_unkn_pdp_cnt].u_cnt);
			break;
		}
        printf("\t\t\t</ds>\n");	 
    }
	printf("\t\t</cdp_prep>\n");

	printf("\t\t<database>\n");
	fseek(in_file,(rra_start
		       +(rrd.rra_ptr[i].cur_row+1)
		       * rrd.stat_head->ds_cnt
		       * sizeof(rrd_value_t)),SEEK_SET);
	timer = - (rrd.rra_def[i].row_cnt-1);
	ii=rrd.rra_ptr[i].cur_row;
	for(ix=0;ix<rrd.rra_def[i].row_cnt;ix++){	    
	    ii++;
	    if (ii>=rrd.rra_def[i].row_cnt) {
		fseek(in_file,rra_start,SEEK_SET);
		ii=0; /* wrap if max row cnt is reached */
	    }
	    now = (rrd.live_head->last_up 
		   - rrd.live_head->last_up 
		   % (rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step)) 
		+ (timer*rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step);

	    timer++;
#if HAVE_STRFTIME
	    localtime_r(&now, &tm);
	    strftime(somestring,200,"%Y-%m-%d %H:%M:%S %Z", &tm);
#else
# error "Need strftime"
#endif
	    printf("\t\t\t<!-- %s / %d --> <row>",somestring,(int)now);
	    for(iii=0;iii<rrd.stat_head->ds_cnt;iii++){			 
		fread(&my_cdp,sizeof(rrd_value_t),1,in_file);		
		if (isnan(my_cdp)){
		  printf("<v> NaN </v>");
		} else {
		  printf("<v> %0.10e </v>",my_cdp);
		};
	    }
	    printf("</row>\n");
	}
	printf("\t\t</database>\n\t</rra>\n");
	
    }
    printf("</rrd>\n");
    rrd_free(&rrd);
    fclose(in_file);
    return(0);
}
コード例 #15
0
int rrd_lastupdate_r(const char *filename,
        time_t *ret_last_update,
        unsigned long *ret_ds_count,
        char ***ret_ds_names,
        char ***ret_last_ds)
{
    unsigned long i = 0;
    rrd_t     rrd;
    rrd_file_t *rrd_file;

    rrd_init(&rrd);
    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
    if (rrd_file == NULL) {
        rrd_free(&rrd);
        return (-1);
    }

    *ret_last_update = rrd.live_head->last_up;
    *ret_ds_count = rrd.stat_head->ds_cnt;
    *ret_ds_names = (char **) malloc (rrd.stat_head->ds_cnt * sizeof(char *));
    if (*ret_ds_names == NULL) {
        rrd_set_error ("malloc fetch ret_ds_names array");
        rrd_close (rrd_file);
        rrd_free (&rrd);
        return (-1);
    }
    memset (*ret_ds_names, 0, rrd.stat_head->ds_cnt * sizeof(char *));

    *ret_last_ds = (char **) malloc (rrd.stat_head->ds_cnt * sizeof(char *));
    if (*ret_last_ds == NULL) {
        rrd_set_error ("malloc fetch ret_last_ds array");
        free (*ret_ds_names);
        *ret_ds_names = NULL;
        rrd_close (rrd_file);
        rrd_free (&rrd);
        return (-1);
    }
    memset (*ret_last_ds, 0, rrd.stat_head->ds_cnt * sizeof(char *));

    for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
        (*ret_ds_names)[i] = sprintf_alloc("%s", rrd.ds_def[i].ds_nam);
        (*ret_last_ds)[i] = sprintf_alloc("%s", rrd.pdp_prep[i].last_ds);

        if (((*ret_ds_names)[i] == NULL) || ((*ret_last_ds)[i] == NULL))
            break;
    }

    /* Check if all names and values could be copied and free everything if
     * not. */
    if (i < rrd.stat_head->ds_cnt) {
        rrd_set_error ("sprintf_alloc failed");
        for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
            if ((*ret_ds_names)[i] != NULL)
            {
                free ((*ret_ds_names)[i]);
                (*ret_ds_names)[i] = NULL;
            }
            if ((*ret_last_ds)[i] != NULL)
            {
                free ((*ret_last_ds)[i]);
                (*ret_last_ds)[i] = NULL;
            }
        }
        free (*ret_ds_names);
        *ret_ds_names = NULL;
        free (*ret_last_ds);
        *ret_last_ds = NULL;
        rrd_close (rrd_file);
        rrd_free (&rrd);
        return (-1);
    }

    rrd_free(&rrd);
    rrd_close(rrd_file);
    return (0);
} /* int rrd_lastupdate_r */
コード例 #16
0
int rrd_resize(
    int argc,
    char **argv)
{
    char     *infilename, outfilename[11] = "resize.rrd";
    rrd_t     rrdold, rrdnew;
    rrd_value_t buffer;
    int       version;
    unsigned long l, rra;
    long      modify;
    unsigned long target_rra;
    int       grow = 0, shrink = 0;
    char     *endptr;
    rrd_file_t *rrd_file, *rrd_out_file;

    infilename = argv[1];
    if (!strcmp(infilename, "resize.rrd")) {
        rrd_set_error("resize.rrd is a reserved name");
        return (-1);
    }
    if (argc != 5) {
        rrd_set_error("wrong number of parameters");
        return (-1);
    }

    target_rra = strtol(argv[2], &endptr, 0);

    if (!strcmp(argv[3], "GROW"))
        grow = 1;
    else if (!strcmp(argv[3], "SHRINK"))
        shrink = 1;
    else {
        rrd_set_error("I can only GROW or SHRINK");
        return (-1);
    }

    modify = strtol(argv[4], &endptr, 0);

    if ((modify < 1)) {
        rrd_set_error("Please grow or shrink with at least 1 row");
        return (-1);
    }

    if (shrink)
        modify = -modify;


    rrd_init(&rrdold);
    rrd_file = rrd_open(infilename, &rrdold, RRD_READWRITE | RRD_COPY);
    if (rrd_file == NULL) {
        rrd_free(&rrdold);
        return (-1);
    }

    if (rrd_lock(rrd_file) != 0) {
        rrd_set_error("could not lock original RRD");
        rrd_free(&rrdold);
        rrd_close(rrd_file);
        return (-1);
    }


    if (target_rra >= rrdold.stat_head->rra_cnt) {
        rrd_set_error("no such RRA in this RRD");
        rrd_free(&rrdold);
        rrd_close(rrd_file);
        return (-1);
    }

    if (modify < 0)
        if ((long) rrdold.rra_def[target_rra].row_cnt <= -modify) {
            rrd_set_error("This RRA is not that big");
            rrd_free(&rrdold);
            rrd_close(rrd_file);
            return (-1);
        }

    rrd_init(&rrdnew);
    /* These need to be initialised before calling rrd_open() with 
       the RRD_CREATE flag */

    if ((rrdnew.stat_head = (stat_head_t*)calloc(1, sizeof(stat_head_t))) == NULL) {
        rrd_set_error("allocating stat_head for new RRD");
        rrd_free(&rrdold);
        rrd_close(rrd_file);
        return (-1);
    }
    memcpy(rrdnew.stat_head,rrdold.stat_head,sizeof(stat_head_t));

    if ((rrdnew.rra_def = (rra_def_t *)malloc(sizeof(rra_def_t) * rrdold.stat_head->rra_cnt)) == NULL) {
        rrd_set_error("allocating rra_def for new RRD");
        rrd_free(&rrdnew);
        rrd_free(&rrdold);
        rrd_close(rrd_file);
        return (-1);
    }
    memcpy(rrdnew.rra_def,rrdold.rra_def,sizeof(rra_def_t) * rrdold.stat_head->rra_cnt);

    /* Set this so that the file will be created with the correct size */
    rrdnew.rra_def[target_rra].row_cnt += modify;

    rrd_out_file = rrd_open(outfilename, &rrdnew, RRD_READWRITE | RRD_CREAT);
    if (rrd_out_file == NULL) {
        rrd_set_error("Can't create '%s': %s", outfilename,
                      rrd_strerror(errno));
        rrd_free(&rrdnew);
        rrd_free(&rrdold);
        rrd_close(rrd_file);
        return (-1);
    }
    if (rrd_lock(rrd_out_file) != 0) {
        rrd_set_error("could not lock new RRD");
        rrd_free(&rrdnew);
        rrd_free(&rrdold);
        rrd_close(rrd_file);
        rrd_close(rrd_out_file);
        return (-1);
    }
/*XXX: do one write for those parts of header that are unchanged */
    if ((rrdnew.rra_ptr = (rra_ptr_t *)malloc(sizeof(rra_ptr_t) * rrdold.stat_head->rra_cnt)) == NULL) {
        rrd_set_error("allocating rra_ptr for new RRD");
        rrd_free(&rrdnew);
        rrd_free(&rrdold);
        rrd_close(rrd_file);
        rrd_close(rrd_out_file);
        return (-1);
    }

    /* Put this back the way it was so that the rest of the algorithm
       below remains unchanged, it will be corrected later */
    rrdnew.rra_def[target_rra].row_cnt -= modify;

    rrdnew.ds_def = rrdold.ds_def;
    rrdnew.live_head = rrdold.live_head;
    rrdnew.pdp_prep = rrdold.pdp_prep;
    rrdnew.cdp_prep = rrdold.cdp_prep;
    memcpy(rrdnew.rra_ptr,rrdold.rra_ptr,sizeof(rra_ptr_t) * rrdold.stat_head->rra_cnt);


    version = atoi(rrdold.stat_head->version);
    switch (version) {
    case 4:
        break;        
    case 3:
        break;
    case 1:
        rrdnew.stat_head->version[3] = '3';
        break;
    default:
        rrd_set_error("Do not know how to handle RRD version %s",
                      rrdold.stat_head->version);

        rrdnew.ds_def = NULL;
        rrdnew.live_head = NULL;
        rrdnew.pdp_prep = NULL;
        rrdnew.cdp_prep = NULL;

        rrd_free(&rrdnew);
        rrd_free(&rrdold);
        rrd_close(rrd_file);
        rrd_close(rrd_out_file);
        return (-1);
        break;
    }

/* XXX: Error checking? */
    rrd_write(rrd_out_file, rrdnew.stat_head, sizeof(stat_head_t) * 1);
    rrd_write(rrd_out_file, rrdnew.ds_def,
              sizeof(ds_def_t) * rrdnew.stat_head->ds_cnt);
    rrd_write(rrd_out_file, rrdnew.rra_def,
              sizeof(rra_def_t) * rrdnew.stat_head->rra_cnt);
    rrd_write(rrd_out_file, rrdnew.live_head, sizeof(live_head_t) * 1);
    rrd_write(rrd_out_file, rrdnew.pdp_prep,
              sizeof(pdp_prep_t) * rrdnew.stat_head->ds_cnt);
    rrd_write(rrd_out_file, rrdnew.cdp_prep,
              sizeof(cdp_prep_t) * rrdnew.stat_head->ds_cnt *
              rrdnew.stat_head->rra_cnt);
    rrd_write(rrd_out_file, rrdnew.rra_ptr,
              sizeof(rra_ptr_t) * rrdnew.stat_head->rra_cnt);

    /* Move the CDPs from the old to the new database.
     ** This can be made (much) faster but isn't worth the effort. Clarity
     ** is much more important.
     */

    /* Move data in unmodified RRAs
     */
    l = 0;
    for (rra = 0; rra < target_rra; rra++) {
        l += rrdnew.stat_head->ds_cnt * rrdnew.rra_def[rra].row_cnt;
    }
    while (l > 0) {
        rrd_read(rrd_file, &buffer, sizeof(rrd_value_t) * 1);
        rrd_write(rrd_out_file, &buffer, sizeof(rrd_value_t) * 1);
        l--;
    }
    /* Move data in this RRA, either removing or adding some rows
     */
    if (modify > 0) {
        /* Adding extra rows; insert unknown values just after the
         ** current row number.
         */
        l = rrdnew.stat_head->ds_cnt *
            (rrdnew.rra_ptr[target_rra].cur_row + 1);
        while (l > 0) {
            rrd_read(rrd_file, &buffer, sizeof(rrd_value_t) * 1);
            rrd_write(rrd_out_file, &buffer, sizeof(rrd_value_t) * 1);
            l--;
        }
        buffer = DNAN;
        l = rrdnew.stat_head->ds_cnt * modify;
        while (l > 0) {
            rrd_write(rrd_out_file, &buffer, sizeof(rrd_value_t) * 1);
            l--;
        }
    } else {
        /* Removing rows. Normally this would be just after the cursor
         ** however this may also mean that we wrap to the beginning of
         ** the array.
         */
        signed long int remove_end = 0;

        remove_end =
            (rrdnew.rra_ptr[target_rra].cur_row -
             modify) % rrdnew.rra_def[target_rra].row_cnt;
        if (remove_end <=
            (signed long int) rrdnew.rra_ptr[target_rra].cur_row) {
            while (remove_end >= 0) {
                rrd_seek(rrd_file,
                         sizeof(rrd_value_t) * rrdnew.stat_head->ds_cnt,
                         SEEK_CUR);
                rrdnew.rra_ptr[target_rra].cur_row--;
                rrdnew.rra_def[target_rra].row_cnt--;
                remove_end--;
                modify++;
            }
            remove_end = rrdnew.rra_def[target_rra].row_cnt - 1;
        }
        for (l = 0; l <= rrdnew.rra_ptr[target_rra].cur_row; l++) {
            unsigned int tmp;

            for (tmp = 0; tmp < rrdnew.stat_head->ds_cnt; tmp++) {
                rrd_read(rrd_file, &buffer, sizeof(rrd_value_t) * 1);
                rrd_write(rrd_out_file, &buffer, sizeof(rrd_value_t) * 1);
            }
        }
        while (modify < 0) {
            rrd_seek(rrd_file,
                     sizeof(rrd_value_t) * rrdnew.stat_head->ds_cnt,
                     SEEK_CUR);
            rrdnew.rra_def[target_rra].row_cnt--;
            modify++;
        }
    }
    /* Move the rest of the CDPs
     */
    while (1) {
        ssize_t b_read;
        if ((b_read=rrd_read(rrd_file, &buffer, sizeof(rrd_value_t) * 1)) <= 0)
            break;
        if(rrd_out_file->pos+b_read > rrd_out_file->file_len) {
            fprintf(stderr,"WARNING: ignoring last %zu bytes\nWARNING: if you see this message multiple times for a single file you're in trouble\n", b_read);
            continue;
        }
        rrd_write(rrd_out_file, &buffer, b_read);
    }
    rrdnew.rra_def[target_rra].row_cnt += modify;
    rrd_seek(rrd_out_file,
             sizeof(stat_head_t) +
             sizeof(ds_def_t) * rrdnew.stat_head->ds_cnt, SEEK_SET);
    rrd_write(rrd_out_file, rrdnew.rra_def,
              sizeof(rra_def_t) * rrdnew.stat_head->rra_cnt);
    rrd_seek(rrd_out_file, sizeof(live_head_t), SEEK_CUR);
    rrd_seek(rrd_out_file, sizeof(pdp_prep_t) * rrdnew.stat_head->ds_cnt,
             SEEK_CUR);
    rrd_seek(rrd_out_file,
             sizeof(cdp_prep_t) * rrdnew.stat_head->ds_cnt *
             rrdnew.stat_head->rra_cnt, SEEK_CUR);
    rrd_write(rrd_out_file, rrdnew.rra_ptr,
              sizeof(rra_ptr_t) * rrdnew.stat_head->rra_cnt);
    rrd_close(rrd_file);    
    rrd_close(rrd_out_file);    
    rrd_free(&rrdold);

    rrdnew.ds_def = NULL;
    rrdnew.live_head = NULL;
    rrdnew.pdp_prep = NULL;
    rrdnew.cdp_prep = NULL;

    rrd_free(&rrdnew);
    return (0);
}
コード例 #17
0
ファイル: rrd_modify.c プロジェクト: nirgal/rrdtool-1.x
int handle_modify(const rrd_t *in, const char *outfilename,
		  int argc, char **argv, int optidx,
		  int newstep) {
    // parse add/remove options
    int rc = -1;
    int i;

    const char **del = NULL, **add = NULL;
    rra_mod_op_t *rra_ops = NULL;
    int rcnt = 0, acnt = 0, rraopcnt = 0;
    
    for (i = optidx ; i < argc ; i++) {
	if (strncmp("DEL:", argv[i], 4) == 0 && strlen(argv[i]) > 4) {
		del = (const char **) realloc(del, (rcnt + 2) * sizeof(char*));
	    if (del == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

	    del[rcnt] = strdup(argv[i] + 4);
	    if (del[rcnt] == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

	    rcnt++;
	    del[rcnt] = NULL;
	} else if (strncmp("DS:", argv[i], 3) == 0 && strlen(argv[i]) > 3) {
		add = (const char **) realloc(add, (acnt + 2) * sizeof(char*));
	    if (add == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

	    add[acnt] = strdup(argv[i]);
	    if (add[acnt] == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

	    acnt++;
	    add[acnt] = NULL;
	} else if (strncmp("RRA#", argv[i], 4) == 0 && strlen(argv[i]) > 4) {
		rra_mod_op_t rra_mod; // = { .def = NULL };  // not in VS2013
		rra_mod.def = NULL;
	    char sign;
	    unsigned int number;
	    unsigned int idx;
	    
	    if (sscanf(argv[i] + 4, "%u:%c%u", &idx, &sign, &number) != 3) {
		rrd_set_error("Failed to parse RRA# command");
		rc = -1;
		goto done;
	    }

	    rra_mod.index = idx;
	    switch (sign) {
	    case '=':
	    case '-':
	    case '+':
		rra_mod.index = idx;
		rra_mod.op = sign;
		rra_mod.row_count = number;
		rra_mod.final_row_count = 0;
		break;
	    default:
		rrd_set_error("Failed to parse RRA# command: invalid operation: %c", sign);
		rc = -1;
		goto done;
	    }

	    rra_ops = (rra_mod_op_t *) copy_over_realloc(rra_ops, rraopcnt,
					&rra_mod, 0, sizeof(rra_mod));
	    if (rra_ops == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }
	    rraopcnt++;
	} else if (strncmp("RRA:", argv[i], 4) == 0 && strlen(argv[i]) > 4) {
	    rra_mod_op_t rra_mod;
	    rra_mod.op = 'a';
	    rra_mod.index = -1;
	    rra_mod.def = strdup(argv[i]);

	    if (rra_mod.def == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }

		rra_ops = (rra_mod_op_t *) copy_over_realloc(rra_ops, rraopcnt,
					&rra_mod, 0, sizeof(rra_mod));
	    if (rra_ops == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }
	    rraopcnt++;
	} else if (strncmp("DELRRA:", argv[i], 7) == 0 && strlen(argv[i]) > 7) {
		rra_mod_op_t rra_mod;
		/* NOT in VS2013 C++ allowed
		= { .def = NULL,
				     .op = '=', 
				     .row_count = 0 // eg. deletion
	    };*/
		rra_mod.def = NULL;
		rra_mod.op = '='; 
		rra_mod.row_count = 0; // eg. deletion

	    rra_mod.index = atoi(argv[i] + 7);
	    if (rra_mod.index < 0 ) {
		rrd_set_error("DELRRA requires a non-negative, integer argument");
		rc = -1;
		goto done;
	    }

		rra_ops = (rra_mod_op_t *) copy_over_realloc(rra_ops, rraopcnt,
					&rra_mod, 0, sizeof(rra_mod));
	    if (rra_ops == NULL) {
		rrd_set_error("out of memory");
		rc = -1;
		goto done;
	    }
	    rraopcnt++;
	} else {
	    rrd_set_error("unparseable argument: %s", argv[i]);
	    rc = -1;
	    goto done;
	}
    }
    
    if (rcnt > 0 || acnt > 0 || rraopcnt > 0) {
	unsigned long hashed_name = FnvHash(outfilename);
	rrd_t *out = rrd_modify_r2(in, del, add, rra_ops, rraopcnt, newstep, hashed_name);
    
	if (out == NULL) {
	    goto done;
	}
    
	rc = write_rrd(outfilename, out);
	rrd_free(out);
	free(out);

	if (rc < 0) goto done;
    }
    
    rc = argc;

done:
    if (del) {
	for (const char **c = del ; *c ; c++) {
	    free((void*) *c);
	}
	free(del);
    } 
    if (add) {
	for (const char **c = add ; *c ; c++) {
	    free((void*) *c);
	}
	free(add);
    }
    if (rra_ops) {
	for (i = 0 ; i < rraopcnt ; i++) {
	    if (rra_ops[i].def) free(rra_ops[i].def);
	}
	free(rra_ops);
    }

    return rc;
}
コード例 #18
0
int
rrd_resize(int argc, char **argv)
{
    char		*infilename,outfilename[11]="resize.rrd";
    FILE		*infile,*outfile;
    rrd_t		rrdold,rrdnew;
    rrd_value_t		buffer;
    int			version;
    unsigned long	l,rra;
    long		modify;
    unsigned long	target_rra;
    int			grow=0,shrink=0;
    char		*endptr;

    infilename=argv[1];
    if (!strcmp(infilename,"resize.rrd")) {
        rrd_set_error("resize.rrd is a reserved name");
        return(-1);
    }
    if (argc!=5) {
        rrd_set_error("wrong number of parameters");
        return(-1);
    }

    target_rra=strtol(argv[2],&endptr,0);

    if (!strcmp(argv[3],"GROW")) grow=1;
    else if (!strcmp(argv[3],"SHRINK")) shrink=1;
    else {
        rrd_set_error("I can only GROW or SHRINK");
        return(-1);
    }

    modify=strtol(argv[4],&endptr,0);

    if ((modify<1)) {
        rrd_set_error("Please grow or shrink with at least 1 row");
        return(-1);
    }

    if (shrink) modify = -modify;


    if (rrd_open(infilename, &infile, &rrdold, 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(&rrdold);
        fclose(infile);
        return(-1);
    }

    if (target_rra >= rrdold.stat_head->rra_cnt) {
        rrd_set_error("no such RRA in this RRD");
        rrd_free(&rrdold);
        fclose(infile);
        return(-1);
    }

    if (modify < 0)
	if ((long)rrdold.rra_def[target_rra].row_cnt <= -modify) {
	    rrd_set_error("This RRA is not that big");
	    rrd_free(&rrdold);
	    fclose(infile);
	    return(-1);
	}

    rrdnew.stat_head = rrdold.stat_head;
    rrdnew.ds_def    = rrdold.ds_def;
    rrdnew.rra_def   = rrdold.rra_def;
    rrdnew.live_head = rrdold.live_head;
    rrdnew.pdp_prep  = rrdold.pdp_prep;
    rrdnew.cdp_prep  = rrdold.cdp_prep;
    rrdnew.rra_ptr   = rrdold.rra_ptr;

    version = atoi(rrdold.stat_head->version);
    switch (version) {
	case 3: break;
	case 1: rrdold.stat_head->version[3]='3';
		break;
	default: {
		rrd_set_error("Do not know how to handle RRD version %s",rrdold.stat_head->version);
		rrd_free(&rrdold);	
		fclose(infile);
		return(-1);
		}
    }

    if ((outfile=fopen(outfilename,"wb"))==NULL) {
        rrd_set_error("Can't create '%s'",outfilename);
        return(-1);
    }
    if (LockRRD(outfile) != 0) {
        rrd_set_error("could not lock new RRD");
        rrd_free(&rrdold);
        fclose(infile);
        fclose(outfile);
        return(-1);
    }
    fwrite(rrdnew.stat_head, sizeof(stat_head_t),1,outfile);
    fwrite(rrdnew.ds_def,sizeof(ds_def_t),rrdnew.stat_head->ds_cnt,outfile);
    fwrite(rrdnew.rra_def,sizeof(rra_def_t),rrdnew.stat_head->rra_cnt,outfile);
    fwrite(rrdnew.live_head,sizeof(live_head_t),1,outfile);
    fwrite(rrdnew.pdp_prep,sizeof(pdp_prep_t),rrdnew.stat_head->ds_cnt,outfile);
    fwrite(rrdnew.cdp_prep,sizeof(cdp_prep_t),rrdnew.stat_head->ds_cnt*rrdnew.stat_head->rra_cnt,outfile);
    fwrite(rrdnew.rra_ptr,sizeof(rra_ptr_t),rrdnew.stat_head->rra_cnt,outfile);

    /* Move the CDPs from the old to the new database.
    ** This can be made (much) faster but isn't worth the effort. Clarity
    ** is much more important.
    */

    /* Move data in unmodified RRAs
    */
    l=0;
    for (rra=0;rra<target_rra;rra++) {
        l+=rrdnew.stat_head->ds_cnt * rrdnew.rra_def[rra].row_cnt;
    }
    while (l>0) {
        fread(&buffer,sizeof(rrd_value_t),1,infile);
        fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
        l--;
    }
    /* Move data in this RRA, either removing or adding some rows
    */
    if (modify>0) {
        /* Adding extra rows; insert unknown values just after the
        ** current row number.
        */
        l = rrdnew.stat_head->ds_cnt * (rrdnew.rra_ptr[target_rra].cur_row+1);
        while (l>0) {
            fread(&buffer,sizeof(rrd_value_t),1,infile);
            fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
            l--;
        }
        buffer=DNAN;
        l=rrdnew.stat_head->ds_cnt * modify;
        while (l>0) {
            fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
            l--;
        }
    } else {
        /* Removing rows. Normally this would be just after the cursor
        ** however this may also mean that we wrap to the beginning of
        ** the array.
        */
        signed long int remove_end=0;

        remove_end=(rrdnew.rra_ptr[target_rra].cur_row-modify)%rrdnew.rra_def[target_rra].row_cnt;
        if (remove_end <= (signed long int)rrdnew.rra_ptr[target_rra].cur_row) {
            while (remove_end >= 0) {
                fseek(infile,sizeof(rrd_value_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
                rrdnew.rra_ptr[target_rra].cur_row--;
                rrdnew.rra_def[target_rra].row_cnt--;
                remove_end--;
                modify++;
            }
            remove_end=rrdnew.rra_def[target_rra].row_cnt-1;
        }
        for (l=0;l<=rrdnew.rra_ptr[target_rra].cur_row;l++) {
            unsigned int tmp;
            for (tmp=0;tmp<rrdnew.stat_head->ds_cnt;tmp++) {
                fread(&buffer,sizeof(rrd_value_t),1,infile);
                fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
            }
        }
        while (modify<0) {
            fseek(infile,sizeof(rrd_value_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
            rrdnew.rra_def[target_rra].row_cnt--;
            modify++;
        }
    }
    /* Move the rest of the CDPs
    */
    while (1) {
	fread(&buffer,sizeof(rrd_value_t),1,infile);
	if (feof(infile))
	    break;
        fwrite(&buffer,sizeof(rrd_value_t),1,outfile);
    }
    rrdnew.rra_def[target_rra].row_cnt += modify;
    fseek(outfile,sizeof(stat_head_t)+sizeof(ds_def_t)*rrdnew.stat_head->ds_cnt,SEEK_SET);
    fwrite(rrdnew.rra_def,sizeof(rra_def_t),rrdnew.stat_head->rra_cnt, outfile);
    fseek(outfile,sizeof(live_head_t),SEEK_CUR);
    fseek(outfile,sizeof(pdp_prep_t)*rrdnew.stat_head->ds_cnt,SEEK_CUR);
    fseek(outfile,sizeof(cdp_prep_t)*rrdnew.stat_head->ds_cnt*rrdnew.stat_head->rra_cnt,SEEK_CUR);
    fwrite(rrdnew.rra_ptr,sizeof(rra_ptr_t),rrdnew.stat_head->rra_cnt, outfile);
    
    fclose(outfile);
    rrd_free(&rrdold);
    fclose(infile);
    return(0);
}