Esempio n. 1
0
int rrd_close(
    rrd_file_t *rrd_file)
{
    rrd_simple_file_t *rrd_simple_file;
    rrd_simple_file = (rrd_simple_file_t *)rrd_file->pvt;
    int       ret;

#ifdef HAVE_MMAP
    ret = munmap(rrd_simple_file->file_start, rrd_file->file_len);
    if (ret != 0)
        rrd_set_error("munmap rrd_file: %s", rrd_strerror(errno));
#endif
#ifdef HAVE_LIBRADOS
    if (rrd_file->rados)
        ret = rrd_rados_close(rrd_file->rados);
    else
#endif
    ret = close(rrd_simple_file->fd);

    if (ret != 0)
        rrd_set_error("closing file: %s", rrd_strerror(errno));
    free(rrd_file->pvt);
    free(rrd_file);
    rrd_file = NULL;
    return ret;
}
Esempio n. 2
0
int write_file(
    const char *file_name,
    rrd_t *rrd)
{
    FILE     *fh;

#ifdef HAVE_LIBRADOS
    if (strncmp("ceph//", file_name, 6) == 0) {
      return rrd_rados_create(file_name + 6, rrd);
    }
#endif

    if (strcmp("-", file_name) == 0)
        fh = stdout;
    else {
        int       fd_flags = O_WRONLY | O_CREAT;
        int       fd;

#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
        fd_flags |= O_BINARY;
#endif

        if (opt_force_overwrite == 0)
            fd_flags |= O_EXCL;

        fd = open(file_name, fd_flags, 0666);
        if (fd == -1) {
            rrd_set_error("creating '%s': %s", file_name,
                          rrd_strerror(errno));
            return (-1);
        }

        fh = fdopen(fd, "wb");
        if (fh == NULL) {
            rrd_set_error("fdopen failed: %s", rrd_strerror(errno));
            close(fd);
            return (-1);
        }
    }

    int rc = write_fh(fh, rrd);

    /* lets see if we had an error */
    if (ferror(fh)) {
        rrd_set_error("a file error occurred while creating '%s': %s", file_name,
            rrd_strerror(errno));
        fclose(fh);
        if (strcmp("-", file_name) != 0)
            unlink(file_name);
        return (-1);
    }

    fclose(fh);
    
    return rc;
}
Esempio n. 3
0
int getDouble(const char* v, double *val,char**extra) {
  /* try to execute the parser */
  /* NOTE that this may be a bit different from the original parser */
  char *old_locale;
  *extra=NULL;
  old_locale = setlocale(LC_NUMERIC, "C");
  errno = 0;
  *val = strtod(v,extra);
  if (errno > 0) {
      rrd_set_error("converting '%s' to float: %s", v, rrd_strerror(errno));
      setlocale(LC_NUMERIC, old_locale);
      return -1;
  };
  setlocale(LC_NUMERIC, old_locale);

  *val=strtod(v,extra);
  /* and error handling */
  if (extra==NULL) {
    return 0;
  } else {
    if (*extra==v) {
      return -1; /* failed miserably */
    }  else {
      if ((*extra)[0]==0) { return 0; }
      return 1; /* got extra bytes */
    }
  }
  /* not found, so return error */
  return -2;
}
Esempio n. 4
0
off_t rrd_seek(
    rrd_file_t *rrd_file,
    off_t off,
    int whence)
{
    off_t     ret = 0;
#ifndef HAVE_MMAP
    rrd_simple_file_t *rrd_simple_file;
    rrd_simple_file = (rrd_simple_file_t *)rrd_file->pvt;
#endif
 
#ifdef HAVE_MMAP
    if (whence == SEEK_SET)
        rrd_file->pos = off;
    else if (whence == SEEK_CUR)
        rrd_file->pos += off;
    else if (whence == SEEK_END)
        rrd_file->pos = rrd_file->file_len + off;
#else
    ret = lseek(rrd_simple_file->fd, off, whence);
    if (ret < 0)
        rrd_set_error("lseek: %s", rrd_strerror(errno));
    rrd_file->pos = ret;
#endif
    /* mimic fseek, which returns 0 upon success */
    return ret < 0;     /*XXX: or just ret to mimic lseek */
}
Esempio n. 5
0
int rrd_dump_opt_r(
    const char *filename,
    char *outname,
    int opt_noheader)
{
    FILE     *out_file;
    int       res;

    out_file = NULL;
    if (outname) {
        if (!(out_file = fopen(outname, "w"))) {
            return (-1);
        }
    } else {
        out_file = stdout;
    }

    res = rrd_dump_cb_r(filename, opt_noheader, rrd_dump_opt_cb_fileout, (void *)out_file);

    if (fflush(out_file) != 0) {
        rrd_set_error("error flushing output: %s", rrd_strerror(errno));
        res = -1;
    }
    if (out_file != stdout) {
        fclose(out_file);
        if (res != 0)
            unlink(outname);
    }

    return res;
}
Esempio n. 6
0
/* get_path: Return a path name appropriate to be sent to the daemon.
 *
 * When talking to a local daemon (thru a UNIX socket), relative path names
 * are resolved to absolute path names to allow for transparent integration
 * into existing solutions (as requested by Tobi). Else, absolute path names
 * are not allowed, since path name translation is done by the server.
 *
 * One must hold `lock' when calling this function. */
static const char *get_path (const char *path, char *resolved_path) /* {{{ */
{
  const char *ret = path;
  int is_unix = 0;

  if ((path == NULL) || (resolved_path == NULL) || (sd_path == NULL))
    return (NULL);

  if ((*sd_path == '/')
      || (strncmp ("unix:", sd_path, strlen ("unix:")) == 0))
    is_unix = 1;

  if (is_unix)
  {
    ret = realpath(path, resolved_path);
    if (ret == NULL)
      rrd_set_error("realpath(%s): %s", path, rrd_strerror(errno));
    return ret;
  }
  else
  {
    if (*path == '/') /* not absolute path */
    {
      rrd_set_error ("absolute path names not allowed when talking "
          "to a remote daemon");
      return NULL;
    }
  }

  return path;
} /* }}} char *get_path */
Esempio n. 7
0
/* convenience function; if there is a daemon specified, or if we can
 * detect one from the environment, then flush the file.  Otherwise, no-op
 */
int rrdc_flush_if_daemon (const char *opt_daemon, const char *filename) /* {{{ */
{
  int status = 0;

  rrdc_connect(opt_daemon);

  if (rrdc_is_connected(opt_daemon))
  {
    rrd_clear_error();
    status = rrdc_flush (filename);

    if (status != 0 && !rrd_test_error())
    {
      if (status > 0)
      {
        rrd_set_error("rrdc_flush (%s) failed: %s",
                      filename, rrd_strerror(status));
      }
      else if (status < 0)
      {
        rrd_set_error("rrdc_flush (%s) failed with status %i.",
                      filename, status);
      }
    }
  } /* if (rrdc_is_connected(..)) */

  return status;
} /* }}} int rrdc_flush_if_daemon */
Esempio n. 8
0
static int get_xml_time_t(
    xmlTextReaderPtr reader,
    time_t *value)
{    
    xmlChar *text;
    time_t temp;    
    if ((text = get_xml_text(reader)) != NULL){
        errno = 0;        
#if SIZEOF_TIME_T == 4
        temp = strtol((char *)text,NULL, 0);
#elif SIZEOF_TIME_T == 8
        temp = strtoll((char *)text,NULL, 0);        
#else
#error "Don't know how to deal with TIME_T other than 4 or 8 bytes"
#endif    
        if (errno>0){
            rrd_set_error("ling %d: get_xml_time_t from '%s' %s",
                          xmlTextReaderGetParserLineNumber(reader),
                          text,rrd_strerror(errno));
            xmlFree(text);            
            return -1;
        }
        xmlFree(text);            
        *value = temp;
        return 0;
    }
    return -1;
} /* get_xml_time_t */
Esempio n. 9
0
static int readfile(
    const char *file_name,
    char **buffer,
    int skipfirst)
{
    long      writecnt = 0, totalcnt = MEMBLK;
    long      offset = 0;
    FILE     *input = NULL;
    char      c;

    if ((strcmp("-", file_name) == 0)) {
        input = stdin;
    } else {
        if ((input = fopen(file_name, "rb")) == NULL) {
            rrd_set_error("opening '%s': %s", file_name, rrd_strerror(errno));
            return (-1);
        }
    }
    if (skipfirst) {
        do {
            c = getc(input);
            offset++;
        } while (c != '\n' && !feof(input));
    }
    if (strcmp("-", file_name)) {
        fseek(input, 0, SEEK_END);
        /* have extra space for detecting EOF without realloc */
        totalcnt = (ftell(input) + 1) / sizeof(char) - offset;
        if (totalcnt < MEMBLK)
            totalcnt = MEMBLK;  /* sanitize */
        fseek(input, offset * sizeof(char), SEEK_SET);
    }
    if (((*buffer) = (char *) malloc((totalcnt + 4) * sizeof(char))) == NULL) {
        perror("Allocate Buffer:");
        exit(1);
    };
    do {
        writecnt +=
            fread((*buffer) + writecnt, 1,
                  (totalcnt - writecnt) * sizeof(char), input);
        if (writecnt >= totalcnt) {
            totalcnt += MEMBLK;
            if (((*buffer) =
                 rrd_realloc((*buffer),
                             (totalcnt + 4) * sizeof(char))) == NULL) {
                perror("Realloc Buffer:");
                exit(1);
            };
        }
    } while (!feof(input));
    (*buffer)[writecnt] = '\0';
    if (strcmp("-", file_name) != 0) {
        fclose(input);
    };
    return writecnt;
}
Esempio n. 10
0
int rrdc_connect (const char *addr) /* {{{ */
{
  int status = 0;

  if (addr == NULL) {
    addr = getenv (ENV_RRDCACHED_ADDRESS);
  }

  if (addr == NULL || strcmp(addr,"") == 0 ) {
    addr = NULL;
    return 0;   
  }

  pthread_mutex_lock(&lock);

  if (sd >= 0 && sd_path != NULL && strcmp(addr, sd_path) == 0)
  {
    /* connection to the same daemon; use cached connection */
    pthread_mutex_unlock (&lock);
    return (0);
  }
  else
  {
    close_connection();
  }

  rrd_clear_error ();
  if (strncmp ("unix:", addr, strlen ("unix:")) == 0)
    status = rrdc_connect_unix (addr + strlen ("unix:"));
  else if (addr[0] == '/')
    status = rrdc_connect_unix (addr);
  else
    status = rrdc_connect_network(addr);

  if (status == 0 && sd >= 0)
    sd_path = strdup(addr);
  else
  {
    char *err = rrd_test_error () ? rrd_get_error () : "Internal error";
    /* err points the string that gets written to by rrd_set_error(), thus we
     * cannot pass it to that function */
    err = strdup (err);
    rrd_set_error("Unable to connect to rrdcached: %s",
                  (status < 0)
                  ? (err ? err : "Internal error")
                  : rrd_strerror (status));
    if (err != NULL)
      free (err);
  }

  pthread_mutex_unlock (&lock);
  return (status);
} /* }}} int rrdc_connect */
Esempio n. 11
0
/* Print list of in-core pages of a the current rrd_file.  */
static
void mincore_print(
    rrd_file_t *rrd_file,
    char *mark)
{
    rrd_simple_file_t *rrd_simple_file;
    rrd_simple_file = (rrd_simple_file_t *)rrd_file->pvt;
#ifdef HAVE_MMAP
    /* pretty print blocks in core */
    size_t     off;
    unsigned char *vec;
    ssize_t   _page_size = sysconf(_SC_PAGESIZE);

    off = rrd_file->file_len +
        ((rrd_file->file_len + _page_size - 1) / _page_size);
    vec = malloc(off);
    if (vec != NULL) {
        memset(vec, 0, off);
        if (mincore(rrd_simple_file->file_start, rrd_file->file_len, vec) == 0) {
            int       prev;
            unsigned  is_in = 0, was_in = 0;

            for (off = 0, prev = 0; off < rrd_file->file_len; ++off) {
                is_in = vec[off] & 1;   /* if lsb set then is core resident */
                if (off == 0)
                    was_in = is_in;
                if (was_in != is_in) {
                    fprintf(stderr, "%s: %sin core: %p len %ld\n", mark,
                            was_in ? "" : "not ", vec + prev, off - prev);
                    was_in = is_in;
                    prev = off;
                }
            }
            fprintf(stderr,
                    "%s: %sin core: %p len %ld\n", mark,
                    was_in ? "" : "not ", vec + prev, off - prev);
        } else
            fprintf(stderr, "mincore: %s", rrd_strerror(errno));
    }
#else
    fprintf(stderr, "sorry mincore only works with mmap");
#endif
}
Esempio n. 12
0
static int get_xml_ulong(
    xmlTextReaderPtr reader,
    unsigned long *value)
{
    
    xmlChar *text;
    unsigned long temp;    
    if ((text = get_xml_text(reader)) != NULL){
        errno = 0;        
        temp = strtoul((char *)text,NULL, 0);        
        if (errno>0){
            rrd_set_error("ling %d: get_xml_ulong from '%s' %s",
                          xmlTextReaderGetParserLineNumber(reader),
                          text,rrd_strerror(errno));
            xmlFree(text);            
            return -1;
        }
        xmlFree(text);
        *value = temp;        
        return 0;
    }
    return -1;
} /* get_xml_ulong */
Esempio n. 13
0
static int get_xml_double(
    xmlTextReaderPtr reader,
    double *value)
{
    
    xmlChar *text;
    double temp;    
    if ((text = get_xml_text(reader))!= NULL){
        if (xmlStrcasestr(text,(xmlChar *)"nan")){
            *value = DNAN;
            xmlFree(text);
            return 0;            
        }
        else if (xmlStrcasestr(text,(xmlChar *)"-inf")){
            *value = -DINF;
            xmlFree(text);
            return 0;            
        }
        else if (xmlStrcasestr(text,(xmlChar *)"+inf")
                 || xmlStrcasestr(text,(xmlChar *)"inf")){
            *value = DINF;
            xmlFree(text);
            return 0;            
        }        
        if ( rrd_strtodbl((char *)text,NULL, &temp, NULL) != 2 ){
            rrd_set_error("ling %d: get_xml_double from '%s' %s",
                          xmlTextReaderGetParserLineNumber(reader),
                          text,rrd_strerror(errno));
            xmlFree(text);
            return -1;
        }
        xmlFree(text);        
        *value = temp;
        return 0;
    }
    return -1;
} /* get_xml_double */
Esempio n. 14
0
/* HandleInputLine is NOT thread safe - due to readdir issues,
   resolving them portably is not really simple. */
static int HandleInputLine(
    int argc,
    char **argv,
    FILE * out)
{
#if defined(HAVE_OPENDIR) && defined (HAVE_READDIR)
    DIR      *curdir;   /* to read current dir with ls */
    struct dirent *dent;
#endif

    /* Reset errno to 0 before we start.
     */
    if (RemoteMode) {
        if (argc > 1 && strcmp("quit", argv[1]) == 0) {
            if (argc != 2) {
                printf("ERROR: invalid parameter count for quit\n");
                return (1);
            }
            exit(0);
        }
#if defined(HAVE_OPENDIR) && defined(HAVE_READDIR) && defined(HAVE_CHDIR) && defined(HAVE_SYS_STAT_H)
        if (argc > 1 && strcmp("cd", argv[1]) == 0) {
            if (argc != 3) {
                printf("ERROR: invalid parameter count for cd\n");
                return (1);
            }
#if ! defined(HAVE_CHROOT) && defined(HAVE_GETUID)
            if (getuid() == 0 && !ChangeRoot) {
                printf
                    ("ERROR: chdir security problem - rrdtool is running as "
                     "root but not chroot!\n");
                return (1);
            }
#endif
            if (chdir(argv[2]) != 0){
                printf("ERROR: chdir %s %s\n", argv[2], rrd_strerror(errno));
                return (1);
            }
            return (0);
        }
        if (argc > 1 && strcmp("pwd", argv[1]) == 0) {
            char     *cwd;      /* To hold current working dir on call to pwd */
            if (argc != 2) {
                printf("ERROR: invalid parameter count for pwd\n");
                return (1);
            }
#ifdef MAXPATH
            cwd = getcwd(NULL, MAXPATH);
#elif defined(HAVE_GET_CURRENT_DIR_NAME)
            cwd = get_current_dir_name();
#else
#error "You must have either MAXPATH or get_current_dir_name()"
#endif
            if (cwd == NULL) {
                printf("ERROR: getcwd %s\n", rrd_strerror(errno));
                return (1);
            }
            printf("%s\n", cwd);
            free(cwd);
            return (0);
        }
        if (argc > 1 && strcmp("mkdir", argv[1]) == 0) {
            if (argc != 3) {
                printf("ERROR: invalid parameter count for mkdir\n");
                return (1);
            }
#if ! defined(HAVE_CHROOT) && defined(HAVE_GETUID)
            if (getuid() == 0 && !ChangeRoot) {
                printf
                    ("ERROR: mkdir security problem - rrdtool is running as "
                     "root but not chroot!\n");
                return (1);
            }
#endif
            if(mkdir(argv[2], 0777)!=0){
                printf("ERROR: mkdir %s: %s\n", argv[2],rrd_strerror(errno));
                return (1);
            }
            return (0);
        }
        if (argc > 1 && strcmp("ls", argv[1]) == 0) {
            if (argc != 2) {
                printf("ERROR: invalid parameter count for ls\n");
                return (1);
            }
            if ((curdir = opendir(".")) != NULL) {
                struct stat st;
                while ((dent = readdir(curdir)) != NULL) {
                    if (!stat(dent->d_name, &st)) {
                        if (S_ISDIR(st.st_mode)) {
                            printf("d %s\n", dent->d_name);
                        }
                        if (strlen(dent->d_name) > 4 && S_ISREG(st.st_mode)) {
                            if (!strcmp
                                (dent->d_name + NAMLEN(dent) - 4, ".rrd")
                                || !strcmp(dent->d_name + NAMLEN(dent) - 4,
                                           ".RRD")) {
                                printf("- %s\n", dent->d_name);
                            }
                        }
                    }
                }
                closedir(curdir);
            } else {
                printf("ERROR: opendir .: %s\n", rrd_strerror(errno));
                return (errno);
            }
            return (0);
        }
#endif                          /* opendir and readdir */

    }
    if (argc < 3
        || strcmp("help", argv[1]) == 0
        || strcmp("--help", argv[1]) == 0
        || strcmp("-help", argv[1]) == 0
        || strcmp("-?", argv[1]) == 0 || strcmp("-h", argv[1]) == 0) {
        PrintUsage("");
        return 0;
    }

    if (strcmp("create", argv[1]) == 0)
        rrd_create(argc - 1, &argv[1]);
    else if (strcmp("dump", argv[1]) == 0)
        rrd_dump(argc - 1, &argv[1]);
    else if (strcmp("info", argv[1]) == 0 || strcmp("updatev", argv[1]) == 0) {
        rrd_info_t *data;

        if (strcmp("info", argv[1]) == 0)

            data = rrd_info(argc - 1, &argv[1]);
        else
            data = rrd_update_v(argc - 1, &argv[1]);
        rrd_info_print(data);
        rrd_info_free(data);
    }
    else if (strcmp("list", argv[1]) == 0) {
        char *list;
        list = rrd_list(argc - 1, &argv[1]);

	if (list) {
	  printf("%s", list);
	  free(list);
	}
    }
    else if (strcmp("--version", argv[1]) == 0 ||
             strcmp("version", argv[1]) == 0 ||
             strcmp("v", argv[1]) == 0 ||
             strcmp("-v", argv[1]) == 0 || strcmp("-version", argv[1]) == 0)
        printf("RRDtool " PACKAGE_VERSION
               "  Copyright by Tobi Oetiker (%f)\n",
               rrd_version());
    else if (strcmp("restore", argv[1]) == 0)
#ifdef HAVE_RRD_RESTORE
        rrd_restore(argc - 1, &argv[1]);
#else
	rrd_set_error("the instance of rrdtool has been compiled without XML import functions");
#endif
    else if (strcmp("resize", argv[1]) == 0)
Esempio n. 15
0
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

}
Esempio n. 16
0
int
rrd_open(const char *file_name, FILE **in_file, rrd_t *rrd, int rdwr)    
{

    
    char *mode = NULL;
    int version;
    
    rrd_init(rrd);
    if (rdwr == RRD_READONLY) {
        mode = "rb";
    } else {
        mode = "rb+";
    }
    
    if (((*in_file) = fopen(file_name,mode)) == NULL ){
        rrd_set_error("opening '%s': %s",file_name, rrd_strerror(errno));
        return (-1);
    }

#ifdef HAVE_POSIX_FADVISE
    /* In general we need no read-ahead when dealing with rrd_files.
       When we stop reading, it is highly unlikely that we start up again.
       In this manner we actually save time and diskaccess (and buffer cache).
       Thanks to Dave Plonka for the Idea of using POSIX_FADV_RANDOM here. */       
    /* if (0 != posix_fadvise(fileno(*in_file), 0, 0, POSIX_FADV_RANDOM)) {
        rrd_set_error("setting POSIX_FADV_RANDOM on '%s': %s",file_name, rrd_strerror(errno));
        fclose(*in_file);
        return(-1); */

        /* if it does not work, then this is sad, but we should not quit */
     posix_fadvise(fileno(*in_file), 0, 0, POSIX_FADV_RANDOM);
        
     /*     }     */
#endif

/*
        if (rdwr == RRD_READWRITE)
        {
           if (setvbuf((*in_file),NULL,_IONBF,2)) {
                  rrd_set_error("failed to disable the stream buffer\n");
                  return (-1);
           }
        }
*/
    
#define MYFREAD(MYVAR,MYVART,MYCNT) \
    if ((MYVAR = malloc(sizeof(MYVART) * MYCNT)) == NULL) {\
        rrd_set_error("" #MYVAR " malloc"); \
        fclose(*in_file); \
        return (-1); } \
    fread(MYVAR,sizeof(MYVART),MYCNT, *in_file); 


    MYFREAD(rrd->stat_head, stat_head_t,  1)
    /* lets see if the first read worked */
    if (ferror( *in_file ) || feof(*in_file)) {
        rrd_set_error("reading the cookie off %s faild",file_name);
        fclose(*in_file);
        return(-1);
    }        

        /* lets do some test if we are on track ... */
        if (strncmp(rrd->stat_head->cookie,RRD_COOKIE,4) != 0){
            rrd_set_error("'%s' is not an RRD file",file_name);
            free(rrd->stat_head);
            rrd->stat_head = NULL; 
            fclose(*in_file);
            return(-1);}

        if (rrd->stat_head->float_cookie != FLOAT_COOKIE){
            rrd_set_error("This RRD was created on other architecture");
            free(rrd->stat_head);
            rrd->stat_head = NULL; 
            fclose(*in_file);
            return(-1);}

    version = atoi(rrd->stat_head->version);

        if (version > atoi(RRD_VERSION)){
            rrd_set_error("can't handle RRD file version %s",
                        rrd->stat_head->version);
            free(rrd->stat_head);
            rrd->stat_head = NULL; 
            fclose(*in_file);
            return(-1);}


    MYFREAD(rrd->ds_def,    ds_def_t,     rrd->stat_head->ds_cnt)
    MYFREAD(rrd->rra_def,   rra_def_t,    rrd->stat_head->rra_cnt)
    /* handle different format for the live_head */
    if(version < 3) {
            rrd->live_head = (live_head_t *)malloc(sizeof(live_head_t));
            if(rrd->live_head == NULL) {
                rrd_set_error("live_head_t malloc");
                fclose(*in_file); 
                return (-1);
            }
                fread(&rrd->live_head->last_up, sizeof(long), 1, *in_file); 
                rrd->live_head->last_up_usec = 0;
    }
    else {
            MYFREAD(rrd->live_head, live_head_t, 1)
    }
    MYFREAD(rrd->pdp_prep,  pdp_prep_t,   rrd->stat_head->ds_cnt)
    MYFREAD(rrd->cdp_prep,  cdp_prep_t,   (rrd->stat_head->rra_cnt
                                             * rrd->stat_head->ds_cnt))
    MYFREAD(rrd->rra_ptr,   rra_ptr_t,    rrd->stat_head->rra_cnt)
#undef MYFREAD

    return(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);
}
Esempio n. 18
0
rrd_file_t *rrd_open(
    const char *const file_name,
    rrd_t *rrd,
    unsigned rdwr)
{
    unsigned long ui;
    int       flags = 0;
    int       version;

#ifdef HAVE_MMAP
    char     *data = MAP_FAILED;
#endif
    off_t     offset = 0;
    struct stat statb;
    rrd_file_t *rrd_file = NULL;
    rrd_simple_file_t *rrd_simple_file = NULL;
    size_t     newfile_size = 0;
    size_t header_len, value_cnt, data_len;

    /* Are we creating a new file? */
    if((rdwr & RRD_CREAT) && (rrd->stat_head != NULL))
    {
        header_len = rrd_get_header_size(rrd);

        value_cnt = 0;
        for (ui = 0; ui < rrd->stat_head->rra_cnt; ui++)
            value_cnt += rrd->stat_head->ds_cnt * rrd->rra_def[ui].row_cnt;

        data_len = sizeof(rrd_value_t) * value_cnt;

        newfile_size = header_len + data_len;
    }
    
    rrd_file = (rrd_file_t*)malloc(sizeof(rrd_file_t));
    if (rrd_file == NULL) {
        rrd_set_error("allocating rrd_file descriptor for '%s'", file_name);
        return NULL;
    }
    memset(rrd_file, 0, sizeof(rrd_file_t));
    rrd_file->rrd = rrd;
    
    rrd_file->pvt = malloc(sizeof(rrd_simple_file_t));
    if(rrd_file->pvt == NULL) {
        rrd_set_error("allocating rrd_simple_file for '%s'", file_name);
        return NULL;
    }
    memset(rrd_file->pvt, 0, sizeof(rrd_simple_file_t));
    rrd_simple_file = (rrd_simple_file_t *)rrd_file->pvt;

#ifdef DEBUG
    if ((rdwr & (RRD_READONLY | RRD_READWRITE)) ==
        (RRD_READONLY | RRD_READWRITE)) {
        /* Both READONLY and READWRITE were given, which is invalid.  */
        rrd_set_error("in read/write request mask");
        exit(-1);
    }
#endif

#ifdef HAVE_MMAP
    rrd_simple_file->mm_prot = PROT_READ;
    rrd_simple_file->mm_flags = 0;
#endif

    if (rdwr & RRD_READONLY) {
        flags |= O_RDONLY;
#ifdef HAVE_MMAP
# if !defined(AIX)
        rrd_simple_file->mm_flags = MAP_PRIVATE;
# endif
# ifdef MAP_NORESERVE
        rrd_simple_file->mm_flags |= MAP_NORESERVE;  /* readonly, so no swap backing needed */
# endif
#endif
    } else {
        if (rdwr & RRD_READWRITE) {
            flags |= O_RDWR;
#ifdef HAVE_MMAP 
            rrd_simple_file->mm_flags = MAP_SHARED; 
            rrd_simple_file->mm_prot |= PROT_WRITE; 
#endif 
        }
        if (rdwr & RRD_CREAT) {
            flags |= (O_CREAT | O_TRUNC);
        }
        if (rdwr & RRD_EXCL) {
            flags |= O_EXCL;
        }
    }
    if (rdwr & RRD_READAHEAD) {
#ifdef MAP_POPULATE
        rrd_simple_file->mm_flags |= MAP_POPULATE;   /* populate ptes and data */
#endif
#if defined MAP_NONBLOCK
        rrd_simple_file->mm_flags |= MAP_NONBLOCK;   /* just populate ptes */
#endif
    }
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
    flags |= O_BINARY;
#endif

    if ((rrd_simple_file->fd = open(file_name, flags, 0666)) < 0) {
        rrd_set_error("opening '%s': %s", file_name, rrd_strerror(errno));
        goto out_free;
    }

#ifdef HAVE_MMAP
#ifdef HAVE_BROKEN_MS_ASYNC
    if (rdwr & RRD_READWRITE) {    
        /* some unices, the files mtime does not get updated
           on memory mapped files, in order to help them,     
           we update the the timestamp at this point.      
           The thing happens pretty 'close' to the open    
           call so the chances of a race should be minimal.    
                
           Maybe ask your vendor to fix your OS ... */    
           utime(file_name,NULL);  
    }
#endif    
#endif

    /* Better try to avoid seeks as much as possible. stat may be heavy but
     * many concurrent seeks are even worse.  */
    if (newfile_size == 0 && ((fstat(rrd_simple_file->fd, &statb)) < 0)) {
        rrd_set_error("fstat '%s': %s", file_name, rrd_strerror(errno));
        goto out_close;
    }
    if (newfile_size == 0) {
        rrd_file->file_len = statb.st_size;
    } else {
        rrd_file->file_len = newfile_size;
#ifdef HAVE_POSIX_FALLOCATE
        if (posix_fallocate(rrd_simple_file->fd, 0, newfile_size) == 0){
            /* if all  is well we skip the seeking below */            
            goto no_lseek_necessary;        
        }
#endif
        lseek(rrd_simple_file->fd, newfile_size - 1, SEEK_SET);
        if ( write(rrd_simple_file->fd, "\0", 1) == -1){    /* poke */
            rrd_set_error("write '%s': %s", file_name, rrd_strerror(errno));
            goto out_close;
        }
        lseek(rrd_simple_file->fd, 0, SEEK_SET);
    }
    no_lseek_necessary:
#ifdef HAVE_POSIX_FADVISE
    /* In general we need no read-ahead when dealing with rrd_files.
       When we stop reading, it is highly unlikely that we start up again.
       In this manner we actually save time and diskaccess (and buffer cache).
       Thanks to Dave Plonka for the Idea of using POSIX_FADV_RANDOM here. */
    posix_fadvise(rrd_simple_file->fd, 0, 0, POSIX_FADV_RANDOM);
#endif

/*
        if (rdwr & RRD_READWRITE)
        {
           if (setvbuf((rrd_simple_file->fd),NULL,_IONBF,2)) {
                  rrd_set_error("failed to disable the stream buffer\n");
                  return (-1);
           }
        }
*/

#ifdef HAVE_MMAP
#ifndef HAVE_POSIX_FALLOCATE
	/* force allocating the file on the underlaying filesystem to prevent any
	 * future bus error when the filesystem is full and attempting to write
	 * trough the file mapping. Filling the file using memset on the file
	 * mapping can also lead some bus error, so we use the old fashioned
	 * write().
	 */
    if (rdwr & RRD_CREAT) {
		char     buf[4096];
		unsigned i;

		memset(buf, DNAN, sizeof buf);
		lseek(rrd_simple_file->fd, offset, SEEK_SET);
        
		for (i = 0; i < (newfile_size - 1) / sizeof buf; ++i)
		{
			if (write(rrd_simple_file->fd, buf, sizeof buf) == -1)
			{
				rrd_set_error("write '%s': %s", file_name, rrd_strerror(errno));
				goto out_close;
			}
		}
		
		if (write(rrd_simple_file->fd, buf,
					(newfile_size - 1) % sizeof buf) == -1)
		{
			rrd_set_error("write '%s': %s", file_name, rrd_strerror(errno));
			goto out_close;
		}

		lseek(rrd_simple_file->fd, 0, SEEK_SET);
    }
#endif

    data = mmap(0, rrd_file->file_len, 
        rrd_simple_file->mm_prot, rrd_simple_file->mm_flags,
        rrd_simple_file->fd, offset);

    /* lets see if the first read worked */
    if (data == MAP_FAILED) {
        rrd_set_error("mmaping file '%s': %s", file_name,
                      rrd_strerror(errno));
        goto out_close;
    }
    rrd->__mmap_start = data;
    rrd->__mmap_size  = rrd_file->file_len;
	    
    rrd_simple_file->file_start = data;
#endif
    if (rdwr & RRD_CREAT)
        goto out_done;
#ifdef USE_MADVISE
    if (rdwr & RRD_COPY) {
        /* We will read everything in a moment (copying) */
        madvise(data, rrd_file->file_len, MADV_SEQUENTIAL );
    } else {
        /* We do not need to read anything in for the moment */
        madvise(data, rrd_file->file_len, MADV_RANDOM);
    }
#endif

    __rrd_read(rrd->stat_head, stat_head_t,
               1);

    /* lets do some test if we are on track ... */
    if (memcmp(rrd->stat_head->cookie, RRD_COOKIE, sizeof(RRD_COOKIE)) != 0) {
        rrd_set_error("'%s' is not an RRD file", file_name);
        goto out_nullify_head;
    }

    if (rrd->stat_head->float_cookie != FLOAT_COOKIE) {
        rrd_set_error("This RRD was created on another architecture");
        goto out_nullify_head;
    }

    version = atoi(rrd->stat_head->version);

    if (version > atoi(RRD_VERSION)) {
        rrd_set_error("can't handle RRD file version %s",
                      rrd->stat_head->version);
        goto out_nullify_head;
    }
    __rrd_read(rrd->ds_def, ds_def_t,
               rrd->stat_head->ds_cnt);

    __rrd_read(rrd->rra_def, rra_def_t,
               rrd->stat_head->rra_cnt);

    /* handle different format for the live_head */
    if (version < 3) {
        rrd->live_head = (live_head_t *) malloc(sizeof(live_head_t));
        if (rrd->live_head == NULL) {
            rrd_set_error("live_head_t malloc");
            goto out_close;
        }
        __rrd_read(rrd->legacy_last_up, time_t,
                   1);

        rrd->live_head->last_up = *rrd->legacy_last_up;
        rrd->live_head->last_up_usec = 0;
    } else {
        __rrd_read(rrd->live_head, live_head_t,
                   1);
    }
    __rrd_read(rrd->pdp_prep, pdp_prep_t,
               rrd->stat_head->ds_cnt);
    __rrd_read(rrd->cdp_prep, cdp_prep_t,
               rrd->stat_head->rra_cnt * rrd->stat_head->ds_cnt);
    __rrd_read(rrd->rra_ptr, rra_ptr_t,
               rrd->stat_head->rra_cnt);

    rrd_file->header_len = offset;
    rrd_file->pos = offset;

    {
      unsigned long row_cnt = 0;

      for (ui=0; ui<rrd->stat_head->rra_cnt; ui++)
        row_cnt += rrd->rra_def[ui].row_cnt;

      size_t  correct_len = rrd_file->header_len +
        sizeof(rrd_value_t) * row_cnt * rrd->stat_head->ds_cnt;

      if (correct_len > rrd_file->file_len)
      {
        rrd_set_error("'%s' is too small (should be %ld bytes)",
                      file_name, (long long) correct_len);
        goto out_nullify_head;
      }
      if (rdwr & RRD_READVALUES) {
	  long d_offset = offset;
	  
	  __rrd_read(rrd->rrd_value, rrd_value_t,
		     row_cnt * rrd->stat_head->ds_cnt);

	  rrd_file->header_len = d_offset;
	  rrd_file->pos = d_offset;
      }
      
    }

    
    
  out_done:
    return (rrd_file);
  out_nullify_head:
    rrd->stat_head = NULL;
  out_close:
#ifdef HAVE_MMAP
    if (data != MAP_FAILED)
      munmap(data, rrd_file->file_len);
    rrd->__mmap_start = NULL;
    rrd->__mmap_size = 0;
#endif

    close(rrd_simple_file->fd);
  out_free:
    free(rrd_file->pvt);
    free(rrd_file);
    return NULL;
}
Esempio n. 19
0
int
rrd_write(char *file_name, rrd_t *rrd, char force_overwrite)
{
    unsigned long    i,ii,val_cnt;
    FILE             *rrd_file=NULL;
    int			fdflags;
    int			fd;

    if (strcmp("-",file_name)==0){
      rrd_file= stdout;
    } else {
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
      fdflags = O_RDWR|O_BINARY|O_CREAT;
#else
      fdflags = O_WRONLY|O_CREAT;
#endif            
      if (force_overwrite == 0) {
      	fdflags |= O_EXCL;
      }
      fd = open(file_name,fdflags,0666);
      if (fd == -1 || (rrd_file = fdopen(fd,"wb")) == NULL) {
	rrd_set_error("creating '%s': %s",file_name,rrd_strerror(errno));
        if (fd != -1)
          close(fd);
	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);

	 /* maybe the xml hold an old formatted rrd */
    if (atoi(rrd->stat_head->version) < 3)
      fwrite(&(rrd->live_head->last_up), sizeof(long),1, rrd_file);
    else
      fwrite(rrd->live_head, sizeof(live_head_t),1, rrd_file);

    fwrite( rrd->pdp_prep, sizeof(pdp_prep_t),rrd->stat_head->ds_cnt,rrd_file);
    
    fwrite( rrd->cdp_prep, sizeof(cdp_prep_t),rrd->stat_head->rra_cnt*
	    rrd->stat_head->ds_cnt,rrd_file);
    fwrite( rrd->rra_ptr, sizeof(rra_ptr_t), rrd->stat_head->rra_cnt,rrd_file);



    /* calculate the number of rrd_values to dump */
    val_cnt=0;
    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++)
	    val_cnt++;
    fwrite( rrd->rrd_value, sizeof(rrd_value_t),val_cnt,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);	
	return(-1);
    }
    
    fclose(rrd_file);    
    return 0;
}
Esempio n. 20
0
/* HandleInputLine is NOT thread safe - due to readdir issues,
   resolving them portably is not really simple. */
int HandleInputLine(
    int argc,
    char **argv,
    FILE * out)
{
#if defined(HAVE_OPENDIR) && defined (HAVE_READDIR)
    DIR      *curdir;   /* to read current dir with ls */
    struct dirent *dent;
#endif
#if defined(HAVE_SYS_STAT_H)
    struct stat st;
#endif

    /* Reset errno to 0 before we start.
     */
    if (RemoteMode) {
        if (argc > 1 && strcmp("quit", argv[1]) == 0) {
            if (argc > 2) {
                printf("ERROR: invalid parameter count for quit\n");
                return (1);
            }
            exit(0);
        }
#if defined(HAVE_OPENDIR) && defined(HAVE_READDIR) && defined(HAVE_CHDIR)
        if (argc > 1 && strcmp("cd", argv[1]) == 0) {
            if (argc > 3) {
                printf("ERROR: invalid parameter count for cd\n");
                return (1);
            }
#if ! defined(HAVE_CHROOT) || ! defined(HAVE_GETUID)
            if (getuid() == 0 && !ChangeRoot) {
                printf
                ("ERROR: chdir security problem - rrdtool is running as "
                 "root but not chroot!\n");
                return (1);
            }
#endif
            if (chdir(argv[2]) != 0) {
                printf("ERROR: chdir %s %s\n", argv[2], rrd_strerror(errno));
                return (1);
            }
            return (0);
        }
        if (argc > 1 && strcmp("pwd", argv[1]) == 0) {
            char     *cwd;      /* To hold current working dir on call to pwd */
            if (argc > 2) {
                printf("ERROR: invalid parameter count for pwd\n");
                return (1);
            }
            cwd = getcwd(NULL, MAXPATH);
            if (cwd == NULL) {
                printf("ERROR: getcwd %s\n", rrd_strerror(errno));
                return (1);
            }
            printf("%s\n", cwd);
            free(cwd);
            return (0);
        }
        if (argc > 1 && strcmp("mkdir", argv[1]) == 0) {
            if (argc > 3) {
                printf("ERROR: invalid parameter count for mkdir\n");
                return (1);
            }
#if ! defined(HAVE_CHROOT) || ! defined(HAVE_GETUID)
            if (getuid() == 0 && !ChangeRoot) {
                printf
                ("ERROR: mkdir security problem - rrdtool is running as "
                 "root but not chroot!\n");
                return (1);
            }
#endif
            if(mkdir(argv[2], 0777)!=0) {
                printf("ERROR: mkdir %s: %s\n", argv[2],rrd_strerror(errno));
                return (1);
            }
            return (0);
        }
        if (argc > 1 && strcmp("ls", argv[1]) == 0) {
            if (argc > 2) {
                printf("ERROR: invalid parameter count for ls\n");
                return (1);
            }
            if ((curdir = opendir(".")) != NULL) {
                while ((dent = readdir(curdir)) != NULL) {
                    if (!stat(dent->d_name, &st)) {
                        if (S_ISDIR(st.st_mode)) {
                            printf("d %s\n", dent->d_name);
                        }
                        if (strlen(dent->d_name) > 4 && S_ISREG(st.st_mode)) {
                            if (!strcmp
                                    (dent->d_name + NAMLEN(dent) - 4, ".rrd")
                                    || !strcmp(dent->d_name + NAMLEN(dent) - 4,
                                               ".RRD")) {
                                printf("- %s\n", dent->d_name);
                            }
                        }
                    }
                }
                closedir(curdir);
            } else {
                printf("ERROR: opendir .: %s\n", rrd_strerror(errno));
                return (errno);
            }
            return (0);
        }
#endif                          /* opendir and readdir */

    }
    if (argc < 3
            || strcmp("help", argv[1]) == 0
            || strcmp("--help", argv[1]) == 0
            || strcmp("-help", argv[1]) == 0
            || strcmp("-?", argv[1]) == 0 || strcmp("-h", argv[1]) == 0) {
        PrintUsage("");
        return 0;
    }

    if (strcmp("create", argv[1]) == 0)
        rrd_create(argc - 1, &argv[1]);
    else if (strcmp("dump", argv[1]) == 0)
        rrd_dump(argc - 1, &argv[1]);
    else if (strcmp("info", argv[1]) == 0 || strcmp("updatev", argv[1]) == 0) {
        rrd_info_t *data;

        if (strcmp("info", argv[1]) == 0)

            data = rrd_info(argc - 1, &argv[1]);
        else
            data = rrd_update_v(argc - 1, &argv[1]);
        rrd_info_print(data);
        rrd_info_free(data);
    }

    else if (strcmp("--version", argv[1]) == 0 ||
             strcmp("version", argv[1]) == 0 ||
             strcmp("v", argv[1]) == 0 ||
             strcmp("-v", argv[1]) == 0 || strcmp("-version", argv[1]) == 0)
        printf("RRDtool " PACKAGE_VERSION
               "  Copyright by Tobi Oetiker, 1997-2008 (%f)\n",
               rrd_version());
    else if (strcmp("restore", argv[1]) == 0)
        rrd_restore(argc - 1, &argv[1]);
    else if (strcmp("resize", argv[1]) == 0)
        rrd_resize(argc - 1, &argv[1]);
    else if (strcmp("last", argv[1]) == 0)
        printf("%ld\n", rrd_last(argc - 1, &argv[1]));
    else if (strcmp("lastupdate", argv[1]) == 0) {
        rrd_lastupdate(argc - 1, &argv[1]);
    } else if (strcmp("first", argv[1]) == 0)
        printf("%ld\n", rrd_first(argc - 1, &argv[1]));
    else if (strcmp("update", argv[1]) == 0)
        rrd_update(argc - 1, &argv[1]);
    else if (strcmp("fetch", argv[1]) == 0) {
        time_t    start, end, ti;
        unsigned long step, ds_cnt, i, ii;
        rrd_value_t *data, *datai;
        char    **ds_namv;

        if (rrd_fetch
                (argc - 1, &argv[1], &start, &end, &step, &ds_cnt, &ds_namv,
                 &data) != -1) {
            datai = data;
            printf("           ");
            for (i = 0; i < ds_cnt; i++)
                printf("%20s", ds_namv[i]);
            printf("\n\n");
            for (ti = start + step; ti <= end; ti += step) {
                printf("%10lu:", ti);
                for (ii = 0; ii < ds_cnt; ii++)
                    printf(" %0.10e", *(datai++));
                printf("\n");
            }
            for (i = 0; i < ds_cnt; i++)
                free(ds_namv[i]);
            free(ds_namv);
            free(data);
        }
    } else if (strcmp("xport", argv[1]) == 0) {
        int       xxsize;
        unsigned long int j = 0;
        time_t    start, end, ti;
        unsigned long step, col_cnt, row_cnt;
        rrd_value_t *data, *ptr;
        char    **legend_v;
        int       enumds = 0;
        int       i;
        size_t    vtag_s = strlen(COL_DATA_TAG) + 10;
        char     *vtag = malloc(vtag_s);

        for (i = 2; i < argc; i++) {
            if (strcmp("--enumds", argv[i]) == 0)
                enumds = 1;
        }

        if (rrd_xport
                (argc - 1, &argv[1], &xxsize, &start, &end, &step, &col_cnt,
                 &legend_v, &data) != -1) {
            char *old_locale = setlocale(LC_NUMERIC, "C");
            row_cnt = (end - start) / step;
            ptr = data;
            printf("<?xml version=\"1.0\" encoding=\"%s\"?>\n\n",
                   XML_ENCODING);
            printf("<%s>\n", ROOT_TAG);
            printf("  <%s>\n", META_TAG);
            printf("    <%s>%lld</%s>\n", META_START_TAG,
                   (long long int) start + step, META_START_TAG);
            printf("    <%s>%lu</%s>\n", META_STEP_TAG, step, META_STEP_TAG);
            printf("    <%s>%lld</%s>\n", META_END_TAG, (long long int) end,
                   META_END_TAG);
            printf("    <%s>%lu</%s>\n", META_ROWS_TAG, row_cnt,
                   META_ROWS_TAG);
            printf("    <%s>%lu</%s>\n", META_COLS_TAG, col_cnt,
                   META_COLS_TAG);
            printf("    <%s>\n", LEGEND_TAG);
            for (j = 0; j < col_cnt; j++) {
                char     *entry = NULL;

                entry = legend_v[j];
                printf("      <%s>%s</%s>\n", LEGEND_ENTRY_TAG, entry,
                       LEGEND_ENTRY_TAG);
                free(entry);
            }
            free(legend_v);
            printf("    </%s>\n", LEGEND_TAG);
            printf("  </%s>\n", META_TAG);
            printf("  <%s>\n", DATA_TAG);
            for (ti = start + step; ti <= end; ti += step) {
                printf("    <%s>", DATA_ROW_TAG);
                printf("<%s>%lld</%s>", COL_TIME_TAG, (long long int)ti, COL_TIME_TAG);
                for (j = 0; j < col_cnt; j++) {
                    rrd_value_t newval = DNAN;

                    if (enumds == 1)

                        snprintf(vtag, vtag_s, "%s%lu", COL_DATA_TAG, j);
                    else
                        snprintf(vtag, vtag_s, "%s", COL_DATA_TAG);
                    newval = *ptr;
                    if (isnan(newval)) {
                        printf("<%s>NaN</%s>", vtag, vtag);
                    } else {
                        printf("<%s>%0.10e</%s>", vtag, newval, vtag);
                    };
                    ptr++;
                }
                printf("</%s>\n", DATA_ROW_TAG);
            }
            free(data);
            printf("  </%s>\n", DATA_TAG);
            printf("</%s>\n", ROOT_TAG);
            setlocale(LC_NUMERIC, old_locale);
        }
        free(vtag);
    } else if (strcmp("graph", argv[1]) == 0) {
        char    **calcpr;

#ifdef notused /*XXX*/
        const char *imgfile = argv[2];  /* rrd_graph changes argv pointer */
#endif
        int       xsize, ysize;
        double    ymin, ymax;
        int       i;
        int       tostdout = (strcmp(argv[2], "-") == 0);
        int       imginfo = 0;

        for (i = 2; i < argc; i++) {
            if (strcmp(argv[i], "--imginfo") == 0
                    || strcmp(argv[i], "-f") == 0) {
                imginfo = 1;
                break;
            }
        }
        if (rrd_graph
                (argc - 1, &argv[1], &calcpr, &xsize, &ysize, NULL, &ymin,
                 &ymax) != -1) {
            if (!tostdout && !imginfo)
                printf("%dx%d\n", xsize, ysize);
            if (calcpr) {
                for (i = 0; calcpr[i]; i++) {
                    if (!tostdout)
                        printf("%s\n", calcpr[i]);
                    free(calcpr[i]);
                }
                free(calcpr);
            }
        }

    } else if (strcmp("graphv", argv[1]) == 0) {
        rrd_info_t *grinfo = NULL;  /* 1 to distinguish it from the NULL that rrd_graph sends in */

        grinfo = rrd_graph_v(argc - 1, &argv[1]);
        if (grinfo) {
            rrd_info_print(grinfo);
            rrd_info_free(grinfo);
        }

    } else if (strcmp("tune", argv[1]) == 0)
        rrd_tune(argc - 1, &argv[1]);
    else if (strcmp("flushcached", argv[1]) == 0)
        rrd_flushcached(argc - 1, &argv[1]);
    else {
        rrd_set_error("unknown function '%s'", argv[1]);
    }
    if (rrd_test_error()) {
        fprintf(out, "ERROR: %s\n", rrd_get_error());
        rrd_clear_error();
        return 1;
    }
    return (0);
}
Esempio n. 21
0
int main(
    int argc,
    char *argv[])
{
    char    **myargv;
    char     *aLine;
    char     *firstdir = "";

#ifdef MUST_DISABLE_SIGFPE
    signal(SIGFPE, SIG_IGN);
#endif
#ifdef MUST_DISABLE_FPMASK
    fpsetmask(0);
#endif

    /* initialize locale settings
       according to localeconv(3) */       
    setlocale(LC_ALL, "");

#if defined(WIN32) && !defined(__CYGWIN__)
    setmode(fileno(stdout), O_BINARY);
    setmode(fileno(stdin), O_BINARY);
#endif


#if defined(HAVE_LIBINTL_H) && defined(BUILD_LIBINTL)
    bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
    textdomain(GETTEXT_PACKAGE);
#endif
    if (argc == 1) {
        PrintUsage("");
        return 0;
    }

    if (((argc == 2) || (argc == 3)) && !strcmp("-", argv[1])) {
#if HAVE_GETRUSAGE
        struct rusage myusage;
        struct timeval starttime;
        struct timeval currenttime;

        gettimeofday(&starttime, NULL);
#endif
        RemoteMode = 1;
        if ((argc == 3) && strcmp("", argv[2])) {

            if (
#ifdef HAVE_GETUID
                   getuid()
#else
                   1
#endif
                   == 0) {

#ifdef HAVE_CHROOT
                if (chroot(argv[2]) != 0){
                    fprintf(stderr, "ERROR: chroot %s: %s\n", argv[2],rrd_strerror(errno));
                    exit(errno);
                }
                ChangeRoot = 1;
                firstdir = "/";
#else
                fprintf(stderr,
                        "ERROR: change root is not supported by your OS "
                        "or at least by this copy of rrdtool\n");
                exit(1);
#endif
            } else {
                firstdir = argv[2];
            }
        }
        if (strcmp(firstdir, "")) {
            if (chdir(firstdir) != 0){
                fprintf(stderr, "ERROR: chdir %s %s\n", firstdir,rrd_strerror(errno));
                exit(errno);
            }
        }

        while (fgetslong(&aLine, stdin)) {
            char *aLineOrig = aLine;
            if ((argc = CountArgs(aLine)) == 0) {
                free(aLine);
                printf("ERROR: not enough arguments\n");
                continue;                
            }
            if ((myargv = (char **) malloc((argc + 1) *
                                           sizeof(char *))) == NULL) {
                perror("malloc");
                exit(1);
            }
            if ((argc = CreateArgs(argv[0], aLine, myargv)) < 0) {
                printf("ERROR: creating arguments\n");
            } else {
                if ( HandleInputLine(argc, myargv, stdout) == 0 ){
#if HAVE_GETRUSAGE
                    getrusage(RUSAGE_SELF, &myusage);
                    gettimeofday(&currenttime, NULL);
                    printf("OK u:%1.2f s:%1.2f r:%1.2f\n",
                           (double) myusage.ru_utime.tv_sec +
                           (double) myusage.ru_utime.tv_usec / 1000000.0,
                           (double) myusage.ru_stime.tv_sec +
                           (double) myusage.ru_stime.tv_usec / 1000000.0,
                           (double) (currenttime.tv_sec - starttime.tv_sec)
                           + (double) (currenttime.tv_usec -
                                       starttime.tv_usec)
                           / 1000000.0);
#else
                    printf("OK\n");
#endif
                }
            }
            fflush(stdout); /* this is important for pipes to work */
            free(myargv);
            free(aLineOrig);
        }
    } else if (argc == 2) {
        PrintUsage(argv[1]);
        exit(0);
    } else if (argc == 3 && !strcmp(argv[1], "help")) {
        PrintUsage(argv[2]);
        exit(0);
    } else {
        exit(HandleInputLine(argc, argv, stderr));
    }
    return 0;
}
Esempio n. 22
0
int rrd_create_fn(
    const char *file_name,
    rrd_t *rrd)
{
    unsigned long i, ii;
    rrd_value_t *unknown;
    int       unkn_cnt;
    rrd_file_t *rrd_file_dn;
    rrd_t     rrd_dn;
    unsigned  rrd_flags = RRD_READWRITE | RRD_CREAT;

    if (opt_no_overwrite) {
      rrd_flags |= RRD_EXCL ;
    }

    unkn_cnt = 0;
    for (i = 0; i < rrd->stat_head->rra_cnt; i++)
        unkn_cnt += rrd->stat_head->ds_cnt * rrd->rra_def[i].row_cnt;

    if ((rrd_file_dn = rrd_open(file_name, rrd, rrd_flags)) == NULL) {
        rrd_set_error("creating '%s': %s", file_name, rrd_strerror(errno));
        rrd_free2(rrd);
        return (-1);
    }

    rrd_write(rrd_file_dn, rrd->stat_head, sizeof(stat_head_t));

    rrd_write(rrd_file_dn, rrd->ds_def, sizeof(ds_def_t) * rrd->stat_head->ds_cnt);

    rrd_write(rrd_file_dn, rrd->rra_def,
          sizeof(rra_def_t) * rrd->stat_head->rra_cnt);

    rrd_write(rrd_file_dn, rrd->live_head, sizeof(live_head_t));

    if ((rrd->pdp_prep = (pdp_prep_t*)calloc(1, sizeof(pdp_prep_t))) == NULL) {
        rrd_set_error("allocating pdp_prep");
        rrd_free2(rrd);
        rrd_close(rrd_file_dn);
        return (-1);
    }

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

    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++)
        rrd_write(rrd_file_dn, rrd->pdp_prep, sizeof(pdp_prep_t));

    if ((rrd->cdp_prep = (cdp_prep_t*)calloc(1, sizeof(cdp_prep_t))) == NULL) {
        rrd_set_error("allocating cdp_prep");
        rrd_free2(rrd);
        rrd_close(rrd_file_dn);
        return (-1);
    }


    for (i = 0; i < rrd->stat_head->rra_cnt; i++) {
        switch (cf_conv(rrd->rra_def[i].cf_nam)) {
        case CF_HWPREDICT:
        case CF_MHWPREDICT:
            init_hwpredict_cdp(rrd->cdp_prep);
            break;
        case CF_SEASONAL:
        case CF_DEVSEASONAL:
            init_seasonal_cdp(rrd->cdp_prep);
            break;
        case CF_FAILURES:
            /* initialize violation history to 0 */
            for (ii = 0; ii < MAX_CDP_PAR_EN; ii++) {
                /* We can zero everything out, by setting u_val to the
                 * NULL address. Each array entry in scratch is 8 bytes
                 * (a double), but u_cnt only accessed 4 bytes (long) */
                rrd->cdp_prep->scratch[ii].u_val = 0.0;
            }
            break;
        default:
            /* can not be zero because we don't know anything ... */
            rrd->cdp_prep->scratch[CDP_val].u_val = DNAN;
            /* 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;
            break;
        }

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

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

    if ((rrd->rra_ptr = (rra_ptr_t*)calloc(1, sizeof(rra_ptr_t))) == NULL) {
        rrd_set_error("allocating rra_ptr");
        rrd_free2(rrd);
        rrd_close(rrd_file_dn);
        return (-1);
    }

    /* changed this initialization to be consistent with
     * rrd_restore. With the old value (0), the first update
     * would occur for cur_row = 1 because rrd_update increments
     * the pointer a priori. */
    for (i = 0; i < rrd->stat_head->rra_cnt; i++) {
        rrd->rra_ptr->cur_row = rrd_select_initial_row(rrd_file_dn, i, &rrd->rra_def[i]);
        rrd_write(rrd_file_dn, rrd->rra_ptr, sizeof(rra_ptr_t));
    }

    /* write the empty data area */
    if ((unknown = (rrd_value_t *) malloc(512 * sizeof(rrd_value_t))) == NULL) {
        rrd_set_error("allocating unknown");
        rrd_free2(rrd);
        rrd_close(rrd_file_dn);
        return (-1);
    }
    for (i = 0; i < 512; ++i)
        unknown[i] = DNAN;

    while (unkn_cnt > 0) {
        if(rrd_write(rrd_file_dn, unknown, sizeof(rrd_value_t) * min(unkn_cnt, 512)) < 0)
        {
            rrd_set_error("creating rrd: %s", rrd_strerror(errno));
            return -1;
        }

        unkn_cnt -= 512;
    }
    free(unknown);
    rrd_free2(rrd);
    if (rrd_close(rrd_file_dn) == -1) {
        rrd_set_error("creating rrd: %s", rrd_strerror(errno));
        return -1;
    }
    /* flush all we don't need out of the cache */
    rrd_init(&rrd_dn);
    if((rrd_file_dn = rrd_open(file_name, &rrd_dn, RRD_READONLY)) != NULL)
    {
        rrd_dontneed(rrd_file_dn, &rrd_dn);
        /* rrd_free(&rrd_dn); */
        rrd_close(rrd_file_dn);
    }
    return (0);
}
Esempio n. 23
0
/* Smooth a periodic array with a moving average: equal weights and
 * length = 5% of the period. */
int apply_smoother(
    rrd_t *rrd,
    unsigned long rra_idx,
    unsigned long rra_start,
    rrd_file_t *rrd_file)
{
    unsigned long i, j, k;
    unsigned long totalbytes;
    rrd_value_t *rrd_values;
    unsigned long row_length = rrd->stat_head->ds_cnt;
    unsigned long row_count = rrd->rra_def[rra_idx].row_cnt;
    unsigned long offset;
    FIFOqueue **buffers;
    rrd_value_t *working_average;
    rrd_value_t *rrd_values_cpy;
    rrd_value_t *baseline;

    if (atoi(rrd->stat_head->version) >= 4) {
        offset = floor(rrd->rra_def[rra_idx].
                       par[RRA_seasonal_smoothing_window].
                       u_val / 2 * row_count);
    } else {
        offset = floor(0.05 / 2 * row_count);
    }

    if (offset == 0)
        return 0;       /* no smoothing */

    /* allocate memory */
    totalbytes = sizeof(rrd_value_t) * row_length * row_count;
    rrd_values = (rrd_value_t *) malloc(totalbytes);
    if (rrd_values == NULL) {
        rrd_set_error("apply smoother: memory allocation failure");
        return -1;
    }

    /* rra_start is at the beginning of this rra */
    if (rrd_seek(rrd_file, rra_start, SEEK_SET)) {
        rrd_set_error("seek to rra %d failed", rra_start);
        free(rrd_values);
        return -1;
    }

    /* could read all data in a single block, but we need to
     * check for NA values */
    for (i = 0; i < row_count; ++i) {
        for (j = 0; j < row_length; ++j) {
            if (rrd_read
                (rrd_file, &(rrd_values[i * row_length + j]),
                 sizeof(rrd_value_t) * 1)
                != (ssize_t) (sizeof(rrd_value_t) * 1)) {
                rrd_set_error("reading value failed: %s",
                              rrd_strerror(errno));
            }
            if (isnan(rrd_values[i * row_length + j])) {
                /* can't apply smoothing, still uninitialized values */
#ifdef DEBUG
                fprintf(stderr,
                        "apply_smoother: NA detected in seasonal array: %ld %ld\n",
                        i, j);
#endif
                free(rrd_values);
                return 0;
            }
        }
    }

    /* allocate queues, one for each data source */
    buffers = (FIFOqueue **) malloc(sizeof(FIFOqueue *) * row_length);
    for (i = 0; i < row_length; ++i) {
        queue_alloc(&(buffers[i]), 2 * offset + 1);
    }
    /* need working average initialized to 0 */
    working_average = (rrd_value_t *) calloc(row_length, sizeof(rrd_value_t));
    baseline = (rrd_value_t *) calloc(row_length, sizeof(rrd_value_t));

    /* compute sums of the first 2*offset terms */
    for (i = 0; i < 2 * offset; ++i) {
        k = MyMod(i - offset, row_count);
        for (j = 0; j < row_length; ++j) {
            queue_push(buffers[j], rrd_values[k * row_length + j]);
            working_average[j] += rrd_values[k * row_length + j];
        }
    }

    /* as we are working through the value, we have to make sure to not double
       apply the smoothing after wrapping around. so best is to copy the rrd_values first */

    rrd_values_cpy = (rrd_value_t *) calloc(row_length*row_count, sizeof(rrd_value_t));
    memcpy(rrd_values_cpy,rrd_values,sizeof(rrd_value_t)*row_length*row_count);

    /* compute moving averages */
    for (i = offset; i < row_count + offset; ++i) {
        for (j = 0; j < row_length; ++j) {
            k = MyMod(i, row_count);
            /* add a term to the sum */
            working_average[j] += rrd_values_cpy[k * row_length + j];
            queue_push(buffers[j], rrd_values_cpy[k * row_length + j]);

            /* reset k to be the center of the window */
            k = MyMod(i - offset, row_count);
            /* overwrite rdd_values entry, the old value is already
             * saved in buffers */
            rrd_values[k * row_length + j] =
                working_average[j] / (2 * offset + 1);
            baseline[j] += rrd_values[k * row_length + j];

            /* remove a term from the sum */
            working_average[j] -= queue_pop(buffers[j]);
        }
    }

    for (i = 0; i < row_length; ++i) {
        queue_dealloc(buffers[i]);
        baseline[i] /= row_count;
    }
    free(rrd_values_cpy);
    free(buffers);
    free(working_average);

    if (cf_conv(rrd->rra_def[rra_idx].cf_nam) == CF_SEASONAL) {
        rrd_value_t (
    *init_seasonality) (
    rrd_value_t seasonal_coef,
    rrd_value_t intercept);

        switch (cf_conv(rrd->rra_def[hw_dep_idx(rrd, rra_idx)].cf_nam)) {
        case CF_HWPREDICT:
            init_seasonality = hw_additive_init_seasonality;
            break;
        case CF_MHWPREDICT:
            init_seasonality = hw_multiplicative_init_seasonality;
            break;
        default:
            rrd_set_error("apply smoother: SEASONAL rra doesn't have "
                          "valid dependency: %s",
                          rrd->rra_def[hw_dep_idx(rrd, rra_idx)].cf_nam);
            return -1;
        }

        for (j = 0; j < row_length; ++j) {
            for (i = 0; i < row_count; ++i) {
                rrd_values[i * row_length + j] =
                    init_seasonality(rrd_values[i * row_length + j],
                                     baseline[j]);
            }
            /* update the baseline coefficient,
             * first, compute the cdp_index. */
            offset = hw_dep_idx(rrd, rra_idx) * row_length + j;
            (rrd->cdp_prep[offset]).scratch[CDP_hw_intercept].u_val +=
                baseline[j];
        }
/* if we are not running on mmap, lets write stuff to disk now */
#ifndef HAVE_MMAP
        /* flush cdp to disk */
        if (rrd_seek(rrd_file, sizeof(stat_head_t) +
                     rrd->stat_head->ds_cnt * sizeof(ds_def_t) +
                     rrd->stat_head->rra_cnt * sizeof(rra_def_t) +
                     sizeof(live_head_t) +
                     rrd->stat_head->ds_cnt * sizeof(pdp_prep_t), SEEK_SET)) {
            rrd_set_error("apply_smoother: seek to cdp_prep failed");
            free(rrd_values);
            return -1;
        }
        if (rrd_write(rrd_file, rrd->cdp_prep,
                      sizeof(cdp_prep_t) *
                      (rrd->stat_head->rra_cnt) * rrd->stat_head->ds_cnt)
            != (ssize_t) (sizeof(cdp_prep_t) * (rrd->stat_head->rra_cnt) *
                          (rrd->stat_head->ds_cnt))) {
            rrd_set_error("apply_smoother: cdp_prep write failed");
            free(rrd_values);
            return -1;
        }
#endif

    }

    /* endif CF_SEASONAL */
    /* flush updated values to disk */
    if (rrd_seek(rrd_file, rra_start, SEEK_SET)) {
        rrd_set_error("apply_smoother: seek to pos %d failed", rra_start);
        free(rrd_values);
        return -1;
    }
    /* write as a single block */
    if (rrd_write
        (rrd_file, rrd_values, sizeof(rrd_value_t) * row_length * row_count)
        != (ssize_t) (sizeof(rrd_value_t) * row_length * row_count)) {
        rrd_set_error("apply_smoother: write failed to %lu", rra_start);
        free(rrd_values);
        return -1;
    }

    free(rrd_values);
    free(baseline);
    return 0;
}
Esempio n. 24
0
/* HandleInputLine is NOT thread safe - due to readdir issues,
   resolving them portably is not really simple. */
int HandleInputLine(
    int argc,
    char **argv,
    FILE * out)
{
#if defined(HAVE_OPENDIR) && defined (HAVE_READDIR)
    DIR      *curdir;   /* to read current dir with ls */
    struct dirent *dent;
#endif

    /* Reset errno to 0 before we start.
     */
    if (RemoteMode) {
        if (argc > 1 && strcmp("quit", argv[1]) == 0) {
            if (argc != 2) {
                printf("ERROR: invalid parameter count for quit\n");
                return (1);
            }
            exit(0);
        }
#if defined(HAVE_OPENDIR) && defined(HAVE_READDIR) && defined(HAVE_CHDIR) && defined(HAVE_SYS_STAT_H)
        if (argc > 1 && strcmp("cd", argv[1]) == 0) {
            if (argc != 3) {
                printf("ERROR: invalid parameter count for cd\n");
                return (1);
            }
#if ! defined(HAVE_CHROOT) || ! defined(HAVE_GETUID)
            if (getuid() == 0 && !ChangeRoot) {
                printf
                    ("ERROR: chdir security problem - rrdtool is running as "
                     "root but not chroot!\n");
                return (1);
            }
#endif
            if (chdir(argv[2]) != 0){
                printf("ERROR: chdir %s %s\n", argv[2], rrd_strerror(errno));
                return (1);
            }
            return (0);
        }
        if (argc > 1 && strcmp("pwd", argv[1]) == 0) {
            char     *cwd;      /* To hold current working dir on call to pwd */
            if (argc != 2) {
                printf("ERROR: invalid parameter count for pwd\n");
                return (1);
            }
            cwd = getcwd(NULL, MAXPATH);
            if (cwd == NULL) {
                printf("ERROR: getcwd %s\n", rrd_strerror(errno));
                return (1);
            }
            printf("%s\n", cwd);
            free(cwd);
            return (0);
        }
        if (argc > 1 && strcmp("mkdir", argv[1]) == 0) {
            if (argc != 3) {
                printf("ERROR: invalid parameter count for mkdir\n");
                return (1);
            }
#if ! defined(HAVE_CHROOT) || ! defined(HAVE_GETUID)
            if (getuid() == 0 && !ChangeRoot) {
                printf
                    ("ERROR: mkdir security problem - rrdtool is running as "
                     "root but not chroot!\n");
                return (1);
            }
#endif
            if(mkdir(argv[2], 0777)!=0){
                printf("ERROR: mkdir %s: %s\n", argv[2],rrd_strerror(errno));
                return (1);
            }
            return (0);
        }
        if (argc > 1 && strcmp("ls", argv[1]) == 0) {
            if (argc != 2) {
                printf("ERROR: invalid parameter count for ls\n");
                return (1);
            }
            if ((curdir = opendir(".")) != NULL) {
                struct stat st;
                while ((dent = readdir(curdir)) != NULL) {
                    if (!stat(dent->d_name, &st)) {
                        if (S_ISDIR(st.st_mode)) {
                            printf("d %s\n", dent->d_name);
                        }
                        if (strlen(dent->d_name) > 4 && S_ISREG(st.st_mode)) {
                            if (!strcmp
                                (dent->d_name + NAMLEN(dent) - 4, ".rrd")
                                || !strcmp(dent->d_name + NAMLEN(dent) - 4,
                                           ".RRD")) {
                                printf("- %s\n", dent->d_name);
                            }
                        }
                    }
                }
                closedir(curdir);
            } else {
                printf("ERROR: opendir .: %s\n", rrd_strerror(errno));
                return (errno);
            }
            return (0);
        }
#endif                          /* opendir and readdir */

    }
    if (argc < 3
        || strcmp("help", argv[1]) == 0
        || strcmp("--help", argv[1]) == 0
        || strcmp("-help", argv[1]) == 0
        || strcmp("-?", argv[1]) == 0 || strcmp("-h", argv[1]) == 0) {
        PrintUsage("");
        return 0;
    }

    if (strcmp("create", argv[1]) == 0)
        rrd_create(argc - 1, &argv[1]);
    else if (strcmp("dump", argv[1]) == 0)
        rrd_dump(argc - 1, &argv[1]);
    else if (strcmp("info", argv[1]) == 0 || strcmp("updatev", argv[1]) == 0) {
        rrd_info_t *data;

        if (strcmp("info", argv[1]) == 0)

            data = rrd_info(argc - 1, &argv[1]);
        else
            data = rrd_update_v(argc - 1, &argv[1]);
        rrd_info_print(data);
        rrd_info_free(data);
    }

    else if (strcmp("--version", argv[1]) == 0 ||
             strcmp("version", argv[1]) == 0 ||
             strcmp("v", argv[1]) == 0 ||
             strcmp("-v", argv[1]) == 0 || strcmp("-version", argv[1]) == 0)
        printf("RRDtool " PACKAGE_VERSION
               "  Copyright by Tobi Oetiker, 1997-2008 (%f)\n",
               rrd_version());
    else if (strcmp("restore", argv[1]) == 0)
        rrd_restore(argc - 1, &argv[1]);
    else if (strcmp("resize", argv[1]) == 0)
        rrd_resize(argc - 1, &argv[1]);
    else if (strcmp("last", argv[1]) == 0)
        printf("%ld\n", rrd_last(argc - 1, &argv[1]));
    else if (strcmp("lastupdate", argv[1]) == 0) {
        rrd_lastupdate(argc - 1, &argv[1]);
    } else if (strcmp("first", argv[1]) == 0)
        printf("%ld\n", rrd_first(argc - 1, &argv[1]));
    else if (strcmp("update", argv[1]) == 0)
        rrd_update(argc - 1, &argv[1]);
    else if (strcmp("fetch", argv[1]) == 0) {
        time_t    start, end, ti;
        unsigned long step, ds_cnt, i, ii;
        rrd_value_t *data, *datai;
        char    **ds_namv;

        if (rrd_fetch
            (argc - 1, &argv[1], &start, &end, &step, &ds_cnt, &ds_namv,
             &data) == 0) {
            datai = data;
            printf("           ");
            for (i = 0; i < ds_cnt; i++)
                printf("%20s", ds_namv[i]);
            printf("\n\n");
            for (ti = start + step; ti <= end; ti += step) {
                printf("%10lu:", ti);
                for (ii = 0; ii < ds_cnt; ii++)
                    printf(" %0.10e", *(datai++));
                printf("\n");
            }
            for (i = 0; i < ds_cnt; i++)
                free(ds_namv[i]);
            free(ds_namv);
            free(data);
        }
    } else if (strcmp("xport", argv[1]) == 0) {
#ifdef HAVE_RRD_GRAPH
      time_t    start, end;
      unsigned long step, col_cnt;
      rrd_value_t *data;
      char    **legend_v;
      rrd_xport
	(argc - 1, &argv[1], NULL, &start, &end, &step, &col_cnt,
	 &legend_v, &data);
#else
        rrd_set_error("the instance of rrdtool has been compiled without graphics");
#endif
    } else if (strcmp("graph", argv[1]) == 0) {
#ifdef HAVE_RRD_GRAPH
        char    **calcpr;

#ifdef notused /*XXX*/
        const char *imgfile = argv[2];  /* rrd_graph changes argv pointer */
#endif
        int       xsize, ysize;
        double    ymin, ymax;
        int       i;
        int       tostdout = (strcmp(argv[2], "-") == 0);
        int       imginfo = 0;

        for (i = 2; i < argc; i++) {
            if (strcmp(argv[i], "--imginfo") == 0
                || strcmp(argv[i], "-f") == 0) {
                imginfo = 1;
                break;
            }
        }
        if (rrd_graph
            (argc - 1, &argv[1], &calcpr, &xsize, &ysize, NULL, &ymin,
             &ymax) == 0) {
            if (!tostdout && !imginfo)
                printf("%dx%d\n", xsize, ysize);
            if (calcpr) {
                for (i = 0; calcpr[i]; i++) {
                    if (!tostdout)
                        printf("%s\n", calcpr[i]);
                    free(calcpr[i]);
                }
                free(calcpr);
            }
        }

#else
       rrd_set_error("the instance of rrdtool has been compiled without graphics");
#endif
    } else if (strcmp("graphv", argv[1]) == 0) {
#ifdef HAVE_RRD_GRAPH
        rrd_info_t *grinfo = NULL;  /* 1 to distinguish it from the NULL that rrd_graph sends in */

        grinfo = rrd_graph_v(argc - 1, &argv[1]);
        if (grinfo) {
            rrd_info_print(grinfo);
            rrd_info_free(grinfo);
        }
#else
       rrd_set_error("the instance of rrdtool has been compiled without graphics");
#endif
    } else if (strcmp("tune", argv[1]) == 0)
        rrd_tune(argc - 1, &argv[1]);
    else if (strcmp("flushcached", argv[1]) == 0)
        rrd_flushcached(argc - 1, &argv[1]);
    else if (strcmp("modify", argv[1]) == 0)
        rrd_modify(argc - 1, &argv[1]);
    else {
        rrd_set_error("unknown function '%s'", argv[1]);
    }
    if (rrd_test_error()) {
        fprintf(out, "ERROR: %s\n", rrd_get_error());
        rrd_clear_error();
        return 1;
    }
    return (0);
}
Esempio n. 25
0
const char *rrdCreate(const char *filename, unsigned long step, 
		time_t start, int argc, const char **argv) {
	int ret;
	ret = rrd_create_r(filename, step, start, argc, argv);
	return rrd_strerror(ret);
}